From f7a14e0a5a5c8c929e05a9d678609608bc784c4e Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sun, 17 Mar 2013 00:29:12 -0700 Subject: [PATCH 001/403] rt: don't save and restore xmm/regs in __morestack. --- src/rt/arch/x86_64/morestack.S | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index 4acb50497d92e..239f7d58b098c 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -49,7 +49,7 @@ MORESTACK: // Calculate the CFA as on offset from %ebp .cfi_def_cfa_register %rbp - subq $184, %rsp + subq $56, %rsp // Save argument registers of the original function movq %rdi, (%rsp) @@ -58,14 +58,6 @@ MORESTACK: movq %rcx, 24(%rsp) movq %r8, 32(%rsp) movq %r9, 40(%rsp) - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) // Calculate the address of the stack arguments. // We have the base pointer, __morestack's return address, @@ -96,16 +88,8 @@ MORESTACK: movq 24(%rsp), %rcx movq 32(%rsp), %r8 movq 40(%rsp), %r9 - movdqa 48(%rsp), %xmm0 - movdqa 64(%rsp), %xmm1 - movdqa 80(%rsp), %xmm2 - movdqa 96(%rsp), %xmm3 - movdqa 112(%rsp), %xmm4 - movdqa 128(%rsp), %xmm5 - movdqa 144(%rsp), %xmm6 - movdqa 160(%rsp), %xmm7 - - addq $184, %rsp + + addq $56, %rsp movq 8(%rbp),%r10 // Grab the return pointer. incq %r10 // Skip past the `ret` in our parent frame From 2b07f0fb0018649588cda06bd33c33b71c5cac70 Mon Sep 17 00:00:00 2001 From: John Clements Date: Tue, 12 Mar 2013 11:37:31 -0700 Subject: [PATCH 002/403] field renaming --- src/libsyntax/ext/tt/transcribe.rs | 57 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 67c2f438269d8..f0e1273534ab1 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -26,7 +26,7 @@ use core::vec; `~` */ ///an unzipping of `token_tree`s struct TtFrame { - readme: @mut ~[ast::token_tree], + forest: @mut ~[ast::token_tree], idx: uint, dotdotdoted: bool, sep: Option, @@ -37,7 +37,7 @@ pub struct TtReader { sp_diag: @span_handler, interner: @ident_interner, // the unzipped tree: - cur: @mut TtFrame, + stack: @mut TtFrame, /* for MBE-style macro transcription */ interpolations: LinearMap, repeat_idx: ~[uint], @@ -58,8 +58,8 @@ pub fn new_tt_reader(sp_diag: @span_handler, let r = @mut TtReader { sp_diag: sp_diag, interner: itr, - cur: @mut TtFrame { - readme: @mut src, + stack: @mut TtFrame { + forest: @mut src, idx: 0u, dotdotdoted: false, sep: None, @@ -81,7 +81,7 @@ pub fn new_tt_reader(sp_diag: @span_handler, fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame { @mut TtFrame { - readme: @mut (copy *f.readme), + forest: @mut (copy *f.forest), idx: f.idx, dotdotdoted: f.dotdotdoted, sep: copy f.sep, @@ -96,7 +96,7 @@ pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader { @mut TtReader { sp_diag: r.sp_diag, interner: r.interner, - cur: dup_tt_frame(r.cur), + stack: dup_tt_frame(r.stack), interpolations: r.interpolations, repeat_idx: copy r.repeat_idx, repeat_len: copy r.repeat_len, @@ -167,7 +167,8 @@ fn lockstep_iter_size(t: token_tree, r: &mut TtReader) -> lis { } } - +// return the next token from the TtReader. +// EFFECT: advances the reader's token field pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { let ret_val = TokenAndSpan { tok: copy r.cur_tok, @@ -175,37 +176,37 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }; loop { { - let cur = &mut *r.cur; - let readme = &mut *cur.readme; - if cur.idx < readme.len() { + let stack = &mut *r.stack; + let forest = &mut *stack.forest; + if stack.idx < forest.len() { break; } } /* done with this set; pop or repeat? */ - if ! r.cur.dotdotdoted + if ! r.stack.dotdotdoted || { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } { - match r.cur.up { + match r.stack.up { None => { r.cur_tok = EOF; return ret_val; } Some(tt_f) => { - if r.cur.dotdotdoted { + if r.stack.dotdotdoted { r.repeat_idx.pop(); r.repeat_len.pop(); } - r.cur = tt_f; - r.cur.idx += 1u; + r.stack = tt_f; + r.stack.idx += 1u; } } } else { /* repeat */ - r.cur.idx = 0u; + r.stack.idx = 0u; r.repeat_idx[r.repeat_idx.len() - 1u] += 1u; - match r.cur.sep { + match r.stack.sep { Some(copy tk) => { r.cur_tok = tk; /* repeat same span, I guess */ return ret_val; @@ -216,21 +217,21 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } loop { /* because it's easiest, this handles `tt_delim` not starting with a `tt_tok`, even though it won't happen */ - match r.cur.readme[r.cur.idx] { + match r.stack.forest[r.stack.idx] { tt_delim(copy tts) => { - r.cur = @mut TtFrame { - readme: @mut tts, + r.stack = @mut TtFrame { + forest: @mut tts, idx: 0u, dotdotdoted: false, sep: None, - up: option::Some(r.cur) + up: option::Some(r.stack) }; // if this could be 0-length, we'd need to potentially recur here } tt_tok(sp, copy tok) => { r.cur_span = sp; r.cur_tok = tok; - r.cur.idx += 1u; + r.stack.idx += 1u; return ret_val; } tt_seq(sp, copy tts, copy sep, zerok) => { @@ -256,17 +257,17 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { once"); } - r.cur.idx += 1u; + r.stack.idx += 1u; return tt_next_token(r); } else { r.repeat_len.push(len); r.repeat_idx.push(0u); - r.cur = @mut TtFrame { - readme: @mut tts, + r.stack = @mut TtFrame { + forest: @mut tts, idx: 0u, dotdotdoted: true, sep: sep, - up: Some(r.cur) + up: Some(r.stack) }; } } @@ -280,13 +281,13 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { (b) we actually can, since it's a token. */ matched_nonterminal(nt_ident(sn,b)) => { r.cur_span = sp; r.cur_tok = IDENT(sn,b); - r.cur.idx += 1u; + r.stack.idx += 1u; return ret_val; } matched_nonterminal(ref other_whole_nt) => { r.cur_span = sp; r.cur_tok = INTERPOLATED(copy *other_whole_nt); - r.cur.idx += 1u; + r.stack.idx += 1u; return ret_val; } matched_seq(*) => { From 556143c488f8b8b2ac25ac29efdf030017cba7d7 Mon Sep 17 00:00:00 2001 From: John Clements Date: Fri, 8 Mar 2013 10:19:19 -0800 Subject: [PATCH 003/403] commenting parser --- src/libsyntax/parse/common.rs | 15 ++++++++++++++- src/libsyntax/parse/lexer.rs | 7 ++++++- src/libsyntax/parse/mod.rs | 8 ++++++-- src/libsyntax/parse/parser.rs | 24 ++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index c14c7bed1399f..ae7dd8ff96fce 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -159,6 +159,9 @@ pub impl Parser { } } + // if the given word is not a keyword, signal an error. + // if the next token is the given keyword, eat it and return + // true. Otherwise, return false. fn eat_keyword(&self, word: &~str) -> bool { self.require_keyword(word); let is_kw = match *self.token { @@ -169,6 +172,9 @@ pub impl Parser { is_kw } + // if the given word is not a keyword, signal an error. + // if the next token is not the given word, signal an error. + // otherwise, eat it. fn expect_keyword(&self, word: &~str) { self.require_keyword(word); if !self.eat_keyword(word) { @@ -182,10 +188,12 @@ pub impl Parser { } } + // return true if the given string is a strict keyword fn is_strict_keyword(&self, word: &~str) -> bool { self.strict_keywords.contains(word) } + // signal an error if the current token is a strict keyword fn check_strict_keywords(&self) { match *self.token { token::IDENT(_, false) => { @@ -196,16 +204,19 @@ pub impl Parser { } } + // signal an error if the given string is a strict keyword fn check_strict_keywords_(&self, w: &~str) { if self.is_strict_keyword(w) { self.fatal(fmt!("found `%s` in ident position", *w)); } } + // return true if this is a reserved keyword fn is_reserved_keyword(&self, word: &~str) -> bool { self.reserved_keywords.contains(word) } + // signal an error if the current token is a reserved keyword fn check_reserved_keywords(&self) { match *self.token { token::IDENT(_, false) => { @@ -216,6 +227,7 @@ pub impl Parser { } } + // signal an error if the given string is a reserved keyword fn check_reserved_keywords_(&self, w: &~str) { if self.is_reserved_keyword(w) { self.fatal(fmt!("`%s` is a reserved keyword", *w)); @@ -223,7 +235,8 @@ pub impl Parser { } // expect and consume a GT. if a >> is seen, replace it - // with a single > and continue. + // with a single > and continue. If a GT is not seen, + // signal an error. fn expect_gt(&self) { if *self.token == token::GT { self.bump(); diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index ffd2a1d801c96..512b6c0ec78eb 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -80,7 +80,8 @@ pub fn new_low_level_string_reader(span_diagnostic: @span_handler, last_pos: filemap.start_pos, col: CharPos(0), curr: initial_char, - filemap: filemap, interner: itr, + filemap: filemap, + interner: itr, /* dummy values; not read */ peek_tok: token::EOF, peek_span: codemap::dummy_sp() @@ -150,6 +151,7 @@ impl reader for TtReader { } // EFFECT: advance peek_tok and peek_span to refer to the next token. +// EFFECT: update the interner, maybe. fn string_advance_token(r: @mut StringReader) { match (consume_whitespace_and_comments(r)) { Some(comment) => { @@ -539,6 +541,9 @@ fn ident_continue(c: char) -> bool { || (c > 'z' && char::is_XID_continue(c)) } +// return the next token from the string +// EFFECT: advances the input past that token +// EFFECT: updates the interner fn next_token_inner(rdr: @mut StringReader) -> token::Token { let mut accum_str = ~""; let mut c = rdr.curr; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index cdb67129c355b..ba7a9624c1895 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -45,10 +45,14 @@ pub mod classify; /// Reporting obsolete syntax pub mod obsolete; +// info about a parsing session. +// This structure and the reader both have +// an interner associated with them. If they're +// not the same, bad things can happen. pub struct ParseSess { - cm: @codemap::CodeMap, + cm: @codemap::CodeMap, // better be the same as the one in the reader! next_id: node_id, - span_diagnostic: @span_handler, + span_diagnostic: @span_handler, // better be the same as the one in the reader! interner: @ident_interner, } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d93e5995d4f8e..fc5254726534d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -246,6 +246,7 @@ pub fn Parser(sess: @mut ParseSess, } } +// ooh, nasty mutable fields everywhere.... pub struct Parser { sess: @mut ParseSess, cfg: crate_cfg, @@ -338,6 +339,7 @@ pub impl Parser { self.sess.interner.get(id) } + // is this one of the keywords that signals a closure type? fn token_is_closure_keyword(&self, tok: &token::Token) -> bool { self.token_is_keyword(&~"pure", tok) || self.token_is_keyword(&~"unsafe", tok) || @@ -345,6 +347,7 @@ pub impl Parser { self.token_is_keyword(&~"fn", tok) } + // parse a ty_bare_fun type: fn parse_ty_bare_fn(&self) -> ty_ { /* @@ -372,6 +375,7 @@ pub impl Parser { }); } + // parse a ty_closure type fn parse_ty_closure(&self, sigil: ast::Sigil, region: Option<@ast::Lifetime>) -> ty_ @@ -430,6 +434,7 @@ pub impl Parser { } } + // parse a function type (following the 'fn') fn parse_ty_fn_decl(&self) -> (fn_decl, OptVec) { /* @@ -541,12 +546,14 @@ pub impl Parser { } + // parse a possibly mutable type fn parse_mt(&self) -> mt { let mutbl = self.parse_mutability(); let t = self.parse_ty(false); mt { ty: t, mutbl: mutbl } } + // parse [mut/const/imm] ID : TY fn parse_ty_field(&self) -> ty_field { let lo = self.span.lo; let mutbl = self.parse_mutability(); @@ -563,6 +570,7 @@ pub impl Parser { ) } + // parse optional return type [ -> TY ] in function decl fn parse_ret_ty(&self) -> (ret_style, @Ty) { return if self.eat(&token::RARROW) { let lo = self.span.lo; @@ -591,6 +599,7 @@ pub impl Parser { } } + // parse a type. // Useless second parameter for compatibility with quasiquote macros. // Bleh! fn parse_ty(&self, _: bool) -> @Ty { @@ -627,15 +636,19 @@ pub impl Parser { t } } else if *self.token == token::AT { + // MANAGED POINTER self.bump(); self.parse_box_or_uniq_pointee(ManagedSigil, ty_box) } else if *self.token == token::TILDE { + // OWNED POINTER self.bump(); self.parse_box_or_uniq_pointee(OwnedSigil, ty_uniq) } else if *self.token == token::BINOP(token::STAR) { + // STAR POINTER (bare pointer?) self.bump(); ty_ptr(self.parse_mt()) } else if *self.token == token::LBRACE { + // STRUCTURAL RECORD (remove?) let elems = self.parse_unspanned_seq( &token::LBRACE, &token::RBRACE, @@ -648,6 +661,7 @@ pub impl Parser { self.obsolete(*self.last_span, ObsoleteRecordType); ty_nil } else if *self.token == token::LBRACKET { + // VECTOR self.expect(&token::LBRACKET); let mt = self.parse_mt(); if mt.mutbl == m_mutbl { // `m_const` too after snapshot @@ -663,16 +677,20 @@ pub impl Parser { self.expect(&token::RBRACKET); t } else if *self.token == token::BINOP(token::AND) { + // BORROWED POINTER self.bump(); self.parse_borrowed_pointee() } else if self.eat_keyword(&~"extern") { + // EXTERN FUNCTION self.parse_ty_bare_fn() } else if self.token_is_closure_keyword(© *self.token) { + // CLOSURE let result = self.parse_ty_closure(ast::BorrowedSigil, None); self.obsolete(*self.last_span, ObsoleteBareFnType); result } else if *self.token == token::MOD_SEP || is_ident_or_path(&*self.token) { + // NAMED TYPE let path = self.parse_path_with_tps(false); ty_path(path, self.get_id()) } else { @@ -881,6 +899,8 @@ pub impl Parser { let global = self.eat(&token::MOD_SEP); let mut ids = ~[]; loop { + // if there's a ::< coming, stop processing + // the path. let is_not_last = self.look_ahead(2u) != token::LT && self.look_ahead(1u) == token::MOD_SEP; @@ -900,6 +920,9 @@ pub impl Parser { types: ~[] } } + // parse a path optionally with type parameters. If 'colons' + // is true, then type parameters must be preceded by colons, + // as in a::t:: fn parse_path_with_tps(&self, colons: bool) -> @ast::path { debug!("parse_path_with_tps(colons=%b)", colons); @@ -1067,6 +1090,7 @@ pub impl Parser { self.token_is_keyword(&~"const", tok) } + // parse mutability declaration (mut/const/imm) fn parse_mutability(&self) -> mutability { if self.eat_keyword(&~"mut") { m_mutbl From f2e47cddf835af49a925d91639d7fefb8c23d08f Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 6 Mar 2013 12:38:13 -0800 Subject: [PATCH 004/403] change to parsing using tts also, updates test cases a bit --- src/librustc/driver/driver.rs | 2 +- src/libsyntax/parse/mod.rs | 44 ++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 3aa0959317a4a..1f463a1614d23 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -150,7 +150,7 @@ pub fn parse_input(sess: Session, +cfg: ast::crate_cfg, input: input) -> @ast::crate { match input { file_input(ref file) => { - parse::parse_crate_from_file(&(*file), cfg, sess.parse_sess) + parse::parse_crate_from_file_using_tts(&(*file), cfg, sess.parse_sess) } str_input(ref src) => { // FIXME (#2319): Don't really want to box the source string diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ba7a9624c1895..10d3de4acee81 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -94,6 +94,19 @@ pub fn parse_crate_from_file( // why is there no p.abort_if_errors here? } +pub fn parse_crate_from_file_using_tts( + input: &Path, + cfg: ast::crate_cfg, + sess: @mut ParseSess +) -> @ast::crate { + let p = new_parser_from_file(sess, /*bad*/ copy cfg, input); + let tts = p.parse_all_token_trees(); + new_parser_from_tts(sess,cfg,tts).parse_crate_mod(/*bad*/ copy cfg) + // why is there no p.abort_if_errors here? +} + + + pub fn parse_crate_from_source_str( name: ~str, source: @~str, @@ -317,6 +330,7 @@ mod test { use std; use core::io; use core::option::None; + use ast; #[test] fn to_json_str>(val: @E) -> ~str { do io::with_str_writer |writer| { @@ -324,10 +338,38 @@ mod test { } } + fn string_to_crate (source_str : @~str) -> @ast::crate { + parse_crate_from_source_str( + ~"bogofile", + source_str, + ~[], + new_parse_sess(None)) + } + + fn string_to_tt_to_crate (source_str : @~str) -> @ast::crate { + let tts = parse_tts_from_source_str( + ~"bogofile", + source_str, + ~[], + new_parse_sess(None)); + new_parser_from_tts(new_parse_sess(None),~[],tts) + .parse_crate_mod(~[]) + } + + // make sure that parsing from TTs produces the same result + // as parsing from strings + #[test] fn tts_produce_the_same_result () { + let source_str = @~"fn foo (x : int) { x; }"; + assert_eq!(string_to_tt_to_crate(source_str), + string_to_crate(source_str)); + } + + // check the contents of the tt manually: #[test] fn alltts () { + let source_str = @~"fn foo (x : int) { x; }"; let tts = parse_tts_from_source_str( ~"bogofile", - @~"fn foo (x : int) { x; }", + source_str, ~[], new_parse_sess(None)); assert_eq!( From a20d1ad0cbcca13ee386fd819f33563b465f1185 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 1 Apr 2013 16:37:40 -0700 Subject: [PATCH 005/403] Improve documentation for core::io. --- src/libcore/io.rs | 76 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 60a0ee4fa9713..be3e100631488 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -49,29 +49,89 @@ pub mod rustrt { // FIXME (#2004): This is all buffered. We might need an unbuffered variant // as well +/** +* The SeekStyle enum describes the relationship between the position +* we'd like to seek to from our current position. It's used as an argument +* to the `seek` method defined on the `Reader` trait. +* +* There are three seek styles: +* +* 1. `SeekSet` means that the new position should become our position. +* 2. `SeekCur` means that we should seek from the current position. +* 3. `SeekEnd` means that we should seek from the end. +* +* # Examples +* +* None right now. +*/ pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, } -/// The raw underlying reader trait. All readers must implement this. +/** +* The core Reader trait. All readers must implement this trait. +* +* # Examples +* +* None right now. +*/ 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. + /** + * Reads bytes and puts them into `bytes`. Returns the number of + * bytes read. + * + * The number of bytes to be read is `len` or the end of the file, + * whichever comes first. + * + * The buffer must be at least `len` bytes long. + * + * # Examples + * + * None right now. + */ fn read(&self, bytes: &mut [u8], len: uint) -> uint; - /// Read a single byte, returning a negative value for EOF or read error. + /** + * Reads a single byte. + * + * In the case of an EOF or an error, returns a negative value. + * + * # Examples + * + * None right now. + */ fn read_byte(&self) -> int; - /// Return whether the stream is currently at EOF position. + /** + * Returns a boolean value: are we currently at EOF? + * + * # Examples + * + * None right now. + */ fn eof(&self) -> bool; - /// Move the current position within the stream. The second parameter - /// determines the position that the first parameter is relative to. + /** + * Seek to a given `position` in the stream. + * + * Takes an optional SeekStyle, which affects how we seek from the + * position. See `SeekStyle` docs for more details. + * + * # Examples + * + * None right now. + */ fn seek(&self, position: int, style: SeekStyle); - /// Return the current position within the stream. + /** + * Returns the current position within the stream. + * + * # Examples + * + * None right now. + */ fn tell(&self) -> uint; } From 1d658d9b97434a391a7e202a033080555a2bc69e Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 1 Apr 2013 18:03:54 -0700 Subject: [PATCH 006/403] Improve docs for Core::ReaderUtil. I filled out better descriptions for all of the neccesary functions. --- src/libcore/io.rs | 375 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 335 insertions(+), 40 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 60a0ee4fa9713..1a15a9f5d809c 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -93,120 +93,415 @@ impl Reader for @Reader { } } -/// Generic utility functions defined on readers. +/** +* The `ReaderUtil` trait is a home for many of the utility functions +* a particular Reader should implement. +* +* The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based +* on higher-level concepts like 'chars' and 'lines.' +* +* # Examples: +* +* None right now. +*/ pub trait ReaderUtil { - /// Read len bytes into a new vec. + /** + * Reads `len` number of bytes, and gives you a new vector back. + * + * # Examples + * + * None right now. + */ fn read_bytes(&self, len: uint) -> ~[u8]; - /// Read up until a specified character (which is optionally included) or EOF. + /** + * Reads up until a specific character or EOF. + * + * The `include` parameter specifies if the character should be included + * in the returned string. + * + * # Examples + * + * None right now. + */ fn read_until(&self, c: char, include: bool) -> ~str; - /// Read up until the first '\n' char (which is not returned), or EOF. + /** + * Reads up until the first '\n' or EOF. + * + * The '\n' is not included in the result. + * + * # Examples + * + * None right now. + */ fn read_line(&self) -> ~str; - /// Read n utf-8 encoded chars. + /** + * Reads `n` chars. + * + * Assumes that those chars are UTF-8 encoded. + * + * The '\n' is not included in the result. + * + * # Examples + * + * None right now. + */ fn read_chars(&self, n: uint) -> ~[char]; - /// Read a single utf-8 encoded char. + /** + * Reads a single UTF-8 encoded char. + * + * # Examples + * + * None right now. + */ fn read_char(&self) -> char; - /// Read up until the first null byte (which is not returned), or EOF. + /** + * Reads up until the first null byte or EOF. + * + * The null byte is not returned. + * + * # Examples + * + * None right now. + */ fn read_c_str(&self) -> ~str; - /// Read all the data remaining in the stream in one go. + /** + * Reads all remaining data in the stream. + * + * # Examples + * + * None right now. + */ fn read_whole_stream(&self) -> ~[u8]; - /// Iterate over every byte until the iterator breaks or EOF. + /** + * Iterate over every byte until EOF or the iterator breaks. + * + * # Examples + * + * None right now. + */ fn each_byte(&self, it: &fn(int) -> bool); - /// Iterate over every char until the iterator breaks or EOF. + /** + * Iterate over every char until EOF or the iterator breaks. + * + * # Examples + * + * None right now. + */ fn each_char(&self, it: &fn(char) -> bool); - /// Iterate over every line until the iterator breaks or EOF. + /** + * Iterate over every line until EOF or the iterator breaks. + * + * # Examples + * + * None right now. + */ fn each_line(&self, it: &fn(&str) -> bool); - /// Read all the lines of the file into a vector. + /** + * Reads all of the lines in the stream. + * + * Returns a vector of those lines. + * + * # Examples + * + * None right now. + */ fn read_lines(&self) -> ~[~str]; - /// Read n (between 1 and 8) little-endian unsigned integer bytes. + /** + * Reads `n` little-endian unsigned integer bytes. + * + * `n` must be between 1 and 8, inclusive. + * + * # Examples + * + * None right now. + */ fn read_le_uint_n(&self, nbytes: uint) -> u64; - /// Read n (between 1 and 8) little-endian signed integer bytes. + /** + * Reads `n` little-endian signed integer bytes. + * + * `n` must be between 1 and 8, inclusive. + * + * # Examples + * + * None right now. + */ fn read_le_int_n(&self, nbytes: uint) -> i64; - /// Read n (between 1 and 8) big-endian unsigned integer bytes. + /** + * Reads `n` big-endian unsigned integer bytes. + * + * `n` must be between 1 and 8, inclusive. + * + * # Examples + * + * None right now. + */ fn read_be_uint_n(&self, nbytes: uint) -> u64; - /// Read n (between 1 and 8) big-endian signed integer bytes. + /** + * Reads `n` big-endian signed integer bytes. + * + * `n` must be between 1 and 8, inclusive. + * + * # Examples + * + * None right now. + */ fn read_be_int_n(&self, nbytes: uint) -> i64; - /// Read a little-endian uint (number of bytes depends on system). + /** + * Reads a little-endian unsigned integer. + * + * The number of bytes returned is system-dependant. + * + * # Examples + * + * None right now. + */ fn read_le_uint(&self) -> uint; - /// Read a little-endian int (number of bytes depends on system). + /** + * Reads a little-endian integer. + * + * The number of bytes returned is system-dependant. + * + * # Examples + * + * None right now. + */ fn read_le_int(&self) -> int; - /// Read a big-endian uint (number of bytes depends on system). + /** + * Reads a big-endian unsigned integer. + * + * The number of bytes returned is system-dependant. + * + * # Examples + * + * None right now. + */ fn read_be_uint(&self) -> uint; - /// Read a big-endian int (number of bytes depends on system). + /** + * Reads a big-endian integer. + * + * The number of bytes returned is system-dependant. + * + * # Examples + * + * None right now. + */ fn read_be_int(&self) -> int; - /// Read a big-endian u64 (8 bytes). + /** + * Reads a big-endian `u64`. + * + * `u64`s are 8 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_u64(&self) -> u64; - /// Read a big-endian u32 (4 bytes). + /** + * Reads a big-endian `u32`. + * + * `u32`s are 4 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_u32(&self) -> u32; - /// Read a big-endian u16 (2 bytes). + /** + * Reads a big-endian `u16`. + * + * `u16`s are 2 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_u16(&self) -> u16; - /// Read a big-endian i64 (8 bytes). + /** + * Reads a big-endian `i64`. + * + * `i64`s are 8 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_i64(&self) -> i64; - /// Read a big-endian i32 (4 bytes). + /** + * Reads a big-endian `i32`. + * + * `i32`s are 4 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_i32(&self) -> i32; - /// Read a big-endian i16 (2 bytes). + /** + * Reads a big-endian `i16`. + * + * `i16`s are 2 bytes long. + * + * # Examples + * + * None right now. + */ fn read_be_i16(&self) -> i16; - /// Read a big-endian IEEE754 double-precision floating-point (8 bytes). + /** + * Reads a big-endian `f64`. + * + * `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + * + * # Examples + * + * None right now. + */ fn read_be_f64(&self) -> f64; - /// Read a big-endian IEEE754 single-precision floating-point (4 bytes). + /** + * Reads a big-endian `f32`. + * + * `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + * + * # Examples + * + * None right now. + */ fn read_be_f32(&self) -> f32; - /// Read a little-endian u64 (8 bytes). + /** + * Reads a little-endian `u64`. + * + * `u64`s are 8 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_u64(&self) -> u64; - /// Read a little-endian u32 (4 bytes). + /** + * Reads a little-endian `u32`. + * + * `u32`s are 4 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_u32(&self) -> u32; - /// Read a little-endian u16 (2 bytes). + /** + * Reads a little-endian `u16`. + * + * `u16`s are 2 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_u16(&self) -> u16; - /// Read a litle-endian i64 (8 bytes). + /** + * Reads a little-endian `i64`. + * + * `i64`s are 8 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_i64(&self) -> i64; - /// Read a litle-endian i32 (4 bytes). + /** + * Reads a little-endian `i32`. + * + * `i32`s are 4 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_i32(&self) -> i32; - /// Read a litle-endian i16 (2 bytes). + /** + * Reads a little-endian `i16`. + * + * `i16`s are 2 bytes long. + * + * # Examples + * + * None right now. + */ fn read_le_i16(&self) -> i16; - /// Read a litten-endian IEEE754 double-precision floating-point - /// (8 bytes). + /** + * Reads a little-endian `f64`. + * + * `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + * + * # Examples + * + * None right now. + */ fn read_le_f64(&self) -> f64; - /// Read a litten-endian IEEE754 single-precision floating-point - /// (4 bytes). + /** + * Reads a little-endian `f32`. + * + * `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + * + * # Examples + * + * None right now. + */ fn read_le_f32(&self) -> f32; - /// Read a u8 (1 byte). + /** + * Read a u8. + * + * `u8`s are 1 byte. + * + * # Examples + * + * None right now. + */ fn read_u8(&self) -> u8; - /// Read a i8 (1 byte). + /** + * Read an i8. + * + * `u8`s are 1 byte. + * + * # Examples + * + * None right now. + */ fn read_i8(&self) -> i8; } From 948ff6056f9f4c2fe312da98456d3d6b7d1ce699 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 1 Apr 2013 18:20:30 -0700 Subject: [PATCH 007/403] Typo fix. u8 -> i8 --- src/libcore/io.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 1a15a9f5d809c..b3dfe8d46af2c 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -496,7 +496,7 @@ pub trait ReaderUtil { /** * Read an i8. * - * `u8`s are 1 byte. + * `i8`s are 1 byte. * * # Examples * From 88e4b5de8350968b69b9e4d9037f35a5eaf3f796 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 2 Apr 2013 19:25:03 -0400 Subject: [PATCH 008/403] install the librust{doc,pkg} host libraries --- mk/install.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mk/install.mk b/mk/install.mk index fd7f44ddae57c..a84f527a165b4 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -119,6 +119,8 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE)) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUST_GLOB_$(CFG_BUILD_TRIPLE))) + $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) + $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(S)/man, \ From 86d5ce5cef29e388de04c667e8cfd205327629cc Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 2 Apr 2013 17:29:02 -0700 Subject: [PATCH 009/403] remove trailing whitespace --- src/libcore/io.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index be3e100631488..925079f4cf212 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -55,14 +55,14 @@ pub mod rustrt { * to the `seek` method defined on the `Reader` trait. * * There are three seek styles: -* +* * 1. `SeekSet` means that the new position should become our position. * 2. `SeekCur` means that we should seek from the current position. * 3. `SeekEnd` means that we should seek from the end. * * # Examples -* -* None right now. +* +* None right now. */ pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, } @@ -71,8 +71,8 @@ pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, } * The core Reader trait. All readers must implement this trait. * * # Examples -* -* None right now. +* +* None right now. */ pub trait Reader { // FIXME (#2004): Seekable really should be orthogonal. @@ -82,14 +82,14 @@ pub trait Reader { * Reads bytes and puts them into `bytes`. Returns the number of * bytes read. * - * The number of bytes to be read is `len` or the end of the file, + * The number of bytes to be read is `len` or the end of the file, * whichever comes first. * * The buffer must be at least `len` bytes long. * * # Examples - * - * None right now. + * + * None right now. */ fn read(&self, bytes: &mut [u8], len: uint) -> uint; @@ -99,8 +99,8 @@ pub trait Reader { * In the case of an EOF or an error, returns a negative value. * * # Examples - * - * None right now. + * + * None right now. */ fn read_byte(&self) -> int; @@ -108,20 +108,20 @@ pub trait Reader { * Returns a boolean value: are we currently at EOF? * * # Examples - * - * None right now. + * + * None right now. */ fn eof(&self) -> bool; /** * Seek to a given `position` in the stream. - * + * * Takes an optional SeekStyle, which affects how we seek from the * position. See `SeekStyle` docs for more details. * * # Examples - * - * None right now. + * + * None right now. */ fn seek(&self, position: int, style: SeekStyle); @@ -129,8 +129,8 @@ pub trait Reader { * Returns the current position within the stream. * * # Examples - * - * None right now. + * + * None right now. */ fn tell(&self) -> uint; } From a3e2d6ea81b93bf41b4387be935b5f488e47ef73 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 2 Apr 2013 17:31:42 -0700 Subject: [PATCH 010/403] Remove excess trailing whitespace. --- src/libcore/io.rs | 122 +++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index b3dfe8d46af2c..c49117fe23d48 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -96,10 +96,10 @@ impl Reader for @Reader { /** * The `ReaderUtil` trait is a home for many of the utility functions * a particular Reader should implement. -* +* * The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based * on higher-level concepts like 'chars' and 'lines.' -* +* * # Examples: * * None right now. @@ -117,7 +117,7 @@ pub trait ReaderUtil { /** * Reads up until a specific character or EOF. - * + * * The `include` parameter specifies if the character should be included * in the returned string. * @@ -129,7 +129,7 @@ pub trait ReaderUtil { /** * Reads up until the first '\n' or EOF. - * + * * The '\n' is not included in the result. * * # Examples @@ -140,9 +140,9 @@ pub trait ReaderUtil { /** * Reads `n` chars. - * + * * Assumes that those chars are UTF-8 encoded. - * + * * The '\n' is not included in the result. * * # Examples @@ -209,7 +209,7 @@ pub trait ReaderUtil { /** * Reads all of the lines in the stream. - * + * * Returns a vector of those lines. * * # Examples @@ -220,9 +220,9 @@ pub trait ReaderUtil { /** * Reads `n` little-endian unsigned integer bytes. - * + * * `n` must be between 1 and 8, inclusive. - * + * * # Examples * * None right now. @@ -231,9 +231,9 @@ pub trait ReaderUtil { /** * Reads `n` little-endian signed integer bytes. - * + * * `n` must be between 1 and 8, inclusive. - * + * * # Examples * * None right now. @@ -242,9 +242,9 @@ pub trait ReaderUtil { /** * Reads `n` big-endian unsigned integer bytes. - * + * * `n` must be between 1 and 8, inclusive. - * + * * # Examples * * None right now. @@ -253,9 +253,9 @@ pub trait ReaderUtil { /** * Reads `n` big-endian signed integer bytes. - * + * * `n` must be between 1 and 8, inclusive. - * + * * # Examples * * None right now. @@ -264,9 +264,9 @@ pub trait ReaderUtil { /** * Reads a little-endian unsigned integer. - * + * * The number of bytes returned is system-dependant. - * + * * # Examples * * None right now. @@ -275,9 +275,9 @@ pub trait ReaderUtil { /** * Reads a little-endian integer. - * + * * The number of bytes returned is system-dependant. - * + * * # Examples * * None right now. @@ -286,9 +286,9 @@ pub trait ReaderUtil { /** * Reads a big-endian unsigned integer. - * + * * The number of bytes returned is system-dependant. - * + * * # Examples * * None right now. @@ -297,9 +297,9 @@ pub trait ReaderUtil { /** * Reads a big-endian integer. - * + * * The number of bytes returned is system-dependant. - * + * * # Examples * * None right now. @@ -308,9 +308,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `u64`. - * + * * `u64`s are 8 bytes long. - * + * * # Examples * * None right now. @@ -319,9 +319,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `u32`. - * + * * `u32`s are 4 bytes long. - * + * * # Examples * * None right now. @@ -330,9 +330,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `u16`. - * + * * `u16`s are 2 bytes long. - * + * * # Examples * * None right now. @@ -341,9 +341,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `i64`. - * + * * `i64`s are 8 bytes long. - * + * * # Examples * * None right now. @@ -352,9 +352,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `i32`. - * + * * `i32`s are 4 bytes long. - * + * * # Examples * * None right now. @@ -363,9 +363,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `i16`. - * + * * `i16`s are 2 bytes long. - * + * * # Examples * * None right now. @@ -374,9 +374,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `f64`. - * + * * `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - * + * * # Examples * * None right now. @@ -385,9 +385,9 @@ pub trait ReaderUtil { /** * Reads a big-endian `f32`. - * + * * `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - * + * * # Examples * * None right now. @@ -396,9 +396,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `u64`. - * + * * `u64`s are 8 bytes long. - * + * * # Examples * * None right now. @@ -407,9 +407,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `u32`. - * + * * `u32`s are 4 bytes long. - * + * * # Examples * * None right now. @@ -418,9 +418,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `u16`. - * + * * `u16`s are 2 bytes long. - * + * * # Examples * * None right now. @@ -429,9 +429,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `i64`. - * + * * `i64`s are 8 bytes long. - * + * * # Examples * * None right now. @@ -440,9 +440,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `i32`. - * + * * `i32`s are 4 bytes long. - * + * * # Examples * * None right now. @@ -451,9 +451,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `i16`. - * + * * `i16`s are 2 bytes long. - * + * * # Examples * * None right now. @@ -462,9 +462,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `f64`. - * + * * `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - * + * * # Examples * * None right now. @@ -473,9 +473,9 @@ pub trait ReaderUtil { /** * Reads a little-endian `f32`. - * + * * `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - * + * * # Examples * * None right now. @@ -483,10 +483,10 @@ pub trait ReaderUtil { fn read_le_f32(&self) -> f32; /** - * Read a u8. - * + * Read a u8. + * * `u8`s are 1 byte. - * + * * # Examples * * None right now. @@ -494,10 +494,10 @@ pub trait ReaderUtil { fn read_u8(&self) -> u8; /** - * Read an i8. - * + * Read an i8. + * * `i8`s are 1 byte. - * + * * # Examples * * None right now. From e4edfa046af08a345c607ec9c80426d9eabc7c82 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 23 Feb 2013 17:46:04 +1100 Subject: [PATCH 011/403] libstd: implement fileinput. Iterate over lines in a series of files. API (mostly) adopted from Python's fileinput module. --- src/libstd/fileinput.rs | 464 ++++++++++++++++++++++++++++++++++++++++ src/libstd/std.rc | 1 + 2 files changed, 465 insertions(+) create mode 100644 src/libstd/fileinput.rs diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs new file mode 100644 index 0000000000000..3f281150331d6 --- /dev/null +++ b/src/libstd/fileinput.rs @@ -0,0 +1,464 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! +A convience device for iterating through the lines in a series of +files. Very similar to [the Python module of the same +name](http://docs.python.org/3.3/library/fileinput.html). + +It allows the programmer to automatically take filenames from the +command line arguments (via `input` and `input_state`), as well as +specify them as a vector directly (`input_vec` and +`input_vec_state`). The files are opened as necessary, so any files +that can't be opened only cause an error when reached in the +iteration. + +On the command line, `stdin` is represented by a filename of `-` (a +single hyphen) and in the functions that take a vector directly +(e.g. `input_vec`) it is represented by `None`. Note `stdin` is *not* +reset once it has been finished, so attempting to iterate on `[None, +None]` will only take input once unless `io::stdin().seek(0, SeekSet)` +is called between. + +The `pathify` function handles converting a list of file paths as +strings to the appropriate format, including the (optional) conversion +of `"-"` to `stdin`. + +# Basic + +In many cases, one can use the `input_*` functions without having +to handle any `FileInput` structs. E.g. a simple `cat` program + + for input |line| { + io::println(line) + } + +or a program that numbers lines after concatenating two files + + for input_vec_state(pathify([~"a.txt", ~"b.txt"])) |line, state| { + io::println(fmt!("%u: %s", state.line_num, + line)); + } + +The 2 `_vec` functions take a vec of file names (and empty means +read from `stdin`), the other 2 use the command line arguments. + +# Advanced + +For more complicated uses (e.g. if one needs to pause iteration and +resume it later), a `FileInput` instance can be constructed via the +`from_vec`, `from_vec_raw` and `from_args` functions. + +Once created, the `lines_each` and `lines_each_state` methods +allow one to iterate on the lines (the latter provides more +information about the position within the iteration to the caller. + +It is possible (and safe) to skip lines and files using the +`read_line` and `next_file` methods. + +E.g. the following (pointless) program reads until an empty line, +pauses for user input, skips the current file and then numbers the +remaining lines (where the numbers are from the start of the file, +rather than the total line count). + + let mut in = FileInput::from_vec(pathify([~"a.txt", ~"b.txt", ~"c.txt"], + true)); + + for in.lines_each |line| { + if line.is_empty() { + break + } + io::println(line); + } + + io::println("Continue?"); + + if io::stdin().read_line() == ~"yes" { + in.next_file(); // skip! + + for in.lines_each_state |line, state| { + io::println(fmt!("%u: %s", state.line_num_file, + line)) + } + } +*/ + +use core::prelude::*; +use core::io::ReaderUtil; + +/** +A summary of the internal state of a FileInput object. `line_num` and +`line_num_file` represent the number of lines read in total and in the +current file respectively. +*/ +pub struct FileInputState { + current_path: Option, + line_num: uint, + line_num_file: uint +} + +impl FileInputState { + fn is_stdin(&self) -> bool { + self.current_path.is_none() + } + + fn is_first_line(&self) -> bool { + self.line_num_file == 1 + } +} + +priv struct FileInput { + /** + `Some(path)` is the file represented by `path`, `None` is + `stdin`. Consumed as the files are read. + */ + files: ~[Option], + /** + The current file: `Some(r)` for an open file, `None` before + starting and after reading everything. + */ + current_reader: Option<@io::Reader>, + state: FileInputState +} + +impl FileInput { + /** + Create a `FileInput` object from a vec of files. An empty + vec means lines are read from `stdin` (use `from_vec_raw` to stop + this behaviour). Any occurence of `None` represents `stdin`. + */ + static pure fn from_vec(files: ~[Option]) -> FileInput { + FileInput::from_vec_raw( + if files.is_empty() { + ~[None] + } else { + files + }) + } + + /** + Identical to `from_vec`, but an empty `files` vec stays + empty. (`None` is `stdin`.) + */ + static pure fn from_vec_raw(files: ~[Option]) + -> FileInput { + FileInput { + files: files, + current_reader: None, + state: FileInputState { + current_path: None, + line_num: 0, + line_num_file: 0 + } + } + } + + /** + Create a `FileInput` object from the command line + arguments. `-` represents `stdin`. + */ + static fn from_args() -> FileInput { + let args = os::args(), + pathed = pathify(args.tail(), true); + FileInput::from_vec(pathed) + } + + priv fn current_file_eof(&self) -> bool { + match self.current_reader { + None => false, + Some(r) => r.eof() + } + } + + /** + Skip to the next file in the queue. Can `fail` when opening + a file. + */ + pub fn next_file(&mut self) { + // No more files + if self.files.is_empty() { + self.current_reader = None; + return; + } + + let path_option = self.files.shift(), + file = match path_option { + None => io::stdin(), + Some(ref path) => io::file_reader(path).get() + }; + + self.current_reader = Some(file); + self.state.current_path = path_option; + self.state.line_num_file = 0; + } + + /** + Attempt to open the next file if there is none currently open, + or if the current one is EOF'd. + */ + priv fn next_file_if_eof(&mut self) { + match self.current_reader { + None => self.next_file(), + Some(r) => { + if r.eof() { + self.next_file() + } + } + } + } + + /** + Read a single line. Returns `None` if there are no remaining lines + in any remaining file. (Automatically opens files as required, see + `next_file` for details.) + + (Name to avoid conflicting with `core::io::ReaderUtil::read_line`.) + */ + pub fn next_line(&mut self) -> Option<~str> { + loop { + // iterate until there is a file that can be read from + self.next_file_if_eof(); + match self.current_reader { + None => { + // no file has any content + return None; + }, + Some(r) => { + let l = r.read_line(); + + // at the end of this file, and we read nothing, so + // go to the next file + if r.eof() && l.is_empty() { + loop; + } + self.state.line_num += 1; + self.state.line_num_file += 1; + return Some(l); + } + } + } + } + + /** + Call `f` on the lines in the files in succession, stopping if + it ever returns `false`. + + State is preserved across calls. + + (The name is to avoid conflict with + `core::io::ReaderUtil::each_line`.) + */ + pub fn lines_each(&mut self, f: &fn(~str) -> bool) { + loop { + match self.next_line() { + None => break, + Some(line) => { + if !f(line) { + break; + } + } + } + } + } + + /** + Apply `f` to each line successively, along with some state + (line numbers and file names, see documentation for + `FileInputState`). Otherwise identical to `lines_each`. + */ + pub fn lines_each_state(&mut self, + f: &fn(~str, &FileInputState) -> bool) { + loop { + match self.next_line() { + None => break, + Some(line) => { + if !f(line, &self.state) { + break; + } + } + } + } + } +} + +/** +Convert a list of strings to an appropriate form for a `FileInput` +instance. `stdin_hyphen` controls whether `-` represents `stdin` or +not. +*/ +// XXX: stupid, unclear name +pub fn pathify(vec: &[~str], stdin_hyphen : bool) -> ~[Option] { + vec::map(vec, |&str : & ~str| { + if stdin_hyphen && str == ~"-" { + None + } else { + Some(Path(str)) + } + }) +} + +/** +Iterate directly over the command line arguments (no arguments implies +reading from `stdin`). + +Fails when attempting to read from a file that can't be opened. +*/ +pub fn input(f: &fn(~str) -> bool) { + let mut i = FileInput::from_args(); + i.lines_each(f); +} + +/** +Iterate directly over the command line arguments (no arguments +implies reading from `stdin`) with the current state of the iteration +provided at each call. + +Fails when attempting to read from a file that can't be opened. +*/ +pub fn input_state(f: &fn(~str, &FileInputState) -> bool) { + let mut i = FileInput::from_args(); + i.lines_each_state(f); +} + +/** +Iterate over a vec of files (an empty vec implies just `stdin`). + +Fails when attempting to read from a file that can't be opened. +*/ +pub fn input_vec(files: ~[Option], f: &fn(~str) -> bool) { + let mut i = FileInput::from_vec(files); + i.lines_each(f); +} + +/** +Iterate over a vec of files (an empty vec implies just `stdin`) with +the current state of the iteration provided at each call. + +Fails when attempting to read from a file that can't be opened. +*/ +pub fn input_vec_state(files: ~[Option], + f: &fn(~str, &FileInputState) -> bool) { + let mut i = FileInput::from_vec(files); + i.lines_each_state(f); +} + +#[cfg(test)] +mod test { + use core::io::WriterUtil; + use core::prelude::*; + use super::{FileInput, pathify, input_vec, input_vec_state}; + + fn make_file(path : &Path, contents: &[~str]) { + let file = io::file_writer(path, [io::Create, io::Truncate]).get(); + + for contents.each |&str| { + file.write_str(str); + file.write_char('\n'); + } + } + + #[test] + fn test_pathify() { + let strs = [~"some/path", + ~"some/other/path"], + paths = ~[Some(Path("some/path")), + Some(Path("some/other/path"))]; + + fail_unless!(pathify(strs, true) == paths); + fail_unless!(pathify(strs, false) == paths); + + fail_unless!(pathify([~"-"], true) == ~[None]); + fail_unless!(pathify([~"-"], false) == ~[Some(Path("-"))]); + } + + #[test] + fn test_input_vec() { + let mut all_lines = ~[]; + let filenames = pathify(vec::from_fn( + 3, + |i| fmt!("tmp/lib-fileinput-test-input-vec-%u.tmp", i)), true); + + for filenames.eachi |i, &filename| { + let contents = + vec::from_fn(3, |j| fmt!("%u %u", i, j)); + make_file(&filename.get(), contents); + all_lines.push_all(contents); + } + + let mut read_lines = ~[]; + for input_vec(filenames) |line| { + read_lines.push(line); + } + fail_unless!(read_lines == all_lines); + } + + #[test] + fn test_input_vec_state() { + let filenames = pathify(vec::from_fn( + 3, + |i| + fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true); + + for filenames.eachi |i, &filename| { + let contents = + vec::from_fn(3, |j| fmt!("%u %u", i, j + 1)); + make_file(&filename.get(), contents); + } + + for input_vec_state(filenames) |line, state| { + let nums = str::split_char(line, ' '); + + let file_num = uint::from_str(nums[0]).get(); + let line_num = uint::from_str(nums[1]).get(); + + fail_unless!(line_num == state.line_num_file); + fail_unless!(file_num * 3 + line_num == state.line_num); + } + } + + #[test] + fn test_next_file() { + let filenames = pathify(vec::from_fn( + 3, + |i| + fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); + + for filenames.eachi |i, &filename| { + let contents = + vec::from_fn(3, |j| fmt!("%u %u", i, j + 1)); + make_file(&filename.get(), contents); + } + + let mut in = FileInput::from_vec(filenames); + + // read once from 0 + fail_unless!(in.next_line() == Some(~"0 1")); + in.next_file(); // skip the rest of 1 + + // read all lines from 1 (but don't read any from 2), + for uint::range(1, 4) |i| { + fail_unless!(in.next_line() == Some(fmt!("1 %u", i))); + } + // 1 is finished, but 2 hasn't been started yet, so this will + // just "skip" to the beginning of 2 (Python's fileinput does + // the same) + in.next_file(); + + fail_unless!(in.next_line() == Some(~"2 1")); + } + + #[test] + #[should_fail] + fn test_input_vec_missing_file() { + for input_vec(pathify([~"this/file/doesnt/exist"], true)) |line| { + io::println(line); + } + } +} diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 89bdc750c2277..74ef229a03353 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -98,6 +98,7 @@ pub mod workcache; pub mod bigint; pub mod stats; pub mod semver; +pub mod fileinput; #[cfg(unicode)] mod unicode; From 1e28d8fdb63a469ec9b1c8f2e79eae04f228b65e Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 25 Mar 2013 21:34:36 +1100 Subject: [PATCH 012/403] libstd: implement io::Reader for fileinput. --- src/libstd/fileinput.rs | 397 +++++++++++++++++++++++++++------------- 1 file changed, 271 insertions(+), 126 deletions(-) diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs index 3f281150331d6..0056b34eccbca 100644 --- a/src/libstd/fileinput.rs +++ b/src/libstd/fileinput.rs @@ -9,7 +9,7 @@ // except according to those terms. /*! -A convience device for iterating through the lines in a series of +A library for iterating through the lines in a series of files. Very similar to [the Python module of the same name](http://docs.python.org/3.3/library/fileinput.html). @@ -47,8 +47,9 @@ or a program that numbers lines after concatenating two files line)); } -The 2 `_vec` functions take a vec of file names (and empty means -read from `stdin`), the other 2 use the command line arguments. +The two `input_vec*` functions take a vec of file names (where empty +means read from `stdin`), the other two functions use the command line +arguments. # Advanced @@ -56,22 +57,25 @@ For more complicated uses (e.g. if one needs to pause iteration and resume it later), a `FileInput` instance can be constructed via the `from_vec`, `from_vec_raw` and `from_args` functions. -Once created, the `lines_each` and `lines_each_state` methods -allow one to iterate on the lines (the latter provides more -information about the position within the iteration to the caller. +Once created, the `each_line` (from the `core::io::ReaderUtil` trait) +and `each_line_state` methods allow one to iterate on the lines; the +latter provides more information about the position within the +iteration to the caller. It is possible (and safe) to skip lines and files using the -`read_line` and `next_file` methods. +`read_line` and `next_file` methods. Also, `FileInput` implements +`core::io::Reader`, and the state will be updated correctly while +using any of those methods. -E.g. the following (pointless) program reads until an empty line, -pauses for user input, skips the current file and then numbers the -remaining lines (where the numbers are from the start of the file, -rather than the total line count). +E.g. the following program reads until an empty line, pauses for user +input, skips the current file and then numbers the remaining lines +(where the numbers are from the start of each file, rather than the +total line count). - let mut in = FileInput::from_vec(pathify([~"a.txt", ~"b.txt", ~"c.txt"], + let in = FileInput::from_vec(pathify([~"a.txt", ~"b.txt", ~"c.txt"], true)); - for in.lines_each |line| { + for in.each_line |line| { if line.is_empty() { break } @@ -83,20 +87,23 @@ rather than the total line count). if io::stdin().read_line() == ~"yes" { in.next_file(); // skip! - for in.lines_each_state |line, state| { + for in.each_line_state |line, state| { io::println(fmt!("%u: %s", state.line_num_file, line)) } } */ +#[allow(deprecated_mutable_fields)]; + use core::prelude::*; use core::io::ReaderUtil; /** -A summary of the internal state of a FileInput object. `line_num` and -`line_num_file` represent the number of lines read in total and in the -current file respectively. +A summary of the internal state of a `FileInput` object. `line_num` +and `line_num_file` represent the number of lines read in total and in +the current file respectively. `current_path` is `None` if the current +file is `stdin`. */ pub struct FileInputState { current_path: Option, @@ -114,18 +121,32 @@ impl FileInputState { } } -priv struct FileInput { +struct FileInput_ { /** `Some(path)` is the file represented by `path`, `None` is `stdin`. Consumed as the files are read. */ - files: ~[Option], + priv files: ~[Option], /** The current file: `Some(r)` for an open file, `None` before starting and after reading everything. */ - current_reader: Option<@io::Reader>, - state: FileInputState + priv current_reader: Option<@io::Reader>, + priv state: FileInputState, + + /** + Used to keep track of whether we need to insert the newline at the + end of a file that is missing it, which is needed to separate the + last and first lines. + */ + priv previous_was_newline: bool +} + +// XXX: remove this when Reader has &mut self. Should be removable via +// "self.fi." -> "self." and renaming FileInput_. Documentation above +// will likely have to be updated to use `let mut in = ...`. +pub struct FileInput { + priv mut fi: FileInput_ } impl FileInput { @@ -134,7 +155,7 @@ impl FileInput { vec means lines are read from `stdin` (use `from_vec_raw` to stop this behaviour). Any occurence of `None` represents `stdin`. */ - static pure fn from_vec(files: ~[Option]) -> FileInput { + pub fn from_vec(files: ~[Option]) -> FileInput { FileInput::from_vec_raw( if files.is_empty() { ~[None] @@ -147,31 +168,35 @@ impl FileInput { Identical to `from_vec`, but an empty `files` vec stays empty. (`None` is `stdin`.) */ - static pure fn from_vec_raw(files: ~[Option]) + pub fn from_vec_raw(files: ~[Option]) -> FileInput { - FileInput { - files: files, - current_reader: None, - state: FileInputState { - current_path: None, - line_num: 0, - line_num_file: 0 + FileInput{ + fi: FileInput_ { + files: files, + current_reader: None, + state: FileInputState { + current_path: None, + line_num: 0, + line_num_file: 0 + }, + // there was no previous unended line + previous_was_newline: true } } } /** Create a `FileInput` object from the command line - arguments. `-` represents `stdin`. + arguments. `"-"` represents `stdin`. */ - static fn from_args() -> FileInput { + pub fn from_args() -> FileInput { let args = os::args(), pathed = pathify(args.tail(), true); FileInput::from_vec(pathed) } priv fn current_file_eof(&self) -> bool { - match self.current_reader { + match self.fi.current_reader { None => false, Some(r) => r.eof() } @@ -180,110 +205,143 @@ impl FileInput { /** Skip to the next file in the queue. Can `fail` when opening a file. + + Returns `false` if there is no more files, and `true` when it + successfully opens the next file. */ - pub fn next_file(&mut self) { + + pub fn next_file(&self) -> bool { // No more files - if self.files.is_empty() { - self.current_reader = None; - return; + + // Compiler whines about "illegal borrow unless pure" for + // files.is_empty() + if unsafe { self.fi.files.is_empty() } { + self.fi.current_reader = None; + return false; } - let path_option = self.files.shift(), + let path_option = self.fi.files.shift(), file = match path_option { None => io::stdin(), Some(ref path) => io::file_reader(path).get() }; - self.current_reader = Some(file); - self.state.current_path = path_option; - self.state.line_num_file = 0; + self.fi.current_reader = Some(file); + self.fi.state.current_path = path_option; + self.fi.state.line_num_file = 0; + true } /** Attempt to open the next file if there is none currently open, or if the current one is EOF'd. + + Returns `true` if it had to move to the next file and did + so successfully. */ - priv fn next_file_if_eof(&mut self) { - match self.current_reader { + priv fn next_file_if_eof(&self) -> bool { + match self.fi.current_reader { None => self.next_file(), Some(r) => { if r.eof() { self.next_file() + } else { + false } } } } /** - Read a single line. Returns `None` if there are no remaining lines - in any remaining file. (Automatically opens files as required, see - `next_file` for details.) + Apply `f` to each line successively, along with some state + (line numbers and file names, see documentation for + `FileInputState`). Otherwise identical to `lines_each`. + */ + pub fn each_line_state(&self, + f: &fn(&str, FileInputState) -> bool) { + self.each_line(|line| f(line, copy self.fi.state)); + } - (Name to avoid conflicting with `core::io::ReaderUtil::read_line`.) + + /** + Retrieve the current `FileInputState` information. */ - pub fn next_line(&mut self) -> Option<~str> { + pub fn state(&self) -> FileInputState { + copy self.fi.state + } +} + +impl io::Reader for FileInput { + fn read_byte(&self) -> int { loop { - // iterate until there is a file that can be read from - self.next_file_if_eof(); - match self.current_reader { - None => { - // no file has any content - return None; - }, + let stepped = self.next_file_if_eof(); + + // if we moved to the next file, and the previous + // character wasn't \n, then there is an unfinished line + // from the previous file. This library models + // line-by-line processing and the trailing line of the + // previous file and the leading of the current file + // should be considered different, so we need to insert a + // fake line separator + if stepped && !self.fi.previous_was_newline { + self.fi.state.line_num += 1; + self.fi.state.line_num_file += 1; + self.fi.previous_was_newline = true; + return '\n' as int; + } + + match self.fi.current_reader { + None => return -1, Some(r) => { - let l = r.read_line(); + let b = r.read_byte(); - // at the end of this file, and we read nothing, so - // go to the next file - if r.eof() && l.is_empty() { + if b < 0 { loop; } - self.state.line_num += 1; - self.state.line_num_file += 1; - return Some(l); + + if b == '\n' as int { + self.fi.state.line_num += 1; + self.fi.state.line_num_file += 1; + self.fi.previous_was_newline = true; + } else { + self.fi.previous_was_newline = false; + } + + return b; } } } } + fn read(&self, buf: &mut [u8], len: uint) -> uint { + let mut count = 0; + while count < len { + let b = self.read_byte(); + if b < 0 { break } + + buf[count] = b as u8; + count += 1; + } - /** - Call `f` on the lines in the files in succession, stopping if - it ever returns `false`. + count + } + fn eof(&self) -> bool { + // we've run out of files, and current_reader is either None or eof. - State is preserved across calls. + // compiler whines about illegal borrows for files.is_empty() + (unsafe { self.fi.files.is_empty() }) && + match self.fi.current_reader { None => true, Some(r) => r.eof() } - (The name is to avoid conflict with - `core::io::ReaderUtil::each_line`.) - */ - pub fn lines_each(&mut self, f: &fn(~str) -> bool) { - loop { - match self.next_line() { - None => break, - Some(line) => { - if !f(line) { - break; - } - } - } + } + fn seek(&self, offset: int, whence: io::SeekStyle) { + match self.fi.current_reader { + None => {}, + Some(r) => r.seek(offset, whence) } } - - /** - Apply `f` to each line successively, along with some state - (line numbers and file names, see documentation for - `FileInputState`). Otherwise identical to `lines_each`. - */ - pub fn lines_each_state(&mut self, - f: &fn(~str, &FileInputState) -> bool) { - loop { - match self.next_line() { - None => break, - Some(line) => { - if !f(line, &self.state) { - break; - } - } - } + fn tell(&self) -> uint { + match self.fi.current_reader { + None => 0, + Some(r) => r.tell() } } } @@ -291,7 +349,7 @@ impl FileInput { /** Convert a list of strings to an appropriate form for a `FileInput` instance. `stdin_hyphen` controls whether `-` represents `stdin` or -not. +a literal `-`. */ // XXX: stupid, unclear name pub fn pathify(vec: &[~str], stdin_hyphen : bool) -> ~[Option] { @@ -310,9 +368,9 @@ reading from `stdin`). Fails when attempting to read from a file that can't be opened. */ -pub fn input(f: &fn(~str) -> bool) { +pub fn input(f: &fn(&str) -> bool) { let mut i = FileInput::from_args(); - i.lines_each(f); + i.each_line(f); } /** @@ -322,31 +380,31 @@ provided at each call. Fails when attempting to read from a file that can't be opened. */ -pub fn input_state(f: &fn(~str, &FileInputState) -> bool) { +pub fn input_state(f: &fn(&str, FileInputState) -> bool) { let mut i = FileInput::from_args(); - i.lines_each_state(f); + i.each_line_state(f); } /** -Iterate over a vec of files (an empty vec implies just `stdin`). +Iterate over a vector of files (an empty vector implies just `stdin`). Fails when attempting to read from a file that can't be opened. */ -pub fn input_vec(files: ~[Option], f: &fn(~str) -> bool) { +pub fn input_vec(files: ~[Option], f: &fn(&str) -> bool) { let mut i = FileInput::from_vec(files); - i.lines_each(f); + i.each_line(f); } /** -Iterate over a vec of files (an empty vec implies just `stdin`) with -the current state of the iteration provided at each call. +Iterate over a vector of files (an empty vector implies just `stdin`) +with the current state of the iteration provided at each call. Fails when attempting to read from a file that can't be opened. */ pub fn input_vec_state(files: ~[Option], - f: &fn(~str, &FileInputState) -> bool) { + f: &fn(&str, FileInputState) -> bool) { let mut i = FileInput::from_vec(files); - i.lines_each_state(f); + i.each_line_state(f); } #[cfg(test)] @@ -371,11 +429,61 @@ mod test { paths = ~[Some(Path("some/path")), Some(Path("some/other/path"))]; - fail_unless!(pathify(strs, true) == paths); - fail_unless!(pathify(strs, false) == paths); + assert_eq!(pathify(strs, true), copy paths); + assert_eq!(pathify(strs, false), paths); - fail_unless!(pathify([~"-"], true) == ~[None]); - fail_unless!(pathify([~"-"], false) == ~[Some(Path("-"))]); + assert_eq!(pathify([~"-"], true), ~[None]); + assert_eq!(pathify([~"-"], false), ~[Some(Path("-"))]); + } + + #[test] + fn test_fileinput_read_byte() { + let filenames = pathify(vec::from_fn( + 3, + |i| fmt!("tmp/lib-fileinput-test-fileinput-read-byte-%u.tmp", i)), true); + + // 3 files containing 0\n, 1\n, and 2\n respectively + for filenames.eachi |i, &filename| { + make_file(filename.get_ref(), ~[fmt!("%u", i)]); + } + + let fi = FileInput::from_vec(copy filenames); + + for "012".each_chari |line, c| { + assert_eq!(fi.read_byte(), c as int); + assert_eq!(fi.state().line_num, line); + assert_eq!(fi.state().line_num_file, 0); + assert_eq!(fi.read_byte(), '\n' as int); + assert_eq!(fi.state().line_num, line + 1); + assert_eq!(fi.state().line_num_file, 1); + + assert_eq!(copy fi.state().current_path, copy filenames[line]); + } + + assert_eq!(fi.read_byte(), -1); + fail_unless!(fi.eof()); + assert_eq!(fi.state().line_num, 3) + + } + + #[test] + fn test_fileinput_read() { + let filenames = pathify(vec::from_fn( + 3, + |i| fmt!("tmp/lib-fileinput-test-fileinput-read-%u.tmp", i)), true); + + // 3 files containing 1\n, 2\n, and 3\n respectively + for filenames.eachi |i, &filename| { + make_file(filename.get_ref(), ~[fmt!("%u", i)]); + } + + let fi = FileInput::from_vec(filenames); + let mut buf : ~[u8] = vec::from_elem(6, 0u8); + let count = fi.read(buf, 10); + assert_eq!(count, 6); + assert_eq!(buf, "0\n1\n2\n".to_bytes()); + fail_unless!(fi.eof()) + assert_eq!(fi.state().line_num, 3); } #[test] @@ -388,47 +496,84 @@ mod test { for filenames.eachi |i, &filename| { let contents = vec::from_fn(3, |j| fmt!("%u %u", i, j)); - make_file(&filename.get(), contents); + make_file(filename.get_ref(), contents); all_lines.push_all(contents); } let mut read_lines = ~[]; for input_vec(filenames) |line| { - read_lines.push(line); + read_lines.push(line.to_owned()); } - fail_unless!(read_lines == all_lines); + assert_eq!(read_lines, all_lines); } #[test] fn test_input_vec_state() { let filenames = pathify(vec::from_fn( 3, - |i| - fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true); + |i| fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true); for filenames.eachi |i, &filename| { let contents = vec::from_fn(3, |j| fmt!("%u %u", i, j + 1)); - make_file(&filename.get(), contents); + make_file(filename.get_ref(), contents); } for input_vec_state(filenames) |line, state| { let nums = str::split_char(line, ' '); - let file_num = uint::from_str(nums[0]).get(); let line_num = uint::from_str(nums[1]).get(); + assert_eq!(line_num, state.line_num_file); + assert_eq!(file_num * 3 + line_num, state.line_num); + } + } + + #[test] + fn test_empty_files() { + let filenames = pathify(vec::from_fn( + 3, + |i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); + + make_file(filenames[0].get_ref(), ~[~"1", ~"2"]); + make_file(filenames[1].get_ref(), ~[]); + make_file(filenames[2].get_ref(), ~[~"3", ~"4"]); + + let mut count = 0; + for input_vec_state(copy filenames) |line, state| { + let expected_path = match line { + "1" | "2" => copy filenames[0], + "3" | "4" => copy filenames[2], + _ => fail!(~"unexpected line") + }; + assert_eq!(copy state.current_path, expected_path); + count += 1; + } + assert_eq!(count, 4); + } - fail_unless!(line_num == state.line_num_file); - fail_unless!(file_num * 3 + line_num == state.line_num); + #[test] + fn test_no_trailing_newline() { + let f1 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp")), + f2 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp")); + + let wr = io::file_writer(f1.get_ref(), [io::Create, io::Truncate]).get(); + wr.write_str("1\n2"); + let wr = io::file_writer(f2.get_ref(), [io::Create, io::Truncate]).get(); + wr.write_str("3\n4"); + + let mut lines = ~[]; + for input_vec(~[f1, f2]) |line| { + lines.push(line.to_owned()); } + assert_eq!(lines, ~[~"1", ~"2", ~"3", ~"4"]); } + #[test] fn test_next_file() { let filenames = pathify(vec::from_fn( 3, - |i| - fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); + |i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); for filenames.eachi |i, &filename| { let contents = @@ -439,19 +584,19 @@ mod test { let mut in = FileInput::from_vec(filenames); // read once from 0 - fail_unless!(in.next_line() == Some(~"0 1")); + assert_eq!(in.read_line(), ~"0 1"); in.next_file(); // skip the rest of 1 // read all lines from 1 (but don't read any from 2), for uint::range(1, 4) |i| { - fail_unless!(in.next_line() == Some(fmt!("1 %u", i))); + assert_eq!(in.read_line(), fmt!("1 %u", i)); } // 1 is finished, but 2 hasn't been started yet, so this will // just "skip" to the beginning of 2 (Python's fileinput does // the same) in.next_file(); - fail_unless!(in.next_line() == Some(~"2 1")); + assert_eq!(in.read_line(), ~"2 1"); } #[test] From fea1380a9a0ca94738132db4d51ec4bd86bac3dd Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 3 Apr 2013 12:38:14 +1100 Subject: [PATCH 013/403] libstd: make fileinput tests pass. --- src/libstd/fileinput.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs index 0056b34eccbca..df733425f3ef0 100644 --- a/src/libstd/fileinput.rs +++ b/src/libstd/fileinput.rs @@ -461,7 +461,7 @@ mod test { } assert_eq!(fi.read_byte(), -1); - fail_unless!(fi.eof()); + assert!(fi.eof()); assert_eq!(fi.state().line_num, 3) } @@ -482,7 +482,7 @@ mod test { let count = fi.read(buf, 10); assert_eq!(count, 6); assert_eq!(buf, "0\n1\n2\n".to_bytes()); - fail_unless!(fi.eof()) + assert!(fi.eof()) assert_eq!(fi.state().line_num, 3); } @@ -520,7 +520,9 @@ mod test { } for input_vec_state(filenames) |line, state| { - let nums = str::split_char(line, ' '); + let nums = do vec::build |p| { + for str::each_split_char(line, ' ') |s| { p(s.to_owned()); } + }; let file_num = uint::from_str(nums[0]).get(); let line_num = uint::from_str(nums[1]).get(); assert_eq!(line_num, state.line_num_file); From e2bffb79717f7622e97870c3194435b06e3e56bc Mon Sep 17 00:00:00 2001 From: James Miller Date: Wed, 3 Apr 2013 19:40:27 +1300 Subject: [PATCH 014/403] Implement Clone for tuples --- src/libcore/tuple.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index a5c86d592c636..35b8496f6c57e 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -10,6 +10,7 @@ //! Operations on tuples +use clone::Clone; use kinds::Copy; use vec; @@ -46,6 +47,15 @@ impl CopyableTuple for (T, U) { } +impl Clone for (T, U) { + fn clone(&self) -> (T, U) { + let (a, b) = match *self { + (ref a, ref b) => (a, b) + }; + (a.clone(), b.clone()) + } +} + pub trait ImmutableTuple { fn first_ref(&self) -> &'self T; fn second_ref(&self) -> &'self U; @@ -252,3 +262,10 @@ fn test_tuple() { assert!(('a', 2).swap() == (2, 'a')); } +#[test] +fn test_clone() { + let a = (1, ~"2"); + let b = a.clone(); + assert!(a.first() == b.first()); + assert!(a.second() == b.second()); +} From 84e503346672dfc5d237e90e49ed42a2ae3641b4 Mon Sep 17 00:00:00 2001 From: Ben Striegel Date: Wed, 3 Apr 2013 06:54:14 -0400 Subject: [PATCH 015/403] Make bench/noise.rs more idiomatic and 20x faster --- src/test/bench/noise.rs | 61 +++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index d28382abaa386..4397dcd5247f5 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -1,25 +1,28 @@ // Perlin noise benchmark from https://gist.github.com/1170424 -use core::rand::RngUtil; +use core::rand::{Rng, RngUtil}; struct Vec2 { x: f32, y: f32, } -fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } -fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } +#[inline(always)] +fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } -fn random_gradient(r: @rand::Rng) -> Vec2 { +#[inline(always)] +fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } + +fn random_gradient(r: @Rng) -> Vec2 { let v = r.gen_float() * float::consts::pi * 2.0; - Vec2{ + Vec2 { x: float::cos(v) as f32, y: float::sin(v) as f32, } } fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 { - let sp = Vec2{x: p.x - orig.x, y: p.y - orig.y}; + let sp = Vec2 {x: p.x - orig.x, y: p.y - orig.y}; grad.x * sp.x + grad.y + sp.y } @@ -28,28 +31,28 @@ struct Noise2DContext { permutations: [int, ..256], } -fn Noise2DContext() -> ~Noise2DContext { - let r = rand::Rng(); - let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; - for int::range(0, 256) |i| { rgradients[i] = random_gradient(r); } - let mut permutations = [ 0, ..256 ]; - for int::range(0, 256) |i| { permutations[i] = i; } - r.shuffle_mut(permutations); - - ~Noise2DContext{ - rgradients: rgradients, - permutations: permutations, +pub impl Noise2DContext { + fn new() -> Noise2DContext { + let r = rand::Rng(); + let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; + for int::range(0, 256) |i| { rgradients[i] = random_gradient(r); } + let mut permutations = [ 0, ..256 ]; + for int::range(0, 256) |i| { permutations[i] = i; } + r.shuffle_mut(permutations); + + Noise2DContext { + rgradients: rgradients, + permutations: permutations, + } } -} -pub impl Noise2DContext { #[inline(always)] fn get_gradient(&self, x: int, y: int) -> Vec2 { let idx = self.permutations[x & 255] + self.permutations[y & 255]; self.rgradients[idx & 255] } - #[inline(always)] + #[inline] fn get_gradients(&self, gradients: &mut [Vec2, ..4], origins: &mut [Vec2, ..4], x: f32, y: f32) { let x0f = f32::floor(x); let y0f = f32::floor(y); @@ -63,14 +66,15 @@ pub impl Noise2DContext { gradients[2] = self.get_gradient(x0, y1); gradients[3] = self.get_gradient(x1, y1); - origins[0] = Vec2{x: x0f + 0.0, y: y0f + 0.0}; - origins[1] = Vec2{x: x0f + 1.0, y: y0f + 0.0}; - origins[2] = Vec2{x: x0f + 0.0, y: y0f + 1.0}; - origins[3] = Vec2{x: x0f + 1.0, y: y0f + 1.0}; + origins[0] = Vec2 {x: x0f + 0.0, y: y0f + 0.0}; + origins[1] = Vec2 {x: x0f + 1.0, y: y0f + 0.0}; + origins[2] = Vec2 {x: x0f + 0.0, y: y0f + 1.0}; + origins[3] = Vec2 {x: x0f + 1.0, y: y0f + 1.0}; } + #[inline] fn get(&self, x: f32, y: f32) -> f32 { - let p = Vec2{x: x, y: y}; + let p = Vec2 {x: x, y: y}; let mut gradients = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; let mut origins = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; self.get_gradients(&mut gradients, &mut origins, x, y); @@ -88,9 +92,9 @@ pub impl Noise2DContext { fn main() { let symbols = [" ", "░", "▒", "▓", "█", "█"]; - let mut pixels = vec::from_elem(256*256, 0f32); - let n2d = Noise2DContext(); - for int::range(0, 100) |_| { + let mut pixels = [0f32, ..256*256]; + let n2d = ~Noise2DContext::new(); + for 100.times { for int::range(0, 256) |y| { for int::range(0, 256) |x| { let v = n2d.get( @@ -109,4 +113,3 @@ fn main() { io::println(""); }*/ } - From 44029a5bbc4812f7144ee8d0d4ee95d52aeca6cf Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 3 Apr 2013 08:45:14 -0400 Subject: [PATCH 016/403] hashmap: rm linear namespace --- doc/rust.md | 2 +- doc/tutorial.md | 2 +- src/libcore/gc.rs | 2 +- src/libcore/hashmap.rs | 1700 ++++++++--------- src/libcore/task/spawn.rs | 2 +- src/libcore/unstable/global.rs | 2 +- src/libcore/unstable/weak_task.rs | 2 +- src/librustc/back/rpath.rs | 2 +- src/librustc/lib/llvm.rs | 2 +- src/librustc/metadata/creader.rs | 2 +- src/librustc/metadata/cstore.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/borrowck/check_loans.rs | 2 +- src/librustc/middle/borrowck/gather_loans.rs | 2 +- src/librustc/middle/borrowck/mod.rs | 2 +- src/librustc/middle/const_eval.rs | 2 +- src/librustc/middle/freevars.rs | 2 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/middle/lint.rs | 2 +- src/librustc/middle/liveness.rs | 2 +- src/librustc/middle/moves.rs | 2 +- src/librustc/middle/pat_util.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/middle/resolve.rs | 2 +- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/build.rs | 2 +- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/reachable.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/_match.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/check/vtable.rs | 2 +- src/librustc/middle/typeck/coherence.rs | 2 +- .../middle/typeck/infer/region_inference.rs | 2 +- src/librustc/middle/typeck/mod.rs | 2 +- src/librustc/util/common.rs | 2 +- src/librustpkg/rustpkg.rc | 2 +- src/librustpkg/util.rs | 2 +- src/libstd/json.rs | 4 +- src/libstd/net_url.rs | 4 +- src/libstd/serialize.rs | 2 +- src/libstd/workcache.rs | 2 +- src/libsyntax/ast_map.rs | 2 +- src/libsyntax/attr.rs | 2 +- src/libsyntax/ext/base.rs | 4 +- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/ext/tt/transcribe.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/parse/token.rs | 2 +- src/libsyntax/util/interner.rs | 2 +- src/test/auxiliary/issue-2631-a.rs | 2 +- src/test/bench/core-map.rs | 2 +- src/test/bench/core-set.rs | 2 +- src/test/bench/graph500-bfs.rs | 2 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/bench/shootout-mandelbrot.rs | 2 +- .../borrowck-borrowed-uniq-rvalue.rs | 2 +- .../borrowck-insert-during-each.rs | 2 +- src/test/compile-fail/for-loop-decl.rs | 2 +- src/test/compile-fail/map-types.rs | 2 +- src/test/run-fail/unwind-misc-1.rs | 2 +- src/test/run-pass/hashmap-memory.rs | 2 +- src/test/run-pass/issue-1696.rs | 2 +- src/test/run-pass/issue-2631-b.rs | 2 +- src/test/run-pass/issue-2804-2.rs | 2 +- src/test/run-pass/issue-2804.rs | 2 +- src/test/run-pass/issue-3026.rs | 2 +- src/test/run-pass/issue-3559.rs | 2 +- src/test/run-pass/issue-4016.rs | 2 +- src/test/run-pass/issue-4092.rs | 2 +- 75 files changed, 925 insertions(+), 929 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index c6dba96267679..64f0dc93e7867 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -441,7 +441,7 @@ expression context, the final namespace qualifier is omitted. Two examples of paths with type arguments: ~~~~ -# use core::hashmap::linear::LinearMap; +# use core::hashmap::LinearMap; # fn f() { # fn id(t: T) -> T { t } type t = LinearMap; // Type arguments used in a type expression diff --git a/doc/tutorial.md b/doc/tutorial.md index 42b0d5a585aee..8c5294767c26a 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1888,7 +1888,7 @@ illegal to copy and pass by value. Generic `type`, `struct`, and `enum` declarations follow the same pattern: ~~~~ -# use core::hashmap::linear::LinearMap; +# use core::hashmap::LinearMap; type Set = LinearMap; struct Stack { diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 2f35c1e0bb15e..46f2ad76d0792 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -43,7 +43,7 @@ use io; use libc::{size_t, uintptr_t}; use option::{None, Option, Some}; use ptr; -use hashmap::linear::LinearSet; +use hashmap::LinearSet; use stackwalk; use sys; diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 9387ec4f43209..67942abba4633 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -13,1013 +13,1009 @@ //! The tables use a keyed hash with new random keys generated for each container, so the ordering //! of a set of keys in a hash table is randomized. -/// Open addressing with linear probing. -pub mod linear { - use container::{Container, Mutable, Map, Set}; - use cmp::{Eq, Equiv}; - use hash::Hash; - use to_bytes::IterBytes; - use iter::BaseIter; - use hash::Hash; - use iter; - use option::{None, Option, Some}; - use rand::RngUtil; - use rand; - use uint; - use vec; - use util::unreachable; +use container::{Container, Mutable, Map, Set}; +use cmp::{Eq, Equiv}; +use hash::Hash; +use to_bytes::IterBytes; +use iter::BaseIter; +use hash::Hash; +use iter; +use option::{None, Option, Some}; +use rand::RngUtil; +use rand; +use uint; +use vec; +use util::unreachable; + +static INITIAL_CAPACITY: uint = 32u; // 2^5 + +struct Bucket { + hash: uint, + key: K, + value: V, +} - static INITIAL_CAPACITY: uint = 32u; // 2^5 +pub struct LinearMap { + priv k0: u64, + priv k1: u64, + priv resize_at: uint, + priv size: uint, + priv buckets: ~[Option>], +} - struct Bucket { - hash: uint, - key: K, - value: V, - } +// We could rewrite FoundEntry to have type Option<&Bucket> +// which would be nifty +enum SearchResult { + FoundEntry(uint), FoundHole(uint), TableFull +} - pub struct LinearMap { - priv k0: u64, - priv k1: u64, - priv resize_at: uint, - priv size: uint, - priv buckets: ~[Option>], - } +#[inline(always)] +fn resize_at(capacity: uint) -> uint { + ((capacity as float) * 3. / 4.) as uint +} - // We could rewrite FoundEntry to have type Option<&Bucket> - // which would be nifty - enum SearchResult { - FoundEntry(uint), FoundHole(uint), TableFull +pub fn linear_map_with_capacity( + initial_capacity: uint) -> LinearMap { + let r = rand::task_rng(); + linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(), + initial_capacity) +} + +fn linear_map_with_capacity_and_keys( + k0: u64, k1: u64, + initial_capacity: uint) -> LinearMap { + LinearMap { + k0: k0, k1: k1, + resize_at: resize_at(initial_capacity), + size: 0, + buckets: vec::from_fn(initial_capacity, |_| None) } +} +priv impl LinearMap { #[inline(always)] - fn resize_at(capacity: uint) -> uint { - ((capacity as float) * 3. / 4.) as uint + fn to_bucket(&self, h: uint) -> uint { + // A good hash function with entropy spread over all of the + // bits is assumed. SipHash is more than good enough. + h % self.buckets.len() } - pub fn linear_map_with_capacity( - initial_capacity: uint) -> LinearMap { - let r = rand::task_rng(); - linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(), - initial_capacity) + #[inline(always)] + fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint { + let n = (idx + 1) % len_buckets; + debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n); + n } - fn linear_map_with_capacity_and_keys( - k0: u64, k1: u64, - initial_capacity: uint) -> LinearMap { - LinearMap { - k0: k0, k1: k1, - resize_at: resize_at(initial_capacity), - size: 0, - buckets: vec::from_fn(initial_capacity, |_| None) + #[inline(always)] + fn bucket_sequence(&self, hash: uint, + op: &fn(uint) -> bool) -> uint { + let start_idx = self.to_bucket(hash); + let len_buckets = self.buckets.len(); + let mut idx = start_idx; + loop { + if !op(idx) { + return idx; + } + idx = self.next_bucket(idx, len_buckets); + if idx == start_idx { + return start_idx; + } } } - priv impl LinearMap { - #[inline(always)] - fn to_bucket(&self, h: uint) -> uint { - // A good hash function with entropy spread over all of the - // bits is assumed. SipHash is more than good enough. - h % self.buckets.len() - } + #[inline(always)] + fn bucket_for_key(&self, k: &K) -> SearchResult { + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.bucket_for_key_with_hash(hash, k) + } - #[inline(always)] - fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint { - let n = (idx + 1) % len_buckets; - debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n); - n - } + #[inline(always)] + fn bucket_for_key_equiv>(&self, + k: &Q) + -> SearchResult { + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.bucket_for_key_with_hash_equiv(hash, k) + } - #[inline(always)] - fn bucket_sequence(&self, hash: uint, - op: &fn(uint) -> bool) -> uint { - let start_idx = self.to_bucket(hash); - let len_buckets = self.buckets.len(); - let mut idx = start_idx; - loop { - if !op(idx) { - return idx; - } - idx = self.next_bucket(idx, len_buckets); - if idx == start_idx { - return start_idx; - } + #[inline(always)] + fn bucket_for_key_with_hash(&self, + hash: uint, + k: &K) + -> SearchResult { + let _ = for self.bucket_sequence(hash) |i| { + match self.buckets[i] { + Some(ref bkt) => if bkt.hash == hash && *k == bkt.key { + return FoundEntry(i); + }, + None => return FoundHole(i) } - } - - #[inline(always)] - fn bucket_for_key(&self, k: &K) -> SearchResult { - let hash = k.hash_keyed(self.k0, self.k1) as uint; - self.bucket_for_key_with_hash(hash, k) - } - - #[inline(always)] - fn bucket_for_key_equiv>(&self, - k: &Q) - -> SearchResult { - let hash = k.hash_keyed(self.k0, self.k1) as uint; - self.bucket_for_key_with_hash_equiv(hash, k) - } + }; + TableFull + } - #[inline(always)] - fn bucket_for_key_with_hash(&self, - hash: uint, - k: &K) - -> SearchResult { - let _ = for self.bucket_sequence(hash) |i| { - match self.buckets[i] { - Some(ref bkt) => if bkt.hash == hash && *k == bkt.key { + #[inline(always)] + fn bucket_for_key_with_hash_equiv>(&self, + hash: uint, + k: &Q) + -> SearchResult { + let _ = for self.bucket_sequence(hash) |i| { + match self.buckets[i] { + Some(ref bkt) => { + if bkt.hash == hash && k.equiv(&bkt.key) { return FoundEntry(i); - }, - None => return FoundHole(i) - } - }; - TableFull - } - - #[inline(always)] - fn bucket_for_key_with_hash_equiv>(&self, - hash: uint, - k: &Q) - -> SearchResult { - let _ = for self.bucket_sequence(hash) |i| { - match self.buckets[i] { - Some(ref bkt) => { - if bkt.hash == hash && k.equiv(&bkt.key) { - return FoundEntry(i); - } - }, - None => return FoundHole(i) - } - }; - TableFull - } + } + }, + None => return FoundHole(i) + } + }; + TableFull + } - /// Expand the capacity of the array to the next power of two - /// and re-insert each of the existing buckets. - #[inline(always)] - fn expand(&mut self) { - let new_capacity = self.buckets.len() * 2; - self.resize(new_capacity); - } + /// Expand the capacity of the array to the next power of two + /// and re-insert each of the existing buckets. + #[inline(always)] + fn expand(&mut self) { + let new_capacity = self.buckets.len() * 2; + self.resize(new_capacity); + } - /// Expands the capacity of the array and re-insert each of the - /// existing buckets. - fn resize(&mut self, new_capacity: uint) { - let old_capacity = self.buckets.len(); - self.resize_at = resize_at(new_capacity); + /// Expands the capacity of the array and re-insert each of the + /// existing buckets. + fn resize(&mut self, new_capacity: uint) { + let old_capacity = self.buckets.len(); + self.resize_at = resize_at(new_capacity); - let mut old_buckets = vec::from_fn(new_capacity, |_| None); - self.buckets <-> old_buckets; + let mut old_buckets = vec::from_fn(new_capacity, |_| None); + self.buckets <-> old_buckets; - self.size = 0; - for uint::range(0, old_capacity) |i| { - let mut bucket = None; - bucket <-> old_buckets[i]; - self.insert_opt_bucket(bucket); - } + self.size = 0; + for uint::range(0, old_capacity) |i| { + let mut bucket = None; + bucket <-> old_buckets[i]; + self.insert_opt_bucket(bucket); } + } - fn insert_opt_bucket(&mut self, bucket: Option>) { - match bucket { - Some(Bucket{hash: hash, key: key, value: value}) => { - self.insert_internal(hash, key, value); - } - None => {} + fn insert_opt_bucket(&mut self, bucket: Option>) { + match bucket { + Some(Bucket{hash: hash, key: key, value: value}) => { + self.insert_internal(hash, key, value); } + None => {} } + } - #[inline(always)] - fn value_for_bucket(&self, idx: uint) -> &'self V { - match self.buckets[idx] { - Some(ref bkt) => &bkt.value, - None => fail!(~"LinearMap::find: internal logic error"), - } + #[inline(always)] + fn value_for_bucket(&self, idx: uint) -> &'self V { + match self.buckets[idx] { + Some(ref bkt) => &bkt.value, + None => fail!(~"LinearMap::find: internal logic error"), } + } - #[inline(always)] - fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V { - match self.buckets[idx] { - Some(ref mut bkt) => &mut bkt.value, - None => unreachable() - } + #[inline(always)] + fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V { + match self.buckets[idx] { + Some(ref mut bkt) => &mut bkt.value, + None => unreachable() } + } - /// Inserts the key value pair into the buckets. - /// Assumes that there will be a bucket. - /// True if there was no previous entry with that key - fn insert_internal(&mut self, hash: uint, k: K, v: V) -> bool { - match self.bucket_for_key_with_hash(hash, &k) { - TableFull => { fail!(~"Internal logic error"); } - FoundHole(idx) => { - debug!("insert fresh (%?->%?) at idx %?, hash %?", - k, v, idx, hash); - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - true - } - FoundEntry(idx) => { - debug!("insert overwrite (%?->%?) at idx %?, hash %?", - k, v, idx, hash); - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - false - } + /// Inserts the key value pair into the buckets. + /// Assumes that there will be a bucket. + /// True if there was no previous entry with that key + fn insert_internal(&mut self, hash: uint, k: K, v: V) -> bool { + match self.bucket_for_key_with_hash(hash, &k) { + TableFull => { fail!(~"Internal logic error"); } + FoundHole(idx) => { + debug!("insert fresh (%?->%?) at idx %?, hash %?", + k, v, idx, hash); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + true + } + FoundEntry(idx) => { + debug!("insert overwrite (%?->%?) at idx %?, hash %?", + k, v, idx, hash); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + false } } + } - fn pop_internal(&mut self, hash: uint, k: &K) -> Option { - // Removing from an open-addressed hashtable - // is, well, painful. The problem is that - // the entry may lie on the probe path for other - // entries, so removing it would make you think that - // those probe paths are empty. - // - // To address this we basically have to keep walking, - // re-inserting entries we find until we reach an empty - // bucket. We know we will eventually reach one because - // we insert one ourselves at the beginning (the removed - // entry). - // - // I found this explanation elucidating: - // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf - let mut idx = match self.bucket_for_key_with_hash(hash, k) { - TableFull | FoundHole(_) => return None, - FoundEntry(idx) => idx - }; - - let len_buckets = self.buckets.len(); + fn pop_internal(&mut self, hash: uint, k: &K) -> Option { + // Removing from an open-addressed hashtable + // is, well, painful. The problem is that + // the entry may lie on the probe path for other + // entries, so removing it would make you think that + // those probe paths are empty. + // + // To address this we basically have to keep walking, + // re-inserting entries we find until we reach an empty + // bucket. We know we will eventually reach one because + // we insert one ourselves at the beginning (the removed + // entry). + // + // I found this explanation elucidating: + // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf + let mut idx = match self.bucket_for_key_with_hash(hash, k) { + TableFull | FoundHole(_) => return None, + FoundEntry(idx) => idx + }; + + let len_buckets = self.buckets.len(); + let mut bucket = None; + self.buckets[idx] <-> bucket; + + let value = match bucket { + None => None, + Some(bucket) => { + let Bucket{value: value, _} = bucket; + Some(value) + }, + }; + + /* re-inserting buckets may cause changes in size, so remember + what our new size is ahead of time before we start insertions */ + let size = self.size - 1; + idx = self.next_bucket(idx, len_buckets); + while self.buckets[idx].is_some() { let mut bucket = None; - self.buckets[idx] <-> bucket; - - let value = match bucket { - None => None, - Some(bucket) => { - let Bucket{value: value, _} = bucket; - Some(value) - }, - }; - - /* re-inserting buckets may cause changes in size, so remember - what our new size is ahead of time before we start insertions */ - let size = self.size - 1; + bucket <-> self.buckets[idx]; + self.insert_opt_bucket(bucket); idx = self.next_bucket(idx, len_buckets); - while self.buckets[idx].is_some() { - let mut bucket = None; - bucket <-> self.buckets[idx]; - self.insert_opt_bucket(bucket); - idx = self.next_bucket(idx, len_buckets); - } - self.size = size; - - value } + self.size = size; - fn search(&self, hash: uint, - op: &fn(x: &Option>) -> bool) { - let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i])); - } + value } - impl<'self,K:Hash + IterBytes + Eq,V> - BaseIter<(&'self K, &'self V)> for LinearMap { - /// Visit all key-value pairs - fn each(&self, blk: &fn(&(&'self K, &'self V)) -> bool) { - for uint::range(0, self.buckets.len()) |i| { - let mut broke = false; - do self.buckets[i].map |bucket| { - if !blk(&(&bucket.key, &bucket.value)) { - broke = true; // FIXME(#3064) just write "break;" - } - }; - if broke { break; } - } + fn search(&self, hash: uint, + op: &fn(x: &Option>) -> bool) { + let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i])); + } +} + +impl<'self,K:Hash + IterBytes + Eq,V> + BaseIter<(&'self K, &'self V)> for LinearMap { + /// Visit all key-value pairs + fn each(&self, blk: &fn(&(&'self K, &'self V)) -> bool) { + for uint::range(0, self.buckets.len()) |i| { + let mut broke = false; + do self.buckets[i].map |bucket| { + if !blk(&(&bucket.key, &bucket.value)) { + broke = true; // FIXME(#3064) just write "break;" + } + }; + if broke { break; } } - fn size_hint(&self) -> Option { Some(self.len()) } } + fn size_hint(&self) -> Option { Some(self.len()) } +} - impl Container for LinearMap { - /// Return the number of elements in the map - fn len(&const self) -> uint { self.size } +impl Container for LinearMap { + /// Return the number of elements in the map + fn len(&const self) -> uint { self.size } - /// Return true if the map contains no elements - fn is_empty(&const self) -> bool { self.len() == 0 } - } + /// Return true if the map contains no elements + fn is_empty(&const self) -> bool { self.len() == 0 } +} - impl Mutable for LinearMap { - /// Clear the map, removing all key-value pairs. - fn clear(&mut self) { - for uint::range(0, self.buckets.len()) |idx| { - self.buckets[idx] = None; - } - self.size = 0; +impl Mutable for LinearMap { + /// Clear the map, removing all key-value pairs. + fn clear(&mut self) { + for uint::range(0, self.buckets.len()) |idx| { + self.buckets[idx] = None; } + self.size = 0; } +} - impl<'self,K:Hash + IterBytes + Eq,V> Map for LinearMap { - /// Return true if the map contains a value for the specified key - fn contains_key(&self, k: &K) -> bool { - match self.bucket_for_key(k) { - FoundEntry(_) => {true} - TableFull | FoundHole(_) => {false} - } - } - - /// Visit all keys - fn each_key(&self, blk: &fn(k: &K) -> bool) { - self.each(|&(k, _)| blk(k)) +impl<'self,K:Hash + IterBytes + Eq,V> Map for LinearMap { + /// Return true if the map contains a value for the specified key + fn contains_key(&self, k: &K) -> bool { + match self.bucket_for_key(k) { + FoundEntry(_) => {true} + TableFull | FoundHole(_) => {false} } + } - /// Visit all values - fn each_value(&self, blk: &fn(v: &V) -> bool) { - self.each(|&(_, v)| blk(v)) - } + /// Visit all keys + fn each_key(&self, blk: &fn(k: &K) -> bool) { + self.each(|&(k, _)| blk(k)) + } - /// Iterate over the map and mutate the contained values - fn mutate_values(&mut self, blk: &fn(&'self K, - &'self mut V) -> bool) { - for uint::range(0, self.buckets.len()) |i| { - match self.buckets[i] { - Some(Bucket{key: ref key, value: ref mut value, _}) => { - if !blk(key, value) { return } - } - None => () - } - } - } + /// Visit all values + fn each_value(&self, blk: &fn(v: &V) -> bool) { + self.each(|&(_, v)| blk(v)) + } - /// Return a reference to the value corresponding to the key - fn find(&self, k: &K) -> Option<&'self V> { - match self.bucket_for_key(k) { - FoundEntry(idx) => Some(self.value_for_bucket(idx)), - TableFull | FoundHole(_) => None, + /// Iterate over the map and mutate the contained values + fn mutate_values(&mut self, blk: &fn(&'self K, + &'self mut V) -> bool) { + for uint::range(0, self.buckets.len()) |i| { + match self.buckets[i] { + Some(Bucket{key: ref key, value: ref mut value, _}) => { + if !blk(key, value) { return } + } + None => () } } + } - /// Return a mutable reference to the value corresponding to the key - fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { - let idx = match self.bucket_for_key(k) { - FoundEntry(idx) => idx, - TableFull | FoundHole(_) => return None - }; - unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker - Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) - } + /// Return a reference to the value corresponding to the key + fn find(&self, k: &K) -> Option<&'self V> { + match self.bucket_for_key(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, } + } - /// Insert a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Return true if the key did - /// not already exist in the map. - fn insert(&mut self, k: K, v: V) -> bool { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } - - let hash = k.hash_keyed(self.k0, self.k1) as uint; - self.insert_internal(hash, k, v) + /// Return a mutable reference to the value corresponding to the key + fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { + let idx = match self.bucket_for_key(k) { + FoundEntry(idx) => idx, + TableFull | FoundHole(_) => return None + }; + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) } + } - /// Remove a key-value pair from the map. Return true if the key - /// was present in the map, otherwise false. - fn remove(&mut self, k: &K) -> bool { - self.pop(k).is_some() - } + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, k: K, v: V) -> bool { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.insert_internal(hash, k, v) } - pub impl LinearMap { - /// Create an empty LinearMap - fn new() -> LinearMap { - LinearMap::with_capacity(INITIAL_CAPACITY) - } + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, k: &K) -> bool { + self.pop(k).is_some() + } +} - /// Create an empty LinearMap with space for at least `n` elements in - /// the hash table. - fn with_capacity(capacity: uint) -> LinearMap { - linear_map_with_capacity(capacity) - } +pub impl LinearMap { + /// Create an empty LinearMap + fn new() -> LinearMap { + LinearMap::with_capacity(INITIAL_CAPACITY) + } - /// Reserve space for at least `n` elements in the hash table. - fn reserve_at_least(&mut self, n: uint) { - if n > self.buckets.len() { - let buckets = n * 4 / 3 + 1; - self.resize(uint::next_power_of_two(buckets)); - } - } + /// Create an empty LinearMap with space for at least `n` elements in + /// the hash table. + fn with_capacity(capacity: uint) -> LinearMap { + linear_map_with_capacity(capacity) + } - fn pop(&mut self, k: &K) -> Option { - let hash = k.hash_keyed(self.k0, self.k1) as uint; - self.pop_internal(hash, k) + /// Reserve space for at least `n` elements in the hash table. + fn reserve_at_least(&mut self, n: uint) { + if n > self.buckets.len() { + let buckets = n * 4 / 3 + 1; + self.resize(uint::next_power_of_two(buckets)); } + } - fn swap(&mut self, k: K, v: V) -> Option { - // this could be faster. - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let old_value = self.pop_internal(hash, &k); - - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } + fn pop(&mut self, k: &K) -> Option { + let hash = k.hash_keyed(self.k0, self.k1) as uint; + self.pop_internal(hash, k) + } - self.insert_internal(hash, k, v); + fn swap(&mut self, k: K, v: V) -> Option { + // this could be faster. + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let old_value = self.pop_internal(hash, &k); - old_value + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); } - /// Return the value corresponding to the key in the map, or insert - /// and return the value if it doesn't exist. - fn find_or_insert(&mut self, k: K, v: V) -> &'self V { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } + self.insert_internal(hash, k, v); - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let idx = match self.bucket_for_key_with_hash(hash, &k) { - TableFull => fail!(~"Internal logic error"), - FoundEntry(idx) => idx, - FoundHole(idx) => { - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - idx - }, - }; + old_value + } - unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker - ::cast::transmute_region(self.value_for_bucket(idx)) - } + /// Return the value corresponding to the key in the map, or insert + /// and return the value if it doesn't exist. + fn find_or_insert(&mut self, k: K, v: V) -> &'self V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) } + } - /// Return the value corresponding to the key in the map, or create, - /// insert, and return a new value if it doesn't exist. - fn find_or_insert_with(&mut self, k: K, f: &fn(&K) -> V) -> &'self V { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } - - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let idx = match self.bucket_for_key_with_hash(hash, &k) { - TableFull => fail!(~"Internal logic error"), - FoundEntry(idx) => idx, - FoundHole(idx) => { - let v = f(&k); - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - idx - }, - }; - - unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker - ::cast::transmute_region(self.value_for_bucket(idx)) - } + /// Return the value corresponding to the key in the map, or create, + /// insert, and return a new value if it doesn't exist. + fn find_or_insert_with(&mut self, k: K, f: &fn(&K) -> V) -> &'self V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + let v = f(&k); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) } + } - fn consume(&mut self, f: &fn(K, V)) { - let mut buckets = ~[]; - self.buckets <-> buckets; - self.size = 0; - - do vec::consume(buckets) |_, bucket| { - match bucket { - None => {}, - Some(bucket) => { - let Bucket{key: key, value: value, _} = bucket; - f(key, value) - } + fn consume(&mut self, f: &fn(K, V)) { + let mut buckets = ~[]; + self.buckets <-> buckets; + self.size = 0; + + do vec::consume(buckets) |_, bucket| { + match bucket { + None => {}, + Some(bucket) => { + let Bucket{key: key, value: value, _} = bucket; + f(key, value) } } } + } - fn get(&self, k: &K) -> &'self V { - match self.find(k) { - Some(v) => v, - None => fail!(fmt!("No entry found for key: %?", k)), - } + fn get(&self, k: &K) -> &'self V { + match self.find(k) { + Some(v) => v, + None => fail!(fmt!("No entry found for key: %?", k)), } + } - /// Return true if the map contains a value for the specified key, - /// using equivalence - fn contains_key_equiv>(&self, key: &Q) - -> bool { - match self.bucket_for_key_equiv(key) { - FoundEntry(_) => {true} - TableFull | FoundHole(_) => {false} - } + /// Return true if the map contains a value for the specified key, + /// using equivalence + fn contains_key_equiv>(&self, key: &Q) + -> bool { + match self.bucket_for_key_equiv(key) { + FoundEntry(_) => {true} + TableFull | FoundHole(_) => {false} } + } - /// Return the value corresponding to the key in the map, using - /// equivalence - fn find_equiv>(&self, k: &Q) - -> Option<&'self V> { - match self.bucket_for_key_equiv(k) { - FoundEntry(idx) => Some(self.value_for_bucket(idx)), - TableFull | FoundHole(_) => None, - } + /// Return the value corresponding to the key in the map, using + /// equivalence + fn find_equiv>(&self, k: &Q) + -> Option<&'self V> { + match self.bucket_for_key_equiv(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, } } +} - impl Eq for LinearMap { - fn eq(&self, other: &LinearMap) -> bool { - if self.len() != other.len() { return false; } +impl Eq for LinearMap { + fn eq(&self, other: &LinearMap) -> bool { + if self.len() != other.len() { return false; } - for self.each |&(key, value)| { - match other.find(key) { - None => return false, - Some(v) => if value != v { return false }, - } + for self.each |&(key, value)| { + match other.find(key) { + None => return false, + Some(v) => if value != v { return false }, } - - true } - fn ne(&self, other: &LinearMap) -> bool { !self.eq(other) } + true } - pub struct LinearSet { - priv map: LinearMap - } + fn ne(&self, other: &LinearMap) -> bool { !self.eq(other) } +} - impl BaseIter for LinearSet { - /// Visit all values in order - fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } - fn size_hint(&self) -> Option { Some(self.len()) } - } +pub struct LinearSet { + priv map: LinearMap +} - impl Eq for LinearSet { - fn eq(&self, other: &LinearSet) -> bool { self.map == other.map } - fn ne(&self, other: &LinearSet) -> bool { self.map != other.map } - } +impl BaseIter for LinearSet { + /// Visit all values in order + fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } + fn size_hint(&self) -> Option { Some(self.len()) } +} - impl Container for LinearSet { - /// Return the number of elements in the set - fn len(&const self) -> uint { self.map.len() } +impl Eq for LinearSet { + fn eq(&self, other: &LinearSet) -> bool { self.map == other.map } + fn ne(&self, other: &LinearSet) -> bool { self.map != other.map } +} - /// Return true if the set contains no elements - fn is_empty(&const self) -> bool { self.map.is_empty() } - } +impl Container for LinearSet { + /// Return the number of elements in the set + fn len(&const self) -> uint { self.map.len() } - impl Mutable for LinearSet { - /// Clear the set, removing all values. - fn clear(&mut self) { self.map.clear() } - } + /// Return true if the set contains no elements + fn is_empty(&const self) -> bool { self.map.is_empty() } +} - impl Set for LinearSet { - /// Return true if the set contains a value - fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } +impl Mutable for LinearSet { + /// Clear the set, removing all values. + fn clear(&mut self) { self.map.clear() } +} - /// Add a value to the set. Return true if the value was not already - /// present in the set. - fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } +impl Set for LinearSet { + /// Return true if the set contains a value + fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } - /// Remove a value from the set. Return true if the value was - /// present in the set. - fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } + /// Add a value to the set. Return true if the value was not already + /// present in the set. + fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } - /// Return true if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - fn is_disjoint(&self, other: &LinearSet) -> bool { - iter::all(self, |v| !other.contains(v)) - } + /// Remove a value from the set. Return true if the value was + /// present in the set. + fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } - /// Return true if the set is a subset of another - fn is_subset(&self, other: &LinearSet) -> bool { - iter::all(self, |v| other.contains(v)) - } + /// Return true if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + fn is_disjoint(&self, other: &LinearSet) -> bool { + iter::all(self, |v| !other.contains(v)) + } - /// Return true if the set is a superset of another - fn is_superset(&self, other: &LinearSet) -> bool { - other.is_subset(self) - } + /// Return true if the set is a subset of another + fn is_subset(&self, other: &LinearSet) -> bool { + iter::all(self, |v| other.contains(v)) + } - /// Visit the values representing the difference - fn difference(&self, other: &LinearSet, f: &fn(&T) -> bool) { - for self.each |v| { - if !other.contains(v) { - if !f(v) { return } - } + /// Return true if the set is a superset of another + fn is_superset(&self, other: &LinearSet) -> bool { + other.is_subset(self) + } + + /// Visit the values representing the difference + fn difference(&self, other: &LinearSet, f: &fn(&T) -> bool) { + for self.each |v| { + if !other.contains(v) { + if !f(v) { return } } } + } - /// Visit the values representing the symmetric difference - fn symmetric_difference(&self, - other: &LinearSet, - f: &fn(&T) -> bool) { - self.difference(other, f); - other.difference(self, f); - } + /// Visit the values representing the symmetric difference + fn symmetric_difference(&self, + other: &LinearSet, + f: &fn(&T) -> bool) { + self.difference(other, f); + other.difference(self, f); + } - /// Visit the values representing the intersection - fn intersection(&self, other: &LinearSet, f: &fn(&T) -> bool) { - for self.each |v| { - if other.contains(v) { - if !f(v) { return } - } + /// Visit the values representing the intersection + fn intersection(&self, other: &LinearSet, f: &fn(&T) -> bool) { + for self.each |v| { + if other.contains(v) { + if !f(v) { return } } } + } - /// Visit the values representing the union - fn union(&self, other: &LinearSet, f: &fn(&T) -> bool) { - for self.each |v| { - if !f(v) { return } - } + /// Visit the values representing the union + fn union(&self, other: &LinearSet, f: &fn(&T) -> bool) { + for self.each |v| { + if !f(v) { return } + } - for other.each |v| { - if !self.contains(v) { - if !f(v) { return } - } + for other.each |v| { + if !self.contains(v) { + if !f(v) { return } } } } +} - pub impl LinearSet { - /// Create an empty LinearSet - fn new() -> LinearSet { - LinearSet::with_capacity(INITIAL_CAPACITY) - } +pub impl LinearSet { + /// Create an empty LinearSet + fn new() -> LinearSet { + LinearSet::with_capacity(INITIAL_CAPACITY) + } - /// Create an empty LinearSet with space for at least `n` elements in - /// the hash table. - fn with_capacity(capacity: uint) -> LinearSet { - LinearSet { map: LinearMap::with_capacity(capacity) } - } + /// Create an empty LinearSet with space for at least `n` elements in + /// the hash table. + fn with_capacity(capacity: uint) -> LinearSet { + LinearSet { map: LinearMap::with_capacity(capacity) } + } - /// Reserve space for at least `n` elements in the hash table. - fn reserve_at_least(&mut self, n: uint) { - self.map.reserve_at_least(n) - } + /// Reserve space for at least `n` elements in the hash table. + fn reserve_at_least(&mut self, n: uint) { + self.map.reserve_at_least(n) + } - /// Consumes all of the elements in the set, emptying it out - fn consume(&mut self, f: &fn(T)) { - self.map.consume(|k, _| f(k)) - } + /// Consumes all of the elements in the set, emptying it out + fn consume(&mut self, f: &fn(T)) { + self.map.consume(|k, _| f(k)) } +} + +#[test] +mod test_map { + use container::{Container, Map, Set}; + use option::{None, Some}; + use super::*; + use uint; #[test] - mod test_map { - use container::{Container, Map, Set}; - use option::{None, Some}; - use hashmap::linear::LinearMap; - use hashmap::linear; - use uint; - - #[test] - pub fn test_insert() { - let mut m = LinearMap::new(); - assert!(m.insert(1, 2)); - assert!(m.insert(2, 4)); - assert!(*m.get(&1) == 2); - assert!(*m.get(&2) == 4); - } + pub fn test_insert() { + let mut m = LinearMap::new(); + assert!(m.insert(1, 2)); + assert!(m.insert(2, 4)); + assert!(*m.get(&1) == 2); + assert!(*m.get(&2) == 4); + } - #[test] - fn test_find_mut() { - let mut m = LinearMap::new(); - assert!(m.insert(1, 12)); - assert!(m.insert(2, 8)); - assert!(m.insert(5, 14)); - let new = 100; - match m.find_mut(&5) { - None => fail!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } + #[test] + fn test_find_mut() { + let mut m = LinearMap::new(); + assert!(m.insert(1, 12)); + assert!(m.insert(2, 8)); + assert!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } - #[test] - pub fn test_insert_overwrite() { - let mut m = LinearMap::new(); - assert!(m.insert(1, 2)); - assert!(*m.get(&1) == 2); - assert!(!m.insert(1, 3)); - assert!(*m.get(&1) == 3); - } + #[test] + pub fn test_insert_overwrite() { + let mut m = LinearMap::new(); + assert!(m.insert(1, 2)); + assert!(*m.get(&1) == 2); + assert!(!m.insert(1, 3)); + assert!(*m.get(&1) == 3); + } - #[test] - pub fn test_insert_conflicts() { - let mut m = linear::linear_map_with_capacity(4); - assert!(m.insert(1, 2)); - assert!(m.insert(5, 3)); - assert!(m.insert(9, 4)); - assert!(*m.get(&9) == 4); - assert!(*m.get(&5) == 3); - assert!(*m.get(&1) == 2); - } + #[test] + pub fn test_insert_conflicts() { + let mut m = linear_map_with_capacity(4); + assert!(m.insert(1, 2)); + assert!(m.insert(5, 3)); + assert!(m.insert(9, 4)); + assert!(*m.get(&9) == 4); + assert!(*m.get(&5) == 3); + assert!(*m.get(&1) == 2); + } - #[test] - pub fn test_conflict_remove() { - let mut m = linear::linear_map_with_capacity(4); - assert!(m.insert(1, 2)); - assert!(m.insert(5, 3)); - assert!(m.insert(9, 4)); - assert!(m.remove(&1)); - assert!(*m.get(&9) == 4); - assert!(*m.get(&5) == 3); - } + #[test] + pub fn test_conflict_remove() { + let mut m = linear_map_with_capacity(4); + assert!(m.insert(1, 2)); + assert!(m.insert(5, 3)); + assert!(m.insert(9, 4)); + assert!(m.remove(&1)); + assert!(*m.get(&9) == 4); + assert!(*m.get(&5) == 3); + } - #[test] - pub fn test_is_empty() { - let mut m = linear::linear_map_with_capacity(4); - assert!(m.insert(1, 2)); - assert!(!m.is_empty()); - assert!(m.remove(&1)); - assert!(m.is_empty()); - } + #[test] + pub fn test_is_empty() { + let mut m = linear_map_with_capacity(4); + assert!(m.insert(1, 2)); + assert!(!m.is_empty()); + assert!(m.remove(&1)); + assert!(m.is_empty()); + } - #[test] - pub fn test_pop() { - let mut m = LinearMap::new(); - m.insert(1, 2); - assert!(m.pop(&1) == Some(2)); - assert!(m.pop(&1) == None); - } + #[test] + pub fn test_pop() { + let mut m = LinearMap::new(); + m.insert(1, 2); + assert!(m.pop(&1) == Some(2)); + assert!(m.pop(&1) == None); + } - #[test] - pub fn test_swap() { - let mut m = LinearMap::new(); - assert!(m.swap(1, 2) == None); - assert!(m.swap(1, 3) == Some(2)); - assert!(m.swap(1, 4) == Some(3)); - } + #[test] + pub fn test_swap() { + let mut m = LinearMap::new(); + assert!(m.swap(1, 2) == None); + assert!(m.swap(1, 3) == Some(2)); + assert!(m.swap(1, 4) == Some(3)); + } - #[test] - pub fn test_find_or_insert() { - let mut m = LinearMap::new::(); - assert!(m.find_or_insert(1, 2) == &2); - assert!(m.find_or_insert(1, 3) == &2); - } + #[test] + pub fn test_find_or_insert() { + let mut m = LinearMap::new::(); + assert!(m.find_or_insert(1, 2) == &2); + assert!(m.find_or_insert(1, 3) == &2); + } - #[test] - pub fn test_find_or_insert_with() { - let mut m = LinearMap::new::(); - assert!(m.find_or_insert_with(1, |_| 2) == &2); - assert!(m.find_or_insert_with(1, |_| 3) == &2); - } + #[test] + pub fn test_find_or_insert_with() { + let mut m = LinearMap::new::(); + assert!(m.find_or_insert_with(1, |_| 2) == &2); + assert!(m.find_or_insert_with(1, |_| 3) == &2); + } - #[test] - pub fn test_consume() { - let mut m = LinearMap::new(); - assert!(m.insert(1, 2)); - assert!(m.insert(2, 3)); - let mut m2 = LinearMap::new(); - do m.consume |k, v| { - m2.insert(k, v); - } - assert!(m.len() == 0); - assert!(m2.len() == 2); - assert!(m2.get(&1) == &2); - assert!(m2.get(&2) == &3); - } + #[test] + pub fn test_consume() { + let mut m = LinearMap::new(); + assert!(m.insert(1, 2)); + assert!(m.insert(2, 3)); + let mut m2 = LinearMap::new(); + do m.consume |k, v| { + m2.insert(k, v); + } + assert!(m.len() == 0); + assert!(m2.len() == 2); + assert!(m2.get(&1) == &2); + assert!(m2.get(&2) == &3); + } - #[test] - pub fn test_iterate() { - let mut m = linear::linear_map_with_capacity(4); - for uint::range(0, 32) |i| { - assert!(m.insert(i, i*2)); - } - let mut observed = 0; - for m.each |&(k, v)| { - assert!(*v == *k * 2); - observed |= (1 << *k); - } - assert!(observed == 0xFFFF_FFFF); + #[test] + pub fn test_iterate() { + let mut m = linear_map_with_capacity(4); + for uint::range(0, 32) |i| { + assert!(m.insert(i, i*2)); } - - #[test] - pub fn test_find() { - let mut m = LinearMap::new(); - assert!(m.find(&1).is_none()); - m.insert(1, 2); - match m.find(&1) { - None => fail!(), - Some(v) => assert!(*v == 2) - } + let mut observed = 0; + for m.each |&(k, v)| { + assert!(*v == *k * 2); + observed |= (1 << *k); } + assert!(observed == 0xFFFF_FFFF); + } - #[test] - pub fn test_eq() { - let mut m1 = LinearMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); + #[test] + pub fn test_find() { + let mut m = LinearMap::new(); + assert!(m.find(&1).is_none()); + m.insert(1, 2); + match m.find(&1) { + None => fail!(), + Some(v) => assert!(*v == 2) + } + } - let mut m2 = LinearMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); + #[test] + pub fn test_eq() { + let mut m1 = LinearMap::new(); + m1.insert(1, 2); + m1.insert(2, 3); + m1.insert(3, 4); - assert!(m1 != m2); + let mut m2 = LinearMap::new(); + m2.insert(1, 2); + m2.insert(2, 3); - m2.insert(3, 4); + assert!(m1 != m2); - assert!(m1 == m2); - } + m2.insert(3, 4); - #[test] - pub fn test_expand() { - let mut m = LinearMap::new(); + assert!(m1 == m2); + } - assert!(m.len() == 0); - assert!(m.is_empty()); + #[test] + pub fn test_expand() { + let mut m = LinearMap::new(); - let mut i = 0u; - let old_resize_at = m.resize_at; - while old_resize_at == m.resize_at { - m.insert(i, i); - i += 1; - } + assert!(m.len() == 0); + assert!(m.is_empty()); - assert!(m.len() == i); - assert!(!m.is_empty()); + let mut i = 0u; + let old_resize_at = m.resize_at; + while old_resize_at == m.resize_at { + m.insert(i, i); + i += 1; } + + assert!(m.len() == i); + assert!(!m.is_empty()); } +} #[test] - mod test_set { - use hashmap::linear; - use container::{Container, Map, Set}; - use vec; - - #[test] - fn test_disjoint() { - let mut xs = linear::LinearSet::new(); - let mut ys = linear::LinearSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } +mod test_set { + use super::*; + use container::{Container, Map, Set}; + use vec; - #[test] - fn test_subset_and_superset() { - let mut a = linear::LinearSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = linear::LinearSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } + #[test] + fn test_disjoint() { + let mut xs = LinearSet::new(); + let mut ys = LinearSet::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(5)); + assert!(ys.insert(11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(ys.insert(-11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert(7)); + assert!(!xs.is_disjoint(&ys)); + assert!(!ys.is_disjoint(&xs)); + } - #[test] - fn test_intersection() { - let mut a = linear::LinearSet::new(); - let mut b = linear::LinearSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let mut i = 0; - let expected = [3, 5, 11, 77]; - for a.intersection(&b) |x| { - assert!(vec::contains(expected, x)); - i += 1 - } - assert!(i == expected.len()); - } + #[test] + fn test_subset_and_superset() { + let mut a = LinearSet::new(); + assert!(a.insert(0)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); + + let mut b = LinearSet::new(); + assert!(b.insert(0)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(b.insert(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } - #[test] - fn test_difference() { - let mut a = linear::LinearSet::new(); - let mut b = linear::LinearSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let mut i = 0; - let expected = [1, 5, 11]; - for a.difference(&b) |x| { - assert!(vec::contains(expected, x)); - i += 1 - } - assert!(i == expected.len()); - } + #[test] + fn test_intersection() { + let mut a = LinearSet::new(); + let mut b = LinearSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + assert!(a.insert(-5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(-9)); + assert!(b.insert(-42)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let mut i = 0; + let expected = [3, 5, 11, 77]; + for a.intersection(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert!(i == expected.len()); + } - #[test] - fn test_symmetric_difference() { - let mut a = linear::LinearSet::new(); - let mut b = linear::LinearSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let mut i = 0; - let expected = [-2, 1, 5, 11, 14, 22]; - for a.symmetric_difference(&b) |x| { - assert!(vec::contains(expected, x)); - i += 1 - } - assert!(i == expected.len()); - } + #[test] + fn test_difference() { + let mut a = LinearSet::new(); + let mut b = LinearSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + + let mut i = 0; + let expected = [1, 5, 11]; + for a.difference(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert!(i == expected.len()); + } - #[test] - fn test_union() { - let mut a = linear::LinearSet::new(); - let mut b = linear::LinearSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let mut i = 0; - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - for a.union(&b) |x| { - assert!(vec::contains(expected, x)); - i += 1 - } - assert!(i == expected.len()); - } + #[test] + fn test_symmetric_difference() { + let mut a = LinearSet::new(); + let mut b = LinearSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(-2)); + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(22)); + + let mut i = 0; + let expected = [-2, 1, 5, 11, 14, 22]; + for a.symmetric_difference(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert!(i == expected.len()); + } + + #[test] + fn test_union() { + let mut a = LinearSet::new(); + let mut b = LinearSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(16)); + assert!(a.insert(19)); + assert!(a.insert(24)); + + assert!(b.insert(-2)); + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let mut i = 0; + let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; + for a.union(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert!(i == expected.len()); } } diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 39e43ba6fc5e8..ac6775eb81fec 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -79,7 +79,7 @@ use comm::{Chan, GenericChan}; use prelude::*; use unstable; use ptr; -use hashmap::linear::LinearSet; +use hashmap::LinearSet; use task::local_data_priv::{local_get, local_set}; use task::rt::rust_task; use task::rt; diff --git a/src/libcore/unstable/global.rs b/src/libcore/unstable/global.rs index ef5970658a192..3187012e2a983 100644 --- a/src/libcore/unstable/global.rs +++ b/src/libcore/unstable/global.rs @@ -34,7 +34,7 @@ use ops::Drop; use unstable::{Exclusive, exclusive}; use unstable::at_exit::at_exit; use unstable::intrinsics::atomic_cxchg; -use hashmap::linear::LinearMap; +use hashmap::LinearMap; use sys::Closure; #[cfg(test)] use unstable::{SharedMutableState, shared_mutable_state}; diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs index 8b24c2fa6f622..5556792c22543 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -21,7 +21,7 @@ is trying to shut down. use cell::Cell; use comm::{GenericSmartChan, stream}; use comm::{Port, Chan, SharedChan, GenericChan, GenericPort}; -use hashmap::linear::LinearMap; +use hashmap::LinearMap; use option::{Some, None}; use unstable::at_exit::at_exit; use unstable::finally::Finally; diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 6c485df84b484..89d1eb53c8201 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -18,7 +18,7 @@ use core::os; use core::uint; use core::util; use core::vec; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; fn not_win32(os: session::os) -> bool { match os { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 34678d1803c17..c50eecd448976 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -10,7 +10,7 @@ use core::prelude::*; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::libc::c_uint; use core::option; use core::ptr; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 086c6a33b3ec8..eb01964f6d692 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -18,7 +18,7 @@ use metadata::decoder; use metadata::filesearch::FileSearch; use metadata::loader; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::vec; use syntax::attr; use syntax::codemap::{span, dummy_sp}; diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index c836538e1e6c8..13447d09736e4 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -17,7 +17,7 @@ use core::prelude::*; use metadata::cstore; use metadata::decoder; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::vec; use std; use syntax::ast; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 340ad443b5888..b7ad62ee4ed2c 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -25,7 +25,7 @@ use util::ppaux::ty_to_str; use core::flate; use core::hash::HashUtil; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::int; use core::io::{Writer, WriterUtil}; use core::io; diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 9b777332c27c3..05f5f302f5379 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -16,7 +16,7 @@ use core::prelude::*; use middle::ty::param_ty; use middle::ty; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::io::WriterUtil; use core::io; use core::uint; diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index ac74dc25fd0d7..2bf89903e1c8b 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -31,7 +31,7 @@ use middle::mem_categorization::{lp_comp, lp_deref, lp_local}; use middle::ty; use util::ppaux::ty_to_str; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use core::uint; use syntax::ast::m_mutbl; use syntax::ast; diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 925659984d4bd..2965921b05a81 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -31,7 +31,7 @@ use middle::ty; use util::common::indenter; use util::ppaux::{expr_repr, region_to_str}; -use core::hashmap::linear::{LinearSet, LinearMap}; +use core::hashmap::{LinearSet, LinearMap}; use core::vec; use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast; diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 3f4f7469832f5..ca3365bbcabc4 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -234,7 +234,7 @@ use middle::moves; use util::common::stmt_set; use util::ppaux::note_and_explain_region; -use core::hashmap::linear::{LinearSet, LinearMap}; +use core::hashmap::{LinearSet, LinearMap}; use core::io; use core::result::{Result, Ok, Err}; use core::to_bytes; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d610b007f3503..788d8f6de89cd 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -20,7 +20,7 @@ use core::vec; use syntax::{ast, ast_map, ast_util, visit}; use syntax::ast::*; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; // // This pass classifies expressions by their constant-ness. diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 19d3e1f431db2..d680d1547351a 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -17,7 +17,7 @@ use core::prelude::*; use middle::resolve; use middle::ty; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use syntax::codemap::span; use syntax::{ast, ast_util, visit}; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 566a52c3894d1..7c399bf2ece68 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -31,7 +31,7 @@ use syntax::ast_util::local_def; use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor}; use syntax::visit::visit_crate; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::ptr; pub enum LangItem { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index ba232f55f74f6..d4cd500f04c48 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -15,7 +15,7 @@ use driver::session; use middle::ty; use util::ppaux::{ty_to_str}; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::char; use core::cmp; use core::i8; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index e9e226d36d1f5..a91404fb47a2a 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -111,7 +111,7 @@ use middle::typeck; use middle::moves; use util::ppaux::ty_to_str; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::io::WriterUtil; use core::io; use core::ptr; diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index a93618b66246f..de52d3e6878e9 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -215,7 +215,7 @@ use middle::typeck::method_map; use util::ppaux; use util::common::indenter; -use core::hashmap::linear::{LinearSet, LinearMap}; +use core::hashmap::{LinearSet, LinearMap}; use core::vec; use syntax::ast::*; use syntax::ast_util; diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 0e47dabcce900..db3f5acf9d590 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -12,7 +12,7 @@ use core::prelude::*; use middle::resolve; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use syntax::ast::*; use syntax::ast_util::{path_to_ident, walk_pat}; use syntax::codemap::span; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f6025548d71c0..e6e1990717254 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -26,7 +26,7 @@ use middle::ty::{region_variance, rv_covariant, rv_invariant}; use middle::ty::{rv_contravariant}; use middle::ty; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::vec; use syntax::ast_map; use syntax::codemap::span; diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 70d9dfacb6940..c4a6584dd66a3 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -77,7 +77,7 @@ use syntax::opt_vec::OptVec; use core::option::Some; use core::str::each_split_str; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; // Definition mapping pub type DefMap = @mut LinearMap; diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 12eaeb77d1103..1b5273dd3d7d3 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -167,7 +167,7 @@ use middle::trans::type_of; use middle::ty; use util::common::indenter; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use syntax::ast; use syntax::ast::ident; use syntax::ast_util::path_to_ident; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 15238f168944d..588690b055444 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -67,7 +67,7 @@ use util::ppaux::ty_to_str; use util::ppaux; use core::hash; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::int; use core::io; use core::libc::{c_uint, c_ulonglong}; diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index ab0e2f38a0b94..234812e66d9db 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -18,7 +18,7 @@ use syntax::codemap::span; use core::prelude::*; use core::cast; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::libc::{c_uint, c_ulonglong, c_char}; use core::libc; use core::option::Some; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 6bb30a5d5b51b..04aca7b9dcdc4 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -45,7 +45,7 @@ use util::ppaux::{expr_repr, ty_to_str}; use core::cast; use core::hash; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::libc::{c_uint, c_longlong, c_ulonglong}; use core::ptr; use core::str; diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index d290a8ffa5c94..69a70c5a2fd51 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -20,7 +20,7 @@ use middle::trans; use middle::ty; use util::ppaux::ty_to_str; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::libc; use core::option; use core::sys; diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index dc910f9f178e3..616a25d3c164f 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -153,7 +153,7 @@ use util::common::indenter; use util::ppaux::ty_to_str; use core::cast::transmute; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use syntax::print::pprust::{expr_to_str}; use syntax::ast; use syntax::codemap; diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 8824e0b782909..fd0eb9667098b 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -21,7 +21,7 @@ use middle::ty; use middle::typeck; use core::prelude::*; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use syntax::ast; use syntax::ast::*; use syntax::ast_util::def_id_of_def; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fddcce523f447..2b00bd0c71246 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -36,7 +36,7 @@ use core::result; use core::to_bytes; use core::uint; use core::vec; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use std::smallintmap::SmallIntMap; use syntax::ast::*; use syntax::ast_util::{is_local, local_def}; diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index cc2cf7a23c598..dd1dcbe67b94a 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -18,7 +18,7 @@ use middle::typeck::check::{instantiate_path, lookup_def}; use middle::typeck::check::{structure_of, valid_range_bounds}; use middle::typeck::require_same_types; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::vec; use syntax::ast; use syntax::ast_util; diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 320f0206fb871..8f7e8478f8adb 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -95,7 +95,7 @@ use middle::typeck::{method_self, method_static, method_trait, method_super}; use util::common::indenter; use util::ppaux::expr_repr; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use core::result; use core::uint; use core::vec; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 056ccf185995b..1c144b294d219 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -110,7 +110,7 @@ use util::common::{block_query, indenter, loop_query}; use util::ppaux::{bound_region_to_str, expr_repr, pat_repr}; use util::ppaux; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::ptr; use core::result::{Result, Ok, Err}; use core::result; diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index a1eaa1f6a3394..ddce274c54207 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -28,7 +28,7 @@ use core::result::{Ok, Err}; use core::result; use core::uint; use core::vec; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 4fc9e8d19ae1f..9f4984e02a603 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -53,7 +53,7 @@ use syntax::visit::{visit_mod}; use util::ppaux::ty_to_str; use core::result::Ok; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::uint; pub struct UniversalQuantificationResult { diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index d9f00451dd57e..b190a98f8cd08 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -548,7 +548,7 @@ use util::common::indenter; use util::ppaux::note_and_explain_region; use core::cell::{Cell, empty_cell}; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::result::{Err, Ok}; use core::to_bytes; use core::uint; diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 2b5a47c18c6d9..1a0a1fceb52a8 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -55,7 +55,7 @@ use middle::ty; use util::common::time; use util::ppaux; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::result; use core::vec; use std::list::List; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 2a2d921ba8636..98eff8b50d14d 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -14,7 +14,7 @@ use syntax::ast; use syntax::codemap::{span}; use syntax::visit; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use core::str; use std; diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index ff549ad2c2261..2f1d25425ec2b 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -28,7 +28,7 @@ extern mod syntax(vers = "0.6"); use core::*; use core::container::Map; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::io::WriterUtil; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index cd64061af0392..15546e96653d8 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -10,7 +10,7 @@ use core::*; use core::hash::Streaming; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; diff --git a/src/libstd/json.rs b/src/libstd/json.rs index e090d6bc036d8..1b79708e59017 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -16,7 +16,7 @@ use core::prelude::*; use core::io::{WriterUtil, ReaderUtil}; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use serialize::Encodable; use serialize; @@ -1161,7 +1161,7 @@ mod tests { use super::*; use core::prelude::*; - use core::hashmap::linear::LinearMap; + use core::hashmap::LinearMap; use std::serialize::Decodable; diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index d23784953ef99..b32a9841ac6c1 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -17,7 +17,7 @@ use core::from_str::FromStr; use core::io::{Reader, ReaderUtil}; use core::io; use core::prelude::*; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::str; use core::to_bytes::IterBytes; use core::to_bytes; @@ -818,7 +818,7 @@ mod tests { use net_url::*; - use core::hashmap::linear::LinearMap; + use core::hashmap::LinearMap; #[test] pub fn test_url_parse() { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index ddc84e07a3584..88ae58ee01b4c 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -17,7 +17,7 @@ Core encoding and decoding interfaces. #[forbid(non_camel_case_types)]; use core::prelude::*; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::trie::{TrieMap, TrieSet}; use deque::Deque; use dlist::DList; diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index 6ed1364d7fcb2..6886d5d630e19 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -24,7 +24,7 @@ use core::pipes::recv; use core::prelude::*; use core::result; use core::run; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::task; use core::to_bytes; diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index f22b466efebda..04d7cbdca0c3d 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -23,7 +23,7 @@ use print::pprust; use visit; use core::cmp; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::str; use core::vec; diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 9f8dbef9b967b..71e2faa93f569 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -20,7 +20,7 @@ use diagnostic::span_handler; use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; use core::vec; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use std; /* Constructors */ diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 93e2ad64c8c23..cae56267f5eb3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -20,7 +20,7 @@ use parse; use parse::token; use core::vec; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; // new-style macro! tt code: // @@ -509,7 +509,7 @@ impl MapChain{ #[cfg(test)] mod test { use super::MapChain; - use core::hashmap::linear::LinearMap; + use core::hashmap::LinearMap; #[test] fn testenv () { let mut a = LinearMap::new(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index f74fbbc3c03f7..fcb0c76a2c78a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -20,7 +20,7 @@ use parse::token::{Token, EOF, to_str, nonterminal}; use parse::token; use core::prelude::*; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; /* This is an Earley-like parser, without support for in-grammar nonterminals, only by calling out to the main rust parser for named nonterminals (which it diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 67c2f438269d8..de0b4c0799fba 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -18,7 +18,7 @@ use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; use parse::lexer::TokenAndSpan; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::option; use core::vec; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ceafecde3a0b1..1b845ad1dd9d4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -94,7 +94,7 @@ use opt_vec::OptVec; use core::either::Either; use core::either; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use core::vec; #[deriving(Eq)] diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 5fdf6f7620cc1..ff10b6070e66d 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,7 +18,7 @@ use util::interner; use core::cast; use core::char; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use core::str; use core::task; diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 159a205637b59..dd4044036ef84 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -13,7 +13,7 @@ // type, and vice versa. use core::prelude::*; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub struct Interner { priv map: @mut LinearMap, diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index fad72ee4eb360..eded285eef117 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -13,7 +13,7 @@ extern mod std; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub type header_map = LinearMap<~str, @mut ~[@~str]>; diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index d6ebf4d346bcc..c30c38e92f724 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -13,7 +13,7 @@ extern mod std; use core::io; use std::time; use std::treemap::TreeMap; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::trie::TrieMap; fn timed(label: &str, f: &fn()) { diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index a3210108dcc17..2fcd82eefe61b 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -9,7 +9,7 @@ // except according to those terms. extern mod std; -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; use std::bitv::BitvSet; use std::treemap::TreeSet; use core::io::WriterUtil; diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index a156f915faca7..397c08228995c 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -24,7 +24,7 @@ use std::arc; use std::time; use std::deque::Deque; use std::par; -use core::hashmap::linear::{LinearMap, LinearSet}; +use core::hashmap::{LinearMap, LinearSet}; use core::io::WriterUtil; use core::int::abs; use core::rand::RngUtil; diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 3bc40a46cfb2c..f608c71000b29 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -15,7 +15,7 @@ extern mod std; use std::sort; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use core::io::ReaderUtil; use core::comm::{stream, Port, Chan}; use core::cmp::Ord; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 1764ef48412cc..65d99858d1d36 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -25,7 +25,7 @@ // writes pbm image to output path use core::io::WriterUtil; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; struct cmplx { re: f64, diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs index 6dbfa5dd53847..b3cf314edd001 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs @@ -10,7 +10,7 @@ //buggy.rs -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; fn main() { let mut buggy_map :LinearMap = diff --git a/src/test/compile-fail/borrowck-insert-during-each.rs b/src/test/compile-fail/borrowck-insert-during-each.rs index 788c5397e35d0..1420a67556cad 100644 --- a/src/test/compile-fail/borrowck-insert-during-each.rs +++ b/src/test/compile-fail/borrowck-insert-during-each.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::linear::LinearSet; +use core::hashmap::LinearSet; struct Foo { n: LinearSet, diff --git a/src/test/compile-fail/for-loop-decl.rs b/src/test/compile-fail/for-loop-decl.rs index 918d8f00d7842..c7c1ea4821307 100644 --- a/src/test/compile-fail/for-loop-decl.rs +++ b/src/test/compile-fail/for-loop-decl.rs @@ -11,7 +11,7 @@ // error-pattern: mismatched types extern mod std; use std::bitv; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; struct FnInfo { vars: LinearMap diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index 6f71bd40affe5..00efdbbf75acc 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -9,7 +9,7 @@ // except according to those terms. use core::container::Map; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; // Test that trait types printed in error msgs include the type arguments. diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs index 06a3f0113b01c..5ec4beb364d89 100644 --- a/src/test/run-fail/unwind-misc-1.rs +++ b/src/test/run-fail/unwind-misc-1.rs @@ -14,7 +14,7 @@ fn main() { let count = @mut 0u; - let mut map = core::hashmap::linear::LinearMap::new(); + let mut map = core::hashmap::LinearMap::new(); let mut arr = ~[]; for uint::range(0u, 10u) |i| { arr += ~[@~"key stuff"]; diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 4234c064e8d38..415f753a562e2 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -19,7 +19,7 @@ pub fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); } mod map_reduce { - use core::hashmap::linear::LinearMap; + use core::hashmap::LinearMap; use core::comm::*; pub type putter = @fn(~str, ~str); diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 5f8b8d2983072..401920789c098 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -10,7 +10,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub fn main() { let mut m = LinearMap::new(); diff --git a/src/test/run-pass/issue-2631-b.rs b/src/test/run-pass/issue-2631-b.rs index b22c423ed0412..42452d3a2bb0f 100644 --- a/src/test/run-pass/issue-2631-b.rs +++ b/src/test/run-pass/issue-2631-b.rs @@ -14,7 +14,7 @@ extern mod req; use req::*; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub fn main() { let v = ~[@~"hi"]; diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index 8934c3935c087..4f0930deaaef1 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -13,7 +13,7 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; fn add_interfaces(managed_ip: ~str, device: LinearMap<~str, int>) { error!("%s, %?", managed_ip, device.get(&~"interfaces")); diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs index 3d1a2c3df5d3b..a1c5f4a6757dc 100644 --- a/src/test/run-pass/issue-2804.rs +++ b/src/test/run-pass/issue-2804.rs @@ -11,7 +11,7 @@ // except according to those terms. extern mod std; -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; use std::json; enum object { diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index 022d3f6fceb05..9665113bc0cee 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -10,7 +10,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub fn main() { let mut buggy_map: LinearMap = LinearMap::new::(); diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index f7b7605523c25..a73f130e88981 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -29,7 +29,7 @@ fn check_strs(actual: &str, expected: &str) -> bool #[test] fn tester() { - let mut table = core::hashmap::linear::LinearMap(); + let mut table = core::hashmap::LinearMap(); table.insert(@~"one", 1); table.insert(@~"two", 2); assert!(check_strs(table.to_str(), ~"xxx")); // not sure what expected should be diff --git a/src/test/run-pass/issue-4016.rs b/src/test/run-pass/issue-4016.rs index 69cd1a2a19d86..2384b0e859393 100644 --- a/src/test/run-pass/issue-4016.rs +++ b/src/test/run-pass/issue-4016.rs @@ -11,7 +11,7 @@ // xfail-test extern mod std; -use hashmap::linear; +use hashmap; use std::json; use std::serialization::{Deserializable, deserialize}; diff --git a/src/test/run-pass/issue-4092.rs b/src/test/run-pass/issue-4092.rs index 85cb3e3207ee7..8cda78840b341 100644 --- a/src/test/run-pass/issue-4092.rs +++ b/src/test/run-pass/issue-4092.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::linear::LinearMap; +use core::hashmap::LinearMap; pub fn main() { let mut x = LinearMap::new(); From cc148b58ff7a4eb6861701be61396d1a685f6657 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 3 Apr 2013 09:28:36 -0400 Subject: [PATCH 017/403] rename Linear{Map,Set} => Hash{Map,Set} --- doc/rust.md | 4 +- doc/tutorial.md | 4 +- src/libcore/gc.rs | 4 +- src/libcore/hashmap.rs | 134 +++++++++--------- src/libcore/task/spawn.rs | 6 +- src/libcore/unstable/global.rs | 6 +- src/libcore/unstable/weak_task.rs | 4 +- src/librustc/back/rpath.rs | 4 +- src/librustc/lib/llvm.rs | 10 +- src/librustc/metadata/creader.rs | 4 +- src/librustc/metadata/cstore.rs | 12 +- src/librustc/metadata/encoder.rs | 14 +- src/librustc/metadata/tyencode.rs | 4 +- src/librustc/middle/borrowck/check_loans.rs | 6 +- src/librustc/middle/borrowck/gather_loans.rs | 10 +- src/librustc/middle/borrowck/mod.rs | 20 +-- src/librustc/middle/const_eval.rs | 18 +-- src/librustc/middle/freevars.rs | 8 +- src/librustc/middle/lang_items.rs | 6 +- src/librustc/middle/lint.rs | 10 +- src/librustc/middle/liveness.rs | 24 ++-- src/librustc/middle/moves.rs | 14 +- src/librustc/middle/pat_util.rs | 6 +- src/librustc/middle/region.rs | 18 +-- src/librustc/middle/resolve.rs | 66 ++++----- src/librustc/middle/trans/_match.rs | 6 +- src/librustc/middle/trans/base.rs | 62 ++++---- src/librustc/middle/trans/build.rs | 4 +- src/librustc/middle/trans/common.rs | 58 ++++---- src/librustc/middle/trans/debuginfo.rs | 6 +- src/librustc/middle/trans/expr.rs | 4 +- src/librustc/middle/trans/reachable.rs | 12 +- src/librustc/middle/ty.rs | 102 ++++++------- src/librustc/middle/typeck/check/_match.rs | 8 +- src/librustc/middle/typeck/check/method.rs | 6 +- src/librustc/middle/typeck/check/mod.rs | 26 ++-- src/librustc/middle/typeck/check/vtable.rs | 4 +- src/librustc/middle/typeck/coherence.rs | 24 ++-- .../middle/typeck/infer/region_inference.rs | 18 +-- src/librustc/middle/typeck/mod.rs | 10 +- src/librustc/util/common.rs | 4 +- src/librustpkg/rustpkg.rc | 10 +- src/librustpkg/util.rs | 4 +- src/libstd/json.rs | 16 +-- src/libstd/net_url.rs | 16 +-- src/libstd/serialize.rs | 18 +-- src/libstd/workcache.rs | 16 +-- src/libsyntax/ast_map.rs | 6 +- src/libsyntax/attr.rs | 4 +- src/libsyntax/ext/base.rs | 18 +-- src/libsyntax/ext/tt/macro_parser.rs | 12 +- src/libsyntax/ext/tt/transcribe.rs | 8 +- src/libsyntax/parse/parser.rs | 12 +- src/libsyntax/parse/token.rs | 18 +-- src/libsyntax/util/interner.rs | 6 +- src/test/auxiliary/issue-2631-a.rs | 4 +- src/test/bench/core-map.rs | 12 +- src/test/bench/core-set.rs | 8 +- src/test/bench/graph500-bfs.rs | 6 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 10 +- src/test/bench/shootout-mandelbrot.rs | 4 +- .../borrowck-borrowed-uniq-rvalue.rs | 6 +- .../borrowck-insert-during-each.rs | 6 +- src/test/compile-fail/for-loop-decl.rs | 4 +- src/test/compile-fail/map-types.rs | 4 +- src/test/run-fail/unwind-misc-1.rs | 2 +- src/test/run-pass/explicit-self-generic.rs | 10 +- src/test/run-pass/hashmap-memory.rs | 10 +- src/test/run-pass/issue-1696.rs | 4 +- src/test/run-pass/issue-2631-b.rs | 4 +- src/test/run-pass/issue-2804-2.rs | 4 +- src/test/run-pass/issue-2804.rs | 4 +- src/test/run-pass/issue-3026.rs | 4 +- src/test/run-pass/issue-3559.rs | 2 +- src/test/run-pass/issue-4092.rs | 4 +- 75 files changed, 523 insertions(+), 523 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 64f0dc93e7867..66280b1b9723e 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -441,10 +441,10 @@ expression context, the final namespace qualifier is omitted. Two examples of paths with type arguments: ~~~~ -# use core::hashmap::LinearMap; +# use core::hashmap::HashMap; # fn f() { # fn id(t: T) -> T { t } -type t = LinearMap; // Type arguments used in a type expression +type t = HashMap; // Type arguments used in a type expression let x = id::(10); // Type arguments used in a call expression # } ~~~~ diff --git a/doc/tutorial.md b/doc/tutorial.md index 8c5294767c26a..42c3a7a8d664f 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1888,8 +1888,8 @@ illegal to copy and pass by value. Generic `type`, `struct`, and `enum` declarations follow the same pattern: ~~~~ -# use core::hashmap::LinearMap; -type Set = LinearMap; +# use core::hashmap::HashMap; +type Set = HashMap; struct Stack { elements: ~[T] diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 46f2ad76d0792..9fd9ac3a8c8ec 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -43,7 +43,7 @@ use io; use libc::{size_t, uintptr_t}; use option::{None, Option, Some}; use ptr; -use hashmap::LinearSet; +use hashmap::HashSet; use stackwalk; use sys; @@ -344,7 +344,7 @@ pub fn cleanup_stack_for_failure() { ptr::null() }; - let mut roots = LinearSet::new(); + let mut roots = HashSet::new(); for walk_gc_roots(need_cleanup, sentinel) |root, tydesc| { // Track roots to avoid double frees. if roots.contains(&*root) { diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 67942abba4633..5dbf085f09719 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -35,7 +35,7 @@ struct Bucket { value: V, } -pub struct LinearMap { +pub struct HashMap { priv k0: u64, priv k1: u64, priv resize_at: uint, @@ -55,7 +55,7 @@ fn resize_at(capacity: uint) -> uint { } pub fn linear_map_with_capacity( - initial_capacity: uint) -> LinearMap { + initial_capacity: uint) -> HashMap { let r = rand::task_rng(); linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(), initial_capacity) @@ -63,8 +63,8 @@ pub fn linear_map_with_capacity( fn linear_map_with_capacity_and_keys( k0: u64, k1: u64, - initial_capacity: uint) -> LinearMap { - LinearMap { + initial_capacity: uint) -> HashMap { + HashMap { k0: k0, k1: k1, resize_at: resize_at(initial_capacity), size: 0, @@ -72,7 +72,7 @@ fn linear_map_with_capacity_and_keys( } } -priv impl LinearMap { +priv impl HashMap { #[inline(always)] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the @@ -190,7 +190,7 @@ priv impl LinearMap { fn value_for_bucket(&self, idx: uint) -> &'self V { match self.buckets[idx] { Some(ref bkt) => &bkt.value, - None => fail!(~"LinearMap::find: internal logic error"), + None => fail!(~"HashMap::find: internal logic error"), } } @@ -280,7 +280,7 @@ priv impl LinearMap { } impl<'self,K:Hash + IterBytes + Eq,V> - BaseIter<(&'self K, &'self V)> for LinearMap { + BaseIter<(&'self K, &'self V)> for HashMap { /// Visit all key-value pairs fn each(&self, blk: &fn(&(&'self K, &'self V)) -> bool) { for uint::range(0, self.buckets.len()) |i| { @@ -297,7 +297,7 @@ impl<'self,K:Hash + IterBytes + Eq,V> } -impl Container for LinearMap { +impl Container for HashMap { /// Return the number of elements in the map fn len(&const self) -> uint { self.size } @@ -305,7 +305,7 @@ impl Container for LinearMap { fn is_empty(&const self) -> bool { self.len() == 0 } } -impl Mutable for LinearMap { +impl Mutable for HashMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { for uint::range(0, self.buckets.len()) |idx| { @@ -315,7 +315,7 @@ impl Mutable for LinearMap { } } -impl<'self,K:Hash + IterBytes + Eq,V> Map for LinearMap { +impl<'self,K:Hash + IterBytes + Eq,V> Map for HashMap { /// Return true if the map contains a value for the specified key fn contains_key(&self, k: &K) -> bool { match self.bucket_for_key(k) { @@ -391,15 +391,15 @@ impl<'self,K:Hash + IterBytes + Eq,V> Map for LinearMap { } } -pub impl LinearMap { - /// Create an empty LinearMap - fn new() -> LinearMap { - LinearMap::with_capacity(INITIAL_CAPACITY) +pub impl HashMap { + /// Create an empty HashMap + fn new() -> HashMap { + HashMap::with_capacity(INITIAL_CAPACITY) } - /// Create an empty LinearMap with space for at least `n` elements in + /// Create an empty HashMap with space for at least `n` elements in /// the hash table. - fn with_capacity(capacity: uint) -> LinearMap { + fn with_capacity(capacity: uint) -> HashMap { linear_map_with_capacity(capacity) } @@ -541,8 +541,8 @@ pub impl LinearMap { } } -impl Eq for LinearMap { - fn eq(&self, other: &LinearMap) -> bool { +impl Eq for HashMap { + fn eq(&self, other: &HashMap) -> bool { if self.len() != other.len() { return false; } for self.each |&(key, value)| { @@ -555,25 +555,25 @@ impl Eq for LinearMap { true } - fn ne(&self, other: &LinearMap) -> bool { !self.eq(other) } + fn ne(&self, other: &HashMap) -> bool { !self.eq(other) } } -pub struct LinearSet { - priv map: LinearMap +pub struct HashSet { + priv map: HashMap } -impl BaseIter for LinearSet { +impl BaseIter for HashSet { /// Visit all values in order fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } fn size_hint(&self) -> Option { Some(self.len()) } } -impl Eq for LinearSet { - fn eq(&self, other: &LinearSet) -> bool { self.map == other.map } - fn ne(&self, other: &LinearSet) -> bool { self.map != other.map } +impl Eq for HashSet { + fn eq(&self, other: &HashSet) -> bool { self.map == other.map } + fn ne(&self, other: &HashSet) -> bool { self.map != other.map } } -impl Container for LinearSet { +impl Container for HashSet { /// Return the number of elements in the set fn len(&const self) -> uint { self.map.len() } @@ -581,12 +581,12 @@ impl Container for LinearSet { fn is_empty(&const self) -> bool { self.map.is_empty() } } -impl Mutable for LinearSet { +impl Mutable for HashSet { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } } -impl Set for LinearSet { +impl Set for HashSet { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } @@ -600,22 +600,22 @@ impl Set for LinearSet { /// Return true if the set has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. - fn is_disjoint(&self, other: &LinearSet) -> bool { + fn is_disjoint(&self, other: &HashSet) -> bool { iter::all(self, |v| !other.contains(v)) } /// Return true if the set is a subset of another - fn is_subset(&self, other: &LinearSet) -> bool { + fn is_subset(&self, other: &HashSet) -> bool { iter::all(self, |v| other.contains(v)) } /// Return true if the set is a superset of another - fn is_superset(&self, other: &LinearSet) -> bool { + fn is_superset(&self, other: &HashSet) -> bool { other.is_subset(self) } /// Visit the values representing the difference - fn difference(&self, other: &LinearSet, f: &fn(&T) -> bool) { + fn difference(&self, other: &HashSet, f: &fn(&T) -> bool) { for self.each |v| { if !other.contains(v) { if !f(v) { return } @@ -625,14 +625,14 @@ impl Set for LinearSet { /// Visit the values representing the symmetric difference fn symmetric_difference(&self, - other: &LinearSet, + other: &HashSet, f: &fn(&T) -> bool) { self.difference(other, f); other.difference(self, f); } /// Visit the values representing the intersection - fn intersection(&self, other: &LinearSet, f: &fn(&T) -> bool) { + fn intersection(&self, other: &HashSet, f: &fn(&T) -> bool) { for self.each |v| { if other.contains(v) { if !f(v) { return } @@ -641,7 +641,7 @@ impl Set for LinearSet { } /// Visit the values representing the union - fn union(&self, other: &LinearSet, f: &fn(&T) -> bool) { + fn union(&self, other: &HashSet, f: &fn(&T) -> bool) { for self.each |v| { if !f(v) { return } } @@ -654,16 +654,16 @@ impl Set for LinearSet { } } -pub impl LinearSet { - /// Create an empty LinearSet - fn new() -> LinearSet { - LinearSet::with_capacity(INITIAL_CAPACITY) +pub impl HashSet { + /// Create an empty HashSet + fn new() -> HashSet { + HashSet::with_capacity(INITIAL_CAPACITY) } - /// Create an empty LinearSet with space for at least `n` elements in + /// Create an empty HashSet with space for at least `n` elements in /// the hash table. - fn with_capacity(capacity: uint) -> LinearSet { - LinearSet { map: LinearMap::with_capacity(capacity) } + fn with_capacity(capacity: uint) -> HashSet { + HashSet { map: HashMap::with_capacity(capacity) } } /// Reserve space for at least `n` elements in the hash table. @@ -686,7 +686,7 @@ mod test_map { #[test] pub fn test_insert() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(m.insert(2, 4)); assert!(*m.get(&1) == 2); @@ -695,7 +695,7 @@ mod test_map { #[test] fn test_find_mut() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.insert(1, 12)); assert!(m.insert(2, 8)); assert!(m.insert(5, 14)); @@ -708,7 +708,7 @@ mod test_map { #[test] pub fn test_insert_overwrite() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(*m.get(&1) == 2); assert!(!m.insert(1, 3)); @@ -748,7 +748,7 @@ mod test_map { #[test] pub fn test_pop() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); m.insert(1, 2); assert!(m.pop(&1) == Some(2)); assert!(m.pop(&1) == None); @@ -756,7 +756,7 @@ mod test_map { #[test] pub fn test_swap() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.swap(1, 2) == None); assert!(m.swap(1, 3) == Some(2)); assert!(m.swap(1, 4) == Some(3)); @@ -764,24 +764,24 @@ mod test_map { #[test] pub fn test_find_or_insert() { - let mut m = LinearMap::new::(); + let mut m = HashMap::new::(); assert!(m.find_or_insert(1, 2) == &2); assert!(m.find_or_insert(1, 3) == &2); } #[test] pub fn test_find_or_insert_with() { - let mut m = LinearMap::new::(); + let mut m = HashMap::new::(); assert!(m.find_or_insert_with(1, |_| 2) == &2); assert!(m.find_or_insert_with(1, |_| 3) == &2); } #[test] pub fn test_consume() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(m.insert(2, 3)); - let mut m2 = LinearMap::new(); + let mut m2 = HashMap::new(); do m.consume |k, v| { m2.insert(k, v); } @@ -807,7 +807,7 @@ mod test_map { #[test] pub fn test_find() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.find(&1).is_none()); m.insert(1, 2); match m.find(&1) { @@ -818,12 +818,12 @@ mod test_map { #[test] pub fn test_eq() { - let mut m1 = LinearMap::new(); + let mut m1 = HashMap::new(); m1.insert(1, 2); m1.insert(2, 3); m1.insert(3, 4); - let mut m2 = LinearMap::new(); + let mut m2 = HashMap::new(); m2.insert(1, 2); m2.insert(2, 3); @@ -836,7 +836,7 @@ mod test_map { #[test] pub fn test_expand() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(m.len() == 0); assert!(m.is_empty()); @@ -861,8 +861,8 @@ mod test_set { #[test] fn test_disjoint() { - let mut xs = LinearSet::new(); - let mut ys = LinearSet::new(); + let mut xs = HashSet::new(); + let mut ys = HashSet::new(); assert!(xs.is_disjoint(&ys)); assert!(ys.is_disjoint(&xs)); assert!(xs.insert(5)); @@ -883,13 +883,13 @@ mod test_set { #[test] fn test_subset_and_superset() { - let mut a = LinearSet::new(); + let mut a = HashSet::new(); assert!(a.insert(0)); assert!(a.insert(5)); assert!(a.insert(11)); assert!(a.insert(7)); - let mut b = LinearSet::new(); + let mut b = HashSet::new(); assert!(b.insert(0)); assert!(b.insert(7)); assert!(b.insert(19)); @@ -912,8 +912,8 @@ mod test_set { #[test] fn test_intersection() { - let mut a = LinearSet::new(); - let mut b = LinearSet::new(); + let mut a = HashSet::new(); + let mut b = HashSet::new(); assert!(a.insert(11)); assert!(a.insert(1)); @@ -942,8 +942,8 @@ mod test_set { #[test] fn test_difference() { - let mut a = LinearSet::new(); - let mut b = LinearSet::new(); + let mut a = HashSet::new(); + let mut b = HashSet::new(); assert!(a.insert(1)); assert!(a.insert(3)); @@ -965,8 +965,8 @@ mod test_set { #[test] fn test_symmetric_difference() { - let mut a = LinearSet::new(); - let mut b = LinearSet::new(); + let mut a = HashSet::new(); + let mut b = HashSet::new(); assert!(a.insert(1)); assert!(a.insert(3)); @@ -991,8 +991,8 @@ mod test_set { #[test] fn test_union() { - let mut a = LinearSet::new(); - let mut b = LinearSet::new(); + let mut a = HashSet::new(); + let mut b = HashSet::new(); assert!(a.insert(1)); assert!(a.insert(3)); diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index ac6775eb81fec..e1b645cd56272 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -79,7 +79,7 @@ use comm::{Chan, GenericChan}; use prelude::*; use unstable; use ptr; -use hashmap::LinearSet; +use hashmap::HashSet; use task::local_data_priv::{local_get, local_set}; use task::rt::rust_task; use task::rt; @@ -96,10 +96,10 @@ macro_rules! move_it ( { $x:expr } => ( unsafe { let y = *ptr::addr_of(&($x)); y } ) ) -type TaskSet = LinearSet<*rust_task>; +type TaskSet = HashSet<*rust_task>; fn new_taskset() -> TaskSet { - LinearSet::new() + HashSet::new() } fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) { let didnt_overwrite = tasks.insert(task); diff --git a/src/libcore/unstable/global.rs b/src/libcore/unstable/global.rs index 3187012e2a983..41d0842002f67 100644 --- a/src/libcore/unstable/global.rs +++ b/src/libcore/unstable/global.rs @@ -34,7 +34,7 @@ use ops::Drop; use unstable::{Exclusive, exclusive}; use unstable::at_exit::at_exit; use unstable::intrinsics::atomic_cxchg; -use hashmap::LinearMap; +use hashmap::HashMap; use sys::Closure; #[cfg(test)] use unstable::{SharedMutableState, shared_mutable_state}; @@ -144,7 +144,7 @@ pub unsafe fn global_data_clone( // destructor. Keys are pointers derived from the type of the // global value. There is a single GlobalState instance per runtime. struct GlobalState { - map: LinearMap + map: HashMap } impl Drop for GlobalState { @@ -171,7 +171,7 @@ fn get_global_state() -> Exclusive { // The global state object let state = GlobalState { - map: LinearMap::new() + map: HashMap::new() }; // It's under a reference-counted mutex diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs index 5556792c22543..6eabb0629d1fc 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -21,7 +21,7 @@ is trying to shut down. use cell::Cell; use comm::{GenericSmartChan, stream}; use comm::{Port, Chan, SharedChan, GenericChan, GenericPort}; -use hashmap::LinearMap; +use hashmap::HashMap; use option::{Some, None}; use unstable::at_exit::at_exit; use unstable::finally::Finally; @@ -97,7 +97,7 @@ fn create_global_service() -> ~WeakTaskService { fn run_weak_task_service(port: Port) { - let mut shutdown_map = LinearMap::new(); + let mut shutdown_map = HashMap::new(); loop { match port.recv() { diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 89d1eb53c8201..cc1168bd79ddd 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -18,7 +18,7 @@ use core::os; use core::uint; use core::util; use core::vec; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; fn not_win32(os: session::os) -> bool { match os { @@ -186,7 +186,7 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> Path { } pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { - let mut set = LinearSet::new(); + let mut set = HashSet::new(); let mut minimized = ~[]; for rpaths.each |rpath| { if set.insert(rpath.to_str()) { diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index c50eecd448976..b6d3fce7e7546 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -10,7 +10,7 @@ use core::prelude::*; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::libc::c_uint; use core::option; use core::ptr; @@ -1467,8 +1467,8 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { /* Memory-managed object interface to type handles. */ pub struct TypeNames { - type_names: @mut LinearMap, - named_types: @mut LinearMap<@str, TypeRef> + type_names: @mut HashMap, + named_types: @mut HashMap<@str, TypeRef> } pub fn associate_type(tn: @TypeNames, s: @str, t: TypeRef) { @@ -1486,8 +1486,8 @@ pub fn name_has_type(tn: @TypeNames, s: @str) -> Option { pub fn mk_type_names() -> @TypeNames { @TypeNames { - type_names: @mut LinearMap::new(), - named_types: @mut LinearMap::new() + type_names: @mut HashMap::new(), + named_types: @mut HashMap::new() } } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index eb01964f6d692..8609434e6df29 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -18,7 +18,7 @@ use metadata::decoder; use metadata::filesearch::FileSearch; use metadata::loader; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::vec; use syntax::attr; use syntax::codemap::{span, dummy_sp}; @@ -302,7 +302,7 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers - let mut cnum_map = LinearMap::new(); + let mut cnum_map = HashMap::new(); for decoder::get_crate_deps(e.intr, cdata).each |dep| { let extrn_cnum = dep.cnum; let cname = dep.name; diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 13447d09736e4..65bd37236b714 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -17,7 +17,7 @@ use core::prelude::*; use metadata::cstore; use metadata::decoder; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::vec; use std; use syntax::ast; @@ -27,7 +27,7 @@ use syntax::parse::token::ident_interner; // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their // own crate numbers. -pub type cnum_map = @mut LinearMap; +pub type cnum_map = @mut HashMap; pub struct crate_metadata { name: @~str, @@ -37,7 +37,7 @@ pub struct crate_metadata { } pub struct CStore { - priv metas: LinearMap , + priv metas: HashMap , priv extern_mod_crate_map: extern_mod_crate_map, priv used_crate_files: ~[Path], priv used_libraries: ~[~str], @@ -46,12 +46,12 @@ pub struct CStore { } // Map from node_id's of local extern mod statements to crate numbers -type extern_mod_crate_map = LinearMap; +type extern_mod_crate_map = HashMap; pub fn mk_cstore(intr: @ident_interner) -> CStore { return CStore { - metas: LinearMap::new(), - extern_mod_crate_map: LinearMap::new(), + metas: HashMap::new(), + extern_mod_crate_map: HashMap::new(), used_crate_files: ~[], used_libraries: ~[], used_link_args: ~[], diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b7ad62ee4ed2c..6000e559554f3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -25,7 +25,7 @@ use util::ppaux::ty_to_str; use core::flate; use core::hash::HashUtil; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::int; use core::io::{Writer, WriterUtil}; use core::io; @@ -50,7 +50,7 @@ use syntax; use writer = std::ebml::writer; // used by astencode: -type abbrev_map = @mut LinearMap; +type abbrev_map = @mut HashMap; pub type encode_inlined_item = @fn(ecx: @EncodeContext, ebml_w: writer::Encoder, @@ -62,8 +62,8 @@ pub struct EncodeParams { tcx: ty::ctxt, reachable: reachable::map, reexports2: middle::resolve::ExportMap2, - item_symbols: @mut LinearMap, - discrim_symbols: @mut LinearMap, + item_symbols: @mut HashMap, + discrim_symbols: @mut HashMap, link_meta: LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item @@ -89,8 +89,8 @@ pub struct EncodeContext { stats: @mut Stats, reachable: reachable::map, reexports2: middle::resolve::ExportMap2, - item_symbols: @mut LinearMap, - discrim_symbols: @mut LinearMap, + item_symbols: @mut HashMap, + discrim_symbols: @mut HashMap, link_meta: LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item, @@ -1345,7 +1345,7 @@ pub fn encode_metadata(+parms: EncodeParams, crate: &crate) -> ~[u8] { link_meta: link_meta, cstore: cstore, encode_inlined_item: encode_inlined_item, - type_abbrevs: @mut LinearMap::new() + type_abbrevs: @mut HashMap::new() }; let ebml_w = writer::Encoder(wr as @io::Writer); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 05f5f302f5379..251ba9b35cbd9 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -16,7 +16,7 @@ use core::prelude::*; use middle::ty::param_ty; use middle::ty; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::io::WriterUtil; use core::io; use core::uint; @@ -47,7 +47,7 @@ pub struct ty_abbrev { pub enum abbrev_ctxt { ac_no_abbrevs, - ac_use_abbrevs(@mut LinearMap), + ac_use_abbrevs(@mut HashMap), } fn cx_uses_abbrevs(cx: @ctxt) -> bool { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 2bf89903e1c8b..160356567421d 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -31,7 +31,7 @@ use middle::mem_categorization::{lp_comp, lp_deref, lp_local}; use middle::ty; use util::ppaux::ty_to_str; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use core::uint; use syntax::ast::m_mutbl; use syntax::ast; @@ -44,7 +44,7 @@ struct CheckLoanCtxt { bccx: @BorrowckCtxt, req_maps: ReqMaps, - reported: LinearSet, + reported: HashSet, declared_purity: @mut ast::purity, fn_args: @mut @~[ast::node_id] @@ -68,7 +68,7 @@ pub fn check_loans(bccx: @BorrowckCtxt, let clcx = @mut CheckLoanCtxt { bccx: bccx, req_maps: req_maps, - reported: LinearSet::new(), + reported: HashSet::new(), declared_purity: @mut ast::impure_fn, fn_args: @mut @~[] }; diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 2965921b05a81..122e2c64b2133 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -31,7 +31,7 @@ use middle::ty; use util::common::indenter; use util::ppaux::{expr_repr, region_to_str}; -use core::hashmap::{LinearSet, LinearMap}; +use core::hashmap::{HashSet, HashMap}; use core::vec; use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast; @@ -72,17 +72,17 @@ struct GatherLoanCtxt { req_maps: ReqMaps, item_ub: ast::node_id, root_ub: ast::node_id, - ignore_adjustments: LinearSet + ignore_adjustments: HashSet } pub fn gather_loans(bccx: @BorrowckCtxt, crate: @ast::crate) -> ReqMaps { let glcx = @mut GatherLoanCtxt { bccx: bccx, - req_maps: ReqMaps { req_loan_map: LinearMap::new(), - pure_map: LinearMap::new() }, + req_maps: ReqMaps { req_loan_map: HashMap::new(), + pure_map: HashMap::new() }, item_ub: 0, root_ub: 0, - ignore_adjustments: LinearSet::new() + ignore_adjustments: HashSet::new() }; let v = visit::mk_vt(@visit::Visitor {visit_expr: req_loans_in_expr, visit_fn: req_loans_in_fn, diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index ca3365bbcabc4..5e7903f66102f 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -234,7 +234,7 @@ use middle::moves; use util::common::stmt_set; use util::ppaux::note_and_explain_region; -use core::hashmap::{LinearSet, LinearMap}; +use core::hashmap::{HashSet, HashMap}; use core::io; use core::result::{Result, Ok, Err}; use core::to_bytes; @@ -260,9 +260,9 @@ pub fn check_crate( moves_map: moves_map, capture_map: capture_map, root_map: root_map(), - mutbl_map: @mut LinearSet::new(), - write_guard_map: @mut LinearSet::new(), - stmt_map: @mut LinearSet::new(), + mutbl_map: @mut HashSet::new(), + write_guard_map: @mut HashSet::new(), + stmt_map: @mut HashSet::new(), stats: @mut BorrowStats { loaned_paths_same: 0, loaned_paths_imm: 0, @@ -333,7 +333,7 @@ pub struct RootInfo { // a map mapping id's of expressions of gc'd type (@T, @[], etc) where // the box needs to be kept live to the id of the scope for which they // must stay live. -pub type root_map = @mut LinearMap; +pub type root_map = @mut HashMap; // the keys to the root map combine the `id` of the expression with // the number of types that it is autodereferenced. So, for example, @@ -348,11 +348,11 @@ pub struct root_map_key { // set of ids of local vars / formal arguments that are modified / moved. // this is used in trans for optimization purposes. -pub type mutbl_map = @mut LinearSet; +pub type mutbl_map = @mut HashSet; // A set containing IDs of expressions of gc'd type that need to have a write // guard. -pub type write_guard_map = @mut LinearSet; +pub type write_guard_map = @mut HashSet; // Errors that can occur #[deriving(Eq)] @@ -405,8 +405,8 @@ pub struct Loan { /// - `pure_map`: map from block/expr that must be pure to the error message /// that should be reported if they are not pure pub struct ReqMaps { - req_loan_map: LinearMap, - pure_map: LinearMap + req_loan_map: HashMap, + pure_map: HashMap } pub fn save_and_restore(save_and_restore_t: &mut T, @@ -450,7 +450,7 @@ impl to_bytes::IterBytes for root_map_key { } pub fn root_map() -> root_map { - return @mut LinearMap::new(); + return @mut HashMap::new(); } // ___________________________________________________________________________ diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 788d8f6de89cd..d6434e469b2d1 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -20,7 +20,7 @@ use core::vec; use syntax::{ast, ast_map, ast_util, visit}; use syntax::ast::*; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; // // This pass classifies expressions by their constant-ness. @@ -189,14 +189,14 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, } } else { let maps = astencode::Maps { - mutbl_map: @mut LinearSet::new(), - root_map: @mut LinearMap::new(), - last_use_map: @mut LinearMap::new(), - method_map: @mut LinearMap::new(), - vtable_map: @mut LinearMap::new(), - write_guard_map: @mut LinearSet::new(), - moves_map: @mut LinearSet::new(), - capture_map: @mut LinearMap::new() + mutbl_map: @mut HashSet::new(), + root_map: @mut HashMap::new(), + last_use_map: @mut HashMap::new(), + method_map: @mut HashMap::new(), + vtable_map: @mut HashMap::new(), + write_guard_map: @mut HashSet::new(), + moves_map: @mut HashSet::new(), + capture_map: @mut HashMap::new() }; match csearch::maybe_get_item_ast(tcx, def_id, |a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) { diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index d680d1547351a..e6e9f3be85d21 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -17,7 +17,7 @@ use core::prelude::*; use middle::resolve; use middle::ty; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use syntax::codemap::span; use syntax::{ast, ast_util, visit}; @@ -30,7 +30,7 @@ pub struct freevar_entry { span: span //< First span where it is accessed (there can be multiple) } pub type freevar_info = @~[@freevar_entry]; -pub type freevar_map = @mut LinearMap; +pub type freevar_map = @mut HashMap; // Searches through part of the AST for all references to locals or // upvars in this frame and returns the list of definition IDs thus found. @@ -39,7 +39,7 @@ pub type freevar_map = @mut LinearMap; // in order to start the search. fn collect_freevars(def_map: resolve::DefMap, blk: &ast::blk) -> freevar_info { - let seen = @mut LinearMap::new(); + let seen = @mut HashMap::new(); let refs = @mut ~[]; fn ignore_item(_i: @ast::item, &&_depth: int, _v: visit::vt) { } @@ -92,7 +92,7 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::blk) // one pass. This could be improved upon if it turns out to matter. pub fn annotate_freevars(def_map: resolve::DefMap, crate: @ast::crate) -> freevar_map { - let freevars = @mut LinearMap::new(); + let freevars = @mut HashMap::new(); let walk_fn: @fn(&visit::fn_kind, &ast::fn_decl, diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 7c399bf2ece68..ab9b8ca0db624 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -31,7 +31,7 @@ use syntax::ast_util::local_def; use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor}; use syntax::visit::visit_crate; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::ptr; pub enum LangItem { @@ -259,7 +259,7 @@ fn LanguageItemCollector<'r>(crate: @crate, session: Session, items: &'r mut LanguageItems) -> LanguageItemCollector<'r> { - let mut item_refs = LinearMap::new(); + let mut item_refs = HashMap::new(); item_refs.insert(@~"const", ConstTraitLangItem as uint); item_refs.insert(@~"copy", CopyTraitLangItem as uint); @@ -317,7 +317,7 @@ struct LanguageItemCollector<'self> { crate: @crate, session: Session, - item_refs: LinearMap<@~str, uint>, + item_refs: HashMap<@~str, uint>, } pub impl<'self> LanguageItemCollector<'self> { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index d4cd500f04c48..a21cc26bd9124 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -15,7 +15,7 @@ use driver::session; use middle::ty; use util::ppaux::{ty_to_str}; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::char; use core::cmp; use core::i8; @@ -108,7 +108,7 @@ struct LintSpec { default: level } -pub type LintDict = @LinearMap<~str, LintSpec>; +pub type LintDict = @HashMap<~str, LintSpec>; /* Pass names should not contain a '-', as the compiler normalizes @@ -273,7 +273,7 @@ pub fn get_lint_dict() -> LintDict { }), */ ]; - let mut map = LinearMap::new(); + let mut map = HashMap::new(); do vec::consume(v) |_, (k, v)| { map.insert(k, v); } @@ -282,7 +282,7 @@ pub fn get_lint_dict() -> LintDict { // This is a highly not-optimal set of data structure decisions. type LintModes = @mut SmallIntMap; -type LintModeMap = @mut LinearMap; +type LintModeMap = @mut HashMap; // settings_map maps node ids of items with non-default lint settings // to their settings; default_settings contains the settings for everything @@ -295,7 +295,7 @@ pub struct LintSettings { pub fn mk_lint_settings() -> LintSettings { LintSettings { default_settings: @mut SmallIntMap::new(), - settings_map: @mut LinearMap::new() + settings_map: @mut HashMap::new() } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a91404fb47a2a..01598b118518d 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -111,7 +111,7 @@ use middle::typeck; use middle::moves; use util::ppaux::ty_to_str; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::io::WriterUtil; use core::io; use core::ptr; @@ -134,7 +134,7 @@ use syntax::{visit, ast_util}; // // Very subtle (#2633): borrowck will remove entries from this table // if it detects an outstanding loan (that is, the addr is taken). -pub type last_use_map = @mut LinearMap; +pub type last_use_map = @mut HashMap; #[deriving(Eq)] struct Variable(uint); @@ -172,7 +172,7 @@ pub fn check_crate(tcx: ty::ctxt, .. *visit::default_visitor() }); - let last_use_map = @mut LinearMap::new(); + let last_use_map = @mut HashMap::new(); let initial_maps = @mut IrMaps(tcx, method_map, variable_moves_map, @@ -264,9 +264,9 @@ struct IrMaps { num_live_nodes: uint, num_vars: uint, - live_node_map: LinearMap, - variable_map: LinearMap, - capture_info_map: LinearMap, + live_node_map: HashMap, + variable_map: HashMap, + capture_info_map: HashMap, var_kinds: ~[VarKind], lnks: ~[LiveNodeKind], } @@ -285,9 +285,9 @@ fn IrMaps(tcx: ty::ctxt, last_use_map: last_use_map, num_live_nodes: 0, num_vars: 0, - live_node_map: LinearMap::new(), - variable_map: LinearMap::new(), - capture_info_map: LinearMap::new(), + live_node_map: HashMap::new(), + variable_map: HashMap::new(), + capture_info_map: HashMap::new(), var_kinds: ~[], lnks: ~[] } @@ -612,7 +612,7 @@ static ACC_READ: uint = 1u; static ACC_WRITE: uint = 2u; static ACC_USE: uint = 4u; -type LiveNodeMap = @mut LinearMap; +type LiveNodeMap = @mut HashMap; struct Liveness { tcx: ty::ctxt, @@ -639,8 +639,8 @@ fn Liveness(ir: @mut IrMaps, specials: Specials) -> Liveness { users: @mut vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users()), loop_scope: @mut ~[], - break_ln: @mut LinearMap::new(), - cont_ln: @mut LinearMap::new() + break_ln: @mut HashMap::new(), + cont_ln: @mut HashMap::new() } } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index de52d3e6878e9..2f379ece5d374 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -215,7 +215,7 @@ use middle::typeck::method_map; use util::ppaux; use util::common::indenter; -use core::hashmap::{LinearSet, LinearMap}; +use core::hashmap::{HashSet, HashMap}; use core::vec; use syntax::ast::*; use syntax::ast_util; @@ -240,14 +240,14 @@ pub struct CaptureVar { mode: CaptureMode // How variable is being accessed } -pub type CaptureMap = @mut LinearMap; +pub type CaptureMap = @mut HashMap; -pub type MovesMap = @mut LinearSet; +pub type MovesMap = @mut HashSet; /** * For each variable which will be moved, links to the * expression */ -pub type VariableMovesMap = @mut LinearMap; +pub type VariableMovesMap = @mut HashMap; /** See the section Output on the module comment for explanation. */ pub struct MoveMaps { @@ -280,9 +280,9 @@ pub fn compute_moves(tcx: ty::ctxt, tcx: tcx, method_map: method_map, move_maps: MoveMaps { - moves_map: @mut LinearSet::new(), - variable_moves_map: @mut LinearMap::new(), - capture_map: @mut LinearMap::new() + moves_map: @mut HashSet::new(), + variable_moves_map: @mut HashMap::new(), + capture_map: @mut HashMap::new() } }; visit::visit_crate(*crate, visit_cx, visitor); diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index db3f5acf9d590..2e2048b7ae4cd 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -12,17 +12,17 @@ use core::prelude::*; use middle::resolve; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use syntax::ast::*; use syntax::ast_util::{path_to_ident, walk_pat}; use syntax::codemap::span; -pub type PatIdMap = LinearMap; +pub type PatIdMap = HashMap; // This is used because same-named variables in alternative patterns need to // use the node_id of their namesake in the first pattern. pub fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> PatIdMap { - let mut map = LinearMap::new(); + let mut map = HashMap::new(); do pat_bindings(dm, pat) |_bm, p_id, _s, n| { map.insert(path_to_ident(n), p_id); }; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index e6e1990717254..75eb8ef1a8580 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -26,7 +26,7 @@ use middle::ty::{region_variance, rv_covariant, rv_invariant}; use middle::ty::{rv_contravariant}; use middle::ty; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::vec; use syntax::ast_map; use syntax::codemap::span; @@ -46,7 +46,7 @@ Encodes the bounding lifetime for a given AST node: - Variables and bindings are mapped to the block in which they are declared. */ -pub type region_map = @mut LinearMap; +pub type region_map = @mut HashMap; pub struct ctxt { sess: Session, @@ -62,7 +62,7 @@ pub struct ctxt { // the condition in a while loop is always a parent. In those // cases, we add the node id of such an expression to this set so // that when we visit it we can view it as a parent. - root_exprs: @mut LinearSet, + root_exprs: @mut HashSet, // The parent scope is the innermost block, statement, call, or match // expression during the execution of which the current expression @@ -350,8 +350,8 @@ pub fn resolve_crate(sess: Session, -> region_map { let cx: ctxt = ctxt {sess: sess, def_map: def_map, - region_map: @mut LinearMap::new(), - root_exprs: @mut LinearSet::new(), + region_map: @mut HashMap::new(), + root_exprs: @mut HashSet::new(), parent: None}; let visitor = visit::mk_vt(@visit::Visitor { visit_block: resolve_block, @@ -387,7 +387,7 @@ pub fn resolve_crate(sess: Session, // a worklist. We can then process the worklist, propagating indirect // dependencies until a fixed point is reached. -pub type region_paramd_items = @mut LinearMap; +pub type region_paramd_items = @mut HashMap; #[deriving(Eq)] pub struct region_dep { @@ -395,7 +395,7 @@ pub struct region_dep { id: ast::node_id } -pub type dep_map = @mut LinearMap; +pub type dep_map = @mut HashMap; pub struct DetermineRpCtxt { sess: Session, @@ -790,8 +790,8 @@ pub fn determine_rp_in_crate(sess: Session, sess: sess, ast_map: ast_map, def_map: def_map, - region_paramd_items: @mut LinearMap::new(), - dep_map: @mut LinearMap::new(), + region_paramd_items: @mut HashMap::new(), + dep_map: @mut HashMap::new(), worklist: ~[], item_id: 0, anon_implies_rp: false, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c4a6584dd66a3..08542301e238f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -77,10 +77,10 @@ use syntax::opt_vec::OptVec; use core::option::Some; use core::str::each_split_str; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; // Definition mapping -pub type DefMap = @mut LinearMap; +pub type DefMap = @mut HashMap; pub struct binding_info { span: span, @@ -88,7 +88,7 @@ pub struct binding_info { } // Map from the name in a pattern to its binding mode. -pub type BindingMap = LinearMap; +pub type BindingMap = HashMap; // Implementation resolution // @@ -109,11 +109,11 @@ pub struct Impl { } // Trait method resolution -pub type TraitMap = LinearMap; +pub type TraitMap = HashMap; // This is the replacement export map. It maps a module to all of the exports // within. -pub type ExportMap2 = @mut LinearMap; +pub type ExportMap2 = @mut HashMap; pub struct Export2 { name: @~str, // The name of the target. @@ -328,13 +328,13 @@ pub fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode) /// One local scope. pub struct Rib { - bindings: @mut LinearMap, + bindings: @mut HashMap, kind: RibKind, } pub fn Rib(kind: RibKind) -> Rib { Rib { - bindings: @mut LinearMap::new(), + bindings: @mut HashMap::new(), kind: kind } } @@ -450,12 +450,12 @@ pub struct Module { def_id: Option, kind: ModuleKind, - children: @mut LinearMap, + children: @mut HashMap, imports: @mut ~[@ImportDirective], // The external module children of this node that were declared with // `extern mod`. - external_module_children: @mut LinearMap, + external_module_children: @mut HashMap, // The anonymous children of this node. Anonymous children are pseudo- // modules that are implicitly created around items contained within @@ -472,10 +472,10 @@ pub struct Module { // There will be an anonymous module created around `g` with the ID of the // entry block for `f`. - anonymous_children: @mut LinearMap, + anonymous_children: @mut HashMap, // The status of resolving each import in this module. - import_resolutions: @mut LinearMap, + import_resolutions: @mut HashMap, // The number of unresolved globs that this module exports. glob_count: uint, @@ -492,11 +492,11 @@ pub fn Module(parent_link: ParentLink, parent_link: parent_link, def_id: def_id, kind: kind, - children: @mut LinearMap::new(), + children: @mut HashMap::new(), imports: @mut ~[], - external_module_children: @mut LinearMap::new(), - anonymous_children: @mut LinearMap::new(), - import_resolutions: @mut LinearMap::new(), + external_module_children: @mut HashMap::new(), + anonymous_children: @mut HashMap::new(), + import_resolutions: @mut HashMap::new(), glob_count: 0, resolved_import_count: 0 } @@ -707,7 +707,7 @@ pub fn NameBindings() -> NameBindings { /// Interns the names of the primitive types. pub struct PrimitiveTypeTable { - primitive_types: LinearMap, + primitive_types: HashMap, } pub impl PrimitiveTypeTable { @@ -720,7 +720,7 @@ pub impl PrimitiveTypeTable { pub fn PrimitiveTypeTable(intr: @ident_interner) -> PrimitiveTypeTable { let mut table = PrimitiveTypeTable { - primitive_types: LinearMap::new() + primitive_types: HashMap::new() }; table.intern(intr, @~"bool", ty_bool); @@ -775,8 +775,8 @@ pub fn Resolver(session: Session, graph_root: graph_root, - trait_info: LinearMap::new(), - structs: LinearSet::new(), + trait_info: HashMap::new(), + structs: HashSet::new(), unresolved_imports: 0, @@ -799,9 +799,9 @@ pub fn Resolver(session: Session, attr_main_fn: None, main_fns: ~[], - def_map: @mut LinearMap::new(), - export_map2: @mut LinearMap::new(), - trait_map: LinearMap::new(), + def_map: @mut HashMap::new(), + export_map2: @mut HashMap::new(), + trait_map: HashMap::new(), intr: session.intr() }; @@ -819,8 +819,8 @@ pub struct Resolver { graph_root: @mut NameBindings, - trait_info: LinearMap>, - structs: LinearSet, + trait_info: HashMap>, + structs: HashSet, // The number of imports that are currently unresolved. unresolved_imports: uint, @@ -1309,7 +1309,7 @@ pub impl Resolver { } // Add the names of all the methods to the trait info. - let mut method_names = LinearSet::new(); + let mut method_names = HashSet::new(); for methods.each |method| { let ty_m = trait_method_to_ty_method(method); @@ -1543,7 +1543,7 @@ pub impl Resolver { fn handle_external_def(@mut self, def: def, - modules: &mut LinearMap, + modules: &mut HashMap, child_name_bindings: @mut NameBindings, final_ident: &str, ident: ident, @@ -1623,7 +1623,7 @@ pub impl Resolver { // Nothing to do. } Some(method_names) => { - let mut interned_method_names = LinearSet::new(); + let mut interned_method_names = HashSet::new(); for method_names.each |method_data| { let (method_name, self_ty) = *method_data; debug!("(building reduced graph for \ @@ -1663,7 +1663,7 @@ pub impl Resolver { * crate. */ fn build_reduced_graph_for_external_crate(@mut self, root: @mut Module) { - let mut modules = LinearMap::new(); + let mut modules = HashMap::new(); // Create all the items reachable by paths. for each_path(self.session.cstore, root.def_id.get().crate) @@ -3906,7 +3906,7 @@ pub impl Resolver { } fn binding_mode_map(@mut self, pat: @pat) -> BindingMap { - let mut result = LinearMap::new(); + let mut result = HashMap::new(); do pat_bindings(self.def_map, pat) |binding_mode, _id, sp, path| { let ident = path_to_ident(path); result.insert(ident, @@ -3958,7 +3958,7 @@ pub impl Resolver { fn resolve_arm(@mut self, arm: &arm, visitor: ResolveVisitor) { self.value_ribs.push(@Rib(NormalRibKind)); - let bindings_list = @mut LinearMap::new(); + let bindings_list = @mut HashMap::new(); for arm.pats.each |pattern| { self.resolve_pattern(*pattern, RefutableMode, Immutable, Some(bindings_list), visitor); @@ -4078,7 +4078,7 @@ pub impl Resolver { mutability: Mutability, // Maps idents to the node ID for the (outermost) // pattern that binds them - bindings_list: Option<@mut LinearMap>, + bindings_list: Option<@mut HashMap>, visitor: ResolveVisitor) { let pat_id = pattern.id; do walk_pat(pattern) |pattern| { @@ -4282,7 +4282,7 @@ pub impl Resolver { } pat_struct(path, _, _) => { - let structs: &mut LinearSet = &mut self.structs; + let structs: &mut HashSet = &mut self.structs; match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) if structs.contains(&class_id) => { @@ -4791,7 +4791,7 @@ pub impl Resolver { expr_struct(path, _, _) => { // Resolve the path to the structure it goes to. - let structs: &mut LinearSet = &mut self.structs; + let structs: &mut HashSet = &mut self.structs; match self.resolve_path(path, TypeNS, false, visitor) { Some(def_ty(class_id)) | Some(def_struct(class_id)) if structs.contains(&class_id) => { diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 1b5273dd3d7d3..32c9189ad2d7d 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -167,7 +167,7 @@ use middle::trans::type_of; use middle::ty; use util::common::indenter; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use syntax::ast; use syntax::ast::ident; use syntax::ast_util::path_to_ident; @@ -323,7 +323,7 @@ pub struct BindingInfo { ty: ty::t, } -pub type BindingsMap = LinearMap; +pub type BindingsMap = HashMap; pub struct ArmData<'self> { bodycx: block, @@ -1620,7 +1620,7 @@ pub fn trans_match_inner(scope_cx: block, // to an alloca() that will be the value for that local variable. // Note that we use the names because each binding will have many ids // from the various alternatives. - let mut bindings_map = LinearMap::new(); + let mut bindings_map = HashMap::new(); do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, _s, path| { let ident = path_to_ident(path); let variable_ty = node_id_type(bcx, p_id); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 588690b055444..aa97c287b4c05 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -67,7 +67,7 @@ use util::ppaux::ty_to_str; use util::ppaux; use core::hash; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::int; use core::io; use core::libc::{c_uint, c_ulonglong}; @@ -1609,9 +1609,9 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, llself: None, personality: None, loop_ret: None, - llargs: @mut LinearMap::new(), - lllocals: @mut LinearMap::new(), - llupvars: @mut LinearMap::new(), + llargs: @mut HashMap::new(), + lllocals: @mut HashMap::new(), + llupvars: @mut HashMap::new(), id: id, impl_id: impl_id, param_substs: param_substs, @@ -2610,7 +2610,7 @@ pub fn p2i(ccx: @CrateContext, v: ValueRef) -> ValueRef { } } -pub fn declare_intrinsics(llmod: ModuleRef) -> LinearMap<~str, ValueRef> { +pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { let T_memcpy32_args: ~[TypeRef] = ~[T_ptr(T_i8()), T_ptr(T_i8()), T_i32(), T_i32(), T_i1()]; let T_memcpy64_args: ~[TypeRef] = @@ -2743,7 +2743,7 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> LinearMap<~str, ValueRef> { let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64", T_fn(~[T_i64()], T_i64())); - let mut intrinsics = LinearMap::new(); + let mut intrinsics = HashMap::new(); intrinsics.insert(~"llvm.gcroot", gcroot); intrinsics.insert(~"llvm.gcread", gcread); intrinsics.insert(~"llvm.memcpy.p0i8.p0i8.i32", memcpy32); @@ -2804,7 +2804,7 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> LinearMap<~str, ValueRef> { } pub fn declare_dbg_intrinsics(llmod: ModuleRef, - intrinsics: &mut LinearMap<~str, ValueRef>) { + intrinsics: &mut HashMap<~str, ValueRef>) { let declare = decl_cdecl_fn(llmod, ~"llvm.dbg.declare", T_fn(~[T_metadata(), T_metadata()], T_void())); @@ -3052,37 +3052,37 @@ pub fn trans_crate(sess: session::Session, llmod: llmod, td: td, tn: tn, - externs: @mut LinearMap::new(), + externs: @mut HashMap::new(), intrinsics: intrinsics, - item_vals: @mut LinearMap::new(), + item_vals: @mut HashMap::new(), exp_map2: emap2, reachable: reachable, - item_symbols: @mut LinearMap::new(), + item_symbols: @mut HashMap::new(), link_meta: link_meta, - enum_sizes: @mut LinearMap::new(), - discrims: @mut LinearMap::new(), - discrim_symbols: @mut LinearMap::new(), - tydescs: @mut LinearMap::new(), + enum_sizes: @mut HashMap::new(), + discrims: @mut HashMap::new(), + discrim_symbols: @mut HashMap::new(), + tydescs: @mut HashMap::new(), finished_tydescs: @mut false, - external: @mut LinearMap::new(), - monomorphized: @mut LinearMap::new(), - monomorphizing: @mut LinearMap::new(), - type_use_cache: @mut LinearMap::new(), - vtables: @mut LinearMap::new(), - const_cstr_cache: @mut LinearMap::new(), - const_globals: @mut LinearMap::new(), - const_values: @mut LinearMap::new(), - extern_const_values: @mut LinearMap::new(), - module_data: @mut LinearMap::new(), - lltypes: @mut LinearMap::new(), - llsizingtypes: @mut LinearMap::new(), - adt_reprs: @mut LinearMap::new(), + external: @mut HashMap::new(), + monomorphized: @mut HashMap::new(), + monomorphizing: @mut HashMap::new(), + type_use_cache: @mut HashMap::new(), + vtables: @mut HashMap::new(), + const_cstr_cache: @mut HashMap::new(), + const_globals: @mut HashMap::new(), + const_values: @mut HashMap::new(), + extern_const_values: @mut HashMap::new(), + module_data: @mut HashMap::new(), + lltypes: @mut HashMap::new(), + llsizingtypes: @mut HashMap::new(), + adt_reprs: @mut HashMap::new(), names: new_namegen(sess.parse_sess.interner), next_addrspace: new_addrspace_gen(), symbol_hasher: symbol_hasher, - type_hashcodes: @mut LinearMap::new(), - type_short_names: @mut LinearMap::new(), - all_llvm_symbols: @mut LinearSet::new(), + type_hashcodes: @mut HashMap::new(), + type_short_names: @mut HashMap::new(), + all_llvm_symbols: @mut HashSet::new(), tcx: tcx, maps: maps, stats: @mut Stats { @@ -3095,7 +3095,7 @@ pub fn trans_crate(sess: session::Session, n_inlines: 0u, n_closures: 0u, llvm_insn_ctxt: @mut ~[], - llvm_insns: @mut LinearMap::new(), + llvm_insns: @mut HashMap::new(), fn_times: @mut ~[] }, upcalls: upcall::declare_upcalls(targ_cfg, llmod), diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 234812e66d9db..fa2be2f415f95 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -18,7 +18,7 @@ use syntax::codemap::span; use core::prelude::*; use core::cast; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::libc::{c_uint, c_ulonglong, c_char}; use core::libc; use core::option::Some; @@ -55,7 +55,7 @@ pub fn count_insn(cx: block, category: &str) { // Build version of path with cycles removed. // Pass 1: scan table mapping str -> rightmost pos. - let mut mm = LinearMap::new(); + let mut mm = HashMap::new(); let len = vec::len(*v); let mut i = 0u; while i < len { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 04aca7b9dcdc4..f0c17a6f80d7b 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -45,7 +45,7 @@ use util::ppaux::{expr_repr, ty_to_str}; use core::cast; use core::hash; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::libc::{c_uint, c_longlong, c_ulonglong}; use core::ptr; use core::str; @@ -134,7 +134,7 @@ pub struct Stats { n_inlines: uint, n_closures: uint, llvm_insn_ctxt: @mut ~[~str], - llvm_insns: @mut LinearMap<~str, uint>, + llvm_insns: @mut HashMap<~str, uint>, fn_times: @mut ~[(~str, int)] // (ident, time) } @@ -156,7 +156,7 @@ pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { } } -pub type ExternMap = @mut LinearMap<@str, ValueRef>; +pub type ExternMap = @mut HashMap<@str, ValueRef>; // Crate context. Every crate we compile has one of these. pub struct CrateContext { @@ -165,30 +165,30 @@ pub struct CrateContext { td: TargetData, tn: @TypeNames, externs: ExternMap, - intrinsics: LinearMap<~str, ValueRef>, - item_vals: @mut LinearMap, + intrinsics: HashMap<~str, ValueRef>, + item_vals: @mut HashMap, exp_map2: resolve::ExportMap2, reachable: reachable::map, - item_symbols: @mut LinearMap, + item_symbols: @mut HashMap, link_meta: LinkMeta, - enum_sizes: @mut LinearMap, - discrims: @mut LinearMap, - discrim_symbols: @mut LinearMap, - tydescs: @mut LinearMap, + enum_sizes: @mut HashMap, + discrims: @mut HashMap, + discrim_symbols: @mut HashMap, + tydescs: @mut HashMap, // Set when running emit_tydescs to enforce that no more tydescs are // created. finished_tydescs: @mut bool, // Track mapping of external ids to local items imported for inlining - external: @mut LinearMap>, + external: @mut HashMap>, // Cache instances of monomorphized functions - monomorphized: @mut LinearMap, - monomorphizing: @mut LinearMap, + monomorphized: @mut HashMap, + monomorphizing: @mut HashMap, // Cache computed type parameter uses (see type_use.rs) - type_use_cache: @mut LinearMap, + type_use_cache: @mut HashMap, // Cache generated vtables - vtables: @mut LinearMap, + vtables: @mut HashMap, // Cache of constant strings, - const_cstr_cache: @mut LinearMap<@~str, ValueRef>, + const_cstr_cache: @mut HashMap<@~str, ValueRef>, // Reverse-direction for const ptrs cast from globals. // Key is an int, cast from a ValueRef holding a *T, @@ -198,24 +198,24 @@ pub struct CrateContext { // when we ptrcast, and we have to ptrcast during translation // of a [T] const because we form a slice, a [*T,int] pair, not // a pointer to an LLVM array type. - const_globals: @mut LinearMap, + const_globals: @mut HashMap, // Cache of emitted const values - const_values: @mut LinearMap, + const_values: @mut HashMap, // Cache of external const values - extern_const_values: @mut LinearMap, + extern_const_values: @mut HashMap, - module_data: @mut LinearMap<~str, ValueRef>, - lltypes: @mut LinearMap, - llsizingtypes: @mut LinearMap, - adt_reprs: @mut LinearMap, + module_data: @mut HashMap<~str, ValueRef>, + lltypes: @mut HashMap, + llsizingtypes: @mut HashMap, + adt_reprs: @mut HashMap, names: namegen, next_addrspace: addrspace_gen, symbol_hasher: @hash::State, - type_hashcodes: @mut LinearMap, - type_short_names: @mut LinearMap, - all_llvm_symbols: @mut LinearSet<~str>, + type_hashcodes: @mut HashMap, + type_short_names: @mut HashMap, + all_llvm_symbols: @mut HashSet<~str>, tcx: ty::ctxt, maps: astencode::Maps, stats: @mut Stats, @@ -314,12 +314,12 @@ pub struct fn_ctxt_ { loop_ret: Option<(ValueRef, ValueRef)>, // Maps arguments to allocas created for them in llallocas. - llargs: @mut LinearMap, + llargs: @mut HashMap, // Maps the def_ids for local variables to the allocas created for // them in llallocas. - lllocals: @mut LinearMap, + lllocals: @mut HashMap, // Same as above, but for closure upvars - llupvars: @mut LinearMap, + llupvars: @mut HashMap, // The node_id of the function, or -1 if it doesn't correspond to // a user-defined function. diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 69a70c5a2fd51..277d529c8462f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -20,7 +20,7 @@ use middle::trans; use middle::ty; use util::ppaux::ty_to_str; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::libc; use core::option; use core::sys; @@ -106,7 +106,7 @@ pub struct DebugContext { pub fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> DebugContext { DebugContext { - llmetadata: @mut LinearMap::new(), + llmetadata: @mut HashMap::new(), names: new_namegen(intr), crate_file: crate } @@ -151,7 +151,7 @@ struct RetvalMetadata { id: ast::node_id } -type metadata_cache = @mut LinearMap; +type metadata_cache = @mut HashMap; enum debug_metadata { file_metadata(@Metadata), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 616a25d3c164f..5afdd1b027188 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -153,7 +153,7 @@ use util::common::indenter; use util::ppaux::ty_to_str; use core::cast::transmute; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use syntax::print::pprust::{expr_to_str}; use syntax::ast; use syntax::codemap; @@ -1091,7 +1091,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { }; fn take_local(bcx: block, - table: &LinearMap, + table: &HashMap, nid: ast::node_id) -> Datum { let (v, mode) = match table.find(&nid) { Some(&local_mem(v)) => (v, ByRef), diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index fd0eb9667098b..9f9323bf9f788 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -21,7 +21,7 @@ use middle::ty; use middle::typeck; use core::prelude::*; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use syntax::ast; use syntax::ast::*; use syntax::ast_util::def_id_of_def; @@ -30,18 +30,18 @@ use syntax::codemap; use syntax::print::pprust::expr_to_str; use syntax::{visit, ast_map}; -pub type map = @LinearSet; +pub type map = @HashSet; struct ctx<'self> { exp_map2: resolve::ExportMap2, tcx: ty::ctxt, method_map: typeck::method_map, - rmap: &'self mut LinearSet, + rmap: &'self mut HashSet, } pub fn find_reachable(crate_mod: &_mod, exp_map2: resolve::ExportMap2, tcx: ty::ctxt, method_map: typeck::method_map) -> map { - let mut rmap = LinearSet::new(); + let mut rmap = HashSet::new(); { let cx = ctx { exp_map2: exp_map2, @@ -96,7 +96,7 @@ fn traverse_public_mod(cx: ctx, mod_id: node_id, m: &_mod) { fn traverse_public_item(cx: ctx, item: @item) { // XXX: it shouldn't be necessary to do this - let rmap: &mut LinearSet = cx.rmap; + let rmap: &mut HashSet = cx.rmap; if rmap.contains(&item.id) { return; } rmap.insert(item.id); match item.node { @@ -154,7 +154,7 @@ fn mk_ty_visitor() -> visit::vt { fn traverse_ty<'a>(ty: @Ty, cx: ctx<'a>, v: visit::vt>) { // XXX: it shouldn't be necessary to do this - let rmap: &mut LinearSet = cx.rmap; + let rmap: &mut HashSet = cx.rmap; if rmap.contains(&ty.id) { return; } rmap.insert(ty.id); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2b00bd0c71246..30b933061e215 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -36,7 +36,7 @@ use core::result; use core::to_bytes; use core::uint; use core::vec; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use std::smallintmap::SmallIntMap; use syntax::ast::*; use syntax::ast_util::{is_local, local_def}; @@ -119,7 +119,7 @@ pub struct creader_cache_key { len: uint } -type creader_cache = @mut LinearMap; +type creader_cache = @mut HashMap; impl to_bytes::IterBytes for creader_cache_key { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { @@ -210,7 +210,7 @@ pub enum AutoRefKind { // This is a map from ID of each implementation to the method info and trait // method ID of each of the default methods belonging to the trait that that // implementation implements. -pub type ProvidedMethodsMap = @mut LinearMap; +pub type ProvidedMethodsMap = @mut HashMap; // Stores the method info and definition ID of the associated trait method for // each instantiation of each provided method. @@ -233,7 +233,7 @@ pub type ctxt = @ctxt_; struct ctxt_ { diag: @syntax::diagnostic::span_handler, - interner: @mut LinearMap, + interner: @mut HashMap, next_id: @mut uint, vecs_implicitly_copyable: bool, legacy_modes: bool, @@ -253,43 +253,43 @@ struct ctxt_ { // of this node. This only applies to nodes that refer to entities // parameterized by type parameters, such as generic fns, types, or // other items. - node_type_substs: @mut LinearMap, + node_type_substs: @mut HashMap, items: ast_map::map, - intrinsic_defs: @mut LinearMap, + intrinsic_defs: @mut HashMap, freevars: freevars::freevar_map, tcache: type_cache, rcache: creader_cache, ccache: constness_cache, - short_names_cache: @mut LinearMap, - needs_unwind_cleanup_cache: @mut LinearMap, - tc_cache: @mut LinearMap, - ast_ty_to_ty_cache: @mut LinearMap, - enum_var_cache: @mut LinearMap, - trait_method_cache: @mut LinearMap, - ty_param_bounds: @mut LinearMap, - inferred_modes: @mut LinearMap, - adjustments: @mut LinearMap, - normalized_cache: @mut LinearMap, + short_names_cache: @mut HashMap, + needs_unwind_cleanup_cache: @mut HashMap, + tc_cache: @mut HashMap, + ast_ty_to_ty_cache: @mut HashMap, + enum_var_cache: @mut HashMap, + trait_method_cache: @mut HashMap, + ty_param_bounds: @mut HashMap, + inferred_modes: @mut HashMap, + adjustments: @mut HashMap, + normalized_cache: @mut HashMap, lang_items: middle::lang_items::LanguageItems, // A mapping from an implementation ID to the method info and trait // method ID of the provided (a.k.a. default) methods in the traits that // that implementation implements. provided_methods: ProvidedMethodsMap, - provided_method_sources: @mut LinearMap, - supertraits: @mut LinearMap, + provided_method_sources: @mut HashMap, + supertraits: @mut HashMap, // A mapping from the def ID of an enum or struct type to the def ID // of the method that implements its destructor. If the type is not // present in this map, it does not have a destructor. This map is // populated during the coherence phase of typechecking. - destructor_for_type: @mut LinearMap, + destructor_for_type: @mut HashMap, // A method will be in this list if and only if it is a destructor. - destructors: @mut LinearSet, + destructors: @mut HashSet, // Maps a trait onto a mapping from self-ty to impl - trait_impls: @mut LinearMap> + trait_impls: @mut HashMap> } enum tbox_flag { @@ -771,18 +771,18 @@ pub struct ty_param_substs_and_ty { ty: ty::t } -type type_cache = @mut LinearMap; +type type_cache = @mut HashMap; -type constness_cache = @mut LinearMap; +type constness_cache = @mut HashMap; pub type node_type_table = @mut SmallIntMap; fn mk_rcache() -> creader_cache { - return @mut LinearMap::new(); + return @mut HashMap::new(); } -pub fn new_ty_hash() -> @mut LinearMap { - @mut LinearMap::new() +pub fn new_ty_hash() -> @mut HashMap { + @mut HashMap::new() } pub fn mk_ctxt(s: session::Session, @@ -809,7 +809,7 @@ pub fn mk_ctxt(s: session::Session, lint::vecs_implicitly_copyable) == allow; @ctxt_ { diag: s.diagnostic(), - interner: @mut LinearMap::new(), + interner: @mut HashMap::new(), next_id: @mut 0, vecs_implicitly_copyable: vecs_implicitly_copyable, legacy_modes: legacy_modes, @@ -819,30 +819,30 @@ pub fn mk_ctxt(s: session::Session, region_map: region_map, region_paramd_items: region_paramd_items, node_types: @mut SmallIntMap::new(), - node_type_substs: @mut LinearMap::new(), + node_type_substs: @mut HashMap::new(), items: amap, - intrinsic_defs: @mut LinearMap::new(), + intrinsic_defs: @mut HashMap::new(), freevars: freevars, - tcache: @mut LinearMap::new(), + tcache: @mut HashMap::new(), rcache: mk_rcache(), - ccache: @mut LinearMap::new(), + ccache: @mut HashMap::new(), short_names_cache: new_ty_hash(), needs_unwind_cleanup_cache: new_ty_hash(), - tc_cache: @mut LinearMap::new(), - ast_ty_to_ty_cache: @mut LinearMap::new(), - enum_var_cache: @mut LinearMap::new(), - trait_method_cache: @mut LinearMap::new(), - ty_param_bounds: @mut LinearMap::new(), - inferred_modes: @mut LinearMap::new(), - adjustments: @mut LinearMap::new(), + tc_cache: @mut HashMap::new(), + ast_ty_to_ty_cache: @mut HashMap::new(), + enum_var_cache: @mut HashMap::new(), + trait_method_cache: @mut HashMap::new(), + ty_param_bounds: @mut HashMap::new(), + inferred_modes: @mut HashMap::new(), + adjustments: @mut HashMap::new(), normalized_cache: new_ty_hash(), lang_items: lang_items, - provided_methods: @mut LinearMap::new(), - provided_method_sources: @mut LinearMap::new(), - supertraits: @mut LinearMap::new(), - destructor_for_type: @mut LinearMap::new(), - destructors: @mut LinearSet::new(), - trait_impls: @mut LinearMap::new() + provided_methods: @mut HashMap::new(), + provided_method_sources: @mut HashMap::new(), + supertraits: @mut HashMap::new(), + destructor_for_type: @mut HashMap::new(), + destructors: @mut HashSet::new(), + trait_impls: @mut HashMap::new() } } @@ -1620,7 +1620,7 @@ pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool { None => () } - let mut tycache = LinearSet::new(); + let mut tycache = HashSet::new(); let needs_unwind_cleanup = type_needs_unwind_cleanup_(cx, ty, &mut tycache, false); cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup); @@ -1628,7 +1628,7 @@ pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool { } fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, - tycache: &mut LinearSet, + tycache: &mut HashSet, encountered_box: bool) -> bool { // Prevent infinite recursion @@ -1855,14 +1855,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { None => {} } - let mut cache = LinearMap::new(); + let mut cache = HashMap::new(); let result = tc_ty(cx, ty, &mut cache); cx.tc_cache.insert(ty_id, result); return result; fn tc_ty(cx: ctxt, ty: t, - cache: &mut LinearMap) -> TypeContents + cache: &mut HashMap) -> TypeContents { // Subtle: Note that we are *not* using cx.tc_cache here but rather a // private cache for this walk. This is needed in the case of cyclic @@ -2054,7 +2054,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { fn tc_mt(cx: ctxt, mt: mt, - cache: &mut LinearMap) -> TypeContents + cache: &mut HashMap) -> TypeContents { let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE}; mc + tc_ty(cx, mt.ty, cache) @@ -3258,7 +3258,7 @@ pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { // Maintains a little union-set tree for inferred modes. `canon()` returns // the current head value for `m0`. -fn canon(tbl: &mut LinearMap>, +fn canon(tbl: &mut HashMap>, +m0: ast::inferable) -> ast::inferable { match m0 { ast::infer(id) => { @@ -4286,7 +4286,7 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt, } }; - let mut supertrait_map = LinearMap::new(); + let mut supertrait_map = HashMap::new(); let mut seen_def_ids = ~[]; let mut i = 0; let trait_ty_id = ty_to_def_id(bound_trait_ty).expect( diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index dd1dcbe67b94a..f2d0ef22970b4 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -18,7 +18,7 @@ use middle::typeck::check::{instantiate_path, lookup_def}; use middle::typeck::check::{structure_of, valid_range_bounds}; use middle::typeck::require_same_types; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::vec; use syntax::ast; use syntax::ast_util; @@ -228,7 +228,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, /// `class_fields` describes the type of each field of the struct. /// `class_id` is the ID of the struct. /// `substitutions` are the type substitutions applied to this struct type -/// (e.g. K,V in LinearMap). +/// (e.g. K,V in HashMap). /// `etc` is true if the pattern said '...' and false otherwise. pub fn check_struct_pat_fields(pcx: pat_ctxt, span: span, @@ -241,13 +241,13 @@ pub fn check_struct_pat_fields(pcx: pat_ctxt, let tcx = pcx.fcx.ccx.tcx; // Index the class fields. - let mut field_map = LinearMap::new(); + let mut field_map = HashMap::new(); for class_fields.eachi |i, class_field| { field_map.insert(class_field.ident, i); } // Typecheck each field. - let mut found_fields = LinearSet::new(); + let mut found_fields = HashSet::new(); for fields.each |field| { match field_map.find(&field.ident) { Some(&index) => { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 8f7e8478f8adb..3b01f0e839ab9 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -95,7 +95,7 @@ use middle::typeck::{method_self, method_static, method_trait, method_super}; use util::common::indenter; use util::ppaux::expr_repr; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use core::result; use core::uint; use core::vec; @@ -131,7 +131,7 @@ pub fn lookup( check_traits: CheckTraitsFlag, // Whether we check traits only. autoderef_receiver: AutoderefReceiverFlag) -> Option { - let mut impl_dups = LinearSet::new(); + let mut impl_dups = HashSet::new(); let lcx = LookupContext { fcx: fcx, expr: expr, @@ -159,7 +159,7 @@ pub struct LookupContext<'self> { callee_id: node_id, m_name: ast::ident, supplied_tps: &'self [ty::t], - impl_dups: &'self mut LinearSet, + impl_dups: &'self mut HashSet, inherent_candidates: @mut ~[Candidate], extension_candidates: @mut ~[Candidate], deref_args: check::DerefArgs, diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 1c144b294d219..eba207f978b6e 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -110,7 +110,7 @@ use util::common::{block_query, indenter, loop_query}; use util::ppaux::{bound_region_to_str, expr_repr, pat_repr}; use util::ppaux; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::ptr; use core::result::{Result, Ok, Err}; use core::result; @@ -158,12 +158,12 @@ pub struct SelfInfo { /// share the inherited fields. pub struct inherited { infcx: @mut infer::InferCtxt, - locals: @mut LinearMap, + locals: @mut HashMap, // Temporary tables: - node_types: @mut LinearMap, - node_type_substs: @mut LinearMap, - adjustments: @mut LinearMap, + node_types: @mut HashMap, + node_type_substs: @mut HashMap, + adjustments: @mut HashMap, method_map: method_map, vtable_map: vtable_map, } @@ -220,12 +220,12 @@ pub struct FnCtxt { pub fn blank_inherited(ccx: @mut CrateCtxt) -> @inherited { @inherited { infcx: infer::new_infer_ctxt(ccx.tcx), - locals: @mut LinearMap::new(), - node_types: @mut LinearMap::new(), - node_type_substs: @mut LinearMap::new(), - adjustments: @mut LinearMap::new(), - method_map: @mut LinearMap::new(), - vtable_map: @mut LinearMap::new(), + locals: @mut HashMap::new(), + node_types: @mut HashMap::new(), + node_type_substs: @mut HashMap::new(), + adjustments: @mut HashMap::new(), + method_map: @mut HashMap::new(), + vtable_map: @mut HashMap::new(), } } @@ -504,7 +504,7 @@ pub fn check_method(ccx: @mut CrateCtxt, pub fn check_no_duplicate_fields(tcx: ty::ctxt, fields: ~[(ast::ident, span)]) { - let mut field_names = LinearMap::new(); + let mut field_names = HashMap::new(); for fields.each |p| { let (id, sp) = *p; @@ -1761,7 +1761,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, check_completeness: bool) { let tcx = fcx.ccx.tcx; - let mut class_field_map = LinearMap::new(); + let mut class_field_map = HashMap::new(); let mut fields_found = 0; for field_types.each |field| { // XXX: Check visibility here. diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index ddce274c54207..51f54d21ec4af 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -28,7 +28,7 @@ use core::result::{Ok, Err}; use core::result; use core::uint; use core::vec; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; @@ -234,7 +234,7 @@ pub fn lookup_vtable(vcx: &VtableContext, _ => { let mut found = ~[]; - let mut impls_seen = LinearSet::new(); + let mut impls_seen = HashSet::new(); match vcx.ccx.coherence_info.extension_methods.find(&trait_id) { None => { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 9f4984e02a603..466cb8ed54f2b 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -53,7 +53,7 @@ use syntax::visit::{visit_mod}; use util::ppaux::ty_to_str; use core::result::Ok; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::uint; pub struct UniversalQuantificationResult { @@ -164,17 +164,17 @@ pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo { pub struct CoherenceInfo { // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. - inherent_methods: @mut LinearMap, + inherent_methods: @mut HashMap, // Contains implementations of methods associated with a trait. For these, // the associated trait must be imported at the call site. - extension_methods: @mut LinearMap, + extension_methods: @mut HashMap, } pub fn CoherenceInfo() -> CoherenceInfo { CoherenceInfo { - inherent_methods: @mut LinearMap::new(), - extension_methods: @mut LinearMap::new(), + inherent_methods: @mut HashMap::new(), + extension_methods: @mut HashMap::new(), } } @@ -183,7 +183,7 @@ pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker { crate_context: crate_context, inference_context: new_infer_ctxt(crate_context.tcx), - base_type_def_ids: @mut LinearMap::new(), + base_type_def_ids: @mut HashMap::new(), } } @@ -194,7 +194,7 @@ pub struct CoherenceChecker { // A mapping from implementations to the corresponding base type // definition ID. - base_type_def_ids: @mut LinearMap, + base_type_def_ids: @mut HashMap, } pub impl CoherenceChecker { @@ -471,7 +471,7 @@ pub impl CoherenceChecker { ty_to_str(self.crate_context.tcx, self_t)); match self.crate_context.tcx.trait_impls.find(&trait_t) { None => { - let m = @mut LinearMap::new(); + let m = @mut HashMap::new(); m.insert(self_t, the_impl); self.crate_context.tcx.trait_impls.insert(trait_t, m); } @@ -501,7 +501,7 @@ pub impl CoherenceChecker { f: &fn(x: &ty::method) -> bool) { // Make a list of all the names of the provided methods. // XXX: This is horrible. - let mut provided_method_idents = LinearSet::new(); + let mut provided_method_idents = HashSet::new(); let tcx = self.crate_context.tcx; for ty::provided_trait_methods(tcx, trait_did).each |ident| { provided_method_idents.insert(*ident); @@ -705,7 +705,7 @@ pub impl CoherenceChecker { let tcx = self.crate_context.tcx; - let mut provided_names = LinearSet::new(); + let mut provided_names = HashSet::new(); // Implemented methods for uint::range(0, all_methods.len()) |i| { provided_names.insert(all_methods[i].ident); @@ -812,7 +812,7 @@ pub impl CoherenceChecker { // External crate handling - fn add_impls_for_module(&self, impls_seen: &mut LinearSet, + fn add_impls_for_module(&self, impls_seen: &mut HashSet, crate_store: @mut CStore, module_def_id: def_id) { let implementations = get_impls_for_mod(crate_store, @@ -931,7 +931,7 @@ pub impl CoherenceChecker { // Adds implementations and traits from external crates to the coherence // info. fn add_external_crates(&self) { - let mut impls_seen = LinearSet::new(); + let mut impls_seen = HashSet::new(); let crate_store = self.crate_context.tcx.sess.cstore; do iter_crate_data(crate_store) |crate_number, _crate_metadata| { diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index b190a98f8cd08..98d12bea6a429 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -548,7 +548,7 @@ use util::common::indenter; use util::ppaux::note_and_explain_region; use core::cell::{Cell, empty_cell}; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::result::{Err, Ok}; use core::to_bytes; use core::uint; @@ -600,12 +600,12 @@ enum CombineMapType { Lub, Glb } -type CombineMap = LinearMap; +type CombineMap = HashMap; pub struct RegionVarBindings { tcx: ty::ctxt, var_spans: ~[span], - constraints: LinearMap, + constraints: HashMap, lubs: CombineMap, glbs: CombineMap, skolemization_count: uint, @@ -632,9 +632,9 @@ pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings { tcx: tcx, var_spans: ~[], values: empty_cell(), - constraints: LinearMap::new(), - lubs: LinearMap::new(), - glbs: LinearMap::new(), + constraints: HashMap::new(), + lubs: HashMap::new(), + glbs: HashMap::new(), skolemization_count: 0, bound_count: 0, undo_log: ~[] @@ -1194,7 +1194,7 @@ struct SpannedRegion { span: span, } -type TwoRegionsMap = LinearSet; +type TwoRegionsMap = HashSet; pub impl RegionVarBindings { fn infer_variable_values(&mut self) -> ~[GraphNodeValue] { @@ -1423,7 +1423,7 @@ pub impl RegionVarBindings { &mut self, graph: &Graph) -> ~[GraphNodeValue] { - let mut dup_map = LinearSet::new(); + let mut dup_map = HashSet::new(); graph.nodes.mapi(|idx, node| { match node.value { Value(_) => { @@ -1598,7 +1598,7 @@ pub impl RegionVarBindings { orig_node_idx: RegionVid, dir: Direction) -> ~[SpannedRegion] { - let mut set = LinearSet::new(); + let mut set = HashSet::new(); let mut stack = ~[orig_node_idx]; set.insert(orig_node_idx.to_uint()); let mut result = ~[]; diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 1a0a1fceb52a8..d829b0d2a0d51 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -55,7 +55,7 @@ use middle::ty; use util::common::time; use util::ppaux; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::result; use core::vec; use std::list::List; @@ -129,7 +129,7 @@ pub struct method_map_entry { // maps from an expression id that corresponds to a method call to the details // of the method to be invoked -pub type method_map = @mut LinearMap; +pub type method_map = @mut HashMap; // Resolutions for bounds of all parameters, left to right, for a given path. pub type vtable_res = @~[vtable_origin]; @@ -170,7 +170,7 @@ pub impl vtable_origin { } } -pub type vtable_map = @mut LinearMap; +pub type vtable_map = @mut HashMap; pub struct CrateCtxt { // A mapping from method call sites to traits that have that method. @@ -342,8 +342,8 @@ pub fn check_crate(tcx: ty::ctxt, let time_passes = tcx.sess.time_passes(); let ccx = @mut CrateCtxt { trait_map: trait_map, - method_map: @mut LinearMap::new(), - vtable_map: @mut LinearMap::new(), + method_map: @mut HashMap::new(), + vtable_map: @mut HashMap::new(), coherence_info: @coherence::CoherenceInfo(), tcx: tcx }; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 98eff8b50d14d..30152c2284574 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -14,7 +14,7 @@ use syntax::ast; use syntax::codemap::{span}; use syntax::visit; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use core::str; use std; @@ -114,7 +114,7 @@ pub fn pluralize(n: uint, +s: ~str) -> ~str { } // A set of node IDs (used to keep track of which node IDs are for statements) -pub type stmt_set = @mut LinearSet; +pub type stmt_set = @mut HashSet; // // Local Variables: diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 2f1d25425ec2b..bf1301868af54 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -28,7 +28,7 @@ extern mod syntax(vers = "0.6"); use core::*; use core::container::Map; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::io::WriterUtil; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; @@ -253,7 +253,7 @@ impl PackageScript { struct Ctx { cfgs: ~[~str], json: bool, - dep_cache: @mut LinearMap<~str, bool> + dep_cache: @mut HashMap<~str, bool> } impl Ctx { @@ -483,14 +483,14 @@ impl Ctx { if self.json { match PackageScript::parse(&os::getcwd()) { result::Ok(script) => { - let mut map = ~LinearMap::new(); + let mut map = ~HashMap::new(); map.insert(~"id", json::String(script.id)); map.insert(~"name", json::String(script.name)); map.insert(~"vers", json::String(script.vers.to_str())); map.insert(~"deps", json::List(do script.deps.map |&dep| { let (url, target) = dep; - let mut inner = ~LinearMap::new(); + let mut inner = ~HashMap::new(); inner.insert(~"url", json::String(url)); @@ -921,7 +921,7 @@ pub fn main() { Ctx { cfgs: cfgs, json: json, - dep_cache: @mut LinearMap::new() + dep_cache: @mut HashMap::new() }.run(cmd, args); } diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 15546e96653d8..9d3751c3de297 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -10,7 +10,7 @@ use core::*; use core::hash::Streaming; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; @@ -337,7 +337,7 @@ fn _add_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] { } } - let mut map = ~LinearMap::new(); + let mut map = ~HashMap::new(); map.insert(~"id", json::String(pkg.id)); map.insert(~"vers", json::String(pkg.vers.to_str())); diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 1b79708e59017..f426b74736ad3 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -16,7 +16,7 @@ use core::prelude::*; use core::io::{WriterUtil, ReaderUtil}; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use serialize::Encodable; use serialize; @@ -33,7 +33,7 @@ pub enum Json { } pub type List = ~[Json]; -pub type Object = LinearMap<~str, Json>; +pub type Object = HashMap<~str, Json>; #[deriving(Eq)] pub struct Error { @@ -677,7 +677,7 @@ priv impl Parser { self.bump(); self.parse_whitespace(); - let mut values = ~LinearMap::new(); + let mut values = ~HashMap::new(); if self.ch == '}' { self.bump(); @@ -1127,9 +1127,9 @@ impl ToJson for ~[A] { fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) } } -impl ToJson for LinearMap<~str, A> { +impl ToJson for HashMap<~str, A> { fn to_json(&self) -> Json { - let mut d = LinearMap::new(); + let mut d = HashMap::new(); for self.each |&(key, value)| { d.insert(copy *key, value.to_json()); } @@ -1161,7 +1161,7 @@ mod tests { use super::*; use core::prelude::*; - use core::hashmap::LinearMap; + use core::hashmap::HashMap; use std::serialize::Decodable; @@ -1190,7 +1190,7 @@ mod tests { } fn mk_object(items: &[(~str, Json)]) -> Json { - let mut d = ~LinearMap::new(); + let mut d = ~HashMap::new(); for items.each |item| { match *item { @@ -1755,7 +1755,7 @@ mod tests { fn test_decode_map() { let s = ~"{\"a\": \"Dog\", \"b\": [\"Frog\", \"Henry\", 349]}"; let decoder = Decoder(from_str(s).unwrap()); - let mut map: LinearMap<~str, Animal> = Decodable::decode(&decoder); + let mut map: HashMap<~str, Animal> = Decodable::decode(&decoder); assert_eq!(map.pop(&~"a"), Some(Dog)); assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349))); diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index b32a9841ac6c1..81598f17aed16 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -17,7 +17,7 @@ use core::from_str::FromStr; use core::io::{Reader, ReaderUtil}; use core::io; use core::prelude::*; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::str; use core::to_bytes::IterBytes; use core::to_bytes; @@ -212,7 +212,7 @@ fn encode_plus(s: &str) -> ~str { /** * Encode a hashmap to the 'application/x-www-form-urlencoded' media type. */ -pub fn encode_form_urlencoded(m: &LinearMap<~str, ~[~str]>) -> ~str { +pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str { let mut out = ~""; let mut first = true; @@ -238,9 +238,9 @@ pub fn encode_form_urlencoded(m: &LinearMap<~str, ~[~str]>) -> ~str { * Decode a string encoded with the 'application/x-www-form-urlencoded' media * type into a hashmap. */ -pub fn decode_form_urlencoded(s: &[u8]) -> LinearMap<~str, ~[~str]> { +pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> { do io::with_bytes_reader(s) |rdr| { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); let mut key = ~""; let mut value = ~""; let mut parsing_key = true; @@ -818,7 +818,7 @@ mod tests { use net_url::*; - use core::hashmap::LinearMap; + use core::hashmap::HashMap; #[test] pub fn test_url_parse() { @@ -1053,18 +1053,18 @@ mod tests { #[test] pub fn test_encode_form_urlencoded() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); assert!(encode_form_urlencoded(&m) == ~""); m.insert(~"", ~[]); m.insert(~"foo", ~[]); assert!(encode_form_urlencoded(&m) == ~""); - let mut m = LinearMap::new(); + let mut m = HashMap::new(); m.insert(~"foo", ~[~"bar", ~"123"]); assert!(encode_form_urlencoded(&m) == ~"foo=bar&foo=123"); - let mut m = LinearMap::new(); + let mut m = HashMap::new(); m.insert(~"foo bar", ~[~"abc", ~"12 = 34"]); assert!(encode_form_urlencoded(&m) == ~"foo+bar=abc&foo+bar=12+%3D+34"); diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 88ae58ee01b4c..e1ab59fb2b3ae 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -17,7 +17,7 @@ Core encoding and decoding interfaces. #[forbid(non_camel_case_types)]; use core::prelude::*; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::trie::{TrieMap, TrieSet}; use deque::Deque; use dlist::DList; @@ -591,7 +591,7 @@ impl< E: Encoder, K: Encodable + Hash + IterBytes + Eq, V: Encodable -> Encodable for LinearMap { +> Encodable for HashMap { fn encode(&self, e: &E) { do e.emit_map(self.len()) { let mut i = 0; @@ -608,10 +608,10 @@ impl< D: Decoder, K: Decodable + Hash + IterBytes + Eq, V: Decodable -> Decodable for LinearMap { - fn decode(d: &D) -> LinearMap { +> Decodable for HashMap { + fn decode(d: &D) -> HashMap { do d.read_map |len| { - let mut map = LinearMap::with_capacity(len); + let mut map = HashMap::with_capacity(len); for uint::range(0, len) |i| { let key = d.read_map_elt_key(i, || Decodable::decode(d)); let val = d.read_map_elt_val(i, || Decodable::decode(d)); @@ -625,7 +625,7 @@ impl< impl< S: Encoder, T: Encodable + Hash + IterBytes + Eq -> Encodable for LinearSet { +> Encodable for HashSet { fn encode(&self, s: &S) { do s.emit_seq(self.len()) { let mut i = 0; @@ -640,10 +640,10 @@ impl< impl< D: Decoder, T: Decodable + Hash + IterBytes + Eq -> Decodable for LinearSet { - fn decode(d: &D) -> LinearSet { +> Decodable for HashSet { + fn decode(d: &D) -> HashSet { do d.read_seq |len| { - let mut set = LinearSet::with_capacity(len); + let mut set = HashSet::with_capacity(len); for uint::range(0, len) |i| { set.insert(d.read_seq_elt(i, || Decodable::decode(d))); } diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index 6886d5d630e19..3e494d0236e97 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -24,7 +24,7 @@ use core::pipes::recv; use core::prelude::*; use core::result; use core::run; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::task; use core::to_bytes; @@ -136,10 +136,10 @@ pub impl WorkKey { } } -struct WorkMap(LinearMap); +struct WorkMap(HashMap); impl WorkMap { - fn new() -> WorkMap { WorkMap(LinearMap::new()) } + fn new() -> WorkMap { WorkMap(HashMap::new()) } } impl Encodable for WorkMap { @@ -166,7 +166,7 @@ impl Decodable for WorkMap { struct Database { db_filename: Path, - db_cache: LinearMap<~str, ~str>, + db_cache: HashMap<~str, ~str>, db_dirty: bool } @@ -212,7 +212,7 @@ struct Context { db: @mut Database, logger: @mut Logger, cfg: @json::Object, - freshness: LinearMap<~str,@fn(&str,&str)->bool> + freshness: HashMap<~str,@fn(&str,&str)->bool> } struct Prep { @@ -267,7 +267,7 @@ pub impl Context { db: db, logger: lg, cfg: cfg, - freshness: LinearMap::new() + freshness: HashMap::new() } } @@ -411,10 +411,10 @@ fn test() { use core::io::WriterUtil; let db = @mut Database { db_filename: Path("db.json"), - db_cache: LinearMap::new(), + db_cache: HashMap::new(), db_dirty: false }; let lg = @mut Logger { a: () }; - let cfg = @LinearMap::new(); + let cfg = @HashMap::new(); let cx = @Context::new(db, lg, cfg); let w:Work<~str> = do cx.prep("test1") |prep| { let pth = Path("foo.c"); diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 04d7cbdca0c3d..147d8227b81ea 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -23,7 +23,7 @@ use print::pprust; use visit; use core::cmp; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::str; use core::vec; @@ -104,7 +104,7 @@ pub enum ast_node { node_struct_ctor(@struct_def, @item, @path), } -pub type map = @mut LinearMap; +pub type map = @mut HashMap; pub struct Ctx { map: map, @@ -134,7 +134,7 @@ pub fn mk_ast_map_visitor() -> vt { pub fn map_crate(diag: @span_handler, c: crate) -> map { let cx = @mut Ctx { - map: @mut LinearMap::new(), + map: @mut HashMap::new(), path: ~[], local_id: 0u, diag: diag, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 71e2faa93f569..5063a0381e782 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -20,7 +20,7 @@ use diagnostic::span_handler; use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; use core::vec; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use std; /* Constructors */ @@ -333,7 +333,7 @@ pub fn find_inline_attr(attrs: &[ast::attribute]) -> inline_attr { pub fn require_unique_names(diagnostic: @span_handler, metas: &[@ast::meta_item]) { - let mut set = LinearSet::new(); + let mut set = HashSet::new(); for metas.each |meta| { let name = get_meta_item_name(*meta); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cae56267f5eb3..92f0c7c7679a9 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -20,7 +20,7 @@ use parse; use parse::token; use core::vec; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; // new-style macro! tt code: // @@ -125,7 +125,7 @@ pub fn syntax_expander_table() -> SyntaxEnv { fn builtin_item_tt(f: SyntaxExpanderTTItemFun) -> @Transformer { @SE(IdentTT(SyntaxExpanderTTItem{expander: f, span: None})) } - let mut syntax_expanders = LinearMap::new(); + let mut syntax_expanders = HashMap::new(); // NB identifier starts with space, and can't conflict with legal idents syntax_expanders.insert(@~" block", @ScopeMacros(true)); @@ -430,8 +430,8 @@ pub fn get_exprs_from_tts(cx: @ext_ctxt, tts: &[ast::token_tree]) // a transformer env is either a base map or a map on top // of another chain. pub enum MapChain { - BaseMapChain(~LinearMap), - ConsMapChain(~LinearMap,@mut MapChain) + BaseMapChain(~HashMap), + ConsMapChain(~HashMap,@mut MapChain) } @@ -439,13 +439,13 @@ pub enum MapChain { impl MapChain{ // Constructor. I don't think we need a zero-arg one. - fn new(+init: ~LinearMap) -> @mut MapChain { + fn new(+init: ~HashMap) -> @mut MapChain { @mut BaseMapChain(init) } // add a new frame to the environment (functionally) fn push_frame (@mut self) -> @mut MapChain { - @mut ConsMapChain(~LinearMap::new() ,self) + @mut ConsMapChain(~HashMap::new() ,self) } // no need for pop, it'll just be functional. @@ -454,7 +454,7 @@ impl MapChain{ // ugh: can't get this to compile with mut because of the // lack of flow sensitivity. - fn get_map(&self) -> &'self LinearMap { + fn get_map(&self) -> &'self HashMap { match *self { BaseMapChain (~ref map) => map, ConsMapChain (~ref map,_) => map @@ -509,10 +509,10 @@ impl MapChain{ #[cfg(test)] mod test { use super::MapChain; - use core::hashmap::LinearMap; + use core::hashmap::HashMap; #[test] fn testenv () { - let mut a = LinearMap::new(); + let mut a = HashMap::new(); a.insert (@~"abc",@15); let m = MapChain::new(~a); m.insert (@~"def",@16); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index fcb0c76a2c78a..afb7e04a53204 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -20,7 +20,7 @@ use parse::token::{Token, EOF, to_str, nonterminal}; use parse::token; use core::prelude::*; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; /* This is an Earley-like parser, without support for in-grammar nonterminals, only by calling out to the main rust parser for named nonterminals (which it @@ -186,9 +186,9 @@ pub enum named_match { pub type earley_item = ~MatcherPos; pub fn nameize(p_s: @mut ParseSess, ms: ~[matcher], res: ~[@named_match]) - -> LinearMap { + -> HashMap { fn n_rec(p_s: @mut ParseSess, m: matcher, res: ~[@named_match], - ret_val: &mut LinearMap) { + ret_val: &mut HashMap) { match m { codemap::spanned {node: match_tok(_), _} => (), codemap::spanned {node: match_seq(ref more_ms, _, _, _, _), _} => { @@ -207,13 +207,13 @@ pub fn nameize(p_s: @mut ParseSess, ms: ~[matcher], res: ~[@named_match]) } } } - let mut ret_val = LinearMap::new(); + let mut ret_val = HashMap::new(); for ms.each() |m| { n_rec(p_s, *m, res, &mut ret_val) } return ret_val; } pub enum parse_result { - success(LinearMap), + success(HashMap), failure(codemap::span, ~str), error(codemap::span, ~str) } @@ -223,7 +223,7 @@ pub fn parse_or_else( +cfg: ast::crate_cfg, rdr: @reader, ms: ~[matcher] -) -> LinearMap { +) -> HashMap { match parse(sess, cfg, rdr, ms) { success(m) => m, failure(sp, str) => sess.span_diagnostic.span_fatal(sp, str), diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index de0b4c0799fba..0a74b6a94354a 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -18,7 +18,7 @@ use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; use parse::lexer::TokenAndSpan; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::option; use core::vec; @@ -39,7 +39,7 @@ pub struct TtReader { // the unzipped tree: cur: @mut TtFrame, /* for MBE-style macro transcription */ - interpolations: LinearMap, + interpolations: HashMap, repeat_idx: ~[uint], repeat_len: ~[uint], /* cached: */ @@ -52,7 +52,7 @@ pub struct TtReader { * should) be none. */ pub fn new_tt_reader(sp_diag: @span_handler, itr: @ident_interner, - interp: Option>, + interp: Option>, +src: ~[ast::token_tree]) -> @mut TtReader { let r = @mut TtReader { @@ -66,7 +66,7 @@ pub fn new_tt_reader(sp_diag: @span_handler, up: option::None }, interpolations: match interp { /* just a convienience */ - None => LinearMap::new(), + None => HashMap::new(), Some(x) => x }, repeat_idx: ~[], diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1b845ad1dd9d4..f36d8f42f2ac6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -94,7 +94,7 @@ use opt_vec::OptVec; use core::either::Either; use core::either; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use core::vec; #[deriving(Eq)] @@ -243,7 +243,7 @@ pub fn Parser(sess: @mut ParseSess, keywords: token::keyword_table(), strict_keywords: token::strict_keyword_table(), reserved_keywords: token::reserved_keyword_table(), - obsolete_set: @mut LinearSet::new(), + obsolete_set: @mut HashSet::new(), mod_path_stack: @mut ~[], } } @@ -262,12 +262,12 @@ pub struct Parser { quote_depth: @mut uint, // not (yet) related to the quasiquoter reader: @reader, interner: @token::ident_interner, - keywords: LinearSet<~str>, - strict_keywords: LinearSet<~str>, - reserved_keywords: LinearSet<~str>, + keywords: HashSet<~str>, + strict_keywords: HashSet<~str>, + reserved_keywords: HashSet<~str>, /// The set of seen errors about obsolete syntax. Used to suppress /// extra detail when the same error is seen twice - obsolete_set: @mut LinearSet, + obsolete_set: @mut HashSet, /// Used to determine the path to externally loaded source files mod_path_stack: @mut ~[~str], diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index ff10b6070e66d..713a6e8947554 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,7 +18,7 @@ use util::interner; use core::cast; use core::char; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use core::str; use core::task; @@ -458,8 +458,8 @@ pub fn mk_fake_ident_interner() -> @ident_interner { * appear as identifiers at all. Reserved keywords are not used anywhere in * the language and may not appear as identifiers. */ -pub fn keyword_table() -> LinearSet<~str> { - let mut keywords = LinearSet::new(); +pub fn keyword_table() -> HashSet<~str> { + let mut keywords = HashSet::new(); let mut tmp = temporary_keyword_table(); let mut strict = strict_keyword_table(); let mut reserved = reserved_keyword_table(); @@ -471,8 +471,8 @@ pub fn keyword_table() -> LinearSet<~str> { } /// Keywords that may be used as identifiers -pub fn temporary_keyword_table() -> LinearSet<~str> { - let mut words = LinearSet::new(); +pub fn temporary_keyword_table() -> HashSet<~str> { + let mut words = HashSet::new(); let keys = ~[ ~"self", ~"static", ]; @@ -483,8 +483,8 @@ pub fn temporary_keyword_table() -> LinearSet<~str> { } /// Full keywords. May not appear anywhere else. -pub fn strict_keyword_table() -> LinearSet<~str> { - let mut words = LinearSet::new(); +pub fn strict_keyword_table() -> HashSet<~str> { + let mut words = HashSet::new(); let keys = ~[ ~"as", ~"break", @@ -509,8 +509,8 @@ pub fn strict_keyword_table() -> LinearSet<~str> { return words; } -pub fn reserved_keyword_table() -> LinearSet<~str> { - let mut words = LinearSet::new(); +pub fn reserved_keyword_table() -> HashSet<~str> { + let mut words = HashSet::new(); let keys = ~[ ~"be" ]; diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index dd4044036ef84..4108871d0089c 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -13,10 +13,10 @@ // type, and vice versa. use core::prelude::*; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; pub struct Interner { - priv map: @mut LinearMap, + priv map: @mut HashMap, priv vect: @mut ~[T], } @@ -24,7 +24,7 @@ pub struct Interner { pub impl Interner { fn new() -> Interner { Interner { - map: @mut LinearMap::new(), + map: @mut HashMap::new(), vect: @mut ~[], } } diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index eded285eef117..bee754f5bd448 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -13,9 +13,9 @@ extern mod std; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; -pub type header_map = LinearMap<~str, @mut ~[@~str]>; +pub type header_map = HashMap<~str, @mut ~[@~str]>; // the unused ty param is necessary so this gets monomorphized pub fn request(req: &header_map) { diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index c30c38e92f724..8a8962fb9d637 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -13,7 +13,7 @@ extern mod std; use core::io; use std::time; use std::treemap::TreeMap; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::trie::TrieMap; fn timed(label: &str, f: &fn()) { @@ -102,7 +102,7 @@ fn main() { { let rng = core::rand::seeded_rng([1, 1, 1, 1, 1, 1, 1]); - let mut set = LinearSet::new(); + let mut set = HashSet::new(); while set.len() != n_keys { let next = rng.next() as uint; if set.insert(next) { @@ -131,21 +131,21 @@ fn main() { vector(&mut map, n_keys, rand); } - io::println("\nLinearMap:"); + io::println("\nHashMap:"); { - let mut map = LinearMap::new::(); + let mut map = HashMap::new::(); ascending(&mut map, n_keys); } { - let mut map = LinearMap::new::(); + let mut map = HashMap::new::(); descending(&mut map, n_keys); } { io::println(" Random integers:"); - let mut map = LinearMap::new::(); + let mut map = HashMap::new::(); vector(&mut map, n_keys, rand); } diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 2fcd82eefe61b..5f8f13896fb95 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -9,7 +9,7 @@ // except according to those terms. extern mod std; -use core::hashmap::LinearSet; +use core::hashmap::HashSet; use std::bitv::BitvSet; use std::treemap::TreeSet; use core::io::WriterUtil; @@ -158,9 +158,9 @@ fn main() { { let rng = rand::seeded_rng(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || LinearSet::new::()); - results.bench_str(rng, num_keys, || LinearSet::new::<~str>()); - write_results("core::hashmap::LinearSet", &results); + results.bench_int(rng, num_keys, max, || HashSet::new::()); + results.bench_str(rng, num_keys, || HashSet::new::<~str>()); + write_results("core::hashmap::HashSet", &results); } { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 397c08228995c..396ea08136281 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -24,7 +24,7 @@ use std::arc; use std::time; use std::deque::Deque; use std::par; -use core::hashmap::{LinearMap, LinearSet}; +use core::hashmap::{HashMap, HashSet}; use core::io::WriterUtil; use core::int::abs; use core::rand::RngUtil; @@ -81,7 +81,7 @@ fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] { fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph { let mut graph = do vec::from_fn(N) |_i| { - LinearSet::new() + HashSet::new() }; do vec::each(edges) |e| { @@ -104,7 +104,7 @@ fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph { } fn gen_search_keys(graph: &[~[node_id]], n: uint) -> ~[node_id] { - let mut keys = LinearSet::new(); + let mut keys = HashSet::new(); let r = rand::Rng(); while keys.len() < n { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index f608c71000b29..6ba1caa0d1e1a 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -15,13 +15,13 @@ extern mod std; use std::sort; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use core::io::ReaderUtil; use core::comm::{stream, Port, Chan}; use core::cmp::Ord; // given a map, print a sorted version of it -fn sort_and_fmt(mm: &LinearMap<~[u8], uint>, total: uint) -> ~str { +fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { fn pct(xx: uint, yy: uint) -> float { return (xx as float) * 100f / (yy as float); } @@ -67,7 +67,7 @@ fn sort_and_fmt(mm: &LinearMap<~[u8], uint>, total: uint) -> ~str { } // given a map, search for the frequency of a pattern -fn find(mm: &LinearMap<~[u8], uint>, key: ~str) -> uint { +fn find(mm: &HashMap<~[u8], uint>, key: ~str) -> uint { match mm.find(&str::to_bytes(str::to_lower(key))) { option::None => { return 0u; } option::Some(&num) => { return num; } @@ -75,7 +75,7 @@ fn find(mm: &LinearMap<~[u8], uint>, key: ~str) -> uint { } // given a map, increment the counter for a key -fn update_freq(mm: &mut LinearMap<~[u8], uint>, key: &[u8]) { +fn update_freq(mm: &mut HashMap<~[u8], uint>, key: &[u8]) { let key = vec::slice(key, 0, key.len()).to_vec(); let newval = match mm.pop(&key) { Some(v) => v + 1, @@ -103,7 +103,7 @@ fn windows_with_carry(bb: &[u8], nn: uint, fn make_sequence_processor(sz: uint, from_parent: comm::Port<~[u8]>, to_parent: comm::Chan<~str>) { - let mut freqs: LinearMap<~[u8], uint> = LinearMap::new(); + let mut freqs: HashMap<~[u8], uint> = HashMap::new(); let mut carry: ~[u8] = ~[]; let mut total: uint = 0u; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 65d99858d1d36..f5d1661fa52bd 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -25,7 +25,7 @@ // writes pbm image to output path use core::io::WriterUtil; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; struct cmplx { re: f64, @@ -125,7 +125,7 @@ fn writer(path: ~str, pport: comm::Port, size: uint) }; cout.write_line("P4"); cout.write_line(fmt!("%u %u", size, size)); - let mut lines: LinearMap = LinearMap::new(); + let mut lines: HashMap = HashMap::new(); let mut done = 0_u; let mut i = 0_u; while i < size { diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs index b3cf314edd001..bda659aa7b97e 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs @@ -10,11 +10,11 @@ //buggy.rs -use core::hashmap::LinearMap; +use core::hashmap::HashMap; fn main() { - let mut buggy_map :LinearMap = - LinearMap::new::(); + let mut buggy_map :HashMap = + HashMap::new::(); buggy_map.insert(42, &*~1); //~ ERROR illegal borrow // but it is ok if we use a temporary diff --git a/src/test/compile-fail/borrowck-insert-during-each.rs b/src/test/compile-fail/borrowck-insert-during-each.rs index 1420a67556cad..17c0efe225e4d 100644 --- a/src/test/compile-fail/borrowck-insert-during-each.rs +++ b/src/test/compile-fail/borrowck-insert-during-each.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::LinearSet; +use core::hashmap::HashSet; struct Foo { - n: LinearSet, + n: HashSet, } pub impl Foo { @@ -29,6 +29,6 @@ fn bar(f: &mut Foo) { } fn main() { - let mut f = Foo { n: LinearSet::new() }; + let mut f = Foo { n: HashSet::new() }; bar(&mut f); } diff --git a/src/test/compile-fail/for-loop-decl.rs b/src/test/compile-fail/for-loop-decl.rs index c7c1ea4821307..de28d72677728 100644 --- a/src/test/compile-fail/for-loop-decl.rs +++ b/src/test/compile-fail/for-loop-decl.rs @@ -11,10 +11,10 @@ // error-pattern: mismatched types extern mod std; use std::bitv; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; struct FnInfo { - vars: LinearMap + vars: HashMap } struct VarInfo { diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index 00efdbbf75acc..ebc5b015d2752 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -9,12 +9,12 @@ // except according to those terms. use core::container::Map; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; // Test that trait types printed in error msgs include the type arguments. fn main() { - let x: @Map<~str, ~str> = @LinearMap::new::<~str, ~str>() as + let x: @Map<~str, ~str> = @HashMap::new::<~str, ~str>() as @Map<~str, ~str>; let y: @Map = @x; //~^ ERROR mismatched types: expected `@core::container::Map` diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs index 5ec4beb364d89..7e3318f865228 100644 --- a/src/test/run-fail/unwind-misc-1.rs +++ b/src/test/run-fail/unwind-misc-1.rs @@ -14,7 +14,7 @@ fn main() { let count = @mut 0u; - let mut map = core::hashmap::LinearMap::new(); + let mut map = core::hashmap::HashMap::new(); let mut arr = ~[]; for uint::range(0u, 10u) |i| { arr += ~[@~"key stuff"]; diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index fdf733d0314bc..1a2a8cab3032c 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -20,17 +20,17 @@ type EqFn = ~fn(K, K) -> bool; struct LM { resize_at: uint, size: uint } -enum LinearMap { - LinearMap_(LM) +enum HashMap { + HashMap_(LM) } -fn linear_map() -> LinearMap { - LinearMap_(LM{ +fn linear_map() -> HashMap { + HashMap_(LM{ resize_at: 32, size: 0}) } -pub impl LinearMap { +pub impl HashMap { fn len(&mut self) -> uint { self.size } diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 415f753a562e2..910708b710602 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -19,7 +19,7 @@ pub fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); } mod map_reduce { - use core::hashmap::LinearMap; + use core::hashmap::HashMap; use core::comm::*; pub type putter = @fn(~str, ~str); @@ -37,9 +37,9 @@ mod map_reduce { } fn map_task(ctrl: SharedChan, input: ~str) { - let intermediates = @mut LinearMap::new(); + let intermediates = @mut HashMap::new(); - fn emit(im: &mut LinearMap<~str, int>, ctrl: SharedChan, key: ~str, + fn emit(im: &mut HashMap<~str, int>, ctrl: SharedChan, key: ~str, _val: ~str) { if im.contains_key(&key) { return; @@ -65,9 +65,9 @@ mod map_reduce { // This task becomes the master control task. It spawns others // to do the rest. - let mut reducers: LinearMap<~str, int>; + let mut reducers: HashMap<~str, int>; - reducers = LinearMap::new(); + reducers = HashMap::new(); start_mappers(ctrl_chan, inputs.clone()); diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 401920789c098..5b40d0abff818 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -10,10 +10,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::LinearMap; +use core::hashmap::HashMap; pub fn main() { - let mut m = LinearMap::new(); + let mut m = HashMap::new(); m.insert(str::to_bytes(~"foo"), str::to_bytes(~"bar")); error!(m); } diff --git a/src/test/run-pass/issue-2631-b.rs b/src/test/run-pass/issue-2631-b.rs index 42452d3a2bb0f..f6e40fa247d5e 100644 --- a/src/test/run-pass/issue-2631-b.rs +++ b/src/test/run-pass/issue-2631-b.rs @@ -14,11 +14,11 @@ extern mod req; use req::*; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; pub fn main() { let v = ~[@~"hi"]; - let mut m: req::header_map = LinearMap::new(); + let mut m: req::header_map = HashMap::new(); m.insert(~"METHOD", @mut v); request::(&m); } diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index 4f0930deaaef1..b25e4095b185e 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -13,9 +13,9 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr -use core::hashmap::LinearMap; +use core::hashmap::HashMap; -fn add_interfaces(managed_ip: ~str, device: LinearMap<~str, int>) { +fn add_interfaces(managed_ip: ~str, device: HashMap<~str, int>) { error!("%s, %?", managed_ip, device.get(&~"interfaces")); } diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs index a1c5f4a6757dc..4614c26fa5fc8 100644 --- a/src/test/run-pass/issue-2804.rs +++ b/src/test/run-pass/issue-2804.rs @@ -11,7 +11,7 @@ // except according to those terms. extern mod std; -use core::hashmap::LinearMap; +use core::hashmap::HashMap; use std::json; enum object { @@ -58,7 +58,7 @@ fn add_interface(store: int, managed_ip: ~str, data: std::json::Json) -> (~str, } } -fn add_interfaces(store: int, managed_ip: ~str, device: LinearMap<~str, std::json::Json>) -> ~[(~str, object)] +fn add_interfaces(store: int, managed_ip: ~str, device: HashMap<~str, std::json::Json>) -> ~[(~str, object)] { match device.get(&~"interfaces") { diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index 9665113bc0cee..16e9b4753f830 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -10,10 +10,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::LinearMap; +use core::hashmap::HashMap; pub fn main() { - let mut buggy_map: LinearMap = LinearMap::new::(); + let mut buggy_map: HashMap = HashMap::new::(); let x = ~1; buggy_map.insert(42, &*x); } diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index a73f130e88981..334831fea4d03 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -29,7 +29,7 @@ fn check_strs(actual: &str, expected: &str) -> bool #[test] fn tester() { - let mut table = core::hashmap::LinearMap(); + let mut table = core::hashmap::HashMap(); table.insert(@~"one", 1); table.insert(@~"two", 2); assert!(check_strs(table.to_str(), ~"xxx")); // not sure what expected should be diff --git a/src/test/run-pass/issue-4092.rs b/src/test/run-pass/issue-4092.rs index 8cda78840b341..e129e0a88687a 100644 --- a/src/test/run-pass/issue-4092.rs +++ b/src/test/run-pass/issue-4092.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::LinearMap; +use core::hashmap::HashMap; pub fn main() { - let mut x = LinearMap::new(); + let mut x = HashMap::new(); x.insert((@"abc", 0), 0); } From c16919d3a8e83e4c72668f6ad89d48f6ba8341f6 Mon Sep 17 00:00:00 2001 From: Matthijs Hofstra Date: Tue, 2 Apr 2013 23:15:04 +0200 Subject: [PATCH 018/403] Removing mut fields from vec.rs, at_vec.rs, str.rs, unstable.rs, and cell.rs. --- src/libcore/at_vec.rs | 4 ++-- src/libcore/cell.rs | 12 +++++------- src/libcore/str.rs | 4 ++-- src/libcore/unstable.rs | 14 +++++++------- src/libcore/vec.rs | 12 ++++++------ 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 3e3d70530dd35..38a663dc24504 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -208,7 +208,7 @@ pub mod raw { */ #[inline(always)] pub unsafe fn set_len(v: @[T], new_len: uint) { - let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(&v)); + let repr: **mut VecRepr = ::cast::reinterpret_cast(&addr_of(&v)); (**repr).unboxed.fill = new_len * sys::size_of::(); } @@ -226,7 +226,7 @@ pub mod raw { #[inline(always)] // really pretty please pub unsafe fn push_fast(v: &mut @[T], initval: T) { - let repr: **VecRepr = ::cast::reinterpret_cast(&v); + let repr: **mut VecRepr = ::cast::reinterpret_cast(&v); let fill = (**repr).unboxed.fill; (**repr).unboxed.fill += sys::size_of::(); let p = addr_of(&((**repr).unboxed.data)); diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 28b3ebe4484c7..c2983e033e537 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -10,7 +10,7 @@ //! A mutable, nullable memory location -use cast::transmute; +use cast::transmute_mut; use prelude::*; /* @@ -20,16 +20,12 @@ Similar to a mutable option type, but friendlier. */ pub struct Cell { - mut value: Option + value: Option } impl cmp::Eq for Cell { fn eq(&self, other: &Cell) -> bool { - unsafe { - let frozen_self: &Option = transmute(&mut self.value); - let frozen_other: &Option = transmute(&mut other.value); - frozen_self == frozen_other - } + (self.value) == (other.value) } fn ne(&self, other: &Cell) -> bool { !self.eq(other) } } @@ -46,6 +42,7 @@ pub fn empty_cell() -> Cell { pub impl Cell { /// Yields the value, failing if the cell is empty. fn take(&self) -> T { + let mut self = unsafe { transmute_mut(self) }; if self.is_empty() { fail!(~"attempt to take an empty cell"); } @@ -57,6 +54,7 @@ pub impl Cell { /// Returns the value, failing if the cell is full. fn put_back(&self, value: T) { + let mut self = unsafe { transmute_mut(self) }; if !self.is_empty() { fail!(~"attempt to put a value back into a full cell"); } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 67fd37996cda0..18ea169d96e5c 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2274,8 +2274,8 @@ pub mod raw { /// Sets the length of the string and adds the null terminator pub unsafe fn set_len(v: &mut ~str, new_len: uint) { - let v: **vec::raw::VecRepr = cast::transmute(v); - let repr: *vec::raw::VecRepr = *v; + let v: **mut vec::raw::VecRepr = cast::transmute(v); + let repr: *mut vec::raw::VecRepr = *v; (*repr).unboxed.fill = new_len + 1u; let null = ptr::mut_offset(cast::transmute(&((*repr).unboxed.data)), new_len); diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index 665a3e1b6b6d4..e2b57a8dd3eda 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -106,13 +106,13 @@ fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool { ****************************************************************************/ struct ArcData { - mut count: libc::intptr_t, + count: libc::intptr_t, // FIXME(#3224) should be able to make this non-option to save memory - mut data: Option, + data: Option, } struct ArcDestruct { - mut data: *libc::c_void, + data: *libc::c_void, } #[unsafe_destructor] @@ -122,7 +122,7 @@ impl Drop for ArcDestruct{ do task::unkillable { let data: ~ArcData = cast::reinterpret_cast(&self.data); let new_count = - intrinsics::atomic_xsub(&mut data.count, 1) - 1; + intrinsics::atomic_xsub(cast::transmute_mut(&data.count), 1) - 1; assert!(new_count >= 0); if new_count == 0 { // drop glue takes over. @@ -186,7 +186,7 @@ pub unsafe fn clone_shared_mutable_state(rc: &SharedMutableState) -> SharedMutableState { unsafe { let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); - let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1; + let new_count = intrinsics::atomic_xadd(cast::transmute_mut(&ptr.count), 1) + 1; assert!(new_count >= 2); cast::forget(ptr); } @@ -252,7 +252,7 @@ pub impl LittleLock { } } -struct ExData { lock: LittleLock, mut failed: bool, mut data: T, } +struct ExData { lock: LittleLock, failed: bool, data: T, } /** * An arc over mutable data that is protected by a lock. For library use only. */ @@ -260,7 +260,7 @@ pub struct Exclusive { x: SharedMutableState> } pub fn exclusive(user_data: T) -> Exclusive { let data = ExData { - lock: LittleLock(), mut failed: false, mut data: user_data + lock: LittleLock(), failed: false, data: user_data }; Exclusive { x: unsafe { shared_mutable_state(data) } } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 0ac86ac280d06..21e876ea0fb02 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -633,7 +633,7 @@ pub fn push(v: &mut ~[T], initval: T) { // This doesn't bother to make sure we have space. #[inline(always)] // really pretty please unsafe fn push_fast(v: &mut ~[T], initval: T) { - let repr: **raw::VecRepr = ::cast::transmute(v); + let repr: **mut raw::VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; (**repr).unboxed.fill += sys::nonzero_size_of::(); let p = addr_of(&((**repr).unboxed.data)); @@ -2148,8 +2148,8 @@ pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { /// The internal 'unboxed' representation of a vector pub struct UnboxedVecRepr { - mut fill: uint, - mut alloc: uint, + fill: uint, + alloc: uint, data: u8 } @@ -2171,8 +2171,8 @@ pub mod raw { } pub struct SliceRepr { - mut data: *u8, - mut len: uint + data: *u8, + len: uint } /** @@ -2184,7 +2184,7 @@ pub mod raw { */ #[inline(always)] pub unsafe fn set_len(v: &mut ~[T], new_len: uint) { - let repr: **VecRepr = ::cast::transmute(v); + let repr: **mut VecRepr = ::cast::transmute(v); (**repr).unboxed.fill = new_len * sys::nonzero_size_of::(); } From 397a47852849ac2e286508f2315e695f5d8168cf Mon Sep 17 00:00:00 2001 From: Matthijs Hofstra Date: Wed, 3 Apr 2013 18:28:44 +0200 Subject: [PATCH 019/403] Unstable didn't need transmute_mut after all. --- src/libcore/unstable.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index e2b57a8dd3eda..c717c1692a8c5 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -120,9 +120,9 @@ impl Drop for ArcDestruct{ fn finalize(&self) { unsafe { do task::unkillable { - let data: ~ArcData = cast::reinterpret_cast(&self.data); + let mut data: ~ArcData = cast::reinterpret_cast(&self.data); let new_count = - intrinsics::atomic_xsub(cast::transmute_mut(&data.count), 1) - 1; + intrinsics::atomic_xsub(&mut data.count, 1) - 1; assert!(new_count >= 0); if new_count == 0 { // drop glue takes over. @@ -185,8 +185,8 @@ pub unsafe fn get_shared_immutable_state<'a,T:Owned>( pub unsafe fn clone_shared_mutable_state(rc: &SharedMutableState) -> SharedMutableState { unsafe { - let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); - let new_count = intrinsics::atomic_xadd(cast::transmute_mut(&ptr.count), 1) + 1; + let mut ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1; assert!(new_count >= 2); cast::forget(ptr); } From c4d2b7999a12b8c9111ae1d897c476c052ddc05a Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Wed, 3 Apr 2013 11:03:41 -0600 Subject: [PATCH 020/403] Add Clone derivation for std::net::url types. --- src/libstd/net_url.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index d23784953ef99..9174e99e40a0a 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -25,7 +25,7 @@ use core::to_str::ToStr; use core::to_str; use core::uint; -#[deriving(Eq)] +#[deriving(Clone, Eq)] struct Url { scheme: ~str, user: Option, @@ -36,7 +36,7 @@ struct Url { fragment: Option<~str> } -#[deriving(Eq)] +#[deriving(Clone, Eq)] struct UserInfo { user: ~str, pass: Option<~str> @@ -398,7 +398,7 @@ pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> { return Err(~"url: Scheme must be terminated with a colon."); } -#[deriving(Eq)] +#[deriving(Clone, Eq)] enum Input { Digit, // all digits Hex, // digits and letters a-f From d79b22474cf9b02d0d3a0a78f8c6ef279770c36b Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 3 Apr 2013 11:40:23 -0700 Subject: [PATCH 021/403] Add information about logging macros to the tutorial. Closes #5699. --- doc/rust.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/rust.md b/doc/rust.md index c6dba96267679..eceb308b4f6a5 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -3251,6 +3251,28 @@ of runtime logging modules follows. * `::rt::backtrace` Log a backtrace on task failure * `::rt::callback` Unused +#### Logging Expressions + +Rust provides several macros to log information. Here's a simple Rust program +that demonstrates all four of them: + +```rust +fn main() { + error!("This is an error log") + warn!("This is a warn log") + info!("this is an info log") + debug!("This is a dubug log") +} +``` + +These four log levels correspond to levels 1-4, as controlled by `RUST_LOG`: + +```bash +$ RUST_LOG=rust=3 ./rust +rust: ~"\"This is na error log\"" +rust: ~"\"This is a warn log\"" +rust: ~"\"this is an info log\"" +``` # Appendix: Rationales and design tradeoffs From 34b2336dd08c7d8eeb8a79cb9c06c89ccb1639cb Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 3 Apr 2013 11:54:49 -0700 Subject: [PATCH 022/403] Fix compiletest on windows --- src/compiletest/procsrv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index a96f36f5e702c..ca10aa0da7d45 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -26,7 +26,7 @@ fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] { // Make sure we include the aux directory in the path assert!(prog.ends_with(~".exe")); - let aux_path = prog.slice(0u, prog.len() - 4u) + ~".libaux"; + let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ~".libaux"; env = do vec::map(env) |pair| { let (k,v) = *pair; From 3044f5e2b64ae8c0ee726ec42f3d2a3faca9e77e Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 3 Apr 2013 12:44:41 -0700 Subject: [PATCH 023/403] typo fix: na -> an --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index eceb308b4f6a5..1cb8b7053b5ce 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -3269,7 +3269,7 @@ These four log levels correspond to levels 1-4, as controlled by `RUST_LOG`: ```bash $ RUST_LOG=rust=3 ./rust -rust: ~"\"This is na error log\"" +rust: ~"\"This is an error log\"" rust: ~"\"This is a warn log\"" rust: ~"\"this is an info log\"" ``` From 8dd5a70ef4bf951c4cdecef3ef9a27ddfc6a03fb Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 3 Apr 2013 18:52:28 -0300 Subject: [PATCH 024/403] Update tut. to not sound like I missed a section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sentence "Remember that `(float, float)` is a tuple of two floats" sounds like you've already read a section on tuples, but that section comes later. Changing it to "Assuming that ..." makes it more about taking the writer's word that the syntax is how tuples are defined. --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 42b0d5a585aee..92e2f55b02d12 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -495,7 +495,7 @@ omitted. A powerful application of pattern matching is *destructuring*: matching in order to bind names to the contents of data -types. Remember that `(float, float)` is a tuple of two floats: +types. Assuming that `(float, float)` is a tuple of two floats: ~~~~ fn angle(vector: (float, float)) -> float { From a7f0bfbda65d6ac2494d2270a96f45570dfb552e Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 3 Apr 2013 16:59:13 -0700 Subject: [PATCH 025/403] One more typo: dubug -> debug --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 1cb8b7053b5ce..d70fcded5e76a 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -3261,7 +3261,7 @@ fn main() { error!("This is an error log") warn!("This is a warn log") info!("this is an info log") - debug!("This is a dubug log") + debug!("This is a debug log") } ``` From e2c7a4def2730e33babf26ff834abe32a1de9a04 Mon Sep 17 00:00:00 2001 From: Anthony Juckel Date: Wed, 3 Apr 2013 19:10:09 -0500 Subject: [PATCH 026/403] Simple typo fix --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 42b0d5a585aee..499eb7e387880 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -988,7 +988,7 @@ custom destructors. # Boxes -Many modern languages represent values as as pointers to heap memory by +Many modern languages represent values as pointers to heap memory by default. In contrast, Rust, like C and C++, represents such types directly. Another way to say this is that aggregate data in Rust are *unboxed*. This means that if you `let x = Point { x: 1f, y: 1f };`, you are creating a struct From f06404860ce4c083461483b41879ae40f08a3fc2 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Wed, 3 Apr 2013 14:42:50 +0900 Subject: [PATCH 027/403] Remove a android hack --- src/librustc/middle/trans/base.rs | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index aa97c287b4c05..5c5f78aeab6f5 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2284,25 +2284,14 @@ pub fn create_main_wrapper(ccx: @CrateContext, let opaque_crate_map = llvm::LLVMBuildPointerCast( bld, crate_map, T_ptr(T_i8()), noname()); - if *ccx.sess.building_library { - ~[ - retptr, - C_null(T_opaque_box_ptr(ccx)), - opaque_rust_main, - llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), - llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), - opaque_crate_map - ] - } else { - ~[ - retptr, - C_null(T_opaque_box_ptr(ccx)), - opaque_rust_main, - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - } + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ] }; unsafe { From fac0d9d89bd55eccda2549d59b5355afdcaa783f Mon Sep 17 00:00:00 2001 From: ILyoan Date: Wed, 3 Apr 2013 15:44:26 +0900 Subject: [PATCH 028/403] Decides main name by target --- src/librustc/middle/trans/base.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 5c5f78aeab6f5..a8fe60ba68ee8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2243,17 +2243,17 @@ pub fn create_main_wrapper(ccx: @CrateContext, } fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef) { - #[cfg(windows)] - fn main_name() -> ~str { return ~"WinMain@16"; } - #[cfg(unix)] - fn main_name() -> ~str { return ~"main"; } let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); // FIXME #4404 android JNI hacks let llfn = if *ccx.sess.building_library { decl_cdecl_fn(ccx.llmod, ~"amain", llfty) } else { - decl_cdecl_fn(ccx.llmod, main_name(), llfty) + let main_name = match ccx.sess.targ_cfg.os { + session::os_win32 => ~"WinMain@16", + _ => ~"main", + }; + decl_cdecl_fn(ccx.llmod, main_name, llfty) }; let llbb = str::as_c_str(~"top", |buf| { unsafe { From 53232f7acfa651f14c7ed5afd5ec44da9f82eb08 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Thu, 4 Apr 2013 11:16:26 +0900 Subject: [PATCH 029/403] Fix fileinput test fail --- src/libstd/fileinput.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs index df733425f3ef0..4ac3e0b174729 100644 --- a/src/libstd/fileinput.rs +++ b/src/libstd/fileinput.rs @@ -534,7 +534,7 @@ mod test { fn test_empty_files() { let filenames = pathify(vec::from_fn( 3, - |i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); + |i| fmt!("tmp/lib-fileinput-test-empty-files-%u.tmp", i)),true); make_file(filenames[0].get_ref(), ~[~"1", ~"2"]); make_file(filenames[1].get_ref(), ~[]); From 679b1dcb62b53f52f6e4ffe18cc89be8dbf5cc15 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 3 Apr 2013 22:34:29 -0700 Subject: [PATCH 030/403] doc: Rewrite task tutorial intro It doesn't quite reflect reality --- doc/tutorial-tasks.md | 67 ++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 5168809e9aab7..7831dc1d80fc0 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -2,66 +2,56 @@ # Introduction -The designers of Rust designed the language from the ground up to support pervasive -and safe concurrency through lightweight, memory-isolated tasks and -message passing. - -Rust tasks are not the same as traditional threads: rather, they are more like -_green threads_. The Rust runtime system schedules tasks cooperatively onto a -small number of operating system threads. Because tasks are significantly +Rust provides safe concurrency through a combination +of lightweight, memory-isolated tasks and message passing. +This tutorial will describe the concurrency model in Rust, how it +relates to the Rust type system, and introduce +the fundamental library abstractions for constructing concurrent programs. + +Rust tasks are not the same as traditional threads: rather, +they are considered _green threads_, lightweight units of execution that the Rust +runtime schedules cooperatively onto a small number of operating system threads. +On a multi-core system Rust tasks will be scheduled in parallel by default. +Because tasks are significantly cheaper to create than traditional threads, Rust can create hundreds of thousands of concurrent tasks on a typical 32-bit system. +In general, all Rust code executes inside a task, including the `main` function. + +In order to make efficient use of memory Rust tasks have dynamically sized stacks. +A task begins its life with a small +amount of stack space (currently in the low thousands of bytes, depending on +platform), and acquires more stack as needed. +Unlike in languages such as C, a Rust task cannot accidentally write to +memory beyond the end of the stack, causing crashes or worse. -Tasks provide failure isolation and recovery. When an exception occurs in Rust -code (as a result of an explicit call to `fail!()`, an assertion failure, or -another invalid operation), the runtime system destroys the entire +Tasks provide failure isolation and recovery. When a fatal error occurs in Rust +code as a result of an explicit call to `fail!()`, an assertion failure, or +another invalid operation, the runtime system destroys the entire task. Unlike in languages such as Java and C++, there is no way to `catch` an exception. Instead, tasks may monitor each other for failure. -Rust tasks have dynamically sized stacks. A task begins its life with a small -amount of stack space (currently in the low thousands of bytes, depending on -platform), and acquires more stack as needed. Unlike in languages such as C, a -Rust task cannot run off the end of the stack. However, tasks do have a stack -budget. If a Rust task exceeds its stack budget, then it will fail safely: -with a checked exception. - Tasks use Rust's type system to provide strong memory safety guarantees. In particular, the type system guarantees that tasks cannot share mutable state with each other. Tasks communicate with each other by transferring _owned_ data through the global _exchange heap_. -This tutorial explains the basics of tasks and communication in Rust, -explores some typical patterns in concurrent Rust code, and finally -discusses some of the more unusual synchronization types in the standard -library. - -> ***Warning:*** This tutorial is incomplete - ## A note about the libraries While Rust's type system provides the building blocks needed for safe and efficient tasks, all of the task functionality itself is implemented in the core and standard libraries, which are still under development -and do not always present a consistent interface. - -In particular, there are currently two independent modules that provide a -message passing interface to Rust code: `core::comm` and `core::pipes`. -`core::comm` is an older, less efficient system that is being phased out in -favor of `pipes`. At some point, we will remove the existing `core::comm` API -and move the user-facing portions of `core::pipes` to `core::comm`. In this -tutorial, we discuss `pipes` and ignore the `comm` API. +and do not always present a consistent or complete interface. For your reference, these are the standard modules involved in Rust concurrency at this writing. * [`core::task`] - All code relating to tasks and task scheduling -* [`core::comm`] - The deprecated message passing API -* [`core::pipes`] - The new message passing infrastructure and API -* [`std::comm`] - Higher level messaging types based on `core::pipes` +* [`core::comm`] - The message passing interface +* [`core::pipes`] - The underlying messaging infrastructure +* [`std::comm`] - Additional messaging types based on `core::pipes` * [`std::sync`] - More exotic synchronization tools, including locks -* [`std::arc`] - The ARC (atomic reference counted) type, for safely sharing - immutable data -* [`std::par`] - Some basic tools for implementing parallel algorithms +* [`std::arc`] - The ARC (atomically reference counted) type, + for safely sharing immutable data [`core::task`]: core/task.html [`core::comm`]: core/comm.html @@ -69,7 +59,6 @@ concurrency at this writing. [`std::comm`]: std/comm.html [`std::sync`]: std/sync.html [`std::arc`]: std/arc.html -[`std::par`]: std/par.html # Basics From 99b156e78a592e8195ae7918a1ad958abef96050 Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Tue, 19 Mar 2013 13:32:03 +0800 Subject: [PATCH 031/403] mk: mips toolchain config --- mk/platform.mk | 25 +++++++++++++++++++++++++ mk/rt.mk | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/mk/platform.mk b/mk/platform.mk index 16b5ba452f4c9..1e102587bf4a0 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -239,6 +239,31 @@ CFG_RUN_arm-linux-androideabi= CFG_RUN_TARG_arm-linux-androideabi= RUSTC_FLAGS_arm-linux-androideabi :=--android-cross-path=$(CFG_ANDROID_CROSS_PATH) +# mips-unknown-linux-gnu configuration +CC_mips-unknown-linux-gnu=mips-linux-gnu-gcc +CXX_mips-unknown-linux-gnu=mips-linux-gnu-g++ +CPP_mips-unknown-linux-gnu=mips-linux-gnu-gcc -E +AR_mips-unknown-linux-gnu=mips-linux-gnu-ar +CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so +CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM +CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 +CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti +CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32 +CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive -Wl,-znoexecstack +CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def +CFG_INSTALL_NAME_mips-unknown-linux-gnu = +CFG_LIBUV_LINK_FLAGS_mips-unknown-linux-gnu = +CFG_EXE_SUFFIX_mips-unknown-linux-gnu := +CFG_WINDOWSY_mips-unknown-linux-gnu := +CFG_UNIXY_mips-unknown-linux-gnu := 1 +CFG_PATH_MUNGE_mips-unknown-linux-gnu := true +CFG_LDPATH_mips-unknown-linux-gnu := +CFG_RUN_mips-unknown-linux-gnu= +CFG_RUN_TARG_mips-unknown-linux-gnu= + # i686-pc-mingw32 configuration CC_i686-pc-mingw32=$(CC) CXX_i686-pc-mingw32=$(CXX) diff --git a/mk/rt.mk b/mk/rt.mk index 15712b91a1e47..b2c282e207fbc 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -27,6 +27,7 @@ LIBUV_FLAGS_i386 = -m32 -fPIC LIBUV_FLAGS_x86_64 = -m64 -fPIC LIBUV_FLAGS_arm = -fPIC -DANDROID -std=gnu99 +LIBUV_FLAGS_mips = -fPIC -mips32r2 -msoft-float -mabi=32 # when we're doing a snapshot build, we intentionally degrade as many # features in libuv and the runtime as possible, to ease portability. @@ -180,6 +181,10 @@ else $$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) $$(Q)$$(MAKE) -C $$(S)src/libuv/ \ CFLAGS="$$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \ + LDFLAGS="$$(LIBUV_FLAGS_$$(HOST_$(1)))" \ + CC="$$(CC_$(1))" \ + CXX="$$(CXX_$(1))" \ + AR="$$(AR_$(1))" \ builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/libuv" \ V=$$(VERBOSE) endif From fdf48a7b52de948b3ec4ba187539a6164a56edcb Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Tue, 19 Mar 2013 13:34:12 +0800 Subject: [PATCH 032/403] rt: improve mips backend --- src/libcore/rt/context.rs | 1 + src/librustc/driver/driver.rs | 2 +- src/rt/arch/mips/_context.S | 3 ++- src/rt/arch/mips/ccall.S | 29 +++++++++++++++++++---------- src/rt/arch/mips/context.cpp | 1 + src/rt/sync/rust_thread.cpp | 3 +++ 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/libcore/rt/context.rs b/src/libcore/rt/context.rs index 224f28a0329f8..9dc9f5da8c1da 100644 --- a/src/libcore/rt/context.rs +++ b/src/libcore/rt/context.rs @@ -189,6 +189,7 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: regs[4] = arg as uint; regs[29] = sp as uint; + regs[25] = fptr as uint; regs[31] = fptr as uint; } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 809a4a591ac83..3b1401ae1d2c8 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -89,7 +89,7 @@ pub fn default_configuration(sess: Session, +argv0: ~str, input: input) -> abi::X86 => (~"little",~"x86",~"32"), abi::X86_64 => (~"little",~"x86_64",~"64"), abi::Arm => (~"little",~"arm",~"32"), - abi::Mips => (~"little",~"arm",~"32") + abi::Mips => (~"big",~"mips",~"32") }; return ~[ // Target bindings. diff --git a/src/rt/arch/mips/_context.S b/src/rt/arch/mips/_context.S index c926a03798d2d..6d8207d97d094 100644 --- a/src/rt/arch/mips/_context.S +++ b/src/rt/arch/mips/_context.S @@ -51,7 +51,6 @@ swap_registers: lw $2, 2 * 4($5) lw $3, 3 * 4($5) lw $4, 4 * 4($5) - lw $5, 5 * 4($5) lw $6, 6 * 4($5) lw $7, 7 * 4($5) @@ -82,6 +81,8 @@ swap_registers: lw $30, 30 * 4($5) lw $31, 31 * 4($5) + lw $5, 5 * 4($5) + jr $31 nop .end swap_registers diff --git a/src/rt/arch/mips/ccall.S b/src/rt/arch/mips/ccall.S index f41d8e721f66f..abbbad164fd37 100644 --- a/src/rt/arch/mips/ccall.S +++ b/src/rt/arch/mips/ccall.S @@ -5,30 +5,39 @@ .text +.align 2 .globl __morestack .hidden __morestack -.align 2 +.cfi_sections .eh_frame_entry +.cfi_startproc .set nomips16 .ent __morestack __morestack: .set noreorder .set nomacro - move $7, $29 - move $29, $6 - sw $7, 0($29) - sw $31, -4($29) + addiu $29, $29, -8 + sw $31, 4($29) + sw $30, 0($29) - addiu $29, $29, -24 + .cfi_def_cfa_offset 8 + .cfi_offset 31, -4 + .cfi_offset 30, -8 + + move $30, $29 + .cfi_def_cfa_register 30 + + move $29, $6 move $25, $5 jalr $25 nop - addiu $29, $29, 24 + move $29, $30 - lw $31, -4($29) - lw $7, 0($29) + lw $30, 0($29) + lw $31, 4($29) + addiu $29, $29, 8 - move $29, $7 jr $31 nop .end __morestack +.cfi_endproc diff --git a/src/rt/arch/mips/context.cpp b/src/rt/arch/mips/context.cpp index d8c3c38daa6df..7347a92e98b92 100644 --- a/src/rt/arch/mips/context.cpp +++ b/src/rt/arch/mips/context.cpp @@ -40,6 +40,7 @@ void context::call(void *f, void *arg, void *stack) regs.data[4] = (uint32_t)arg; regs.data[29] = (uint32_t)sp; + regs.data[25] = (uint32_t)f; regs.data[31] = (uint32_t)f; // Last base pointer on the stack should be 0 diff --git a/src/rt/sync/rust_thread.cpp b/src/rt/sync/rust_thread.cpp index 70fa08d7f2e5d..99613da9b0dbf 100644 --- a/src/rt/sync/rust_thread.cpp +++ b/src/rt/sync/rust_thread.cpp @@ -41,6 +41,9 @@ rust_thread::start() { #if defined(__WIN32__) thread = CreateThread(NULL, stack_sz, rust_thread_start, this, 0, NULL); #else + if (stack_sz < PTHREAD_STACK_MIN) { + stack_sz = PTHREAD_STACK_MIN; + } pthread_attr_t attr; CHECKED(pthread_attr_init(&attr)); CHECKED(pthread_attr_setstacksize(&attr, stack_sz)); From 4f1d8cb6fce625d13baf12f49e41d29f1433c8dd Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Fri, 29 Mar 2013 11:31:34 +0800 Subject: [PATCH 033/403] fix mac build and comment on stack size check --- src/rt/sync/rust_thread.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rt/sync/rust_thread.cpp b/src/rt/sync/rust_thread.cpp index 99613da9b0dbf..824642fc435d0 100644 --- a/src/rt/sync/rust_thread.cpp +++ b/src/rt/sync/rust_thread.cpp @@ -10,6 +10,7 @@ #include "rust_thread.h" +#include const size_t default_stack_sz = 1024*1024; @@ -41,6 +42,8 @@ rust_thread::start() { #if defined(__WIN32__) thread = CreateThread(NULL, stack_sz, rust_thread_start, this, 0, NULL); #else + // PTHREAD_STACK_MIN of some system is larger than default size + // so we check stack_sz to prevent assertion failure. if (stack_sz < PTHREAD_STACK_MIN) { stack_sz = PTHREAD_STACK_MIN; } From cb91e914185f4be9073dcec9a96ca6b78b7e877f Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 4 Apr 2013 15:08:25 +0200 Subject: [PATCH 034/403] Tutorial: rename variable to avoid confusion. --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 42b0d5a585aee..c7d92c03b6d1d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1191,7 +1191,7 @@ they are frozen: let x = @mut 5; let y = x; { - let y = &*y; // the managed box is now frozen + let z = &*y; // the managed box is now frozen // modifying it through x or y will cause a task failure } // the box is now unfrozen again From 964fc862e061a01a399c537bc36b076e672ffaa1 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 4 Apr 2013 18:13:12 +0200 Subject: [PATCH 035/403] Tutorial: comment on how mutability applies to boxes --- doc/tutorial.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/tutorial.md b/doc/tutorial.md index c7d92c03b6d1d..54340c0a4c10d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1067,6 +1067,26 @@ let mut d = @mut 5; // mutable variable, mutable box d = @mut 15; ~~~~ +A mutable variable and an immutable variable can refer to the same box, given +that their types are compatible. Mutability of a box is a property of its type, +however, so for example a mutable hande to an immutable box cannot be assigned +a reference to a mutable box. + +~~~~ +let a = @1; // immutable box +let b = @mut 2; // mutable box + +let mut c : @int; // declare a variable with type managed immutable int +let mut d : @mut int; // and one of type managed mutable int + +c = a; // box type is the same +d = b; // box type is the same + +// but b cannot be assigned to c, or a to d +c = b; // error +~~~~ + + # Move semantics Rust uses a shallow copy for parameter passing, assignment and returning values @@ -1081,6 +1101,16 @@ let y = x.clone(); // y is a newly allocated box let z = x; // no new memory allocated, x can no longer be used ~~~~ +Since in owned boxes mutabilility is a property of the owner, not the +box, mutable boxes may become immutable when they are moved, and vice-versa. + +~~~~ +let r = ~13; +let mut s = r; // box becomes mutable +*s += 1; +let t = s; // box becomes immutable +~~~~ + # Borrowed pointers Rust's borrowed pointers are a general purpose reference type. In contrast with From 2c02aab75851f6bc86b033f07d971fe892c111ef Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Thu, 4 Apr 2013 11:34:35 -0600 Subject: [PATCH 036/403] Add cell#with_mut_ref for handling mutable references to the content. --- src/libcore/cell.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c2983e033e537..1707bddc2b9d4 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -73,6 +73,14 @@ pub impl Cell { self.put_back(v); r } + + // Calls a closure with a mutable reference to the value. + fn with_mut_ref(&self, op: &fn(v: &mut T) -> R) -> R { + let mut v = self.take(); + let r = op(&mut v); + self.put_back(v); + r + } } #[test] @@ -101,3 +109,21 @@ fn test_put_back_non_empty() { let value_cell = Cell(~10); value_cell.put_back(~20); } + +#[test] +fn test_with_ref() { + let good = 6; + let c = Cell(~[1, 2, 3, 4, 5, 6]); + let l = do c.with_ref() |v| { v.len() }; + assert!(l == good); +} + +#[test] +fn test_with_mut_ref() { + let good = ~[1, 2, 3]; + let mut v = ~[1, 2]; + let c = Cell(v); + do c.with_mut_ref() |v| { v.push(3); } + let v = c.take(); + assert!(v == good); +} From 25b39b85da9544a4df9ce8201ac9878b1ec34ff5 Mon Sep 17 00:00:00 2001 From: Steven De Coeyer Date: Thu, 4 Apr 2013 20:49:56 +0200 Subject: [PATCH 037/403] src/librust/rust.rc: Fixes typo 'an executable' vs 'a executable' --- src/librust/rust.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librust/rust.rc b/src/librust/rust.rc index d407cf216a88e..714abbba0db1e 100644 --- a/src/librust/rust.rc +++ b/src/librust/rust.rc @@ -64,7 +64,7 @@ static commands: &'static [Command<'static>] = &[ Command{ cmd: "run", action: Call(cmd_run), - usage_line: "build a executable, and run it", + usage_line: "build an executable, and run it", usage_full: UsgStr( "The run command is an shortcut for the command line \n\ \"rustc -o ~ && ./~\".\ From 1e483c7b70a7369da3c1cd2c858cf2c3d455968c Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 4 Apr 2013 22:35:23 +0200 Subject: [PATCH 038/403] Tutorial: fix typo --- doc/tutorial.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 54340c0a4c10d..794f3089a100d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1069,8 +1069,8 @@ d = @mut 15; A mutable variable and an immutable variable can refer to the same box, given that their types are compatible. Mutability of a box is a property of its type, -however, so for example a mutable hande to an immutable box cannot be assigned -a reference to a mutable box. +however, so for example a mutable handle to an immutable box cannot be +assigned a reference to a mutable box. ~~~~ let a = @1; // immutable box @@ -1079,8 +1079,8 @@ let b = @mut 2; // mutable box let mut c : @int; // declare a variable with type managed immutable int let mut d : @mut int; // and one of type managed mutable int -c = a; // box type is the same -d = b; // box type is the same +c = a; // box type is the same, okay +d = b; // box type is the same, okay // but b cannot be assigned to c, or a to d c = b; // error From ba63cba18d5f0a042fdcb4ab0d39b1bf822d4400 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Apr 2013 17:36:24 +1100 Subject: [PATCH 039/403] libstd: move bigint to dedicated num directory --- src/libstd/{ => num}/bigint.rs | 0 src/libstd/std.rc | 1 + 2 files changed, 1 insertion(+) rename src/libstd/{ => num}/bigint.rs (100%) diff --git a/src/libstd/bigint.rs b/src/libstd/num/bigint.rs similarity index 100% rename from src/libstd/bigint.rs rename to src/libstd/num/bigint.rs diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 74ef229a03353..30346d1b16b5a 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -95,6 +95,7 @@ pub mod cmp; pub mod base64; pub mod rl; pub mod workcache; +#[path="num/bigint.rs"] pub mod bigint; pub mod stats; pub mod semver; From 7b0401d774bac77bee279dff8641aba2b05cf9b8 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Apr 2013 17:54:11 +1100 Subject: [PATCH 040/403] libstd: add basic rational numbers --- src/libstd/num/rational.rs | 511 +++++++++++++++++++++++++++++++++++++ src/libstd/std.rc | 2 + 2 files changed, 513 insertions(+) create mode 100644 src/libstd/num/rational.rs diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs new file mode 100644 index 0000000000000..f15b382dcd351 --- /dev/null +++ b/src/libstd/num/rational.rs @@ -0,0 +1,511 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +//! Rational numbers + +use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round}; +use core::from_str::FromStr; +use core::to_str::ToStr; +use core::prelude::*; +use core::cmp::TotalEq; +use super::bigint::BigInt; + +/// Represents the ratio between 2 numbers. +#[deriving(Clone)] +pub struct Ratio { + numer: T, + denom: T +} + +/// Alias for a `Ratio` of machine-sized integers. +pub type Rational = Ratio; +pub type Rational32 = Ratio; +pub type Rational64 = Ratio; + +/// Alias for arbitrary precision rationals. +pub type BigRational = Ratio; + +impl + Modulo + Neg + Zero + One + Ord + Eq> + Ratio { + /// Create a ratio representing the integer `t`. + #[inline(always)] + pub fn from_integer(t: T) -> Ratio { + Ratio::new_raw(t, One::one()) + } + + /// Create a ratio without checking for `denom == 0` or reducing. + #[inline(always)] + pub fn new_raw(numer: T, denom: T) -> Ratio { + Ratio { numer: numer, denom: denom } + } + + // Create a new Ratio. Fails if `denom == 0`. + #[inline(always)] + pub fn new(numer: T, denom: T) -> Ratio { + if denom == Zero::zero() { + fail!(~"divide by 0"); + } + let mut ret = Ratio::new_raw(numer, denom); + ret.reduce(); + ret + } + + /// Put self into lowest terms, with denom > 0. + fn reduce(&mut self) { + let mut g : T = gcd(self.numer, self.denom); + + self.numer /= g; + self.denom /= g; + + // keep denom positive! + if self.denom < Zero::zero() { + self.numer = -self.numer; + self.denom = -self.denom; + } + } + /// Return a `reduce`d copy of self. + fn reduced(&self) -> Ratio { + let mut ret = copy *self; + ret.reduce(); + ret + } +} + +/** +Compute the greatest common divisor of two numbers, via Euclid's algorithm. + +The result can be negative. +*/ +#[inline] +pub fn gcd_raw + Zero + Eq>(n: T, m: T) -> T { + let mut m = m, n = n; + while m != Zero::zero() { + let temp = m; + m = n % temp; + n = temp; + } + n +} + +/** +Compute the greatest common divisor of two numbers, via Euclid's algorithm. + +The result is always positive. +*/ +#[inline] +pub fn gcd + Neg + Zero + Ord + Eq>(n: T, m: T) -> T { + let g = gcd_raw(n, m); + if g < Zero::zero() { -g } + else { g } +} + +/* Comparisons */ + +// comparing a/b and c/d is the same as comparing a*d and b*c, so we +// abstract that pattern. The following macro takes a trait and either +// a comma-separated list of "method name -> return value" or just +// "method name" (return value is bool in that case) +macro_rules! cmp_impl { + (impl $imp:ident, $($method:ident),+) => { + cmp_impl!(impl $imp, $($method -> bool),+) + }; + // return something other than a Ratio + (impl $imp:ident, $($method:ident -> $res:ty),+) => { + impl + $imp> $imp for Ratio { + $( + #[inline] + fn $method(&self, other: &Ratio) -> $res { + (self.numer * other.denom). $method (&(self.denom*other.numer)) + } + )+ + } + }; +} +cmp_impl!(impl Eq, eq, ne) +cmp_impl!(impl TotalEq, equals) +cmp_impl!(impl Ord, lt, gt, le, ge) +cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering) + +/* Arithmetic */ +// a/b * c/d = (a*c)/(b*d) +impl + Div + Modulo + Neg + Zero + One + Ord + Eq> + Mul,Ratio> for Ratio { + #[inline] + fn mul(&self, rhs: &Ratio) -> Ratio { + Ratio::new(self.numer * rhs.numer, self.denom * rhs.denom) + } +} + +// (a/b) / (c/d) = (a*d)/(b*c) +impl + Div + Modulo + Neg + Zero + One + Ord + Eq> + Div,Ratio> for Ratio { + #[inline] + fn div(&self, rhs: &Ratio) -> Ratio { + Ratio::new(self.numer * rhs.denom, self.denom * rhs.numer) + } +} + +// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern +macro_rules! arith_impl { + (impl $imp:ident, $method:ident) => { + impl + Sub + Mul + Div + Modulo + Neg + + Zero + One + Ord + Eq> + $imp,Ratio> for Ratio { + #[inline] + fn $method(&self, rhs: &Ratio) -> Ratio { + Ratio::new((self.numer * rhs.denom).$method(&(self.denom * rhs.numer)), + self.denom * rhs.denom) + } + } + } +} + +// a/b + c/d = (a*d + b*c)/(b*d +arith_impl!(impl Add, add) + +// a/b - c/d = (a*d - b*c)/(b*d) +arith_impl!(impl Sub, sub) + +// a/b % c/d = (a*d % b*c)/(b*d) +arith_impl!(impl Modulo, modulo) + +impl + Modulo + Neg + Zero + One + Ord + Eq> + Neg> for Ratio { + #[inline] + fn neg(&self) -> Ratio { + Ratio::new_raw(-self.numer, self.denom) + } +} + +/* Constants */ +impl + Modulo + Neg + Zero + One + Ord + Eq> + Zero for Ratio { + #[inline] + fn zero() -> Ratio { + Ratio::new_raw(Zero::zero(), One::one()) + } +} + +impl + Modulo + Neg + Zero + One + Ord + Eq> + One for Ratio { + #[inline] + fn one() -> Ratio { + Ratio::new_raw(One::one(), One::one()) + } +} + +/* Utils */ +impl + Sub + Mul + Div + Modulo + Neg + + Zero + One + Ord + Eq> + Round for Ratio { + fn round(&self, mode: num::RoundMode) -> Ratio { + match mode { + num::RoundUp => { self.ceil() } + num::RoundDown => { self.floor()} + num::RoundToZero => { Ratio::from_integer(self.numer / self.denom) } + num::RoundFromZero => { + if *self < Zero::zero() { + Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) + } else { + Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) + } + } + } + } + + fn floor(&self) -> Ratio { + if *self < Zero::zero() { + Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) + } else { + Ratio::from_integer(self.numer / self.denom) + } + } + fn ceil(&self) -> Ratio { + if *self < Zero::zero() { + Ratio::from_integer(self.numer / self.denom) + } else { + Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) + } + } + fn fract(&self) -> Ratio { + Ratio::new_raw(self.numer % self.denom, self.denom) + } +} + + +/* String conversions */ +impl ToStr for Ratio { + /// Renders as `numer/denom`. + fn to_str(&self) -> ~str { + fmt!("%s/%s", self.numer.to_str(), self.denom.to_str()) + } +} +impl ToStrRadix for Ratio { + /// Renders as `numer/denom` where the numbers are in base `radix`. + fn to_str_radix(&self, radix: uint) -> ~str { + fmt!("%s/%s", self.numer.to_str_radix(radix), self.denom.to_str_radix(radix)) + } +} + +impl + Modulo + Neg + Zero + One + Ord + Eq> + FromStr for Ratio { + /// Parses `numer/denom`. + fn from_str(s: &str) -> Option> { + let split = vec::build(|push| { + for str::each_splitn_char(s, '/', 1) |s| { + push(s.to_owned()); + } + }); + if split.len() < 2 { return None; } + do FromStr::from_str(split[0]).chain |a| { + do FromStr::from_str(split[1]).chain |b| { + Some(Ratio::new(a,b)) + } + } + } +} +impl + Modulo + Neg + Zero + One + Ord + Eq> + FromStrRadix for Ratio { + /// Parses `numer/denom` where the numbers are in base `radix`. + fn from_str_radix(s: &str, radix: uint) -> Option> { + let split = vec::build(|push| { + for str::each_splitn_char(s, '/', 1) |s| { + push(s.to_owned()); + } + }); + if split.len() < 2 { None } + else { + do FromStrRadix::from_str_radix(split[0], radix).chain |a| { + do FromStrRadix::from_str_radix(split[1], radix).chain |b| { + Some(Ratio::new(a,b)) + } + } + } + } +} + +#[cfg(test)] +mod test { + use core::prelude::*; + use super::*; + use core::num::{Zero,One,FromStrRadix}; + use core::from_str::FromStr; + + pub static _0 : Rational = Ratio { numer: 0, denom: 1}; + pub static _1 : Rational = Ratio { numer: 1, denom: 1}; + pub static _2: Rational = Ratio { numer: 2, denom: 1}; + pub static _1_2: Rational = Ratio { numer: 1, denom: 2}; + pub static _3_2: Rational = Ratio { numer: 3, denom: 2}; + pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2}; + + #[test] + fn test_gcd() { + assert_eq!(gcd(10,2),2); + assert_eq!(gcd(10,3),1); + assert_eq!(gcd(0,3),3); + assert_eq!(gcd(3,3),3); + + assert_eq!(gcd(3,-3), 3); + assert_eq!(gcd(-6,3), 3); + assert_eq!(gcd(-4,-2), 2); + } + + #[test] + fn test_test_constants() { + // check our constants are what Ratio::new etc. would make. + assert_eq!(_0, Zero::zero()); + assert_eq!(_1, One::one()); + assert_eq!(_2, Ratio::from_integer(2)); + assert_eq!(_1_2, Ratio::new(1,2)); + assert_eq!(_3_2, Ratio::new(3,2)); + assert_eq!(_neg1_2, Ratio::new(-1,2)); + } + + #[test] + fn test_new_reduce() { + let one22 = Ratio::new(2i,2); + + assert_eq!(one22, One::one()); + } + #[test] + #[should_fail] + fn test_new_zero() { + let _a = Ratio::new(1,0); + } + + + #[test] + fn test_cmp() { + assert!(_0 == _0 && _1 == _1); + assert!(_0 != _1 && _1 != _0); + assert!(_0 < _1 && !(_1 < _0)); + assert!(_1 > _0 && !(_0 > _1)); + + assert!(_0 <= _0 && _1 <= _1); + assert!(_0 <= _1 && !(_1 <= _0)); + + assert!(_0 >= _0 && _1 >= _1); + assert!(_1 >= _0 && !(_0 >= _1)); + } + + + mod arith { + use super::*; + use super::super::*; + + + #[test] + fn test_add() { + assert_eq!(_1 + _1_2, _3_2); + assert_eq!(_1 + _1, _2); + assert_eq!(_1_2 + _3_2, _2); + assert_eq!(_1_2 + _neg1_2, _0); + } + + #[test] + fn test_sub() { + assert_eq!(_1 - _1_2, _1_2); + assert_eq!(_3_2 - _1_2, _1); + assert_eq!(_1 - _neg1_2, _3_2); + } + + #[test] + fn test_mul() { + assert_eq!(_1 * _1_2, _1_2); + assert_eq!(_1_2 * _3_2, Ratio::new(3,4)); + assert_eq!(_1_2 * _neg1_2, Ratio::new(-1, 4)); + } + + #[test] + fn test_div() { + assert_eq!(_1 / _1_2, _2); + assert_eq!(_3_2 / _1_2, _1 + _2); + assert_eq!(_1 / _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2); + } + + #[test] + fn test_modulo() { + assert_eq!(_3_2 % _1, _1_2); + assert_eq!(_2 % _neg1_2, _0); + assert_eq!(_1_2 % _2, _1_2); + } + + #[test] + fn test_neg() { + assert_eq!(-_0, _0); + assert_eq!(-_1_2, _neg1_2); + assert_eq!(-(-_1), _1); + } + #[test] + fn test_zero() { + assert_eq!(_0 + _0, _0); + assert_eq!(_0 * _0, _0); + assert_eq!(_0 * _1, _0); + assert_eq!(_0 / _neg1_2, _0); + assert_eq!(_0 - _0, _0); + } + #[test] + #[should_fail] + fn test_div_0() { + let _a = _1 / _0; + } + } + + #[test] + fn test_round() { + assert_eq!(_1_2.ceil(), _1); + assert_eq!(_1_2.floor(), _0); + assert_eq!(_1_2.round(num::RoundToZero), _0); + assert_eq!(_1_2.round(num::RoundFromZero), _1); + + assert_eq!(_neg1_2.ceil(), _0); + assert_eq!(_neg1_2.floor(), -_1); + assert_eq!(_neg1_2.round(num::RoundToZero), _0); + assert_eq!(_neg1_2.round(num::RoundFromZero), -_1); + + assert_eq!(_1.ceil(), _1); + assert_eq!(_1.floor(), _1); + assert_eq!(_1.round(num::RoundToZero), _1); + assert_eq!(_1.round(num::RoundFromZero), _1); + } + + #[test] + fn test_fract() { + assert_eq!(_1.fract(), _0); + assert_eq!(_neg1_2.fract(), _neg1_2); + assert_eq!(_1_2.fract(), _1_2); + assert_eq!(_3_2.fract(), _1_2); + } + + #[test] + fn test_to_from_str() { + fn test(r: Rational, s: ~str) { + assert_eq!(FromStr::from_str(s), Some(r)); + assert_eq!(r.to_str(), s); + } + test(_1, ~"1/1"); + test(_0, ~"0/1"); + test(_1_2, ~"1/2"); + test(_3_2, ~"3/2"); + test(_2, ~"2/1"); + test(_neg1_2, ~"-1/2"); + } + #[test] + fn test_from_str_fail() { + fn test(s: &str) { + assert_eq!(FromStr::from_str::(s), None); + } + + for ["0 /1", "abc", "", "1/", "--1/2","3/2/1"].each |&s| { + test(s); + } + } + + #[test] + fn test_to_from_str_radix() { + fn test(r: Rational, s: ~str, n: uint) { + assert_eq!(FromStrRadix::from_str_radix(s, n), Some(r)); + assert_eq!(r.to_str_radix(n), s); + } + fn test3(r: Rational, s: ~str) { test(r, s, 3) } + fn test16(r: Rational, s: ~str) { test(r, s, 16) } + + test3(_1, ~"1/1"); + test3(_0, ~"0/1"); + test3(_1_2, ~"1/2"); + test3(_3_2, ~"10/2"); + test3(_2, ~"2/1"); + test3(_neg1_2, ~"-1/2"); + test3(_neg1_2 / _2, ~"-1/11"); + + test16(_1, ~"1/1"); + test16(_0, ~"0/1"); + test16(_1_2, ~"1/2"); + test16(_3_2, ~"3/2"); + test16(_2, ~"2/1"); + test16(_neg1_2, ~"-1/2"); + test16(_neg1_2 / _2, ~"-1/4"); + test16(Ratio::new(13,15), ~"d/f"); + test16(_1_2*_1_2*_1_2*_1_2, ~"1/10"); + } + + #[test] + fn test_from_str_radix_fail() { + fn test(s: &str) { + assert_eq!(FromStrRadix::from_str_radix::(s, 3), None); + } + + for ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"].each |&s| { + test(s); + } + } +} \ No newline at end of file diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 30346d1b16b5a..656156b355f91 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -97,6 +97,8 @@ pub mod rl; pub mod workcache; #[path="num/bigint.rs"] pub mod bigint; +#[path="num/rational.rs"] +pub mod rational; pub mod stats; pub mod semver; pub mod fileinput; From 82d54602d7493f9a40a040d43ffe5be692582665 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Apr 2013 18:18:19 +1100 Subject: [PATCH 041/403] libstd: add basic complex numbers --- src/libstd/num/complex.rs | 316 ++++++++++++++++++++++++++++++++++++++ src/libstd/std.rc | 2 + 2 files changed, 318 insertions(+) create mode 100644 src/libstd/num/complex.rs diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs new file mode 100644 index 0000000000000..ceb1078d3f27b --- /dev/null +++ b/src/libstd/num/complex.rs @@ -0,0 +1,316 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +//! Complex numbers. + +use core::num::{Zero,One,ToStrRadix}; +use core::prelude::*; + +// FIXME #1284: handle complex NaN & infinity etc. This +// probably doesn't map to C's _Complex correctly. + +// XXX: Need generic sqrt to implement .norm(). Need generic sin/cos +// for .to/from_polar(). + + +/// A complex number in Cartesian form. +#[deriving(Eq,Clone)] +pub struct Cmplx { + re: T, + im: T +} + +pub type Complex = Cmplx; +pub type Complex32 = Cmplx; +pub type Complex64 = Cmplx; + +impl + Sub + Mul + Div + Neg> + Cmplx { + /// Create a new Cmplx + #[inline] + pub fn new(re: T, im: T) -> Cmplx { + Cmplx { re: re, im: im } + } + + /** + Returns the square of the norm (since `T` doesn't necessarily + have a sqrt function), i.e. `re^2 + im^2`. + */ + #[inline] + pub fn norm_sqr(&self) -> T { + self.re * self.re + self.im * self.im + } + + + /// Returns the complex conjugate. i.e. `re - i im` + #[inline] + pub fn conj(&self) -> Cmplx { + Cmplx::new(self.re, -self.im) + } + + + /// Multiplies `self` by the scalar `t`. + #[inline] + pub fn scale(&self, t: T) -> Cmplx { + Cmplx::new(self.re * t, self.im * t) + } + + /// Divides `self` by the scalar `t`. + #[inline] + pub fn unscale(&self, t: T) -> Cmplx { + Cmplx::new(self.re / t, self.im / t) + } + + /// Returns `1/self` + #[inline] + pub fn inv(&self) -> Cmplx { + let norm_sqr = self.norm_sqr(); + Cmplx::new(self.re / norm_sqr, + -self.im / norm_sqr) + + } +} + +/* arithmetic */ +// (a + i b) + (c + i d) == (a + c) + i (b + d) +impl + Sub + Mul + Div + Neg> + Add, Cmplx> for Cmplx { + #[inline] + fn add(&self, other: &Cmplx) -> Cmplx { + Cmplx::new(self.re + other.re, self.im + other.im) + } +} +// (a + i b) - (c + i d) == (a - c) + i (b - d) +impl + Sub + Mul + Div + Neg> + Sub, Cmplx> for Cmplx { + #[inline] + fn sub(&self, other: &Cmplx) -> Cmplx { + Cmplx::new(self.re - other.re, self.im - other.im) + } +} +// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) +impl + Sub + Mul + Div + Neg> + Mul, Cmplx> for Cmplx { + #[inline] + fn mul(&self, other: &Cmplx) -> Cmplx { + Cmplx::new(self.re*other.re - self.im*other.im, + self.re*other.im + self.im*other.re) + } +} + +// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d) +// == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)] +impl + Sub + Mul + Div + Neg> + Div, Cmplx> for Cmplx { + #[inline] + fn div(&self, other: &Cmplx) -> Cmplx { + let norm_sqr = other.norm_sqr(); + Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr, + (self.im*other.re - self.re*other.im) / norm_sqr) + } +} + +impl + Sub + Mul + Div + Neg> + Neg> for Cmplx { + #[inline] + fn neg(&self) -> Cmplx { + Cmplx::new(-self.re, -self.im) + } +} + +/* constants */ +impl + Sub + Mul + Div + Neg + Zero> + Zero for Cmplx { + #[inline] + fn zero() -> Cmplx { + Cmplx::new(Zero::zero(), Zero::zero()) + } +} + +impl + Sub + Mul + Div + Neg + Zero + One> + One for Cmplx { + #[inline] + fn one() -> Cmplx { + Cmplx::new(One::one(), Zero::zero()) + } +} + +/* string conversions */ +impl> ToStr for Cmplx { + fn to_str(&self) -> ~str { + if self.im < Zero::zero() { + fmt!("%s-%si", self.re.to_str(), (-self.im).to_str()) + } else { + fmt!("%s+%si", self.re.to_str(), self.im.to_str()) + } + } +} + +impl> ToStrRadix for Cmplx { + fn to_str_radix(&self, radix: uint) -> ~str { + if self.im < Zero::zero() { + fmt!("%s-%si", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix)) + } else { + fmt!("%s+%si", self.re.to_str_radix(radix), self.im.to_str_radix(radix)) + } + } +} + +#[cfg(test)] +mod test { + use core::prelude::*; + use super::*; + use core::num::{Zero,One}; + + pub static _0_0i : Complex = Cmplx { re: 0f, im: 0f }; + pub static _1_0i : Complex = Cmplx { re: 1f, im: 0f }; + pub static _1_1i : Complex = Cmplx { re: 1f, im: 1f }; + pub static _0_1i : Complex = Cmplx { re: 0f, im: 1f }; + pub static _neg1_1i : Complex = Cmplx { re: -1f, im: 1f }; + pub static _05_05i : Complex = Cmplx { re: 0.5f, im: 0.5f }; + pub static all_consts : [Complex, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i]; + + #[test] + fn test_consts() { + // check our constants are what Cmplx::new creates + fn test(c : Complex, r : float, i: float) { + assert_eq!(c, Cmplx::new(r,i)); + } + test(_0_0i, 0f, 0f); + test(_1_0i, 1f, 0f); + test(_1_1i, 1f, 1f); + test(_neg1_1i, -1f, 1f); + test(_05_05i, 0.5f, 0.5f); + + assert_eq!(_0_0i, Zero::zero()); + assert_eq!(_1_0i, One::one()); + } + + #[test] + fn test_norm_sqr() { + fn test(c: Complex, ns: float) { + assert_eq!(c.norm_sqr(), ns); + } + test(_0_0i, 0f); + test(_1_0i, 1f); + test(_1_1i, 2f); + test(_neg1_1i, 2f); + test(_05_05i, 0.5f); + } + + #[test] + fn test_scale_unscale() { + assert_eq!(_05_05i.scale(2f), _1_1i); + assert_eq!(_1_1i.unscale(2f), _05_05i); + for all_consts.each |&c| { + assert_eq!(c.scale(2f).unscale(2f), c); + } + } + + #[test] + fn test_conj() { + for all_consts.each |&c| { + assert_eq!(c.conj(), Cmplx::new(c.re, -c.im)); + assert_eq!(c.conj().conj(), c); + } + } + + #[test] + fn test_inv() { + assert_eq!(_1_1i.inv(), _05_05i.conj()); + assert_eq!(_1_0i.inv(), _1_0i.inv()); + } + + #[test] + #[should_fail] + #[ignore] + fn test_inv_zero() { + // XXX: should this really fail, or just NaN? + _0_0i.inv(); + } + + + mod arith { + use super::*; + use super::super::*; + use core::num::Zero; + + #[test] + fn test_add() { + assert_eq!(_05_05i + _05_05i, _1_1i); + assert_eq!(_0_1i + _1_0i, _1_1i); + assert_eq!(_1_0i + _neg1_1i, _0_1i); + + for all_consts.each |&c| { + assert_eq!(_0_0i + c, c); + assert_eq!(c + _0_0i, c); + } + } + + #[test] + fn test_sub() { + assert_eq!(_05_05i - _05_05i, _0_0i); + assert_eq!(_0_1i - _1_0i, _neg1_1i); + assert_eq!(_0_1i - _neg1_1i, _1_0i); + + for all_consts.each |&c| { + assert_eq!(c - _0_0i, c); + assert_eq!(c - c, _0_0i); + } + } + + #[test] + fn test_mul() { + assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2f)); + assert_eq!(_1_1i * _0_1i, _neg1_1i); + + // i^2 & i^4 + assert_eq!(_0_1i * _0_1i, -_1_0i); + assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i); + + for all_consts.each |&c| { + assert_eq!(c * _1_0i, c); + assert_eq!(_1_0i * c, c); + } + } + #[test] + fn test_div() { + assert_eq!(_neg1_1i / _0_1i, _1_1i); + for all_consts.each |&c| { + if c != Zero::zero() { + assert_eq!(c / c, _1_0i); + } + } + } + #[test] + fn test_neg() { + assert_eq!(-_1_0i + _0_1i, _neg1_1i); + assert_eq!((-_0_1i) * _0_1i, _1_0i); + for all_consts.each |&c| { + assert_eq!(-(-c), c); + } + } + } + + #[test] + fn test_to_str() { + fn test(c : Complex, s: ~str) { + assert_eq!(c.to_str(), s); + } + test(_0_0i, ~"0+0i"); + test(_1_0i, ~"1+0i"); + test(_0_1i, ~"0+1i"); + test(_1_1i, ~"1+1i"); + test(_neg1_1i, ~"-1+1i"); + test(-_neg1_1i, ~"1-1i"); + test(_05_05i, ~"0.5+0.5i"); + } +} diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 656156b355f91..9aac8d230558d 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -99,6 +99,8 @@ pub mod workcache; pub mod bigint; #[path="num/rational.rs"] pub mod rational; +#[path="num/complex.rs"] +pub mod complex; pub mod stats; pub mod semver; pub mod fileinput; From c6949b3669d23a1694b964108f21d5200c985cb5 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Apr 2013 19:26:58 +1100 Subject: [PATCH 042/403] libstd: make complex.rs XXX's into issues and FIXME's --- src/libstd/num/complex.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs index ceb1078d3f27b..1e8fc0e6c2baa 100644 --- a/src/libstd/num/complex.rs +++ b/src/libstd/num/complex.rs @@ -17,8 +17,8 @@ use core::prelude::*; // FIXME #1284: handle complex NaN & infinity etc. This // probably doesn't map to C's _Complex correctly. -// XXX: Need generic sqrt to implement .norm(). Need generic sin/cos -// for .to/from_polar(). +// FIXME #5734:: Need generic sin/cos for .to/from_polar(). +// FIXME #5735: Need generic sqrt to implement .norm(). /// A complex number in Cartesian form. @@ -75,7 +75,6 @@ impl + Sub + Mul + Div + Neg> let norm_sqr = self.norm_sqr(); Cmplx::new(self.re / norm_sqr, -self.im / norm_sqr) - } } @@ -233,7 +232,7 @@ mod test { #[should_fail] #[ignore] fn test_inv_zero() { - // XXX: should this really fail, or just NaN? + // FIXME #5736: should this really fail, or just NaN? _0_0i.inv(); } From 1745a2cd08d1aa7437ec3d080c9ca85434b54cf5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 26 Mar 2013 16:27:34 -0400 Subject: [PATCH 043/403] refactor check_call_inner to have a better name and be readable --- src/librustc/middle/typeck/check/mod.rs | 190 +++++++++++------------- 1 file changed, 86 insertions(+), 104 deletions(-) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index eba207f978b6e..516ec3a50cd96 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1122,9 +1122,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, unifier: &fn()) { debug!(">> typechecking %s", fcx.expr_to_str(expr)); - // A generic function to factor out common logic from call and - // overloaded operations - fn check_call_inner( + fn check_argument_types( fcx: @mut FnCtxt, sp: span, call_expr_id: ast::node_id, @@ -1134,18 +1132,24 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, sugar: ast::CallSugar, deref_args: DerefArgs) -> ty::t { + /*! + * + * Generic function that factors out common logic from + * function calls, method calls and overloaded operators. + */ + let tcx = fcx.ccx.tcx; // Replace all region parameters in the arguments and return // type with fresh region variables. - debug!("check_call_inner: before universal quant., in_fty=%s", + debug!("check_argument_types: before universal quant., in_fty=%s", fcx.infcx().ty_to_str(in_fty)); - let formal_tys; + let sty = structure_of(fcx, sp, in_fty); // FIXME(#3678) For now, do not permit calls to C abi functions. - match structure_of(fcx, sp, in_fty) { + match sty { ty::ty_bare_fn(ty::BareFnTy {abis, _}) => { if !abis.is_rust() { tcx.sess.span_err( @@ -1157,68 +1161,65 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, _ => {} } - // This is subtle: we expect `fty` to be a function type, which - // normally introduce a level of binding. In this case, we want to - // process the types bound by the function but not by any nested - // functions. Therefore, we match one level of structure. - let ret_ty = match structure_of(fcx, sp, in_fty) { - ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) | - ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => { - let (_, _, sig) = - replace_bound_regions_in_fn_sig( - tcx, @Nil, None, sig, - |_br| fcx.infcx().next_region_var( - sp, call_expr_id)); - - let supplied_arg_count = args.len(); - - // Grab the argument types, supplying fresh type variables - // if the wrong number of arguments were supplied - let expected_arg_count = sig.inputs.len(); - formal_tys = if expected_arg_count == supplied_arg_count { - sig.inputs.map(|a| a.ty) - } else { - let suffix = match sugar { - ast::NoSugar => "", - ast::DoSugar => " (including the closure passed by \ - the `do` keyword)", - ast::ForSugar => " (including the closure passed by \ - the `for` keyword)" - }; - let msg = fmt!("this function takes %u parameter%s but \ - %u parameter%s supplied%s", - expected_arg_count, - if expected_arg_count == 1 {""} - else {"s"}, - supplied_arg_count, - if supplied_arg_count == 1 {" was"} - else {"s were"}, - suffix); - - tcx.sess.span_err(sp, msg); - - vec::from_fn(supplied_arg_count, |_| ty::mk_err(tcx)) - }; - - sig.output - } - + // Extract the function signature from `in_fty`. + let sig = match sty { + ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) | + ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig, _ => { fcx.type_error_message(sp, |actual| { - fmt!("expected function or foreign function but \ + fmt!("expected function but \ found `%s`", actual) }, in_fty, None); // check each arg against "error", in order to set up // all the node type bindings - formal_tys = args.map(|_x| ty::mk_err(tcx)); - ty::mk_err(tcx) + FnSig {bound_lifetime_names: opt_vec::Empty, + inputs: args.map(|_x| ty::arg {mode: ast::expl(ast::by_copy), + ty: ty::mk_err(tcx)}), + output: ty::mk_err(tcx)} } }; - debug!("check_call_inner: after universal quant., \ - formal_tys=%? ret_ty=%s", + // Replace any bound regions that appear in the function + // signature with region variables + let (_, _, sig) = + replace_bound_regions_in_fn_sig( + tcx, @Nil, None, &sig, + |_br| fcx.infcx().next_region_var( + sp, call_expr_id)); + + // Grab the argument types, supplying fresh type variables + // if the wrong number of arguments were supplied + let supplied_arg_count = args.len(); + let expected_arg_count = sig.inputs.len(); + let formal_tys = if expected_arg_count == supplied_arg_count { + sig.inputs.map(|a| a.ty) + } else { + let suffix = match sugar { + ast::NoSugar => "", + ast::DoSugar => " (including the closure passed by \ + the `do` keyword)", + ast::ForSugar => " (including the closure passed by \ + the `for` keyword)" + }; + let msg = fmt!("this function takes %u parameter%s but \ + %u parameter%s supplied%s", + expected_arg_count, + if expected_arg_count == 1 {""} + else {"s"}, + supplied_arg_count, + if supplied_arg_count == 1 {" was"} + else {"s were"}, + suffix); + + tcx.sess.span_err(sp, msg); + + vec::from_elem(supplied_arg_count, ty::mk_err(tcx)) + }; + + debug!("check_argument_types: after universal quant., \ + formal_tys=%? sig.output=%s", formal_tys.map(|t| fcx.infcx().ty_to_str(*t)), - fcx.infcx().ty_to_str(ret_ty)); + fcx.infcx().ty_to_str(sig.output)); // Check the arguments. // We do this in a pretty awful way: first we typecheck any arguments @@ -1269,7 +1270,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - ret_ty + sig.output } // A generic function for checking assignment expressions @@ -1284,43 +1285,23 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // The callee checks for bot / err, we don't need to } - // A generic function for doing all of the checking for call or - // method expressions - fn check_call_or_method(fcx: @mut FnCtxt, - sp: span, - call_expr_id: ast::node_id, - fn_ty: ty::t, - expr: @ast::expr, - args: &[@ast::expr], - sugar: ast::CallSugar) - { - - // Call the generic checker. - let ret_ty = check_call_inner(fcx, sp, call_expr_id, - fn_ty, expr, args, sugar, - DontDerefArgs); - // Pull the return type out of the type of the function. - fcx.write_ty(call_expr_id, ret_ty); - // Callee checks for bot and err, no need for that - } - // A generic function for doing all of the checking for call expressions fn check_call(fcx: @mut FnCtxt, - sp: span, - call_expr_id: ast::node_id, + call_expr: @ast::expr, f: @ast::expr, args: &[@ast::expr], sugar: ast::CallSugar) { // Index expressions need to be handled separately, to inform them // that they appear in call position. - let mut _bot = check_expr(fcx, f); - check_call_or_method(fcx, - sp, - call_expr_id, - fcx.expr_ty(f), - f, - args, - sugar) + check_expr(fcx, f); + + // Call the generic checker. + let ret_ty = check_argument_types(fcx, call_expr.span, call_expr.id, + fcx.expr_ty(f), f, args, sugar, + DontDerefArgs); + + // Pull the return type out of the type of the function. + fcx.write_ty(call_expr.id, ret_ty); } // Checks a method call. @@ -1369,13 +1350,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - check_call_or_method(fcx, - expr.span, - expr.id, - fcx.node_ty(expr.callee_id), - expr, - args, - sugar) + // Call the generic checker. + let fn_ty = fcx.node_ty(expr.callee_id); + let ret_ty = check_argument_types(fcx, expr.span, expr.id, + fn_ty, expr, args, sugar, + DontDerefArgs); + + // Pull the return type out of the type of the function. + fcx.write_ty(expr.id, ret_ty); } // A generic function for checking the then and else in an if @@ -1423,10 +1405,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let method_ty = fcx.node_ty(op_ex.callee_id); let method_map = fcx.inh.method_map; method_map.insert(op_ex.id, *origin); - check_call_inner(fcx, op_ex.span, - op_ex.id, method_ty, - op_ex, args, - ast::NoSugar, deref_args) + check_argument_types(fcx, op_ex.span, + op_ex.id, method_ty, + op_ex, args, + ast::NoSugar, deref_args) } _ => { let tcx = fcx.tcx(); @@ -1434,9 +1416,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Check the args anyway // so we get all the error messages let expected_ty = ty::mk_err(tcx); - check_call_inner(fcx, op_ex.span, op_ex.id, - expected_ty, op_ex, args, - ast::NoSugar, deref_args); + check_argument_types(fcx, op_ex.span, op_ex.id, + expected_ty, op_ex, args, + ast::NoSugar, deref_args); ty::mk_err(tcx) } } @@ -2546,7 +2528,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, fcx.node_ty(b.node.id)); } ast::expr_call(f, ref args, sugar) => { - check_call(fcx, expr.span, expr.id, f, *args, sugar); + check_call(fcx, expr, f, *args, sugar); let f_ty = fcx.expr_ty(f); let (args_bot, args_err) = args.foldl((false, false), |&(rest_bot, rest_err), a| { From d94830830f81bde37124efd6b4c8b6c9649180e0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 27 Mar 2013 05:40:56 -0400 Subject: [PATCH 044/403] Move the replacement of bound regions out from `check_arguments` and into check_call / method_resolution --- src/librustc/middle/moves.rs | 6 +- src/librustc/middle/ty.rs | 10 ++ src/librustc/middle/typeck/check/method.rs | 40 ++++- src/librustc/middle/typeck/check/mod.rs | 164 ++++++++++++--------- 4 files changed, 142 insertions(+), 78 deletions(-) diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 2f379ece5d374..7740485e82c00 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -463,7 +463,7 @@ pub impl VisitContext { expr_method_call(callee, _, _, ref args, _) => { // callee.m(args) // Implicit self is equivalent to & mode, but every // other kind should be + mode. - self.use_receiver(expr.id, expr.span, callee, visitor); + self.use_receiver(callee, visitor); self.use_fn_args(expr.callee_id, *args, visitor); } @@ -665,7 +665,7 @@ pub impl VisitContext { return false; } - self.use_receiver(expr.id, expr.span, receiver_expr, visitor); + self.use_receiver(receiver_expr, visitor); // for overloaded operatrs, we are always passing in a // borrowed pointer, so it's always read mode: @@ -718,8 +718,6 @@ pub impl VisitContext { } fn use_receiver(&self, - _expr_id: node_id, - _span: span, receiver_expr: @expr, visitor: vt) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 30b933061e215..19ffb4edc8447 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2726,6 +2726,16 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool { cx.node_type_substs.contains_key(&id) } +pub fn ty_fn_sig(fty: t) -> FnSig { + match get(fty).sty { + ty_bare_fn(ref f) => copy f.sig, + ty_closure(ref f) => copy f.sig, + ref s => { + fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s)) + } + } +} + // Type accessors for substructures of types pub fn ty_fn_args(fty: t) -> ~[arg] { match get(fty).sty { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 3b01f0e839ab9..69d8fb495e131 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -92,6 +92,7 @@ use middle::typeck::check; use middle::typeck::infer; use middle::typeck::{method_map_entry, method_origin, method_param}; use middle::typeck::{method_self, method_static, method_trait, method_super}; +use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use util::common::indenter; use util::ppaux::expr_repr; @@ -99,6 +100,7 @@ use core::hashmap::HashSet; use core::result; use core::uint; use core::vec; +use std::list::Nil; use syntax::ast::{def_id, sty_value, sty_region, sty_box}; use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref}; use syntax::ast::{m_const, m_mutbl, m_imm}; @@ -121,7 +123,7 @@ pub fn lookup( fcx: @mut FnCtxt, // In a call `a.b::(...)`: - expr: @ast::expr, // The expression `a.b`. + expr: @ast::expr, // The expression `a.b(...)`. self_expr: @ast::expr, // The expression `a`. callee_id: node_id, // Where to store `a.b`'s type m_name: ast::ident, // The ident `b`. @@ -1092,10 +1094,16 @@ pub impl<'self> LookupContext<'self> { fn confirm_candidate(&self, self_ty: ty::t, candidate: &Candidate) - -> method_map_entry { + -> method_map_entry + { let tcx = self.tcx(); let fty = self.fn_ty_from_origin(&candidate.origin); + debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)", + expr_repr(tcx, self.expr), + self.cand_to_str(candidate), + self.ty_to_str(fty)); + self.enforce_trait_instance_limitations(fty, candidate); self.enforce_drop_trait_limitations(candidate); @@ -1145,7 +1153,33 @@ pub impl<'self> LookupContext<'self> { ../*bad*/copy candidate.rcvr_substs }; - self.fcx.write_ty_substs(self.callee_id, fty, all_substs); + // Compute the method type with type parameters substituted + debug!("fty=%s all_substs=%s", + self.ty_to_str(fty), + ty::substs_to_str(tcx, &all_substs)); + let fty = ty::subst(tcx, &all_substs, fty); + debug!("after subst, fty=%s", self.ty_to_str(fty)); + + // Replace any bound regions that appear in the function + // signature with region variables + let bare_fn_ty = match ty::get(fty).sty { + ty::ty_bare_fn(ref f) => copy *f, + ref s => { + tcx.sess.span_bug( + self.expr.span, + fmt!("Invoking method with non-bare-fn ty: %?", s)); + } + }; + let (_, _, fn_sig) = + replace_bound_regions_in_fn_sig( + tcx, @Nil, None, &bare_fn_ty.sig, + |_br| self.fcx.infcx().next_region_var( + self.expr.span, self.expr.id)); + let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty}); + debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty)); + + self.fcx.write_ty(self.callee_id, fty); + self.fcx.write_substs(self.callee_id, all_substs); method_map_entry { self_arg: arg { mode: ast::expl(candidate.self_mode), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 516ec3a50cd96..3200949577217 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1122,15 +1122,43 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, unifier: &fn()) { debug!(">> typechecking %s", fcx.expr_to_str(expr)); - fn check_argument_types( + fn check_method_argument_types( fcx: @mut FnCtxt, sp: span, - call_expr_id: ast::node_id, - in_fty: ty::t, + method_fn_ty: ty::t, callee_expr: @ast::expr, args: &[@ast::expr], sugar: ast::CallSugar, deref_args: DerefArgs) -> ty::t + { + match ty::get(method_fn_ty).sty { + ty::ty_bare_fn(ref fty) => { + check_argument_types(fcx, sp, fty.sig.inputs, callee_expr, + args, sugar, deref_args); + fty.sig.output + } + ty::ty_err => { + let err_inputs = err_args(fcx.tcx(), args.len()); + check_argument_types(fcx, sp, err_inputs, callee_expr, + args, sugar, deref_args); + method_fn_ty + } + _ => { + fcx.tcx().sess.span_bug( + sp, + fmt!("Method without bare fn type")); + } + } + } + + fn check_argument_types( + fcx: @mut FnCtxt, + sp: span, + fn_inputs: &[ty::arg], + callee_expr: @ast::expr, + args: &[@ast::expr], + sugar: ast::CallSugar, + deref_args: DerefArgs) { /*! * @@ -1140,59 +1168,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let tcx = fcx.ccx.tcx; - // Replace all region parameters in the arguments and return - // type with fresh region variables. - - debug!("check_argument_types: before universal quant., in_fty=%s", - fcx.infcx().ty_to_str(in_fty)); - - let sty = structure_of(fcx, sp, in_fty); - - // FIXME(#3678) For now, do not permit calls to C abi functions. - match sty { - ty::ty_bare_fn(ty::BareFnTy {abis, _}) => { - if !abis.is_rust() { - tcx.sess.span_err( - sp, - fmt!("Calls to C ABI functions are not (yet) \ - supported; be patient, dear user")); - } - } - _ => {} - } - - // Extract the function signature from `in_fty`. - let sig = match sty { - ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) | - ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig, - _ => { - fcx.type_error_message(sp, |actual| { - fmt!("expected function but \ - found `%s`", actual) }, in_fty, None); - - // check each arg against "error", in order to set up - // all the node type bindings - FnSig {bound_lifetime_names: opt_vec::Empty, - inputs: args.map(|_x| ty::arg {mode: ast::expl(ast::by_copy), - ty: ty::mk_err(tcx)}), - output: ty::mk_err(tcx)} - } - }; - - // Replace any bound regions that appear in the function - // signature with region variables - let (_, _, sig) = - replace_bound_regions_in_fn_sig( - tcx, @Nil, None, &sig, - |_br| fcx.infcx().next_region_var( - sp, call_expr_id)); - // Grab the argument types, supplying fresh type variables // if the wrong number of arguments were supplied let supplied_arg_count = args.len(); - let expected_arg_count = sig.inputs.len(); + let expected_arg_count = fn_inputs.len(); let formal_tys = if expected_arg_count == supplied_arg_count { - sig.inputs.map(|a| a.ty) + fn_inputs.map(|a| a.ty) } else { let suffix = match sugar { ast::NoSugar => "", @@ -1216,10 +1197,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, vec::from_elem(supplied_arg_count, ty::mk_err(tcx)) }; - debug!("check_argument_types: after universal quant., \ - formal_tys=%? sig.output=%s", - formal_tys.map(|t| fcx.infcx().ty_to_str(*t)), - fcx.infcx().ty_to_str(sig.output)); + debug!("check_argument_types: formal_tys=%?", + formal_tys.map(|t| fcx.infcx().ty_to_str(*t))); // Check the arguments. // We do this in a pretty awful way: first we typecheck any arguments @@ -1269,8 +1248,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } } + } - sig.output + fn err_args(tcx: ty::ctxt, len: uint) -> ~[ty::arg] { + vec::from_fn(len, |_| ty::arg {mode: ast::expl(ast::by_copy), + ty: ty::mk_err(tcx)}) } // A generic function for checking assignment expressions @@ -1295,13 +1277,53 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // that they appear in call position. check_expr(fcx, f); + + // Extract the function signature from `in_fty`. + let fn_ty = fcx.expr_ty(f); + let fn_sty = structure_of(fcx, f.span, fn_ty); + + // FIXME(#3678) For now, do not permit calls to C abi functions. + match fn_sty { + ty::ty_bare_fn(ty::BareFnTy {abis, _}) => { + if !abis.is_rust() { + fcx.tcx().sess.span_err( + call_expr.span, + fmt!("Calls to C ABI functions are not (yet) \ + supported; be patient, dear user")); + } + } + _ => {} + } + + let fn_sig = match fn_sty { + ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) | + ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig, + _ => { + fcx.type_error_message(call_expr.span, |actual| { + fmt!("expected function but \ + found `%s`", actual) }, fn_ty, None); + + // check each arg against "error", in order to set up + // all the node type bindings + FnSig {bound_lifetime_names: opt_vec::Empty, + inputs: err_args(fcx.tcx(), args.len()), + output: ty::mk_err(fcx.tcx())} + } + }; + + // Replace any bound regions that appear in the function + // signature with region variables + let (_, _, fn_sig) = + replace_bound_regions_in_fn_sig( + fcx.tcx(), @Nil, None, &fn_sig, + |_br| fcx.infcx().next_region_var(call_expr.span, call_expr.id)); + // Call the generic checker. - let ret_ty = check_argument_types(fcx, call_expr.span, call_expr.id, - fcx.expr_ty(f), f, args, sugar, - DontDerefArgs); + check_argument_types(fcx, call_expr.span, fn_sig.inputs, f, + args, sugar, DontDerefArgs); // Pull the return type out of the type of the function. - fcx.write_ty(call_expr.id, ret_ty); + fcx.write_ty(call_expr.id, fn_sig.output); } // Checks a method call. @@ -1313,6 +1335,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, tps: &[@ast::Ty], sugar: ast::CallSugar) { check_expr(fcx, rcvr); + // no need to check for bot/err -- callee does that let expr_t = structurally_resolved_type(fcx, expr.span, @@ -1352,9 +1375,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Call the generic checker. let fn_ty = fcx.node_ty(expr.callee_id); - let ret_ty = check_argument_types(fcx, expr.span, expr.id, - fn_ty, expr, args, sugar, - DontDerefArgs); + let ret_ty = check_method_argument_types(fcx, expr.span, + fn_ty, expr, args, sugar, + DontDerefArgs); // Pull the return type out of the type of the function. fcx.write_ty(expr.id, ret_ty); @@ -1405,10 +1428,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let method_ty = fcx.node_ty(op_ex.callee_id); let method_map = fcx.inh.method_map; method_map.insert(op_ex.id, *origin); - check_argument_types(fcx, op_ex.span, - op_ex.id, method_ty, - op_ex, args, - ast::NoSugar, deref_args) + check_method_argument_types(fcx, op_ex.span, + method_ty, op_ex, args, + ast::NoSugar, deref_args) } _ => { let tcx = fcx.tcx(); @@ -1416,9 +1438,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Check the args anyway // so we get all the error messages let expected_ty = ty::mk_err(tcx); - check_argument_types(fcx, op_ex.span, op_ex.id, - expected_ty, op_ex, args, - ast::NoSugar, deref_args); + check_method_argument_types(fcx, op_ex.span, + expected_ty, op_ex, args, + ast::NoSugar, deref_args); ty::mk_err(tcx) } } From 007abe935209ab35d85e1b7fa0bfc88460340560 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 27 Mar 2013 10:26:57 -0400 Subject: [PATCH 045/403] Rather than storing a list of ty::method per trait, store one ty::method per method and list of def-ids per trait. --- src/librustc/metadata/common.rs | 4 + src/librustc/metadata/csearch.rs | 29 ++-- src/librustc/metadata/decoder.rs | 102 ++++++------- src/librustc/metadata/encoder.rs | 175 ++++++++++++---------- src/librustc/metadata/tydecode.rs | 6 + src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/astencode.rs | 1 + src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/moves.rs | 2 +- src/librustc/middle/region.rs | 4 +- src/librustc/middle/resolve.rs | 71 +++++---- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/meth.rs | 26 ++-- src/librustc/middle/trans/reflect.rs | 2 +- src/librustc/middle/ty.rs | 115 +++++++++----- src/librustc/middle/typeck/astconv.rs | 10 +- src/librustc/middle/typeck/check/mod.rs | 16 +- src/librustc/middle/typeck/coherence.rs | 6 +- src/librustc/middle/typeck/collect.rs | 153 ++++++++++--------- src/librustc/util/ppaux.rs | 2 +- src/libsyntax/ast.rs | 1 + src/libsyntax/ast_util.rs | 2 +- src/test/compile-fail/extern-no-call.rs | 2 +- src/test/compile-fail/issue-3563.rs | 2 +- 24 files changed, 414 insertions(+), 323 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 920631a55b4ec..d3b06009d727e 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -102,6 +102,7 @@ pub static tag_item_dtor: uint = 0x49u; pub static tag_item_trait_method_self_ty: uint = 0x4b; pub static tag_item_trait_method_self_ty_region: uint = 0x4c; + // Reexports are found within module tags. Each reexport contains def_ids // and names. pub static tag_items_data_item_reexport: uint = 0x4d; @@ -159,6 +160,9 @@ pub static tag_items_data_item_visibility: uint = 0x78; pub static tag_link_args: uint = 0x79; pub static tag_link_args_arg: uint = 0x7a; +pub static tag_item_method_tps: uint = 0x7b; +pub static tag_item_method_fty: uint = 0x7c; + pub struct LinkMeta { name: @str, vers: @str, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 16b896f11d6a4..8e7ecdec638b1 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -111,12 +111,24 @@ pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id, } } -pub fn get_trait_methods(tcx: ty::ctxt, - def: ast::def_id) - -> @~[ty::method] { - let cstore = tcx.cstore; +pub fn get_method(tcx: ty::ctxt, + def: ast::def_id) -> ty::method +{ + let cdata = cstore::get_crate_data(tcx.cstore, def.crate); + decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx) +} + +pub fn get_method_name_and_self_ty(cstore: @mut cstore::CStore, + def: ast::def_id) -> (ast::ident, ast::self_ty_) +{ + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_method_name_and_self_ty(cstore.intr, cdata, def.node) +} + +pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore, + def: ast::def_id) -> ~[ast::def_id] { let cdata = cstore::get_crate_data(cstore, def.crate); - decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx) + decoder::get_trait_method_def_ids(cdata, def.node) } pub fn get_provided_trait_methods(tcx: ty::ctxt, @@ -133,13 +145,6 @@ pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { decoder::get_supertraits(cdata, def.node, tcx) } -pub fn get_method_names_if_trait(cstore: @mut cstore::CStore, - def: ast::def_id) - -> Option<~[(ast::ident, ast::self_ty_)]> { - let cdata = cstore::get_crate_data(cstore, def.crate); - return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node); -} - pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::def_id) -> Option { let cdata = cstore::get_crate_data(cstore, def.crate); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index dcea22b09d6d6..800df628bc23a 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -19,7 +19,8 @@ use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; use metadata::csearch; use metadata::cstore; use metadata::decoder; -use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data}; +use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, + parse_bare_fn_ty_data}; use middle::{ty, resolve}; use core::hash::HashUtil; @@ -229,6 +230,12 @@ fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { |_, did| translate_def_id(cdata, did)) } +fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy { + let tp = reader::get_doc(doc, tag_item_method_fty); + parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx, + |_, did| translate_def_id(cdata, did)) +} + pub fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let t = doc_type(item, tcx, cdata); @@ -247,10 +254,11 @@ fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { results } -fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) +fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd, + tag: uint) -> @~[ty::param_bounds] { let mut bounds = ~[]; - for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| { + for reader::tagged_docs(item, tag) |p| { let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, |_, did| translate_def_id(cdata, did)); bounds.push(bd); @@ -338,7 +346,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) let enum_did = item_reqd_and_translated_parent_item(cnum, item); dl_def(ast::def_variant(enum_did, did)) } - Trait | Enum => dl_def(ast::def_ty(did)), + Trait => dl_def(ast::def_trait(did)), + Enum => dl_def(ast::def_ty(did)), Impl => dl_impl(did), PublicField | PrivateField | InheritedField => dl_field, } @@ -359,7 +368,7 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx, cdata); let tp_bounds = if family_has_type_params(item_family(item)) { - item_ty_param_bounds(item, tcx, cdata) + item_ty_param_bounds(item, tcx, cdata, tag_items_data_item_ty_param_bounds) } else { @~[] }; let rp = item_ty_region_param(item); ty::ty_param_bounds_and_ty { @@ -690,36 +699,46 @@ pub fn get_impls_for_mod(intr: @ident_interner, @result } -/* Works for both classes and traits */ -pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, - tcx: ty::ctxt) -> @~[ty::method] { +pub fn get_method_name_and_self_ty( + intr: @ident_interner, + cdata: cmd, + id: ast::node_id) -> (ast::ident, ast::self_ty_) +{ + let method_doc = lookup_item(id, cdata.data); + let name = item_name(intr, method_doc); + let self_ty = get_self_ty(method_doc); + (name, self_ty) +} + +pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, + tcx: ty::ctxt) -> ty::method +{ + let method_doc = lookup_item(id, cdata.data); + let bounds = item_ty_param_bounds(method_doc, tcx, cdata, + tag_item_method_tps); + let name = item_name(intr, method_doc); + let def_id = item_def_id(method_doc, cdata); + let fty = doc_method_fty(method_doc, tcx, cdata); + let self_ty = get_self_ty(method_doc); + ty::method { + ident: name, + tps: bounds, + fty: fty, + self_ty: self_ty, + vis: ast::public, + def_id: def_id + } +} + +pub fn get_trait_method_def_ids(cdata: cmd, + id: ast::node_id) -> ~[ast::def_id] { let data = cdata.data; let item = lookup_item(id, data); let mut result = ~[]; for reader::tagged_docs(item, tag_item_trait_method) |mth| { - let bounds = item_ty_param_bounds(mth, tcx, cdata); - let name = item_name(intr, mth); - let ty = doc_type(mth, tcx, cdata); - let def_id = item_def_id(mth, cdata); - let fty = match ty::get(ty).sty { - ty::ty_bare_fn(ref f) => copy *f, - _ => { - tcx.diag.handler().bug( - ~"get_trait_methods: id has non-function type"); - } - }; - let self_ty = get_self_ty(mth); - result.push(ty::method { - ident: name, - tps: bounds, - fty: fty, - self_ty: self_ty, - vis: ast::public, - def_id: def_id - }); + result.push(item_def_id(mth, cdata)); } - debug!("get_trait_methods: }"); - @result + result } pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, @@ -734,7 +753,8 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let did = item_def_id(mth, cdata); - let bounds = item_ty_param_bounds(mth, tcx, cdata); + let bounds = item_ty_param_bounds(mth, tcx, cdata, + tag_items_data_item_ty_param_bounds); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); @@ -777,26 +797,6 @@ pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) return results; } -// If the item in question is a trait, returns its set of methods and -// their self types. Otherwise, returns none. This overlaps in an -// annoying way with get_trait_methods. -pub fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd, - node_id: ast::node_id) - -> Option<~[(ast::ident, ast::self_ty_)]> { - - let item = lookup_item(node_id, cdata.data); - if item_family(item) != Trait { - return None; - } - - let mut resulting_methods = ~[]; - for reader::tagged_docs(item, tag_item_trait_method) |method| { - resulting_methods.push( - (item_name(intr, method), get_self_ty(method))); - } - return Some(resulting_methods); -} - pub fn get_type_name_if_impl(intr: @ident_interner, cdata: cmd, node_id: ast::node_id) -> Option { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6000e559554f3..61501d8308331 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -170,8 +170,10 @@ fn encode_family(ebml_w: writer::Encoder, c: char) { pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext, - params: @~[ty::param_bounds]) { +fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, + ecx: @EncodeContext, + params: @~[ty::param_bounds], + tag: uint) { let ty_str_ctxt = @tyencode::ctxt { diag: ecx.diag, ds: def_to_str, @@ -179,7 +181,7 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext, reachable: |a| reachable(ecx, a), abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; for params.each |param| { - ebml_w.start_tag(tag_items_data_item_ty_param_bounds); + ebml_w.start_tag(tag); tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param); ebml_w.end_tag(); } @@ -190,7 +192,8 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder, params: &OptVec) { let ty_param_bounds = @params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(¶m.id)); - encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds); + encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds, + tag_items_data_item_ty_param_bounds); } @@ -227,6 +230,23 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { ebml_w.end_tag(); } +fn encode_method_fty(ecx: @EncodeContext, + ebml_w: writer::Encoder, + typ: &ty::BareFnTy) +{ + ebml_w.start_tag(tag_item_method_fty); + + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ); + + ebml_w.end_tag(); +} + fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); match ecx.item_symbols.find(&id) { @@ -868,8 +888,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, } } item_trait(ref generics, ref traits, ref ms) => { - let mut provided_methods = ~[]; - add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -879,96 +897,89 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); - let mut i = 0u; - for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| { - match (*ms)[i] { - required(ref ty_m) => { - ebml_w.start_tag(tag_item_trait_method); - encode_def_id(ebml_w, local_def((*ty_m).id)); - encode_name(ecx, ebml_w, mty.ident); - encode_type_param_bounds(ebml_w, ecx, - &ty_m.generics.ty_params); - encode_type(ecx, ebml_w, - ty::mk_bare_fn(tcx, copy mty.fty)); - encode_family(ebml_w, purity_fn_family(mty.fty.purity)); - encode_self_type(ebml_w, mty.self_ty); - encode_method_sort(ebml_w, 'r'); - encode_visibility(ebml_w, ast::public); - ebml_w.end_tag(); - } - provided(m) => { - provided_methods.push(m); - - ebml_w.start_tag(tag_item_trait_method); - encode_def_id(ebml_w, local_def(m.id)); - encode_name(ecx, ebml_w, mty.ident); - encode_type_param_bounds(ebml_w, ecx, - &m.generics.ty_params); - encode_type(ecx, ebml_w, - ty::mk_bare_fn(tcx, copy mty.fty)); - encode_family(ebml_w, purity_fn_family(mty.fty.purity)); - encode_self_type(ebml_w, mty.self_ty); - encode_method_sort(ebml_w, 'p'); - encode_visibility(ebml_w, m.vis); - ebml_w.end_tag(); - } - } - i += 1; + for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| { + ebml_w.start_tag(tag_item_trait_method); + encode_def_id(ebml_w, method_def_id); + ebml_w.end_tag(); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); for traits.each |associated_trait| { - encode_trait_ref(ebml_w, ecx, *associated_trait) + encode_trait_ref(ebml_w, ecx, *associated_trait); } - ebml_w.end_tag(); - // Now, output all of the static methods as items. Note that for the - // method info, we output static methods with type signatures as - // written. Here, we output the *real* type signatures. I feel like - // maybe we should only ever handle the real type signatures. - for ms.each |m| { - let ty_m = ast_util::trait_method_to_ty_method(m); - if ty_m.self_ty.node != ast::sty_static { loop; } + // Now output the method info for each method. + // + // Note: for the moment, the data structures here are *slightly* + // different from those expected by `encode_info_for_method()`, + // but I do plan to refactor this later in this patch to avoid the + // duplication. + for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| { + assert!(method_def_id.crate == ast::local_crate); - index.push(entry { val: ty_m.id, pos: ebml_w.writer.tell() }); + let method_ty: @ty::method = ty::method(tcx, method_def_id); + + index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()}); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(ty_m.id)); + + encode_def_id(ebml_w, method_def_id); encode_parent_item(ebml_w, local_def(item.id)); - encode_name(ecx, ebml_w, ty_m.ident); - encode_family(ebml_w, - purity_static_method_family(ty_m.purity)); - let polyty = ecx.tcx.tcache.get(&local_def(ty_m.id)); - encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds); - encode_type(ecx, ebml_w, polyty.ty); - let mut m_path = vec::append(~[], path); // :-( - m_path += [ast_map::path_name(item.ident)]; - encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident)); - - // For now, use the item visibility until trait methods can have - // real visibility in the AST. - encode_visibility(ebml_w, item.vis); + encode_name(ecx, ebml_w, method_ty.ident); + + match method_ty.self_ty { + sty_static => { + encode_family(ebml_w, + purity_static_method_family( + method_ty.fty.purity)); + + let tpt = ty::lookup_item_type(tcx, method_def_id); + encode_ty_type_param_bounds(ebml_w, ecx, tpt.bounds, + tag_items_data_item_ty_param_bounds); + encode_type(ecx, ebml_w, tpt.ty); + } - ebml_w.end_tag(); - } + _ => { + encode_family(ebml_w, + purity_fn_family( + method_ty.fty.purity)); + } + } - // Finally, output all the provided methods as items. - for provided_methods.each |m| { - index.push(entry { val: m.id, pos: ebml_w.writer.tell() }); + encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, + tag_item_method_tps); + encode_method_fty(ecx, ebml_w, &method_ty.fty); + encode_visibility(ebml_w, method_ty.vis); + encode_self_type(ebml_w, method_ty.self_ty); + let mut trait_path = vec::append(~[], path); + trait_path.push(ast_map::path_name(item.ident)); + encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident)); + + match ms[i] { + required(_) => { + encode_method_sort(ebml_w, 'r'); + } - // We do not concatenate the generics of the owning impl and that - // of provided methods. I am not sure why this is. -ndm - let owner_generics = ast_util::empty_generics(); + provided(m) => { + // This is obviously a bogus assert but I don't think this + // ever worked before anyhow...near as I can tell, before + // we would emit two items. + if method_ty.self_ty == sty_static { + tcx.sess.span_unimpl( + item.span, + fmt!("Method %s is both provided and static", + *tcx.sess.intr().get(method_ty.ident))); + } + encode_type_param_bounds(ebml_w, ecx, + &m.generics.ty_params); + encode_method_sort(ebml_w, 'p'); + (ecx.encode_inlined_item)( + ecx, ebml_w, path, + ii_method(local_def(item.id), m)); + } + } - encode_info_for_method(ecx, - ebml_w, - /*bad*/copy path, - true, - item.id, - *m, - item.vis, - &owner_generics, - &m.generics); + ebml_w.end_tag(); } } item_mac(*) => fail!(~"item macros unimplemented") diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 111bc307ed308..2982ed268770d 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -119,6 +119,12 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, parse_ty(st, conv) } +pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, + conv: conv_did) -> ty::BareFnTy { + let st = parse_state_from_data(data, crate_num, pos, tcx); + parse_bare_fn_ty(st, conv) +} + pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, conv: conv_did) -> ty::arg { let st = parse_state_from_data(data, crate_num, pos, tcx); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 251ba9b35cbd9..419219d411d89 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -384,7 +384,7 @@ fn enc_onceness(w: @io::Writer, o: Onceness) { } } -fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) { +pub fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) { enc_purity(w, ft.purity); enc_abi_set(w, ft.abis); enc_fn_sig(w, cx, &ft.sig); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index b6b6730620e9e..6fc74c9a7130d 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -417,6 +417,7 @@ impl tr for ast::def { ast::def_variant(e_did, v_did) => { ast::def_variant(e_did.tr(xcx), v_did.tr(xcx)) } + ast::def_trait(did) => ast::def_trait(did.tr(xcx)), ast::def_ty(did) => ast::def_ty(did.tr(xcx)), ast::def_prim_ty(p) => ast::def_prim_ty(p), ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v), diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b7ec6208d5607..6473cb8e8e006 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -462,7 +462,7 @@ pub impl mem_categorization_ctxt { ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) | ast::def_foreign_mod(_) | ast::def_const(_) | ast::def_use(_) | ast::def_variant(*) | - ast::def_ty(_) | ast::def_prim_ty(_) | + ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*) | ast::def_struct(*) | ast::def_typaram_binder(*) | ast::def_region(_) | ast::def_label(_) | ast::def_self_ty(*) => { diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 7740485e82c00..ed7ca441b984b 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -211,7 +211,7 @@ use core::prelude::*; use middle::pat_util::{pat_bindings}; use middle::freevars; use middle::ty; -use middle::typeck::method_map; +use middle::typeck::{method_map, method_map_entry}; use util::ppaux; use util::common::indenter; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 75eb8ef1a8580..1c60c37ed12a0 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -690,7 +690,9 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, match ty.node { ast::ty_path(path, id) => { match cx.def_map.find(&id) { - Some(&ast::def_ty(did)) | Some(&ast::def_struct(did)) => { + Some(&ast::def_ty(did)) | + Some(&ast::def_trait(did)) | + Some(&ast::def_struct(did)) => { if did.crate == ast::local_crate { if cx.region_is_relevant(path.rp) { cx.add_dep(did.node); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 08542301e238f..7232e99bf2206 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -12,7 +12,8 @@ use core::prelude::*; use driver::session; use driver::session::Session; -use metadata::csearch::{each_path, get_method_names_if_trait}; +use metadata::csearch::{each_path, get_trait_method_def_ids}; +use metadata::csearch::get_method_name_and_self_ty; use metadata::csearch::get_static_methods_if_impl; use metadata::csearch::get_type_name_if_impl; use metadata::cstore::find_extern_mod_stmt_cnum; @@ -31,7 +32,7 @@ use syntax::ast::{crate, decl_item, def, def_arg, def_binding}; use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label}; use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self}; use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty}; -use syntax::ast::{def_ty_param, def_typaram_binder}; +use syntax::ast::{def_ty_param, def_typaram_binder, def_trait}; use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op}; use syntax::ast::{expr_binary, expr_break, expr_field}; use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path}; @@ -1341,7 +1342,7 @@ pub impl Resolver { let def_id = local_def(item.id); self.trait_info.insert(def_id, method_names); - name_bindings.define_type(privacy, def_ty(def_id), sp); + name_bindings.define_type(privacy, def_trait(def_id), sp); visit_item(item, new_parent, visitor); } @@ -1611,36 +1612,40 @@ pub impl Resolver { crate) building value %s", final_ident); child_name_bindings.define_value(Public, def, dummy_sp()); } - def_ty(def_id) => { - debug!("(building reduced graph for external \ - crate) building type %s", final_ident); - - // If this is a trait, add all the method names - // to the trait info. - - match get_method_names_if_trait(self.session.cstore, def_id) { - None => { - // Nothing to do. - } - Some(method_names) => { - let mut interned_method_names = HashSet::new(); - for method_names.each |method_data| { - let (method_name, self_ty) = *method_data; - debug!("(building reduced graph for \ - external crate) ... adding \ - trait method '%s'", - *self.session.str_of(method_name)); - - // Add it to the trait info if not static. - if self_ty != sty_static { - interned_method_names.insert(method_name); - } - } - self.trait_info.insert(def_id, interned_method_names); + def_trait(def_id) => { + debug!("(building reduced graph for external \ + crate) building type %s", final_ident); + + // If this is a trait, add all the method names + // to the trait info. + + let method_def_ids = get_trait_method_def_ids(self.session.cstore, + def_id); + let mut interned_method_names = HashSet::new(); + for method_def_ids.each |&method_def_id| { + let (method_name, self_ty) = + get_method_name_and_self_ty(self.session.cstore, + method_def_id); + + debug!("(building reduced graph for \ + external crate) ... adding \ + trait method '%s'", + *self.session.str_of(method_name)); + + // Add it to the trait info if not static. + if self_ty != sty_static { + interned_method_names.insert(method_name); + } } - } + self.trait_info.insert(def_id, interned_method_names); - child_name_bindings.define_type(Public, def, dummy_sp()); + child_name_bindings.define_type(Public, def, dummy_sp()); + } + def_ty(_) => { + debug!("(building reduced graph for external \ + crate) building type %s", final_ident); + + child_name_bindings.define_type(Public, def, dummy_sp()); } def_struct(def_id) => { debug!("(building reduced graph for external \ @@ -4952,7 +4957,7 @@ pub impl Resolver { match child_name_bindings.def_for_namespace(TypeNS) { Some(def) => { match def { - def_ty(trait_def_id) => { + def_trait(trait_def_id) => { self.add_trait_info_if_containing_method( &mut found_traits, trait_def_id, name); } @@ -4979,7 +4984,7 @@ pub impl Resolver { match target.bindings.def_for_namespace(TypeNS) { Some(def) => { match def { - def_ty(trait_def_id) => { + def_trait(trait_def_id) => { let added = self. add_trait_info_if_containing_method( &mut found_traits, diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index ec67c68f93cda..b8b0bddcf0512 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -148,7 +148,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_self(*) => { datum_callee(bcx, ref_expr) } - ast::def_mod(*) | ast::def_foreign_mod(*) | + ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) | ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) | ast::def_use(*) | ast::def_typaram_binder(*) | ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) | diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index ed9000e7418a4..accdb6557501e 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -174,6 +174,7 @@ pub fn trans_method_callee(bcx: block, mentry: typeck::method_map_entry) -> Callee { let _icx = bcx.insn_ctxt("impl::trans_method_callee"); + let tcx = bcx.tcx(); debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)", callee_id, bcx.expr_to_str(self), mentry); @@ -189,33 +190,33 @@ pub fn trans_method_callee(bcx: block, // Get the ID of the method we're calling. let method_name = - ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident; - let method_id = method_with_name(bcx.ccx(), impl_def_id, - method_name); + ty::trait_method(tcx, trait_id, method_index).ident; + let method_id = + method_with_name(bcx.ccx(), impl_def_id, method_name); origin = typeck::method_static(method_id); } typeck::method_super(trait_id, method_index) => { // is the self type for this method call let self_ty = node_id_type(bcx, self.id); - let tcx = bcx.tcx(); // is the ID of the implementation of // trait for type let impl_id = ty::get_impl_id(tcx, trait_id, self_ty); // Get the supertrait's methods - let supertrait_methods = ty::trait_methods(tcx, trait_id); + let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id); // Make sure to fail with a readable error message if // there's some internal error here - if !(method_index < supertrait_methods.len()) { + if !(method_index < supertrait_method_def_ids.len()) { tcx.sess.bug(~"trans_method_callee: supertrait method \ index is out of bounds"); } // Get the method name using the method index in the origin - let method_name = supertrait_methods[method_index].ident; + let method_name = + ty::method(tcx, supertrait_method_def_ids[method_index]).ident; // Now that we know the impl ID, we can look up the method // ID from its name origin = typeck::method_static(method_with_name(bcx.ccx(), - impl_id, - method_name)); + impl_id, + method_name)); } typeck::method_static(*) | typeck::method_param(*) | typeck::method_trait(*) => {} @@ -448,7 +449,7 @@ pub fn trans_monomorphized_callee(bcx: block, return match vtbl { typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { let ccx = bcx.ccx(); - let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident; + let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident; let mth_id = method_with_name_or_default( bcx.ccx(), impl_did, mname); @@ -791,10 +792,11 @@ pub fn make_impl_vtable(ccx: @CrateContext, || ~"make_impl_vtable: non-trait-type implemented"); let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; - make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| { + make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| { + let im = ty::method(tcx, *method_def_id); let fty = ty::subst_tps(tcx, substs, None, ty::mk_bare_fn(tcx, copy im.fty)); - if (*im.tps).len() > 0u || ty::type_has_self(fty) { + if im.tps.len() > 0u || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", *tcx.sess.str_of(im.ident)); C_null(T_ptr(T_nil())) diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index a9869f15875c7..224981d6e759a 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -31,7 +31,7 @@ use syntax::ast; pub struct Reflector { visitor_val: ValueRef, - visitor_methods: @~[ty::method], + visitor_methods: @~[@ty::method], final_bcx: block, tydesc_ty: TypeRef, bcx: block diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 19ffb4edc8447..fcdd5a650af81 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -255,6 +255,15 @@ struct ctxt_ { // other items. node_type_substs: @mut HashMap, + // Maps from a method to the method "descriptor" + methods: @mut HashMap, + + // Maps from a trait def-id to a list of the def-ids of its methods + trait_method_def_ids: @mut HashMap, + + // A cache for the trait_methods() routine + trait_methods_cache: @mut HashMap, + items: ast_map::map, intrinsic_defs: @mut HashMap, freevars: freevars::freevar_map, @@ -266,7 +275,6 @@ struct ctxt_ { tc_cache: @mut HashMap, ast_ty_to_ty_cache: @mut HashMap, enum_var_cache: @mut HashMap, - trait_method_cache: @mut HashMap, ty_param_bounds: @mut HashMap, inferred_modes: @mut HashMap, adjustments: @mut HashMap, @@ -831,7 +839,9 @@ pub fn mk_ctxt(s: session::Session, tc_cache: @mut HashMap::new(), ast_ty_to_ty_cache: @mut HashMap::new(), enum_var_cache: @mut HashMap::new(), - trait_method_cache: @mut HashMap::new(), + methods: @mut HashMap::new(), + trait_method_def_ids: @mut HashMap::new(), + trait_methods_cache: @mut HashMap::new(), ty_param_bounds: @mut HashMap::new(), inferred_modes: @mut HashMap::new(), adjustments: @mut HashMap::new(), @@ -3028,7 +3038,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, let trt_bounds = ty::lookup_item_type(tcx, trt_id).bounds; @(vec::append(/*bad*/copy *trt_bounds, - *ty::trait_methods(tcx, trt_id)[n_mth].tps)) + *ty::trait_method(tcx, trt_id, n_mth).tps)) } } } @@ -3213,10 +3223,8 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field]) fields.map(|f| tcx.sess.str_of(f.ident)))); } -pub fn method_idx(id: ast::ident, meths: &[method]) -> Option { - let mut i = 0u; - for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; } - return None; +pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option { + vec::position(meths, |m| m.ident == id) } /// Returns a vector containing the indices of all type parameters that appear @@ -3537,10 +3545,6 @@ pub fn def_has_ty_params(def: ast::def) -> bool { } } -pub fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) { - cx.trait_method_cache.insert(ast_util::local_def(id), ms); -} - pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] { if is_local(id) { match cx.items.find(&id.node) { @@ -3594,25 +3598,66 @@ pub fn trait_supertraits(cx: ctxt, return @result; } -pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] { - match cx.trait_method_cache.find(&id) { - // Local traits are supposed to have been added explicitly. - Some(&ms) => ms, - _ => { - // If the lookup in trait_method_cache fails, assume that the trait - // method we're trying to look up is in a different crate, and look - // for it there. - assert!(id.crate != ast::local_crate); - let result = csearch::get_trait_methods(cx, id); - - // Store the trait method in the local trait_method_cache so that - // future lookups succeed. - cx.trait_method_cache.insert(id, result); - result - } +fn lookup_locally_or_in_crate_store( + descr: &str, + def_id: ast::def_id, + map: &mut HashMap, + load_external: &fn() -> V) -> V +{ + /*! + * + * Helper for looking things up in the various maps + * that are populated during typeck::collect (e.g., + * `cx.methods`, `cx.tcache`, etc). All of these share + * the pattern that if the id is local, it should have + * been loaded into the map by the `typeck::collect` phase. + * If the def-id is external, then we have to go consult + * the crate loading code (and cache the result for the future). + */ + + match map.find(&def_id) { + Some(&v) => { return v; } + None => { } + } + + if def_id.crate == ast::local_crate { + fail!(fmt!("No def'n found for %? in tcx.%s", + def_id, descr)); + } + let v = load_external(); + map.insert(def_id, v); + return v; +} + +pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method { + let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx]; + ty::method(cx, method_def_id) +} + +pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] { + match cx.trait_methods_cache.find(&trait_did) { + Some(&methods) => methods, + None => { + let def_ids = ty::trait_method_def_ids(cx, trait_did); + let methods = @def_ids.map(|d| ty::method(cx, *d)); + cx.trait_methods_cache.insert(trait_did, methods); + methods + } } } +pub fn method(cx: ctxt, id: ast::def_id) -> @method { + lookup_locally_or_in_crate_store( + "methods", id, cx.methods, + || @csearch::get_method(cx, id)) +} + +pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] { + lookup_locally_or_in_crate_store( + "methods", id, cx.trait_method_def_ids, + || @csearch::get_trait_method_def_ids(cx.cstore, id)) +} + /* Could this return a list of (def_id, substs) pairs? */ @@ -3916,19 +3961,9 @@ pub fn enum_variant_with_id(cx: ctxt, pub fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { - match cx.tcache.find(&did) { - Some(&tpt) => { - // The item is in this crate. The caller should have added it to the - // type cache already - return tpt; - } - None => { - assert!(did.crate != ast::local_crate); - let tyt = csearch::get_type(cx, did); - cx.tcache.insert(did, tyt); - return tyt; - } - } + lookup_locally_or_in_crate_store( + "tcache", did, cx.tcache, + || csearch::get_type(cx, did)) } // Look up a field ID, whether or not it's local diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 4b4cb8572529c..c54e76b9c0579 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -243,7 +243,7 @@ pub fn ast_ty_to_ty( check_path_args(tcx, path, NO_TPS | NO_REGIONS); return ty::mk_estr(tcx, vst); } - Some(&ast::def_ty(type_def_id)) => { + Some(&ast::def_trait(type_def_id)) => { let result = ast_path_to_substs_and_ty( self, rscope, type_def_id, path); @@ -271,7 +271,11 @@ pub fn ast_ty_to_ty( trait_store); } - _ => {} + _ => { + tcx.sess.span_bug( + a_seq_ty.ty.span, + fmt!("def_trait but not ty_trait")); + } } } _ => {} @@ -372,7 +376,7 @@ pub fn ast_ty_to_ty( Some(&d) => d }; match a_def { - ast::def_ty(did) | ast::def_struct(did) => { + ast::def_trait(did) | ast::def_ty(did) | ast::def_struct(did) => { ast_path_to_ty(self, rscope, did, path).ty } ast::def_prim_ty(nty) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 3200949577217..c8b274e456916 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2126,11 +2126,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_vstore(ev, vst) => { let typ = match ev.node { ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => { - let tt = ast_expr_vstore_to_vstore(fcx, ev, s.len(), vst); + let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); ty::mk_estr(tcx, tt) } ast::expr_vec(ref args, mutbl) => { - let tt = ast_expr_vstore_to_vstore(fcx, ev, args.len(), vst); + let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); let mutability; let mut any_error = false; let mut any_bot = false; @@ -2164,7 +2164,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_repeat(element, count_expr, mutbl) => { let count = ty::eval_repeat_count(tcx, count_expr); check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx)); - let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst); + let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); let mutability = match vst { ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => { ast::m_mutbl @@ -3173,7 +3173,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, ast::def_upvar(_, inner, _, _) => { return ty_param_bounds_and_ty_for_def(fcx, sp, *inner); } - ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*)=> { + ast::def_trait(_) | + ast::def_ty(_) | + ast::def_prim_ty(_) | + ast::def_ty_param(*)=> { fcx.ccx.tcx.sess.span_bug(sp, ~"expected value but found type"); } ast::def_mod(*) | ast::def_foreign_mod(*) => { @@ -3211,6 +3214,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt, let ty_param_count = vec::len(*tpt.bounds); let ty_substs_len = vec::len(pth.types); + debug!("ty_param_count=%? ty_substs_len=%?", + ty_param_count, + ty_substs_len); + // determine the region bound, using the value given by the user // (if any) and otherwise using a fresh region variable let self_r = match pth.rp { @@ -3306,7 +3313,6 @@ pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool { pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt, e: @ast::expr, - _n: uint, v: ast::expr_vstore) -> ty::vstore { match v { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 466cb8ed54f2b..ab99aa20d6487 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -38,7 +38,7 @@ use middle::typeck::infer::combine::Combine; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; use middle::typeck::infer::{resolve_nested_tvar, resolve_type}; -use syntax::ast::{crate, def_id, def_mod, def_ty}; +use syntax::ast::{crate, def_id, def_mod, def_ty, def_trait}; use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref}; use syntax::ast; use syntax::ast_map::node_item; @@ -507,7 +507,7 @@ pub impl CoherenceChecker { provided_method_idents.insert(*ident); } - for ty::trait_methods(tcx, trait_did).each |method| { + for ty::trait_methods(tcx, trait_did).each |&method| { if provided_method_idents.contains(&method.ident) { if !f(method) { break; @@ -947,7 +947,7 @@ pub impl CoherenceChecker { crate_store, def_id); } - dl_def(def_ty(def_id)) => { + dl_def(def_trait(def_id)) => { let tcx = self.crate_context.tcx; let polytype = csearch::get_type(tcx, def_id); match ty::get(polytype.ty).sty { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index f1d743e79e58a..d89d1c407d7ba 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -53,7 +53,6 @@ use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; use syntax::ast_map; use syntax::ast_util::{local_def, split_trait_methods}; -use syntax::ast_util::{trait_method_to_ty_method}; use syntax::ast_util; use syntax::codemap::span; use syntax::codemap; @@ -221,19 +220,61 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, } pub fn ensure_trait_methods(ccx: &CrateCtxt, - id: ast::node_id, - trait_ty: ty::t) { - fn store_methods(ccx: &CrateCtxt, - id: ast::node_id, - stuff: &[T], - f: &fn(v: &T) -> ty::method) { - ty::store_trait_methods(ccx.tcx, id, @stuff.map(f)); + trait_id: ast::node_id, + trait_ty: ty::t) +{ + let tcx = ccx.tcx; + let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x); + match *tcx.items.get(&trait_id) { + ast_map::node_item(@ast::item { + node: ast::item_trait(ref generics, _, ref ms), + _ + }, _) => { + let trait_bounds = ty_param_bounds(ccx, generics); + + // For each method, construct a suitable ty::method and + // store it into the `tcx.methods` table: + for ms.each |m| { + let ty_method = @match m { + &ast::required(ref m) => { + ty_method_of_trait_method(ccx, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) + } + + &ast::provided(ref m) => { + ty_method_of_trait_method(ccx, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) + } + }; + + if ty_method.self_ty == ast::sty_static { + make_static_method_ty(ccx, region_paramd, + ty_method, trait_ty, + trait_bounds); + } + + tcx.methods.insert(ty_method.def_id, ty_method); + } + + // Add an entry mapping + let method_def_ids = @ms.map(|m| { + match m { + &ast::required(ref ty_method) => local_def(ty_method.id), + &ast::provided(ref method) => local_def(method.id) + } + }); + + let trait_def_id = local_def(trait_id); + tcx.trait_method_def_ids.insert(trait_def_id, method_def_ids); + } + _ => { /* Ignore things that aren't traits */ } } fn make_static_method_ty(ccx: &CrateCtxt, - am: &ast::ty_method, rp: Option, - m: ty::method, + m: &ty::method, // Take this as an argument b/c we may check // the impl before the trait. trait_ty: ty::t, @@ -267,7 +308,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty::mk_bare_fn(ccx.tcx, copy m.fty)); let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] + *m.tps); - ccx.tcx.tcache.insert(local_def(am.id), + ccx.tcx.tcache.insert(m.def_id, ty_param_bounds_and_ty { bounds: bounds, region_param: rp, @@ -275,40 +316,31 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, } - let tcx = ccx.tcx; - let region_paramd = tcx.region_paramd_items.find(&id).map_consume(|x| *x); - match *tcx.items.get(&id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(ref generics, _, ref ms), - _ - }, _) => { - store_methods::(ccx, id, *ms, |m| { - let def_id; - match *m { - ast::required(ref ty_method) => { - def_id = local_def((*ty_method).id) - } - ast::provided(method) => def_id = local_def(method.id) - } - - let trait_bounds = ty_param_bounds(ccx, generics); - let ty_m = trait_method_to_ty_method(m); - let method_ty = ty_of_ty_method( - ccx, - &ty_m, - region_paramd, - def_id, - generics - ); - if ty_m.self_ty.node == ast::sty_static { - make_static_method_ty(ccx, &ty_m, region_paramd, - method_ty, trait_ty, - trait_bounds); - } - method_ty - }); - } - _ => { /* Ignore things that aren't traits */ } + fn ty_method_of_trait_method(self: &CrateCtxt, + trait_rp: Option, + trait_generics: &ast::Generics, + m_id: &ast::node_id, + m_ident: &ast::ident, + m_self_ty: &ast::self_ty, + m_generics: &ast::Generics, + m_purity: &ast::purity, + m_decl: &ast::fn_decl) -> ty::method + { + let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics); + ty::method { + ident: *m_ident, + tps: ty_param_bounds(self, m_generics), + fty: astconv::ty_of_bare_fn(self, + &rscope, + *m_purity, + AbiSet::Rust(), + &m_generics.lifetimes, + m_decl), + // assume public, because this is only invoked on trait methods + self_ty: m_self_ty.node, + vis: ast::public, + def_id: local_def(*m_id) + } } } @@ -501,8 +533,8 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, rp: Option, selfty: ty::t, a_trait_ty: @ast::trait_ref, - impl_ms: &[ConvertedMethod]) { - + impl_ms: &[ConvertedMethod]) +{ let tcx = ccx.tcx; let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics); @@ -530,7 +562,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, 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) => { + Some(trait_m) => { let num_impl_tps = generics.ty_params.len(); compare_impl_method( ccx.tcx, num_impl_tps, impl_m, trait_m, @@ -786,29 +818,6 @@ pub fn ty_of_method(ccx: &CrateCtxt, } } -pub fn ty_of_ty_method(self: &CrateCtxt, - m: &ast::ty_method, - rp: Option, - id: ast::def_id, - generics: &ast::Generics) - -> ty::method { - let rscope = MethodRscope::new(m.self_ty.node, rp, generics); - ty::method { - ident: m.ident, - tps: ty_param_bounds(self, &m.generics), - fty: astconv::ty_of_bare_fn(self, - &rscope, - m.purity, - AbiSet::Rust(), - &m.generics.lifetimes, - &m.decl), - // assume public, because this is only invoked on trait methods - self_ty: m.self_ty.node, - vis: ast::public, - def_id: id - } -} - /* Instantiates the path for the given trait reference, assuming that it's bound to a valid trait type. Returns the def_id for the defining @@ -828,7 +837,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt, let rscope = type_rscope(rp); match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) { - ast::def_ty(t_id) => { + ast::def_trait(t_id) => { let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path); write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index afbf3f485d0ae..238ecf7acea27 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -443,7 +443,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { str::from_bytes(~[('a' as u8) + (id as u8)])) } } - ty_self(*) => ~"self", + ty_self(*) => ~"Self", ty_enum(did, ref substs) | ty_struct(did, ref substs) => { let path = ty::item_path(cx, did); let base = ast_map::path_to_str(path, cx.sess.intr()); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2e7ae4c537a8c..31dc476cbe49e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -194,6 +194,7 @@ pub enum def { def_local(node_id, bool /* is_mutbl */), def_variant(def_id /* enum */, def_id /* variant */), def_ty(def_id), + def_trait(def_id), def_prim_ty(prim_ty), def_ty_param(def_id, uint), def_binding(node_id, binding_mode), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 208ed1e35fe1a..c7227fa17687c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -61,7 +61,7 @@ pub fn def_id_of_def(d: def) -> def_id { def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | def_foreign_mod(id) | def_const(id) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | - def_use(id) | def_struct(id) => { + def_use(id) | def_struct(id) | def_trait(id) => { id } def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id) diff --git a/src/test/compile-fail/extern-no-call.rs b/src/test/compile-fail/extern-no-call.rs index 8c6deb3481674..58649f3209bb1 100644 --- a/src/test/compile-fail/extern-no-call.rs +++ b/src/test/compile-fail/extern-no-call.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected function or foreign function but found `*u8` +// error-pattern:expected function but found `*u8` extern fn f() { } diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs index 0388f0fd29083..d56cb0d51d234 100644 --- a/src/test/compile-fail/issue-3563.rs +++ b/src/test/compile-fail/issue-3563.rs @@ -10,7 +10,7 @@ trait A { fn a(&self) { - || self.b() //~ ERROR type `&'self self` does not implement any method in scope named `b` + || self.b() //~ ERROR type `&'self Self` does not implement any method in scope named `b` } } fn main() {} From 569596573a2f90d52c7f7610d8c7c637dc587f0a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 28 Mar 2013 14:27:54 -0400 Subject: [PATCH 046/403] Compute a ty::method for methods that appear in impls as well --- src/librustc/metadata/decoder.rs | 7 ++- src/librustc/metadata/encoder.rs | 63 ++++++++----------- src/librustc/middle/typeck/collect.rs | 89 ++++++++++++++++----------- src/libsyntax/ast.rs | 9 +++ 4 files changed, 89 insertions(+), 79 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 800df628bc23a..598539609e9eb 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -714,18 +714,19 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ty::method { let method_doc = lookup_item(id, cdata.data); + let def_id = item_def_id(method_doc, cdata); + let name = item_name(intr, method_doc); let bounds = item_ty_param_bounds(method_doc, tcx, cdata, tag_item_method_tps); - let name = item_name(intr, method_doc); - let def_id = item_def_id(method_doc, cdata); let fty = doc_method_fty(method_doc, tcx, cdata); + let vis = item_visibility(method_doc); let self_ty = get_self_ty(method_doc); ty::method { ident: name, tps: bounds, fty: fty, self_ty: self_ty, - vis: ast::public, + vis: vis, def_id: def_id } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 61501d8308331..2e3008a0cdc88 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -562,13 +562,25 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext, ebml_w.end_tag(); } +fn encode_method_ty_fields(ecx: @EncodeContext, + ebml_w: writer::Encoder, + method_ty: &ty::method) +{ + encode_def_id(ebml_w, method_ty.def_id); + encode_name(ecx, ebml_w, method_ty.ident); + encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, + tag_item_method_tps); + encode_method_fty(ecx, ebml_w, &method_ty.fty); + encode_visibility(ebml_w, method_ty.vis); + encode_self_type(ebml_w, method_ty.self_ty); +} + fn encode_info_for_method(ecx: @EncodeContext, ebml_w: writer::Encoder, impl_path: &[ast_map::path_elt], should_inline: bool, parent_id: node_id, m: @method, - parent_visibility: ast::visibility, owner_generics: &ast::Generics, method_generics: &ast::Generics) { debug!("encode_info_for_method: %d %s %u %u", m.id, @@ -576,7 +588,10 @@ fn encode_info_for_method(ecx: @EncodeContext, owner_generics.ty_params.len(), method_generics.ty_params.len()); ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, local_def(m.id)); + + let method_def_id = local_def(m.id); + let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id); + encode_method_ty_fields(ecx, ebml_w, method_ty); match m.self_ty.node { ast::sty_static => { @@ -592,16 +607,7 @@ fn encode_info_for_method(ecx: @EncodeContext, encode_type_param_bounds(ebml_w, ecx, &combined_ty_params); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id)); - encode_name(ecx, ebml_w, m.ident); encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident)); - encode_self_type(ebml_w, m.self_ty.node); - - // Combine parent visibility and this visibility. - let visibility = match m.vis { - ast::inherited => parent_visibility, - vis => vis, - }; - encode_visibility(ebml_w, visibility); if len > 0u || should_inline { (ecx.encode_inlined_item)( @@ -610,6 +616,7 @@ fn encode_info_for_method(ecx: @EncodeContext, } else { encode_symbol(ecx, ebml_w, m.id); } + ebml_w.end_tag(); } @@ -863,17 +870,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, let mut impl_path = vec::append(~[], path); impl_path += ~[ast_map::path_name(item.ident)]; - // If there is a trait reference, treat the methods as always public. - // This is to work around some incorrect behavior in privacy checking: - // when the method belongs to a trait, it should acquire the privacy - // from the trait, not the impl. Forcing the visibility to be public - // makes things sorta work. - let parent_visibility = if opt_trait.is_some() { - ast::public - } else { - item.vis - }; - for methods.each |m| { index.push(entry {val: m.id, pos: ebml_w.writer.tell()}); encode_info_for_method(ecx, @@ -882,7 +878,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, should_inline(m.attrs), item.id, *m, - parent_visibility, generics, &m.generics); } @@ -909,11 +904,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.end_tag(); // Now output the method info for each method. - // - // Note: for the moment, the data structures here are *slightly* - // different from those expected by `encode_info_for_method()`, - // but I do plan to refactor this later in this patch to avoid the - // duplication. for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| { assert!(method_def_id.crate == ast::local_crate); @@ -923,9 +913,13 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.start_tag(tag_items_data_item); - encode_def_id(ebml_w, method_def_id); + encode_method_ty_fields(ecx, ebml_w, method_ty); + encode_parent_item(ebml_w, local_def(item.id)); - encode_name(ecx, ebml_w, method_ty.ident); + + let mut trait_path = vec::append(~[], path); + trait_path.push(ast_map::path_name(item.ident)); + encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident)); match method_ty.self_ty { sty_static => { @@ -946,15 +940,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, } } - encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, - tag_item_method_tps); - encode_method_fty(ecx, ebml_w, &method_ty.fty); - encode_visibility(ebml_w, method_ty.vis); - encode_self_type(ebml_w, method_ty.self_ty); - let mut trait_path = vec::append(~[], path); - trait_path.push(ast_map::path_name(item.ident)); - encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident)); - match ms[i] { required(_) => { encode_method_sort(ebml_w, 'r'); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index d89d1c407d7ba..3ac3766e89da4 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -315,7 +315,6 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty: ty}); } - fn ty_method_of_trait_method(self: &CrateCtxt, trait_rp: Option, trait_generics: &ast::Generics, @@ -336,8 +335,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, AbiSet::Rust(), &m_generics.lifetimes, m_decl), - // assume public, because this is only invoked on trait methods self_ty: m_self_ty.node, + // assume public, because this is only invoked on trait methods vis: ast::public, def_id: local_def(*m_id) } @@ -599,7 +598,7 @@ pub fn convert_field(ccx: &CrateCtxt, } pub struct ConvertedMethod { - mty: ty::method, + mty: @ty::method, id: ast::node_id, span: span, body_id: ast::node_id @@ -609,13 +608,15 @@ pub fn convert_methods(ccx: &CrateCtxt, ms: &[@ast::method], rp: Option, rcvr_bounds: @~[ty::param_bounds], - rcvr_generics: &ast::Generics) - -> ~[ConvertedMethod] { - + rcvr_generics: &ast::Generics, + rcvr_visibility: ast::visibility) + -> ~[ConvertedMethod] +{ let tcx = ccx.tcx; - do vec::map(ms) |m| { + return vec::map(ms, |m| { let bounds = ty_param_bounds(ccx, &m.generics); - let mty = ty_of_method(ccx, *m, rp, rcvr_generics, &m.generics); + let mty = @ty_of_method(ccx, *m, rp, rcvr_generics, + rcvr_visibility, &m.generics); let fty = ty::mk_bare_fn(tcx, copy mty.fty); tcx.tcache.insert( local_def(m.id), @@ -628,8 +629,34 @@ pub fn convert_methods(ccx: &CrateCtxt, ty: fty }); write_ty_to_tcx(tcx, m.id, fty); + tcx.methods.insert(mty.def_id, mty); ConvertedMethod {mty: mty, id: m.id, span: m.span, body_id: m.body.node.id} + }); + + fn ty_of_method(ccx: &CrateCtxt, + m: @ast::method, + rp: Option, + rcvr_generics: &ast::Generics, + rcvr_visibility: ast::visibility, + method_generics: &ast::Generics) -> ty::method + { + let rscope = MethodRscope::new(m.self_ty.node, + rp, + rcvr_generics); + ty::method { + ident: m.ident, + tps: ty_param_bounds(ccx, &m.generics), + fty: astconv::ty_of_bare_fn(ccx, + &rscope, + m.purity, + ast::RustAbi, + &method_generics.lifetimes, + &m.decl), + self_ty: m.self_ty.node, + vis: m.vis.inherit_from(rcvr_visibility), + def_id: local_def(m.id) + } } } @@ -665,7 +692,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { generics, rp); } - ast::item_impl(ref generics, trait_ref, selfty, ref ms) => { + ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => { let i_bounds = ty_param_bounds(ccx, generics); let region_parameterization = RegionParameterization::from_variance_and_generics(rp, generics); @@ -677,9 +704,20 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { region_param: rp, ty: selfty}); - // XXX: Bad copy of `ms` below. - let cms = convert_methods(ccx, *ms, rp, i_bounds, generics); - for trait_ref.each |t| { + // If there is a trait reference, treat the methods as always public. + // This is to work around some incorrect behavior in privacy checking: + // when the method belongs to a trait, it should acquire the privacy + // from the trait, not the impl. Forcing the visibility to be public + // makes things sorta work. + let parent_visibility = if opt_trait_ref.is_some() { + ast::public + } else { + it.vis + }; + + let cms = convert_methods(ccx, *ms, rp, i_bounds, generics, + parent_visibility); + for opt_trait_ref.each |t| { check_methods_against_trait(ccx, generics, rp, selfty, *t, cms); } } @@ -694,7 +732,8 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { let (_, provided_methods) = split_trait_methods(*trait_methods); let (bounds, _) = mk_substs(ccx, generics, rp); - let _ = convert_methods(ccx, provided_methods, rp, bounds, generics); + let _ = convert_methods(ccx, provided_methods, rp, bounds, generics, + it.vis); } ast::item_struct(struct_def, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "structure"); @@ -794,30 +833,6 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) { ccx.tcx.tcache.insert(local_def(i.id), tpt); } -pub fn ty_of_method(ccx: &CrateCtxt, - m: @ast::method, - rp: Option, - rcvr_generics: &ast::Generics, - method_generics: &ast::Generics) - -> ty::method { - let rscope = MethodRscope::new(m.self_ty.node, - rp, - rcvr_generics); - ty::method { - ident: m.ident, - tps: ty_param_bounds(ccx, &m.generics), - fty: astconv::ty_of_bare_fn(ccx, - &rscope, - m.purity, - AbiSet::Rust(), - &method_generics.lifetimes, - &m.decl), - self_ty: m.self_ty.node, - vis: m.vis, - def_id: local_def(m.id) - } -} - /* Instantiates the path for the given trait reference, assuming that it's bound to a valid trait type. Returns the def_id for the defining diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 31dc476cbe49e..4a0e58b09c8a8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1186,6 +1186,15 @@ pub struct trait_ref { #[deriving(Eq)] pub enum visibility { public, private, inherited } +impl visibility { + fn inherit_from(&self, parent_visibility: visibility) -> visibility { + match self { + &inherited => parent_visibility, + &public | &private => *self + } + } +} + #[auto_encode] #[auto_decode] #[deriving(Eq)] From 0a0525e3664dfb659aae06c146a4336a878e2b05 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 28 Mar 2013 22:04:13 -0400 Subject: [PATCH 047/403] Pass around a pointer to the ty::method rather than the individual bits of info --- src/librustc/middle/trans/callee.rs | 3 +- src/librustc/middle/trans/meth.rs | 3 +- src/librustc/middle/typeck/check/method.rs | 114 ++++++++++----------- src/librustc/middle/typeck/check/mod.rs | 4 +- src/librustc/middle/typeck/coherence.rs | 8 +- 5 files changed, 65 insertions(+), 67 deletions(-) diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index b8b0bddcf0512..de14266573af9 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -238,8 +238,7 @@ pub fn trans_fn_ref_with_vtables( // Modify the def_id if this is a default method; we want to be // monomorphizing the trait's code. - let (def_id, opt_impl_did) = - match tcx.provided_method_sources.find(&def_id) { + let (def_id, opt_impl_did) = match tcx.provided_method_sources.find(&def_id) { None => (def_id, None), Some(source) => (source.method_id, Some(source.impl_id)) }; diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index accdb6557501e..feab9945fc4c3 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -376,7 +376,8 @@ pub fn method_with_name(ccx: @CrateContext, impl_id: ast::def_id, } } -pub fn method_with_name_or_default(ccx: @CrateContext, impl_id: ast::def_id, +pub fn method_with_name_or_default(ccx: @CrateContext, + impl_id: ast::def_id, name: ast::ident) -> ast::def_id { if impl_id.crate == ast::local_crate { match *ccx.tcx.items.get(&impl_id.node) { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 69d8fb495e131..e2d9a8a20c790 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -176,13 +176,7 @@ pub struct LookupContext<'self> { pub struct Candidate { rcvr_ty: ty::t, rcvr_substs: ty::substs, - explicit_self: ast::self_ty_, - - // FIXME #3446---these two fields should be easily derived from - // origin, yet are not - num_method_tps: uint, - self_mode: ast::rmode, - + method_ty: @ty::method, origin: method_origin, } @@ -474,7 +468,7 @@ pub impl<'self> LookupContext<'self> { } } }; - let method = &trait_methods[pos]; + let method = trait_methods[pos]; let (rcvr_ty, rcvr_substs) = self.create_rcvr_ty_and_substs_for_method( @@ -486,9 +480,7 @@ pub impl<'self> LookupContext<'self> { let cand = Candidate { rcvr_ty: rcvr_ty, rcvr_substs: rcvr_substs, - explicit_self: method.self_ty, - num_method_tps: method.tps.len(), - self_mode: get_mode_from_self_type(method.self_ty), + method_ty: method, origin: method_param( method_param { trait_id: init_trait_id, @@ -520,7 +512,7 @@ pub impl<'self> LookupContext<'self> { Some(i) => i, None => { return; } // no method with the right name }; - let method = &ms[index]; + let method = ms[index]; /* FIXME(#3157) we should transform the vstore in accordance with the self type @@ -554,9 +546,7 @@ pub impl<'self> LookupContext<'self> { self.inherent_candidates.push(Candidate { rcvr_ty: rcvr_ty, rcvr_substs: rcvr_substs, - explicit_self: method.self_ty, - num_method_tps: method.tps.len(), - self_mode: get_mode_from_self_type(method.self_ty), + method_ty: method, origin: method_trait(did, index, store) }); } @@ -565,63 +555,65 @@ pub impl<'self> LookupContext<'self> { self_ty: ty::t, did: def_id, substs: &ty::substs) { + struct MethodInfo { + method_ty: @ty::method, + trait_def_id: ast::def_id, + index: uint + } + let tcx = self.tcx(); // First, try self methods - let mut method = None; + let mut method_info: Option = None; let methods = ty::trait_methods(tcx, did); - let mut index = None; - let mut trait_did = None; match vec::position(*methods, |m| m.ident == self.m_name) { Some(i) => { - index = Some(i); - trait_did = Some(did); - method = Some((methods[i].self_ty, methods[i].tps.len())); + method_info = Some(MethodInfo { + method_ty: methods[i], + index: i, + trait_def_id: did + }); } None => () } // No method found yet? Check each supertrait - if method.is_none() { + if method_info.is_none() { for ty::trait_supertraits(tcx, did).each() |trait_ref| { let supertrait_methods = ty::trait_methods(tcx, trait_ref.def_id); match vec::position(*supertrait_methods, |m| m.ident == self.m_name) { Some(i) => { - index = Some(i); - trait_did = Some(trait_ref.def_id); - method = Some((supertrait_methods[i].self_ty, - supertrait_methods[i].tps.len())); + method_info = Some(MethodInfo { + method_ty: supertrait_methods[i], + index: i, + trait_def_id: trait_ref.def_id + }); break; } None => () } } } - match (method, index, trait_did) { - (Some((method_self_ty, method_num_tps)), - Some(index), Some(trait_did)) => { - + match method_info { + Some(ref info) => { // We've found a method -- return it - let rcvr_substs = substs { self_ty: Some(self_ty), + let rcvr_substs = substs {self_ty: Some(self_ty), ..copy *substs }; let (rcvr_ty, rcvr_substs) = self.create_rcvr_ty_and_substs_for_method( - method_self_ty, + info.method_ty.self_ty, self_ty, rcvr_substs, TransformTypeNormally); - let origin = if trait_did == did { - method_self(trait_did, index) - } - else { - method_super(trait_did, index) + let origin = if did == info.trait_def_id { + method_self(info.trait_def_id, info.index) + } else { + method_super(info.trait_def_id, info.index) }; self.inherent_candidates.push(Candidate { rcvr_ty: rcvr_ty, rcvr_substs: rcvr_substs, - explicit_self: method_self_ty, - num_method_tps: method_num_tps, - self_mode: get_mode_from_self_type(method_self_ty), + method_ty: info.method_ty, origin: origin }); } @@ -653,7 +645,7 @@ pub impl<'self> LookupContext<'self> { } }; - let method = &impl_info.methods[idx]; + let method = ty::method(self.tcx(), impl_info.methods[idx].did); // determine the `self` of the impl with fresh // variables for each parameter: @@ -669,7 +661,7 @@ pub impl<'self> LookupContext<'self> { let (impl_ty, impl_substs) = self.create_rcvr_ty_and_substs_for_method( - method.self_type, + method.self_ty, impl_ty, impl_substs, TransformTypeNormally); @@ -677,10 +669,8 @@ pub impl<'self> LookupContext<'self> { candidates.push(Candidate { rcvr_ty: impl_ty, rcvr_substs: impl_substs, - explicit_self: method.self_type, - num_method_tps: method.n_tps, - self_mode: get_mode_from_self_type(method.self_type), - origin: method_static(method.did) + method_ty: method, + origin: method_static(method.def_id) }); } @@ -701,6 +691,9 @@ pub impl<'self> LookupContext<'self> { debug!("(pushing candidates from provided methods) adding \ candidate"); + let method = ty::method(self.tcx(), + provided_method_info.method_info.did); + // XXX: Needs to support generics. let dummy_substs = substs { self_r: None, @@ -709,7 +702,7 @@ pub impl<'self> LookupContext<'self> { }; let (impl_ty, impl_substs) = self.create_rcvr_ty_and_substs_for_method( - provided_method_info.method_info.self_type, + method.self_ty, self_ty, dummy_substs, TransformTypeNormally); @@ -717,10 +710,7 @@ pub impl<'self> LookupContext<'self> { candidates.push(Candidate { rcvr_ty: impl_ty, rcvr_substs: impl_substs, - explicit_self: provided_method_info.method_info.self_type, - num_method_tps: provided_method_info.method_info.n_tps, - self_mode: get_mode_from_self_type( - provided_method_info.method_info.self_type), + method_ty: method, origin: method_static(provided_method_info.method_info.did) }); } @@ -1126,20 +1116,21 @@ pub impl<'self> LookupContext<'self> { // If they were not explicitly supplied, just construct fresh // type variables. let num_supplied_tps = self.supplied_tps.len(); + let num_method_tps = candidate.method_ty.tps.len(); let m_substs = { if num_supplied_tps == 0u { - self.fcx.infcx().next_ty_vars(candidate.num_method_tps) - } else if candidate.num_method_tps == 0u { + self.fcx.infcx().next_ty_vars(num_method_tps) + } else if num_method_tps == 0u { tcx.sess.span_err( self.expr.span, ~"this method does not take type parameters"); - self.fcx.infcx().next_ty_vars(candidate.num_method_tps) - } else if num_supplied_tps != candidate.num_method_tps { + self.fcx.infcx().next_ty_vars(num_method_tps) + } else if num_supplied_tps != num_method_tps { tcx.sess.span_err( self.expr.span, ~"incorrect number of type \ parameters given for this method"); - self.fcx.infcx().next_ty_vars(candidate.num_method_tps) + self.fcx.infcx().next_ty_vars(num_method_tps) } else { self.supplied_tps.to_vec() } @@ -1178,14 +1169,16 @@ pub impl<'self> LookupContext<'self> { let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty}); debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty)); + let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty); + self.fcx.write_ty(self.callee_id, fty); self.fcx.write_substs(self.callee_id, all_substs); method_map_entry { self_arg: arg { - mode: ast::expl(candidate.self_mode), + mode: ast::expl(self_mode), ty: candidate.rcvr_ty, }, - explicit_self: candidate.explicit_self, + explicit_self: candidate.method_ty.self_ty, origin: candidate.origin, } } @@ -1217,7 +1210,7 @@ pub impl<'self> LookupContext<'self> { self-type through a boxed trait"); } - if candidate.num_method_tps > 0 { + if candidate.method_ty.tps.len() > 0 { self.tcx().sess.span_err( self.expr.span, ~"cannot call a generic method through a boxed trait"); @@ -1334,10 +1327,9 @@ pub impl<'self> LookupContext<'self> { } fn cand_to_str(&self, cand: &Candidate) -> ~str { - fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, self_mode=%?, origin=%?)", + fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)", self.ty_to_str(cand.rcvr_ty), ty::substs_to_str(self.tcx(), &cand.rcvr_substs), - cand.self_mode, cand.origin) } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index c8b274e456916..560fcb8c9209f 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2125,7 +2125,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, match expr.node { ast::expr_vstore(ev, vst) => { let typ = match ev.node { - ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => { + ast::expr_lit(@codemap::spanned { node: ast::lit_str(_), _ }) => { let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); ty::mk_estr(tcx, tt) } @@ -2162,7 +2162,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } ast::expr_repeat(element, count_expr, mutbl) => { - let count = ty::eval_repeat_count(tcx, count_expr); + let _ = ty::eval_repeat_count(tcx, count_expr); check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx)); let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); let mutability = match vst { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index ab99aa20d6487..22b6926e9f0c5 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -333,10 +333,16 @@ pub impl CoherenceChecker { let new_id = parse::next_node_id(tcx.sess.parse_sess); let new_did = local_def(new_id); + let new_method_ty = @ty::method { + def_id: new_did, + ..copy *trait_method + }; + // XXX: Perform substitutions. let new_polytype = ty::lookup_item_type(tcx, trait_method.def_id); tcx.tcache.insert(new_did, new_polytype); + tcx.methods.insert(new_did, new_method_ty); // Pair the new synthesized ID up with the // ID of the method. @@ -498,7 +504,7 @@ pub impl CoherenceChecker { fn each_provided_trait_method(&self, trait_did: ast::def_id, - f: &fn(x: &ty::method) -> bool) { + f: &fn(x: @ty::method) -> bool) { // Make a list of all the names of the provided methods. // XXX: This is horrible. let mut provided_method_idents = HashSet::new(); From 3333b0f1177fd758cfd95d992aed18972ed26dfb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 29 Mar 2013 16:02:55 -0400 Subject: [PATCH 048/403] Add a (currently unused) "transformed self type" pointer into ty::method --- src/librustc/metadata/common.rs | 1 + src/librustc/metadata/decoder.rs | 19 +++++- src/librustc/metadata/encoder.rs | 12 ++++ src/librustc/middle/ty.rs | 1 + src/librustc/middle/typeck/astconv.rs | 87 ++++++++++++++++++++++++-- src/librustc/middle/typeck/collect.rs | 53 +++++++++------- src/test/run-pass/regions-expl-self.rs | 2 +- 7 files changed, 144 insertions(+), 31 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index d3b06009d727e..5df7b0373341a 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -162,6 +162,7 @@ pub static tag_link_args_arg: uint = 0x7a; pub static tag_item_method_tps: uint = 0x7b; pub static tag_item_method_fty: uint = 0x7c; +pub static tag_item_method_transformed_self_ty: uint = 0x7d; pub struct LinkMeta { name: @str, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 598539609e9eb..32a912d010185 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -236,6 +236,16 @@ fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy { |_, did| translate_def_id(cdata, did)) } +fn doc_transformed_self_ty(doc: ebml::Doc, + tcx: ty::ctxt, + cdata: cmd) -> Option +{ + do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| { + parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, + |_, did| translate_def_id(cdata, did)) + } +} + pub fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let t = doc_type(item, tcx, cdata); @@ -716,14 +726,17 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, let method_doc = lookup_item(id, cdata.data); let def_id = item_def_id(method_doc, cdata); let name = item_name(intr, method_doc); - let bounds = item_ty_param_bounds(method_doc, tcx, cdata, - tag_item_method_tps); + let bounds = + item_ty_param_bounds(method_doc, tcx, cdata, + tag_item_method_tps); + let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata); let fty = doc_method_fty(method_doc, tcx, cdata); let vis = item_visibility(method_doc); let self_ty = get_self_ty(method_doc); ty::method { ident: name, tps: bounds, + transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, vis: vis, @@ -767,10 +780,12 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, } }; + let transformed_self_ty = doc_transformed_self_ty(mth, tcx, cdata); let self_ty = get_self_ty(mth); let ty_method = ty::method { ident: name, tps: bounds, + transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, vis: ast::public, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2e3008a0cdc88..e8fc4c44fea62 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -230,6 +230,17 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { ebml_w.end_tag(); } +fn encode_transformed_self_ty(ecx: @EncodeContext, + ebml_w: writer::Encoder, + opt_typ: Option) +{ + for opt_typ.each |&typ| { + ebml_w.start_tag(tag_item_method_transformed_self_ty); + write_type(ecx, ebml_w, typ); + ebml_w.end_tag(); + } +} + fn encode_method_fty(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: &ty::BareFnTy) @@ -570,6 +581,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext, encode_name(ecx, ebml_w, method_ty.ident); encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, tag_item_method_tps); + encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty); encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_visibility(ebml_w, method_ty.vis); encode_self_type(ebml_w, method_ty.self_ty); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fcdd5a650af81..eb9eec25c0480 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -71,6 +71,7 @@ pub type param_bounds = @~[param_bound]; pub struct method { ident: ast::ident, tps: @~[param_bounds], + transformed_self_ty: Option, fty: BareFnTy, self_ty: ast::self_ty_, vis: ast::visibility, diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c54e76b9c0579..05a5e926f279d 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -544,6 +544,29 @@ pub fn bound_lifetimes( bound_lifetime_names } +struct SelfInfo { + untransformed_self_ty: ty::t, + self_transform: ast::self_ty +} + +pub fn ty_of_method( + self: &AC, + rscope: &RS, + purity: ast::purity, + lifetimes: &OptVec, + untransformed_self_ty: ty::t, + self_transform: ast::self_ty, + decl: &ast::fn_decl) -> (Option, ty::BareFnTy) +{ + let self_info = SelfInfo { + untransformed_self_ty: untransformed_self_ty, + self_transform: self_transform + }; + let (a, b) = ty_of_method_or_bare_fn( + self, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl); + (a.get(), b) +} + pub fn ty_of_bare_fn( self: &AC, rscope: &RS, @@ -551,6 +574,20 @@ pub fn ty_of_bare_fn( abi: AbiSet, lifetimes: &OptVec, decl: &ast::fn_decl) -> ty::BareFnTy +{ + let (_, b) = ty_of_method_or_bare_fn( + self, rscope, purity, abi, lifetimes, None, decl); + b +} + +fn ty_of_method_or_bare_fn( + self: &AC, + rscope: &RS, + purity: ast::purity, + abi: AbiSet, + lifetimes: &OptVec, + opt_self_info: Option<&SelfInfo>, + decl: &ast::fn_decl) -> (Option>, ty::BareFnTy) { debug!("ty_of_bare_fn"); @@ -559,18 +596,56 @@ pub fn ty_of_bare_fn( let bound_lifetime_names = bound_lifetimes(self, lifetimes); let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names)); + let opt_transformed_self_ty = opt_self_info.map(|&self_info| { + transform_self_ty(self, &rb, self_info) + }); + let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None)); + let output_ty = match decl.output.node { ast::ty_infer => self.ty_infer(decl.output.span), _ => ast_ty_to_ty(self, &rb, decl.output) }; - ty::BareFnTy { - purity: purity, - abis: abi, - sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names, - inputs: input_tys, - output: output_ty} + return (opt_transformed_self_ty, + ty::BareFnTy { + purity: purity, + abis: abi, + sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names, + inputs: input_tys, + output: output_ty} + }); + + fn transform_self_ty( + self: &AC, + rscope: &RS, + self_info: &SelfInfo) -> Option + { + match self_info.self_transform.node { + ast::sty_static => None, + ast::sty_value => { + Some(self_info.untransformed_self_ty) + } + ast::sty_region(lifetime, mutability) => { + let region = + ast_region_to_region(self, rscope, + self_info.self_transform.span, + lifetime); + Some(ty::mk_rptr(self.tcx(), region, + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + ast::sty_box(mutability) => { + Some(ty::mk_box(self.tcx(), + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + ast::sty_uniq(mutability) => { + Some(ty::mk_uniq(self.tcx(), + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + } } } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 3ac3766e89da4..81acae1d3a99b 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -237,15 +237,17 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, for ms.each |m| { let ty_method = @match m { &ast::required(ref m) => { - ty_method_of_trait_method(ccx, region_paramd, generics, - &m.id, &m.ident, &m.self_ty, - &m.generics, &m.purity, &m.decl) + ty_method_of_trait_method( + ccx, trait_id, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) } &ast::provided(ref m) => { - ty_method_of_trait_method(ccx, region_paramd, generics, - &m.id, &m.ident, &m.self_ty, - &m.generics, &m.purity, &m.decl) + ty_method_of_trait_method( + ccx, trait_id, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) } }; @@ -316,6 +318,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, } fn ty_method_of_trait_method(self: &CrateCtxt, + trait_id: ast::node_id, trait_rp: Option, trait_generics: &ast::Generics, m_id: &ast::node_id, @@ -325,16 +328,16 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, m_purity: &ast::purity, m_decl: &ast::fn_decl) -> ty::method { + let trait_self_ty = ty::mk_self(self.tcx, local_def(trait_id)); let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics); + let (transformed_self_ty, fty) = + astconv::ty_of_method(self, &rscope, *m_purity, &m_generics.lifetimes, + trait_self_ty, *m_self_ty, m_decl); ty::method { ident: *m_ident, tps: ty_param_bounds(self, m_generics), - fty: astconv::ty_of_bare_fn(self, - &rscope, - *m_purity, - AbiSet::Rust(), - &m_generics.lifetimes, - m_decl), + transformed_self_ty: transformed_self_ty, + fty: fty, self_ty: m_self_ty.node, // assume public, because this is only invoked on trait methods vis: ast::public, @@ -607,6 +610,7 @@ pub struct ConvertedMethod { pub fn convert_methods(ccx: &CrateCtxt, ms: &[@ast::method], rp: Option, + untransformed_rcvr_ty: ty::t, rcvr_bounds: @~[ty::param_bounds], rcvr_generics: &ast::Generics, rcvr_visibility: ast::visibility) @@ -615,8 +619,9 @@ pub fn convert_methods(ccx: &CrateCtxt, let tcx = ccx.tcx; return vec::map(ms, |m| { let bounds = ty_param_bounds(ccx, &m.generics); - let mty = @ty_of_method(ccx, *m, rp, rcvr_generics, - rcvr_visibility, &m.generics); + let mty = @ty_of_method( + ccx, *m, rp, untransformed_rcvr_ty, + rcvr_generics, rcvr_visibility, &m.generics); let fty = ty::mk_bare_fn(tcx, copy mty.fty); tcx.tcache.insert( local_def(m.id), @@ -637,6 +642,7 @@ pub fn convert_methods(ccx: &CrateCtxt, fn ty_of_method(ccx: &CrateCtxt, m: @ast::method, rp: Option, + untransformed_rcvr_ty: ty::t, rcvr_generics: &ast::Generics, rcvr_visibility: ast::visibility, method_generics: &ast::Generics) -> ty::method @@ -644,15 +650,16 @@ pub fn convert_methods(ccx: &CrateCtxt, let rscope = MethodRscope::new(m.self_ty.node, rp, rcvr_generics); + let (transformed_self_ty, fty) = + astconv::ty_of_method(ccx, &rscope, m.purity, + &method_generics.lifetimes, + untransformed_rcvr_ty, + m.self_ty, &m.decl); ty::method { ident: m.ident, tps: ty_param_bounds(ccx, &m.generics), - fty: astconv::ty_of_bare_fn(ccx, - &rscope, - m.purity, - ast::RustAbi, - &method_generics.lifetimes, - &m.decl), + transformed_self_ty: transformed_self_ty, + fty: fty, self_ty: m.self_ty.node, vis: m.vis.inherit_from(rcvr_visibility), def_id: local_def(m.id) @@ -715,7 +722,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { it.vis }; - let cms = convert_methods(ccx, *ms, rp, i_bounds, generics, + let cms = convert_methods(ccx, *ms, rp, selfty, i_bounds, generics, parent_visibility); for opt_trait_ref.each |t| { check_methods_against_trait(ccx, generics, rp, selfty, *t, cms); @@ -732,7 +739,9 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { let (_, provided_methods) = split_trait_methods(*trait_methods); let (bounds, _) = mk_substs(ccx, generics, rp); - let _ = convert_methods(ccx, provided_methods, rp, bounds, generics, + let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); + let _ = convert_methods(ccx, provided_methods, rp, + untransformed_rcvr_ty, bounds, generics, it.vis); } ast::item_struct(struct_def, ref generics) => { diff --git a/src/test/run-pass/regions-expl-self.rs b/src/test/run-pass/regions-expl-self.rs index 05f0994c7655d..174b9a206ccdf 100644 --- a/src/test/run-pass/regions-expl-self.rs +++ b/src/test/run-pass/regions-expl-self.rs @@ -15,7 +15,7 @@ struct Foo { } pub impl Foo { - fn foo(&'a self) {} + fn foo<'a>(&'a self) {} } pub fn main() {} \ No newline at end of file From d28f7344125b47b7e991413c5612708ce8d5ed77 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 27 Mar 2013 06:16:28 -0400 Subject: [PATCH 049/403] Refactor so that references to traits are not represented using a type with a bare function store (which is not in fact a kind of value) but rather ty::TraitRef. Removes many uses of fail!() and other telltale signs of type-semantic mismatch. cc #4183 (not a fix, but related) --- src/libcore/option.rs | 28 +- src/libcore/reflect.rs | 4 +- src/libcore/run.rs | 2 +- src/librustc/metadata/common.rs | 4 +- src/librustc/metadata/csearch.rs | 15 +- src/librustc/metadata/decoder.rs | 71 ++- src/librustc/metadata/encoder.rs | 38 +- src/librustc/metadata/tydecode.rs | 15 +- src/librustc/metadata/tyencode.rs | 11 +- src/librustc/middle/astencode.rs | 40 +- src/librustc/middle/kind.rs | 6 +- src/librustc/middle/lint.rs | 3 +- src/librustc/middle/resolve.rs | 47 +- src/librustc/middle/trans/common.rs | 3 - src/librustc/middle/trans/glue.rs | 15 +- src/librustc/middle/trans/inline.rs | 3 +- src/librustc/middle/trans/meth.rs | 29 +- src/librustc/middle/trans/monomorphize.rs | 6 +- src/librustc/middle/ty.rs | 257 ++++++----- src/librustc/middle/typeck/astconv.rs | 163 ++++--- src/librustc/middle/typeck/check/_match.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 43 +- src/librustc/middle/typeck/check/mod.rs | 49 +- src/librustc/middle/typeck/check/vtable.rs | 310 ++++++------- src/librustc/middle/typeck/coherence.rs | 33 +- src/librustc/middle/typeck/collect.rs | 480 ++++++++++---------- src/librustc/middle/typeck/infer/combine.rs | 69 ++- src/librustc/middle/typeck/infer/glb.rs | 9 +- src/librustc/middle/typeck/infer/lub.rs | 9 +- src/librustc/middle/typeck/infer/mod.rs | 49 +- src/librustc/middle/typeck/infer/sub.rs | 9 +- src/librustc/middle/typeck/infer/to_str.rs | 8 +- src/librustc/middle/typeck/mod.rs | 4 +- src/librustc/util/ppaux.rs | 7 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/ext/auto_encode.rs | 14 +- src/libsyntax/ext/build.rs | 11 + src/libsyntax/ext/deriving/mod.rs | 6 +- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/parser.rs | 25 +- src/libsyntax/print/pprust.rs | 8 +- src/libsyntax/visit.rs | 14 +- src/test/compile-fail/issue-2330.rs | 2 +- src/test/compile-fail/selftype-traittype.rs | 2 +- src/test/run-pass/issue-3702.rs | 2 +- src/test/run-pass/reflect-visit-data.rs | 4 +- 46 files changed, 1071 insertions(+), 862 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index cd34d7ab0c0bb..de1482e2c3918 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -46,7 +46,8 @@ use ops::Add; use kinds::Copy; use util; use num::Zero; -use iter::{BaseIter, MutableIter}; +use iter::{BaseIter, MutableIter, ExtendedIter}; +use iter; #[cfg(test)] use ptr; #[cfg(test)] use str; @@ -118,6 +119,31 @@ impl MutableIter for Option { } } +impl ExtendedIter for Option { + pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { + iter::eachi(self, blk) + } + pub fn all(&self, blk: &fn(&A) -> bool) -> bool { + iter::all(self, blk) + } + pub fn any(&self, blk: &fn(&A) -> bool) -> bool { + iter::any(self, blk) + } + pub fn foldl(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { + iter::foldl(self, b0, blk) + } + pub fn position(&self, f: &fn(&A) -> bool) -> Option { + iter::position(self, f) + } + fn map_to_vec(&self, op: &fn(&A) -> B) -> ~[B] { + iter::map_to_vec(self, op) + } + fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) + -> ~[B] { + iter::flat_map_to_vec(self, op) + } +} + pub impl Option { /// Returns true if the option equals `none` fn is_none(&const self) -> bool { diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 3e11febc5bfaa..a449c4e73cf7e 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -443,9 +443,9 @@ impl TyVisitor for MovePtrAdaptor { } fn visit_trait(&self) -> bool { - self.align_to::(); + self.align_to::<@TyVisitor>(); if ! self.inner.visit_trait() { return false; } - self.bump_past::(); + self.bump_past::<@TyVisitor>(); true } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 8116ea952e425..98564beeba901 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -298,7 +298,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { @ProgRes(repr) as @Program } -fn read_all(rd: io::Reader) -> ~str { +fn read_all(rd: @io::Reader) -> ~str { let buf = io::with_bytes_writer(|wr| { let mut bytes = [0, ..4096]; while !rd.eof() { diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 5df7b0373341a..71a1f1b3f9b20 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -74,7 +74,9 @@ pub static tag_crate_dep_vers: uint = 0x2cu; pub static tag_mod_impl: uint = 0x30u; pub static tag_item_trait_method: uint = 0x31u; -pub static tag_impl_trait: uint = 0x32u; + +pub static tag_item_trait_ref: uint = 0x32u; +pub static tag_item_super_trait_ref: uint = 0x33u; // discriminator value for variants pub static tag_disr_val: uint = 0x34u; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 8e7ecdec638b1..74e891a01942f 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -139,7 +139,7 @@ pub fn get_provided_trait_methods(tcx: ty::ctxt, decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx) } -pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { +pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[@ty::TraitRef] { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); decoder::get_supertraits(cdata, def.node, tcx) @@ -180,6 +180,12 @@ pub fn get_type(tcx: ty::ctxt, decoder::get_type(cdata, def.node, tcx) } +pub fn get_trait_def(tcx: ty::ctxt, def: ast::def_id) -> ty::TraitDef { + let cstore = tcx.cstore; + let cdata = cstore::get_crate_data(cstore, def.crate); + decoder::get_trait_def(cdata, def.node, tcx) +} + pub fn get_region_param(cstore: @mut metadata::cstore::CStore, def: ast::def_id) -> Option { let cdata = cstore::get_crate_data(cstore, def.crate); @@ -204,8 +210,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id, debug!("got field data %?", the_field); let ty = decoder::item_type(def, the_field, tcx, cdata); ty::ty_param_bounds_and_ty { - bounds: @~[], - region_param: None, + generics: ty::Generics {bounds: @~[], + region_param: None}, ty: ty } } @@ -213,7 +219,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id, // Given a def_id for an impl or class, return the traits it implements, // or the empty vector if it's not for an impl or for a class that implements // traits -pub fn get_impl_traits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { +pub fn get_impl_traits(tcx: ty::ctxt, + def: ast::def_id) -> ~[@ty::TraitRef] { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); decoder::get_impl_traits(cdata, def.node, tcx) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 32a912d010185..d9ef30ff297d0 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -20,7 +20,7 @@ use metadata::csearch; use metadata::cstore; use metadata::decoder; use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, - parse_bare_fn_ty_data}; + parse_bare_fn_ty_data, parse_trait_ref_data}; use middle::{ty, resolve}; use core::hash::HashUtil; @@ -256,12 +256,14 @@ pub fn item_type(item_id: ast::def_id, item: ebml::Doc, } } -fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { - let mut results = ~[]; - for reader::tagged_docs(item, tag_impl_trait) |ity| { - results.push(doc_type(ity, tcx, cdata)); - }; - results +fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { + parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx, + |_, did| translate_def_id(cdata, did)) +} + +fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { + let tp = reader::get_doc(doc, tag_item_trait_ref); + doc_trait_ref(tp, tcx, cdata) } fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd, @@ -371,6 +373,21 @@ pub fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) -> return def_like_to_def(item_to_def_like(item, did, cnum)); } +pub fn get_trait_def(cdata: cmd, + item_id: ast::node_id, + tcx: ty::ctxt) -> ty::TraitDef +{ + let item_doc = lookup_item(item_id, cdata.data); + let tp_bounds = item_ty_param_bounds(item_doc, tcx, cdata, + tag_items_data_item_ty_param_bounds); + let rp = item_ty_region_param(item_doc); + ty::TraitDef { + generics: ty::Generics {bounds: tp_bounds, + region_param: rp}, + trait_ref: @item_trait_ref(item_doc, tcx, cdata) + } +} + pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ty::ty_param_bounds_and_ty { @@ -382,8 +399,8 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) } else { @~[] }; let rp = item_ty_region_param(item); ty::ty_param_bounds_and_ty { - bounds: tp_bounds, - region_param: rp, + generics: ty::Generics {bounds: tp_bounds, + region_param: rp}, ty: t } } @@ -399,9 +416,19 @@ pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint { item_ty_param_count(lookup_item(id, data)) } -pub fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) - -> ~[ty::t] { - item_impl_traits(lookup_item(id, cdata.data), tcx, cdata) +pub fn get_impl_traits(cdata: cmd, + id: ast::node_id, + tcx: ty::ctxt) -> ~[@ty::TraitRef] +{ + let item_doc = lookup_item(id, cdata.data); + let mut results = ~[]; + for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| { + let trait_ref = + @parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx, + |_, did| translate_def_id(cdata, did)); + results.push(trait_ref); + }; + results } pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, @@ -735,7 +762,10 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, let self_ty = get_self_ty(method_doc); ty::method { ident: name, - tps: bounds, + generics: ty::Generics { + bounds: bounds, + region_param: None + }, transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, @@ -784,7 +814,10 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let self_ty = get_self_ty(mth); let ty_method = ty::method { ident: name, - tps: bounds, + generics: ty::Generics { + bounds: bounds, + region_param: None + }, transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, @@ -804,11 +837,11 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, /// Returns the supertraits of the given trait. pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) - -> ~[ty::t] { + -> ~[@ty::TraitRef] { let mut results = ~[]; let item_doc = lookup_item(id, cdata.data); - for reader::tagged_docs(item_doc, tag_impl_trait) |trait_doc| { - results.push(doc_type(trait_doc, tcx, cdata)); + for reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| { + results.push(@doc_trait_ref(trait_doc, tcx, cdata)); } return results; } @@ -837,8 +870,8 @@ pub fn get_static_methods_if_impl(intr: @ident_interner, return None; } - // If this impl has a trait ref, don't consider it. - for reader::tagged_docs(item, tag_impl_trait) |_doc| { + // If this impl implements a trait, don't consider it. + for reader::tagged_docs(item, tag_item_trait_ref) |_doc| { return None; } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e8fc4c44fea62..e251af7c8a85b 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -153,14 +153,23 @@ fn add_to_index(ecx: @EncodeContext, ebml_w: writer::Encoder, path: &[ident], }); } -fn encode_trait_ref(ebml_w: writer::Encoder, ecx: @EncodeContext, - t: @trait_ref) { - ebml_w.start_tag(tag_impl_trait); - encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id)); +fn encode_trait_ref(ebml_w: writer::Encoder, + ecx: @EncodeContext, + trait_ref: &ty::TraitRef, + tag: uint) +{ + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + + ebml_w.start_tag(tag); + tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref); ebml_w.end_tag(); } - // Item info table encoding fn encode_family(ebml_w: writer::Encoder, c: char) { ebml_w.start_tag(tag_items_data_item_family); @@ -579,7 +588,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext, { encode_def_id(ebml_w, method_ty.def_id); encode_name(ecx, ebml_w, method_ty.ident); - encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, + encode_ty_type_param_bounds(ebml_w, ecx, method_ty.generics.bounds, tag_item_method_tps); encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty); encode_method_fty(ecx, ebml_w, &method_ty.fty); @@ -872,8 +881,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id))); ebml_w.end_tag(); } - for opt_trait.each |associated_trait| { - encode_trait_ref(ebml_w, ecx, *associated_trait); + for opt_trait.each |ast_trait_ref| { + let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id); + encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); ebml_w.end_tag(); @@ -894,14 +904,15 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, &m.generics); } } - item_trait(ref generics, ref traits, ref ms) => { + item_trait(ref generics, ref super_traits, ref ms) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, 'I'); encode_region_param(ecx, ebml_w, item); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); - encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); + let trait_def = ty::lookup_trait_def(tcx, local_def(item.id)); + encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref); encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| { @@ -910,8 +921,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.end_tag(); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); - for traits.each |associated_trait| { - encode_trait_ref(ebml_w, ecx, *associated_trait); + for super_traits.each |ast_trait_ref| { + let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id); + encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref); } ebml_w.end_tag(); @@ -940,7 +952,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, method_ty.fty.purity)); let tpt = ty::lookup_item_type(tcx, method_def_id); - encode_ty_type_param_bounds(ebml_w, ecx, tpt.bounds, + encode_ty_type_param_bounds(ebml_w, ecx, tpt.generics.bounds, tag_items_data_item_ty_param_bounds); encode_type(ecx, ebml_w, tpt.ty); } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 2982ed268770d..2ec13abb483d6 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -125,6 +125,12 @@ pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::c parse_bare_fn_ty(st, conv) } +pub fn parse_trait_ref_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, + conv: conv_did) -> ty::TraitRef { + let st = parse_state_from_data(data, crate_num, pos, tcx); + parse_trait_ref(st, conv) +} + pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, conv: conv_did) -> ty::arg { let st = parse_state_from_data(data, crate_num, pos, tcx); @@ -183,7 +189,6 @@ fn parse_trait_store(st: @mut PState) -> ty::TraitStore { '~' => ty::UniqTraitStore, '@' => ty::BoxTraitStore, '&' => ty::RegionTraitStore(parse_region(st)), - '.' => ty::BareTraitStore, c => st.tcx.sess.bug(fmt!("parse_trait_store(): bad input '%c'", c)) } } @@ -265,6 +270,12 @@ fn parse_str(st: @mut PState, term: char) -> ~str { return result; } +fn parse_trait_ref(st: @mut PState, conv: conv_did) -> ty::TraitRef { + let def = parse_def(st, NominalType, conv); + let substs = parse_substs(st, conv); + ty::TraitRef {def_id: def, substs: substs} +} + fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { match next(st) { 'n' => return ty::mk_nil(st.tcx), @@ -551,7 +562,7 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] { 'C' => ty::bound_copy, 'K' => ty::bound_const, 'O' => ty::bound_durable, - 'I' => ty::bound_trait(parse_ty(st, conv)), + 'I' => ty::bound_trait(@parse_trait_ref(st, conv)), '.' => break, _ => fail!(~"parse_bounds: bad bounds") }); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 419219d411d89..ca2d66de9c44d 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -214,11 +214,16 @@ pub fn enc_vstore(w: @io::Writer, cx: @ctxt, v: ty::vstore) { } } +pub fn enc_trait_ref(w: @io::Writer, cx: @ctxt, s: &ty::TraitRef) { + w.write_str((cx.ds)(s.def_id)); + w.write_char('|'); + enc_substs(w, cx, s.substs); +} + pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) { match s { ty::UniqTraitStore => w.write_char('~'), ty::BoxTraitStore => w.write_char('@'), - ty::BareTraitStore => w.write_char('.'), ty::RegionTraitStore(re) => { w.write_char('&'); enc_region(w, cx, re); @@ -415,8 +420,8 @@ pub fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { ty::bound_const => w.write_char('K'), ty::bound_durable => w.write_char('O'), ty::bound_trait(tp) => { - w.write_char('I'); - enc_ty(w, cx, tp); + w.write_char('I'); + enc_trait_ref(w, cx, tp); } } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 6fc74c9a7130d..20b72a19df794 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -779,16 +779,20 @@ impl ebml_writer_helpers for writer::Encoder { fn emit_tpbt(&self, ecx: @e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty) { - do self.emit_struct("ty_param_bounds_and_ty", 3) { - do self.emit_field(~"bounds", 0) { - do self.emit_from_vec(*tpbt.bounds) |bs| { - self.emit_bounds(ecx, *bs); + do self.emit_struct("ty_param_bounds_and_ty", 2) { + do self.emit_field(~"generics", 0) { + do self.emit_struct("Generics", 2) { + do self.emit_field(~"bounds", 0) { + do self.emit_from_vec(*tpbt.generics.bounds) |bs| { + self.emit_bounds(ecx, *bs); + } + } + do self.emit_field(~"region_param", 1) { + tpbt.generics.region_param.encode(self); + } } } - do self.emit_field(~"region_param", 1u) { - tpbt.region_param.encode(self); - } - do self.emit_field(~"ty", 2u) { + do self.emit_field(~"ty", 1) { self.emit_ty(ecx, tpbt.ty); } } @@ -1046,15 +1050,19 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) -> ty::ty_param_bounds_and_ty { - do self.read_struct("ty_param_bounds_and_ty", 3) { + do self.read_struct("ty_param_bounds_and_ty", 2) { ty::ty_param_bounds_and_ty { - bounds: self.read_field(~"bounds", 0u, || { - @self.read_to_vec(|| self.read_bounds(xcx) ) - }), - region_param: self.read_field(~"region_param", 1u, || { - Decodable::decode(self) - }), - ty: self.read_field(~"ty", 2u, || { + generics: do self.read_struct("Generics", 2) { + ty::Generics { + bounds: self.read_field(~"bounds", 0, || { + @self.read_to_vec(|| self.read_bounds(xcx) ) + }), + region_param: self.read_field(~"region_param", 1, || { + Decodable::decode(self) + }) + } + }, + ty: self.read_field(~"ty", 1, || { self.read_ty(xcx) }) } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index a25e2f49e099e..96e8ef40770a2 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -91,7 +91,7 @@ fn check_struct_safe_for_destructor(cx: Context, span: span, struct_did: def_id) { let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did); - if struct_tpt.bounds.len() == 0 { + if struct_tpt.generics.bounds.len() == 0 { let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs { self_r: None, self_ty: None, @@ -279,7 +279,7 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt) { let bounds = match e.node { expr_path(_) => { let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id)); - ty::lookup_item_type(cx.tcx, did).bounds + ty::lookup_item_type(cx.tcx, did).generics.bounds } _ => { // Type substitutions should only occur on paths and @@ -340,7 +340,7 @@ fn check_ty(aty: @Ty, cx: Context, v: visit::vt) { // FIXME(#5562): removing this copy causes a segfault before stage2 let ts = /*bad*/ copy **ts; let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id)); - let bounds = ty::lookup_item_type(cx.tcx, did).bounds; + let bounds = ty::lookup_item_type(cx.tcx, did).generics.bounds; for vec::each2(ts, *bounds) |ty, bound| { check_bounds(cx, aty.id, aty.span, *ty, *bound) } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index a21cc26bd9124..b4aff91ed5b28 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -825,8 +825,7 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) { ast::item_fn(*) | ast::item_ty(*) | ast::item_enum(*) | - ast::item_struct(*) | - ast::item_trait(*) => check_type(cx, it.id, it.id, it.span, + ast::item_struct(*) => check_type(cx, it.id, it.id, it.span, ty::node_id_to_type(cx, it.id)), _ => () } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 7232e99bf2206..fcf0b7022a7a7 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -79,6 +79,7 @@ use syntax::opt_vec::OptVec; use core::option::Some; use core::str::each_split_str; use core::hashmap::{HashMap, HashSet}; +use core::util; // Definition mapping pub type DefMap = @mut HashMap; @@ -3414,7 +3415,6 @@ pub impl Resolver { self_type, ref methods) => { self.resolve_implementation(item.id, - item.span, generics, implemented_traits, self_type, @@ -3723,13 +3723,30 @@ pub impl Resolver { for type_parameters.each |type_parameter| { for type_parameter.bounds.each |&bound| { match bound { - TraitTyParamBound(ty) => self.resolve_type(ty, visitor), + TraitTyParamBound(tref) => { + self.resolve_trait_reference(tref, visitor) + } RegionTyParamBound => {} } } } } + fn resolve_trait_reference(@mut self, + trait_reference: &trait_ref, + visitor: ResolveVisitor) { + match self.resolve_path(trait_reference.path, TypeNS, true, visitor) { + None => { + self.session.span_err(trait_reference.path.span, + ~"attempt to implement an \ + unknown trait"); + } + Some(def) => { + self.record_def(trait_reference.ref_id, def); + } + } + } + fn resolve_struct(@mut self, id: node_id, generics: &Generics, @@ -3797,7 +3814,6 @@ pub impl Resolver { fn resolve_implementation(@mut self, id: node_id, - span: span, generics: &Generics, opt_trait_reference: Option<@trait_ref>, self_type: @Ty, @@ -3816,25 +3832,16 @@ pub impl Resolver { let original_trait_refs; match opt_trait_reference { Some(trait_reference) => { - let mut new_trait_refs = ~[]; - match self.resolve_path( - trait_reference.path, TypeNS, true, visitor) { - None => { - self.session.span_err(span, - ~"attempt to implement an \ - unknown trait"); - } - Some(def) => { - self.record_def(trait_reference.ref_id, def); + self.resolve_trait_reference(trait_reference, visitor); - // Record the current trait reference. - new_trait_refs.push(def_id_of_def(def)); - } - } // Record the current set of trait references. - let mut old = Some(new_trait_refs); - self.current_trait_refs <-> old; - original_trait_refs = Some(old); + let mut new_trait_refs = ~[]; + for self.def_map.find(&trait_reference.ref_id).each |&def| { + new_trait_refs.push(def_id_of_def(*def)); + } + original_trait_refs = Some(util::replace( + &mut self.current_trait_refs, + Some(new_trait_refs))); } None => { original_trait_refs = None; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index f0c17a6f80d7b..593d37c2ff8d1 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1062,9 +1062,6 @@ pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef { ty::RegionTraitStore(_) => { T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())]) } - ty::BareTraitStore => { - cx.sess.bug(~"can't make T_opaque_trait with bare trait store") - } } } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 1b27d21e6f464..d8c8301a83563 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -40,7 +40,6 @@ use core::libc::c_uint; use core::str; use std::time; use syntax::ast; -use syntax::parse::token::special_idents; pub fn trans_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_free"); @@ -400,11 +399,9 @@ pub fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint) pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) { let _icx = bcx.insn_ctxt("make_visit_glue"); let mut bcx = bcx; - let ty_visitor_name = special_idents::ty_visitor; - assert!(bcx.ccx().tcx.intrinsic_defs.contains_key(&ty_visitor_name)); - let (trait_id, ty) = *bcx.ccx().tcx.intrinsic_defs.get(&ty_visitor_name); - let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), ty))); - bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, trait_id); + let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx()); + let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty))); + bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id); build_return(bcx); } @@ -554,8 +551,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { ty::ty_closure(_) => { closure::make_closure_glue(bcx, v0, t, drop_ty) } - ty::ty_trait(_, _, ty::BoxTraitStore) | - ty::ty_trait(_, _, ty::BareTraitStore) => { + ty::ty_trait(_, _, ty::BoxTraitStore) => { let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u])); decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx)) } @@ -621,8 +617,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { ty::ty_closure(_) => { closure::make_closure_glue(bcx, v, t, take_ty) } - ty::ty_trait(_, _, ty::BoxTraitStore) | - ty::ty_trait(_, _, ty::BareTraitStore) => { + ty::ty_trait(_, _, ty::BoxTraitStore) => { let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u])); incr_refcnt_of_boxed(bcx, llbox); bcx diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index cb20e5bbd32c3..2ca19b9075423 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -87,8 +87,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, ccx.stats.n_inlines += 1; ccx.external.insert(fn_id, Some(mth.id)); let ty::ty_param_bounds_and_ty { - bounds: impl_bnds, - region_param: _, + generics: ty::Generics { bounds: impl_bnds, _ }, ty: _ } = ty::lookup_item_type(ccx.tcx, impl_did); if translate && diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index feab9945fc4c3..bbf53480a56fb 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -11,7 +11,6 @@ use core::prelude::*; use back::abi; -use driver; use lib::llvm::llvm; use lib::llvm::ValueRef; use lib; @@ -302,8 +301,8 @@ pub fn trans_static_method_callee(bcx: block, // found on the type parametesr T1...Tn to find the index of the // one we are interested in. let bound_index = { - let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id); - ty::count_traits_and_supertraits(bcx.tcx(), *trait_polyty.bounds) + let trait_def = ty::lookup_trait_def(bcx.tcx(), trait_id); + ty::count_traits_and_supertraits(bcx.tcx(), *trait_def.generics.bounds) }; let mname = if method_id.crate == ast::local_crate { @@ -552,8 +551,10 @@ pub fn combine_impl_and_methods_origins(bcx: block, // rcvr + method bounds. let ccx = bcx.ccx(), tcx = bcx.tcx(); let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); - let ty::ty_param_bounds_and_ty {bounds: r_m_bounds, _} - = ty::lookup_item_type(tcx, mth_did); + let ty::ty_param_bounds_and_ty { + generics: ty::Generics {bounds: r_m_bounds, _}, + _ + } = ty::lookup_item_type(tcx, mth_did); let n_r_m_tps = r_m_bounds.len(); // rcvr + method tps let m_boundss = vec::slice(*r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps); @@ -656,7 +657,6 @@ pub fn trans_trait_callee_from_llval(bcx: block, // payload. match store { ty::BoxTraitStore | - ty::BareTraitStore | ty::UniqTraitStore => { llself = GEPi(bcx, llbox, [0u, abi::box_field_body]); } @@ -679,7 +679,7 @@ pub fn trans_trait_callee_from_llval(bcx: block, // Pass a pointer to the box. match store { - ty::BoxTraitStore | ty::BareTraitStore => llself = llbox, + ty::BoxTraitStore => llself = llbox, _ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait") } @@ -785,19 +785,14 @@ pub fn make_impl_vtable(ccx: @CrateContext, let tcx = ccx.tcx; // XXX: This should support multiple traits. - let trt_id = driver::session::expect( - tcx.sess, - ty::ty_to_def_id(ty::impl_traits(tcx, - impl_id, - ty::BoxTraitStore)[0]), - || ~"make_impl_vtable: non-trait-type implemented"); - - let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; + let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id; + + let has_tps = ty::lookup_item_type(ccx.tcx, impl_id).generics.bounds.len() > 0u; make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| { let im = ty::method(tcx, *method_def_id); let fty = ty::subst_tps(tcx, substs, None, ty::mk_bare_fn(tcx, copy im.fty)); - if im.tps.len() > 0u || ty::type_has_self(fty) { + if im.generics.bounds.len() > 0u || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", *tcx.sess.str_of(im.ident)); C_null(T_ptr(T_nil())) @@ -844,7 +839,7 @@ pub fn trans_trait_cast(bcx: block, let v_ty = expr_ty(bcx, val); match store { - ty::RegionTraitStore(_) | ty::BoxTraitStore | ty::BareTraitStore => { + ty::RegionTraitStore(_) | ty::BoxTraitStore => { let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]); // Just store the pointer into the pair. llboxdest = PointerCast(bcx, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 89617ac5eb8c3..319f57fb75ce0 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -169,7 +169,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, let psubsts = Some(@param_substs { tys: substs, vtables: vtables, - bounds: tpt.bounds, + bounds: tpt.generics.bounds, self_ty: impl_ty_opt }); @@ -291,7 +291,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, ty::ty_trait(_, _, ref store) => { let sigil = match *store { ty::UniqTraitStore => ast::OwnedSigil, - ty::BoxTraitStore | ty::BareTraitStore => ast::ManagedSigil, + ty::BoxTraitStore => ast::ManagedSigil, ty::RegionTraitStore(_) => ast::BorrowedSigil, }; @@ -328,7 +328,7 @@ pub fn make_mono_id(ccx: @CrateContext, item: ast::def_id, substs: &[ty::t], +param_uses: Option<~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { - let bounds = ty::lookup_item_type(ccx.tcx, item).bounds; + let bounds = ty::lookup_item_type(ccx.tcx, item).generics.bounds; let mut i = 0; vec::map2(*bounds, substs, |bounds, subst| { let mut v = ~[]; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index eb9eec25c0480..b1d977b7445cc 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -25,8 +25,10 @@ use middle; use util::ppaux::{note_and_explain_region, bound_region_to_str}; use util::ppaux::{region_to_str, vstore_to_str}; use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str}; +use util::ppaux::{trait_ref_to_str}; use util::common::{indenter}; +use core; use core::cast; use core::cmp; use core::ops; @@ -44,6 +46,7 @@ use syntax::ast_util; use syntax::codemap::span; use syntax::codemap; use syntax::print::pprust; +use syntax::parse::token::special_idents; use syntax::{ast, ast_map}; use syntax::opt_vec::OptVec; use syntax::opt_vec; @@ -70,7 +73,7 @@ pub type param_bounds = @~[param_bound]; pub struct method { ident: ast::ident, - tps: @~[param_bounds], + generics: ty::Generics, transformed_self_ty: Option, fty: BareFnTy, self_ty: ast::self_ty_, @@ -96,9 +99,8 @@ pub enum vstore { #[auto_encode] #[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum TraitStore { - BareTraitStore, // a plain trait without a sigil BoxTraitStore, // @Trait UniqTraitStore, // ~Trait RegionTraitStore(Region), // &Trait @@ -225,11 +227,6 @@ pub struct ProvidedMethodSource { impl_id: ast::def_id } -pub struct InstantiatedTraitRef { - def_id: ast::def_id, - tpt: ty_param_substs_and_ty -} - pub type ctxt = @ctxt_; struct ctxt_ { @@ -265,8 +262,12 @@ struct ctxt_ { // A cache for the trait_methods() routine trait_methods_cache: @mut HashMap, + trait_refs: @mut HashMap, + trait_defs: @mut HashMap, + items: ast_map::map, intrinsic_defs: @mut HashMap, + intrinsic_traits: @mut HashMap, freevars: freevars::freevar_map, tcache: type_cache, rcache: creader_cache, @@ -286,7 +287,7 @@ struct ctxt_ { // that implementation implements. provided_methods: ProvidedMethodsMap, provided_method_sources: @mut HashMap, - supertraits: @mut HashMap, + supertraits: @mut HashMap, // A mapping from the def ID of an enum or struct type to the def ID // of the method that implements its destructor. If the type is not @@ -536,6 +537,12 @@ pub enum sty { ty_unboxed_vec(mt), } +#[deriving(Eq, IterBytes)] +pub struct TraitRef { + def_id: def_id, + substs: substs +} + #[deriving(Eq)] pub enum IntVarValue { IntType(ast::int_ty), @@ -582,16 +589,17 @@ pub enum type_err { terr_self_substs, terr_integer_as_char, terr_int_mismatch(expected_found), - terr_float_mismatch(expected_found) + terr_float_mismatch(expected_found), + terr_traits(expected_found), } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum param_bound { bound_copy, bound_durable, bound_owned, bound_const, - bound_trait(t), + bound_trait(@TraitRef), } #[deriving(Eq)] @@ -660,19 +668,6 @@ impl cmp::Eq for InferRegion { } } -impl to_bytes::IterBytes for param_bound { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - match *self { - bound_copy => 0u8.iter_bytes(lsb0, f), - bound_durable => 1u8.iter_bytes(lsb0, f), - bound_owned => 2u8.iter_bytes(lsb0, f), - bound_const => 3u8.iter_bytes(lsb0, f), - bound_trait(ref t) => - to_bytes::iter_bytes_2(&4u8, t, lsb0, f) - } - } -} - pub trait Vid { fn to_uint(&self) -> uint; } @@ -759,6 +754,13 @@ impl to_bytes::IterBytes for RegionVid { } } +/// Information about the type/lifetime parametesr associated with an item. +/// Analogous to ast::Generics. +pub struct Generics { + bounds: @~[param_bounds], + region_param: Option, +} + /// A polytype. /// /// - `bounds`: The list of bounds for each type parameter. The length of the @@ -770,11 +772,16 @@ impl to_bytes::IterBytes for RegionVid { /// - `ty`: the base type. May have reference to the (unsubstituted) bound /// region `&self` or to (unsubstituted) ty_param types pub struct ty_param_bounds_and_ty { - bounds: @~[param_bounds], - region_param: Option, + generics: Generics, ty: t } +/// As `ty_param_bounds_and_ty` but for a trait ref. +pub struct TraitDef { + generics: Generics, + trait_ref: @ty::TraitRef, +} + pub struct ty_param_substs_and_ty { substs: ty::substs, ty: ty::t @@ -829,6 +836,9 @@ pub fn mk_ctxt(s: session::Session, region_paramd_items: region_paramd_items, node_types: @mut SmallIntMap::new(), node_type_substs: @mut HashMap::new(), + trait_refs: @mut HashMap::new(), + trait_defs: @mut HashMap::new(), + intrinsic_traits: @mut HashMap::new(), items: amap, intrinsic_defs: @mut HashMap::new(), freevars: freevars, @@ -1412,7 +1422,7 @@ pub fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str { bound_durable => ~"'static", bound_owned => ~"owned", bound_const => ~"const", - bound_trait(t) => ::util::ppaux::ty_to_str(cx, t) + bound_trait(t) => ::util::ppaux::trait_ref_to_str(cx, t) } } @@ -1466,13 +1476,26 @@ pub fn subst(cx: ctxt, } } +pub fn subst_in_trait_ref(cx: ctxt, + substs: &substs, + trait_ref: &ty::TraitRef) -> ty::TraitRef +{ + ty::TraitRef { + def_id: trait_ref.def_id, + substs: subst_in_substs(cx, substs, &trait_ref.substs) + } +} + // Performs substitutions on a set of substitutions (result = sup(sub)) to // yield a new set of substitutions. This is used in trait inheritance. -pub fn subst_substs(cx: ctxt, sup: &substs, sub: &substs) -> substs { +pub fn subst_in_substs(cx: ctxt, + substs: &substs, + in_substs: &substs) -> substs +{ substs { - self_r: sup.self_r, - self_ty: sup.self_ty.map(|typ| subst(cx, sub, *typ)), - tps: sup.tps.map(|typ| subst(cx, sub, *typ)) + self_r: in_substs.self_r, + self_ty: in_substs.self_ty.map(|&typ| subst(cx, substs, typ)), + tps: in_substs.tps.map(|&typ| subst(cx, substs, typ)) } } @@ -1488,6 +1511,11 @@ pub fn type_is_error(ty: t) -> bool { (get(ty).flags & (has_ty_err as uint)) != 0 } +pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool { + tref.substs.self_ty.any(|&t| type_is_error(t)) || + tref.substs.tps.any(|&t| type_is_error(t)) +} + pub fn type_is_ty_var(ty: t) -> bool { match get(ty).sty { ty_infer(TyVar(_)) => true, @@ -1932,8 +1960,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { TC_OWNED_CLOSURE } - ty_trait(_, _, BoxTraitStore) | - ty_trait(_, _, BareTraitStore) => { + ty_trait(_, _, BoxTraitStore) => { TC_MANAGED } @@ -2592,17 +2619,6 @@ impl to_bytes::IterBytes for vstore { } } -impl to_bytes::IterBytes for TraitStore { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - match *self { - BareTraitStore => 0u8.iter_bytes(lsb0, f), - UniqTraitStore => 1u8.iter_bytes(lsb0, f), - BoxTraitStore => 2u8.iter_bytes(lsb0, f), - RegionTraitStore(ref r) => to_bytes::iter_bytes_2(&3u8, r, lsb0, f), - } - } -} - impl to_bytes::IterBytes for substs { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_3(&self.self_r, @@ -2715,6 +2731,16 @@ impl to_bytes::IterBytes for sty { } } +pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef { + match cx.trait_refs.find(&id) { + Some(&t) => t, + None => cx.sess.bug( + fmt!("node_id_to_trait_ref: no trait ref for node `%s`", + ast_map::node_id_to_str(cx.items, id, + cx.sess.parse_sess.interner))) + } +} + pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t { //io::println(fmt!("%?/%?", id, cx.node_types.len())); match cx.node_types.find(&(id as uint)) { @@ -3025,7 +3051,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, // n.b.: When we encode impl methods, the bounds // that we encode include both the impl bounds // and then the method bounds themselves... - ty::lookup_item_type(tcx, did).bounds + ty::lookup_item_type(tcx, did).generics.bounds } typeck::method_param(typeck::method_param { trait_id: trt_id, @@ -3036,10 +3062,9 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, // ...trait methods bounds, in contrast, include only the // method bounds, so we must preprend the tps from the // trait itself. This ought to be harmonized. - let trt_bounds = - ty::lookup_item_type(tcx, trt_id).bounds; + let trt_bounds = ty::lookup_trait_def(tcx, trt_id).generics.bounds; @(vec::append(/*bad*/copy *trt_bounds, - *ty::trait_method(tcx, trt_id, n_mth).tps)) + *ty::trait_method(tcx, trt_id, n_mth).generics.bounds)) } } } @@ -3488,6 +3513,11 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { ty_sort_str(cx, values.expected), ty_sort_str(cx, values.found)) } + terr_traits(values) => { + fmt!("expected trait %s but found trait %s", + item_path_str(cx, values.expected), + item_path_str(cx, values.found)) + } terr_self_substs => { ~"inconsistent self substitution" // XXX this is more of a bug } @@ -3565,11 +3595,11 @@ pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] { } pub fn trait_supertraits(cx: ctxt, - id: ast::def_id) - -> @~[InstantiatedTraitRef] { + id: ast::def_id) -> @~[@TraitRef] +{ // Check the cache. match cx.supertraits.find(&id) { - Some(&instantiated_trait_info) => { return instantiated_trait_info; } + Some(&trait_refs) => { return trait_refs; } None => {} // Continue. } @@ -3578,25 +3608,10 @@ pub fn trait_supertraits(cx: ctxt, assert!(!is_local(id)); // Get the supertraits out of the metadata and create the - // InstantiatedTraitRef for each. - let mut result = ~[]; - for csearch::get_supertraits(cx, id).each |trait_type| { - match get(*trait_type).sty { - ty_trait(def_id, ref substs, _) => { - result.push(InstantiatedTraitRef { - def_id: def_id, - tpt: ty_param_substs_and_ty { - substs: (/*bad*/copy *substs), - ty: *trait_type - } - }); - } - _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait") - } - } - - // Unwrap and return the result. - return @result; + // TraitRef for each. + let result = @csearch::get_supertraits(cx, id); + cx.supertraits.insert(id, result); + return result; } fn lookup_locally_or_in_crate_store( @@ -3659,23 +3674,7 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] { || @csearch::get_trait_method_def_ids(cx.cstore, id)) } -/* - Could this return a list of (def_id, substs) pairs? - */ -pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] { - fn storeify(cx: ctxt, ty: t, store: TraitStore) -> t { - match ty::get(ty).sty { - ty::ty_trait(did, ref substs, trait_store) => { - if store == trait_store { - ty - } else { - mk_trait(cx, did, (/*bad*/copy *substs), store) - } - } - _ => cx.sess.bug(~"impl_traits: not a trait") - } - } - +pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] { if id.crate == ast::local_crate { debug!("(impl_traits) searching for trait impl %?", id); match cx.items.find(&id.node) { @@ -3683,17 +3682,15 @@ pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] { node: ast::item_impl(_, opt_trait, _, _), _}, _)) => { - - do opt_trait.map_default(~[]) |trait_ref| { - ~[storeify(cx, node_id_to_type(cx, trait_ref.ref_id), - store)] + match opt_trait { + Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)], + None => ~[] } } _ => ~[] } } else { - vec::map(csearch::get_impl_traits(cx, id), - |x| storeify(cx, *x, store)) + csearch::get_impl_traits(cx, id) } } @@ -3967,6 +3964,23 @@ pub fn lookup_item_type(cx: ctxt, || csearch::get_type(cx, did)) } +/// Given the did of a trait, returns its canonical trait ref. +pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef { + match cx.trait_defs.find(&did) { + Some(&trait_def) => { + // The item is in this crate. The caller should have added it to the + // type cache already + return trait_def; + } + None => { + assert!(did.crate != ast::local_crate); + let trait_def = @csearch::get_trait_def(cx, did); + cx.trait_defs.insert(did, trait_def); + return trait_def; + } + } +} + // Look up a field ID, whether or not it's local // Takes a list of type substs in case the struct is generic pub fn lookup_field_type(tcx: ctxt, @@ -4250,9 +4264,6 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t { t }, - ty_trait(did, ref substs, BareTraitStore) => - mk_trait(cx, did, copy *substs, BoxTraitStore), - _ => t }; @@ -4318,12 +4329,11 @@ pub fn determine_inherited_purity(parent_purity: ast::purity, // list. pub fn iter_bound_traits_and_supertraits(tcx: ctxt, bounds: param_bounds, - f: &fn(t) -> bool) { + f: &fn(&TraitRef) -> bool) { let mut fin = false; for bounds.each |bound| { - - let bound_trait_ty = match *bound { + let bound_trait_ref = match *bound { ty::bound_trait(bound_t) => bound_t, ty::bound_copy | ty::bound_owned | @@ -4332,39 +4342,38 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt, } }; - let mut supertrait_map = HashMap::new(); + let mut supertrait_set = HashMap::new(); let mut seen_def_ids = ~[]; let mut i = 0; - let trait_ty_id = ty_to_def_id(bound_trait_ty).expect( - ~"iter_trait_ty_supertraits got a non-trait type"); - let mut trait_ty = bound_trait_ty; + let trait_ty_id = bound_trait_ref.def_id; + let mut trait_ref = bound_trait_ref; - debug!("iter_bound_traits_and_supertraits: trait_ty = %s", - ty_to_str(tcx, trait_ty)); + debug!("iter_bound_traits_and_supertraits: trait_ref = %s", + trait_ref_to_str(tcx, trait_ref)); // Add the given trait ty to the hash map - supertrait_map.insert(trait_ty_id, trait_ty); + supertrait_set.insert(trait_ty_id, ()); seen_def_ids.push(trait_ty_id); - if f(trait_ty) { + if f(trait_ref) { // Add all the supertraits to the hash map, // executing on each of them - while i < supertrait_map.len() && !fin { + while i < supertrait_set.len() && !fin { let init_trait_id = seen_def_ids[i]; i += 1; - // Add supertraits to supertrait_map - let supertraits = trait_supertraits(tcx, init_trait_id); - for supertraits.each |supertrait| { - let super_t = supertrait.tpt.ty; - let d_id = ty_to_def_id(super_t).expect("supertrait \ - should be a trait ty"); - if !supertrait_map.contains_key(&d_id) { - supertrait_map.insert(d_id, super_t); - trait_ty = super_t; + + // Add supertraits to supertrait_set + let supertrait_refs = trait_supertraits(tcx, init_trait_id); + for supertrait_refs.each |&supertrait_ref| { + let d_id = supertrait_ref.def_id; + if !supertrait_set.contains_key(&d_id) { + // NOTE Could have same trait multiple times + supertrait_set.insert(d_id, ()); + trait_ref = supertrait_ref; seen_def_ids.push(d_id); } - debug!("A super_t = %s", ty_to_str(tcx, trait_ty)); - if !f(trait_ty) { + debug!("A super_t = %s", trait_ref_to_str(tcx, trait_ref)); + if !f(trait_ref) { fin = true; } } @@ -4401,6 +4410,14 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id { } } +pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) { + let ty_visitor_name = special_idents::ty_visitor; + assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name)); + let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name); + (trait_ref, + mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore)) +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 05a5e926f279d..209091ecd6643 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -14,14 +14,14 @@ * is parameterized by an instance of `AstConv` and a `region_scope`. * * The parameterization of `ast_ty_to_ty()` is because it behaves - * somewhat differently during the collect and check phases, particularly - * with respect to looking up the types of top-level items. In the - * collect phase, the crate context is used as the `AstConv` instance; - * in this phase, the `get_item_ty()` function triggers a recursive call - * to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive - * types and report an error). In the check phase, when the @FnCtxt is - * used as the `AstConv`, `get_item_ty()` just looks up the item type in - * `tcx.tcache`. + * somewhat differently during the collect and check phases, + * particularly with respect to looking up the types of top-level + * items. In the collect phase, the crate context is used as the + * `AstConv` instance; in this phase, the `get_item_ty()` function + * triggers a recursive call to `ty_of_item()` (note that + * `ast_ty_to_ty()` will detect recursive types and report an error). + * In the check phase, when the @FnCtxt is used as the `AstConv`, + * `get_item_ty()` just looks up the item type in `tcx.tcache`. * * The `region_scope` trait controls how region references are * handled. It has two methods which are used to resolve anonymous @@ -76,6 +76,7 @@ use util::common::indenter; pub trait AstConv { fn tcx(&self) -> ty::ctxt; fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty; + fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef; // what type should we use when a type is omitted? fn ty_infer(&self, span: span) -> ty::t; @@ -129,62 +130,96 @@ pub fn ast_region_to_region( get_region_reporting_err(self.tcx(), span, opt_lifetime, res) } -pub fn ast_path_to_substs_and_ty( - self: &AC, - rscope: &RS, - did: ast::def_id, - path: @ast::path) - -> ty_param_substs_and_ty { - let tcx = self.tcx(); - let ty::ty_param_bounds_and_ty { - bounds: decl_bounds, - region_param: decl_rp, - ty: decl_ty - } = self.get_item_ty(did); +fn ast_path_substs( + self: &AC, + rscope: &RS, + def_id: ast::def_id, + decl_generics: &ty::Generics, + path: @ast::path) -> ty::substs +{ + /*! + * + * Given a path `path` that refers to an item `I` with the + * declared generics `decl_generics`, returns an appropriate + * set of substitutions for this particular reference to `I`. + */ - debug!("ast_path_to_substs_and_ty: did=%? decl_rp=%?", - did, decl_rp); + let tcx = self.tcx(); // If the type is parameterized by the self region, then replace self // region with the current anon region binding (in other words, // whatever & would get replaced with). - let self_r = match (decl_rp, path.rp) { - (None, None) => { + let self_r = match (&decl_generics.region_param, &path.rp) { + (&None, &None) => { None } - (None, Some(_)) => { + (&None, &Some(_)) => { tcx.sess.span_err( path.span, fmt!("no region bound is allowed on `%s`, \ which is not declared as containing region pointers", - ty::item_path_str(tcx, did))); + ty::item_path_str(tcx, def_id))); None } - (Some(_), None) => { + (&Some(_), &None) => { let res = rscope.anon_region(path.span); let r = get_region_reporting_err(self.tcx(), path.span, None, res); Some(r) } - (Some(_), Some(_)) => { + (&Some(_), &Some(_)) => { Some(ast_region_to_region(self, rscope, path.span, path.rp)) } }; // Convert the type parameters supplied by the user. - if !vec::same_length(*decl_bounds, path.types) { + if !vec::same_length(*decl_generics.bounds, path.types) { self.tcx().sess.span_fatal( path.span, fmt!("wrong number of type arguments: expected %u but found %u", - (*decl_bounds).len(), path.types.len())); + decl_generics.bounds.len(), path.types.len())); } let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t)); - let substs = substs {self_r:self_r, self_ty:None, tps:tps}; - let ty = ty::subst(tcx, &substs, decl_ty); + substs {self_r:self_r, self_ty:None, tps:tps} +} +pub fn ast_path_to_substs_and_ty( + self: &AC, + rscope: &RS, + did: ast::def_id, + path: @ast::path) -> ty_param_substs_and_ty +{ + let tcx = self.tcx(); + let ty::ty_param_bounds_and_ty { + generics: generics, + ty: decl_ty + } = self.get_item_ty(did); + + let substs = ast_path_substs(self, rscope, did, &generics, path); + let ty = ty::subst(tcx, &substs, decl_ty); ty_param_substs_and_ty { substs: substs, ty: ty } } +pub fn ast_path_to_trait_ref( + self: &AC, + rscope: &RS, + trait_def_id: ast::def_id, + path: @ast::path) -> @ty::TraitRef +{ + let trait_def = + self.get_trait_def(trait_def_id); + let substs = + ast_path_substs( + self, rscope, + trait_def.trait_ref.def_id, &trait_def.generics, + path); + let trait_ref = + @ty::TraitRef {def_id: trait_def_id, + substs: substs}; + return trait_ref; +} + + pub fn ast_path_to_ty( self: &AC, rscope: &RS, @@ -243,40 +278,29 @@ pub fn ast_ty_to_ty( check_path_args(tcx, path, NO_TPS | NO_REGIONS); return ty::mk_estr(tcx, vst); } - Some(&ast::def_trait(type_def_id)) => { - let result = ast_path_to_substs_and_ty( - self, rscope, - type_def_id, path); - match ty::get(result.ty).sty { - ty::ty_trait(trait_def_id, ref substs, _) => { - let trait_store = match vst { - ty::vstore_box => ty::BoxTraitStore, - ty::vstore_uniq => ty::UniqTraitStore, - ty::vstore_slice(r) => { - ty::RegionTraitStore(r) - } - ty::vstore_fixed(*) => { - tcx.sess.span_err( - path.span, - ~"@trait, ~trait or &trait \ - are the only supported \ - forms of casting-to-\ - trait"); - ty::BoxTraitStore - } - }; - return ty::mk_trait(tcx, - trait_def_id, - /*bad*/copy *substs, - trait_store); - + Some(&ast::def_trait(trait_def_id)) => { + let result = ast_path_to_trait_ref( + self, rscope, trait_def_id, path); + let trait_store = match vst { + ty::vstore_box => ty::BoxTraitStore, + ty::vstore_uniq => ty::UniqTraitStore, + ty::vstore_slice(r) => { + ty::RegionTraitStore(r) } - _ => { - tcx.sess.span_bug( - a_seq_ty.ty.span, - fmt!("def_trait but not ty_trait")); + ty::vstore_fixed(*) => { + tcx.sess.span_err( + path.span, + ~"@trait, ~trait or &trait \ + are the only supported \ + forms of casting-to-\ + trait"); + ty::BoxTraitStore } - } + }; + return ty::mk_trait(tcx, + result.def_id, + copy result.substs, + trait_store); } _ => {} } @@ -376,7 +400,16 @@ pub fn ast_ty_to_ty( Some(&d) => d }; match a_def { - ast::def_trait(did) | ast::def_ty(did) | ast::def_struct(did) => { + ast::def_trait(_) => { + let path_str = path_to_str(path, tcx.sess.intr()); + tcx.sess.span_err( + ast_ty.span, + fmt!("reference to trait `%s` where a type is expected; \ + try `@%s`, `~%s`, or `&%s`", + path_str, path_str, path_str, path_str)); + ty::mk_err(tcx) + } + ast::def_ty(did) | ast::def_struct(did) => { ast_path_to_ty(self, rscope, did, path).ty } ast::def_prim_ty(nty) => { diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index f2d0ef22970b4..605caba74a380 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -135,7 +135,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, ty::enum_variant_with_id(tcx, enm, var); let var_tpt = ty::lookup_item_type(tcx, var); vinfo.args.map(|t| { - if var_tpt.bounds.len() == expected_substs.tps.len() { + if var_tpt.generics.bounds.len() == expected_substs.tps.len() { ty::subst(tcx, expected_substs, *t) } else { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index e2d9a8a20c790..fa3cb43d9abe0 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -382,7 +382,7 @@ pub impl<'self> LookupContext<'self> { let bounds = tcx.ty_param_bounds.get(¶m_ty.def_id.node); for bounds.each |bound| { - let bound_trait_ty = match *bound { + let bound_trait_ref = match *bound { ty::bound_trait(bound_t) => bound_t, ty::bound_copy | ty::bound_owned | @@ -391,22 +391,10 @@ pub impl<'self> LookupContext<'self> { } }; - - let bound_substs = match ty::get(bound_trait_ty).sty { - ty::ty_trait(_, ref substs, _) => (/*bad*/copy *substs), - _ => { - self.bug(fmt!("add_candidates_from_param: \ - non-trait bound %s", - self.ty_to_str(bound_trait_ty))); - } - }; - - // Loop over the trait and all of its supertraits. let mut worklist = ~[]; - let init_trait_ty = bound_trait_ty; - let init_substs = bound_substs; + let init_trait_ref = bound_trait_ref; // Replace any appearance of `self` with the type of the // generic parameter itself. Note that this is the only @@ -417,29 +405,26 @@ pub impl<'self> LookupContext<'self> { // to self are not permitted). let init_substs = substs { self_ty: Some(rcvr_ty), - ..init_substs + ..copy bound_trait_ref.substs }; - worklist.push((init_trait_ty, init_substs)); + worklist.push((init_trait_ref.def_id, init_substs)); let mut i = 0; while i < worklist.len() { - let (init_trait_ty, init_substs) = /*bad*/copy worklist[i]; + let (init_trait_id, init_substs) = /*bad*/copy worklist[i]; i += 1; - let init_trait_id = ty::ty_to_def_id(init_trait_ty).get(); - // Add all the supertraits of this trait to the worklist. - let supertraits = ty::trait_supertraits(tcx, - init_trait_id); - for supertraits.each |supertrait| { + let supertraits = ty::trait_supertraits(tcx, init_trait_id); + for supertraits.each |supertrait_ref| { debug!("adding supertrait: %?", - supertrait.def_id); + supertrait_ref.def_id); - let new_substs = ty::subst_substs( + let new_substs = ty::subst_in_substs( tcx, - &supertrait.tpt.substs, - &init_substs); + &init_substs, + &supertrait_ref.substs); // Again replacing the self type let new_substs = substs { @@ -447,7 +432,7 @@ pub impl<'self> LookupContext<'self> { ..new_substs }; - worklist.push((supertrait.tpt.ty, new_substs)); + worklist.push((supertrait_ref.def_id, new_substs)); } @@ -1116,7 +1101,7 @@ pub impl<'self> LookupContext<'self> { // If they were not explicitly supplied, just construct fresh // type variables. let num_supplied_tps = self.supplied_tps.len(); - let num_method_tps = candidate.method_ty.tps.len(); + let num_method_tps = candidate.method_ty.generics.bounds.len(); let m_substs = { if num_supplied_tps == 0u { self.fcx.infcx().next_ty_vars(num_method_tps) @@ -1210,7 +1195,7 @@ pub impl<'self> LookupContext<'self> { self-type through a boxed trait"); } - if candidate.method_ty.tps.len() > 0 { + if candidate.method_ty.generics.bounds.len() > 0 { self.tcx().sess.span_err( self.expr.span, ~"cannot call a generic method through a boxed trait"); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 560fcb8c9209f..957259e7d172a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -610,7 +610,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { } else { for m.items.each |item| { let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id)); - if !tpt.bounds.is_empty() { + if !tpt.generics.bounds.is_empty() { ccx.tcx.sess.span_err( item.span, fmt!("foreign items may not have type parameters")); @@ -629,6 +629,10 @@ impl AstConv for FnCtxt { ty::lookup_item_type(self.tcx(), id) } + fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef { + ty::lookup_trait_def(self.tcx(), id) + } + fn ty_infer(&self, _span: span) -> ty::t { self.infcx().next_ty_var() } @@ -1064,7 +1068,7 @@ pub fn impl_self_ty(vcx: &VtableContext, let (n_tps, region_param, raw_ty) = { let ity = ty::lookup_item_type(tcx, did); - (vec::len(*ity.bounds), ity.region_param, ity.ty) + (ity.generics.bounds.len(), ity.generics.region_param, ity.ty) }; let self_r = if region_param.is_some() { @@ -1888,8 +1892,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } else { let item_type = ty::lookup_item_type(tcx, class_id); - type_parameter_count = (*item_type.bounds).len(); - region_parameterized = item_type.region_param; + type_parameter_count = item_type.generics.bounds.len(); + region_parameterized = item_type.generics.region_param; raw_type = item_type.ty; } @@ -1976,8 +1980,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } else { let item_type = ty::lookup_item_type(tcx, enum_id); - type_parameter_count = (*item_type.bounds).len(); - region_parameterized = item_type.region_param; + type_parameter_count = item_type.generics.bounds.len(); + region_parameterized = item_type.generics.region_param; raw_type = item_type.ty; } @@ -3147,8 +3151,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, ast::def_fn(_, ast::extern_fn) => { // extern functions are just u8 pointers return ty_param_bounds_and_ty { - bounds: @~[], - region_param: None, + generics: ty::Generics { + bounds: @~[], + region_param: None + }, ty: ty::mk_ptr( fcx.ccx.tcx, ty::mt { @@ -3211,7 +3217,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, region_lb: ty::Region) { debug!(">>> instantiate_path"); - let ty_param_count = vec::len(*tpt.bounds); + let ty_param_count = tpt.generics.bounds.len(); let ty_substs_len = vec::len(pth.types); debug!("ty_param_count=%? ty_substs_len=%?", @@ -3222,7 +3228,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, // (if any) and otherwise using a fresh region variable let self_r = match pth.rp { Some(_) => { // user supplied a lifetime parameter... - match tpt.region_param { + match tpt.generics.region_param { None => { // ...but the type is not lifetime parameterized! fcx.ccx.tcx.sess.span_err (span, ~"this item is not region-parameterized"); @@ -3235,7 +3241,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, } None => { // no lifetime parameter supplied, insert default fcx.region_var_if_parameterized( - tpt.region_param, span, region_lb) + tpt.generics.region_param, span, region_lb) } }; @@ -3433,28 +3439,13 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { } ~"visit_tydesc" => { let tydesc_name = special_idents::tydesc; - let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor"); assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); - assert!(ccx.tcx.intrinsic_defs.contains_key(&ty_visitor_name)); let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name); - let (_, visitor_trait) = *tcx.intrinsic_defs.get(&ty_visitor_name); - - let visitor_trait = match ty::get(visitor_trait).sty { - ty::ty_trait(trait_def_id, ref trait_substs, _) => { - ty::mk_trait(tcx, - trait_def_id, - copy *trait_substs, - ty::BoxTraitStore) - } - _ => { - tcx.sess.span_bug(it.span, ~"TyVisitor wasn't a trait?!") - } - }; - + let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty, mutbl: ast::m_imm}); (0u, ~[arg(ast::by_copy, td_ptr), - arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx)) + arg(ast::by_ref, visitor_object_ty)], ty::mk_nil(tcx)) } ~"frame_address" => { let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { @@ -3700,7 +3691,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { output: output} }); let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id)); - let i_n_tps = (*i_ty.bounds).len(); + let i_n_tps = i_ty.generics.bounds.len(); if i_n_tps != n_tps { tcx.sess.span_err(it.span, fmt!("intrinsic has wrong number \ of type parameters: found %u, \ diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 51f54d21ec4af..c30765baf37b3 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -70,7 +70,7 @@ pub impl VtableContext { fn tcx(&const self) -> ty::ctxt { self.ccx.tcx } } -pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool { +fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool { vec::any(tps, |bs| { bs.any(|b| { match b { &ty::bound_trait(_) => true, _ => false } @@ -78,11 +78,11 @@ pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool { }) } -pub fn lookup_vtables(vcx: &VtableContext, - location_info: &LocationInfo, - bounds: @~[ty::param_bounds], - substs: &ty::substs, - is_early: bool) -> vtable_res { +fn lookup_vtables(vcx: &VtableContext, + location_info: &LocationInfo, + bounds: @~[ty::param_bounds], + substs: &ty::substs, + is_early: bool) -> vtable_res { debug!("lookup_vtables(location_info=%?, # bounds=%?, \ substs=%s", @@ -95,30 +95,30 @@ pub fn lookup_vtables(vcx: &VtableContext, let mut result = ~[], i = 0u; for substs.tps.each |ty| { for ty::iter_bound_traits_and_supertraits( - tcx, bounds[i]) |trait_ty| + tcx, bounds[i]) |trait_ref| { debug!("about to subst: %?, %?", - ppaux::ty_to_str(tcx, trait_ty), + ppaux::trait_ref_to_str(tcx, trait_ref), ty::substs_to_str(tcx, substs)); let new_substs = substs { self_ty: Some(*ty), ../*bad*/copy *substs }; - let trait_ty = ty::subst(tcx, &new_substs, trait_ty); + let trait_ref = ty::subst_in_trait_ref(tcx, &new_substs, trait_ref); debug!("after subst: %?", - ppaux::ty_to_str(tcx, trait_ty)); + vcx.infcx.trait_ref_to_str(&trait_ref)); - match lookup_vtable(vcx, location_info, *ty, trait_ty, is_early) { + match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) { Some(vtable) => result.push(vtable), None => { vcx.tcx().sess.span_fatal( location_info.span, fmt!("failed to find an implementation of \ trait %s for %s", - ppaux::ty_to_str(vcx.tcx(), trait_ty), - ppaux::ty_to_str(vcx.tcx(), *ty))); + vcx.infcx.trait_ref_to_str(&trait_ref), + vcx.infcx.ty_to_str(*ty))); } } } @@ -136,9 +136,9 @@ pub fn lookup_vtables(vcx: &VtableContext, @result } -pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, - id: ast::def_id, +substs: ty::substs, - is_early: bool) -> Option { +fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, + id: ast::def_id, +substs: ty::substs, + is_early: bool) -> Option { let tcx = vcx.tcx(); // use a dummy type just to package up the substs that need fixing up let t = ty::mk_trait(tcx, @@ -152,31 +152,58 @@ pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, } } -pub fn relate_trait_tys(vcx: &VtableContext, location_info: &LocationInfo, - exp_trait_ty: ty::t, act_trait_ty: ty::t) { - demand_suptype(vcx, location_info.span, exp_trait_ty, act_trait_ty) +fn relate_trait_refs(vcx: &VtableContext, + location_info: &LocationInfo, + act_trait_ref: &ty::TraitRef, + exp_trait_ref: &ty::TraitRef) +{ + /*! + * + * Checks that an implementation of `act_trait_ref` is suitable + * for use where `exp_trait_ref` is required and reports an + * error otherwise. + */ + + match infer::mk_sub_trait_refs(vcx.infcx, false, location_info.span, + act_trait_ref, exp_trait_ref) + { + result::Ok(()) => {} // Ok. + result::Err(ref err) => { + let r_act_trait_ref = + vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(act_trait_ref); + let r_exp_trait_ref = + vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(exp_trait_ref); + if !ty::trait_ref_contains_error(&r_act_trait_ref) && + !ty::trait_ref_contains_error(&r_exp_trait_ref) + { + let tcx = vcx.tcx(); + tcx.sess.span_err( + location_info.span, + fmt!("expected %s, but found %s (%s)", + ppaux::trait_ref_to_str(tcx, &r_exp_trait_ref), + ppaux::trait_ref_to_str(tcx, &r_act_trait_ref), + ty::type_err_to_str(tcx, err))); + } + } + } } // Look up the vtable to use when treating an item of type `t` as if it has // type `trait_ty` -pub fn lookup_vtable(vcx: &VtableContext, - location_info: &LocationInfo, - ty: ty::t, - trait_ty: ty::t, - is_early: bool) - -> Option { - debug!("lookup_vtable(ty=%s, trait_ty=%s)", - vcx.infcx.ty_to_str(ty), vcx.infcx.ty_to_str(trait_ty)); +fn lookup_vtable(vcx: &VtableContext, + location_info: &LocationInfo, + ty: ty::t, + trait_ref: &ty::TraitRef, + is_early: bool) + -> Option +{ + debug!("lookup_vtable(ty=%s, trait_ref=%s)", + vcx.infcx.ty_to_str(ty), + vcx.infcx.trait_ref_to_str(trait_ref)); let _i = indenter(); let tcx = vcx.tcx(); - let (trait_id, trait_substs, trait_store) = match ty::get(trait_ty).sty { - ty::ty_trait(did, ref substs, store) => - (did, (/*bad*/copy *substs), store), - _ => tcx.sess.impossible_case(location_info.span, - "lookup_vtable: \ - don't know how to handle a non-trait") - }; + let ty = match fixup_ty(vcx, location_info, ty, is_early) { Some(ty) => ty, None => { @@ -194,37 +221,20 @@ pub fn lookup_vtable(vcx: &VtableContext, let mut n_bound = 0; let bounds = *tcx.ty_param_bounds.get(&did.node); for ty::iter_bound_traits_and_supertraits( - tcx, bounds) |ity| { + tcx, bounds) |bound_trait_ref| + { debug!("checking bounds trait %?", - vcx.infcx.ty_to_str(ity)); - - match ty::get(ity).sty { - ty::ty_trait(idid, ref isubsts, _) => { - if trait_id == idid { - debug!("(checking vtable) @0 \ - relating ty to trait \ - ty with did %?", - idid); - - // Convert `ity` so that it has the right vstore. - let ity = ty::mk_trait(vcx.tcx(), - idid, - copy *isubsts, - trait_store); - - relate_trait_tys(vcx, location_info, - trait_ty, ity); - let vtable = vtable_param(n, n_bound); - debug!("found param vtable: %?", - vtable); - return Some(vtable); - } - } - _ => tcx.sess.impossible_case( - location_info.span, - "lookup_vtable: in loop, \ - don't know how to handle a \ - non-trait ity") + vcx.infcx.trait_ref_to_str(bound_trait_ref)); + + if bound_trait_ref.def_id == trait_ref.def_id { + relate_trait_refs(vcx, + location_info, + bound_trait_ref, + trait_ref); + let vtable = vtable_param(n, n_bound); + debug!("found param vtable: %?", + vtable); + return Some(vtable); } n_bound += 1; @@ -236,18 +246,19 @@ pub fn lookup_vtable(vcx: &VtableContext, let mut impls_seen = HashSet::new(); - match vcx.ccx.coherence_info.extension_methods.find(&trait_id) { + match vcx.ccx.coherence_info.extension_methods.find(&trait_ref.def_id) { None => { // Nothing found. Continue. } Some(implementations) => { let implementations: &mut ~[@Impl] = *implementations; + // implementations is the list of all impls in scope for - // trait_ty. (Usually, there's just one.) + // trait_ref. (Usually, there's just one.) for uint::range(0, implementations.len()) |i| { let im = implementations[i]; - // im is one specific impl of trait_ty. + // im is one specific impl of trait_ref. // First, ensure we haven't processed this impl yet. if impls_seen.contains(&im.did) { @@ -269,22 +280,15 @@ pub fn lookup_vtable(vcx: &VtableContext, // ~[baz, bar, quux] // // For each of the traits foo implements, if - // it's the same trait as trait_ty, we need to - // unify it with trait_ty in order to get all + // it's the same trait as trait_ref, we need to + // unify it with trait_ref in order to get all // the ty vars sorted out. - for vec::each(ty::impl_traits(tcx, - im.did, - trait_store)) |of_ty| { - match ty::get(*of_ty).sty { - ty::ty_trait(id, _, _) => { - // Not the trait we're looking for - if id != trait_id { loop; } - } - _ => { /* ok */ } - } + for ty::impl_trait_refs(tcx, im.did).each |&of_trait_ref| + { + if of_trait_ref.def_id != trait_ref.def_id { loop; } - // At this point, we know that of_ty is - // the same trait as trait_ty, but + // At this point, we know that of_trait_ref is + // the same trait as trait_ref, but // possibly applied to different substs. // // Next, we check whether the "for" ty in @@ -318,39 +322,36 @@ pub fn lookup_vtable(vcx: &VtableContext, vcx.infcx.ty_to_str(for_ty), tys_to_str(vcx.tcx(), substs.tps)); - // Next, we unify trait_ty -- the type - // that we want to cast to -- with of_ty + // Next, we unify trait_ref -- the type + // that we want to cast to -- with of_trait_ref // -- the trait that im implements. At // this point, we require that they be // unifiable with each other -- that's - // what relate_trait_tys does. + // what relate_trait_refs does. // // For example, in the above example, - // of_ty would be some_trait, so we - // would be unifying trait_ty (for some + // of_trait_ref would be some_trait, so we + // would be unifying trait_ref (for some // value of U) with some_trait. This // would fail if T and U weren't // compatible. debug!("(checking vtable) @2 relating trait \ - ty %s to of_ty %s", - vcx.infcx.ty_to_str(trait_ty), - vcx.infcx.ty_to_str(*of_ty)); - let of_ty = ty::subst(tcx, &substs, *of_ty); - relate_trait_tys(vcx, location_info, trait_ty, - of_ty); - - // Recall that trait_ty -- the trait type - // we're casting to -- is the trait with - // id trait_id applied to the substs - // trait_substs. Now we extract out the - // types themselves from trait_substs. + ty %s to of_trait_ref %s", + vcx.infcx.trait_ref_to_str(trait_ref), + vcx.infcx.trait_ref_to_str(of_trait_ref)); - let trait_tps = /*bad*/copy trait_substs.tps; + let of_trait_ref = + ty::subst_in_trait_ref(tcx, &substs, of_trait_ref); + relate_trait_refs( + vcx, location_info, + &of_trait_ref, trait_ref); - debug!("Casting to a trait ty whose substs \ - (trait_tps) are %s", - tys_to_str(vcx.tcx(), trait_tps)); + // Recall that trait_ref -- the trait type + // we're casting to -- is the trait with + // id trait_ref.def_id applied to the substs + // trait_ref.substs. Now we extract out the + // types themselves from trait_ref.substs. // Recall that substs is the impl self // type's list of substitutions. That is, @@ -362,7 +363,7 @@ pub fn lookup_vtable(vcx: &VtableContext, let substs_f = match fixup_substs(vcx, location_info, - trait_id, + trait_ref.def_id, substs, is_early) { Some(ref substs) => (/*bad*/copy *substs), @@ -377,7 +378,7 @@ pub fn lookup_vtable(vcx: &VtableContext, they will be unified with the bounds for \ the target ty, %s", tys_to_str(vcx.tcx(), substs_f.tps), - tys_to_str(vcx.tcx(), trait_tps)); + vcx.infcx.trait_ref_to_str(trait_ref)); // Next, we unify the fixed-up // substitutions for the impl self ty with @@ -386,14 +387,13 @@ pub fn lookup_vtable(vcx: &VtableContext, // to. connect_trait_tps requires these // lists of types to unify pairwise. - let im_bs = ty::lookup_item_type(tcx, - im.did).bounds; + let im_bs = + ty::lookup_item_type(tcx, im.did).generics.bounds; connect_trait_tps(vcx, location_info, - /*bad*/copy substs_f.tps, - trait_tps, - im.did, - trait_store); + &substs_f, + trait_ref, + im.did); let subres = lookup_vtables( vcx, location_info, im_bs, &substs_f, is_early); @@ -430,10 +430,10 @@ pub fn lookup_vtable(vcx: &VtableContext, return None; } -pub fn fixup_ty(vcx: &VtableContext, - location_info: &LocationInfo, - ty: ty::t, - is_early: bool) -> Option { +fn fixup_ty(vcx: &VtableContext, + location_info: &LocationInfo, + ty: ty::t, + is_early: bool) -> Option { let tcx = vcx.tcx(); match resolve_type(vcx.infcx, ty, resolve_and_force_all_but_regions) { Ok(new_type) => Some(new_type), @@ -450,45 +450,23 @@ pub fn fixup_ty(vcx: &VtableContext, } } -// Version of demand::suptype() that takes a vtable context instead of a -// function context. -pub fn demand_suptype(vcx: &VtableContext, sp: span, e: ty::t, a: ty::t) { - // NB: Order of actual, expected is reversed. - match infer::mk_subty(vcx.infcx, false, sp, a, e) { - result::Ok(()) => {} // Ok. - result::Err(ref err) => { - vcx.infcx.report_mismatched_types(sp, e, a, err); - } - } -} - -pub fn connect_trait_tps(vcx: &VtableContext, - location_info: &LocationInfo, - impl_tys: ~[ty::t], - trait_tys: ~[ty::t], - impl_did: ast::def_id, - store: ty::TraitStore) { +fn connect_trait_tps(vcx: &VtableContext, + location_info: &LocationInfo, + impl_substs: &ty::substs, + trait_ref: &ty::TraitRef, + impl_did: ast::def_id) +{ let tcx = vcx.tcx(); // XXX: This should work for multiple traits. - let ity = ty::impl_traits(tcx, impl_did, store)[0]; - let trait_ty = ty::subst_tps(tcx, impl_tys, None, ity); - debug!("(connect trait tps) trait type is %?, impl did is %?", - ty::get(trait_ty).sty, impl_did); - match ty::get(trait_ty).sty { - ty::ty_trait(_, ref substs, _) => { - for vec::each2((*substs).tps, trait_tys) |a, b| { - demand_suptype(vcx, location_info.span, *a, *b); - } - } - _ => tcx.sess.impossible_case(location_info.span, "connect_trait_tps: \ - don't know how to handle a non-trait ty") - } + let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0]; + let impl_trait_ref = ty::subst_in_trait_ref(tcx, impl_substs, impl_trait_ref); + relate_trait_refs(vcx, location_info, trait_ref, &impl_trait_ref); } -pub fn insert_vtables(fcx: @mut FnCtxt, - callee_id: ast::node_id, - vtables: vtable_res) { +fn insert_vtables(fcx: @mut FnCtxt, + callee_id: ast::node_id, + vtables: vtable_res) { debug!("insert_vtables(callee_id=%d, vtables=%?)", callee_id, vtables.map(|v| v.to_str(fcx.tcx()))); fcx.inh.vtable_map.insert(callee_id, vtables); @@ -517,15 +495,15 @@ pub fn early_resolve_expr(ex: @ast::expr, let item_ty = ty::lookup_item_type(cx.tcx, did); debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def, fcx.infcx().ty_to_str(item_ty.ty)); - if has_trait_bounds(/*bad*/copy *item_ty.bounds) { - for item_ty.bounds.each |bounds| { + if has_trait_bounds(/*bad*/copy *item_ty.generics.bounds) { + for item_ty.generics.bounds.each |bounds| { debug!("early_resolve_expr: looking up vtables for bound \ %s", ty::param_bounds_to_str(fcx.tcx(), *bounds)); } let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), - item_ty.bounds, substs, is_early); + item_ty.generics.bounds, substs, is_early); if !is_early { insert_vtables(fcx, ex.id, vtbls); } @@ -564,7 +542,7 @@ pub fn early_resolve_expr(ex: @ast::expr, ast::expr_cast(src, _) => { let target_ty = fcx.expr_ty(ex); match ty::get(target_ty).sty { - ty::ty_trait(_, _, store) => { + ty::ty_trait(target_def_id, ref target_substs, store) => { // Look up vtables for the type we're casting to, // passing in the source and target type. The source // must be a pointer type suitable to the object sigil, @@ -573,7 +551,6 @@ pub fn early_resolve_expr(ex: @ast::expr, fcx.expr_ty(src)); match (&ty::get(ty).sty, store) { (&ty::ty_box(mt), ty::BoxTraitStore) | - // XXX: Bare trait store is deprecated. (&ty::ty_uniq(mt), ty::UniqTraitStore) | (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => { let location_info = @@ -582,11 +559,15 @@ pub fn early_resolve_expr(ex: @ast::expr, ccx: fcx.ccx, infcx: fcx.infcx() }; + let target_trait_ref = ty::TraitRef { + def_id: target_def_id, + substs: copy *target_substs + }; let vtable_opt = lookup_vtable(&vcx, location_info, mt.ty, - target_ty, + &target_trait_ref, is_early); match vtable_opt { Some(vtable) => { @@ -622,11 +603,12 @@ pub fn early_resolve_expr(ex: @ast::expr, } } - (_, ty::BareTraitStore) => { + (_, ty::UniqTraitStore) => { fcx.ccx.tcx.sess.span_err( ex.span, - ~"a sigil (`@`, `~`, or `&`) must be specified \ - when casting to a trait"); + fmt!("can only cast an ~-pointer \ + to a ~-object, not a %s", + ty::ty_sort_str(fcx.tcx(), ty))); } (_, ty::BoxTraitStore) => { @@ -637,14 +619,6 @@ pub fn early_resolve_expr(ex: @ast::expr, ty::ty_sort_str(fcx.tcx(), ty))); } - (_, ty::UniqTraitStore) => { - fcx.ccx.tcx.sess.span_err( - ex.span, - fmt!("can only cast an ~-pointer \ - to a ~-object, not a %s", - ty::ty_sort_str(fcx.tcx(), ty))); - } - (_, ty::RegionTraitStore(_)) => { fcx.ccx.tcx.sess.span_err( ex.span, @@ -661,9 +635,9 @@ pub fn early_resolve_expr(ex: @ast::expr, } } -pub fn resolve_expr(ex: @ast::expr, - &&fcx: @mut FnCtxt, - v: visit::vt<@mut FnCtxt>) { +fn resolve_expr(ex: @ast::expr, + &&fcx: @mut FnCtxt, + v: visit::vt<@mut FnCtxt>) { early_resolve_expr(ex, fcx, false); visit::visit_expr(ex, fcx, v); } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 22b6926e9f0c5..f6042cf2e0cca 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -358,7 +358,7 @@ pub impl CoherenceChecker { @ProvidedMethodInfo { method_info: @MethodInfo { did: new_did, - n_tps: trait_method.tps.len(), + n_tps: trait_method.generics.bounds.len(), ident: trait_method.ident, self_type: trait_method.self_ty }, @@ -542,10 +542,10 @@ pub impl CoherenceChecker { -> UniversalQuantificationResult { // NDM--this span is bogus. let self_region = - polytype.region_param.map( + polytype.generics.region_param.map( |_r| self.inference_context.next_region_var_nb(dummy_sp())); - let bounds_count = polytype.bounds.len(); + let bounds_count = polytype.generics.bounds.len(); let type_parameters = self.inference_context.next_ty_vars(bounds_count); @@ -565,7 +565,7 @@ pub impl CoherenceChecker { UniversalQuantificationResult { monotype: monotype, type_variables: type_parameters, - bounds: polytype.bounds + bounds: polytype.generics.bounds } } @@ -864,17 +864,8 @@ pub impl CoherenceChecker { } // Record all the trait methods. - for associated_traits.each |trait_type| { - match get(*trait_type).sty { - ty_trait(trait_id, _, _) => { - self.add_trait_method(trait_id, *implementation); - } - _ => { - self.crate_context.tcx.sess.bug(~"trait type \ - returned is not a \ - trait"); - } - } + for associated_traits.each |trait_ref| { + self.add_trait_method(trait_ref.def_id, *implementation); } // Add the implementation to the mapping from @@ -923,7 +914,7 @@ pub impl CoherenceChecker { @ProvidedMethodInfo { method_info: @MethodInfo { did: new_did, - n_tps: trait_method_info.ty.tps.len(), + n_tps: trait_method_info.ty.generics.bounds.len(), ident: trait_method_info.ty.ident, self_type: trait_method_info.ty.self_ty }, @@ -954,15 +945,7 @@ pub impl CoherenceChecker { def_id); } dl_def(def_trait(def_id)) => { - let tcx = self.crate_context.tcx; - let polytype = csearch::get_type(tcx, def_id); - match ty::get(polytype.ty).sty { - ty::ty_trait(*) => { - self.add_default_methods_for_external_trait( - def_id); - } - _ => {} - } + self.add_default_methods_for_external_trait(def_id); } dl_def(_) | dl_impl(_) | dl_field => { // Skip this. diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 81acae1d3a99b..a2245dc82cf80 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -33,7 +33,6 @@ are represented as `ty_param()` instances. use core::prelude::*; use metadata::csearch; -use middle::ty::InstantiatedTraitRef; use middle::ty::{substs, ty_param_bounds_and_ty, ty_param_substs_and_ty}; use middle::ty; use middle::typeck::astconv::{AstConv, ty_of_arg}; @@ -83,12 +82,10 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) { match intrinsic_item.node { ast::item_trait(*) => { - let ty = ty::mk_trait(ccx.tcx, - def_id, - substs, - ty::BareTraitStore); - ccx.tcx.intrinsic_defs.insert - (intrinsic_item.ident, (def_id, ty)); + let tref = @ty::TraitRef {def_id: def_id, + substs: substs}; + ccx.tcx.intrinsic_traits.insert + (intrinsic_item.ident, tref); } ast::item_enum(*) => { @@ -152,6 +149,10 @@ impl AstConv for CrateCtxt { } } + fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef { + get_trait_def(self, id) + } + fn ty_infer(&self, span: span) -> ty::t { self.tcx.sess.span_bug(span, ~"found `ty_infer` in unexpected place"); @@ -186,8 +187,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, ast::struct_variant_kind(struct_def) => { let tpt = ty_param_bounds_and_ty { - bounds: ty_param_bounds(ccx, generics), - region_param: rp, + generics: ty_generics(ccx, rp, generics), ty: enum_ty }; @@ -208,8 +208,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, None => {} Some(result_ty) => { let tpt = ty_param_bounds_and_ty { - bounds: ty_param_bounds(ccx, generics), - region_param: rp, + generics: ty_generics(ccx, rp, generics), ty: result_ty }; tcx.tcache.insert(local_def(variant.node.id), tpt); @@ -220,8 +219,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, } pub fn ensure_trait_methods(ccx: &CrateCtxt, - trait_id: ast::node_id, - trait_ty: ty::t) + trait_id: ast::node_id) { let tcx = ccx.tcx; let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x); @@ -230,7 +228,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, node: ast::item_trait(ref generics, _, ref ms), _ }, _) => { - let trait_bounds = ty_param_bounds(ccx, generics); + let trait_ty_generics = ty_generics(ccx, region_paramd, generics); // For each method, construct a suitable ty::method and // store it into the `tcx.methods` table: @@ -252,9 +250,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, }; if ty_method.self_ty == ast::sty_static { - make_static_method_ty(ccx, region_paramd, - ty_method, trait_ty, - trait_bounds); + make_static_method_ty(ccx, trait_id, ty_method, + &trait_ty_generics); } tcx.methods.insert(ty_method.def_id, ty_method); @@ -275,12 +272,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, } fn make_static_method_ty(ccx: &CrateCtxt, - rp: Option, + trait_id: ast::node_id, m: &ty::method, - // Take this as an argument b/c we may check - // the impl before the trait. - trait_ty: ty::t, - trait_bounds: @~[ty::param_bounds]) { + trait_ty_generics: &ty::Generics) { // We need to create a typaram that replaces self. This param goes // *in between* the typarams from the trait and those from the // method (since its bound can depend on the trait? or @@ -291,12 +285,13 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, let dummy_defid = ast::def_id {crate: 0, node: 0}; - let non_shifted_trait_tps = do vec::from_fn(trait_bounds.len()) |i| { + let num_trait_bounds = trait_ty_generics.bounds.len(); + let non_shifted_trait_tps = do vec::from_fn(num_trait_bounds) |i| { ty::mk_param(ccx.tcx, i, dummy_defid) }; - let self_param = ty::mk_param(ccx.tcx, trait_bounds.len(), + let self_param = ty::mk_param(ccx.tcx, num_trait_bounds, dummy_defid); - let shifted_method_tps = do vec::from_fn(m.tps.len()) |i| { + let shifted_method_tps = do vec::from_fn(m.generics.bounds.len()) |i| { ty::mk_param(ccx.tcx, i + 1, dummy_defid) }; @@ -308,13 +303,20 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, let ty = ty::subst(ccx.tcx, &substs, ty::mk_bare_fn(ccx.tcx, copy m.fty)); - let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] - + *m.tps); + let trait_def = get_trait_def(ccx, local_def(trait_id)); + let trait_ref = trait_def.trait_ref; + let mut new_bounds = ~[]; + new_bounds.push_all(*trait_ty_generics.bounds); + new_bounds.push(@~[ty::bound_trait(trait_ref)]); + new_bounds.push_all(*m.generics.bounds); ccx.tcx.tcache.insert(m.def_id, ty_param_bounds_and_ty { - bounds: bounds, - region_param: rp, - ty: ty}); + generics: ty::Generics { + bounds: @new_bounds, + region_param: trait_ty_generics.region_param + }, + ty: ty + }); } fn ty_method_of_trait_method(self: &CrateCtxt, @@ -335,7 +337,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_self_ty, *m_self_ty, m_decl); ty::method { ident: *m_ident, - tps: ty_param_bounds(self, m_generics), + generics: ty_generics(self, None, m_generics), transformed_self_ty: transformed_self_ty, fty: fty, self_ty: m_self_ty.node, @@ -350,25 +352,28 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, id: ast::node_id, sp: codemap::span, rp: Option, - trait_refs: &[@ast::trait_ref], - generics: &ast::Generics) { + ast_trait_refs: &[@ast::trait_ref], + generics: &ast::Generics) +{ let tcx = ccx.tcx; if tcx.supertraits.contains_key(&local_def(id)) { return; } - let mut instantiated = ~[]; - for trait_refs.each |trait_ref| { - let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp, generics); - if instantiated.any(|other_trait: &InstantiatedTraitRef| - { other_trait.def_id == did }) { + let mut ty_trait_refs: ~[@ty::TraitRef] = ~[]; + for ast_trait_refs.each |&ast_trait_ref| { + let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics); + + // NOTE Could have same trait multiple times + if ty_trait_refs.any(|other_trait| other_trait.def_id == trait_ref.def_id) { // This means a trait inherited from the same supertrait more // than once. tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \ declaration"); - return; + break; + } else { + ty_trait_refs.push(trait_ref); } - instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt }); } - tcx.supertraits.insert(local_def(id), @instantiated); + tcx.supertraits.insert(local_def(id), @ty_trait_refs); } /** @@ -422,15 +427,15 @@ pub fn compare_impl_method(tcx: ty::ctxt, } } - if impl_m.tps.len() != trait_m.tps.len() { + if impl_m.generics.bounds.len() != trait_m.generics.bounds.len() { tcx.sess.span_err( cm.span, fmt!("method `%s` has %u type %s, but its trait \ declaration has %u type %s", - *tcx.sess.str_of(trait_m.ident), impl_m.tps.len(), - pluralize(impl_m.tps.len(), ~"parameter"), - trait_m.tps.len(), - pluralize(trait_m.tps.len(), ~"parameter"))); + *tcx.sess.str_of(trait_m.ident), impl_m.generics.bounds.len(), + pluralize(impl_m.generics.bounds.len(), ~"parameter"), + trait_m.generics.bounds.len(), + pluralize(trait_m.generics.bounds.len(), ~"parameter"))); return; } @@ -448,9 +453,9 @@ pub fn compare_impl_method(tcx: ty::ctxt, // FIXME(#2687)---we should be checking that the bounds of the // trait imply the bounds of the subtype, but it appears // we are...not checking this. - for trait_m.tps.eachi() |i, trait_param_bounds| { + for trait_m.generics.bounds.eachi() |i, trait_param_bounds| { // For each of the corresponding impl ty param's bounds... - let impl_param_bounds = impl_m.tps[i]; + let impl_param_bounds = impl_m.generics.bounds[i]; // Make sure the bounds lists have the same length // Would be nice to use the ty param names in the error message, // but we don't have easy access to them here @@ -490,7 +495,7 @@ pub fn compare_impl_method(tcx: ty::ctxt, }; debug!("impl_fty: %s", ppaux::ty_to_str(tcx, impl_fty)); let trait_fty = { - let dummy_tps = do vec::from_fn((*trait_m.tps).len()) |i| { + let dummy_tps = do vec::from_fn(trait_m.generics.bounds.len()) |i| { // hack: we don't know the def id of the impl tp, but it // is not important for unification ty::mk_param(tcx, i + impl_tps, ast::def_id {crate: 0, node: 0}) @@ -538,37 +543,23 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, impl_ms: &[ConvertedMethod]) { let tcx = ccx.tcx; - let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics); - - if did.crate == ast::local_crate { - // NB: This is subtle. We need to do this on the type of the trait - // item *itself*, not on the type that includes the parameter - // substitutions provided by the programmer at this particular - // trait ref. Otherwise, we will potentially overwrite the types of - // the methods within the trait with bogus results. (See issue #3903.) - - match tcx.items.find(&did.node) { - Some(&ast_map::node_item(item, _)) => { - let tpt = ty_of_item(ccx, item); - ensure_trait_methods(ccx, did.node, tpt.ty); - } - _ => { - tcx.sess.bug(~"trait ref didn't resolve to trait"); - } - } + let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp, generics); + + if trait_ref.def_id.crate == ast::local_crate { + ensure_trait_methods(ccx, trait_ref.def_id.node); } // 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); + let trait_ms = ty::trait_methods(tcx, trait_ref.def_id); for impl_ms.each |impl_m| { match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) { Some(trait_m) => { let num_impl_tps = generics.ty_params.len(); compare_impl_method( ccx.tcx, num_impl_tps, impl_m, trait_m, - &tpt.substs, selfty); + &trait_ref.substs, selfty); } None => { // This method is not part of the trait @@ -594,8 +585,10 @@ pub fn convert_field(ccx: &CrateCtxt, /* add the field to the tcache */ ccx.tcx.tcache.insert(local_def(v.node.id), ty::ty_param_bounds_and_ty { - bounds: bounds, - region_param: rp, + generics: ty::Generics { + bounds: bounds, + region_param: rp + }, ty: tt }); } @@ -609,28 +602,34 @@ pub struct ConvertedMethod { pub fn convert_methods(ccx: &CrateCtxt, ms: &[@ast::method], - rp: Option, untransformed_rcvr_ty: ty::t, - rcvr_bounds: @~[ty::param_bounds], - rcvr_generics: &ast::Generics, + rcvr_ty_generics: &ty::Generics, + rcvr_ast_generics: &ast::Generics, rcvr_visibility: ast::visibility) -> ~[ConvertedMethod] { let tcx = ccx.tcx; return vec::map(ms, |m| { - let bounds = ty_param_bounds(ccx, &m.generics); - let mty = @ty_of_method( - ccx, *m, rp, untransformed_rcvr_ty, - rcvr_generics, rcvr_visibility, &m.generics); - let fty = ty::mk_bare_fn(tcx, copy mty.fty); + let m_ty_generics = + ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics); + let mty = + @ty_of_method(ccx, *m, rcvr_ty_generics.region_param, + untransformed_rcvr_ty, + rcvr_ast_generics, rcvr_visibility, + &m.generics); + let fty = + ty::mk_bare_fn(tcx, copy mty.fty); tcx.tcache.insert( local_def(m.id), // n.b.: the type of a method is parameterized by both // the tps on the receiver and those on the method itself ty_param_bounds_and_ty { - bounds: @(vec::append(/*bad*/copy *rcvr_bounds, *bounds)), - region_param: rp, + generics: ty::Generics { + bounds: @(vec::append(copy *rcvr_ty_generics.bounds, + *m_ty_generics.bounds)), + region_param: rcvr_ty_generics.region_param + }, ty: fty }); write_ty_to_tcx(tcx, m.id, fty); @@ -657,7 +656,7 @@ pub fn convert_methods(ccx: &CrateCtxt, m.self_ty, &m.decl); ty::method { ident: m.ident, - tps: ty_param_bounds(ccx, &m.generics), + generics: ty_generics(ccx, None, &m.generics), transformed_self_ty: transformed_self_ty, fty: fty, self_ty: m.self_ty.node, @@ -700,16 +699,15 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { rp); } ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => { - let i_bounds = ty_param_bounds(ccx, generics); + let i_ty_generics = ty_generics(ccx, rp, generics); let region_parameterization = RegionParameterization::from_variance_and_generics(rp, generics); let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty); write_ty_to_tcx(tcx, it.id, selfty); tcx.tcache.insert(local_def(it.id), ty_param_bounds_and_ty { - bounds: i_bounds, - region_param: rp, - ty: selfty}); + generics: i_ty_generics, + ty: selfty}); // If there is a trait reference, treat the methods as always public. // This is to work around some incorrect behavior in privacy checking: @@ -722,27 +720,27 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { it.vis }; - let cms = convert_methods(ccx, *ms, rp, selfty, i_bounds, generics, + let cms = convert_methods(ccx, *ms, selfty, + &i_ty_generics, generics, parent_visibility); for opt_trait_ref.each |t| { check_methods_against_trait(ccx, generics, rp, selfty, *t, cms); } } ast::item_trait(ref generics, ref supertraits, ref trait_methods) => { - let tpt = ty_of_item(ccx, it); - debug!("item_trait(it.id=%d, tpt.ty=%s)", - it.id, ppaux::ty_to_str(tcx, tpt.ty)); - write_ty_to_tcx(tcx, it.id, tpt.ty); - ensure_trait_methods(ccx, it.id, tpt.ty); - ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics); - - let (_, provided_methods) = - split_trait_methods(*trait_methods); - let (bounds, _) = mk_substs(ccx, generics, rp); - let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); - let _ = convert_methods(ccx, provided_methods, rp, - untransformed_rcvr_ty, bounds, generics, - it.vis); + let trait_def = trait_def_of_item(ccx, it); + tcx.trait_defs.insert(local_def(it.id), trait_def); + ensure_trait_methods(ccx, it.id); + ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics); + + let (_, provided_methods) = + split_trait_methods(*trait_methods); + let (ty_generics, _) = mk_substs(ccx, generics, rp); + let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); + let _ = convert_methods(ccx, provided_methods, + untransformed_rcvr_ty, + &ty_generics, generics, + it.vis); } ast::item_struct(struct_def, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "structure"); @@ -794,14 +792,16 @@ pub fn convert_struct(ccx: &CrateCtxt, write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), ty_param_bounds_and_ty { - bounds: tpt.bounds, - region_param: rp, - ty: t_dtor}); + generics: ty::Generics { + bounds: tpt.generics.bounds, + region_param: rp + }, + ty: t_dtor}); }; // Write the type of each of the members for struct_def.fields.each |f| { - convert_field(ccx, rp, tpt.bounds, *f, generics); + convert_field(ccx, rp, tpt.generics.bounds, *f, generics); } let (_, substs) = mk_substs(ccx, generics, rp); let selfty = ty::mk_struct(tcx, local_def(id), substs); @@ -824,8 +824,7 @@ pub fn convert_struct(ccx: &CrateCtxt, let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty { - bounds: tpt.bounds, - region_param: tpt.region_param, + generics: tpt.generics, ty: ctor_fn_ty }); } @@ -842,38 +841,75 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) { ccx.tcx.tcache.insert(local_def(i.id), tpt); } -/* - Instantiates the path for the given trait reference, assuming that - it's bound to a valid trait type. Returns the def_id for the defining - trait. Fails if the type is a type other than an trait type. - */ pub fn instantiate_trait_ref(ccx: &CrateCtxt, - t: @ast::trait_ref, + ast_trait_ref: @ast::trait_ref, rp: Option, - generics: &ast::Generics) - -> (ast::def_id, ty_param_substs_and_ty) { - - let sp = t.path.span, err = ~"can only implement trait types", - sess = ccx.tcx.sess; + generics: &ast::Generics) -> @ty::TraitRef +{ + /*! + * Instantiates the path for the given trait reference, assuming that + * it's bound to a valid trait type. Returns the def_id for the defining + * trait. Fails if the type is a type other than an trait type. + */ let rp = RegionParameterization::from_variance_and_generics(rp, generics); let rscope = type_rscope(rp); - match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) { - ast::def_trait(t_id) => { - let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path); + match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) { + ast::def_trait(trait_did) => { + let trait_ref = + astconv::ast_path_to_trait_ref( + ccx, &rscope, trait_did, ast_trait_ref.path); + ccx.tcx.trait_refs.insert( + ast_trait_ref.ref_id, trait_ref); + return trait_ref; + } + _ => { + ccx.tcx.sess.span_fatal( + ast_trait_ref.path.span, + fmt!("%s is not a trait", + path_to_str(ast_trait_ref.path, + ccx.tcx.sess.intr()))); + } + } +} - write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt); +fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::def_id) -> @ty::TraitDef { + if trait_id.crate != ast::local_crate { + ty::lookup_trait_def(ccx.tcx, trait_id) + } else { + match ccx.tcx.items.get(&trait_id.node) { + &ast_map::node_item(item, _) => trait_def_of_item(ccx, item), + _ => ccx.tcx.sess.bug(fmt!("get_trait_def(%d): not an item", + trait_id.node)) + } + } +} - match ty::get(tpt.ty).sty { - ty::ty_trait(*) => { - (t_id, tpt) - } - _ => sess.span_fatal(sp, err), +pub fn trait_def_of_item(ccx: &CrateCtxt, it: @ast::item) -> @ty::TraitDef { + let def_id = local_def(it.id); + let tcx = ccx.tcx; + match tcx.trait_defs.find(&def_id) { + Some(&def) => return def, + _ => {} + } + let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x); + match it.node { + ast::item_trait(ref generics, _, _) => { + let (ty_generics, substs) = mk_substs(ccx, generics, rp); + let trait_ref = @ty::TraitRef {def_id: def_id, + substs: substs}; + let trait_def = @ty::TraitDef {generics: ty_generics, + trait_ref: trait_ref}; + tcx.trait_defs.insert(def_id, trait_def); + return trait_def; + } + ref s => { + tcx.sess.span_bug( + it.span, + fmt!("trait_def_of_item invoked on %?", s)); } - } - _ => sess.span_fatal(sp, err) } } @@ -894,7 +930,8 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) return tpt; } ast::item_fn(ref decl, purity, _, ref generics, _) => { - let bounds = ty_param_bounds(ccx, generics); + assert!(rp.is_none()); + let ty_generics = ty_generics(ccx, None, generics); let tofd = astconv::ty_of_bare_fn(ccx, &empty_rscope, purity, @@ -902,8 +939,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) &generics.lifetimes, decl); let tpt = ty_param_bounds_and_ty { - bounds: bounds, - region_param: None, + generics: ty::Generics { + bounds: ty_generics.bounds, + region_param: None + }, ty: ty::mk_bare_fn(ccx.tcx, tofd) }; debug!("type of %s (id %d) is %s", @@ -934,8 +973,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } }; ty_param_bounds_and_ty { - bounds: ty_param_bounds(ccx, generics), - region_param: rp, + generics: ty_generics(ccx, rp, generics), ty: ty } }; @@ -945,37 +983,26 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } ast::item_enum(_, ref generics) => { // Create a new generic polytype. - let (bounds, substs) = mk_substs(ccx, generics, rp); + let (ty_generics, substs) = mk_substs(ccx, generics, rp); let t = ty::mk_enum(tcx, local_def(it.id), substs); let tpt = ty_param_bounds_and_ty { - bounds: bounds, - region_param: rp, + generics: ty_generics, ty: t }; tcx.tcache.insert(local_def(it.id), tpt); return tpt; } - ast::item_trait(ref generics, _, _) => { - let (bounds, substs) = mk_substs(ccx, generics, rp); - let t = ty::mk_trait(tcx, - local_def(it.id), - substs, - ty::BareTraitStore); - let tpt = ty_param_bounds_and_ty { - bounds: bounds, - region_param: rp, - ty: t - }; - tcx.tcache.insert(local_def(it.id), tpt); - return tpt; + ast::item_trait(*) => { + tcx.sess.span_bug( + it.span, + fmt!("Invoked ty_of_item on trait")); } ast::item_struct(_, ref generics) => { - let (bounds, substs) = mk_substs(ccx, generics, rp); + let (ty_generics, substs) = mk_substs(ccx, generics, rp); let t = ty::mk_struct(tcx, local_def(it.id), substs); let tpt = ty_param_bounds_and_ty { - bounds: bounds, - region_param: rp, - ty: t + generics: ty_generics, + ty: t }; tcx.tcache.insert(local_def(it.id), tpt); return tpt; @@ -997,76 +1024,82 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item) } ast::foreign_item_const(t) => { ty::ty_param_bounds_and_ty { - bounds: @~[], - region_param: None, + generics: ty::Generics { + bounds: @~[], + region_param: None, + }, ty: ast_ty_to_ty(ccx, &empty_rscope, t) } } } } -// Translate the AST's notion of ty param bounds (which are an enum consisting -// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can -// either be user-defined traits, or one of the four built-in traits (formerly -// known as kinds): Const, Copy, Durable, and Send. -pub fn compute_bounds(ccx: &CrateCtxt, - ast_bounds: @OptVec) - -> ty::param_bounds { - @ast_bounds.flat_map_to_vec(|b| { - match b { - &TraitTyParamBound(b) => { - let li = &ccx.tcx.lang_items; - let ity = ast_ty_to_ty(ccx, &empty_rscope, b); - match ty::get(ity).sty { - ty::ty_trait(did, _, _) => { - if did == li.owned_trait() { - ~[ty::bound_owned] - } else if did == li.copy_trait() { - ~[ty::bound_copy] - } else if did == li.const_trait() { - ~[ty::bound_const] - } else if did == li.durable_trait() { - ~[ty::bound_durable] - } else { - // Must be a user-defined trait - ~[ty::bound_trait(ity)] - } - } - _ => { - ccx.tcx.sess.span_err( - (*b).span, ~"type parameter bounds must be \ - trait types"); - ~[] - } +pub fn ty_generics(ccx: &CrateCtxt, + rp: Option, + generics: &ast::Generics) -> ty::Generics { + return ty::Generics { + region_param: rp, + bounds: @generics.ty_params.map_to_vec(|param| { + match ccx.tcx.ty_param_bounds.find(¶m.id) { + Some(&bs) => bs, + None => { + let bounds = compute_bounds(ccx, rp, generics, param.bounds); + ccx.tcx.ty_param_bounds.insert(param.id, bounds); + bounds } } - &RegionTyParamBound => ~[ty::bound_durable] - } - }) -} + }) + }; -pub fn ty_param_bounds(ccx: &CrateCtxt, - generics: &ast::Generics) - -> @~[ty::param_bounds] { - @do generics.ty_params.map_to_vec |param| { - match ccx.tcx.ty_param_bounds.find(¶m.id) { - Some(&bs) => bs, - None => { - let bounds = compute_bounds(ccx, param.bounds); - ccx.tcx.ty_param_bounds.insert(param.id, bounds); - bounds - } - } + fn compute_bounds( + ccx: &CrateCtxt, + rp: Option, + generics: &ast::Generics, + ast_bounds: @OptVec) -> ty::param_bounds + { + /*! + * + * Translate the AST's notion of ty param bounds (which are an + * enum consisting of a newtyped Ty or a region) to ty's + * notion of ty param bounds, which can either be user-defined + * traits, or one of the four built-in traits (formerly known + * as kinds): Const, Copy, Durable, and Send. + */ + + @ast_bounds.flat_map_to_vec(|b| { + match b { + &TraitTyParamBound(b) => { + let li = &ccx.tcx.lang_items; + let trait_ref = instantiate_trait_ref(ccx, b, rp, generics); + if trait_ref.def_id == li.owned_trait() { + ~[ty::bound_owned] + } else if trait_ref.def_id == li.copy_trait() { + ~[ty::bound_copy] + } else if trait_ref.def_id == li.const_trait() { + ~[ty::bound_const] + } else if trait_ref.def_id == li.durable_trait() { + ~[ty::bound_durable] + } else { + // Must be a user-defined trait + ~[ty::bound_trait(trait_ref)] + } + } + + &RegionTyParamBound => { + ~[ty::bound_durable] + } + } + }) } } pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, decl: &ast::fn_decl, def_id: ast::def_id, - generics: &ast::Generics) + ast_generics: &ast::Generics) -> ty::ty_param_bounds_and_ty { - let bounds = ty_param_bounds(ccx, generics); - let region_param_names = RegionParamNames::from_generics(generics); + let ty_generics = ty_generics(ccx, None, ast_generics); + let region_param_names = RegionParamNames::from_generics(ast_generics); let rb = in_binding_rscope(&empty_rscope, region_param_names); let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) ); let output_ty = ast_ty_to_ty(ccx, &rb, decl.output); @@ -1081,33 +1114,24 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, output: output_ty} }); let tpt = ty_param_bounds_and_ty { - bounds: bounds, - region_param: None, + generics: ty_generics, ty: t_fn }; ccx.tcx.tcache.insert(def_id, tpt); return tpt; } -pub fn mk_generics(ccx: &CrateCtxt, generics: &ast::Generics) - -> (@~[ty::param_bounds], ~[ty::t]) -{ - let mut i = 0u; - let bounds = ty_param_bounds(ccx, generics); - (bounds, - generics.ty_params.map_to_vec(|atp| { - let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); - i += 1u; - t - })) -} - pub fn mk_substs(ccx: &CrateCtxt, - generics: &ast::Generics, - rp: Option) - -> (@~[ty::param_bounds], ty::substs) + ast_generics: &ast::Generics, + rp: Option) -> (ty::Generics, ty::substs) { - let (bounds, params) = mk_generics(ccx, generics); + let mut i = 0; + let ty_generics = ty_generics(ccx, rp, ast_generics); + let params = ast_generics.ty_params.map_to_vec(|atp| { + let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); + i += 1u; + t + }); let self_r = rscope::bound_self_region(rp); - (bounds, substs { self_r: self_r, self_ty: None, tps: params }) + (ty_generics, substs {self_r: self_r, self_ty: None, tps: params}) } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index add70b21e39a4..69c7b1d616b0a 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -90,7 +90,7 @@ pub trait Combine { fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]>; fn self_tys(&self, a: Option, b: Option) -> cres>; - fn substs(&self, did: ast::def_id, as_: &ty::substs, + fn substs(&self, generics: &ty::Generics, as_: &ty::substs, bs: &ty::substs) -> cres; fn bare_fn_tys(&self, a: &ty::BareFnTy, b: &ty::BareFnTy) -> cres; @@ -114,6 +114,7 @@ pub trait Combine { a: ty::TraitStore, b: ty::TraitStore) -> cres; + fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres; } pub struct CombineFields { @@ -192,32 +193,31 @@ pub fn eq_opt_regions( } pub fn super_substs( - self: &C, did: ast::def_id, + self: &C, generics: &ty::Generics, a: &ty::substs, b: &ty::substs) -> cres { fn relate_region_param( self: &C, - did: ast::def_id, + generics: &ty::Generics, a: Option, b: Option) -> cres> { - let polyty = ty::lookup_item_type(self.infcx().tcx, did); - match (polyty.region_param, a, b) { - (None, None, None) => { + match (&generics.region_param, &a, &b) { + (&None, &None, &None) => { Ok(None) } - (Some(ty::rv_invariant), Some(a), Some(b)) => { + (&Some(ty::rv_invariant), &Some(a), &Some(b)) => { do eq_regions(self, a, b).then { Ok(Some(a)) } } - (Some(ty::rv_covariant), Some(a), Some(b)) => { + (&Some(ty::rv_covariant), &Some(a), &Some(b)) => { do self.regions(a, b).chain |r| { Ok(Some(r)) } } - (Some(ty::rv_contravariant), Some(a), Some(b)) => { + (&Some(ty::rv_contravariant), &Some(a), &Some(b)) => { do self.contraregions(a, b).chain |r| { Ok(Some(r)) } @@ -233,14 +233,14 @@ pub fn super_substs( b had opt_region %s with variance %?", a.inf_str(self.infcx()), b.inf_str(self.infcx()), - polyty.region_param)); + generics.region_param)); } } } do self.tps(a.tps, b.tps).chain |tps| { do self.self_tys(a.self_ty, b.self_ty).chain |self_ty| { - do relate_region_param(self, did, + do relate_region_param(self, generics, a.self_r, b.self_r).chain |self_r| { Ok(substs { @@ -520,26 +520,29 @@ pub fn super_tys( (ty::ty_enum(a_id, ref a_substs), ty::ty_enum(b_id, ref b_substs)) if a_id == b_id => { - do self.substs(a_id, a_substs, b_substs).chain |substs| { - Ok(ty::mk_enum(tcx, a_id, substs)) - } + let type_def = ty::lookup_item_type(tcx, a_id); + do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| { + Ok(ty::mk_enum(tcx, a_id, substs)) + } } (ty::ty_trait(a_id, ref a_substs, a_store), ty::ty_trait(b_id, ref b_substs, b_store)) if a_id == b_id => { - do self.substs(a_id, a_substs, b_substs).chain |substs| { - do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| { - Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s)) - } - } + let trait_def = ty::lookup_trait_def(tcx, a_id); + do self.substs(&trait_def.generics, a_substs, b_substs).chain |substs| { + do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| { + Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s)) + } + } } (ty::ty_struct(a_id, ref a_substs), ty::ty_struct(b_id, ref b_substs)) if a_id == b_id => { - do self.substs(a_id, a_substs, b_substs).chain |substs| { - Ok(ty::mk_struct(tcx, a_id, substs)) - } + let type_def = ty::lookup_item_type(tcx, a_id); + do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| { + Ok(ty::mk_struct(tcx, a_id, substs)) + } } (ty::ty_box(ref a_mt), ty::ty_box(ref b_mt)) => { @@ -634,3 +637,25 @@ pub fn super_tys( Ok(ty::mk_mach_float(tcx, val)) } } + +pub fn super_trait_refs( + self: &C, a: &ty::TraitRef, b: &ty::TraitRef) -> cres +{ + // Different traits cannot be related + + // - NOTE in the future, expand out subtraits! + + if a.def_id != b.def_id { + Err(ty::terr_traits( + expected_found(self, a.def_id, b.def_id))) + } else { + let tcx = self.infcx().tcx; + let trait_def = ty::lookup_trait_def(tcx, a.def_id); + let substs = if_ok!(self.substs(&trait_def.generics, &a.substs, &b.substs)); + Ok(ty::TraitRef { + def_id: a.def_id, + substs: substs + }) + } +} + diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 9c8c8997ae087..43f2b0eaf7229 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -299,10 +299,11 @@ impl Combine for Glb { super_closure_tys(self, a, b) } - fn substs(&self, did: ast::def_id, + fn substs(&self, + generics: &ty::Generics, as_: &ty::substs, bs: &ty::substs) -> cres { - super_substs(self, did, as_, bs) + super_substs(self, generics, as_, bs) } fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { @@ -313,5 +314,9 @@ impl Combine for Glb { -> cres> { super_self_tys(self, a, b) } + + fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres { + super_trait_refs(self, a, b) + } } diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 5a705c31c1239..7cf4d25c67024 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -244,10 +244,11 @@ impl Combine for Lub { super_args(self, a, b) } - fn substs(&self, did: ast::def_id, + fn substs(&self, + generics: &ty::Generics, as_: &ty::substs, bs: &ty::substs) -> cres { - super_substs(self, did, as_, bs) + super_substs(self, generics, as_, bs) } fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { @@ -258,4 +259,8 @@ impl Combine for Lub { -> cres> { super_self_tys(self, a, b) } + + fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres { + super_trait_refs(self, a, b) + } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index d8093d571a111..58de0122c8c9b 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -265,7 +265,7 @@ use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::unify::{ValsAndBindings, Root}; use middle::typeck::isr_alist; use util::common::indent; -use util::ppaux::{bound_region_to_str, ty_to_str}; +use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str}; use core::cmp::Eq; use core::result::{Result, Ok, Err}; @@ -419,6 +419,23 @@ pub fn mk_eqty(cx: @mut InferCtxt, }.to_ures() } +pub fn mk_sub_trait_refs(cx: @mut InferCtxt, + a_is_expected: bool, + span: span, + a: &ty::TraitRef, + b: &ty::TraitRef) + -> ures +{ + debug!("mk_sub_trait_refs(%s <: %s)", + a.inf_str(cx), b.inf_str(cx)); + do indent { + do cx.commit { + let suber = cx.sub(a_is_expected, span); + suber.trait_refs(a, b) + } + }.to_ures() +} + pub fn mk_coercety(cx: @mut InferCtxt, a_is_expected: bool, span: span, @@ -700,6 +717,11 @@ pub impl InferCtxt { self.resolve_type_vars_if_possible(t)) } + fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str { + let t = self.resolve_type_vars_in_trait_ref_if_possible(t); + trait_ref_to_str(self.tcx, &t) + } + fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t { match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) { result::Ok(new_type) => new_type, @@ -707,6 +729,31 @@ pub impl InferCtxt { } } + fn resolve_type_vars_in_trait_ref_if_possible(@mut self, + trait_ref: &ty::TraitRef) + -> ty::TraitRef + { + // make up a dummy type just to reuse/abuse the resolve machinery + let dummy0 = ty::mk_trait(self.tcx, + trait_ref.def_id, + copy trait_ref.substs, + ty::UniqTraitStore); + let dummy1 = self.resolve_type_vars_if_possible(dummy0); + match ty::get(dummy1).sty { + ty::ty_trait(ref def_id, ref substs, _) => { + ty::TraitRef {def_id: *def_id, + substs: copy *substs} + } + _ => { + self.tcx.sess.bug( + fmt!("resolve_type_vars_if_possible() yielded %s \ + when supplied with %s", + self.ty_to_str(dummy0), + self.ty_to_str(dummy1))); + } + } + } + fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str, actual_ty: ty::t, err: Option<&ty::type_err>) { let actual_ty = self.resolve_type_vars_if_possible(actual_ty); diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 161905c12e5dd..2e1be2c380f8f 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -256,10 +256,11 @@ impl Combine for Sub { super_args(self, a, b) } - fn substs(&self, did: ast::def_id, + fn substs(&self, + generics: &ty::Generics, as_: &ty::substs, bs: &ty::substs) -> cres { - super_substs(self, did, as_, bs) + super_substs(self, generics, as_, bs) } fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { @@ -270,5 +271,9 @@ impl Combine for Sub { -> cres> { super_self_tys(self, a, b) } + + fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres { + super_trait_refs(self, a, b) + } } diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index 559d29e66efba..d4959961f12ce 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -16,7 +16,7 @@ use middle::ty; use middle::typeck::infer::{Bound, Bounds}; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::unify::{Redirect, Root, VarValue}; -use util::ppaux::{mt_to_str, ty_to_str}; +use util::ppaux::{mt_to_str, ty_to_str, trait_ref_to_str}; use syntax::ast; @@ -91,3 +91,9 @@ impl InferStr for ast::float_ty { self.to_str() } } + +impl InferStr for ty::TraitRef { + fn inf_str(&self, cx: &InferCtxt) -> ~str { + trait_ref_to_str(cx.tcx, self) + } +} diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index d829b0d2a0d51..d3502adb33ab8 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -222,8 +222,8 @@ pub fn lookup_def_ccx(ccx: @mut CrateCtxt, sp: span, id: ast::node_id) pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty { - bounds: @~[], - region_param: None, + generics: ty::Generics {bounds: @~[], + region_param: None}, ty: t } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 238ecf7acea27..cdeb12b80f448 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -239,7 +239,6 @@ pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str { pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str { match s { - ty::BareTraitStore => ~"", ty::UniqTraitStore => ~"~", ty::BoxTraitStore => ~"@", ty::RegionTraitStore(r) => region_to_str_space(cx, "&", r) @@ -285,6 +284,12 @@ pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str { ty_to_str(cx, typ.output)) } +pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str { + let path = ty::item_path(cx, trait_ref.def_id); + let base = ast_map::path_to_str(path, cx.sess.intr()); + parameterized(cx, base, trait_ref.substs.self_r, trait_ref.substs.tps) +} + pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str { let ty::arg {mode: mode, ty: ty} = input; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4a0e58b09c8a8..ec77b54a85371 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -144,7 +144,7 @@ pub static crate_node_id: node_id = 0; // the "special" built-in traits (see middle::lang_items) and // detects Copy, Send, Owned, and Const. pub enum TyParamBound { - TraitTyParamBound(@Ty), + TraitTyParamBound(@trait_ref), RegionTyParamBound } diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index d25792355a718..39b8d4f2cced3 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -227,10 +227,9 @@ priv impl @ext_ctxt { path: @ast::path, bounds: @OptVec ) -> ast::TyParam { - let bound = ast::TraitTyParamBound(@ast::Ty { - id: self.next_id(), - node: ast::ty_path(path, self.next_id()), - span: span, + let bound = ast::TraitTyParamBound(@ast::trait_ref { + ref_id: self.next_id(), + path: path }); ast::TyParam { @@ -466,10 +465,9 @@ fn mk_impl( // All the type parameters need to bound to the trait. let mut impl_tps = opt_vec::with(ty_param); for generics.ty_params.each |tp| { - let t_bound = ast::TraitTyParamBound(@ast::Ty { - id: cx.next_id(), - node: ast::ty_path(path, cx.next_id()), - span: span, + let t_bound = ast::TraitTyParamBound(@ast::trait_ref { + path: path, + ref_id: cx.next_id(), }); impl_tps.push(ast::TyParam { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 9499f95f0e76f..43f0c9edcb964 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -337,6 +337,17 @@ pub fn mk_ty_path_global(cx: @ext_ctxt, let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span }; ty } +pub fn mk_trait_ref_global(cx: @ext_ctxt, + span: span, + +idents: ~[ ast::ident ]) + -> @ast::trait_ref +{ + let path = build::mk_raw_path_global(span, idents); + @ast::trait_ref { + path: path, + ref_id: cx.next_id() + } +} pub fn mk_simple_ty_path(cx: @ext_ctxt, span: span, ident: ast::ident) diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 18ebceaeb4396..ccd9a33757dd5 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -177,9 +177,9 @@ pub fn create_derived_impl(cx: @ext_ctxt, // Create the type parameters. let impl_ty_params = generics.ty_params.map(|ty_param| { - let bound = build::mk_ty_path_global(cx, - span, - trait_path.map(|x| *x)); + let bound = build::mk_trait_ref_global(cx, + span, + trait_path.map(|x| *x)); let bounds = @opt_vec::with(TraitTyParamBound(bound)); build::mk_ty_param(cx, ty_param.ident, bounds) }); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0a473b1cebeaf..5aa51c262e174 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -134,7 +134,7 @@ pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl { fn fold_ty_param_bound(tpb: &TyParamBound, fld: @ast_fold) -> TyParamBound { match *tpb { - TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)), + TraitTyParamBound(ty) => TraitTyParamBound(fold_trait_ref(ty, fld)), RegionTyParamBound => RegionTyParamBound } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1d780c9b80698..3a3597828cd24 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2750,8 +2750,8 @@ pub impl Parser { self.bump(); } token::MOD_SEP | token::IDENT(*) => { - let maybe_bound = match *self.token { - token::MOD_SEP => None, + let obsolete_bound = match *self.token { + token::MOD_SEP => false, token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { ~"send" | @@ -2761,27 +2761,18 @@ pub impl Parser { self.obsolete( *self.span, ObsoleteLowerCaseKindBounds); - - // Bogus value, but doesn't matter, since - // is an error - Some(TraitTyParamBound( - self.mk_ty_path(sid))) + self.bump(); + true } - _ => None + _ => false } } _ => fail!() }; - match maybe_bound { - Some(bound) => { - self.bump(); - result.push(bound); - } - None => { - let ty = self.parse_ty(true); - result.push(TraitTyParamBound(ty)); - } + if !obsolete_bound { + let tref = self.parse_trait_ref(); + result.push(TraitTyParamBound(tref)); } } _ => break, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0c79cbca039a6..20fc99baf2179 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -562,7 +562,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) { match opt_trait { Some(t) => { - print_path(s, t.path, false); + print_trait_ref(s, t); space(s.s); word_space(s, ~"for"); } @@ -619,6 +619,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) { (s.ann.post)(ann_node); } +fn print_trait_ref(s: @ps, t: &ast::trait_ref) { + print_path(s, t.path, false); +} + pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def, generics: &ast::Generics, ident: ast::ident, span: codemap::span, visibility: ast::visibility) { @@ -1744,7 +1748,7 @@ pub fn print_bounds(s: @ps, bounds: @OptVec) { } match *bound { - TraitTyParamBound(ty) => print_type(s, ty), + TraitTyParamBound(tref) => print_trait_ref(s, tref), RegionTyParamBound => word(s.s, ~"'static"), } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a994f2b5b2280..b20c5eeee1f04 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -147,6 +147,10 @@ pub fn visit_local(loc: @local, e: E, v: vt) { } } +fn visit_trait_ref(tref: @ast::trait_ref, e: E, v: vt) { + visit_path(tref.path, e, v); +} + pub fn visit_item(i: @item, e: E, v: vt) { match i.node { item_const(t, ex) => { @@ -189,9 +193,9 @@ pub fn visit_item(i: @item, e: E, v: vt) { } item_impl(ref tps, ref traits, ty, ref methods) => { (v.visit_generics)(tps, e, v); - for traits.each |p| { - visit_path(p.path, e, v); - } + for traits.each |&p| { + visit_trait_ref(p, e, v); + } (v.visit_ty)(ty, e, v); for methods.each |m| { visit_method_helper(*m, e, v) @@ -327,8 +331,8 @@ pub fn visit_ty_param_bounds(bounds: @OptVec, e: E, v: vt) { for bounds.each |bound| { match *bound { - TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v), - RegionTyParamBound => () + TraitTyParamBound(ty) => visit_trait_ref(ty, e, v), + RegionTyParamBound => {} } } } diff --git a/src/test/compile-fail/issue-2330.rs b/src/test/compile-fail/issue-2330.rs index d8acbf2893aa5..6152e82294d1b 100644 --- a/src/test/compile-fail/issue-2330.rs +++ b/src/test/compile-fail/issue-2330.rs @@ -15,7 +15,7 @@ trait channel { } // `chan` is not a trait, it's an enum -impl chan for int { //~ ERROR can only implement trait types +impl chan for int { //~ ERROR chan is not a trait fn send(&self, v: int) { fail!() } } diff --git a/src/test/compile-fail/selftype-traittype.rs b/src/test/compile-fail/selftype-traittype.rs index 467154244b760..220573660c5b0 100644 --- a/src/test/compile-fail/selftype-traittype.rs +++ b/src/test/compile-fail/selftype-traittype.rs @@ -12,7 +12,7 @@ trait add { fn plus(&self, x: Self) -> Self; } -fn do_add(x: add, y: add) -> add { +fn do_add(x: @add, y: @add) -> @add { x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait } diff --git a/src/test/run-pass/issue-3702.rs b/src/test/run-pass/issue-3702.rs index eaa2ac4c4baf2..7c2f8cf98cb8a 100644 --- a/src/test/run-pass/issue-3702.rs +++ b/src/test/run-pass/issue-3702.rs @@ -13,7 +13,7 @@ pub fn main() { fn to_str(&self) -> ~str; } - fn to_string(t: Text) { + fn to_string(t: @Text) { io::println(t.to_str()); } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 565c06fb8c890..a27599e6ed00a 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -417,9 +417,9 @@ impl TyVisitor for ptr_visit_adaptor { } fn visit_trait(&self) -> bool { - self.align_to::(); + self.align_to::<@TyVisitor>(); if ! self.inner.visit_trait() { return false; } - self.bump_past::(); + self.bump_past::<@TyVisitor>(); true } From 2a44a1bd97cbd072646f98eb60db6de08f679f1b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 2 Apr 2013 09:42:08 -0700 Subject: [PATCH 050/403] Fix various warnings, NOTEs, etc --- src/libcore/libc.rs | 2 +- src/librustc/driver/driver.rs | 2 +- src/librustc/middle/moves.rs | 2 +- src/librustc/middle/trans/expr.rs | 1 - src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/coherence.rs | 2 +- src/librustc/middle/typeck/collect.rs | 7 +++---- src/librustdoc/prune_private_pass.rs | 2 +- src/libsyntax/ext/auto_encode.rs | 2 +- src/rt/rust_log.cpp | 2 +- 10 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index fdb82a7303bea..95d963a36e3aa 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1394,7 +1394,7 @@ pub mod funcs { use libc::types::common::posix88::{DIR, dirent_t}; use libc::types::os::arch::c95::{c_char, c_int, c_long}; - // NOTE: On OS X opendir and readdir have two versions, + // NB: On OS X opendir and readdir have two versions, // one for 32-bit kernelspace and one for 64. // We should be linking to the 64-bit ones, called // opendir$INODE64, etc. but for some reason rustc diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 3b1401ae1d2c8..cd1af369570ef 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -308,7 +308,7 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, }; - // NOTE: Android hack + // NB: Android hack if sess.targ_cfg.arch == abi::Arm && (sess.opts.output_type == link::output_type_object || sess.opts.output_type == link::output_type_exe) { diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index ed7ca441b984b..1401d86123e64 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -211,7 +211,7 @@ use core::prelude::*; use middle::pat_util::{pat_bindings}; use middle::freevars; use middle::ty; -use middle::typeck::{method_map, method_map_entry}; +use middle::typeck::{method_map}; use util::ppaux; use util::common::indenter; diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 5afdd1b027188..d4a1013e83c85 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1714,7 +1714,6 @@ fn trans_assign_op(bcx: block, return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum); } -// NOTE: Mode neccessary here? fn shorten(+x: ~str) -> ~str { if x.len() > 60 { x.substr(0, 60).to_owned() } else { x } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b1d977b7445cc..b20678ac092e0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4367,7 +4367,7 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt, for supertrait_refs.each |&supertrait_ref| { let d_id = supertrait_ref.def_id; if !supertrait_set.contains_key(&d_id) { - // NOTE Could have same trait multiple times + // FIXME(#5527) Could have same trait multiple times supertrait_set.insert(d_id, ()); trait_ref = supertrait_ref; seen_def_ids.push(d_id); diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index f6042cf2e0cca..b0e5ecee01ebb 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -38,7 +38,7 @@ use middle::typeck::infer::combine::Combine; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; use middle::typeck::infer::{resolve_nested_tvar, resolve_type}; -use syntax::ast::{crate, def_id, def_mod, def_ty, def_trait}; +use syntax::ast::{crate, def_id, def_mod, def_trait}; use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref}; use syntax::ast; use syntax::ast_map::node_item; diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a2245dc82cf80..8dda513106e68 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -33,7 +33,7 @@ are represented as `ty_param()` instances. use core::prelude::*; use metadata::csearch; -use middle::ty::{substs, ty_param_bounds_and_ty, ty_param_substs_and_ty}; +use middle::ty::{substs, ty_param_bounds_and_ty}; use middle::ty; use middle::typeck::astconv::{AstConv, ty_of_arg}; use middle::typeck::astconv::{ast_ty_to_ty}; @@ -41,8 +41,7 @@ use middle::typeck::astconv; use middle::typeck::infer; use middle::typeck::rscope::*; use middle::typeck::rscope; -use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx, - write_tpt_to_tcx}; +use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx}; use util::common::{indenter, pluralize}; use util::ppaux; @@ -362,7 +361,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, for ast_trait_refs.each |&ast_trait_ref| { let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics); - // NOTE Could have same trait multiple times + // FIXME(#5527) Could have same trait multiple times if ty_trait_refs.any(|other_trait| other_trait.def_id == trait_ref.def_id) { // This means a trait inherited from the same supertrait more // than once. diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index a1f8fdb75d9ea..08008ab2bcae0 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -117,7 +117,7 @@ fn fold_mod( !doc.methods.is_empty() } else { // This is a trait implementation, make it visible - // NOTE: This is not quite right since this could be an impl + // NB: This is not quite right since this could be an impl // of a private trait. We can't know that without running // resolve though. true diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 39b8d4f2cced3..97bc89248acf2 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -222,7 +222,7 @@ pub fn expand_auto_decode( priv impl @ext_ctxt { fn bind_path( &self, - span: span, + _span: span, ident: ast::ident, path: @ast::path, bounds: @OptVec diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp index 2b86db6defe09..32723cf31bc6f 100644 --- a/src/rt/rust_log.cpp +++ b/src/rt/rust_log.cpp @@ -314,7 +314,7 @@ void update_log_settings(void* crate_map, char* settings) { n_dirs, &n_matches); if (n_matches < n_dirs) { - // NOTE: Android compiler is complaining about format specifiers here + // NB: Android compiler is complaining about format specifiers here // and I don't understand why /*printf("warning: got %" PRIdPTR " RUST_LOG specs, " "enabled %" PRIdPTR " flags.", From d7163985b8c8daccc34cc6213fb621657f1bc50a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 4 Apr 2013 17:14:39 -0400 Subject: [PATCH 051/403] Add comment explaining method visibility --- src/librustc/middle/typeck/collect.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 8dda513106e68..a9d54716cd8a8 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -653,13 +653,20 @@ pub fn convert_methods(ccx: &CrateCtxt, &method_generics.lifetimes, untransformed_rcvr_ty, m.self_ty, &m.decl); + + // if the method specifies a visibility, use that, otherwise + // inherit the visibility from the impl (so `foo` in `pub impl + // { fn foo(); }` is public, but private in `priv impl { fn + // foo(); }`). + let method_vis = m.vis.inherit_from(rcvr_visibility); + ty::method { ident: m.ident, generics: ty_generics(ccx, None, &m.generics), transformed_self_ty: transformed_self_ty, fty: fty, self_ty: m.self_ty.node, - vis: m.vis.inherit_from(rcvr_visibility), + vis: method_vis, def_id: local_def(m.id) } } From 13801f60b26009991cd6880b6b40fae9265a8280 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 4 Apr 2013 17:14:59 -0400 Subject: [PATCH 052/403] rustc: Be careful about calls to fn types that contain nested errors --- src/librustc/middle/typeck/check/mod.rs | 33 +++++++++++++------------ 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 957259e7d172a..c3ec2d14d83d0 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1135,22 +1135,23 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, sugar: ast::CallSugar, deref_args: DerefArgs) -> ty::t { - match ty::get(method_fn_ty).sty { - ty::ty_bare_fn(ref fty) => { - check_argument_types(fcx, sp, fty.sig.inputs, callee_expr, - args, sugar, deref_args); - fty.sig.output - } - ty::ty_err => { - let err_inputs = err_args(fcx.tcx(), args.len()); - check_argument_types(fcx, sp, err_inputs, callee_expr, - args, sugar, deref_args); - method_fn_ty - } - _ => { - fcx.tcx().sess.span_bug( - sp, - fmt!("Method without bare fn type")); + if ty::type_is_error(method_fn_ty) { + let err_inputs = err_args(fcx.tcx(), args.len()); + check_argument_types(fcx, sp, err_inputs, callee_expr, + args, sugar, deref_args); + method_fn_ty + } else { + match ty::get(method_fn_ty).sty { + ty::ty_bare_fn(ref fty) => { + check_argument_types(fcx, sp, fty.sig.inputs, callee_expr, + args, sugar, deref_args); + fty.sig.output + } + _ => { + fcx.tcx().sess.span_bug( + sp, + fmt!("Method without bare fn type")); + } } } } From fd8f56efab638baa9d6028ce9e02f66a576cfea1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 3 Apr 2013 05:24:30 -0700 Subject: [PATCH 053/403] Link lifetimes of autoslice'd vectors (Issue #3184) Fixes #5739. --- src/librustc/middle/ty.rs | 6 +-- src/librustc/middle/typeck/check/regionck.rs | 53 ++++++++++++++++--- src/test/run-pass/region-dependent-addr-of.rs | 3 ++ src/test/run-pass/region-dependent-autofn.rs | 22 ++++++++ .../run-pass/region-dependent-autoslice.rs | 23 ++++++++ 5 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/region-dependent-autofn.rs create mode 100644 src/test/run-pass/region-dependent-autoslice.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b20678ac092e0..c29029de351e3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -197,13 +197,13 @@ pub enum AutoRefKind { /// Convert from T to &T AutoPtr, - /// Convert from @[]/~[] to &[] (or str) + /// Convert from @[]/~[]/&[] to &[] (or str) AutoBorrowVec, - /// Convert from @[]/~[] to &&[] (or str) + /// Convert from @[]/~[]/&[] to &&[] (or str) AutoBorrowVecRef, - /// Convert from @fn()/~fn() to &fn() + /// Convert from @fn()/~fn()/&fn() to &fn() AutoBorrowFn } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index dfc5f218d67d0..833dbff89a0fc 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -494,8 +494,8 @@ pub mod guarantor { * inferencer would not know of this dependency and thus it might * infer the lifetime of L2 to be greater than L1 (issue #3148). * - * There are a number of troublesome scenarios in the test - * `region-dependent-addr-of.rs`, but here is one example: + * There are a number of troublesome scenarios in the tests + * `region-dependent-*.rs`, but here is one example: * * struct Foo { i: int } * struct Bar { foo: Foo } @@ -583,8 +583,35 @@ pub mod guarantor { let mut expr_ct = categorize_unadjusted(rcx, expr); expr_ct = apply_autoderefs( rcx, expr, autoderefs, expr_ct); - for expr_ct.cat.guarantor.each |g| { - infallibly_mk_subr(rcx, true, expr.span, autoref.region, *g); + + match autoref.kind { + ty::AutoPtr => { + // In this case, we are implicitly adding an `&`. + maybe_make_subregion(rcx, expr, autoref.region, + expr_ct.cat.guarantor); + } + + ty::AutoBorrowVec | + ty::AutoBorrowVecRef | + ty::AutoBorrowFn => { + // In each of these cases, what is being borrowed is + // not the (autoderef'd) expr itself but rather the + // contents of the autoderef'd expression (i.e., what + // the pointer points at). + maybe_make_subregion(rcx, expr, autoref.region, + guarantor_of_deref(&expr_ct.cat)); + } + } + + fn maybe_make_subregion( + rcx: @mut Rcx, + expr: @ast::expr, + sub_region: ty::Region, + sup_region: Option) + { + for sup_region.each |r| { + infallibly_mk_subr(rcx, true, expr.span, sub_region, *r); + } } } @@ -813,19 +840,31 @@ pub mod guarantor { fn pointer_categorize(ty: ty::t) -> PointerCategorization { match ty::get(ty).sty { - ty::ty_rptr(r, _) | ty::ty_evec(_, ty::vstore_slice(r)) | + ty::ty_rptr(r, _) | + ty::ty_evec(_, ty::vstore_slice(r)) | ty::ty_estr(ty::vstore_slice(r)) => { BorrowedPointer(r) } - ty::ty_uniq(*) | ty::ty_estr(ty::vstore_uniq) | + ty::ty_uniq(*) | + ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => { OwnedPointer } - ty::ty_box(*) | ty::ty_ptr(*) | + ty::ty_box(*) | + ty::ty_ptr(*) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => { OtherPointer } + ty::ty_closure(ref closure_ty) => { + match closure_ty.sigil { + ast::BorrowedSigil => BorrowedPointer(closure_ty.region), + ast::OwnedSigil => OwnedPointer, + + // NOTE This is...not quite right. Deduce a test etc. + ast::ManagedSigil => OtherPointer, + } + } _ => { NotPointer } diff --git a/src/test/run-pass/region-dependent-addr-of.rs b/src/test/run-pass/region-dependent-addr-of.rs index 42784200b6639..dd33f7f1e309b 100644 --- a/src/test/run-pass/region-dependent-addr-of.rs +++ b/src/test/run-pass/region-dependent-addr-of.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test lifetimes are linked properly when we create dependent region pointers. +// Issue #3148. + struct A { value: B } diff --git a/src/test/run-pass/region-dependent-autofn.rs b/src/test/run-pass/region-dependent-autofn.rs new file mode 100644 index 0000000000000..82d4115d66d9f --- /dev/null +++ b/src/test/run-pass/region-dependent-autofn.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +fn subslice<'r>(v: &'r fn()) -> &'r fn() { v } + +fn both<'r>(v: &'r fn()) -> &'r fn() { + subslice(subslice(v)) +} + +fn main() { + both(main); +} diff --git a/src/test/run-pass/region-dependent-autoslice.rs b/src/test/run-pass/region-dependent-autoslice.rs new file mode 100644 index 0000000000000..10c2988fc9f26 --- /dev/null +++ b/src/test/run-pass/region-dependent-autoslice.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +fn subslice1<'r>(v: &'r [uint]) -> &'r [uint] { v } + +fn both<'r>(v: &'r [uint]) -> &'r [uint] { + subslice1(subslice1(v)) +} + +fn main() { + let v = ~[1,2,3]; + both(v); +} From e2a6feb8fe38be01512f0fd1ea08b1909f190892 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 5 Apr 2013 12:26:47 +0200 Subject: [PATCH 054/403] Tutorial: spelling correction and move a failing test to an xfail-test marked code block. --- doc/tutorial.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 794f3089a100d..5a47cefb33d2c 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1081,7 +1081,9 @@ let mut d : @mut int; // and one of type managed mutable int c = a; // box type is the same, okay d = b; // box type is the same, okay +~~~~ +~~~~ {.xfail-test} // but b cannot be assigned to c, or a to d c = b; // error ~~~~ @@ -1101,7 +1103,7 @@ let y = x.clone(); // y is a newly allocated box let z = x; // no new memory allocated, x can no longer be used ~~~~ -Since in owned boxes mutabilility is a property of the owner, not the +Since in owned boxes mutability is a property of the owner, not the box, mutable boxes may become immutable when they are moved, and vice-versa. ~~~~ From b22a06000d68faf7fe080dc9fd5a2686502d212f Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Fri, 5 Apr 2013 16:41:47 -0600 Subject: [PATCH 055/403] Implement Clone for @ and @mut types. The borrowck-borrow-from-expr-block test had to be updated. I'm not sure why it compiled before since ~int was already clonable. --- src/libcore/clone.rs | 10 +++++++ .../borrowck-borrow-from-expr-block.rs | 2 +- src/test/run-pass/clones.rs | 27 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/clones.rs diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 7b86355c91e50..10cce4f69c611 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -36,6 +36,16 @@ impl Clone for ~T { fn clone(&self) -> ~T { ~(**self).clone() } } +impl Clone for @T { + #[inline(always)] + fn clone(&self) -> @T { @(**self).clone() } +} + +impl Clone for @mut T { + #[inline(always)] + fn clone(&self) -> @mut T { @mut (**self).clone() } +} + macro_rules! clone_impl( ($t:ty) => { impl Clone for $t { diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index 401985023bcc7..fc7786d08cb57 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -13,7 +13,7 @@ fn borrow(x: &int, f: &fn(x: &int)) { } fn test1(x: @~int) { - do borrow(&*x.clone()) |p| { + do borrow(&**x.clone()) |p| { let x_a = ptr::addr_of(&(**x)); assert!((x_a as uint) != ptr::to_uint(p)); assert!(unsafe{*x_a} == *p); diff --git a/src/test/run-pass/clones.rs b/src/test/run-pass/clones.rs new file mode 100644 index 0000000000000..f4fa1b81ab1ad --- /dev/null +++ b/src/test/run-pass/clones.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let a : ~int = ~5i; + let b : ~int = a.clone(); + + debug!(fmt!("a: %?, b: %?", a, b)); + + let a : @int = @5i; + let b : @int = a.clone(); + + debug!(fmt!("a: %?, b: %?", a, b)); + + let a : @mut int = @mut 5i; + let b : @mut int = a.clone(); + *b = 6; + + debug!(fmt!("a: %?, b: %?", a, b)); +} From d375171fd44247bff3e355fb82d88b83f14da442 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Fri, 5 Apr 2013 17:51:43 -0600 Subject: [PATCH 056/403] Move tests inside clone.rs and fixed copyright headers. --- src/libcore/clone.rs | 23 +++++++++++++++- .../borrowck-borrow-from-expr-block.rs | 2 +- src/test/run-pass/clones.rs | 27 ------------------- 3 files changed, 23 insertions(+), 29 deletions(-) delete mode 100644 src/test/run-pass/clones.rs diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 10cce4f69c611..c4b5bb8d98bbc 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -73,3 +73,24 @@ clone_impl!(f64) clone_impl!(bool) clone_impl!(char) + +#[test] +fn test_owned_clone() { + let a : ~int = ~5i; + let b : ~int = a.clone(); + assert!(a == b); +} + +#[test] +fn test_managed_clone() { + let a : @int = @5i; + let b : @int = a.clone(); + assert!(a == b); +} + +#[test] +fn test_managed_mut_clone() { + let a : @int = @5i; + let b : @int = a.clone(); + assert!(a == b); +} diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index fc7786d08cb57..077de5c7eb125 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/run-pass/clones.rs b/src/test/run-pass/clones.rs deleted file mode 100644 index f4fa1b81ab1ad..0000000000000 --- a/src/test/run-pass/clones.rs +++ /dev/null @@ -1,27 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let a : ~int = ~5i; - let b : ~int = a.clone(); - - debug!(fmt!("a: %?, b: %?", a, b)); - - let a : @int = @5i; - let b : @int = a.clone(); - - debug!(fmt!("a: %?, b: %?", a, b)); - - let a : @mut int = @mut 5i; - let b : @mut int = a.clone(); - *b = 6; - - debug!(fmt!("a: %?, b: %?", a, b)); -} From d6f455ebca79b6a3d374158a047b1cdd744ebc5e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 5 Apr 2013 17:17:49 -0700 Subject: [PATCH 057/403] rustllvm: Only initialize command-line arguments once In my WIP on rustpkg, I was calling driver code that calls LLVMRustWriteOutputFile more than once. This was making LLVM unhappy, since that function has code that initializes the command-line options for LLVM, and I guess you can't do that more than once. So, check if they've already been initialized. --- src/rustllvm/RustWrapper.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index c4846c1a62bc3..bdf13746f3ebf 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -62,6 +62,8 @@ using namespace llvm::sys; static const char *LLVMRustError; +extern cl::opt EnableARMEHABI; + extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { LLVMMemoryBufferRef MemBuf = NULL; @@ -429,10 +431,16 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, LLVMRustInitializeTargets(); - int argc = 3; - const char* argv[] = {"rustc", "-arm-enable-ehabi", - "-arm-enable-ehabi-descriptors"}; - cl::ParseCommandLineOptions(argc, argv); + // Initializing the command-line options more than once is not + // allowed. So, check if they've already been initialized. + // (This could happen if we're being called from rustpkg, for + // example.) + if (!EnableARMEHABI) { + int argc = 3; + const char* argv[] = {"rustc", "-arm-enable-ehabi", + "-arm-enable-ehabi-descriptors"}; + cl::ParseCommandLineOptions(argc, argv); + } TargetOptions Options; Options.NoFramePointerElim = true; From e0f72e22985d0d39707f7741c0b63002889c457a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 7 Mar 2013 14:54:23 -0800 Subject: [PATCH 058/403] checkpoint --- src/librustpkg/rustpkg.rc | 190 ++++++++++++++++++++++++++++++++++---- src/librustpkg/util.rs | 78 ++++++---------- 2 files changed, 200 insertions(+), 68 deletions(-) diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index bf1301868af54..86802c6578144 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -281,7 +281,13 @@ impl Ctx { match cmd { ~"build" => { - self.build(&os::getcwd(), true, false, false); + if args.len() < 1 { + return usage::build(); + } + let pkgid = PkgId::new(args[0]); + let mut src = PkgSrc::new(&Path("."), &pkgid); + src.find_crates(); + src.build(&Path(".")); } ~"clean" => { self.clean(); @@ -927,7 +933,7 @@ pub fn main() { /// A crate is a unit of Rust code to be compiled into a binary or library pub struct Crate { - file: ~str, + file: Path, flags: ~[~str], cfgs: ~[~str] } @@ -959,28 +965,37 @@ pub fn run(listeners: ~[Listener]) { } pub impl Crate { - pub fn flag(&self, flag: ~str) -> Crate { + + static fn new(p: &Path) -> Crate { + Crate { + file: copy *p, + flags: ~[], + cfgs: ~[] + } + } + + fn flag(&self, flag: ~str) -> Crate { Crate { flags: vec::append(copy self.flags, ~[flag]), .. copy *self } } - pub fn flags(&self, flags: ~[~str]) -> Crate { + fn flags(&self, flags: ~[~str]) -> Crate { Crate { flags: vec::append(copy self.flags, flags), .. copy *self } } - pub fn cfg(&self, cfg: ~str) -> Crate { + fn cfg(&self, cfg: ~str) -> Crate { Crate { cfgs: vec::append(copy self.cfgs, ~[cfg]), .. copy *self } } - pub fn cfgs(&self, cfgs: ~[~str]) -> Crate { + fn cfgs(&self, cfgs: ~[~str]) -> Crate { Crate { cfgs: vec::append(copy self.cfgs, cfgs), .. copy *self @@ -988,15 +1003,6 @@ pub impl Crate { } } -/// Create a crate target from a source file -pub fn Crate(file: ~str) -> Crate { - Crate { - file: file, - flags: ~[], - cfgs: ~[] - } -} - /** * Get the working directory of the package script. * Assumes that the package script has been compiled @@ -1026,7 +1032,7 @@ pub fn build(crates: ~[Crate]) -> bool { let test = args[3] == ~"true"; for crates.each |&crate| { - let path = &dir.push_rel(&Path(crate.file)).normalize(); + let path = &dir.push_rel(&crate.file).normalize(); util::note(fmt!("compiling %s", path.to_str())); @@ -1043,3 +1049,155 @@ pub fn build(crates: ~[Crate]) -> bool { success } + + +// Path-fragment identifier of a package such as +// 'github.com/graydon/test'; must be a relative +// path with >=1 component. +struct PkgId { + path: Path +} + +condition! { + bad_pkg_id: (::core::path::Path, ~str) -> ::PkgId; +} + +impl PkgId { + static fn new(s: &str) -> PkgId { + use bad_pkg_id::cond; + + let p = Path(s); + if p.is_absolute { + return cond.raise((p, ~"absolute pkgid")); + } + if p.components.len() < 1 { + return cond.raise((p, ~"0-length pkgid")); + } + PkgId { + path: p + } + } +} + + +// An enumeration of the unpacked source of a package workspace. +// This contains a list of files found in the source workspace. +pub struct PkgSrc { + root: Path, + id: PkgId, + libs: ~[Crate], + mains: ~[Crate], + tests: ~[Crate], + benchs: ~[Crate], +} + +condition! { + bad_path: (::core::path::Path, ~str) -> ::core::path::Path; +} + +condition! { + build_err: (~str) -> (); +} + +impl PkgSrc { + + + static fn new(fs_root: &Path, id: &PkgId) -> PkgSrc { + PkgSrc { + root: copy *fs_root, + id: copy *id, + libs: ~[], + mains: ~[], + tests: ~[], + benchs: ~[] + } + } + + + fn check_dir(&self) -> Path { + use bad_path::cond; + + let dir = self.root.push_rel(&self.id.path).normalize(); + + if ! os::path_exists(&dir) { + return cond.raise((dir, ~"missing package dir")); + } + + if ! os::path_is_dir(&dir) { + return cond.raise((dir, ~"missing package dir")); + } + + dir + } + + + fn has_pkg_file(&self) -> bool { + let dir = self.check_dir(); + dir.push("pkg.rs").exists() + } + + + static fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) { + assert p.components.len() > prefix; + let mut sub = Path(""); + for vec::slice(p.components, prefix, + p.components.len()).each |c| { + sub = sub.push(*c); + } + debug!("found crate %s", sub.to_str()); + cs.push(Crate::new(&sub)); + } + + fn find_crates(&mut self) { + use PkgSrc::push_crate; + assert ! self.has_pkg_file(); + let dir = self.check_dir(); + let prefix = dir.components.len(); + for os::walk_dir(&dir) |pth| { + match pth.filename() { + Some(~"lib.rs") => push_crate(&mut self.libs, + prefix, pth), + Some(~"main.rs") => push_crate(&mut self.mains, + prefix, pth), + Some(~"test.rs") => push_crate(&mut self.tests, + prefix, pth), + Some(~"bench.rs") => push_crate(&mut self.benchs, + prefix, pth), + _ => () + } + } + debug!("found %u libs, %u mains, %u tests, %u benchs", + self.libs.len(), + self.mains.len(), + self.tests.len(), + self.benchs.len()) + } + + + static fn build_crates(dst_dir: &Path, + src_dir: &Path, + crates: &[Crate], + test: bool) { + + for crates.each |&crate| { + let path = &src_dir.push_rel(&crate.file).normalize(); + util::note(fmt!("compiling %s", path.to_str())); + if ! util::compile_crate(None, path, + dst_dir, + crate.flags, + crate.cfgs, + false, test) { + build_err::cond.raise(fmt!("build failure on %s", + path.to_str())); + } + } + } + + fn build(&self, dst_dir: &Path) { + let dir = self.check_dir(); + PkgSrc::build_crates(dst_dir, &dir, self.libs, false); + PkgSrc::build_crates(dst_dir, &dir, self.mains, false); + PkgSrc::build_crates(dst_dir, &dir, self.tests, true); + PkgSrc::build_crates(dst_dir, &dir, self.benchs, true); + } +} \ No newline at end of file diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 9d3751c3de297..776ca39826834 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -597,11 +597,23 @@ pub fn remove_pkg(pkg: &Package) -> bool { true } -pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, - flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - let lib_dir = dir.push(~"lib"); - let bin_dir = dir.push(~"bin"); - let test_dir = dir.push(~"test"); +pub fn compile_input(sysroot: Option, + in_file: &Path, + out_dir: &Path, + flags: ~[~str], + cfgs: ~[~str], + opt: bool, + test: bool) -> bool { + + assert in_file.components.len() > 1; + let input = driver::file_input(copy *in_file); + let short_name = in_file.pop().filename().get(); + let out_file = out_dir.push(os::dll_filename(short_name)); + + debug!("compiling %s into %s", + in_file.to_str(), + out_file.to_str()); + let binary = os::args()[0]; let matches = getopts(flags, driver::optgroups()).get(); let options = @session::options { @@ -630,15 +642,12 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, let mut name = None; let mut vers = None; - let mut uuid = None; let mut crate_type = None; fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>, Option<~str>) { let mut name = None; let mut vers = None; - let mut uuid = None; for mis.each |a| { match a.node { @@ -647,7 +656,6 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, match *v { ~"name" => name = Some(*s), ~"vers" => vers = Some(*s), - ~"uuid" => uuid = Some(*s), _ => { } } } @@ -655,7 +663,7 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, } } - (name, vers, uuid) + (name, vers) } for crate.node.attrs.each |a| { @@ -670,11 +678,10 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, ast::meta_list(v, mis) => { match *v { ~"link" => { - let (n, v, u) = load_link_attr(mis); + let (n, v) = load_link_attr(mis); name = n; vers = v; - uuid = u; } _ => {} } @@ -683,16 +690,6 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, } } - if name.is_none() || vers.is_none() || uuid.is_none() { - error(~"link attr without (name, vers, uuid) values"); - - return false; - } - - let name = name.get(); - let vers = vers.get(); - let uuid = uuid.get(); - let is_bin = match crate_type { Some(crate_type) => { match crate_type { @@ -712,29 +709,14 @@ pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, } }; - if test { - need_dir(&test_dir); - - outputs = driver::build_output_filenames(input, &Some(test_dir), - &None, sess) - } - else if is_bin { - need_dir(&bin_dir); - - let path = bin_dir.push(fmt!("%s-%s-%s%s", name, - hash(name + uuid + vers), - vers, exe_suffix())); - outputs = driver::build_output_filenames(input, &None, &Some(path), - sess); - } else { - need_dir(&lib_dir); - - outputs = driver::build_output_filenames(input, &Some(lib_dir), - &None, sess) - } + outputs = driver::build_output_filenames(input, + &Some(copy *out_dir), + &Some(out_file), + sess); driver::compile_rest(sess, cfg, driver::cu_everything, - Some(outputs), Some(crate)); + Some(outputs), + Some(crate)); true } @@ -753,15 +735,7 @@ pub fn exe_suffix() -> ~str { ~"" } pub fn compile_crate(sysroot: Option, crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs, - opt, test) -} - -pub fn compile_str(sysroot: Option, code: ~str, dir: &Path, - flags: ~[~str], cfgs: ~[~str], opt: bool, - test: bool) -> bool { - compile_input(sysroot, driver::str_input(code), dir, flags, cfgs, - opt, test) + compile_input(sysroot, crate, dir, flags, cfgs, opt, test) } #[cfg(windows)] From 28f0782260ca2e83edd79aeb37888be3e45d23b1 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 6 Apr 2013 13:19:28 +1100 Subject: [PATCH 059/403] librustc: use new `[ty, .. len]` syntax for fixed vector errors. --- src/librustc/util/ppaux.rs | 2 +- src/test/compile-fail/issue-2149.rs | 2 +- src/test/compile-fail/issue-4517.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index cdeb12b80f448..3b3c42d5d8b2e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -248,7 +248,7 @@ pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str { pub fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { match vs { ty::vstore_fixed(_) => { - fmt!("[%s * %s]", ty, vstore_to_str(cx, vs)) + fmt!("[%s, .. %s]", ty, vstore_to_str(cx, vs)) } ty::vstore_slice(_) => { fmt!("%s %s", vstore_to_str(cx, vs), ty) diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index da3728ff3ae12..2842d884c9918 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -22,6 +22,6 @@ impl vec_monad for ~[A] { } fn main() { ["hi"].bind(|x| [x] ); - //~^ ERROR type `[&'static str * 1]` does not implement any method in scope named `bind` + //~^ ERROR type `[&'static str, .. 1]` does not implement any method in scope named `bind` //~^^ ERROR Unconstrained region variable } diff --git a/src/test/compile-fail/issue-4517.rs b/src/test/compile-fail/issue-4517.rs index 23cfeecc520e7..0fbc79b1bc7bd 100644 --- a/src/test/compile-fail/issue-4517.rs +++ b/src/test/compile-fail/issue-4517.rs @@ -2,5 +2,5 @@ fn bar(int_param: int) {} fn main() { let foo: [u8, ..4] = [1u8, ..4u8]; - bar(foo); //~ ERROR mismatched types: expected `int` but found `[u8 * 4]` (expected int but found vector) + bar(foo); //~ ERROR mismatched types: expected `int` but found `[u8, .. 4]` (expected int but found vector) } From 38fe5aa0709891551258ea8888d2c7bb781cdc49 Mon Sep 17 00:00:00 2001 From: klutzy Date: Sun, 7 Apr 2013 01:59:06 +0900 Subject: [PATCH 060/403] vim: disable nested comment Since comment nesting does not work from 0.4. --- src/etc/vim/syntax/rust.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 87f4059716b35..380b0f505c15e 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -110,7 +110,7 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9 syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'" -syn region rustComment start="/\*" end="\*/" contains=rustComment,rustTodo +syn region rustComment start="/\*" end="\*/" contains=rustTodo syn region rustComment start="//" skip="\\$" end="$" contains=rustTodo keepend syn keyword rustTodo contained TODO FIXME XXX NB From 7c2a8c4ac2c89a174fdcf4cc68e17e7639a913c6 Mon Sep 17 00:00:00 2001 From: klutzy Date: Sun, 7 Apr 2013 04:10:40 +0900 Subject: [PATCH 061/403] vim: add rustCommentDoc --- src/etc/vim/syntax/rust.vim | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 380b0f505c15e..75858966c5577 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -110,8 +110,11 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9 syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'" -syn region rustComment start="/\*" end="\*/" contains=rustTodo -syn region rustComment start="//" skip="\\$" end="$" contains=rustTodo keepend +syn region rustCommentDoc start="/\*\*" end="\*/" +syn region rustCommentDoc start="///" skip="\\$" end="$" keepend +syn match rustComment "/\*\*/" +syn region rustComment start="/\*[^\*]" end="\*/" contains=rustTodo +syn region rustComment start="//[^/]" skip="\\$" end="$" contains=rustTodo keepend syn keyword rustTodo contained TODO FIXME XXX NB @@ -134,6 +137,7 @@ hi def link rustConditional Conditional hi def link rustIdentifier Identifier hi def link rustModPath Include hi def link rustFuncName Function +hi def link rustCommentDoc SpecialComment hi def link rustComment Comment hi def link rustMacro Macro hi def link rustType Type From e081c17805203b5e87073e2c766280a84b08e52c Mon Sep 17 00:00:00 2001 From: gareth Date: Sun, 31 Mar 2013 21:24:58 +0100 Subject: [PATCH 062/403] Fix a bug where calling p.destroy() on the result of calling start_program(...) would cause a segfault when p went out of scope due to out_file/err_file being closed twice. --- src/libcore/run.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 98564beeba901..c6d79bd2ecd6d 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -172,6 +172,14 @@ fn with_dirp(d: &Option<~str>, } } +/// helper function that closes non-NULL files and then makes them NULL +priv unsafe fn fclose_and_null(f: &mut *libc::FILE) { + if *f != 0 as *libc::FILE { + libc::fclose(*f); + *f = 0 as *libc::FILE; + } +} + /** * Spawns a process and waits for it to terminate * @@ -249,8 +257,8 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn destroy_repr(r: &mut ProgRepr) { unsafe { finish_repr(&mut *r); - libc::fclose(r.out_file); - libc::fclose(r.err_file); + fclose_and_null(&mut r.out_file); + fclose_and_null(&mut r.err_file); } } struct ProgRes { @@ -507,6 +515,19 @@ mod tests { assert!(status == 1); } + #[test] + pub fn test_destroy_once() { + let mut p = run::start_program("echo", []); + p.destroy(); // this shouldn't crash (and nor should the destructor) + } + + #[test] + pub fn test_destroy_twice() { + let mut p = run::start_program("echo", []); + p.destroy(); // this shouldnt crash... + p.destroy(); // ...and nor should this (and nor should the destructor) + } + } // Local Variables: From 622bb6300f8b4e5a644088fe471e63b580b03453 Mon Sep 17 00:00:00 2001 From: gareth Date: Sun, 31 Mar 2013 21:30:33 +0100 Subject: [PATCH 063/403] Update doc-comments to reflect the current year and trait names now being capitalized. --- src/libcore/run.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index c6d79bd2ecd6d..1441da01460e7 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -44,13 +44,13 @@ pub trait Program { /// Returns the process id of the program fn get_id(&mut self) -> pid_t; - /// Returns an io::writer that can be used to write to stdin + /// Returns an io::Writer that can be used to write to stdin fn input(&mut self) -> @io::Writer; - /// Returns an io::reader that can be used to read from stdout + /// Returns an io::Reader that can be used to read from stdout fn output(&mut self) -> @io::Reader; - /// Returns an io::reader that can be used to read from stderr + /// Returns an io::Reader that can be used to read from stderr fn err(&mut self) -> @io::Reader; /// Closes the handle to the child processes standard input @@ -200,9 +200,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int { } /** - * Spawns a process and returns a program + * Spawns a process and returns a Program * - * The returned value is a boxed class containing a object that can + * The returned value is a boxed class containing a object that can * be used for sending and receiving data over the standard file descriptors. * The class will ensure that file descriptors are closed properly. * From 483e95a35c9f3ab01666de4808134af26fded68c Mon Sep 17 00:00:00 2001 From: gareth Date: Sat, 6 Apr 2013 20:49:52 +0100 Subject: [PATCH 064/403] Change the behaviour of core::run::Program.destroy to forcibly terminate the program (as suggested in issue #5632) --- src/libcore/libc.rs | 16 +++++++++++ src/libcore/run.rs | 66 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 95d963a36e3aa..e17a6be3f1f95 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -863,6 +863,7 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGKILL : int = 9; } pub mod posix01 { } @@ -930,6 +931,7 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGKILL : int = 9; } pub mod posix01 { } @@ -998,6 +1000,7 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGKILL : int = 9; } pub mod posix01 { } @@ -1482,6 +1485,17 @@ pub mod funcs { -> ssize_t; } } + + #[nolink] + #[abi = "cdecl"] + pub mod signal { + use libc::types::os::arch::c95::{c_int}; + use libc::types::os::arch::posix88::{pid_t}; + + pub extern { + unsafe fn kill(pid: pid_t, sig: c_int) -> c_int; + } + } } #[cfg(target_os = "linux")] @@ -1623,6 +1637,7 @@ pub mod funcs { pub mod extra { pub mod kernel32 { + use libc::types::os::arch::c95::{c_uint}; use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE}; use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH}; use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES}; @@ -1663,6 +1678,7 @@ pub mod funcs { findFileData: HANDLE) -> BOOL; unsafe fn FindClose(findFile: HANDLE) -> BOOL; + unsafe fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL; } } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 1441da01460e7..e7602cff4928d 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -62,7 +62,10 @@ pub trait Program { */ fn finish(&mut self) -> int; - /// Closes open handles + /** + * Forcibly terminate the program. On Posix OSs SIGKILL will be sent + * to the process. On Win32 TerminateProcess(..) will be called. + */ fn destroy(&mut self); } @@ -248,19 +251,43 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { r.in_fd = invalid_fd; } } + + fn close_repr_outputs(r: &mut ProgRepr) { + unsafe { + fclose_and_null(&mut r.out_file); + fclose_and_null(&mut r.err_file); + } + } + fn finish_repr(r: &mut ProgRepr) -> int { if r.finished { return 0; } r.finished = true; close_repr_input(&mut *r); return waitpid(r.pid); } + fn destroy_repr(r: &mut ProgRepr) { - unsafe { - finish_repr(&mut *r); - fclose_and_null(&mut r.out_file); - fclose_and_null(&mut r.err_file); + killpid(r.pid); + finish_repr(&mut *r); + close_repr_outputs(&mut *r); + + #[cfg(windows)] + fn killpid(pid: pid_t) { + unsafe { + libc::funcs::extra::kernel32::TerminateProcess( + cast::transmute(pid), 1); + } + } + + #[cfg(unix)] + fn killpid(pid: pid_t) { + unsafe { + libc::funcs::posix88::signal::kill( + pid, libc::consts::os::posix88::SIGKILL as c_int); + } } } + struct ProgRes { r: ProgRepr, } @@ -268,8 +295,9 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { impl Drop for ProgRes { fn finalize(&self) { unsafe { - // FIXME #4943: This is bad. - destroy_repr(cast::transmute(&self.r)); + // FIXME #4943: transmute is bad. + finish_repr(cast::transmute(&self.r)); + close_repr_outputs(cast::transmute(&self.r)); } } } @@ -295,6 +323,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn finish(&mut self) -> int { finish_repr(&mut self.r) } fn destroy(&mut self) { destroy_repr(&mut self.r); } } + let mut repr = ProgRepr { pid: pid, in_fd: pipe_input.out, @@ -466,8 +495,10 @@ pub fn waitpid(pid: pid_t) -> int { #[cfg(test)] mod tests { + use libc; use option::None; use os; + use path::Path; use run::{readclose, writeclose}; use run; @@ -528,6 +559,27 @@ mod tests { p.destroy(); // ...and nor should this (and nor should the destructor) } + #[test] + #[cfg(unix)] // there is no way to sleep on windows from inside libcore... + pub fn test_destroy_actually_kills() { + let path = Path("test/core-run-test-destroy-actually-kills.tmp"); + + os::remove_file(&path); + + let cmd = fmt!("sleep 5 && echo MurderDeathKill > %s", path.to_str()); + let mut p = run::start_program("sh", [~"-c", cmd]); + + p.destroy(); // destroy the program before it has a chance to echo its message + + unsafe { + // wait to ensure the program is really destroyed and not just waiting itself + libc::sleep(10); + } + + // the program should not have had chance to echo its message + assert!(!path.exists()); + } + } // Local Variables: From eebf29ed377189c111afe457be920b645835296c Mon Sep 17 00:00:00 2001 From: gifnksm Date: Sat, 6 Apr 2013 09:43:16 +0900 Subject: [PATCH 065/403] Impl cmp/num traits for BigUint, BigInt TotalEq, TotalOrd, FromStrRadix, ToStrRadix. --- src/libstd/num/bigint.rs | 332 ++++++++++++++++++++++----------------- 1 file changed, 187 insertions(+), 145 deletions(-) diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index 35b1a28a465cd..f15632b1431eb 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -16,8 +16,8 @@ A BigUint is represented as an array of BigDigits. A BigInt is a combination of BigUint and Sign. */ -use core::cmp::{Eq, Ord}; -use core::num::{IntConvertible, Zero, One}; +use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; +use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix}; use core::*; /** @@ -78,15 +78,46 @@ pub struct BigUint { } impl Eq for BigUint { - fn eq(&self, other: &BigUint) -> bool { self.cmp(other) == 0 } - fn ne(&self, other: &BigUint) -> bool { self.cmp(other) != 0 } + fn eq(&self, other: &BigUint) -> bool { self.equals(other) } + fn ne(&self, other: &BigUint) -> bool { !self.equals(other) } +} + +impl TotalEq for BigUint { + fn equals(&self, other: &BigUint) -> bool { + match self.cmp(other) { Equal => true, _ => false } + } } impl Ord for BigUint { - fn lt(&self, other: &BigUint) -> bool { self.cmp(other) < 0 } - fn le(&self, other: &BigUint) -> bool { self.cmp(other) <= 0 } - fn ge(&self, other: &BigUint) -> bool { self.cmp(other) >= 0 } - fn gt(&self, other: &BigUint) -> bool { self.cmp(other) > 0 } + fn lt(&self, other: &BigUint) -> bool { + match self.cmp(other) { Less => true, _ => false} + } + fn le(&self, other: &BigUint) -> bool { + match self.cmp(other) { Less | Equal => true, _ => false } + } + fn ge(&self, other: &BigUint) -> bool { + match self.cmp(other) { Greater | Equal => true, _ => false } + } + fn gt(&self, other: &BigUint) -> bool { + match self.cmp(other) { Greater => true, _ => false } + } +} + +impl TotalOrd for BigUint { + fn cmp(&self, other: &BigUint) -> Ordering { + let s_len = self.data.len(), o_len = other.data.len(); + if s_len < o_len { return Less; } + if s_len > o_len { return Greater; } + + for self.data.eachi_reverse |i, elm| { + match (*elm, other.data[i]) { + (l, r) if l < r => return Less, + (l, r) if l > r => return Greater, + _ => loop + }; + } + return Equal; + } } impl ToStr for BigUint { @@ -95,7 +126,7 @@ impl ToStr for BigUint { impl from_str::FromStr for BigUint { fn from_str(s: &str) -> Option { - BigUint::from_str_radix(s, 10) + FromStrRadix::from_str_radix(s, 10) } } @@ -189,12 +220,10 @@ impl Mul for BigUint { let mm = { let (s1, n1) = sub_sign(sHi, sLo); let (s2, n2) = sub_sign(oHi, oLo); - if s1 * s2 < 0 { - hh + ll + (n1 * n2) - } else if s1 * s2 > 0 { - hh + ll - (n1 * n2) - } else { - hh + ll + match (s1, s2) { + (Equal, _) | (_, Equal) => hh + ll, + (Less, Greater) | (Greater, Less) => hh + ll + (n1 * n2), + (Less, Less) | (Greater, Greater) => hh + ll - (n1 * n2) } }; @@ -223,11 +252,11 @@ impl Mul for BigUint { BigUint::from_slice(vec::slice(a.data, 0, mid))); } - fn sub_sign(a: BigUint, b: BigUint) -> (int, BigUint) { + fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) { match a.cmp(&b) { - s if s < 0 => (s, b - a), - s if s > 0 => (s, a - b), - _ => (0, Zero::zero()) + Less => (Less, b - a), + Greater => (Greater, a - b), + _ => (Equal, Zero::zero()) } } } @@ -261,6 +290,49 @@ impl IntConvertible for BigUint { } } +impl ToStrRadix for BigUint { + fn to_str_radix(&self, radix: uint) -> ~str { + assert!(1 < radix && radix <= 16); + let (base, max_len) = get_radix_base(radix); + if base == BigDigit::base { + return fill_concat(self.data, radix, max_len) + } + return fill_concat(convert_base(copy *self, base), radix, max_len); + + fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] { + let divider = BigUint::from_uint(base); + let mut result = ~[]; + let mut r = n; + while r > divider { + let (d, r0) = r.divmod(÷r); + result += [r0.to_uint() as BigDigit]; + r = d; + } + if r.is_not_zero() { + result += [r.to_uint() as BigDigit]; + } + return result; + } + + fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str { + if v.is_empty() { return ~"0" } + let s = str::concat(vec::reversed(v).map(|n| { + let s = uint::to_str_radix(*n as uint, radix); + str::from_chars(vec::from_elem(l - s.len(), '0')) + s + })); + str::trim_left_chars(s, ['0']).to_owned() + } + } +} + +impl FromStrRadix for BigUint { + /// Creates and initializes an BigUint. + pub fn from_str_radix(s: &str, radix: uint) + -> Option { + BigUint::parse_bytes(str::to_bytes(s), radix) + } +} + pub impl BigUint { /// Creates and initializes an BigUint. pub fn new(v: ~[BigDigit]) -> BigUint { @@ -287,12 +359,6 @@ pub impl BigUint { return BigUint::new(vec::from_slice(slice)); } - /// Creates and initializes an BigUint. - pub fn from_str_radix(s: &str, radix: uint) - -> Option { - BigUint::parse_bytes(str::to_bytes(s), radix) - } - /// Creates and initializes an BigUint. pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { @@ -318,31 +384,15 @@ pub impl BigUint { fn abs(&self) -> BigUint { copy *self } - /// Compare two BigUint value. - fn cmp(&self, other: &BigUint) -> int { - let s_len = self.data.len(), o_len = other.data.len(); - if s_len < o_len { return -1; } - if s_len > o_len { return 1; } - - for self.data.eachi_reverse |i, elm| { - match (*elm, other.data[i]) { - (l, r) if l < r => return -1, - (l, r) if l > r => return 1, - _ => loop - }; - } - return 0; - } - fn divmod(&self, other: &BigUint) -> (BigUint, BigUint) { if other.is_zero() { fail!() } if self.is_zero() { return (Zero::zero(), Zero::zero()); } if *other == One::one() { return (copy *self, Zero::zero()); } match self.cmp(other) { - s if s < 0 => return (Zero::zero(), copy *self), - 0 => return (One::one(), Zero::zero()), - _ => {} // Do nothing + Less => return (Zero::zero(), copy *self), + Equal => return (One::one(), Zero::zero()), + Greater => {} // Do nothing } let mut shift = 0; @@ -433,39 +483,6 @@ pub impl BigUint { } } - fn to_str_radix(&self, radix: uint) -> ~str { - assert!(1 < radix && radix <= 16); - let (base, max_len) = get_radix_base(radix); - if base == BigDigit::base { - return fill_concat(self.data, radix, max_len) - } - return fill_concat(convert_base(copy *self, base), radix, max_len); - - fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] { - let divider = BigUint::from_uint(base); - let mut result = ~[]; - let mut r = n; - while r > divider { - let (d, r0) = r.divmod(÷r); - result += [r0.to_uint() as BigDigit]; - r = d; - } - if r.is_not_zero() { - result += [r.to_uint() as BigDigit]; - } - return result; - } - - fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str { - if v.is_empty() { return ~"0" } - let s = str::concat(vec::reversed(v).map(|n| { - let s = uint::to_str_radix(*n as uint, radix); - str::from_chars(vec::from_elem(l - s.len(), '0')) + s - })); - str::trim_left_chars(s, ['0']).to_owned() - } - } - priv fn shl_unit(self, n_unit: uint) -> BigUint { if n_unit == 0 || self.is_zero() { return self; } @@ -561,22 +578,31 @@ priv fn get_radix_base(radix: uint) -> (uint, uint) { pub enum Sign { Minus, Zero, Plus } impl Ord for Sign { - fn lt(&self, other: &Sign) -> bool { self.cmp(other) < 0 } - fn le(&self, other: &Sign) -> bool { self.cmp(other) <= 0 } - fn ge(&self, other: &Sign) -> bool { self.cmp(other) >= 0 } - fn gt(&self, other: &Sign) -> bool { self.cmp(other) > 0 } + fn lt(&self, other: &Sign) -> bool { + match self.cmp(other) { Less => true, _ => false} + } + fn le(&self, other: &Sign) -> bool { + match self.cmp(other) { Less | Equal => true, _ => false } + } + fn ge(&self, other: &Sign) -> bool { + match self.cmp(other) { Greater | Equal => true, _ => false } + } + fn gt(&self, other: &Sign) -> bool { + match self.cmp(other) { Greater => true, _ => false } + } } -pub impl Sign { - /// Compare two Sign. - fn cmp(&self, other: &Sign) -> int { +impl TotalOrd for Sign { + fn cmp(&self, other: &Sign) -> Ordering { match (*self, *other) { - (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => 0, - (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => -1, - _ => 1 + (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => Equal, + (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => Less, + _ => Greater } } +} +impl Neg for Sign { /// Negate Sign value. fn neg(&self) -> Sign { match *self { @@ -594,15 +620,42 @@ pub struct BigInt { } impl Eq for BigInt { - fn eq(&self, other: &BigInt) -> bool { self.cmp(other) == 0 } - fn ne(&self, other: &BigInt) -> bool { self.cmp(other) != 0 } + fn eq(&self, other: &BigInt) -> bool { self.equals(other) } + fn ne(&self, other: &BigInt) -> bool { !self.equals(other) } +} + +impl TotalEq for BigInt { + fn equals(&self, other: &BigInt) -> bool { + match self.cmp(other) { Equal => true, _ => false } + } } impl Ord for BigInt { - fn lt(&self, other: &BigInt) -> bool { self.cmp(other) < 0 } - fn le(&self, other: &BigInt) -> bool { self.cmp(other) <= 0 } - fn ge(&self, other: &BigInt) -> bool { self.cmp(other) >= 0 } - fn gt(&self, other: &BigInt) -> bool { self.cmp(other) > 0 } + fn lt(&self, other: &BigInt) -> bool { + match self.cmp(other) { Less => true, _ => false} + } + fn le(&self, other: &BigInt) -> bool { + match self.cmp(other) { Less | Equal => true, _ => false } + } + fn ge(&self, other: &BigInt) -> bool { + match self.cmp(other) { Greater | Equal => true, _ => false } + } + fn gt(&self, other: &BigInt) -> bool { + match self.cmp(other) { Greater => true, _ => false } + } +} + +impl TotalOrd for BigInt { + fn cmp(&self, other: &BigInt) -> Ordering { + let scmp = self.sign.cmp(&other.sign); + if scmp != Equal { return scmp; } + + match self.sign { + Zero => Equal, + Plus => self.data.cmp(&other.data), + Minus => other.data.cmp(&self.data), + } + } } impl ToStr for BigInt { @@ -611,7 +664,7 @@ impl ToStr for BigInt { impl from_str::FromStr for BigInt { fn from_str(s: &str) -> Option { - BigInt::from_str_radix(s, 10) + FromStrRadix::from_str_radix(s, 10) } } @@ -659,12 +712,9 @@ impl Sub for BigInt { (Zero, _) => -other, (_, Zero) => copy *self, (Plus, Plus) => match self.data.cmp(&other.data) { - s if s < 0 => - BigInt::from_biguint(Minus, other.data - self.data), - s if s > 0 => - BigInt::from_biguint(Plus, self.data - other.data), - _ => - Zero::zero() + Less => BigInt::from_biguint(Minus, other.data - self.data), + Greater => BigInt::from_biguint(Plus, self.data - other.data), + Equal => Zero::zero() }, (Plus, Minus) => self + (-*other), (Minus, Plus) => -((-self) + *other), @@ -730,6 +780,24 @@ impl IntConvertible for BigInt { } } +impl ToStrRadix for BigInt { + fn to_str_radix(&self, radix: uint) -> ~str { + match self.sign { + Plus => self.data.to_str_radix(radix), + Zero => ~"0", + Minus => ~"-" + self.data.to_str_radix(radix) + } + } +} + +impl FromStrRadix for BigInt { + /// Creates and initializes an BigInt. + pub fn from_str_radix(s: &str, radix: uint) + -> Option { + BigInt::parse_bytes(str::to_bytes(s), radix) + } +} + pub impl BigInt { /// Creates and initializes an BigInt. pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt { @@ -755,12 +823,6 @@ pub impl BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } - /// Creates and initializes an BigInt. - pub fn from_str_radix(s: &str, radix: uint) - -> Option { - BigInt::parse_bytes(str::to_bytes(s), radix) - } - /// Creates and initializes an BigInt. pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { @@ -779,19 +841,6 @@ pub impl BigInt { BigInt::from_biguint(Plus, copy self.data) } - fn cmp(&self, other: &BigInt) -> int { - let ss = self.sign, os = other.sign; - if ss < os { return -1; } - if ss > os { return 1; } - - assert!(ss == os); - match ss { - Zero => 0, - Plus => self.data.cmp(&other.data), - Minus => self.data.cmp(&other.data).neg(), - } - } - fn divmod(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign let (d_ui, m_ui) = self.data.divmod(&other.data); @@ -851,21 +900,14 @@ pub impl BigInt { Minus => 0 } } - - fn to_str_radix(&self, radix: uint) -> ~str { - match self.sign { - Plus => self.data.to_str_radix(radix), - Zero => ~"0", - Minus => ~"-" + self.data.to_str_radix(radix) - } - } } #[cfg(test)] mod biguint_tests { use core::*; - use core::num::{IntConvertible, Zero, One}; + use core::num::{IntConvertible, Zero, One, FromStrRadix}; + use core::cmp::{Less, Equal, Greater}; use super::{BigUint, BigDigit}; #[test] @@ -889,8 +931,8 @@ mod biguint_tests { for vec::slice(data, i, data.len()).eachi |j0, nj| { let j = j0 + i; if i == j { - assert!(ni.cmp(nj) == 0); - assert!(nj.cmp(ni) == 0); + assert_eq!(ni.cmp(nj), Equal); + assert_eq!(nj.cmp(ni), Equal); assert!(ni == nj); assert!(!(ni != nj)); assert!(ni <= nj); @@ -898,8 +940,8 @@ mod biguint_tests { assert!(!(ni < nj)); assert!(!(ni > nj)); } else { - assert!(ni.cmp(nj) < 0); - assert!(nj.cmp(ni) > 0); + assert_eq!(ni.cmp(nj), Less); + assert_eq!(nj.cmp(ni), Greater); assert!(!(ni == nj)); assert!(ni != nj); @@ -1245,13 +1287,13 @@ mod biguint_tests { let &(n, rs) = num_pair; for rs.each |str_pair| { let &(radix, str) = str_pair; - assert!(Some(n) == BigUint::from_str_radix(str, radix)); + assert_eq!(Some(n), FromStrRadix::from_str_radix(str, radix)); } } - assert!(BigUint::from_str_radix(~"Z", 10) == None); - assert!(BigUint::from_str_radix(~"_", 2) == None); - assert!(BigUint::from_str_radix(~"-1", 10) == None); + assert_eq!(FromStrRadix::from_str_radix::(~"Z", 10), None); + assert_eq!(FromStrRadix::from_str_radix::(~"_", 2), None); + assert_eq!(FromStrRadix::from_str_radix::(~"-1", 10), None); } #[test] @@ -1266,7 +1308,7 @@ mod biguint_tests { fn check(n: uint, s: &str) { let n = factor(n); - let ans = match BigUint::from_str_radix(s, 10) { + let ans = match FromStrRadix::from_str_radix(s, 10) { Some(x) => x, None => fail!() }; assert!(n == ans); @@ -1282,9 +1324,9 @@ mod biguint_tests { #[cfg(test)] mod bigint_tests { use super::{BigInt, BigUint, BigDigit, Sign, Minus, Zero, Plus}; - use core::*; - use core::num::{IntConvertible, Zero, One}; + use core::cmp::{Less, Equal, Greater}; + use core::num::{IntConvertible, Zero, One, FromStrRadix}; #[test] fn test_from_biguint() { @@ -1311,8 +1353,8 @@ mod bigint_tests { for vec::slice(nums, i, nums.len()).eachi |j0, nj| { let j = i + j0; if i == j { - assert!(ni.cmp(nj) == 0); - assert!(nj.cmp(ni) == 0); + assert_eq!(ni.cmp(nj), Equal); + assert_eq!(nj.cmp(ni), Equal); assert!(ni == nj); assert!(!(ni != nj)); assert!(ni <= nj); @@ -1320,8 +1362,8 @@ mod bigint_tests { assert!(!(ni < nj)); assert!(!(ni > nj)); } else { - assert!(ni.cmp(nj) < 0); - assert!(nj.cmp(ni) > 0); + assert_eq!(ni.cmp(nj), Less); + assert_eq!(nj.cmp(ni), Greater); assert!(!(ni == nj)); assert!(ni != nj); @@ -1623,8 +1665,8 @@ mod bigint_tests { #[test] fn test_from_str_radix() { fn check(s: &str, ans: Option) { - let ans = ans.map(|&n| IntConvertible::from_int(n)); - assert!(BigInt::from_str_radix(s, 10) == ans); + let ans = ans.map(|&n| IntConvertible::from_int::(n)); + assert!(FromStrRadix::from_str_radix(s, 10) == ans); } check("10", Some(10)); check("1", Some(1)); From c47d80304e7b3726352183f466ab0756c24d7431 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 7 Apr 2013 00:33:10 -0400 Subject: [PATCH 066/403] cmp: derive Clone for Ordering --- src/libcore/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index a928d3bb2af1f..fa2fcd1856091 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -64,7 +64,7 @@ totaleq_impl!(i64) totaleq_impl!(int) totaleq_impl!(uint) -#[deriving(Eq)] +#[deriving(Clone, Eq)] pub enum Ordering { Less, Equal, Greater } /// Trait for types that form a total order From a3f40184bdc0d094ac76b15f66bfbf87a699a705 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 7 Apr 2013 00:49:10 -0400 Subject: [PATCH 067/403] cmp: add Ord+TotalOrd impls for Ordering itself --- src/libcore/cmp.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index fa2fcd1856091..f96575aaf414f 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -65,13 +65,31 @@ totaleq_impl!(int) totaleq_impl!(uint) #[deriving(Clone, Eq)] -pub enum Ordering { Less, Equal, Greater } +pub enum Ordering { Less = -1, Equal = 0, Greater = 1 } /// Trait for types that form a total order pub trait TotalOrd: TotalEq { fn cmp(&self, other: &Self) -> Ordering; } +impl TotalOrd for Ordering { + #[inline(always)] + fn cmp(&self, other: &Ordering) -> Ordering { + (*self as int).cmp(&(*other as int)) + } +} + +impl Ord for Ordering { + #[inline(always)] + fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } + #[inline(always)] + fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) } + #[inline(always)] + fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) } + #[inline(always)] + fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) } +} + macro_rules! totalord_impl( ($t:ty) => { impl TotalOrd for $t { @@ -180,4 +198,10 @@ mod test { assert!(5.equals(&5)); assert!(!2.equals(&17)); } + + #[test] + fn test_ordering_order() { + assert!(Less < Equal); + assert_eq!(Greater.cmp(&Less), Greater); + } } From fc26911b493eb151710e1a96578aad55596cfeb7 Mon Sep 17 00:00:00 2001 From: klutzy Date: Sun, 7 Apr 2013 14:21:00 +0900 Subject: [PATCH 068/403] vim: fix comment highlighting bug Previous commit had a bug that a line which ends with "//" or "/*" is not correctly highlighted. --- src/etc/vim/syntax/rust.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 75858966c5577..303cc0834e8ef 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -113,8 +113,8 @@ syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8 syn region rustCommentDoc start="/\*\*" end="\*/" syn region rustCommentDoc start="///" skip="\\$" end="$" keepend syn match rustComment "/\*\*/" -syn region rustComment start="/\*[^\*]" end="\*/" contains=rustTodo -syn region rustComment start="//[^/]" skip="\\$" end="$" contains=rustTodo keepend +syn region rustComment start="/\*\([^\*]\|$\)" end="\*/" contains=rustTodo +syn region rustComment start="//\([^/]\|$\)" skip="\\$" end="$" contains=rustTodo keepend syn keyword rustTodo contained TODO FIXME XXX NB From 89676d6a5960aa51ee1e6975c423e979819a407c Mon Sep 17 00:00:00 2001 From: gifnksm Date: Sun, 7 Apr 2013 19:51:34 +0900 Subject: [PATCH 069/403] libcore: fix overflow/underflow in range_step --- src/libcore/num/int-template.rs | 28 ++++++++++++++++++++++++---- src/libcore/num/uint-template.rs | 31 +++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index a3cbd9fe7e3a4..9f3fdb01f48db 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -107,11 +107,15 @@ pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) { } else if step > 0 { // ascending while i < stop { if !it(i) { break } + // avoiding overflow. break if i + step > max_value + if i > max_value - step { break; } i += step; } } else { // descending while i > stop { if !it(i) { break } + // avoiding underflow. break if i + step < min_value + if i < min_value - step { break; } i += step; } } @@ -421,10 +425,26 @@ pub fn test_ranges() { for range_step(36,30,-2) |i| { l.push(i); } - assert!(l == ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32]); + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); // None of the `fail`s should execute. for range(10,0) |_i| { diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 400417284a279..7901a6f97b155 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -78,12 +78,15 @@ pub fn range_step(start: T, if step >= 0 { while i < stop { if !it(i) { break } + // avoiding overflow. break if i + step > max_value + if i > max_value - (step as T) { break; } i += step as T; } - } - else { + } else { while i > stop { if !it(i) { break } + // avoiding underflow. break if i + step < min_value + if i < min_value + ((-step) as T) { break; } i -= -step as T; } } @@ -371,11 +374,27 @@ pub fn test_ranges() { for range_step(36,30,-2) |i| { l.push(i); } + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } - assert!(l == ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32]); + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); // None of the `fail`s should execute. for range(0,0) |_i| { From 621d45b341c8c4ed0708b47b5a046278dda0c5be Mon Sep 17 00:00:00 2001 From: zofrex Date: Sun, 7 Apr 2013 22:08:23 +0100 Subject: [PATCH 070/403] Update tutorial: 1-tuples now exist --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 902a79029725e..fe9c6297dd575 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -747,7 +747,7 @@ fn area(sh: Shape) -> float { Tuples in Rust behave exactly like structs, except that their fields do not have names. Thus, you cannot access their fields with dot notation. -Tuples can have any arity except for 0 or 1 (though you may consider +Tuples can have any arity except for 0 (though you may consider unit, `()`, as the empty tuple if you like). ~~~~ From d1e2d295f89276661367ba3fe19589b4a7934538 Mon Sep 17 00:00:00 2001 From: zofrex Date: Sun, 7 Apr 2013 22:08:34 +0100 Subject: [PATCH 071/403] Update manual for single-element tuples --- doc/rust.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index e99b3bb565d78..da4b5146f3400 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1653,11 +1653,12 @@ Path expressions are [lvalues](#lvalues-rvalues-and-temporaries). ### Tuple expressions -Tuples are written by enclosing two or more comma-separated +Tuples are written by enclosing one or more comma-separated expressions in parentheses. They are used to create [tuple-typed](#tuple-types) values. ~~~~~~~~ {.tuple} +(0,); (0f, 4.5f); ("a", 4u, true); ~~~~~~~~ From ac9e694d595a95c75fd96b149bf5e7edce366027 Mon Sep 17 00:00:00 2001 From: zofrex Date: Sun, 7 Apr 2013 22:08:40 +0100 Subject: [PATCH 072/403] Update manual for single-element tuple types --- doc/rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index da4b5146f3400..e9c88fc34121c 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -2579,7 +2579,7 @@ to the record type-constructor. The differences are as follows: Tuple types and values are denoted by listing the types or values of their elements, respectively, in a parenthesized, comma-separated -list. Single-element tuples are not legal; all tuples have two or more values. +list. The members of a tuple are laid out in memory contiguously, like a record, in order specified by the tuple type. From f0d0cbfff8d1aadda1cdb3b914361f3355c9a9cc Mon Sep 17 00:00:00 2001 From: Bryan Dunsmore Date: Sun, 7 Apr 2013 16:49:44 -0500 Subject: [PATCH 073/403] Include definition of tuples for destructuring. Updates the tutorial to include a simple definition for tuples in section 4.2. Fixes #5132. --- doc/tutorial.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 902a79029725e..1ac33fe658588 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -495,7 +495,10 @@ omitted. A powerful application of pattern matching is *destructuring*: matching in order to bind names to the contents of data -types. Assuming that `(float, float)` is a tuple of two floats: +types. + +> ***Note:*** The following code makes use of tuples (`(float, float)`) which +> are explained later. For now you can think of tuples as a list of items. ~~~~ fn angle(vector: (float, float)) -> float { From c6d67829064d9080b8561af0545bbeb1f1d3889f Mon Sep 17 00:00:00 2001 From: Pavel Panchekha Date: Sun, 7 Apr 2013 23:19:31 -0300 Subject: [PATCH 074/403] Fixed typo Change wrong field name in "Trait Inheritance" section. --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 42b0d5a585aee..3313c432e1df3 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -2288,7 +2288,7 @@ impl Shape for CircleStruct { Notice that methods of `Circle` can call methods on `Shape`, as our `radius` implementation calls the `area` method. This is a silly way to compute the radius of a circle -(since we could just return the `circle` field), but you get the idea. +(since we could just return the `radius` field), but you get the idea. In type-parameterized functions, methods of the supertrait may be called on values of subtrait-bound type parameters. From 49cdf36d2b993e08833bfdda2563b0c22ee42de7 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 8 Apr 2013 01:26:51 +1000 Subject: [PATCH 075/403] libcore: from_str_common: correctly signal failure on repeating base 2^n numbers. A number like 0b1_1111_1111 == 511 would be parsed to Some(255u8) rather than None by from_str_common, since 255 * 2 + 1 == 255 (mod 256) so the overflow wasn't detected. Only applied to conversions where the radix was a power of 2, and where all digits repeated. Closes #5770. --- src/libcore/num/strconv.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 5299203eb4273..687b6344b39b2 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -448,7 +448,7 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * - Could accept option to allow ignoring underscores, allowing for numbers * formated like `FF_AE_FF_FF`. */ -pub fn from_str_bytes_common+ +pub fn from_str_bytes_common+ Mul+Sub+Neg+Add+ NumStrConv>( buf: &[u8], radix: uint, negative: bool, fractional: bool, @@ -531,9 +531,12 @@ pub fn from_str_bytes_common+ accum -= cast(digit as int); } - // Detect overflow by comparing to last value - if accum_positive && accum < last_accum { return None; } - if !accum_positive && accum > last_accum { return None; } + // Detect overflow by comparing to last value, except + // if we've not seen any non-zero digits. + if last_accum != _0 { + if accum_positive && accum <= last_accum { return None; } + if !accum_positive && accum >= last_accum { return None; } + } last_accum = accum; } None => match c { @@ -637,7 +640,7 @@ pub fn from_str_bytes_common+ * `from_str_bytes_common()`, for details see there. */ #[inline(always)] -pub fn from_str_common+Mul+ +pub fn from_str_common+Mul+ Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool @@ -645,3 +648,19 @@ pub fn from_str_common+Mul+ from_str_bytes_common(str::to_bytes(buf), radix, negative, fractional, special, exponent, empty_zero) } + +#[cfg(test)] +mod test { + use super::*; + use option::*; + + #[test] + fn from_str_issue5770() { + // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems + // since 255*2+1 == 255 (mod 256) so the overflow wasn't + // detected. + let n : Option = from_str_common("111111111", 2, false, false, false, + ExpNone, false); + assert_eq!(n, None); + } +} From 41c6f67109ed8adee209f28ce7f9dbe1432a45bd Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 8 Apr 2013 00:23:42 +1000 Subject: [PATCH 076/403] libcore: from_str_common: provide option to ignore underscores. Implement the possible improvement listed in the comment on from_str_bytes_common. --- src/libcore/num/f32.rs | 6 ++--- src/libcore/num/f64.rs | 6 ++--- src/libcore/num/float.rs | 6 ++--- src/libcore/num/int-template.rs | 6 ++--- src/libcore/num/strconv.rs | 38 ++++++++++++++++++++++++-------- src/libcore/num/uint-template.rs | 6 ++--- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 6361a6a5cb75e..fa82001151e2a 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -507,7 +507,7 @@ impl num::ToStrRadix for f32 { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -540,7 +540,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -565,7 +565,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for f32 { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 9e731e61ec49e..67dfabacd0b0e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -529,7 +529,7 @@ impl num::ToStrRadix for f64 { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -562,7 +562,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -587,7 +587,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for f64 { diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index c80d52f496b49..2508292970303 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -242,7 +242,7 @@ impl num::ToStrRadix for float { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -275,7 +275,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -300,7 +300,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, radix: uint) -> Option { strconv::from_str_common(num, radix, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for float { diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index a3cbd9fe7e3a4..db90ec7946537 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -202,21 +202,21 @@ impl ops::Neg for T { #[inline(always)] pub fn from_str(s: &str) -> Option { strconv::from_str_common(s, 10u, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. #[inline(always)] pub fn from_str_radix(s: &str, radix: uint) -> Option { strconv::from_str_common(s, radix, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { strconv::from_str_bytes_common(buf, radix, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl FromStr for T { diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 687b6344b39b2..95da5bc29f5df 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -429,6 +429,8 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * `FFp128`. The exponent string itself is always base 10. * Can conflict with `radix`, see Failure. * - `empty_zero` - Whether to accept a empty `buf` as a 0 or not. + * - `ignore_underscores` - Whether all underscores within the string should + * be ignored. * * # Return value * Returns `Some(n)` if `buf` parses to a number n without overflowing, and @@ -443,16 +445,13 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * between digit and exponent sign `'p'`. * - Fails if `radix` > 18 and `special == true` due to conflict * between digit and lowest first character in `inf` and `NaN`, the `'i'`. - * - * # Possible improvements - * - Could accept option to allow ignoring underscores, allowing for numbers - * formated like `FF_AE_FF_FF`. */ pub fn from_str_bytes_common+ Mul+Sub+Neg+Add+ NumStrConv>( buf: &[u8], radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool + special: bool, exponent: ExponentFormat, empty_zero: bool, + ignore_underscores: bool ) -> Option { match exponent { ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' @@ -540,6 +539,7 @@ pub fn from_str_bytes_common+ last_accum = accum; } None => match c { + '_' if ignore_underscores => {} 'e' | 'E' | 'p' | 'P' => { exp_found = true; break; // start of exponent @@ -583,6 +583,7 @@ pub fn from_str_bytes_common+ last_accum = accum; } None => match c { + '_' if ignore_underscores => {} 'e' | 'E' | 'p' | 'P' => { exp_found = true; break; // start of exponent @@ -610,6 +611,7 @@ pub fn from_str_bytes_common+ if exp_found { let c = buf[i] as char; let base = match (c, exponent) { + // c is never _ so don't need to handle specially ('e', ExpDec) | ('E', ExpDec) => 10u, ('p', ExpBin) | ('P', ExpBin) => 2u, _ => return None // char doesn't fit given exponent format @@ -618,7 +620,8 @@ pub fn from_str_bytes_common+ // parse remaining bytes as decimal integer, // skipping the exponent char let exp: Option = from_str_bytes_common( - buf.slice(i+1, len), 10, true, false, false, ExpNone, false); + buf.slice(i+1, len), 10, true, false, false, ExpNone, false, + ignore_underscores); match exp { Some(exp_pow) => { @@ -643,10 +646,12 @@ pub fn from_str_bytes_common+ pub fn from_str_common+Mul+ Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool + special: bool, exponent: ExponentFormat, empty_zero: bool, + ignore_underscores: bool ) -> Option { from_str_bytes_common(str::to_bytes(buf), radix, negative, - fractional, special, exponent, empty_zero) + fractional, special, exponent, empty_zero, + ignore_underscores) } #[cfg(test)] @@ -654,13 +659,28 @@ mod test { use super::*; use option::*; + #[test] + fn from_str_ignore_underscores() { + let s : Option = from_str_common("__1__", 2, false, false, false, + ExpNone, false, true); + assert_eq!(s, Some(1u8)); + + let n : Option = from_str_common("__1__", 2, false, false, false, + ExpNone, false, false); + assert_eq!(n, None); + + let f : Option = from_str_common("_1_._1_e_1_", 10, false, true, false, + ExpDec, false, true); + assert_eq!(f, Some(1.1e1f32)); + } + #[test] fn from_str_issue5770() { // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems // since 255*2+1 == 255 (mod 256) so the overflow wasn't // detected. let n : Option = from_str_common("111111111", 2, false, false, false, - ExpNone, false); + ExpNone, false, false); assert_eq!(n, None); } } diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 400417284a279..39af025217c93 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -168,21 +168,21 @@ impl ops::Neg for T { #[inline(always)] pub fn from_str(s: &str) -> Option { strconv::from_str_common(s, 10u, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. #[inline(always)] pub fn from_str_radix(s: &str, radix: uint) -> Option { strconv::from_str_common(s, radix, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { strconv::from_str_bytes_common(buf, radix, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl FromStr for T { From 0c2ceb1a2e93e2e7624d384e19da6783cbb720ba Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 8 Apr 2013 00:39:28 +1000 Subject: [PATCH 077/403] libsyntax: fail lexing with an error message on an int literal larger than 2^64. Stops an ICE. Closes #5544. --- src/libsyntax/parse/lexer.rs | 11 +++++++++-- src/test/compile-fail/issue-5544-a.rs | 14 ++++++++++++++ src/test/compile-fail/issue-5544-b.rs | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/issue-5544-a.rs create mode 100644 src/test/compile-fail/issue-5544-b.rs diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 5e06ecf60908e..b6ec15d86413b 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -442,7 +442,11 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { if str::len(num_str) == 0u { rdr.fatal(~"no valid digits found for number"); } - let parsed = u64::from_str_radix(num_str, base as uint).get(); + let parsed = match u64::from_str_radix(num_str, base as uint) { + Some(p) => p, + None => rdr.fatal(~"int literal is too large") + }; + match tp { either::Left(t) => return token::LIT_INT(parsed as i64, t), either::Right(t) => return token::LIT_UINT(parsed, t) @@ -503,7 +507,10 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { if str::len(num_str) == 0u { rdr.fatal(~"no valid digits found for number"); } - let parsed = u64::from_str_radix(num_str, base as uint).get(); + let parsed = match u64::from_str_radix(num_str, base as uint) { + Some(p) => p, + None => rdr.fatal(~"int literal is too large") + }; debug!("lexing %s as an unsuffixed integer literal", num_str); diff --git a/src/test/compile-fail/issue-5544-a.rs b/src/test/compile-fail/issue-5544-a.rs new file mode 100644 index 0000000000000..42a18ba5fb765 --- /dev/null +++ b/src/test/compile-fail/issue-5544-a.rs @@ -0,0 +1,14 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _i = 18446744073709551616; // 2^64 + //~^ ERROR int literal is too large +} diff --git a/src/test/compile-fail/issue-5544-b.rs b/src/test/compile-fail/issue-5544-b.rs new file mode 100644 index 0000000000000..bbe43e652a800 --- /dev/null +++ b/src/test/compile-fail/issue-5544-b.rs @@ -0,0 +1,14 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _i = 0xff_ffff_ffff_ffff_ffff; + //~^ ERROR int literal is too large +} From 0ca1885da133cb7e4a1f4d557cfde5d16ac68231 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sat, 6 Apr 2013 14:01:56 -0700 Subject: [PATCH 078/403] Feed enum field offsets to type vistors. --- src/libcore/reflect.rs | 14 +++++++++-- src/libcore/repr.rs | 27 ++++++++++++++++++++- src/librustc/front/intrinsic.rs | 2 +- src/librustc/middle/trans/reflect.rs | 32 +++++++++++++++---------- src/test/run-pass/reflect-visit-data.rs | 6 ++--- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index a449c4e73cf7e..a38e51b38134b 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -406,7 +406,7 @@ impl TyVisitor for MovePtrAdaptor { disr_val: int, n_fields: uint, name: &str) -> bool { - self.inner.push_ptr(); + self.inner.push_ptr(); // NOTE remove after next snapshot if ! self.inner.visit_enter_enum_variant(variant, disr_val, n_fields, name) { return false; @@ -414,6 +414,7 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(stage0)] fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { unsafe { self.align((*inner).align); } if ! self.inner.visit_enum_variant_field(i, inner) { return false; } @@ -421,6 +422,15 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(not(stage0))] + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + self.inner.push_ptr(); + self.bump(offset); + if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } + self.inner.pop_ptr(); + true + } + fn visit_leave_enum_variant(&self, variant: uint, disr_val: int, n_fields: uint, @@ -429,7 +439,7 @@ impl TyVisitor for MovePtrAdaptor { n_fields, name) { return false; } - self.inner.pop_ptr(); + self.inner.pop_ptr(); // NOTE remove after next snapshot true } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index a51f874f3712c..3d42f06483178 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -193,6 +193,14 @@ pub impl ReprVisitor { self.bump(sys::size_of::()); } + #[cfg(stage0)] #[inline(always)] + fn stage0_bump_past(&self) { + self.bump_past::(); + } + #[cfg(not(stage0))] #[inline(always)] + fn stage0_bump_past(&self) { + } + #[inline(always)] fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(self.ptr, inner) @@ -487,7 +495,7 @@ impl TyVisitor for ReprVisitor { self.var_stk.push(TagMismatch); } }; - self.bump_past::(); + self.stage0_bump_past::(); } } @@ -500,6 +508,7 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(stage0)] fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { Degenerate | TagMatch => { @@ -515,6 +524,22 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(not(stage0))] + fn visit_enum_variant_field(&self, i: uint, _offset: uint, inner: *TyDesc) -> bool { + match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { + Degenerate | TagMatch => { + if i != 0 { + self.writer.write_str(", "); + } + if ! self.visit_inner(inner) { + return false; + } + } + TagMismatch => () + } + true + } + fn visit_leave_enum_variant(&self, _variant: uint, _disr_val: int, n_fields: uint, diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index 7d5177a6dfb5d..7a07ce1251616 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -96,7 +96,7 @@ pub mod intrinsic { disr_val: int, n_fields: uint, name: &str) -> bool; - fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool; + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool; fn visit_leave_enum_variant(&self, variant: uint, disr_val: int, n_fields: uint, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 224981d6e759a..9d62231905eea 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -10,6 +10,7 @@ use lib::llvm::{TypeRef, ValueRef}; +use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee::{ArgVals, DontAutorefArg}; @@ -266,23 +267,28 @@ pub impl Reflector { // variant? ty::ty_enum(did, ref substs) => { let bcx = self.bcx; - let tcx = bcx.ccx().tcx; - let variants = ty::substd_enum_variants(tcx, did, substs); + let ccx = bcx.ccx(); + let repr = adt::represent_type(bcx.ccx(), t); + let variants = ty::substd_enum_variants(ccx.tcx, did, substs); - let extra = ~[self.c_uint(vec::len(variants))] + let enum_args = ~[self.c_uint(vec::len(variants))] + self.c_size_and_align(t); - do self.bracketed(~"enum", extra) |this| { + do self.bracketed(~"enum", enum_args) |this| { for variants.eachi |i, v| { - let extra1 = ~[this.c_uint(i), - this.c_int(v.disr_val), - this.c_uint(vec::len(v.args)), - this.c_slice( - bcx.ccx().sess.str_of(v.name))]; - do this.bracketed(~"enum_variant", extra1) |this| { + let variant_args = ~[this.c_uint(i), + this.c_int(v.disr_val), + this.c_uint(vec::len(v.args)), + this.c_slice(ccx.sess.str_of(v.name))]; + do this.bracketed(~"enum_variant", variant_args) |this| { for v.args.eachi |j, a| { - let extra = ~[this.c_uint(j), - this.c_tydesc(*a)]; - this.visit(~"enum_variant_field", extra); + let bcx = this.bcx; + let null = C_null(T_ptr(type_of(ccx, t))); + let offset = p2i(ccx, adt::trans_field_ptr(bcx, repr, null, + v.disr_val, j)); + let field_args = ~[this.c_uint(j), + offset, + this.c_tydesc(*a)]; + this.visit(~"enum_variant_field", field_args); } } } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index a27599e6ed00a..8ddc845f50cbc 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -394,8 +394,8 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enum_variant_field(&self, i: uint, inner: *TyDesc) -> bool { - if ! self.inner.visit_enum_variant_field(i, inner) { return false; } + fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool { + if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; } true } @@ -594,7 +594,7 @@ impl TyVisitor for my_visitor { _disr_val: int, _n_fields: uint, _name: &str) -> bool { true } - fn visit_enum_variant_field(&self, _i: uint, inner: *TyDesc) -> bool { + fn visit_enum_variant_field(&self, _i: uint, _offset: uint, inner: *TyDesc) -> bool { self.visit_inner(inner) } fn visit_leave_enum_variant(&self, _variant: uint, From 640e8ae4e583057e7a4e694063bf704c02f816c1 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sat, 6 Apr 2013 16:47:01 -0700 Subject: [PATCH 079/403] Export adt::trans_get_discr abstractly to the type visitor. --- src/libcore/reflect.rs | 26 +++++++ src/libcore/repr.rs | 94 +++++++++++++++++++++---- src/librustc/front/intrinsic.rs | 5 ++ src/librustc/middle/trans/reflect.rs | 31 ++++++-- src/test/run-pass/reflect-visit-data.rs | 16 +++-- 5 files changed, 150 insertions(+), 22 deletions(-) diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index a38e51b38134b..9a0526b4351ba 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -15,6 +15,7 @@ Runtime type reflection */ use intrinsic::{TyDesc, TyVisitor}; +#[cfg(not(stage0))] use intrinsic::Opaque; use libc::c_void; use sys; use vec; @@ -393,6 +394,7 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(stage0)] fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint) -> bool { self.align(align); @@ -402,6 +404,18 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(not(stage0))] + fn visit_enter_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) + -> bool { + self.align(align); + if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { + return false; + } + true + } + fn visit_enter_enum_variant(&self, variant: uint, disr_val: int, n_fields: uint, @@ -443,6 +457,7 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(stage0)] fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint) -> bool { if ! self.inner.visit_leave_enum(n_variants, sz, align) { @@ -452,6 +467,17 @@ impl TyVisitor for MovePtrAdaptor { true } + #[cfg(not(stage0))] + fn visit_leave_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool { + if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { + return false; + } + self.bump(sz); + true + } + fn visit_trait(&self) -> bool { self.align_to::<@TyVisitor>(); if ! self.inner.visit_trait() { return false; } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 3d42f06483178..30ae3c3b8331e 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -18,6 +18,7 @@ use cast::transmute; use char; use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; +#[cfg(not(stage0))] use intrinsic::Opaque; use io::{Writer, WriterUtil}; use libc::c_void; use managed; @@ -137,12 +138,20 @@ impl Repr for char { // New implementation using reflect::MovePtr +#[cfg(stage0)] enum VariantState { Degenerate, TagMatch, TagMismatch, } +#[cfg(not(stage0))] +enum VariantState { + SearchingFor(int), + Matched, + AlreadyFound +} + pub struct ReprVisitor { mut ptr: *c_void, mut ptr_stk: ~[*c_void], @@ -181,26 +190,18 @@ pub impl ReprVisitor { true } - #[inline(always)] + #[cfg(stage0)] #[inline(always)] fn bump(&self, sz: uint) { do self.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } - #[inline(always)] + #[cfg(stage0)] #[inline(always)] fn bump_past(&self) { self.bump(sys::size_of::()); } - #[cfg(stage0)] #[inline(always)] - fn stage0_bump_past(&self) { - self.bump_past::(); - } - #[cfg(not(stage0))] #[inline(always)] - fn stage0_bump_past(&self) { - } - #[inline(always)] fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(self.ptr, inner) @@ -466,6 +467,7 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(stage0)] fn visit_enter_enum(&self, n_variants: uint, _sz: uint, _align: uint) -> bool { if n_variants == 1 { @@ -476,6 +478,16 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(not(stage0))] + fn visit_enter_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + _sz: uint, _align: uint) -> bool { + let disr = unsafe { get_disr(transmute(self.ptr)) }; + self.var_stk.push(SearchingFor(disr)); + true + } + + #[cfg(stage0)] fn visit_enter_enum_variant(&self, _variant: uint, disr_val: int, n_fields: uint, @@ -495,7 +507,36 @@ impl TyVisitor for ReprVisitor { self.var_stk.push(TagMismatch); } }; - self.stage0_bump_past::(); + self.bump_past::(); + } + } + + if write { + self.writer.write_str(name); + if n_fields > 0 { + self.writer.write_char('('); + } + } + true + } + + #[cfg(not(stage0))] + fn visit_enter_enum_variant(&self, _variant: uint, + disr_val: int, + n_fields: uint, + name: &str) -> bool { + let mut write = false; + match self.var_stk.pop() { + SearchingFor(sought) => { + if disr_val == sought { + self.var_stk.push(Matched); + write = true; + } else { + self.var_stk.push(SearchingFor(sought)); + } + } + Matched | AlreadyFound => { + self.var_stk.push(AlreadyFound); } } @@ -527,7 +568,7 @@ impl TyVisitor for ReprVisitor { #[cfg(not(stage0))] fn visit_enum_variant_field(&self, i: uint, _offset: uint, inner: *TyDesc) -> bool { match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { - Degenerate | TagMatch => { + Matched => { if i != 0 { self.writer.write_str(", "); } @@ -535,11 +576,12 @@ impl TyVisitor for ReprVisitor { return false; } } - TagMismatch => () + _ => () } true } + #[cfg(stage0)] fn visit_leave_enum_variant(&self, _variant: uint, _disr_val: int, n_fields: uint, @@ -555,8 +597,34 @@ impl TyVisitor for ReprVisitor { true } + #[cfg(not(stage0))] + fn visit_leave_enum_variant(&self, _variant: uint, + _disr_val: int, + n_fields: uint, + _name: &str) -> bool { + match self.var_stk[vec::uniq_len(&const self.var_stk) - 1] { + Matched => { + if n_fields > 0 { + self.writer.write_char(')'); + } + } + _ => () + } + true + } + + #[cfg(stage0)] + fn visit_leave_enum(&self, _n_variants: uint, + _sz: uint, _align: uint) -> bool { + self.var_stk.pop(); + true + } + + #[cfg(not(stage0))] fn visit_leave_enum(&self, _n_variants: uint, + _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { + // NOTE should this assert that it's not still SearchingFor the right variant? self.var_stk.pop(); true } diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index 7a07ce1251616..ccb7e3ffd55fc 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -28,6 +28,9 @@ pub mod intrinsic { // Remaining fields not listed } + // FIXME: make this a 0-variant enum; trans/reflect.rs has to match it. + pub type Opaque = (); + pub trait TyVisitor { fn visit_bot(&self) -> bool; fn visit_nil(&self) -> bool; @@ -91,6 +94,7 @@ pub mod intrinsic { sz: uint, align: uint) -> bool; fn visit_enter_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool; fn visit_enter_enum_variant(&self, variant: uint, disr_val: int, @@ -102,6 +106,7 @@ pub mod intrinsic { n_fields: uint, name: &str) -> bool; fn visit_leave_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, sz: uint, align: uint) -> bool; fn visit_enter_fn(&self, purity: uint, proto: uint, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 9d62231905eea..163fc7b84e7a4 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use lib::llvm::{TypeRef, ValueRef}; +use back::link::mangle_internal_name_by_path_and_seq; +use lib::llvm::{TypeRef, ValueRef, llvm}; use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; @@ -25,10 +25,13 @@ use middle::trans::type_of::*; use middle::ty; use util::ppaux::ty_to_str; +use core::libc::c_uint; use core::option::None; use core::vec; use syntax::ast::def_id; use syntax::ast; +use syntax::ast_map::path_name; +use syntax::parse::token::special_idents; pub struct Reflector { visitor_val: ValueRef, @@ -270,8 +273,28 @@ pub impl Reflector { let ccx = bcx.ccx(); let repr = adt::represent_type(bcx.ccx(), t); let variants = ty::substd_enum_variants(ccx.tcx, did, substs); + let llptrty = T_ptr(type_of(ccx, t)); + + // Build the get_disr function. (XXX: break this out into a function) + let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; + let get_disr_sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); + let get_disr_args = [ty::arg { mode: ast::expl(ast::by_copy), + ty: ty::mk_nil_ptr(ccx.tcx) }]; + let get_disr_llfty = type_of_fn(ccx, get_disr_args, ty::mk_int(ccx.tcx)); + let get_disr_llfdecl = decl_internal_cdecl_fn(ccx.llmod, get_disr_sym, get_disr_llfty); + let get_disr_arg = unsafe { + llvm::LLVMGetParam(get_disr_llfdecl, first_real_arg as c_uint) + }; + let get_disr_fcx = new_fn_ctxt(ccx, ~[], get_disr_llfdecl, None); + let get_disr_bcx = top_scope_block(get_disr_fcx, None); + let get_disr_arg = BitCast(get_disr_bcx, get_disr_arg, llptrty); + let get_disr_ret = adt::trans_get_discr(get_disr_bcx, repr, get_disr_arg); + Store(get_disr_bcx, get_disr_ret, get_disr_fcx.llretptr); + cleanup_and_Br(get_disr_bcx, get_disr_bcx, get_disr_fcx.llreturn); + finish_fn(get_disr_fcx, get_disr_bcx.llbb); - let enum_args = ~[self.c_uint(vec::len(variants))] + let enum_args = ~[self.c_uint(vec::len(variants)), + get_disr_llfdecl] + self.c_size_and_align(t); do self.bracketed(~"enum", enum_args) |this| { for variants.eachi |i, v| { @@ -282,7 +305,7 @@ pub impl Reflector { do this.bracketed(~"enum_variant", variant_args) |this| { for v.args.eachi |j, a| { let bcx = this.bcx; - let null = C_null(T_ptr(type_of(ccx, t))); + let null = C_null(llptrty); let offset = p2i(ccx, adt::trans_field_ptr(bcx, repr, null, v.disr_val, j)); let field_args = ~[this.c_uint(j), diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 8ddc845f50cbc..8f3a1dd90c24c 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -13,7 +13,7 @@ use core::bool; use core::libc::c_void; use core::vec::UnboxedVecRepr; -use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; +use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque}; #[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."] @@ -376,10 +376,12 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_enter_enum(&self, n_variants: uint, sz: uint, align: uint) + fn visit_enter_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool { self.align(align); - if ! self.inner.visit_enter_enum(n_variants, sz, align) { return false; } + if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) { return false; } true } @@ -410,9 +412,11 @@ impl TyVisitor for ptr_visit_adaptor { true } - fn visit_leave_enum(&self, n_variants: uint, sz: uint, align: uint) + fn visit_leave_enum(&self, n_variants: uint, + get_disr: extern unsafe fn(ptr: *Opaque) -> int, + sz: uint, align: uint) -> bool { - if ! self.inner.visit_leave_enum(n_variants, sz, align) { return false; } + if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) { return false; } true } @@ -586,6 +590,7 @@ impl TyVisitor for my_visitor { _sz: uint, _align: uint) -> bool { true } fn visit_enter_enum(&self, _n_variants: uint, + _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { // FIXME (#3732): this needs to rewind between enum variants, or something. true @@ -602,6 +607,7 @@ impl TyVisitor for my_visitor { _n_fields: uint, _name: &str) -> bool { true } fn visit_leave_enum(&self, _n_variants: uint, + _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { true } fn visit_enter_fn(&self, _purity: uint, _proto: uint, From 2589eba957ee5632dc9060022b5ca09cbfb782f9 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 20:26:48 -0700 Subject: [PATCH 080/403] When repr'ing an enum value, assert that it matched some variant. --- src/libcore/repr.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 30ae3c3b8331e..530f80ef764cd 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -624,9 +624,10 @@ impl TyVisitor for ReprVisitor { fn visit_leave_enum(&self, _n_variants: uint, _get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { - // NOTE should this assert that it's not still SearchingFor the right variant? - self.var_stk.pop(); - true + match self.var_stk.pop() { + SearchingFor(*) => fail!(~"enum value matched no variant"), + _ => true + } } fn visit_enter_fn(&self, _purity: uint, _proto: uint, From 04b2c26f39782ba30ad8868f971d5d8a606fcf88 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 20:47:44 -0700 Subject: [PATCH 081/403] Make the enum visit callback generator more readable --- src/librustc/middle/trans/reflect.rs | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 163fc7b84e7a4..e64914afd88cc 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -275,26 +275,27 @@ pub impl Reflector { let variants = ty::substd_enum_variants(ccx.tcx, did, substs); let llptrty = T_ptr(type_of(ccx, t)); - // Build the get_disr function. (XXX: break this out into a function) - let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; - let get_disr_sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); - let get_disr_args = [ty::arg { mode: ast::expl(ast::by_copy), - ty: ty::mk_nil_ptr(ccx.tcx) }]; - let get_disr_llfty = type_of_fn(ccx, get_disr_args, ty::mk_int(ccx.tcx)); - let get_disr_llfdecl = decl_internal_cdecl_fn(ccx.llmod, get_disr_sym, get_disr_llfty); - let get_disr_arg = unsafe { - llvm::LLVMGetParam(get_disr_llfdecl, first_real_arg as c_uint) + let make_get_disr = || { + let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; + let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); + let args = [ty::arg { mode: ast::expl(ast::by_copy), + ty: ty::mk_nil_ptr(ccx.tcx) }]; + let llfty = type_of_fn(ccx, args, ty::mk_int(ccx.tcx)); + let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); + let arg = unsafe { + llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) + }; + let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None); + let bcx = top_scope_block(fcx, None); + let arg = BitCast(bcx, arg, llptrty); + let ret = adt::trans_get_discr(bcx, repr, arg); + Store(bcx, ret, fcx.llretptr); + cleanup_and_Br(bcx, bcx, fcx.llreturn); + finish_fn(fcx, bcx.llbb); + llfdecl }; - let get_disr_fcx = new_fn_ctxt(ccx, ~[], get_disr_llfdecl, None); - let get_disr_bcx = top_scope_block(get_disr_fcx, None); - let get_disr_arg = BitCast(get_disr_bcx, get_disr_arg, llptrty); - let get_disr_ret = adt::trans_get_discr(get_disr_bcx, repr, get_disr_arg); - Store(get_disr_bcx, get_disr_ret, get_disr_fcx.llretptr); - cleanup_and_Br(get_disr_bcx, get_disr_bcx, get_disr_fcx.llreturn); - finish_fn(get_disr_fcx, get_disr_bcx.llbb); - let enum_args = ~[self.c_uint(vec::len(variants)), - get_disr_llfdecl] + let enum_args = ~[self.c_uint(vec::len(variants)), make_get_disr()] + self.c_size_and_align(t); do self.bracketed(~"enum", enum_args) |this| { for variants.eachi |i, v| { From e9a52f5af576ffd517284813858b6d06910460ea Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 22:35:26 -0700 Subject: [PATCH 082/403] Make intrinsic::Opaque more opaque --- src/librustc/front/intrinsic.rs | 3 +-- src/librustc/middle/trans/reflect.rs | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index ccb7e3ffd55fc..dcf300bd31da6 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -28,8 +28,7 @@ pub mod intrinsic { // Remaining fields not listed } - // FIXME: make this a 0-variant enum; trans/reflect.rs has to match it. - pub type Opaque = (); + pub enum Opaque { } pub trait TyVisitor { fn visit_bot(&self) -> bool; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index e64914afd88cc..596c55a68f872 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -274,12 +274,15 @@ pub impl Reflector { let repr = adt::represent_type(bcx.ccx(), t); let variants = ty::substd_enum_variants(ccx.tcx, did, substs); let llptrty = T_ptr(type_of(ccx, t)); + let (_, opaquety) = *(ccx.tcx.intrinsic_defs.find(&ccx.sess.ident_of(~"Opaque")) + .expect("Failed to resolve intrinsic::Opaque")); + let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm }); let make_get_disr = || { let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); let args = [ty::arg { mode: ast::expl(ast::by_copy), - ty: ty::mk_nil_ptr(ccx.tcx) }]; + ty: opaqueptrty }]; let llfty = type_of_fn(ccx, args, ty::mk_int(ccx.tcx)); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); let arg = unsafe { From 2190efb3ca86db7f45cb0ec9d5744b8f2491fd0b Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Mon, 8 Apr 2013 10:15:12 +0200 Subject: [PATCH 083/403] Put AUTHORS.txt file in the release tarball --- mk/dist.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/dist.mk b/mk/dist.mk index 92989d157b429..f71abc48620d1 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -18,6 +18,7 @@ PKG_FILES := \ $(S)COPYRIGHT \ $(S)LICENSE-APACHE \ $(S)LICENSE-MIT \ + $(S)AUTHORS.txt \ $(S)README.md \ $(S)configure $(S)Makefile.in \ $(S)man \ From a5c931cc61a6d84bf4d1a261137f687f986a79a4 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Mon, 8 Apr 2013 10:19:16 +0200 Subject: [PATCH 084/403] Update license terms in manpage --- man/rustc.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/rustc.1 b/man/rustc.1 index 14d2cad86d017..9ed98c142943b 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -170,5 +170,5 @@ See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare <\fIgraydon@mozilla.com\fR> is the project leader. .SH "COPYRIGHT" -This work is licensed under MIT-like terms. See \fBLICENSE.txt\fR -in the rust source distribution. +This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR +file in the rust source distribution. From 68d17bca4b12f514331322f938b56331f987ad68 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 6 Apr 2013 20:35:11 -0400 Subject: [PATCH 085/403] clone: managed boxes need to clone by shallow copy Performing a deep copy isn't ever desired for a persistent data structure, and it requires a more complex implementation to do correctly. A deep copy needs to check for cycles to avoid an infinite loop. --- src/libcore/clone.rs | 30 ++++++++++++------- .../borrowck-borrow-from-expr-block.rs | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index c4b5bb8d98bbc..9da970918b0d5 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -14,7 +14,7 @@ In Rust, some simple types are "implicitly copyable" and when you assign them or pass them as arguments, the receiver will get a copy, leaving the original value in place. These types do not require allocation to copy and do not have finalizers (i.e. they do not -contain owned pointers or implement `Drop`), so the compiler considers +contain owned boxes or implement `Drop`), so the compiler considers them cheap and safe to copy and automatically implements the `Copy` trait for them. For other types copies must be made explicitly, by convention implementing the `Clone` trait and calling the @@ -23,32 +23,38 @@ by convention implementing the `Clone` trait and calling the */ pub trait Clone { + /// Return a deep copy of the owned object tree. Managed boxes are cloned with a shallow copy. fn clone(&self) -> Self; } impl Clone for () { + /// Return a copy of the value. #[inline(always)] fn clone(&self) -> () { () } } impl Clone for ~T { + /// Return a deep copy of the owned box. #[inline(always)] fn clone(&self) -> ~T { ~(**self).clone() } } -impl Clone for @T { +impl Clone for @T { + /// Return a shallow copy of the managed box. #[inline(always)] - fn clone(&self) -> @T { @(**self).clone() } + fn clone(&self) -> @T { *self } } -impl Clone for @mut T { +impl Clone for @mut T { + /// Return a shallow copy of the managed box. #[inline(always)] - fn clone(&self) -> @mut T { @mut (**self).clone() } + fn clone(&self) -> @mut T { *self } } macro_rules! clone_impl( ($t:ty) => { impl Clone for $t { + /// Return a copy of the value. #[inline(always)] fn clone(&self) -> $t { *self } } @@ -76,21 +82,23 @@ clone_impl!(char) #[test] fn test_owned_clone() { - let a : ~int = ~5i; - let b : ~int = a.clone(); + let a: ~int = ~5i; + let b: ~int = a.clone(); assert!(a == b); } #[test] fn test_managed_clone() { - let a : @int = @5i; - let b : @int = a.clone(); + let a: @int = @5i; + let b: @int = a.clone(); assert!(a == b); } #[test] fn test_managed_mut_clone() { - let a : @int = @5i; - let b : @int = a.clone(); + let a: @mut int = @mut 5i; + let b: @mut int = a.clone(); + assert!(a == b); + *b = 10; assert!(a == b); } diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index 077de5c7eb125..afa312ea35e7e 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -13,7 +13,7 @@ fn borrow(x: &int, f: &fn(x: &int)) { } fn test1(x: @~int) { - do borrow(&**x.clone()) |p| { + do borrow(&*(*x).clone()) |p| { let x_a = ptr::addr_of(&(**x)); assert!((x_a as uint) != ptr::to_uint(p)); assert!(unsafe{*x_a} == *p); From 3136fba5aeca9184c944829596b93e45886fecf2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 24 Mar 2013 12:41:19 -0400 Subject: [PATCH 086/403] Removing some mutable fields in libstd --- src/libstd/arc.rs | 2 +- src/libstd/json.rs | 36 +++++++++---------- src/libstd/num/complex.rs | 1 - src/libstd/rope.rs | 73 +++++++++++++++++++-------------------- src/libstd/sync.rs | 3 +- src/libstd/task_pool.rs | 7 ++-- src/libstd/test.rs | 61 ++++++++++++++++---------------- 7 files changed, 91 insertions(+), 92 deletions(-) diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index ac8dd1a5d6523..585ce2dc81500 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -259,7 +259,7 @@ struct RWARCInner { lock: RWlock, failed: bool, data: T } */ struct RWARC { x: SharedMutableState>, - mut cant_nest: () + cant_nest: () } /// Create a reader/writer ARC with the supplied data. diff --git a/src/libstd/json.rs b/src/libstd/json.rs index f426b74736ad3..5a2bfd2113b90 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -360,9 +360,9 @@ pub fn to_pretty_str(json: &Json) -> ~str { pub struct Parser { priv rdr: @io::Reader, - priv mut ch: char, - priv mut line: uint, - priv mut col: uint, + priv ch: char, + priv line: uint, + priv col: uint, } /// Decode a json value from an io::reader @@ -376,7 +376,7 @@ pub fn Parser(rdr: @io::Reader) -> Parser { } pub impl Parser { - fn parse(&self) -> Result { + fn parse(&mut self) -> Result { match self.parse_value() { Ok(value) => { // Skip trailing whitespaces. @@ -396,7 +396,7 @@ pub impl Parser { priv impl Parser { fn eof(&self) -> bool { self.ch == -1 as char } - fn bump(&self) { + fn bump(&mut self) { self.ch = self.rdr.read_char(); if self.ch == '\n' { @@ -407,7 +407,7 @@ priv impl Parser { } } - fn next_char(&self) -> char { + fn next_char(&mut self) -> char { self.bump(); self.ch } @@ -416,7 +416,7 @@ priv impl Parser { Err(Error { line: self.line, col: self.col, msg: @msg }) } - fn parse_value(&self) -> Result { + fn parse_value(&mut self) -> Result { self.parse_whitespace(); if self.eof() { return self.error(~"EOF while parsing value"); } @@ -437,11 +437,11 @@ priv impl Parser { } } - fn parse_whitespace(&self) { + fn parse_whitespace(&mut self) { while char::is_whitespace(self.ch) { self.bump(); } } - fn parse_ident(&self, ident: &str, value: Json) -> Result { + fn parse_ident(&mut self, ident: &str, value: Json) -> Result { if str::all(ident, |c| c == self.next_char()) { self.bump(); Ok(value) @@ -450,7 +450,7 @@ priv impl Parser { } } - fn parse_number(&self) -> Result { + fn parse_number(&mut self) -> Result { let mut neg = 1f; if self.ch == '-' { @@ -480,7 +480,7 @@ priv impl Parser { Ok(Number(neg * res)) } - fn parse_integer(&self) -> Result { + fn parse_integer(&mut self) -> Result { let mut res = 0f; match self.ch { @@ -512,7 +512,7 @@ priv impl Parser { Ok(res) } - fn parse_decimal(&self, res: float) -> Result { + fn parse_decimal(&mut self, res: float) -> Result { self.bump(); // Make sure a digit follows the decimal place. @@ -538,10 +538,9 @@ priv impl Parser { Ok(res) } - fn parse_exponent(&self, res: float) -> Result { + fn parse_exponent(&mut self, mut res: float) -> Result { self.bump(); - let mut res = res; let mut exp = 0u; let mut neg_exp = false; @@ -579,7 +578,7 @@ priv impl Parser { Ok(res) } - fn parse_str(&self) -> Result<~str, Error> { + fn parse_str(&mut self) -> Result<~str, Error> { let mut escape = false; let mut res = ~""; @@ -643,7 +642,7 @@ priv impl Parser { self.error(~"EOF while parsing string") } - fn parse_list(&self) -> Result { + fn parse_list(&mut self) -> Result { self.bump(); self.parse_whitespace(); @@ -673,7 +672,7 @@ priv impl Parser { }; } - fn parse_object(&self) -> Result { + fn parse_object(&mut self) -> Result { self.bump(); self.parse_whitespace(); @@ -726,7 +725,8 @@ priv impl Parser { /// Decodes a json value from an @io::Reader pub fn from_reader(rdr: @io::Reader) -> Result { - Parser(rdr).parse() + let mut parser = Parser(rdr); + parser.parse() } /// Decodes a json value from a string diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs index 1e8fc0e6c2baa..949850f3ca677 100644 --- a/src/libstd/num/complex.rs +++ b/src/libstd/num/complex.rs @@ -239,7 +239,6 @@ mod test { mod arith { use super::*; - use super::super::*; use core::num::Zero; #[test] diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index 61f50069d8997..232f46b6676df 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -455,7 +455,7 @@ pub mod iterator { node::Content(x) => return node::leaf_iterator::start(x) } } - pub fn next(it: &node::leaf_iterator::T) -> Option { + pub fn next(it: &mut node::leaf_iterator::T) -> Option { return node::leaf_iterator::next(it); } } @@ -470,7 +470,7 @@ pub mod iterator { node::Content(x) => return node::char_iterator::start(x) } } - pub fn next(it: &node::char_iterator::T) -> Option { + pub fn next(it: &mut node::char_iterator::T) -> Option { return node::char_iterator::next(it) } } @@ -832,9 +832,9 @@ pub mod node { unsafe { let mut buf = vec::from_elem(byte_len(node), 0); let mut offset = 0u;//Current position in the buffer - let it = leaf_iterator::start(node); + let mut it = leaf_iterator::start(node); loop { - match (leaf_iterator::next(&it)) { + match leaf_iterator::next(&mut it) { option::None => break, option::Some(x) => { //FIXME (#2744): Replace with memcpy or something similar @@ -896,9 +896,9 @@ pub mod node { if height(node) < hint_max_node_height { return option::None; } //1. Gather all leaves as a forest let mut forest = ~[]; - let it = leaf_iterator::start(node); + let mut it = leaf_iterator::start(node); loop { - match (leaf_iterator::next(&it)) { + match leaf_iterator::next(&mut it) { option::None => break, option::Some(x) => forest.push(@Leaf(x)) } @@ -1058,11 +1058,12 @@ pub mod node { } pub fn cmp(a: @Node, b: @Node) -> int { - let ita = char_iterator::start(a); - let itb = char_iterator::start(b); + let mut ita = char_iterator::start(a); + let mut itb = char_iterator::start(b); let mut result = 0; while result == 0 { - match ((char_iterator::next(&ita), char_iterator::next(&itb))) { + match (char_iterator::next(&mut ita), char_iterator::next(&mut itb)) + { (option::None, option::None) => break, (option::Some(chara), option::Some(charb)) => { result = char::cmp(chara, charb); @@ -1131,9 +1132,7 @@ pub mod node { * proportional to the height of the rope + the (bounded) * length of the largest leaf. */ - pub fn char_at(node: @Node, pos: uint) -> char { - let mut node = node; - let mut pos = pos; + pub fn char_at(mut node: @Node, mut pos: uint) -> char { loop { match *node { Leaf(x) => return str::char_at(*x.content, pos), @@ -1154,8 +1153,8 @@ pub mod node { use core::vec; pub struct T { - mut stack: ~[@Node], - mut stackpos: int, + stack: ~[@Node], + stackpos: int, } pub fn empty() -> T { @@ -1171,7 +1170,7 @@ pub mod node { } } - pub fn next(it: &T) -> Option { + pub fn next(it: &mut T) -> Option { if it.stackpos < 0 { return option::None; } loop { let current = it.stack[it.stackpos]; @@ -1199,8 +1198,8 @@ pub mod node { pub struct T { leaf_iterator: leaf_iterator::T, - mut leaf: Option, - mut leaf_byte_pos: uint, + leaf: Option, + leaf_byte_pos: uint, } pub fn start(node: @Node) -> T { @@ -1219,13 +1218,13 @@ pub mod node { } } - pub fn next(it: &T) -> Option { + pub fn next(it: &mut T) -> Option { loop { - match (get_current_or_next_leaf(it)) { + match get_current_or_next_leaf(it) { option::None => return option::None, option::Some(_) => { let next_char = get_next_char_in_leaf(it); - match (next_char) { + match next_char { option::None => loop, option::Some(_) => return next_char } @@ -1234,16 +1233,16 @@ pub mod node { }; } - pub fn get_current_or_next_leaf(it: &T) -> Option { - match ((*it).leaf) { - option::Some(_) => return (*it).leaf, + pub fn get_current_or_next_leaf(it: &mut T) -> Option { + match it.leaf { + option::Some(_) => return it.leaf, option::None => { - let next = leaf_iterator::next(&((*it).leaf_iterator)); - match (next) { + let next = leaf_iterator::next(&mut it.leaf_iterator); + match next { option::None => return option::None, option::Some(_) => { - (*it).leaf = next; - (*it).leaf_byte_pos = 0u; + it.leaf = next; + it.leaf_byte_pos = 0u; return next; } } @@ -1251,13 +1250,13 @@ pub mod node { } } - pub fn get_next_char_in_leaf(it: &T) -> Option { - match copy (*it).leaf { + pub fn get_next_char_in_leaf(it: &mut T) -> Option { + match copy it.leaf { option::None => return option::None, option::Some(aleaf) => { - if (*it).leaf_byte_pos >= aleaf.byte_len { + if it.leaf_byte_pos >= aleaf.byte_len { //We are actually past the end of the leaf - (*it).leaf = option::None; + it.leaf = option::None; return option::None } else { let range = @@ -1342,11 +1341,11 @@ mod tests { assert!(rope_to_string(r) == *sample); let mut string_iter = 0u; - let string_len = str::len(*sample); - let rope_iter = iterator::char::start(r); - let mut equal = true; + let string_len = str::len(*sample); + let mut rope_iter = iterator::char::start(r); + let mut equal = true; while equal { - match (node::char_iterator::next(&rope_iter)) { + match (node::char_iterator::next(&mut rope_iter)) { option::None => { if string_iter < string_len { equal = false; @@ -1376,9 +1375,9 @@ mod tests { let r = of_str(sample); let mut len = 0u; - let it = iterator::char::start(r); + let mut it = iterator::char::start(r); loop { - match (node::char_iterator::next(&it)) { + match (node::char_iterator::next(&mut it)) { option::None => break, option::Some(_) => len += 1u } diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 99b3a122d9f70..1bfdd7f99d501 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -72,7 +72,7 @@ fn broadcast_waitqueue(q: &Waitqueue) -> uint { // The building-block used to make semaphores, mutexes, and rwlocks. #[doc(hidden)] struct SemInner { - mut count: int, + count: int, waiters: Waitqueue, // Can be either unit or another waitqueue. Some sems shouldn't come with // a condition variable attached, others should. @@ -729,7 +729,6 @@ mod tests { use core::cast; use core::cell::Cell; - use core::option; use core::ptr; use core::result; use core::task; diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs index aed6721b78ea1..3f2772942a5cb 100644 --- a/src/libstd/task_pool.rs +++ b/src/libstd/task_pool.rs @@ -26,8 +26,7 @@ enum Msg { pub struct TaskPool { channels: ~[Chan>], - mut next_index: uint, - + next_index: uint, } #[unsafe_destructor] @@ -84,7 +83,7 @@ pub impl TaskPool { /// Executes the function `f` on a task in the pool. The function /// receives a reference to the local data returned by the `init_fn`. - fn execute(&self, f: ~fn(&T)) { + fn execute(&mut self, f: ~fn(&T)) { self.channels[self.next_index].send(Execute(f)); self.next_index += 1; if self.next_index == self.channels.len() { self.next_index = 0; } @@ -97,7 +96,7 @@ fn test_task_pool() { let g: ~fn(uint) -> uint = |i| i; g }; - let pool = TaskPool::new(4, Some(SingleThreaded), f); + let mut pool = TaskPool::new(4, Some(SingleThreaded), f); for 8.times { pool.execute(|i| io::println(fmt!("Hello from thread %u!", *i))); } diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 7c5591d839e20..04fa319b25530 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -201,19 +201,19 @@ struct ConsoleTestState { out: @io::Writer, log_out: Option<@io::Writer>, use_color: bool, - mut total: uint, - mut passed: uint, - mut failed: uint, - mut ignored: uint, - mut benchmarked: uint, - mut failures: ~[TestDesc] + total: uint, + passed: uint, + failed: uint, + ignored: uint, + benchmarked: uint, + failures: ~[TestDesc] } // A simple console test runner pub fn run_tests_console(opts: &TestOpts, tests: ~[TestDescAndFn]) -> bool { - fn callback(event: &TestEvent, st: @ConsoleTestState) { + fn callback(event: &TestEvent, st: &mut ConsoleTestState) { debug!("callback(event=%?)", event); match *event { TeFiltered(ref filtered_tests) => { @@ -268,16 +268,16 @@ pub fn run_tests_console(opts: &TestOpts, None => None }; - let st = @ConsoleTestState { + let st = @mut ConsoleTestState { out: io::stdout(), log_out: log_out, use_color: use_color(), - mut total: 0u, - mut passed: 0u, - mut failed: 0u, - mut ignored: 0u, - mut benchmarked: 0u, - mut failures: ~[] + total: 0u, + passed: 0u, + failed: 0u, + ignored: 0u, + benchmarked: 0u, + failures: ~[] }; run_tests(opts, tests, |x| callback(&x, st)); @@ -290,15 +290,18 @@ pub fn run_tests_console(opts: &TestOpts, print_failures(st); } - st.out.write_str(fmt!("\nresult: ")); - if success { - // There's no parallelism at this point so it's safe to use color - write_ok(st.out, true); - } else { - write_failed(st.out, true); + { + let st: &mut ConsoleTestState = st; + st.out.write_str(fmt!("\nresult: ")); + if success { + // There's no parallelism at this point so it's safe to use color + write_ok(st.out, true); + } else { + write_failed(st.out, true); + } + st.out.write_str(fmt!(". %u passed; %u failed; %u ignored\n\n", + st.passed, st.failed, st.ignored)); } - st.out.write_str(fmt!(". %u passed; %u failed; %u ignored\n\n", - st.passed, st.failed, st.ignored)); return success; @@ -356,7 +359,7 @@ pub fn run_tests_console(opts: &TestOpts, } } -fn print_failures(st: @ConsoleTestState) { +fn print_failures(st: &ConsoleTestState) { st.out.write_line(~"\nfailures:"); let mut failures = ~[]; for uint::range(0, vec::uniq_len(&const st.failures)) |i| { @@ -390,12 +393,12 @@ fn should_sort_failures_before_printing_them() { out: wr, log_out: option::None, use_color: false, - mut total: 0u, - mut passed: 0u, - mut failed: 0u, - mut ignored: 0u, - mut benchmarked: 0u, - mut failures: ~[test_b, test_a] + total: 0u, + passed: 0u, + failed: 0u, + ignored: 0u, + benchmarked: 0u, + failures: ~[test_b, test_a] }; print_failures(st); From 255193cc1af5e07753906ad18bae077b45b5c3f0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Apr 2013 16:50:34 -0400 Subject: [PATCH 087/403] Removing no longer needed unsafe blocks --- src/libcore/char.rs | 10 +- src/libcore/hash.rs | 62 ++++------ src/libcore/num/strconv.rs | 80 +++++------- src/libcore/result.rs | 6 +- src/libcore/str.rs | 58 ++++----- src/libcore/to_str.rs | 63 ++++------ src/libcore/vec.rs | 81 +++++------- src/libstd/base64.rs | 158 ++++++++++++------------ src/libstd/dlist.rs | 9 +- src/libstd/json.rs | 35 +++--- src/libstd/md4.rs | 4 +- src/libstd/num/bigint.rs | 2 +- src/libstd/sha1.rs | 230 +++++++++++++++++------------------ src/libstd/sort.rs | 30 ++--- src/libstd/time.rs | 8 +- src/libsyntax/codemap.rs | 16 ++- src/libsyntax/parse/lexer.rs | 10 +- 17 files changed, 379 insertions(+), 483 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 4f1dbe6ab7f23..6ca33540ceef6 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -202,12 +202,10 @@ pub fn escape_unicode(c: char) -> ~str { else { ('U', 8u) }); assert!(str::len(s) <= pad); let mut out = ~"\\"; - unsafe { - str::push_str(&mut out, str::from_char(c)); - for uint::range(str::len(s), pad) |_i| - { str::push_str(&mut out, ~"0"); } - str::push_str(&mut out, s); - } + str::push_str(&mut out, str::from_char(c)); + for uint::range(str::len(s), pad) |_i| + { str::push_str(&mut out, ~"0"); } + str::push_str(&mut out, s); out } diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index d31f35b011508..c229bc17311c9 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -76,36 +76,30 @@ pub trait Streaming { impl Hash for A { #[inline(always)] fn hash_keyed(&self, k0: u64, k1: u64) -> u64 { - unsafe { - let s = &State(k0, k1); - for self.iter_bytes(true) |bytes| { - s.input(bytes); - } - s.result_u64() + let s = &State(k0, k1); + for self.iter_bytes(true) |bytes| { + s.input(bytes); } + s.result_u64() } } fn hash_keyed_2(a: &A, b: &B, k0: u64, k1: u64) -> u64 { - unsafe { - let s = &State(k0, k1); - for a.iter_bytes(true) |bytes| { s.input(bytes); } - for b.iter_bytes(true) |bytes| { s.input(bytes); } - s.result_u64() - } + let s = &State(k0, k1); + for a.iter_bytes(true) |bytes| { s.input(bytes); } + for b.iter_bytes(true) |bytes| { s.input(bytes); } + s.result_u64() } fn hash_keyed_3(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 { - unsafe { - let s = &State(k0, k1); - for a.iter_bytes(true) |bytes| { s.input(bytes); } - for b.iter_bytes(true) |bytes| { s.input(bytes); } - for c.iter_bytes(true) |bytes| { s.input(bytes); } - s.result_u64() - } + let s = &State(k0, k1); + for a.iter_bytes(true) |bytes| { s.input(bytes); } + for b.iter_bytes(true) |bytes| { s.input(bytes); } + for c.iter_bytes(true) |bytes| { s.input(bytes); } + s.result_u64() } fn hash_keyed_4(a: &A, b: &B, c: &C, d: &D, k0: u64, k1: u64) -> u64 { - unsafe { - let s = &State(k0, k1); - for a.iter_bytes(true) |bytes| { s.input(bytes); } - for b.iter_bytes(true) |bytes| { s.input(bytes); } - for c.iter_bytes(true) |bytes| { s.input(bytes); } - for d.iter_bytes(true) |bytes| { s.input(bytes); } - s.result_u64() - } + let s = &State(k0, k1); + for a.iter_bytes(true) |bytes| { s.input(bytes); } + for b.iter_bytes(true) |bytes| { s.input(bytes); } + for c.iter_bytes(true) |bytes| { s.input(bytes); } + for d.iter_bytes(true) |bytes| { s.input(bytes); } + s.result_u64() } fn hash_keyed_5(a: &A, b: &B, c: &C, d: &D, e: &E, k0: u64, k1: u64) -> u64 { - unsafe { - let s = &State(k0, k1); - for a.iter_bytes(true) |bytes| { s.input(bytes); } - for b.iter_bytes(true) |bytes| { s.input(bytes); } - for c.iter_bytes(true) |bytes| { s.input(bytes); } - for d.iter_bytes(true) |bytes| { s.input(bytes); } - for e.iter_bytes(true) |bytes| { s.input(bytes); } - s.result_u64() - } + let s = &State(k0, k1); + for a.iter_bytes(true) |bytes| { s.input(bytes); } + for b.iter_bytes(true) |bytes| { s.input(bytes); } + for c.iter_bytes(true) |bytes| { s.input(bytes); } + for d.iter_bytes(true) |bytes| { s.input(bytes); } + for e.iter_bytes(true) |bytes| { s.input(bytes); } + s.result_u64() } // Implement State as SipState diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 5299203eb4273..9374829dcb86b 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -228,10 +228,8 @@ pub fn to_str_bytes_common break if deccum == _0 { break; } @@ -247,21 +245,15 @@ pub fn to_str_bytes_common { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('-' as u8); - } + buf.push('-' as u8); } SignAll => { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('+' as u8); - } + buf.push('+' as u8); } _ => () } - unsafe { // FIXME: Pureness workaround (#4568) - vec::reverse(buf); - } + vec::reverse(buf); // Remember start of the fractional digits. // Points one beyond end of buf if none get generated, @@ -271,9 +263,7 @@ pub fn to_str_bytes_common 0) { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('.' as u8); - } + buf.push('.' as u8); let mut dig = 0u; // calculate new digits while @@ -299,10 +289,8 @@ pub fn to_str_bytes_common= radix / 2 { // -> need to round - let mut i: int = buf.len() as int - 1; - loop { - // If reached left end of number, have to - // insert additional digit: - if i < 0 - || buf[i] == '-' as u8 - || buf[i] == '+' as u8 { - buf.insert((i + 1) as uint, value2ascii(1)); - break; - } - - // Skip the '.' - if buf[i] == '.' as u8 { i -= 1; loop; } - - // Either increment the digit, - // or set to 0 if max and carry the 1. - let current_digit = ascii2value(buf[i]); - if current_digit < (radix - 1) { - buf[i] = value2ascii(current_digit+1); - break; - } else { - buf[i] = value2ascii(0); - i -= 1; - } + let extra_digit = ascii2value(buf.pop()); + if extra_digit >= radix / 2 { // -> need to round + let mut i: int = buf.len() as int - 1; + loop { + // If reached left end of number, have to + // insert additional digit: + if i < 0 + || buf[i] == '-' as u8 + || buf[i] == '+' as u8 { + buf.insert((i + 1) as uint, value2ascii(1)); + break; + } + + // Skip the '.' + if buf[i] == '.' as u8 { i -= 1; loop; } + + // Either increment the digit, + // or set to 0 if max and carry the 1. + let current_digit = ascii2value(buf[i]); + if current_digit < (radix - 1) { + buf[i] = value2ascii(current_digit+1); + break; + } else { + buf[i] = value2ascii(0); + i -= 1; } } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 24822f52e1e84..8fd81a2060342 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -39,9 +39,8 @@ pub enum Result { pub fn get(res: &Result) -> T { match *res { Ok(copy t) => t, - Err(ref the_err) => unsafe { + Err(ref the_err) => fail!(fmt!("get called on error result: %?", *the_err)) - } } } @@ -56,9 +55,8 @@ pub fn get(res: &Result) -> T { pub fn get_ref<'a, T, U>(res: &'a Result) -> &'a T { match *res { Ok(ref t) => t, - Err(ref the_err) => unsafe { + Err(ref the_err) => fail!(fmt!("get_ref called on error result: %?", *the_err)) - } } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 18ea169d96e5c..f1605309fb488 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1020,11 +1020,9 @@ pub fn any(ss: &str, pred: &fn(char) -> bool) -> bool { /// Apply a function to each character pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { let mut result = ~""; - unsafe { - reserve(&mut result, len(ss)); - for ss.each_char |cc| { - str::push_char(&mut result, ff(cc)); - } + reserve(&mut result, len(ss)); + for ss.each_char |cc| { + str::push_char(&mut result, ff(cc)); } result } @@ -1660,20 +1658,18 @@ pub fn to_utf16(s: &str) -> ~[u16] { // Arithmetic with u32 literals is easier on the eyes than chars. let mut ch = ch as u32; - unsafe { - if (ch & 0xFFFF_u32) == ch { - // The BMP falls through (assuming non-surrogate, as it - // should) - assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); - u.push(ch as u16) - } else { - // Supplementary planes break into surrogates. - assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); - ch -= 0x1_0000_u32; - let w1 = 0xD800_u16 | ((ch >> 10) as u16); - let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all(~[w1, w2]) - } + if (ch & 0xFFFF_u32) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); + u.push(ch as u16) + } else { + // Supplementary planes break into surrogates. + assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); + ch -= 0x1_0000_u32; + let w1 = 0xD800_u16 | ((ch >> 10) as u16); + let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + u.push_all(~[w1, w2]) } } u @@ -1705,16 +1701,14 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) { pub fn from_utf16(v: &[u16]) -> ~str { let mut buf = ~""; - unsafe { - reserve(&mut buf, vec::len(v)); - utf16_chars(v, |ch| push_char(&mut buf, ch)); - } + reserve(&mut buf, vec::len(v)); + utf16_chars(v, |ch| push_char(&mut buf, ch)); buf } pub fn with_capacity(capacity: uint) -> ~str { let mut buf = ~""; - unsafe { reserve(&mut buf, capacity); } + reserve(&mut buf, capacity); buf } @@ -2105,11 +2099,9 @@ pub fn capacity(s: &const ~str) -> uint { /// Escape each char in `s` with char::escape_default. pub fn escape_default(s: &str) -> ~str { let mut out: ~str = ~""; - unsafe { - reserve_at_least(&mut out, str::len(s)); - for s.each_char |c| { - push_str(&mut out, char::escape_default(c)); - } + reserve_at_least(&mut out, str::len(s)); + for s.each_char |c| { + push_str(&mut out, char::escape_default(c)); } out } @@ -2117,11 +2109,9 @@ pub fn escape_default(s: &str) -> ~str { /// Escape each char in `s` with char::escape_unicode. pub fn escape_unicode(s: &str) -> ~str { let mut out: ~str = ~""; - unsafe { - reserve_at_least(&mut out, str::len(s)); - for s.each_char |c| { - push_str(&mut out, char::escape_unicode(c)); - } + reserve_at_least(&mut out, str::len(s)); + for s.each_char |c| { + push_str(&mut out, char::escape_unicode(c)); } out } diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index a6004ed124174..980d4b445d04d 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -72,63 +72,42 @@ impl ToStr for (A, B, C) { impl<'self,A:ToStr> ToStr for &'self [A] { #[inline(always)] fn to_str(&self) -> ~str { - unsafe { - // FIXME #4568 - // Bleh -- not really unsafe - // push_str and push_char - let mut acc = ~"[", first = true; - for self.each |elt| { - unsafe { - if first { first = false; } - else { str::push_str(&mut acc, ~", "); } - str::push_str(&mut acc, elt.to_str()); - } - } - str::push_char(&mut acc, ']'); - acc + let mut acc = ~"[", first = true; + for self.each |elt| { + if first { first = false; } + else { str::push_str(&mut acc, ~", "); } + str::push_str(&mut acc, elt.to_str()); } + str::push_char(&mut acc, ']'); + acc } } impl ToStr for ~[A] { #[inline(always)] fn to_str(&self) -> ~str { - unsafe { - // FIXME #4568 - // Bleh -- not really unsafe - // push_str and push_char - let mut acc = ~"[", first = true; - for self.each |elt| { - unsafe { - if first { first = false; } - else { str::push_str(&mut acc, ~", "); } - str::push_str(&mut acc, elt.to_str()); - } - } - str::push_char(&mut acc, ']'); - acc + let mut acc = ~"[", first = true; + for self.each |elt| { + if first { first = false; } + else { str::push_str(&mut acc, ~", "); } + str::push_str(&mut acc, elt.to_str()); } + str::push_char(&mut acc, ']'); + acc } } impl ToStr for @[A] { #[inline(always)] fn to_str(&self) -> ~str { - unsafe { - // FIXME #4568 - // Bleh -- not really unsafe - // push_str and push_char - let mut acc = ~"[", first = true; - for self.each |elt| { - unsafe { - if first { first = false; } - else { str::push_str(&mut acc, ~", "); } - str::push_str(&mut acc, elt.to_str()); - } - } - str::push_char(&mut acc, ']'); - acc + let mut acc = ~"[", first = true; + for self.each |elt| { + if first { first = false; } + else { str::push_str(&mut acc, ~", "); } + str::push_str(&mut acc, elt.to_str()); } + str::push_char(&mut acc, ']'); + acc } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 21e876ea0fb02..5b06591f9ecc8 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -167,7 +167,7 @@ pub fn from_slice(t: &[T]) -> ~[T] { pub fn with_capacity(capacity: uint) -> ~[T] { let mut vec = ~[]; - unsafe { reserve(&mut vec, capacity); } + reserve(&mut vec, capacity); vec } @@ -186,7 +186,7 @@ pub fn with_capacity(capacity: uint) -> ~[T] { #[inline(always)] pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { let mut vec = with_capacity(size); - builder(|x| unsafe { vec.push(x) }); + builder(|x| vec.push(x)); vec } @@ -437,12 +437,10 @@ pub fn partitioned(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) { let mut rights = ~[]; for each(v) |elt| { - unsafe { - if f(elt) { - lefts.push(*elt); - } else { - rights.push(*elt); - } + if f(elt) { + lefts.push(*elt); + } else { + rights.push(*elt); } } @@ -735,16 +733,14 @@ pub fn dedup(v: &mut ~[T]) { #[inline(always)] pub fn append(lhs: ~[T], rhs: &const [T]) -> ~[T] { let mut v = lhs; - unsafe { - v.push_all(rhs); - } + v.push_all(rhs); v } #[inline(always)] pub fn append_one(lhs: ~[T], x: T) -> ~[T] { let mut v = lhs; - unsafe { v.push(x); } + v.push(x); v } @@ -811,9 +807,7 @@ pub fn grow_set(v: &mut ~[T], index: uint, initval: &T, val: T) { pub fn map(v: &[T], f: &fn(t: &T) -> U) -> ~[U] { let mut result = with_capacity(len(v)); for each(v) |elem| { - unsafe { - result.push(f(elem)); - } + result.push(f(elem)); } result } @@ -841,7 +835,7 @@ pub fn mapi(v: &[T], f: &fn(uint, t: &T) -> U) -> ~[U] { */ pub fn flat_map(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] { let mut result = ~[]; - for each(v) |elem| { unsafe{ result.push_all_move(f(elem)); } } + for each(v) |elem| { result.push_all_move(f(elem)); } result } @@ -853,7 +847,7 @@ pub fn map2(v0: &[T], v1: &[U], let mut u: ~[V] = ~[]; let mut i = 0u; while i < v0_len { - unsafe { u.push(f(&v0[i], &v1[i])) }; + u.push(f(&v0[i], &v1[i])); i += 1u; } u @@ -894,7 +888,7 @@ pub fn filter_mapped( for each(v) |elem| { match f(elem) { None => {/* no-op */ } - Some(result_elem) => unsafe { result.push(result_elem); } + Some(result_elem) => { result.push(result_elem); } } } result @@ -927,7 +921,7 @@ pub fn filter(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] { pub fn filtered(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] { let mut result = ~[]; for each(v) |elem| { - if f(elem) { unsafe { result.push(*elem); } } + if f(elem) { result.push(*elem); } } result } @@ -959,7 +953,7 @@ pub fn retain(v: &mut ~[T], f: &fn(t: &T) -> bool) { */ pub fn concat(v: &[~[T]]) -> ~[T] { let mut r = ~[]; - for each(v) |inner| { unsafe { r.push_all(*inner); } } + for each(v) |inner| { r.push_all(*inner); } r } @@ -968,8 +962,8 @@ pub fn connect(v: &[~[T]], sep: &T) -> ~[T] { let mut r: ~[T] = ~[]; let mut first = true; for each(v) |inner| { - if first { first = false; } else { unsafe { r.push(*sep); } } - unsafe { r.push_all(*inner) }; + if first { first = false; } else { r.push(*sep); } + r.push_all(*inner); } r } @@ -1236,10 +1230,8 @@ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { let mut ts = ~[], us = ~[]; for each(v) |p| { let (t, u) = *p; - unsafe { - ts.push(t); - us.push(u); - } + ts.push(t); + us.push(u); } (ts, us) } @@ -1254,12 +1246,10 @@ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { */ pub fn unzip(v: ~[(T, U)]) -> (~[T], ~[U]) { let mut ts = ~[], us = ~[]; - unsafe { - do consume(v) |_i, p| { - let (t, u) = p; - ts.push(t); - us.push(u); - } + do consume(v) |_i, p| { + let (t, u) = p; + ts.push(t); + us.push(u); } (ts, us) } @@ -1274,7 +1264,8 @@ pub fn zip_slice(v: &const [T], u: &const [U]) let mut i = 0u; assert!(sz == len(u)); while i < sz { - unsafe { zipped.push((v[i], u[i])); i += 1u; } + zipped.push((v[i], u[i])); + i += 1u; } zipped } @@ -1290,10 +1281,10 @@ pub fn zip(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { assert!(i == len(u)); let mut w = with_capacity(i); while i > 0 { - unsafe { w.push((v.pop(),u.pop())); } + w.push((v.pop(),u.pop())); i -= 1; } - unsafe { reverse(w); } + reverse(w); w } @@ -1322,10 +1313,8 @@ pub fn reversed(v: &const [T]) -> ~[T] { let mut rs: ~[T] = ~[]; let mut i = len::(v); if i == 0 { return (rs); } else { i -= 1; } - unsafe { - while i != 0 { rs.push(v[i]); i -= 1; } - rs.push(v[0]); - } + while i != 0 { rs.push(v[i]); i -= 1; } + rs.push(v[0]); rs } @@ -1495,12 +1484,10 @@ pub fn each_permutation(v: &[T], put: &fn(ts: &[T]) -> bool) { while i < ln { let elt = v[i]; let mut rest = slice(v, 0u, i).to_vec(); - unsafe { - rest.push_all(const_slice(v, i+1u, ln)); - for each_permutation(rest) |permutation| { - if !put(append(~[elt], permutation)) { - return; - } + rest.push_all(const_slice(v, i+1u, ln)); + for each_permutation(rest) |permutation| { + if !put(append(~[elt], permutation)) { + return; } } i += 1u; @@ -1514,9 +1501,7 @@ pub fn windowed(nn: uint, xx: &[TT]) -> ~[~[TT]] { for vec::eachi (xx) |ii, _x| { let len = xx.len(); if ii+nn <= len { - unsafe { - ww.push(slice(xx, ii, ii+nn).to_vec()); - } + ww.push(slice(xx, ii, ii+nn).to_vec()); } } ww diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 0266f2d8631cf..781a720b1a4db 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -29,47 +29,45 @@ static CHARS: [char, ..64] = [ impl<'self> ToBase64 for &'self [u8] { fn to_base64(&self) -> ~str { let mut s = ~""; - unsafe { - let len = self.len(); - str::reserve(&mut s, ((len + 3u) / 4u) * 3u); - - let mut i = 0u; - - while i < len - (len % 3u) { - let n = (self[i] as uint) << 16u | - (self[i + 1u] as uint) << 8u | - (self[i + 2u] as uint); - - // This 24-bit number gets separated into four 6-bit numbers. - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); - str::push_char(&mut s, CHARS[n & 63u]); - - i += 3u; - } - - // Heh, would be cool if we knew this was exhaustive - // (the dream of bounded integer types) - match len % 3 { - 0 => (), - 1 => { - let n = (self[i] as uint) << 16u; - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, '='); - str::push_char(&mut s, '='); - } - 2 => { - let n = (self[i] as uint) << 16u | - (self[i + 1u] as uint) << 8u; - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); - str::push_char(&mut s, '='); - } - _ => fail!(~"Algebra is broken, please alert the math police") - } + let len = self.len(); + str::reserve(&mut s, ((len + 3u) / 4u) * 3u); + + let mut i = 0u; + + while i < len - (len % 3u) { + let n = (self[i] as uint) << 16u | + (self[i + 1u] as uint) << 8u | + (self[i + 2u] as uint); + + // This 24-bit number gets separated into four 6-bit numbers. + str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); + str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); + str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); + str::push_char(&mut s, CHARS[n & 63u]); + + i += 3u; + } + + // Heh, would be cool if we knew this was exhaustive + // (the dream of bounded integer types) + match len % 3 { + 0 => (), + 1 => { + let n = (self[i] as uint) << 16u; + str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); + str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); + str::push_char(&mut s, '='); + str::push_char(&mut s, '='); + } + 2 => { + let n = (self[i] as uint) << 16u | + (self[i + 1u] as uint) << 8u; + str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); + str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); + str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); + str::push_char(&mut s, '='); + } + _ => fail!(~"Algebra is broken, please alert the math police") } s } @@ -99,49 +97,47 @@ impl FromBase64 for ~[u8] { let mut r = vec::with_capacity((len / 4u) * 3u - padding); - unsafe { - let mut i = 0u; - while i < len { - let mut n = 0u; - - for iter::repeat(4u) { - let ch = self[i] as char; - n <<= 6u; - - if ch >= 'A' && ch <= 'Z' { - n |= (ch as uint) - 0x41u; - } else if ch >= 'a' && ch <= 'z' { - n |= (ch as uint) - 0x47u; - } else if ch >= '0' && ch <= '9' { - n |= (ch as uint) + 0x04u; - } else if ch == '+' { - n |= 0x3Eu; - } else if ch == '/' { - n |= 0x3Fu; - } else if ch == '=' { - match len - i { - 1u => { - r.push(((n >> 16u) & 0xFFu) as u8); - r.push(((n >> 8u ) & 0xFFu) as u8); - return copy r; - } - 2u => { - r.push(((n >> 10u) & 0xFFu) as u8); - return copy r; - } - _ => fail!(~"invalid base64 padding") - } - } else { - fail!(~"invalid base64 character"); + let mut i = 0u; + while i < len { + let mut n = 0u; + + for iter::repeat(4u) { + let ch = self[i] as char; + n <<= 6u; + + if ch >= 'A' && ch <= 'Z' { + n |= (ch as uint) - 0x41u; + } else if ch >= 'a' && ch <= 'z' { + n |= (ch as uint) - 0x47u; + } else if ch >= '0' && ch <= '9' { + n |= (ch as uint) + 0x04u; + } else if ch == '+' { + n |= 0x3Eu; + } else if ch == '/' { + n |= 0x3Fu; + } else if ch == '=' { + match len - i { + 1u => { + r.push(((n >> 16u) & 0xFFu) as u8); + r.push(((n >> 8u ) & 0xFFu) as u8); + return copy r; + } + 2u => { + r.push(((n >> 10u) & 0xFFu) as u8); + return copy r; + } + _ => fail!(~"invalid base64 padding") } + } else { + fail!(~"invalid base64 character"); + } - i += 1u; - }; + i += 1u; + }; - r.push(((n >> 16u) & 0xFFu) as u8); - r.push(((n >> 8u ) & 0xFFu) as u8); - r.push(((n ) & 0xFFu) as u8); - } + r.push(((n >> 16u) & 0xFFu) as u8); + r.push(((n >> 8u ) & 0xFFu) as u8); + r.push(((n ) & 0xFFu) as u8); } r } diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs index e7701974097b3..a490065b835c1 100644 --- a/src/libstd/dlist.rs +++ b/src/libstd/dlist.rs @@ -99,7 +99,7 @@ pub fn DList() -> @mut DList { /// Creates a new dlist with a single element pub fn from_elem(data: T) -> @mut DList { let list = DList(); - unsafe { list.push(data); } + list.push(data); list } @@ -484,11 +484,8 @@ pub impl DList { /// Get the elements of the list as a vector. O(n). fn to_vec(@mut self) -> ~[T] { let mut v = vec::with_capacity(self.size); - unsafe { - // Take this out of the unchecked when iter's functions are pure - for iter::eachi(&self) |index,data| { - v[index] = *data; - } + for iter::eachi(&self) |index,data| { + v[index] = *data; } v } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 5a2bfd2113b90..d733a60f34fff 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -342,10 +342,7 @@ pub fn to_writer(wr: @io::Writer, json: &Json) { /// Encodes a json value into a string pub fn to_str(json: &Json) -> ~str { - unsafe { - // ugh, should be safe - io::with_str_writer(|wr| to_writer(wr, json)) - } + io::with_str_writer(|wr| to_writer(wr, json)) } /// Encodes a json value into a io::writer @@ -988,23 +985,21 @@ impl Ord for Json { match *other { Number(_) | String(_) | Boolean(_) | List(_) => false, Object(ref d1) => { - unsafe { - let mut d0_flat = ~[]; - let mut d1_flat = ~[]; - - // FIXME #4430: this is horribly inefficient... - for d0.each |&(k, v)| { - d0_flat.push((@copy *k, @copy *v)); - } - d0_flat.qsort(); - - for d1.each |&(k, v)| { - d1_flat.push((@copy *k, @copy *v)); - } - d1_flat.qsort(); - - d0_flat < d1_flat + let mut d0_flat = ~[]; + let mut d1_flat = ~[]; + + // FIXME #4430: this is horribly inefficient... + for d0.each |&(k, v)| { + d0_flat.push((@copy *k, @copy *v)); } + d0_flat.qsort(); + + for d1.each |&(k, v)| { + d1_flat.push((@copy *k, @copy *v)); + } + d1_flat.qsort(); + + d0_flat < d1_flat } Null => true } diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs index 8f35376a6f1f1..24dd08c362e99 100644 --- a/src/libstd/md4.rs +++ b/src/libstd/md4.rs @@ -29,14 +29,14 @@ pub fn md4(msg: &[u8]) -> Quad { let mut msg = vec::append(vec::from_slice(msg), ~[0x80u8]); let mut bitlen = orig_len + 8u64; while (bitlen + 64u64) % 512u64 > 0u64 { - unsafe {msg.push(0u8);} + msg.push(0u8); bitlen += 8u64; } // append length let mut i = 0u64; while i < 8u64 { - unsafe {msg.push((orig_len >> (i * 8u64)) as u8);} + msg.push((orig_len >> (i * 8u64)) as u8); i += 1u64; } diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index f15632b1431eb..ec5d2cded8d56 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -341,7 +341,7 @@ pub impl BigUint { if new_len == v.len() { return BigUint { data: v }; } let mut v = v; - unsafe { v.truncate(new_len); } + v.truncate(new_len); return BigUint { data: v }; } diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index 1a2d4a87d9886..f5f7f5e326a79 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -283,134 +283,132 @@ mod tests { #[test] pub fn test() { - unsafe { - struct Test { - input: ~str, - output: ~[u8], - output_str: ~str, - } + struct Test { + input: ~str, + output: ~[u8], + output_str: ~str, + } - fn a_million_letter_a() -> ~str { - let mut i = 0; - let mut rs = ~""; - while i < 100000 { - str::push_str(&mut rs, ~"aaaaaaaaaa"); - i += 1; - } - return rs; + fn a_million_letter_a() -> ~str { + let mut i = 0; + let mut rs = ~""; + while i < 100000 { + str::push_str(&mut rs, ~"aaaaaaaaaa"); + i += 1; } - // Test messages from FIPS 180-1 + return rs; + } + // Test messages from FIPS 180-1 - let fips_180_1_tests = ~[ - Test { - input: ~"abc", - output: ~[ - 0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, - 0x47u8, 0x06u8, 0x81u8, 0x6Au8, - 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8, - 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, - 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8, - ], - output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d" - }, - Test { - input: - ~"abcdbcdecdefdefgefghfghighij" + - ~"hijkijkljklmklmnlmnomnopnopq", - output: ~[ - 0x84u8, 0x98u8, 0x3Eu8, 0x44u8, - 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, - 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8, - 0xF9u8, 0x51u8, 0x29u8, 0xE5u8, - 0xE5u8, 0x46u8, 0x70u8, 0xF1u8, - ], - output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1" - }, - Test { - input: a_million_letter_a(), - output: ~[ - 0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, - 0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8, - 0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8, - 0xDBu8, 0xADu8, 0x27u8, 0x31u8, - 0x65u8, 0x34u8, 0x01u8, 0x6Fu8, - ], - output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f" - }, - ]; - // Examples from wikipedia + let fips_180_1_tests = ~[ + Test { + input: ~"abc", + output: ~[ + 0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, + 0x47u8, 0x06u8, 0x81u8, 0x6Au8, + 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8, + 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, + 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8, + ], + output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d" + }, + Test { + input: + ~"abcdbcdecdefdefgefghfghighij" + + ~"hijkijkljklmklmnlmnomnopnopq", + output: ~[ + 0x84u8, 0x98u8, 0x3Eu8, 0x44u8, + 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, + 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8, + 0xF9u8, 0x51u8, 0x29u8, 0xE5u8, + 0xE5u8, 0x46u8, 0x70u8, 0xF1u8, + ], + output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1" + }, + Test { + input: a_million_letter_a(), + output: ~[ + 0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, + 0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8, + 0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8, + 0xDBu8, 0xADu8, 0x27u8, 0x31u8, + 0x65u8, 0x34u8, 0x01u8, 0x6Fu8, + ], + output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f" + }, + ]; + // Examples from wikipedia - let wikipedia_tests = ~[ - Test { - input: ~"The quick brown fox jumps over the lazy dog", - output: ~[ - 0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, - 0x7au8, 0x2du8, 0x28u8, 0xfcu8, - 0xedu8, 0x84u8, 0x9eu8, 0xe1u8, - 0xbbu8, 0x76u8, 0xe7u8, 0x39u8, - 0x1bu8, 0x93u8, 0xebu8, 0x12u8, - ], - output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - }, - Test { - input: ~"The quick brown fox jumps over the lazy cog", - output: ~[ - 0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, - 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8, - 0xfau8, 0xd3u8, 0xe8u8, 0x5au8, - 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, - 0x10u8, 0x0du8, 0xb4u8, 0xb3u8, - ], - output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3", - }, - ]; - let tests = fips_180_1_tests + wikipedia_tests; - fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { - assert!((vec::len::(v0) == vec::len::(v1))); - let len = vec::len::(v0); - let mut i = 0u; - while i < len { - let a = v0[i]; - let b = v1[i]; - assert!((a == b)); - i += 1u; - } + let wikipedia_tests = ~[ + Test { + input: ~"The quick brown fox jumps over the lazy dog", + output: ~[ + 0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, + 0x7au8, 0x2du8, 0x28u8, 0xfcu8, + 0xedu8, 0x84u8, 0x9eu8, 0xe1u8, + 0xbbu8, 0x76u8, 0xe7u8, 0x39u8, + 0x1bu8, 0x93u8, 0xebu8, 0x12u8, + ], + output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + }, + Test { + input: ~"The quick brown fox jumps over the lazy cog", + output: ~[ + 0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, + 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8, + 0xfau8, 0xd3u8, 0xe8u8, 0x5au8, + 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, + 0x10u8, 0x0du8, 0xb4u8, 0xb3u8, + ], + output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3", + }, + ]; + let tests = fips_180_1_tests + wikipedia_tests; + fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { + assert!((vec::len::(v0) == vec::len::(v1))); + let len = vec::len::(v0); + let mut i = 0u; + while i < len { + let a = v0[i]; + let b = v1[i]; + assert!((a == b)); + i += 1u; } - // Test that it works when accepting the message all at once + } + // Test that it works when accepting the message all at once - let mut sh = sha1::sha1(); - for vec::each(tests) |t| { - sh.input_str(t.input); - let out = sh.result(); - check_vec_eq(t.output, out); + let mut sh = sha1::sha1(); + for vec::each(tests) |t| { + sh.input_str(t.input); + let out = sh.result(); + check_vec_eq(t.output, out); - let out_str = sh.result_str(); - assert!((out_str.len() == 40)); - assert!((out_str == t.output_str)); + let out_str = sh.result_str(); + assert!((out_str.len() == 40)); + assert!((out_str == t.output_str)); - sh.reset(); - } + sh.reset(); + } - // Test that it works when accepting the message in pieces - for vec::each(tests) |t| { - let len = str::len(t.input); - let mut left = len; - while left > 0u { - let take = (left + 1u) / 2u; - sh.input_str(str::slice(t.input, len - left, - take + len - left).to_owned()); - left = left - take; - } - let out = sh.result(); - check_vec_eq(t.output, out); + // Test that it works when accepting the message in pieces + for vec::each(tests) |t| { + let len = str::len(t.input); + let mut left = len; + while left > 0u { + let take = (left + 1u) / 2u; + sh.input_str(str::slice(t.input, len - left, + take + len - left).to_owned()); + left = left - take; + } + let out = sh.result(); + check_vec_eq(t.output, out); - let out_str = sh.result_str(); - assert!((out_str.len() == 40)); - assert!((out_str == t.output_str)); + let out_str = sh.result_str(); + assert!((out_str.len() == 40)); + assert!((out_str == t.output_str)); - sh.reset(); - } + sh.reset(); } } } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 40a1289517567..39ca9bb5ba66f 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -27,7 +27,7 @@ type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool; pub fn merge_sort(v: &const [T], le: Le) -> ~[T] { type Slice = (uint, uint); - unsafe {return merge_sort_(v, (0u, len(v)), le);} + return merge_sort_(v, (0u, len(v)), le); fn merge_sort_(v: &const [T], slice: Slice, le: Le) -> ~[T] { @@ -68,14 +68,11 @@ fn part(arr: &mut [T], left: uint, let mut storage_index: uint = left; let mut i: uint = left; while i < right { - // XXX: Unsafe because borrow check doesn't handle this right - unsafe { - let a: &T = cast::transmute(&mut arr[i]); - let b: &T = cast::transmute(&mut arr[right]); - if compare_func(a, b) { - arr[i] <-> arr[storage_index]; - storage_index += 1; - } + let a: &mut T = &mut arr[i]; + let b: &mut T = &mut arr[right]; + if compare_func(a, b) { + arr[i] <-> arr[storage_index]; + storage_index += 1; } i += 1; } @@ -888,12 +885,9 @@ mod tests { // tjc: funny that we have to use parens fn ile(x: &(&'static str), y: &(&'static str)) -> bool { - unsafe // to_lower is not pure... - { - let x = x.to_lower(); - let y = y.to_lower(); - x <= y - } + let x = x.to_lower(); + let y = y.to_lower(); + x <= y } let names1 = ~["joe bob", "Joe Bob", "Jack Brown", "JOE Bob", @@ -921,10 +915,8 @@ mod test_tim_sort { impl Ord for CVal { fn lt(&self, other: &CVal) -> bool { - unsafe { - let rng = rand::Rng(); - if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); } - } + let rng = rand::Rng(); + if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); } (*self).val < other.val } fn le(&self, other: &CVal) -> bool { (*self).val <= other.val } diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 3af193e87486b..adfa12594aac1 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -176,16 +176,12 @@ pub fn now() -> Tm { /// Parses the time from the string according to the format string. pub fn strptime(s: &str, format: &str) -> Result { - // unsafe only because do_strptime is annoying to make pure - // (it does IO with a str_reader) - unsafe {do_strptime(s, format)} + do_strptime(s, format) } /// Formats the time according to the format string. pub fn strftime(format: &str, tm: &Tm) -> ~str { - // unsafe only because do_strftime is annoying to make pure - // (it does IO with a str_reader) - unsafe { do_strftime(format, tm) } + do_strftime(format, tm) } pub impl Tm { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7a8aff121a86d..fc08073686d0d 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -252,15 +252,13 @@ pub impl FileMap { // get a line from the list of pre-computed line-beginnings pub fn get_line(&self, line: int) -> ~str { - unsafe { - let begin: BytePos = self.lines[line] - self.start_pos; - let begin = begin.to_uint(); - let end = match str::find_char_from(*self.src, '\n', begin) { - Some(e) => e, - None => str::len(*self.src) - }; - str::slice(*self.src, begin, end).to_owned() - } + let begin: BytePos = self.lines[line] - self.start_pos; + let begin = begin.to_uint(); + let end = match str::find_char_from(*self.src, '\n', begin) { + Some(e) => e, + None => str::len(*self.src) + }; + str::slice(*self.src, begin, end).to_owned() } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 5e06ecf60908e..de3d97de177d7 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -175,12 +175,10 @@ fn byte_offset(rdr: @mut StringReader) -> BytePos { } pub fn get_str_from(rdr: @mut StringReader, start: BytePos) -> ~str { - unsafe { - // I'm pretty skeptical about this subtraction. What if there's a - // multi-byte character before the mark? - return str::slice(*rdr.src, start.to_uint() - 1u, - byte_offset(rdr).to_uint() - 1u).to_owned(); - } + // I'm pretty skeptical about this subtraction. What if there's a + // multi-byte character before the mark? + return str::slice(*rdr.src, start.to_uint() - 1u, + byte_offset(rdr).to_uint() - 1u).to_owned(); } // EFFECT: advance the StringReader by one character. If a newline is From e06b9827efa0a7d8334d0b71577c6efef44a35f0 Mon Sep 17 00:00:00 2001 From: Jens Nockert Date: Mon, 8 Apr 2013 23:59:00 +0200 Subject: [PATCH 088/403] Fix typo in u16 debug info --- src/librustc/middle/trans/debuginfo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 277d529c8462f..8c40142335e38 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -368,7 +368,7 @@ fn create_basic_type(cx: @CrateContext, t: ty::t, span: span) ty::ty_uint(uint_ty) => match uint_ty { ast::ty_u => (~"uint", DW_ATE_unsigned), ast::ty_u8 => (~"u8", DW_ATE_unsigned), - ast::ty_u16 => (~"i16", DW_ATE_unsigned), + ast::ty_u16 => (~"u16", DW_ATE_unsigned), ast::ty_u32 => (~"u32", DW_ATE_unsigned), ast::ty_u64 => (~"u64", DW_ATE_unsigned) }, From 37f17d720410c11cc3e9172602babe4e8b997e59 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Mon, 8 Apr 2013 18:25:15 -0400 Subject: [PATCH 089/403] Update help text to match behavior --- src/librusti/rusti.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 6b91377b67485..9cf0e50cc1050 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -273,7 +273,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, ~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" + ~":load ... - \ loads given crates as dynamic libraries\n" + - ~":clear - clear the screen\n" + + ~":clear - bindings\n" + ~":exit - exit from the repl\n" + ~":help - show this message"); } From 2e907a3ac2fcaa799f570e07c35f54efae39829b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 8 Apr 2013 16:07:54 -0700 Subject: [PATCH 090/403] core: Remove all but one drop block in favor of `finally` --- src/libcore/task/mod.rs | 69 ++++++++++------------------------------- src/libcore/unstable.rs | 23 ++++---------- 2 files changed, 23 insertions(+), 69 deletions(-) diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index ee454312e0443..502efcf9dc6cb 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -42,6 +42,7 @@ use result; use task::rt::{task_id, sched_id, rust_task}; use util; use util::replace; +use unstable::finally::Finally; #[cfg(test)] use comm::SharedChan; @@ -565,51 +566,27 @@ pub fn get_scheduler() -> Scheduler { * ~~~ */ pub unsafe fn unkillable(f: &fn() -> U) -> U { - struct AllowFailure { - t: *rust_task, - drop { - unsafe { - rt::rust_task_allow_kill(self.t); - } - } - } - - fn AllowFailure(t: *rust_task) -> AllowFailure{ - AllowFailure { - t: t - } - } - unsafe { let t = rt::rust_get_task(); - let _allow_failure = AllowFailure(t); rt::rust_task_inhibit_kill(t); - f() + do (|| { + f() + }).finally { + rt::rust_task_allow_kill(t); + } } } /// The inverse of unkillable. Only ever to be used nested in unkillable(). pub unsafe fn rekillable(f: &fn() -> U) -> U { - struct DisallowFailure { - t: *rust_task, - drop { - unsafe { - rt::rust_task_inhibit_kill(self.t); - } - } - } - - fn DisallowFailure(t: *rust_task) -> DisallowFailure { - DisallowFailure { - t: t - } - } - unsafe { let t = rt::rust_get_task(); - let _allow_failure = DisallowFailure(t); rt::rust_task_allow_kill(t); - f() + do (|| { + f() + }).finally { + rt::rust_task_inhibit_kill(t); + } } } @@ -618,28 +595,16 @@ pub unsafe fn rekillable(f: &fn() -> U) -> U { * For use with exclusive ARCs, which use pthread mutexes directly. */ pub unsafe fn atomically(f: &fn() -> U) -> U { - struct DeferInterrupts { - t: *rust_task, - drop { - unsafe { - rt::rust_task_allow_yield(self.t); - rt::rust_task_allow_kill(self.t); - } - } - } - - fn DeferInterrupts(t: *rust_task) -> DeferInterrupts { - DeferInterrupts { - t: t - } - } - unsafe { let t = rt::rust_get_task(); - let _interrupts = DeferInterrupts(t); rt::rust_task_inhibit_kill(t); rt::rust_task_inhibit_yield(t); - f() + do (|| { + f() + }).finally { + rt::rust_task_allow_yield(t); + rt::rust_task_allow_kill(t); + } } } diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index c717c1692a8c5..9ccce0cfe7654 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -16,6 +16,7 @@ use comm::{GenericChan, GenericPort}; use prelude::*; use task; use task::atomically; +use self::finally::Finally; #[path = "unstable/at_exit.rs"] pub mod at_exit; @@ -229,25 +230,13 @@ fn LittleLock() -> LittleLock { pub impl LittleLock { #[inline(always)] unsafe fn lock(&self, f: &fn() -> T) -> T { - struct Unlock { - l: rust_little_lock, - drop { - unsafe { - rustrt::rust_unlock_little_lock(self.l); - } - } - } - - fn Unlock(l: rust_little_lock) -> Unlock { - Unlock { - l: l - } - } - do atomically { rustrt::rust_lock_little_lock(self.l); - let _r = Unlock(self.l); - f() + do (|| { + f() + }).finally { + rustrt::rust_unlock_little_lock(self.l); + } } } } From eaa8bbbb2e23cf68d4f6ea961af025ab4ac67eca Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Mon, 8 Apr 2013 23:58:29 -0400 Subject: [PATCH 091/403] Fix comment to match style of surrounding text --- src/librusti/rusti.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 9cf0e50cc1050..fcc799b665f5b 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -273,7 +273,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, ~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" + ~":load ... - \ loads given crates as dynamic libraries\n" + - ~":clear - bindings\n" + + ~":clear - clear the bindings\n" + ~":exit - exit from the repl\n" + ~":help - show this message"); } From f9f8a3e72c823d3858ebcd9aa021e619b6a37d77 Mon Sep 17 00:00:00 2001 From: Vivek Galatage Date: Tue, 9 Apr 2013 15:45:22 +0530 Subject: [PATCH 092/403] Support https protocol for git submodules for rust Currently submodules are using the git protocol. Git protocol is blocked by certain corporate networks which makes it difficult to sync the submodules. Replacing the git protocol with https in order to sync the submodules. --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4c61c7e409bd7..52ece628c573f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "src/llvm"] path = src/llvm - url = git://github.com/brson/llvm.git + url = https://github.com/brson/llvm.git [submodule "src/libuv"] path = src/libuv - url = git://github.com/brson/libuv.git + url = https://github.com/brson/libuv.git From 9963bd24138999e745584a138f8381f91e3a308c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Apr 2013 22:54:49 -0700 Subject: [PATCH 093/403] Cleanup substitutions and treatment of generics around traits in a number of ways. - In a TraitRef, use the self type consistently to refer to the Self type: - trait ref in `impl Trait for S` has a self type of `S`. - trait ref in `A:Trait` has the self type `A` - trait ref associated with a trait decl has self type `Self` - trait ref associated with a supertype has self type `Self` - trait ref in an object type `@Trait` has no self type - Rewrite `each_bound_traits_and_supertraits` to perform substitutions as it goes, and thus yield a series of trait refs that are always in the same 'namespace' as the type parameter bound given as input. Before, we left this to the caller, but this doesn't work because the caller lacks adequare information to perform the type substitutions correctly. - For provided methods, substitute the generics involved in the provided method correctly. - Introduce TypeParameterDef, which tracks the bounds declared on a type parameter and brings them together with the def_id and (in the future) other information (maybe even the parameter's name!). - Introduce Subst trait, which helps to cleanup a lot of the repetitive code involved with doing type substitution. - Introduce Repr trait, which makes debug printouts far more convenient. Fixes #4183. Needed for #5656. --- src/librustc/metadata/common.rs | 2 +- src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 40 +-- src/librustc/metadata/encoder.rs | 28 +- src/librustc/metadata/tydecode.rs | 14 +- src/librustc/metadata/tyencode.rs | 8 +- src/librustc/middle/astencode.rs | 42 +-- src/librustc/middle/borrowck/gather_loans.rs | 4 +- src/librustc/middle/kind.rs | 33 ++- src/librustc/middle/subst.rs | 173 +++++++++++ src/librustc/middle/trans/base.rs | 13 +- src/librustc/middle/trans/callee.rs | 46 +-- src/librustc/middle/trans/common.rs | 52 ++-- src/librustc/middle/trans/consts.rs | 4 +- src/librustc/middle/trans/inline.rs | 12 +- src/librustc/middle/trans/meth.rs | 33 ++- src/librustc/middle/trans/monomorphize.rs | 47 ++- src/librustc/middle/ty.rs | 225 ++++++-------- src/librustc/middle/typeck/astconv.rs | 19 +- src/librustc/middle/typeck/check/_match.rs | 4 +- src/librustc/middle/typeck/check/method.rs | 155 ++++------ src/librustc/middle/typeck/check/mod.rs | 20 +- src/librustc/middle/typeck/check/vtable.rs | 113 +++---- src/librustc/middle/typeck/check/writeback.rs | 2 +- src/librustc/middle/typeck/coherence.rs | 153 ++++++++-- src/librustc/middle/typeck/collect.rs | 247 ++++++++++------ src/librustc/middle/typeck/infer/combine.rs | 7 +- src/librustc/middle/typeck/mod.rs | 16 +- src/librustc/rustc.rc | 1 + src/librustc/util/ppaux.rs | 278 +++++++++++++++++- src/libsyntax/opt_vec.rs | 10 + .../trait-inheritance-self-in-supertype.rs | 61 ++++ 32 files changed, 1243 insertions(+), 621 deletions(-) create mode 100644 src/librustc/middle/subst.rs create mode 100644 src/test/run-pass/trait-inheritance-self-in-supertype.rs diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 71a1f1b3f9b20..e2672338a8a0b 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -127,7 +127,7 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_node_type_subst = 0x58, tag_table_freevars = 0x59, tag_table_tcache = 0x5a, - tag_table_param_bounds = 0x5b, + tag_table_param_defs = 0x5b, tag_table_inferred_modes = 0x5c, tag_table_mutbl = 0x5d, tag_table_last_use = 0x5e, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 74e891a01942f..f7de281194f39 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -210,7 +210,7 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id, debug!("got field data %?", the_field); let ty = decoder::item_type(def, the_field, tcx, cdata); ty::ty_param_bounds_and_ty { - generics: ty::Generics {bounds: @~[], + generics: ty::Generics {type_param_defs: @~[], region_param: None}, ty: ty } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index d9ef30ff297d0..472b455b73531 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -19,7 +19,8 @@ use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; use metadata::csearch; use metadata::cstore; use metadata::decoder; -use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, +use metadata::tydecode::{parse_ty_data, parse_def_id, + parse_type_param_def_data, parse_bare_fn_ty_data, parse_trait_ref_data}; use middle::{ty, resolve}; @@ -266,13 +267,14 @@ fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { doc_trait_ref(tp, tcx, cdata) } -fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd, - tag: uint) - -> @~[ty::param_bounds] { +fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd, + tag: uint) + -> @~[ty::TypeParameterDef] { let mut bounds = ~[]; for reader::tagged_docs(item, tag) |p| { - let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, - |_, did| translate_def_id(cdata, did)); + let bd = parse_type_param_def_data( + p.data, p.start, cdata.cnum, tcx, + |_, did| translate_def_id(cdata, did)); bounds.push(bd); } @bounds @@ -378,11 +380,11 @@ pub fn get_trait_def(cdata: cmd, tcx: ty::ctxt) -> ty::TraitDef { let item_doc = lookup_item(item_id, cdata.data); - let tp_bounds = item_ty_param_bounds(item_doc, tcx, cdata, - tag_items_data_item_ty_param_bounds); + let tp_defs = item_ty_param_defs(item_doc, tcx, cdata, + tag_items_data_item_ty_param_bounds); let rp = item_ty_region_param(item_doc); ty::TraitDef { - generics: ty::Generics {bounds: tp_bounds, + generics: ty::Generics {type_param_defs: tp_defs, region_param: rp}, trait_ref: @item_trait_ref(item_doc, tcx, cdata) } @@ -394,12 +396,12 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) let item = lookup_item(id, cdata.data); let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx, cdata); - let tp_bounds = if family_has_type_params(item_family(item)) { - item_ty_param_bounds(item, tcx, cdata, tag_items_data_item_ty_param_bounds) + let tp_defs = if family_has_type_params(item_family(item)) { + item_ty_param_defs(item, tcx, cdata, tag_items_data_item_ty_param_bounds) } else { @~[] }; let rp = item_ty_region_param(item); ty::ty_param_bounds_and_ty { - generics: ty::Generics {bounds: tp_bounds, + generics: ty::Generics {type_param_defs: tp_defs, region_param: rp}, ty: t } @@ -753,9 +755,8 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, let method_doc = lookup_item(id, cdata.data); let def_id = item_def_id(method_doc, cdata); let name = item_name(intr, method_doc); - let bounds = - item_ty_param_bounds(method_doc, tcx, cdata, - tag_item_method_tps); + let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata, + tag_item_method_tps); let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata); let fty = doc_method_fty(method_doc, tcx, cdata); let vis = item_visibility(method_doc); @@ -763,7 +764,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, ty::method { ident: name, generics: ty::Generics { - bounds: bounds, + type_param_defs: type_param_defs, region_param: None }, transformed_self_ty: transformed_self_ty, @@ -797,8 +798,9 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let did = item_def_id(mth, cdata); - let bounds = item_ty_param_bounds(mth, tcx, cdata, - tag_items_data_item_ty_param_bounds); + let type_param_defs = + item_ty_param_defs(mth, tcx, cdata, + tag_items_data_item_ty_param_bounds); let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); @@ -815,7 +817,7 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let ty_method = ty::method { ident: name, generics: ty::Generics { - bounds: bounds, + type_param_defs: type_param_defs, region_param: None }, transformed_self_ty: transformed_self_ty, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e251af7c8a85b..b9f0f63040aef 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -179,10 +179,10 @@ fn encode_family(ebml_w: writer::Encoder, c: char) { pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, - ecx: @EncodeContext, - params: @~[ty::param_bounds], - tag: uint) { +fn encode_ty_type_param_defs(ebml_w: writer::Encoder, + ecx: @EncodeContext, + params: @~[ty::TypeParameterDef], + tag: uint) { let ty_str_ctxt = @tyencode::ctxt { diag: ecx.diag, ds: def_to_str, @@ -191,7 +191,7 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; for params.each |param| { ebml_w.start_tag(tag); - tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param); + tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param); ebml_w.end_tag(); } } @@ -199,10 +199,10 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, fn encode_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext, params: &OptVec) { - let ty_param_bounds = - @params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(¶m.id)); - encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds, - tag_items_data_item_ty_param_bounds); + let ty_param_defs = + @params.map_to_vec(|param| *ecx.tcx.ty_param_defs.get(¶m.id)); + encode_ty_type_param_defs(ebml_w, ecx, ty_param_defs, + tag_items_data_item_ty_param_bounds); } @@ -588,8 +588,9 @@ fn encode_method_ty_fields(ecx: @EncodeContext, { encode_def_id(ebml_w, method_ty.def_id); encode_name(ecx, ebml_w, method_ty.ident); - encode_ty_type_param_bounds(ebml_w, ecx, method_ty.generics.bounds, - tag_item_method_tps); + encode_ty_type_param_defs(ebml_w, ecx, + method_ty.generics.type_param_defs, + tag_item_method_tps); encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty); encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_visibility(ebml_w, method_ty.vis); @@ -952,8 +953,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, method_ty.fty.purity)); let tpt = ty::lookup_item_type(tcx, method_def_id); - encode_ty_type_param_bounds(ebml_w, ecx, tpt.generics.bounds, - tag_items_data_item_ty_param_bounds); + encode_ty_type_param_defs(ebml_w, ecx, + tpt.generics.type_param_defs, + tag_items_data_item_ty_param_bounds); encode_type(ecx, ebml_w, tpt.ty); } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 2ec13abb483d6..867fe0cd816cc 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -547,11 +547,17 @@ pub fn parse_def_id(buf: &[u8]) -> ast::def_id { ast::def_id { crate: crate_num, node: def_num } } -pub fn parse_bounds_data(data: @~[u8], start: uint, - crate_num: int, tcx: ty::ctxt, conv: conv_did) - -> @~[ty::param_bound] { +pub fn parse_type_param_def_data(data: @~[u8], start: uint, + crate_num: int, tcx: ty::ctxt, + conv: conv_did) -> ty::TypeParameterDef +{ let st = parse_state_from_data(data, crate_num, start, tcx); - parse_bounds(st, conv) + parse_type_param_def(st, conv) +} + +fn parse_type_param_def(st: @mut PState, conv: conv_did) -> ty::TypeParameterDef { + ty::TypeParameterDef {def_id: parse_def(st, NominalType, conv), + bounds: parse_bounds(st, conv)} } fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index ca2d66de9c44d..238f34b8c01b9 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -412,7 +412,7 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) { enc_ty(w, cx, fsig.output); } -pub fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { +fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { for vec::each(*bs) |bound| { match *bound { ty::bound_owned => w.write_char('S'), @@ -428,6 +428,12 @@ pub fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { w.write_char('.'); } +pub fn enc_type_param_def(w: @io::Writer, cx: @ctxt, v: &ty::TypeParameterDef) { + w.write_str((cx.ds)(v.def_id)); + w.write_char('|'); + enc_bounds(w, cx, v.bounds); +} + // // Local Variables: // mode: rust diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 20b72a19df794..68989b3142566 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -741,7 +741,9 @@ trait ebml_writer_helpers { fn emit_ty(&self, ecx: @e::EncodeContext, ty: ty::t); fn emit_vstore(&self, ecx: @e::EncodeContext, vstore: ty::vstore); fn emit_tys(&self, ecx: @e::EncodeContext, tys: ~[ty::t]); - fn emit_bounds(&self, ecx: @e::EncodeContext, bs: ty::param_bounds); + fn emit_type_param_def(&self, + ecx: @e::EncodeContext, + type_param_def: &ty::TypeParameterDef); fn emit_tpbt(&self, ecx: @e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty); } @@ -771,9 +773,12 @@ impl ebml_writer_helpers for writer::Encoder { } } - fn emit_bounds(&self, ecx: @e::EncodeContext, bs: ty::param_bounds) { + fn emit_type_param_def(&self, + ecx: @e::EncodeContext, + type_param_def: &ty::TypeParameterDef) { do self.emit_opaque { - tyencode::enc_bounds(self.writer, ecx.ty_str_ctxt(), bs) + tyencode::enc_type_param_def(self.writer, ecx.ty_str_ctxt(), + type_param_def) } } @@ -782,9 +787,11 @@ impl ebml_writer_helpers for writer::Encoder { do self.emit_struct("ty_param_bounds_and_ty", 2) { do self.emit_field(~"generics", 0) { do self.emit_struct("Generics", 2) { - do self.emit_field(~"bounds", 0) { - do self.emit_from_vec(*tpbt.generics.bounds) |bs| { - self.emit_bounds(ecx, *bs); + do self.emit_field(~"type_param_defs", 0) { + do self.emit_from_vec(*tpbt.generics.type_param_defs) + |type_param_def| + { + self.emit_type_param_def(ecx, type_param_def); } } do self.emit_field(~"region_param", 1) { @@ -889,11 +896,11 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, } } - for tcx.ty_param_bounds.find(&id).each |&pbs| { - do ebml_w.tag(c::tag_table_param_bounds) { + for tcx.ty_param_defs.find(&id).each |&type_param_def| { + do ebml_w.tag(c::tag_table_param_defs) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ebml_w.emit_bounds(ecx, *pbs) + ebml_w.emit_type_param_def(ecx, type_param_def) } } } @@ -990,7 +997,7 @@ trait ebml_decoder_decoder_helpers { fn read_arg(&self, xcx: @ExtendedDecodeContext) -> ty::arg; fn read_ty(&self, xcx: @ExtendedDecodeContext) -> ty::t; fn read_tys(&self, xcx: @ExtendedDecodeContext) -> ~[ty::t]; - fn read_bounds(&self, xcx: @ExtendedDecodeContext) -> @~[ty::param_bound]; + fn read_type_param_def(&self, xcx: @ExtendedDecodeContext) -> ty::TypeParameterDef; fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) -> ty::ty_param_bounds_and_ty; fn convert_def_id(&self, xcx: @ExtendedDecodeContext, @@ -1038,10 +1045,9 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { self.read_to_vec(|| self.read_ty(xcx) ) } - fn read_bounds(&self, xcx: @ExtendedDecodeContext) - -> @~[ty::param_bound] { + fn read_type_param_def(&self, xcx: @ExtendedDecodeContext) -> ty::TypeParameterDef { do self.read_opaque |doc| { - tydecode::parse_bounds_data( + tydecode::parse_type_param_def_data( doc.data, doc.start, xcx.dcx.cdata.cnum, xcx.dcx.tcx, |s, a| self.convert_def_id(xcx, s, a)) } @@ -1054,8 +1060,8 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { ty::ty_param_bounds_and_ty { generics: do self.read_struct("Generics", 2) { ty::Generics { - bounds: self.read_field(~"bounds", 0, || { - @self.read_to_vec(|| self.read_bounds(xcx) ) + type_param_defs: self.read_field("type_param_defs", 0, || { + @self.read_to_vec(|| self.read_type_param_def(xcx)) }), region_param: self.read_field(~"region_param", 1, || { Decodable::decode(self) @@ -1134,9 +1140,9 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext, let tpbt = val_dsr.read_ty_param_bounds_and_ty(xcx); let lid = ast::def_id { crate: ast::local_crate, node: id }; dcx.tcx.tcache.insert(lid, tpbt); - } else if tag == (c::tag_table_param_bounds as uint) { - let bounds = val_dsr.read_bounds(xcx); - dcx.tcx.ty_param_bounds.insert(id, bounds); + } else if tag == (c::tag_table_param_defs as uint) { + let bounds = val_dsr.read_type_param_def(xcx); + dcx.tcx.ty_param_defs.insert(id, bounds); } else if tag == (c::tag_table_last_use as uint) { let ids = val_dsr.read_to_vec(|| { xcx.tr_id(val_dsr.read_int()) diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 122e2c64b2133..233b1e191dc24 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -29,7 +29,7 @@ use middle::pat_util; use middle::ty::{ty_region}; use middle::ty; use util::common::indenter; -use util::ppaux::{expr_repr, region_to_str}; +use util::ppaux::{Repr, region_to_str}; use core::hashmap::{HashSet, HashMap}; use core::vec; @@ -282,7 +282,7 @@ pub impl GatherLoanCtxt { expr: @ast::expr, adjustment: &ty::AutoAdjustment) { debug!("guarantee_adjustments(expr=%s, adjustment=%?)", - expr_repr(self.tcx(), expr), adjustment); + expr.repr(self.tcx()), adjustment); let _i = indenter(); match *adjustment { diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 96e8ef40770a2..e82b6ba5e7710 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -16,7 +16,7 @@ use middle::liveness; use middle::pat_util; use middle::ty; use middle::typeck; -use util::ppaux::{ty_to_str, tys_to_str}; +use util::ppaux::{Repr, ty_to_str, tys_to_str}; use syntax::ast::*; use syntax::attr::attrs_contains_name; @@ -91,7 +91,7 @@ fn check_struct_safe_for_destructor(cx: Context, span: span, struct_did: def_id) { let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did); - if struct_tpt.generics.bounds.len() == 0 { + if !struct_tpt.generics.has_type_params() { let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs { self_r: None, self_ty: None, @@ -276,10 +276,10 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt) { for cx.tcx.node_type_substs.find(&type_parameter_id).each |ts| { // FIXME(#5562): removing this copy causes a segfault before stage2 let ts = /*bad*/ copy **ts; - let bounds = match e.node { + let type_param_defs = match e.node { expr_path(_) => { let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id)); - ty::lookup_item_type(cx.tcx, did).generics.bounds + ty::lookup_item_type(cx.tcx, did).generics.type_param_defs } _ => { // Type substitutions should only occur on paths and @@ -287,20 +287,20 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt) { // Even though the callee_id may have been the id with // node_type_substs, e.id is correct here. - ty::method_call_bounds(cx.tcx, cx.method_map, e.id).expect( + ty::method_call_type_param_defs(cx.tcx, cx.method_map, e.id).expect( ~"non path/method call expr has type substs??") } }; - if ts.len() != bounds.len() { + if ts.len() != type_param_defs.len() { // Fail earlier to make debugging easier fail!(fmt!("internal error: in kind::check_expr, length \ mismatch between actual and declared bounds: actual = \ - %s (%u tys), declared = %? (%u tys)", - tys_to_str(cx.tcx, ts), ts.len(), - *bounds, bounds.len())); + %s, declared = %s", + ts.repr(cx.tcx), + type_param_defs.repr(cx.tcx))); } - for vec::each2(ts, *bounds) |ty, bound| { - check_bounds(cx, type_parameter_id, e.span, *ty, *bound) + for vec::each2(ts, *type_param_defs) |&ty, type_param_def| { + check_bounds(cx, type_parameter_id, e.span, ty, type_param_def) } } @@ -340,9 +340,10 @@ fn check_ty(aty: @Ty, cx: Context, v: visit::vt) { // FIXME(#5562): removing this copy causes a segfault before stage2 let ts = /*bad*/ copy **ts; let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id)); - let bounds = ty::lookup_item_type(cx.tcx, did).generics.bounds; - for vec::each2(ts, *bounds) |ty, bound| { - check_bounds(cx, aty.id, aty.span, *ty, *bound) + let type_param_defs = + ty::lookup_item_type(cx.tcx, did).generics.type_param_defs; + for vec::each2(ts, *type_param_defs) |&ty, type_param_def| { + check_bounds(cx, aty.id, aty.span, ty, type_param_def) } } } @@ -355,11 +356,11 @@ pub fn check_bounds(cx: Context, _type_parameter_id: node_id, sp: span, ty: ty::t, - bounds: ty::param_bounds) + type_param_def: &ty::TypeParameterDef) { let kind = ty::type_contents(cx.tcx, ty); let mut missing = ~[]; - for bounds.each |bound| { + for type_param_def.bounds.each |bound| { match *bound { ty::bound_trait(_) => { /* Not our job, checking in typeck */ diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs new file mode 100644 index 0000000000000..e40d17bec5a09 --- /dev/null +++ b/src/librustc/middle/subst.rs @@ -0,0 +1,173 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Type substitutions. + +use core::prelude::*; +use middle::ty; +use util::ppaux::Repr; + +/////////////////////////////////////////////////////////////////////////// +// Public trait `Subst` +// +// Just call `foo.subst(tcx, substs)` to perform a substitution across +// `foo`. + +pub trait Subst { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self; +} + +/////////////////////////////////////////////////////////////////////////// +// Substitution over types +// +// Because this is so common, we make a special optimization to avoid +// doing anything is `substs` is a no-op. I tried to generalize these +// to all subst methods but ran into trouble due to the limitations of +// our current method/trait matching algorithm. - Niko + +trait Subst1 { + fn subst1(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self; +} + +impl Subst for ty::t { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::t { + if ty::substs_is_noop(substs) { + return *self; + } else { + return self.subst1(tcx, substs); + } + } +} + +impl Subst1 for ty::t { + fn subst1(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::t { + if !ty::type_needs_subst(*self) { + return *self; + } + + match ty::get(*self).sty { + ty::ty_param(p) => substs.tps[p.idx], + ty::ty_self(_) => substs.self_ty.get(), + _ => { + ty::fold_regions_and_ty( + tcx, *self, + |r| match r { + ty::re_bound(ty::br_self) => { + match substs.self_r { + None => { + tcx.sess.bug( + fmt!("ty::subst: \ + Reference to self region when \ + given substs with no self region, \ + ty = %s", + self.repr(tcx))); + } + Some(self_r) => self_r + } + } + _ => r + }, + |t| t.subst1(tcx, substs), + |t| t.subst1(tcx, substs)) + } + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// Other types + +impl Subst for ~[T] { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ~[T] { + self.map(|t| t.subst(tcx, substs)) + } +} + +impl Subst for @~[T] { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @~[T] { + @(**self).subst(tcx, substs) + } +} + +impl Subst for Option { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Option { + self.map(|t| t.subst(tcx, substs)) + } +} + +impl Subst for ty::TraitRef { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::TraitRef { + ty::TraitRef { + def_id: self.def_id, + substs: self.substs.subst(tcx, substs) + } + } +} + +impl Subst for ty::substs { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::substs { + ty::substs { + self_r: self.self_r, + self_ty: self.self_ty.map(|typ| typ.subst(tcx, substs)), + tps: self.tps.map(|typ| typ.subst(tcx, substs)) + } + } +} + +impl Subst for ty::BareFnTy { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::BareFnTy { + ty::fold_bare_fn_ty(self, |t| t.subst(tcx, substs)) + } +} + +impl Subst for ty::param_bound { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::param_bound { + match self { + &ty::bound_copy | + &ty::bound_durable | + &ty::bound_owned | + &ty::bound_const => { + *self + } + + &ty::bound_trait(tref) => { + ty::bound_trait(@tref.subst(tcx, substs)) + } + } + } +} + +impl Subst for ty::TypeParameterDef { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::TypeParameterDef { + ty::TypeParameterDef { + def_id: self.def_id, + bounds: self.bounds.subst(tcx, substs) + } + } +} + +impl Subst for ty::Generics { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Generics { + ty::Generics { + type_param_defs: self.type_param_defs.subst(tcx, substs), + region_param: self.region_param + } + } +} + +impl Subst for ty::ty_param_bounds_and_ty { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ty_param_bounds_and_ty { + ty::ty_param_bounds_and_ty { + generics: self.generics.subst(tcx, substs), + ty: self.ty.subst(tcx, substs) + } + } +} + diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a8fe60ba68ee8..2eb7f8332ca92 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -63,7 +63,7 @@ use middle::trans::type_of; use middle::trans::type_of::*; use middle::ty; use util::common::indenter; -use util::ppaux::ty_to_str; +use util::ppaux::{Repr, ty_to_str}; use util::ppaux; use core::hash; @@ -1592,11 +1592,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, for param_substs.each |p| { p.validate(); } debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \ - param_substs=%s", + param_substs=%s)", path_str(ccx.sess, path), id, impl_id, - opt_param_substs_to_str(ccx.tcx, ¶m_substs)); + param_substs.repr(ccx.tcx)); let llbbs = mk_standard_basic_blocks(llfndecl); return @mut fn_ctxt_ { @@ -1788,6 +1788,9 @@ pub fn trans_closure(ccx: @CrateContext, let _icx = ccx.insn_ctxt("trans_closure"); set_uwtable(llfndecl); + debug!("trans_closure(..., param_substs=%s)", + param_substs.repr(ccx.tcx)); + // Set up arguments to the function. let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs, Some(body.span)); @@ -1849,7 +1852,9 @@ pub fn trans_fn(ccx: @CrateContext, let do_time = ccx.sess.trans_stats(); let start = if do_time { time::get_time() } else { time::Timespec::new(0, 0) }; - debug!("trans_fn(ty_self=%?)", ty_self); + debug!("trans_fn(ty_self=%?, param_substs=%s)", + ty_self, + param_substs.repr(ccx.tcx)); let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; let the_path_str = path_str(ccx.sess, path); diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index de14266573af9..20382676fed21 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -42,6 +42,7 @@ use middle::trans::type_of; use middle::ty; use middle::typeck; use util::common::indenter; +use util::ppaux::Repr; use syntax::ast; use syntax::ast_map; @@ -74,24 +75,13 @@ pub struct Callee { pub fn trans(bcx: block, expr: @ast::expr) -> Callee { let _icx = bcx.insn_ctxt("trans_callee"); + debug!("callee::trans(expr=%s)", expr.repr(bcx.tcx())); // pick out special kinds of expressions that can be called: match expr.node { ast::expr_path(_) => { return trans_def(bcx, bcx.def(expr.id), expr); } - ast::expr_field(base, _, _) => { - match bcx.ccx().maps.method_map.find(&expr.id) { - Some(origin) => { // An impl method - // FIXME(#5562): removing this copy causes a segfault - // before stage2 - let origin = /*bad*/ copy *origin; - return meth::trans_method_callee(bcx, expr.id, - base, origin); - } - None => {} // not a method, just a field - } - } _ => {} } @@ -178,11 +168,13 @@ pub fn trans_fn_ref(bcx: block, * with id `def_id` into a function pointer. This may require * monomorphization or inlining. */ - let _icx = bcx.insn_ctxt("trans_fn"); + let _icx = bcx.insn_ctxt("trans_fn_ref"); let type_params = node_id_type_params(bcx, ref_id); - let vtables = node_vtables(bcx, ref_id); + debug!("trans_fn_ref(def_id=%s, ref_id=%?, type_params=%s, vtables=%s)", + def_id.repr(bcx.tcx()), ref_id, type_params.repr(bcx.tcx()), + vtables.repr(bcx.tcx())); trans_fn_ref_with_vtables(bcx, def_id, ref_id, type_params, vtables) } @@ -224,12 +216,13 @@ pub fn trans_fn_ref_with_vtables( let ccx = bcx.ccx(); let tcx = ccx.tcx; - debug!("trans_fn_ref_with_vtables(bcx=%s, def_id=%?, ref_id=%?, \ - type_params=%?, vtables=%?)", - bcx.to_str(), def_id, ref_id, - type_params.map(|t| bcx.ty_to_str(*t)), - vtables); - let _indenter = indenter(); + debug!("trans_fn_ref_with_vtables(bcx=%s, def_id=%s, ref_id=%?, \ + type_params=%s, vtables=%s)", + bcx.to_str(), + def_id.repr(bcx.tcx()), + ref_id, + type_params.repr(bcx.tcx()), + vtables.repr(bcx.tcx())); assert!(type_params.all(|t| !ty::type_needs_infer(*t))); @@ -335,6 +328,9 @@ pub fn trans_method_call(in_cx: block, dest: expr::Dest) -> block { let _icx = in_cx.insn_ctxt("trans_method_call"); + debug!("trans_method_call(call_ex=%s, rcvr=%s)", + call_ex.repr(in_cx.tcx()), + rcvr.repr(in_cx.tcx())); trans_call_inner( in_cx, call_ex.info(), @@ -343,9 +339,14 @@ pub fn trans_method_call(in_cx: block, |cx| { match cx.ccx().maps.method_map.find(&call_ex.id) { Some(origin) => { + debug!("origin for %s: %s", + call_ex.repr(in_cx.tcx()), + origin.repr(in_cx.tcx())); + // FIXME(#5562): removing this copy causes a segfault // before stage2 let origin = /*bad*/ copy *origin; + meth::trans_method_callee(cx, call_ex.callee_id, rcvr, @@ -641,8 +642,9 @@ pub fn trans_arg_expr(bcx: block, debug!("trans_arg_expr(formal_ty=(%?,%s), arg_expr=%s, \ ret_flag=%?)", - formal_ty.mode, bcx.ty_to_str(formal_ty.ty), - bcx.expr_to_str(arg_expr), + formal_ty.mode, + formal_ty.ty.repr(bcx.tcx()), + arg_expr.repr(bcx.tcx()), ret_flag.map(|v| bcx.val_str(*v))); let _indenter = indenter(); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 593d37c2ff8d1..2cfd7a25d6823 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -41,7 +41,7 @@ use middle::trans::type_use; use middle::ty::substs; use middle::ty; use middle::typeck; -use util::ppaux::{expr_repr, ty_to_str}; +use util::ppaux::{Repr}; use core::cast; use core::hash; @@ -250,7 +250,7 @@ pub enum local_val { local_mem(ValueRef), local_imm(ValueRef), } pub struct param_substs { tys: ~[ty::t], vtables: Option, - bounds: @~[ty::param_bounds], + type_param_defs: @~[ty::TypeParameterDef], self_ty: Option } @@ -261,16 +261,25 @@ pub impl param_substs { } } -pub fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str { - fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}", - substs.tys.map(|t| ty_to_str(tcx, *t)), - substs.vtables.map(|vs| vs.map(|v| v.to_str(tcx))), - substs.bounds.map(|b| ty::param_bounds_to_str(tcx, *b))) +fn param_substs_to_str(self: ¶m_substs, + tcx: ty::ctxt) -> ~str +{ + fmt!("param_substs {tys:%s, vtables:%s, type_param_defs:%s}", + self.tys.repr(tcx), + self.vtables.repr(tcx), + self.type_param_defs.repr(tcx)) } -pub fn opt_param_substs_to_str(tcx: ty::ctxt, - substs: &Option<@param_substs>) -> ~str { - substs.map_default(~"None", |&ps| param_substs_to_str(tcx, ps)) +impl Repr for param_substs { + fn repr(&self, tcx: ty::ctxt) -> ~str { + param_substs_to_str(self, tcx) + } +} + +impl Repr for @param_substs { + fn repr(&self, tcx: ty::ctxt) -> ~str { + param_substs_to_str(*self, tcx) + } } // Function context. Every LLVM function we create will have one of @@ -413,8 +422,9 @@ pub fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t) pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) { if !ty::type_needs_drop(bcx.tcx(), t) { return; } debug!("add_clean(%s, %s, %s)", - bcx.to_str(), val_str(bcx.ccx().tn, val), - ty_to_str(bcx.ccx().tcx, t)); + bcx.to_str(), + val_str(bcx.ccx().tn, val), + t.repr(bcx.tcx())); let (root, rooted) = root_for_cleanup(bcx, val, t); let cleanup_type = cleanup_type(bcx.tcx(), t); do in_scope_cx(bcx) |scope_info| { @@ -429,7 +439,7 @@ pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) { if !ty::type_needs_drop(cx.tcx(), ty) { return; } debug!("add_clean_temp_immediate(%s, %s, %s)", cx.to_str(), val_str(cx.ccx().tn, val), - ty_to_str(cx.ccx().tcx, ty)); + ty.repr(cx.tcx())); let cleanup_type = cleanup_type(cx.tcx(), ty); do in_scope_cx(cx) |scope_info| { scope_info.cleanups.push( @@ -442,7 +452,7 @@ pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) { if !ty::type_needs_drop(bcx.tcx(), t) { return; } debug!("add_clean_temp_mem(%s, %s, %s)", bcx.to_str(), val_str(bcx.ccx().tn, val), - ty_to_str(bcx.ccx().tcx, t)); + t.repr(bcx.tcx())); let (root, rooted) = root_for_cleanup(bcx, val, t); let cleanup_type = cleanup_type(bcx.tcx(), t); do in_scope_cx(bcx) |scope_info| { @@ -455,7 +465,7 @@ pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) { pub fn add_clean_frozen_root(bcx: block, val: ValueRef, t: ty::t) { debug!("add_clean_frozen_root(%s, %s, %s)", bcx.to_str(), val_str(bcx.ccx().tn, val), - ty_to_str(bcx.ccx().tcx, t)); + t.repr(bcx.tcx())); let (root, rooted) = root_for_cleanup(bcx, val, t); let cleanup_type = cleanup_type(bcx.tcx(), t); do in_scope_cx(bcx) |scope_info| { @@ -703,7 +713,7 @@ pub impl block_ { } fn expr_to_str(@mut self, e: @ast::expr) -> ~str { - expr_repr(self.tcx(), e) + e.repr(self.tcx()) } fn expr_is_lval(@mut self, e: @ast::expr) -> bool { @@ -733,7 +743,7 @@ pub impl block_ { } fn ty_to_str(@mut self, t: ty::t) -> ~str { - ty_to_str(self.tcx(), t) + t.repr(self.tcx()) } fn to_str(@mut self) -> ~str { match self.node_info { @@ -1445,14 +1455,14 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin) pub fn find_vtable(tcx: ty::ctxt, ps: ¶m_substs, n_param: uint, n_bound: uint) -> typeck::vtable_origin { - debug!("find_vtable_in_fn_ctxt(n_param=%u, n_bound=%u, ps=%?)", - n_param, n_bound, param_substs_to_str(tcx, ps)); + debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)", + n_param, n_bound, ps.repr(tcx)); // Vtables are stored in a flat array, finding the right one is // somewhat awkward - let first_n_bounds = ps.bounds.slice(0, n_param); + let first_n_type_param_defs = ps.type_param_defs.slice(0, n_param); let vtables_to_skip = - ty::count_traits_and_supertraits(tcx, first_n_bounds); + ty::count_traits_and_supertraits(tcx, first_n_type_param_defs); let vtable_off = vtables_to_skip + n_bound; /*bad*/ copy ps.vtables.get()[vtable_off] } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 55e6b30439ba4..c5e708569dc25 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -25,7 +25,7 @@ use middle::trans::inline; use middle::trans::machine; use middle::trans::type_of; use middle::ty; -use util::ppaux::{expr_repr, ty_to_str}; +use util::ppaux::{Repr, ty_to_str}; use core::libc::c_uint; use syntax::{ast, ast_util, ast_map}; @@ -237,7 +237,7 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef { llvm::LLVMDumpValue(C_undef(llty)); } cx.sess.bug(fmt!("const %s of type %s has size %u instead of %u", - expr_repr(cx.tcx, e), ty_to_str(cx.tcx, ety), + e.repr(cx.tcx), ty_to_str(cx.tcx, ety), csize, tsize)); } llconst diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 2ca19b9075423..15c2e8e3d9350 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -86,13 +86,11 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, csearch::found(ast::ii_method(impl_did, mth)) => { ccx.stats.n_inlines += 1; ccx.external.insert(fn_id, Some(mth.id)); - let ty::ty_param_bounds_and_ty { - generics: ty::Generics { bounds: impl_bnds, _ }, - ty: _ - } = ty::lookup_item_type(ccx.tcx, impl_did); - if translate && - impl_bnds.len() + mth.generics.ty_params.len() == 0u - { + let impl_tpt = ty::lookup_item_type(ccx.tcx, impl_did); + let num_type_params = + impl_tpt.generics.type_param_defs.len() + + mth.generics.ty_params.len(); + if translate && num_type_params == 0 { let llfn = get_item_val(ccx, mth.id); let path = vec::append( ty::item_path(ccx.tcx, impl_did), diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index bbf53480a56fb..c518605faf13a 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -30,7 +30,7 @@ use middle::ty; use middle::ty::arg; use middle::typeck; use util::common::indenter; -use util::ppaux::ty_to_str; +use util::ppaux::Repr; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util; @@ -61,7 +61,7 @@ pub fn trans_impl(ccx: @CrateContext, +path: path, name: ast::ident, param_substs_opt = Some(@param_substs { tys: ~[], vtables: None, - bounds: @~[], + type_param_defs: @~[], self_ty: Some(self_ty) }); } @@ -115,11 +115,8 @@ pub fn trans_method(ccx: @CrateContext, } }; debug!("calling trans_fn with base_self_ty %s, self_ty %s", - match base_self_ty { - None => ~"(none)", - Some(x) => ty_to_str(ccx.tcx, x), - }, - ty_to_str(ccx.tcx, self_ty)); + base_self_ty.repr(ccx.tcx), + self_ty.repr(ccx.tcx)); match method.self_ty.node { ast::sty_value => { impl_owned_self(self_ty) @@ -175,8 +172,9 @@ pub fn trans_method_callee(bcx: block, let _icx = bcx.insn_ctxt("impl::trans_method_callee"); let tcx = bcx.tcx(); - debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)", - callee_id, bcx.expr_to_str(self), mentry); + debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%s)", + callee_id, bcx.expr_to_str(self), + mentry.repr(bcx.tcx())); // Replace method_self with method_static here. let mut origin = mentry.origin; @@ -302,7 +300,8 @@ pub fn trans_static_method_callee(bcx: block, // one we are interested in. let bound_index = { let trait_def = ty::lookup_trait_def(bcx.tcx(), trait_id); - ty::count_traits_and_supertraits(bcx.tcx(), *trait_def.generics.bounds) + ty::count_traits_and_supertraits( + bcx.tcx(), *trait_def.generics.type_param_defs) }; let mname = if method_id.crate == ast::local_crate { @@ -552,14 +551,15 @@ pub fn combine_impl_and_methods_origins(bcx: block, let ccx = bcx.ccx(), tcx = bcx.tcx(); let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); let ty::ty_param_bounds_and_ty { - generics: ty::Generics {bounds: r_m_bounds, _}, + generics: r_m_generics, _ } = ty::lookup_item_type(tcx, mth_did); - let n_r_m_tps = r_m_bounds.len(); // rcvr + method tps - let m_boundss = vec::slice(*r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps); + let n_r_m_tps = r_m_generics.type_param_defs.len(); // rcvr + method tps + let m_type_param_defs = + vec::slice(*r_m_generics.type_param_defs, n_r_m_tps - n_m_tps, n_r_m_tps); // Flatten out to find the number of vtables the method expects. - let m_vtables = ty::count_traits_and_supertraits(tcx, m_boundss); + let m_vtables = ty::count_traits_and_supertraits(tcx, m_type_param_defs); // Find the vtables we computed at type check time and monomorphize them let r_m_origins = match node_vtables(bcx, callee_id) { @@ -787,12 +787,13 @@ pub fn make_impl_vtable(ccx: @CrateContext, // XXX: This should support multiple traits. let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id; - let has_tps = ty::lookup_item_type(ccx.tcx, impl_id).generics.bounds.len() > 0u; + let has_tps = + !ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty(); make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| { let im = ty::method(tcx, *method_def_id); let fty = ty::subst_tps(tcx, substs, None, ty::mk_bare_fn(tcx, copy im.fty)); - if im.generics.bounds.len() > 0u || ty::type_has_self(fty) { + if im.generics.has_type_params() || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", *tcx.sess.str_of(im.ident)); C_null(T_ptr(T_nil())) diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 319f57fb75ce0..97dc3fed780f0 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -30,7 +30,7 @@ use middle::trans::type_use; use middle::ty; use middle::ty::{FnSig}; use middle::typeck; -use util::ppaux::ty_to_str; +use util::ppaux::Repr; use core::vec; use syntax::ast; @@ -46,8 +46,21 @@ pub fn monomorphic_fn(ccx: @CrateContext, real_substs: &[ty::t], vtables: Option, impl_did_opt: Option, - ref_id: Option) -> - (ValueRef, bool) { + ref_id: Option) + -> (ValueRef, bool) +{ + debug!("monomorphic_fn(\ + fn_id=%s, \ + real_substs=%s, \ + vtables=%s, \ + impl_did_opt=%s, \ + ref_id=%?)", + fn_id.repr(ccx.tcx), + real_substs.repr(ccx.tcx), + vtables.repr(ccx.tcx), + impl_did_opt.repr(ccx.tcx), + ref_id); + assert!(real_substs.all(|t| !ty::type_needs_infer(*t))); let _icx = ccx.insn_ctxt("monomorphic_fn"); let mut must_cast = false; @@ -69,13 +82,15 @@ pub fn monomorphic_fn(ccx: @CrateContext, must_cast = true; } - debug!("monomorphic_fn(fn_id=%? (%s), vtables=%?, \ - real_substs=%?, substs=%?, \ - hash_id = %?", - fn_id, ty::item_path_str(ccx.tcx, fn_id), - vtables, - real_substs.map(|s| ty_to_str(ccx.tcx, *s)), - substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id); + debug!("monomorphic_fn(\ + fn_id=%s, \ + vtables=%s, \ + substs=%s, \ + hash_id=%?)", + fn_id.repr(ccx.tcx), + vtables.repr(ccx.tcx), + substs.repr(ccx.tcx), + hash_id); match ccx.monomorphized.find(&hash_id) { Some(&val) => { @@ -169,7 +184,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, let psubsts = Some(@param_substs { tys: substs, vtables: vtables, - bounds: tpt.generics.bounds, + type_param_defs: tpt.generics.type_param_defs, self_ty: impl_ty_opt }); @@ -322,17 +337,19 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, } } -pub fn make_mono_id(ccx: @CrateContext, item: ast::def_id, substs: &[ty::t], +pub fn make_mono_id(ccx: @CrateContext, + item: ast::def_id, + substs: &[ty::t], vtables: Option, impl_did_opt: Option, +param_uses: Option<~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { - let bounds = ty::lookup_item_type(ccx.tcx, item).generics.bounds; + let item_ty = ty::lookup_item_type(ccx.tcx, item); let mut i = 0; - vec::map2(*bounds, substs, |bounds, subst| { + vec::map2(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| { let mut v = ~[]; - for bounds.each |bound| { + for type_param_def.bounds.each |bound| { match *bound { ty::bound_trait(_) => { v.push(meth::vtable_id(ccx, /*bad*/copy vts[i])); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c29029de351e3..742153124346a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -20,12 +20,13 @@ use middle::lint; use middle::resolve::{Impl, MethodInfo}; use middle::resolve; use middle::ty; +use middle::subst::Subst; use middle::typeck; use middle; use util::ppaux::{note_and_explain_region, bound_region_to_str}; use util::ppaux::{region_to_str, vstore_to_str}; use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str}; -use util::ppaux::{trait_ref_to_str}; +use util::ppaux::Repr; use util::common::{indenter}; use core; @@ -277,7 +278,7 @@ struct ctxt_ { tc_cache: @mut HashMap, ast_ty_to_ty_cache: @mut HashMap, enum_var_cache: @mut HashMap, - ty_param_bounds: @mut HashMap, + ty_param_defs: @mut HashMap, inferred_modes: @mut HashMap, adjustments: @mut HashMap, normalized_cache: @mut HashMap, @@ -400,19 +401,12 @@ impl to_bytes::IterBytes for ClosureTy { } } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub struct param_ty { idx: uint, def_id: def_id } -impl to_bytes::IterBytes for param_ty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.idx, &self.def_id, lsb0, f) - } -} - - /// Representation of regions: #[auto_encode] #[auto_decode] @@ -754,13 +748,24 @@ impl to_bytes::IterBytes for RegionVid { } } +pub struct TypeParameterDef { + def_id: ast::def_id, + bounds: param_bounds +} + /// Information about the type/lifetime parametesr associated with an item. /// Analogous to ast::Generics. pub struct Generics { - bounds: @~[param_bounds], + type_param_defs: @~[TypeParameterDef], region_param: Option, } +pub impl Generics { + fn has_type_params(&self) -> bool { + !self.type_param_defs.is_empty() + } +} + /// A polytype. /// /// - `bounds`: The list of bounds for each type parameter. The length of the @@ -853,7 +858,7 @@ pub fn mk_ctxt(s: session::Session, methods: @mut HashMap::new(), trait_method_def_ids: @mut HashMap::new(), trait_methods_cache: @mut HashMap::new(), - ty_param_bounds: @mut HashMap::new(), + ty_param_defs: @mut HashMap::new(), inferred_modes: @mut HashMap::new(), adjustments: @mut HashMap::new(), normalized_cache: new_ty_hash(), @@ -1227,6 +1232,12 @@ pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig { } } +pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy { + BareFnTy {sig: fold_sig(&fty.sig, fldop), + abis: fty.abis, + purity: fty.purity} +} + fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty { fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs { substs {self_r: substs.self_r, @@ -1261,8 +1272,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty { ty_tup(new_ts) } ty_bare_fn(ref f) => { - let sig = fold_sig(&f.sig, fldop); - ty_bare_fn(BareFnTy {sig: sig, abis: f.abis, purity: f.purity}) + ty_bare_fn(fold_bare_fn_ty(f, fldop)) } ty_closure(ref f) => { let sig = fold_sig(&f.sig, fldop); @@ -1409,94 +1419,22 @@ pub fn substs_is_noop(substs: &substs) -> bool { } pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str { - fmt!("substs(self_r=%s, self_ty=%s, tps=%?)", - substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)), - substs.self_ty.map_default(~"none", - |t| ::util::ppaux::ty_to_str(cx, *t)), - tys_to_str(cx, substs.tps)) + substs.repr(cx) } pub fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str { - match *pb { - bound_copy => ~"copy", - bound_durable => ~"'static", - bound_owned => ~"owned", - bound_const => ~"const", - bound_trait(t) => ::util::ppaux::trait_ref_to_str(cx, t) - } + pb.repr(cx) } pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str { - fmt!("%?", pbs.map(|pb| param_bound_to_str(cx, pb))) + pbs.repr(cx) } pub fn subst(cx: ctxt, substs: &substs, typ: t) -> t { - debug!("subst(substs=%s, typ=%s)", - substs_to_str(cx, substs), - ::util::ppaux::ty_to_str(cx, typ)); - - if substs_is_noop(substs) { return typ; } - let r = do_subst(cx, substs, typ); - debug!(" r = %s", ::util::ppaux::ty_to_str(cx, r)); - return r; - - fn do_subst(cx: ctxt, - substs: &substs, - typ: t) -> t { - let tb = get(typ); - if !tbox_has_flag(tb, needs_subst) { return typ; } - match tb.sty { - ty_param(p) => substs.tps[p.idx], - ty_self(_) => substs.self_ty.get(), - _ => { - fold_regions_and_ty( - cx, typ, - |r| match r { - re_bound(br_self) => { - match substs.self_r { - None => { - cx.sess.bug( - fmt!("ty::subst: \ - Reference to self region when given substs \ - with no self region, ty = %s", - ::util::ppaux::ty_to_str(cx, typ))) - } - Some(self_r) => self_r - } - } - _ => r - }, - |t| do_subst(cx, substs, t), - |t| do_subst(cx, substs, t)) - } - } - } -} - -pub fn subst_in_trait_ref(cx: ctxt, - substs: &substs, - trait_ref: &ty::TraitRef) -> ty::TraitRef -{ - ty::TraitRef { - def_id: trait_ref.def_id, - substs: subst_in_substs(cx, substs, &trait_ref.substs) - } -} - -// Performs substitutions on a set of substitutions (result = sup(sub)) to -// yield a new set of substitutions. This is used in trait inheritance. -pub fn subst_in_substs(cx: ctxt, - substs: &substs, - in_substs: &substs) -> substs -{ - substs { - self_r: in_substs.self_r, - self_ty: in_substs.self_ty.map(|&typ| subst(cx, substs, typ)), - tps: in_substs.tps.map(|&typ| subst(cx, substs, typ)) - } + typ.subst(cx, substs) } // Type utilities @@ -1511,6 +1449,10 @@ pub fn type_is_error(ty: t) -> bool { (get(ty).flags & (has_ty_err as uint)) != 0 } +pub fn type_needs_subst(ty: t) -> bool { + tbox_has_flag(get(ty), needs_subst) +} + pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool { tref.substs.self_ty.any(|&t| type_is_error(t)) || tref.substs.tps.any(|&t| type_is_error(t)) @@ -2046,8 +1988,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { // def-id. assert!(p.def_id.crate == ast::local_crate); - param_bounds_to_contents( - cx, *cx.ty_param_bounds.get(&p.def_id.node)) + type_param_def_to_contents( + cx, cx.ty_param_defs.get(&p.def_id.node)) } ty_self(_) => { @@ -2141,13 +2083,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { st + rt + ot } - fn param_bounds_to_contents(cx: ctxt, - bounds: param_bounds) -> TypeContents + fn type_param_def_to_contents(cx: ctxt, + type_param_def: &TypeParameterDef) -> TypeContents { - debug!("param_bounds_to_contents()"); + debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx)); let _i = indenter(); - let r = bounds.foldl(TC_ALL, |tc, bound| { + let r = type_param_def.bounds.foldl(TC_ALL, |tc, bound| { debug!("tc = %s, bound = %?", tc.to_str(), bound); match *bound { bound_copy => tc - TypeContents::nonimplicitly_copyable(cx), @@ -3042,16 +2984,18 @@ pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool { return node_id_has_type_params(cx, expr.id); } -pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, - id: ast::node_id) - -> Option<@~[param_bounds]> { +pub fn method_call_type_param_defs( + tcx: ctxt, + method_map: typeck::method_map, + id: ast::node_id) -> Option<@~[TypeParameterDef]> +{ do method_map.find(&id).map |method| { match method.origin { typeck::method_static(did) => { // n.b.: When we encode impl methods, the bounds // that we encode include both the impl bounds // and then the method bounds themselves... - ty::lookup_item_type(tcx, did).generics.bounds + ty::lookup_item_type(tcx, did).generics.type_param_defs } typeck::method_param(typeck::method_param { trait_id: trt_id, @@ -3062,9 +3006,11 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, // ...trait methods bounds, in contrast, include only the // method bounds, so we must preprend the tps from the // trait itself. This ought to be harmonized. - let trt_bounds = ty::lookup_trait_def(tcx, trt_id).generics.bounds; - @(vec::append(/*bad*/copy *trt_bounds, - *ty::trait_method(tcx, trt_id, n_mth).generics.bounds)) + let trait_type_param_defs = + ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs; + @vec::append( + copy *trait_type_param_defs, + *ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs) } } } @@ -3614,6 +3560,12 @@ pub fn trait_supertraits(cx: ctxt, return result; } +pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] { + let supertrait_refs = trait_supertraits(cx, trait_ref.def_id); + supertrait_refs.map( + |supertrait_ref| @supertrait_ref.subst(cx, &trait_ref.substs)) +} + fn lookup_locally_or_in_crate_store( descr: &str, def_id: ast::def_id, @@ -4327,11 +4279,9 @@ pub fn determine_inherited_purity(parent_purity: ast::purity, // Here, the supertraits are the transitive closure of the supertrait // relation on the supertraits from each bounded trait's constraint // list. -pub fn iter_bound_traits_and_supertraits(tcx: ctxt, +pub fn each_bound_trait_and_supertraits(tcx: ctxt, bounds: param_bounds, f: &fn(&TraitRef) -> bool) { - let mut fin = false; - for bounds.each |bound| { let bound_trait_ref = match *bound { ty::bound_trait(bound_t) => bound_t, @@ -4343,51 +4293,46 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt, }; let mut supertrait_set = HashMap::new(); - let mut seen_def_ids = ~[]; + let mut trait_refs = ~[]; let mut i = 0; - let trait_ty_id = bound_trait_ref.def_id; - let mut trait_ref = bound_trait_ref; - debug!("iter_bound_traits_and_supertraits: trait_ref = %s", - trait_ref_to_str(tcx, trait_ref)); + // Seed the worklist with the trait from the bound + supertrait_set.insert(bound_trait_ref.def_id, ()); + trait_refs.push(bound_trait_ref); // Add the given trait ty to the hash map - supertrait_set.insert(trait_ty_id, ()); - seen_def_ids.push(trait_ty_id); - - if f(trait_ref) { - // Add all the supertraits to the hash map, - // executing on each of them - while i < supertrait_set.len() && !fin { - let init_trait_id = seen_def_ids[i]; - i += 1; - - // Add supertraits to supertrait_set - let supertrait_refs = trait_supertraits(tcx, init_trait_id); - for supertrait_refs.each |&supertrait_ref| { - let d_id = supertrait_ref.def_id; - if !supertrait_set.contains_key(&d_id) { - // FIXME(#5527) Could have same trait multiple times - supertrait_set.insert(d_id, ()); - trait_ref = supertrait_ref; - seen_def_ids.push(d_id); - } - debug!("A super_t = %s", trait_ref_to_str(tcx, trait_ref)); - if !f(trait_ref) { - fin = true; - } + while i < trait_refs.len() { + debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)", + i, trait_refs[i].repr(tcx)); + + if !f(trait_refs[i]) { + return; + } + + // Add supertraits to supertrait_set + let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]); + for supertrait_refs.each |&supertrait_ref| { + debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)", + supertrait_ref.repr(tcx)); + + let d_id = supertrait_ref.def_id; + if !supertrait_set.contains_key(&d_id) { + // FIXME(#5527) Could have same trait multiple times + supertrait_set.insert(d_id, ()); + trait_refs.push(supertrait_ref); } } - }; - fin = false; + + i += 1; + } } } pub fn count_traits_and_supertraits(tcx: ctxt, - boundses: &[param_bounds]) -> uint { + type_param_defs: &[TypeParameterDef]) -> uint { let mut total = 0; - for boundses.each |bounds| { - for iter_bound_traits_and_supertraits(tcx, *bounds) |_trait_ty| { + for type_param_defs.each |type_param_def| { + for each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |_| { total += 1; } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 209091ecd6643..bfc9d646dbb6c 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -135,6 +135,7 @@ fn ast_path_substs( rscope: &RS, def_id: ast::def_id, decl_generics: &ty::Generics, + self_ty: Option, path: @ast::path) -> ty::substs { /*! @@ -172,15 +173,15 @@ fn ast_path_substs( }; // Convert the type parameters supplied by the user. - if !vec::same_length(*decl_generics.bounds, path.types) { + if !vec::same_length(*decl_generics.type_param_defs, path.types) { self.tcx().sess.span_fatal( path.span, fmt!("wrong number of type arguments: expected %u but found %u", - decl_generics.bounds.len(), path.types.len())); + decl_generics.type_param_defs.len(), path.types.len())); } let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t)); - substs {self_r:self_r, self_ty:None, tps:tps} + substs {self_r:self_r, self_ty:self_ty, tps:tps} } pub fn ast_path_to_substs_and_ty( @@ -195,7 +196,7 @@ pub fn ast_path_to_substs_and_ty( ty: decl_ty } = self.get_item_ty(did); - let substs = ast_path_substs(self, rscope, did, &generics, path); + let substs = ast_path_substs(self, rscope, did, &generics, None, path); let ty = ty::subst(tcx, &substs, decl_ty); ty_param_substs_and_ty { substs: substs, ty: ty } } @@ -204,14 +205,18 @@ pub fn ast_path_to_trait_ref( self: &AC, rscope: &RS, trait_def_id: ast::def_id, + self_ty: Option, path: @ast::path) -> @ty::TraitRef { let trait_def = self.get_trait_def(trait_def_id); let substs = ast_path_substs( - self, rscope, - trait_def.trait_ref.def_id, &trait_def.generics, + self, + rscope, + trait_def.trait_ref.def_id, + &trait_def.generics, + self_ty, path); let trait_ref = @ty::TraitRef {def_id: trait_def_id, @@ -280,7 +285,7 @@ pub fn ast_ty_to_ty( } Some(&ast::def_trait(trait_def_id)) => { let result = ast_path_to_trait_ref( - self, rscope, trait_def_id, path); + self, rscope, trait_def_id, None, path); let trait_store = match vst { ty::vstore_box => ty::BoxTraitStore, ty::vstore_uniq => ty::UniqTraitStore, diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 605caba74a380..aa2414eac6240 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -135,7 +135,9 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, ty::enum_variant_with_id(tcx, enm, var); let var_tpt = ty::lookup_item_type(tcx, var); vinfo.args.map(|t| { - if var_tpt.generics.bounds.len() == expected_substs.tps.len() { + if var_tpt.generics.type_param_defs.len() == + expected_substs.tps.len() + { ty::subst(tcx, expected_substs, *t) } else { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index fa3cb43d9abe0..af6a114494b1b 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -94,7 +94,6 @@ use middle::typeck::{method_map_entry, method_origin, method_param}; use middle::typeck::{method_self, method_static, method_trait, method_super}; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use util::common::indenter; -use util::ppaux::expr_repr; use core::hashmap::HashSet; use core::result; @@ -149,8 +148,7 @@ pub fn lookup( autoderef_receiver: autoderef_receiver, }; let mme = lcx.do_lookup(self_ty); - debug!("method lookup for %s yielded %?", - expr_repr(fcx.tcx(), expr), mme); + debug!("method lookup for %s yielded %?", expr.repr(fcx.tcx()), mme); return mme; } @@ -197,9 +195,8 @@ pub impl<'self> LookupContext<'self> { debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)", self.ty_to_str(self_ty), - expr_repr(self.tcx(), self.expr), - expr_repr(self.tcx(), self.self_expr)); - let _indenter = indenter(); + self.expr.repr(self.tcx()), + self.self_expr.repr(self.tcx())); // Prepare the list of candidates self.push_inherent_candidates(self_ty); @@ -379,105 +376,52 @@ pub impl<'self> LookupContext<'self> { let tcx = self.tcx(); let mut next_bound_idx = 0; // count only trait bounds - let bounds = tcx.ty_param_bounds.get(¶m_ty.def_id.node); - - for bounds.each |bound| { - let bound_trait_ref = match *bound { - ty::bound_trait(bound_t) => bound_t, - - ty::bound_copy | ty::bound_owned | - ty::bound_const | ty::bound_durable => { - loop; // skip non-trait bounds + let type_param_def = tcx.ty_param_defs.get(¶m_ty.def_id.node); + + for ty::each_bound_trait_and_supertraits(tcx, type_param_def.bounds) + |bound_trait_ref| + { + let this_bound_idx = next_bound_idx; + next_bound_idx += 1; + + let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id); + let pos = { + match trait_methods.position(|m| { + m.self_ty != ast::sty_static && + m.ident == self.m_name }) + { + Some(pos) => pos, + None => { + debug!("trait doesn't contain method: %?", + bound_trait_ref.def_id); + loop; // check next trait or bound + } } }; + let method = trait_methods[pos]; - // Loop over the trait and all of its supertraits. - let mut worklist = ~[]; - - let init_trait_ref = bound_trait_ref; - - // Replace any appearance of `self` with the type of the - // generic parameter itself. Note that this is the only - // case where this replacement is necessary: in all other - // cases, we are either invoking a method directly from an - // impl or class (where the self type is not permitted), - // or from a trait type (in which case methods that refer - // to self are not permitted). - let init_substs = substs { - self_ty: Some(rcvr_ty), - ..copy bound_trait_ref.substs - }; - - worklist.push((init_trait_ref.def_id, init_substs)); - - let mut i = 0; - while i < worklist.len() { - let (init_trait_id, init_substs) = /*bad*/copy worklist[i]; - i += 1; - - // Add all the supertraits of this trait to the worklist. - let supertraits = ty::trait_supertraits(tcx, init_trait_id); - for supertraits.each |supertrait_ref| { - debug!("adding supertrait: %?", - supertrait_ref.def_id); - - let new_substs = ty::subst_in_substs( - tcx, - &init_substs, - &supertrait_ref.substs); - - // Again replacing the self type - let new_substs = substs { - self_ty: Some(rcvr_ty), - ..new_substs - }; - - worklist.push((supertrait_ref.def_id, new_substs)); - } - - - let this_bound_idx = next_bound_idx; - next_bound_idx += 1; - - let trait_methods = ty::trait_methods(tcx, init_trait_id); - let pos = { - match trait_methods.position(|m| { - m.self_ty != ast::sty_static && - m.ident == self.m_name }) - { - Some(pos) => pos, - None => { - debug!("trait doesn't contain method: %?", - init_trait_id); - loop; // check next trait or bound - } - } - }; - let method = trait_methods[pos]; - - let (rcvr_ty, rcvr_substs) = - self.create_rcvr_ty_and_substs_for_method( - method.self_ty, - rcvr_ty, - init_substs, - TransformTypeNormally); + let (rcvr_ty, rcvr_substs) = + self.create_rcvr_ty_and_substs_for_method( + method.self_ty, + rcvr_ty, + copy bound_trait_ref.substs, + TransformTypeNormally); - let cand = Candidate { - rcvr_ty: rcvr_ty, - rcvr_substs: rcvr_substs, - method_ty: method, - origin: method_param( - method_param { - trait_id: init_trait_id, - method_num: pos, - param_num: param_ty.idx, - bound_num: this_bound_idx, - }) - }; + let cand = Candidate { + rcvr_ty: rcvr_ty, + rcvr_substs: rcvr_substs, + method_ty: method, + origin: method_param( + method_param { + trait_id: bound_trait_ref.def_id, + method_num: pos, + param_num: param_ty.idx, + bound_num: this_bound_idx, + }) + }; - debug!("pushing inherent candidate for param: %?", cand); - self.inherent_candidates.push(cand); - } + debug!("pushing inherent candidate for param: %?", cand); + self.inherent_candidates.push(cand); } } @@ -499,7 +443,7 @@ pub impl<'self> LookupContext<'self> { }; let method = ms[index]; - /* FIXME(#3157) we should transform the vstore in accordance + /* FIXME(#5762) we should transform the vstore in accordance with the self type match method.self_type { @@ -517,6 +461,9 @@ pub impl<'self> LookupContext<'self> { // `trait_ty` for `self` here, because it allows the compiler // to soldier on. An error will be reported should this // candidate be selected if the method refers to `self`. + // + // NB: `confirm_candidate()` also relies upon this substitution + // for Self. let rcvr_substs = substs { self_ty: Some(self_ty), ../*bad*/copy *substs @@ -1075,7 +1022,7 @@ pub impl<'self> LookupContext<'self> { let fty = self.fn_ty_from_origin(&candidate.origin); debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)", - expr_repr(tcx, self.expr), + self.expr.repr(tcx), self.cand_to_str(candidate), self.ty_to_str(fty)); @@ -1101,7 +1048,7 @@ pub impl<'self> LookupContext<'self> { // If they were not explicitly supplied, just construct fresh // type variables. let num_supplied_tps = self.supplied_tps.len(); - let num_method_tps = candidate.method_ty.generics.bounds.len(); + let num_method_tps = candidate.method_ty.generics.type_param_defs.len(); let m_substs = { if num_supplied_tps == 0u { self.fcx.infcx().next_ty_vars(num_method_tps) @@ -1195,7 +1142,7 @@ pub impl<'self> LookupContext<'self> { self-type through a boxed trait"); } - if candidate.method_ty.generics.bounds.len() > 0 { + if candidate.method_ty.generics.has_type_params() { self.tcx().sess.span_err( self.expr.span, ~"cannot call a generic method through a boxed trait"); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index c3ec2d14d83d0..2455201907447 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -107,7 +107,7 @@ use middle::typeck::{isr_alist, lookup_def_ccx}; use middle::typeck::no_params; use middle::typeck::{require_same_types, method_map, vtable_map}; use util::common::{block_query, indenter, loop_query}; -use util::ppaux::{bound_region_to_str, expr_repr, pat_repr}; +use util::ppaux::{bound_region_to_str}; use util::ppaux; use core::hashmap::HashMap; @@ -610,7 +610,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { } else { for m.items.each |item| { let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id)); - if !tpt.generics.bounds.is_empty() { + if tpt.generics.has_type_params() { ccx.tcx.sess.span_err( item.span, fmt!("foreign items may not have type parameters")); @@ -761,11 +761,11 @@ pub impl FnCtxt { } fn expr_to_str(&self, expr: @ast::expr) -> ~str { - expr_repr(self.tcx(), expr) + expr.repr(self.tcx()) } fn pat_to_str(&self, pat: @ast::pat) -> ~str { - pat_repr(self.tcx(), pat) + pat.repr(self.tcx()) } fn expr_ty(&self, ex: @ast::expr) -> ty::t { @@ -1068,7 +1068,7 @@ pub fn impl_self_ty(vcx: &VtableContext, let (n_tps, region_param, raw_ty) = { let ity = ty::lookup_item_type(tcx, did); - (ity.generics.bounds.len(), ity.generics.region_param, ity.ty) + (ity.generics.type_param_defs.len(), ity.generics.region_param, ity.ty) }; let self_r = if region_param.is_some() { @@ -1893,7 +1893,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } else { let item_type = ty::lookup_item_type(tcx, class_id); - type_parameter_count = item_type.generics.bounds.len(); + type_parameter_count = item_type.generics.type_param_defs.len(); region_parameterized = item_type.generics.region_param; raw_type = item_type.ty; } @@ -1981,7 +1981,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } else { let item_type = ty::lookup_item_type(tcx, enum_id); - type_parameter_count = item_type.generics.bounds.len(); + type_parameter_count = item_type.generics.type_param_defs.len(); region_parameterized = item_type.generics.region_param; raw_type = item_type.ty; } @@ -3153,7 +3153,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, // extern functions are just u8 pointers return ty_param_bounds_and_ty { generics: ty::Generics { - bounds: @~[], + type_param_defs: @~[], region_param: None }, ty: ty::mk_ptr( @@ -3218,7 +3218,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, region_lb: ty::Region) { debug!(">>> instantiate_path"); - let ty_param_count = tpt.generics.bounds.len(); + let ty_param_count = tpt.generics.type_param_defs.len(); let ty_substs_len = vec::len(pth.types); debug!("ty_param_count=%? ty_substs_len=%?", @@ -3692,7 +3692,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { output: output} }); let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id)); - let i_n_tps = i_ty.generics.bounds.len(); + let i_n_tps = i_ty.generics.type_param_defs.len(); if i_n_tps != n_tps { tcx.sess.span_err(it.span, fmt!("intrinsic has wrong number \ of type parameters: found %u, \ diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index c30765baf37b3..6ea668605fd4d 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -20,6 +20,7 @@ use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; use middle::typeck::infer; use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res}; use middle::typeck::vtable_static; +use middle::subst::Subst; use util::common::indenter; use util::ppaux::tys_to_str; use util::ppaux; @@ -27,7 +28,6 @@ use util::ppaux; use core::result::{Ok, Err}; use core::result; use core::uint; -use core::vec; use core::hashmap::HashSet; use syntax::ast; use syntax::ast_util; @@ -70,45 +70,43 @@ pub impl VtableContext { fn tcx(&const self) -> ty::ctxt { self.ccx.tcx } } -fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool { - vec::any(tps, |bs| { - bs.any(|b| { - match b { &ty::bound_trait(_) => true, _ => false } - }) - }) +fn has_trait_bounds(type_param_defs: &[ty::TypeParameterDef]) -> bool { + type_param_defs.any( + |type_param_def| type_param_def.bounds.any( + |bound| match bound { &ty::bound_trait(*) => true, _ => false })) } fn lookup_vtables(vcx: &VtableContext, location_info: &LocationInfo, - bounds: @~[ty::param_bounds], + type_param_defs: &[ty::TypeParameterDef], substs: &ty::substs, is_early: bool) -> vtable_res { - debug!("lookup_vtables(location_info=%?, - # bounds=%?, \ + debug!("lookup_vtables(location_info=%?, \ + type_param_defs=%s, \ substs=%s", location_info, - bounds.len(), - ty::substs_to_str(vcx.tcx(), substs)); + type_param_defs.repr(vcx.tcx()), + substs.repr(vcx.tcx())); let _i = indenter(); let tcx = vcx.tcx(); let mut result = ~[], i = 0u; for substs.tps.each |ty| { - for ty::iter_bound_traits_and_supertraits( - tcx, bounds[i]) |trait_ref| + // ty is the value supplied for the type parameter A... + + for ty::each_bound_trait_and_supertraits( + tcx, type_param_defs[i].bounds) |trait_ref| { - debug!("about to subst: %?, %?", - ppaux::trait_ref_to_str(tcx, trait_ref), - ty::substs_to_str(tcx, substs)); + // ...and here trait_ref is each bound that was declared on A, + // expressed in terms of the type parameters. + + debug!("about to subst: %s, %s", trait_ref.repr(tcx), substs.repr(tcx)); - let new_substs = substs { - self_ty: Some(*ty), - ../*bad*/copy *substs - }; - let trait_ref = ty::subst_in_trait_ref(tcx, &new_substs, trait_ref); + // Substitute the values of the type parameters that may + // appear in the bound. + let trait_ref = trait_ref.subst(tcx, substs); - debug!("after subst: %?", - vcx.infcx.trait_ref_to_str(&trait_ref)); + debug!("after subst: %s", trait_ref.repr(tcx)); match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) { Some(vtable) => result.push(vtable), @@ -125,14 +123,14 @@ fn lookup_vtables(vcx: &VtableContext, i += 1u; } debug!("lookup_vtables result(\ - location_info=%?, - # bounds=%?, \ + location_info=%?, \ + type_param_defs=%s, \ substs=%s, \ - result=%?", + result=%s)", location_info, - bounds.len(), - ty::substs_to_str(vcx.tcx(), substs), - result); + type_param_defs.repr(vcx.tcx()), + substs.repr(vcx.tcx()), + result.repr(vcx.tcx())); @result } @@ -219,12 +217,11 @@ fn lookup_vtable(vcx: &VtableContext, match ty::get(ty).sty { ty::ty_param(param_ty {idx: n, def_id: did}) => { let mut n_bound = 0; - let bounds = *tcx.ty_param_bounds.get(&did.node); - for ty::iter_bound_traits_and_supertraits( - tcx, bounds) |bound_trait_ref| + let type_param_def = tcx.ty_param_defs.get(&did.node); + for ty::each_bound_trait_and_supertraits( + tcx, type_param_def.bounds) |bound_trait_ref| { - debug!("checking bounds trait %?", - vcx.infcx.trait_ref_to_str(bound_trait_ref)); + debug!("checking bounds trait %s", bound_trait_ref.repr(vcx.tcx())); if bound_trait_ref.def_id == trait_ref.def_id { relate_trait_refs(vcx, @@ -302,6 +299,8 @@ fn lookup_vtable(vcx: &VtableContext, // of the thing that we're trying to cast // to some_trait. If not, then we try the next // impl. + // + // FIXME(#5781) this should be mk_eqty not mk_subty let ty::ty_param_substs_and_ty { substs: substs, ty: for_ty @@ -341,8 +340,7 @@ fn lookup_vtable(vcx: &VtableContext, vcx.infcx.trait_ref_to_str(trait_ref), vcx.infcx.trait_ref_to_str(of_trait_ref)); - let of_trait_ref = - ty::subst_in_trait_ref(tcx, &substs, of_trait_ref); + let of_trait_ref = of_trait_ref.subst(tcx, &substs); relate_trait_refs( vcx, location_info, &of_trait_ref, trait_ref); @@ -387,15 +385,16 @@ fn lookup_vtable(vcx: &VtableContext, // to. connect_trait_tps requires these // lists of types to unify pairwise. - let im_bs = - ty::lookup_item_type(tcx, im.did).generics.bounds; + let im_generics = + ty::lookup_item_type(tcx, im.did).generics; connect_trait_tps(vcx, location_info, &substs_f, trait_ref, im.did); let subres = lookup_vtables( - vcx, location_info, im_bs, &substs_f, + vcx, location_info, + *im_generics.type_param_defs, &substs_f, is_early); // Finally, we register that we found a @@ -460,15 +459,15 @@ fn connect_trait_tps(vcx: &VtableContext, // XXX: This should work for multiple traits. let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0]; - let impl_trait_ref = ty::subst_in_trait_ref(tcx, impl_substs, impl_trait_ref); - relate_trait_refs(vcx, location_info, trait_ref, &impl_trait_ref); + let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs); + relate_trait_refs(vcx, location_info, &impl_trait_ref, trait_ref); } fn insert_vtables(fcx: @mut FnCtxt, callee_id: ast::node_id, vtables: vtable_res) { debug!("insert_vtables(callee_id=%d, vtables=%?)", - callee_id, vtables.map(|v| v.to_str(fcx.tcx()))); + callee_id, vtables.repr(fcx.tcx())); fcx.inh.vtable_map.insert(callee_id, vtables); } @@ -493,17 +492,15 @@ pub fn early_resolve_expr(ex: @ast::expr, let def = *cx.tcx.def_map.get(&ex.id); let did = ast_util::def_id_of_def(def); let item_ty = ty::lookup_item_type(cx.tcx, did); - debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def, + debug!("early resolve expr: def %? %?, %?, %s", ex.id, did, def, fcx.infcx().ty_to_str(item_ty.ty)); - if has_trait_bounds(/*bad*/copy *item_ty.generics.bounds) { - for item_ty.generics.bounds.each |bounds| { - debug!("early_resolve_expr: looking up vtables for bound \ - %s", - ty::param_bounds_to_str(fcx.tcx(), *bounds)); - } + if has_trait_bounds(*item_ty.generics.type_param_defs) { + debug!("early_resolve_expr: looking up vtables for type params %s", + item_ty.generics.type_param_defs.repr(fcx.tcx())); let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), - item_ty.generics.bounds, substs, is_early); + *item_ty.generics.type_param_defs, + substs, is_early); if !is_early { insert_vtables(fcx, ex.id, vtbls); } @@ -519,9 +516,9 @@ pub fn early_resolve_expr(ex: @ast::expr, ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*) | ast::expr_index(*) | ast::expr_method_call(*) => { - match ty::method_call_bounds(cx.tcx, fcx.inh.method_map, ex.id) { - Some(bounds) => { - if has_trait_bounds(/*bad*/copy *bounds) { + match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) { + Some(type_param_defs) => { + if has_trait_bounds(*type_param_defs) { let callee_id = match ex.node { ast::expr_field(_, _, _) => ex.id, _ => ex.callee_id @@ -530,7 +527,7 @@ pub fn early_resolve_expr(ex: @ast::expr, let substs = fcx.node_ty_substs(callee_id); let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), - bounds, &substs, is_early); + *type_param_defs, &substs, is_early); if !is_early { insert_vtables(fcx, callee_id, vtbls); } @@ -561,7 +558,11 @@ pub fn early_resolve_expr(ex: @ast::expr, }; let target_trait_ref = ty::TraitRef { def_id: target_def_id, - substs: copy *target_substs + substs: ty::substs { + tps: copy target_substs.tps, + self_r: target_substs.self_r, + self_ty: Some(mt.ty) + } }; let vtable_opt = lookup_vtable(&vcx, diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 31301db2a0a1b..3af4cb7f10cb4 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -91,7 +91,7 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) { let vtable_map = fcx.ccx.vtable_map; vtable_map.insert(id, r_origins); debug!("writeback::resolve_vtable_map_entry(id=%d, vtables=%?)", - id, r_origins.map(|v| v.to_str(fcx.tcx()))); + id, r_origins.repr(fcx.tcx())); } } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index b0e5ecee01ebb..174a20dd7f4c7 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -32,6 +32,7 @@ use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup}; use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec}; use middle::ty::{type_is_ty_var}; +use middle::subst::Subst; use middle::ty; use middle::typeck::CrateCtxt; use middle::typeck::infer::combine::Combine; @@ -59,7 +60,7 @@ use core::uint; pub struct UniversalQuantificationResult { monotype: t, type_variables: ~[ty::t], - bounds: @~[param_bounds] + type_param_defs: @~[ty::TypeParameterDef] } pub fn get_base_type(inference_context: @mut InferCtxt, @@ -269,17 +270,16 @@ pub impl CoherenceChecker { // We only want to generate one Impl structure. When we generate one, // we store it here so that we don't recreate it. let mut implementation_opt = None; - for associated_traits.each |associated_trait| { - let trait_did = - self.trait_ref_to_trait_def_id(*associated_trait); - debug!("(checking implementation) adding impl for trait \ - '%s', item '%s'", - ast_map::node_id_to_str( - self.crate_context.tcx.items, trait_did.node, - self.crate_context.tcx.sess.parse_sess.interner), - *self.crate_context.tcx.sess.str_of(item.ident)); - - self.instantiate_default_methods(item.id, trait_did); + for associated_traits.each |&associated_trait| { + let trait_ref = + ty::node_id_to_trait_ref( + self.crate_context.tcx, + associated_trait.ref_id); + debug!("(checking implementation) adding impl for trait '%s', item '%s'", + trait_ref.repr(self.crate_context.tcx), + *self.crate_context.tcx.sess.str_of(item.ident)); + + self.instantiate_default_methods(item.id, trait_ref); let implementation; if implementation_opt.is_none() { @@ -287,7 +287,7 @@ pub impl CoherenceChecker { implementation_opt = Some(implementation); } - self.add_trait_method(trait_did, implementation_opt.get()); + self.add_trait_method(trait_ref.def_id, implementation_opt.get()); } // Add the implementation to the mapping from implementation to base @@ -325,22 +325,48 @@ pub impl CoherenceChecker { // Creates default method IDs and performs type substitutions for an impl // and trait pair. Then, for each provided method in the trait, inserts a // `ProvidedMethodInfo` instance into the `provided_method_sources` map. - fn instantiate_default_methods(&self, impl_id: ast::node_id, - trait_did: ast::def_id) { - for self.each_provided_trait_method(trait_did) |trait_method| { + fn instantiate_default_methods(&self, + impl_id: ast::node_id, + trait_ref: &ty::TraitRef) { + let tcx = self.crate_context.tcx; + debug!("instantiate_default_methods(impl_id=%?, trait_ref=%s)", + impl_id, trait_ref.repr(tcx)); + + let impl_poly_type = ty::lookup_item_type(tcx, local_def(impl_id)); + + for self.each_provided_trait_method(trait_ref.def_id) |trait_method| { // Synthesize an ID. - let tcx = self.crate_context.tcx; let new_id = parse::next_node_id(tcx.sess.parse_sess); let new_did = local_def(new_id); - let new_method_ty = @ty::method { - def_id: new_did, - ..copy *trait_method + debug!("new_did=%? trait_method=%s", new_did, trait_method.repr(tcx)); + + // Create substitutions for the various trait parameters. + let new_method_ty = + @subst_receiver_types_in_method_ty( + tcx, + impl_id, + trait_ref, + new_did, + trait_method); + + debug!("new_method_ty=%s", new_method_ty.repr(tcx)); + + // construct the polytype for the method based on the method_ty + let new_generics = ty::Generics { + type_param_defs: + @vec::append( + copy *impl_poly_type.generics.type_param_defs, + *new_method_ty.generics.type_param_defs), + region_param: + impl_poly_type.generics.region_param + }; + let new_polytype = ty::ty_param_bounds_and_ty { + generics: new_generics, + ty: ty::mk_bare_fn(tcx, copy new_method_ty.fty) }; + debug!("new_polytype=%s", new_polytype.repr(tcx)); - // XXX: Perform substitutions. - let new_polytype = ty::lookup_item_type(tcx, - trait_method.def_id); tcx.tcache.insert(new_did, new_polytype); tcx.methods.insert(new_did, new_method_ty); @@ -358,7 +384,7 @@ pub impl CoherenceChecker { @ProvidedMethodInfo { method_info: @MethodInfo { did: new_did, - n_tps: trait_method.generics.bounds.len(), + n_tps: trait_method.generics.type_param_defs.len(), ident: trait_method.ident, self_type: trait_method.self_ty }, @@ -545,9 +571,8 @@ pub impl CoherenceChecker { polytype.generics.region_param.map( |_r| self.inference_context.next_region_var_nb(dummy_sp())); - let bounds_count = polytype.generics.bounds.len(); - let type_parameters = - self.inference_context.next_ty_vars(bounds_count); + let bounds_count = polytype.generics.type_param_defs.len(); + let type_parameters = self.inference_context.next_ty_vars(bounds_count); let substitutions = substs { self_r: self_region, @@ -565,7 +590,7 @@ pub impl CoherenceChecker { UniversalQuantificationResult { monotype: monotype, type_variables: type_parameters, - bounds: polytype.generics.bounds + type_param_defs: polytype.generics.type_param_defs } } @@ -582,13 +607,13 @@ pub impl CoherenceChecker { // Check to ensure that each parameter binding respected its // kind bounds. for [ a, b ].each |result| { - for vec::each2(result.type_variables, *result.bounds) - |ty_var, bounds| { + for vec::each2(result.type_variables, *result.type_param_defs) + |ty_var, type_param_def| { match resolve_type(self.inference_context, *ty_var, resolve_nested_tvar) { Ok(resolved_ty) => { - for bounds.each |bound| { + for type_param_def.bounds.each |bound| { match *bound { bound_copy => { if !ty::type_is_copyable( @@ -914,7 +939,7 @@ pub impl CoherenceChecker { @ProvidedMethodInfo { method_info: @MethodInfo { did: new_did, - n_tps: trait_method_info.ty.generics.bounds.len(), + n_tps: trait_method_info.ty.generics.type_param_defs.len(), ident: trait_method_info.ty.ident, self_type: trait_method_info.ty.self_ty }, @@ -1010,6 +1035,70 @@ pub impl CoherenceChecker { } } +fn subst_receiver_types_in_method_ty( + tcx: ty::ctxt, + impl_id: ast::node_id, + trait_ref: &ty::TraitRef, + new_def_id: ast::def_id, + method: &ty::method) -> ty::method +{ + /*! + * Substitutes the values for the receiver's type parameters + * that are found in method, leaving the method's type parameters + * intact. This is in fact a mildly complex operation, + * largely because of the hokey way that we concatenate the + * receiver and method generics. + */ + + // determine how many type parameters were declared on the impl + let num_impl_type_parameters = { + let impl_polytype = ty::lookup_item_type(tcx, local_def(impl_id)); + impl_polytype.generics.type_param_defs.len() + }; + + // determine how many type parameters appear on the trait + let num_trait_type_parameters = trait_ref.substs.tps.len(); + + // the current method type has the type parameters from the trait + method + let num_method_type_parameters = + num_trait_type_parameters + method.generics.type_param_defs.len(); + + // the new method type will have the type parameters from the impl + method + let combined_tps = vec::from_fn(num_method_type_parameters, |i| { + if i < num_trait_type_parameters { + // replace type parameters that come from trait with new value + trait_ref.substs.tps[i] + } else { + // replace type parameters that belong to method with another + // type parameter, this time with the index adjusted + let method_index = i - num_trait_type_parameters; + let type_param_def = &method.generics.type_param_defs[method_index]; + let new_index = num_impl_type_parameters + method_index; + ty::mk_param(tcx, new_index, type_param_def.def_id) + } + }); + + let combined_substs = ty::substs { + self_r: trait_ref.substs.self_r, + self_ty: trait_ref.substs.self_ty, + tps: combined_tps + }; + + ty::method { + ident: method.ident, + + // method tps cannot appear in the self_ty, so use `substs` from trait ref + transformed_self_ty: method.transformed_self_ty.subst(tcx, &trait_ref.substs), + + // method types *can* appear in the generic bounds or the fty + generics: method.generics.subst(tcx, &combined_substs), + fty: method.fty.subst(tcx, &combined_substs), + self_ty: method.self_ty, + vis: method.vis, + def_id: new_def_id + } +} + pub fn check_coherence(crate_context: @mut CrateCtxt, crate: @crate) { let coherence_checker = @CoherenceChecker(crate_context); coherence_checker.check_coherence(crate); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a9d54716cd8a8..ca1a3a363ea08 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -35,6 +35,7 @@ use core::prelude::*; use metadata::csearch; use middle::ty::{substs, ty_param_bounds_and_ty}; use middle::ty; +use middle::subst::Subst; use middle::typeck::astconv::{AstConv, ty_of_arg}; use middle::typeck::astconv::{ast_ty_to_ty}; use middle::typeck::astconv; @@ -186,7 +187,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, ast::struct_variant_kind(struct_def) => { let tpt = ty_param_bounds_and_ty { - generics: ty_generics(ccx, rp, generics), + generics: ty_generics(ccx, rp, generics, 0), ty: enum_ty }; @@ -207,7 +208,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, None => {} Some(result_ty) => { let tpt = ty_param_bounds_and_ty { - generics: ty_generics(ccx, rp, generics), + generics: ty_generics(ccx, rp, generics, 0), ty: result_ty }; tcx.tcache.insert(local_def(variant.node.id), tpt); @@ -227,7 +228,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, node: ast::item_trait(ref generics, _, ref ms), _ }, _) => { - let trait_ty_generics = ty_generics(ccx, region_paramd, generics); + let trait_ty_generics = ty_generics(ccx, region_paramd, generics, 0); // For each method, construct a suitable ty::method and // store it into the `tcx.methods` table: @@ -274,48 +275,99 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::node_id, m: &ty::method, trait_ty_generics: &ty::Generics) { - // We need to create a typaram that replaces self. This param goes - // *in between* the typarams from the trait and those from the - // method (since its bound can depend on the trait? or - // something like that). + // If declaration is + // + // trait { + // fn foo(...) -> Self; + // } + // + // and we will create a function like + // + // fn foo(...) -> D' {} + // + // Note that `Self` is replaced with an explicit type + // parameter D' that is sandwiched in between the trait params + // and the method params, and thus the indices of the method + // type parameters are offset by 1 (that is, the method + // parameters are mapped from D, E, F to E', F', and G'). The + // choice of this ordering is somewhat arbitrary. + // + // Also, this system is rather a hack that should be replaced + // with a more uniform treatment of Self (which is partly + // underway). // build up a subst that shifts all of the parameters over // by one and substitute in a new type param for self + let tcx = ccx.tcx; + let dummy_defid = ast::def_id {crate: 0, node: 0}; - let num_trait_bounds = trait_ty_generics.bounds.len(); + // Represents [A',B',C'] + let num_trait_bounds = trait_ty_generics.type_param_defs.len(); let non_shifted_trait_tps = do vec::from_fn(num_trait_bounds) |i| { - ty::mk_param(ccx.tcx, i, dummy_defid) + ty::mk_param(tcx, i, dummy_defid) }; - let self_param = ty::mk_param(ccx.tcx, num_trait_bounds, + + // Represents [D'] + let self_param = ty::mk_param(tcx, num_trait_bounds, dummy_defid); - let shifted_method_tps = do vec::from_fn(m.generics.bounds.len()) |i| { - ty::mk_param(ccx.tcx, i + 1, dummy_defid) + + // Represents [E',F',G'] + let num_method_bounds = m.generics.type_param_defs.len(); + let shifted_method_tps = do vec::from_fn(num_method_bounds) |i| { + ty::mk_param(tcx, i + 1, dummy_defid) }; + // build up the substitution from + // A,B,C => A',B',C' + // Self => D' + // D,E,F => E',F',G' let substs = substs { self_r: None, self_ty: Some(self_param), tps: non_shifted_trait_tps + shifted_method_tps }; - let ty = ty::subst(ccx.tcx, + + // create the type of `foo`, applying the substitution above + let ty = ty::subst(tcx, &substs, - ty::mk_bare_fn(ccx.tcx, copy m.fty)); - let trait_def = get_trait_def(ccx, local_def(trait_id)); - let trait_ref = trait_def.trait_ref; - let mut new_bounds = ~[]; - new_bounds.push_all(*trait_ty_generics.bounds); - new_bounds.push(@~[ty::bound_trait(trait_ref)]); - new_bounds.push_all(*m.generics.bounds); - ccx.tcx.tcache.insert(m.def_id, - ty_param_bounds_and_ty { - generics: ty::Generics { - bounds: @new_bounds, - region_param: trait_ty_generics.region_param - }, - ty: ty - }); + ty::mk_bare_fn(tcx, copy m.fty)); + + // create the type parameter definitions for `foo`, applying + // the substutition to any traits that appear in their bounds. + + // add in the type parameters from the trait + let mut new_type_param_defs = ~[]; + let substd_type_param_defs = + trait_ty_generics.type_param_defs.subst(tcx, &substs); + new_type_param_defs.push_all(*substd_type_param_defs); + + // add in the "self" type parameter + let self_trait_def = get_trait_def(ccx, local_def(trait_id)); + let self_trait_ref = @self_trait_def.trait_ref.subst(tcx, &substs); + new_type_param_defs.push(ty::TypeParameterDef { + def_id: dummy_defid, + bounds: @~[ty::bound_trait(self_trait_ref)] + }); + + // add in the type parameters from the method + let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs); + new_type_param_defs.push_all(*substd_type_param_defs); + + debug!("static method %s type_param_defs=%s substs=%s", + m.def_id.repr(tcx), + new_type_param_defs.repr(tcx), + substs.repr(tcx)); + + tcx.tcache.insert(m.def_id, + ty_param_bounds_and_ty { + generics: ty::Generics { + type_param_defs: @new_type_param_defs, + region_param: trait_ty_generics.region_param + }, + ty: ty + }); } fn ty_method_of_trait_method(self: &CrateCtxt, @@ -334,9 +386,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, let (transformed_self_ty, fty) = astconv::ty_of_method(self, &rscope, *m_purity, &m_generics.lifetimes, trait_self_ty, *m_self_ty, m_decl); + let num_trait_type_params = trait_generics.ty_params.len(); ty::method { ident: *m_ident, - generics: ty_generics(self, None, m_generics), + generics: ty_generics(self, None, m_generics, num_trait_type_params), transformed_self_ty: transformed_self_ty, fty: fty, self_ty: m_self_ty.node, @@ -357,9 +410,11 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, let tcx = ccx.tcx; if tcx.supertraits.contains_key(&local_def(id)) { return; } + let self_ty = ty::mk_self(ccx.tcx, local_def(id)); let mut ty_trait_refs: ~[@ty::TraitRef] = ~[]; for ast_trait_refs.each |&ast_trait_ref| { - let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics); + let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, + generics, self_ty); // FIXME(#5527) Could have same trait multiple times if ty_trait_refs.any(|other_trait| other_trait.def_id == trait_ref.def_id) { @@ -426,15 +481,18 @@ pub fn compare_impl_method(tcx: ty::ctxt, } } - if impl_m.generics.bounds.len() != trait_m.generics.bounds.len() { + let num_impl_m_type_params = impl_m.generics.type_param_defs.len(); + let num_trait_m_type_params = trait_m.generics.type_param_defs.len(); + if num_impl_m_type_params != num_trait_m_type_params { tcx.sess.span_err( cm.span, fmt!("method `%s` has %u type %s, but its trait \ declaration has %u type %s", - *tcx.sess.str_of(trait_m.ident), impl_m.generics.bounds.len(), - pluralize(impl_m.generics.bounds.len(), ~"parameter"), - trait_m.generics.bounds.len(), - pluralize(trait_m.generics.bounds.len(), ~"parameter"))); + *tcx.sess.str_of(trait_m.ident), + num_impl_m_type_params, + pluralize(num_impl_m_type_params, ~"parameter"), + num_trait_m_type_params, + pluralize(num_trait_m_type_params, ~"parameter"))); return; } @@ -452,23 +510,23 @@ pub fn compare_impl_method(tcx: ty::ctxt, // FIXME(#2687)---we should be checking that the bounds of the // trait imply the bounds of the subtype, but it appears // we are...not checking this. - for trait_m.generics.bounds.eachi() |i, trait_param_bounds| { + for trait_m.generics.type_param_defs.eachi |i, trait_param_def| { // For each of the corresponding impl ty param's bounds... - let impl_param_bounds = impl_m.generics.bounds[i]; + let impl_param_def = &impl_m.generics.type_param_defs[i]; // Make sure the bounds lists have the same length // Would be nice to use the ty param names in the error message, // but we don't have easy access to them here - if impl_param_bounds.len() != trait_param_bounds.len() { + if impl_param_def.bounds.len() != trait_param_def.bounds.len() { tcx.sess.span_err( cm.span, fmt!("in method `%s`, \ type parameter %u has %u %s, but the same type \ parameter in its trait declaration has %u %s", *tcx.sess.str_of(trait_m.ident), - i, impl_param_bounds.len(), - pluralize(impl_param_bounds.len(), ~"bound"), - trait_param_bounds.len(), - pluralize(trait_param_bounds.len(), ~"bound"))); + i, impl_param_def.bounds.len(), + pluralize(impl_param_def.bounds.len(), ~"bound"), + trait_param_def.bounds.len(), + pluralize(trait_param_def.bounds.len(), ~"bound"))); return; } } @@ -492,12 +550,12 @@ pub fn compare_impl_method(tcx: ty::ctxt, debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty)); replace_bound_self(tcx, impl_fty, dummy_self_r) }; - debug!("impl_fty: %s", ppaux::ty_to_str(tcx, impl_fty)); + debug!("impl_fty (post-subst): %s", ppaux::ty_to_str(tcx, impl_fty)); let trait_fty = { - let dummy_tps = do vec::from_fn(trait_m.generics.bounds.len()) |i| { - // hack: we don't know the def id of the impl tp, but it - // is not important for unification - ty::mk_param(tcx, i + impl_tps, ast::def_id {crate: 0, node: 0}) + let num_trait_m_type_params = trait_m.generics.type_param_defs.len(); + let dummy_tps = do vec::from_fn(num_trait_m_type_params) |i| { + ty::mk_param(tcx, i + impl_tps, + impl_m.generics.type_param_defs[i].def_id) }; let trait_tps = trait_substs.tps.map( |t| replace_bound_self(tcx, *t, dummy_self_r)); @@ -507,9 +565,11 @@ pub fn compare_impl_method(tcx: ty::ctxt, tps: vec::append(trait_tps, dummy_tps) }; let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty); - debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty)); + debug!("trait_fty (pre-subst): %s substs=%s", + trait_fty.repr(tcx), substs.repr(tcx)); ty::subst(tcx, &substs, trait_fty) }; + debug!("trait_fty (post-subst): %s", trait_fty.repr(tcx)); let infcx = infer::new_infer_ctxt(tcx); match infer::mk_subty(infcx, false, cm.span, impl_fty, trait_fty) { @@ -542,7 +602,8 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, impl_ms: &[ConvertedMethod]) { let tcx = ccx.tcx; - let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp, generics); + let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp, + generics, selfty); if trait_ref.def_id.crate == ast::local_crate { ensure_trait_methods(ccx, trait_ref.def_id.node); @@ -574,7 +635,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt, pub fn convert_field(ccx: &CrateCtxt, rp: Option, - bounds: @~[ty::param_bounds], + type_param_defs: @~[ty::TypeParameterDef], v: @ast::struct_field, generics: &ast::Generics) { let region_parameterization = @@ -585,7 +646,7 @@ pub fn convert_field(ccx: &CrateCtxt, ccx.tcx.tcache.insert(local_def(v.node.id), ty::ty_param_bounds_and_ty { generics: ty::Generics { - bounds: bounds, + type_param_defs: type_param_defs, region_param: rp }, ty: tt @@ -609,8 +670,10 @@ pub fn convert_methods(ccx: &CrateCtxt, { let tcx = ccx.tcx; return vec::map(ms, |m| { + let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs.len(); let m_ty_generics = - ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics); + ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics, + num_rcvr_ty_params); let mty = @ty_of_method(ccx, *m, rcvr_ty_generics.region_param, untransformed_rcvr_ty, @@ -625,8 +688,9 @@ pub fn convert_methods(ccx: &CrateCtxt, // the tps on the receiver and those on the method itself ty_param_bounds_and_ty { generics: ty::Generics { - bounds: @(vec::append(copy *rcvr_ty_generics.bounds, - *m_ty_generics.bounds)), + type_param_defs: @vec::append( + copy *rcvr_ty_generics.type_param_defs, + *m_ty_generics.type_param_defs), region_param: rcvr_ty_generics.region_param }, ty: fty @@ -660,9 +724,10 @@ pub fn convert_methods(ccx: &CrateCtxt, // foo(); }`). let method_vis = m.vis.inherit_from(rcvr_visibility); + let num_rcvr_type_params = rcvr_generics.ty_params.len(); ty::method { ident: m.ident, - generics: ty_generics(ccx, None, &m.generics), + generics: ty_generics(ccx, None, &m.generics, num_rcvr_type_params), transformed_self_ty: transformed_self_ty, fty: fty, self_ty: m.self_ty.node, @@ -705,7 +770,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { rp); } ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => { - let i_ty_generics = ty_generics(ccx, rp, generics); + let i_ty_generics = ty_generics(ccx, rp, generics, 0); let region_parameterization = RegionParameterization::from_variance_and_generics(rp, generics); let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty); @@ -741,8 +806,9 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { let (_, provided_methods) = split_trait_methods(*trait_methods); - let (ty_generics, _) = mk_substs(ccx, generics, rp); let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); + let (ty_generics, _) = mk_item_substs(ccx, generics, rp, + Some(untransformed_rcvr_ty)); let _ = convert_methods(ccx, provided_methods, untransformed_rcvr_ty, &ty_generics, generics, @@ -799,7 +865,7 @@ pub fn convert_struct(ccx: &CrateCtxt, tcx.tcache.insert(local_def(dtor.node.id), ty_param_bounds_and_ty { generics: ty::Generics { - bounds: tpt.generics.bounds, + type_param_defs: tpt.generics.type_param_defs, region_param: rp }, ty: t_dtor}); @@ -807,9 +873,9 @@ pub fn convert_struct(ccx: &CrateCtxt, // Write the type of each of the members for struct_def.fields.each |f| { - convert_field(ccx, rp, tpt.generics.bounds, *f, generics); + convert_field(ccx, rp, tpt.generics.type_param_defs, *f, generics); } - let (_, substs) = mk_substs(ccx, generics, rp); + let (_, substs) = mk_item_substs(ccx, generics, rp, None); let selfty = ty::mk_struct(tcx, local_def(id), substs); // If this struct is enum-like or tuple-like, create the type of its @@ -850,7 +916,8 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) { pub fn instantiate_trait_ref(ccx: &CrateCtxt, ast_trait_ref: @ast::trait_ref, rp: Option, - generics: &ast::Generics) -> @ty::TraitRef + generics: &ast::Generics, + self_ty: ty::t) -> @ty::TraitRef { /*! * Instantiates the path for the given trait reference, assuming that @@ -866,7 +933,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt, ast::def_trait(trait_did) => { let trait_ref = astconv::ast_path_to_trait_ref( - ccx, &rscope, trait_did, ast_trait_ref.path); + ccx, &rscope, trait_did, Some(self_ty), ast_trait_ref.path); ccx.tcx.trait_refs.insert( ast_trait_ref.ref_id, trait_ref); return trait_ref; @@ -903,7 +970,9 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: @ast::item) -> @ty::TraitDef { let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x); match it.node { ast::item_trait(ref generics, _, _) => { - let (ty_generics, substs) = mk_substs(ccx, generics, rp); + let self_ty = ty::mk_self(tcx, def_id); + let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, + Some(self_ty)); let trait_ref = @ty::TraitRef {def_id: def_id, substs: substs}; let trait_def = @ty::TraitDef {generics: ty_generics, @@ -937,7 +1006,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } ast::item_fn(ref decl, purity, _, ref generics, _) => { assert!(rp.is_none()); - let ty_generics = ty_generics(ccx, None, generics); + let ty_generics = ty_generics(ccx, None, generics, 0); let tofd = astconv::ty_of_bare_fn(ccx, &empty_rscope, purity, @@ -946,7 +1015,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) decl); let tpt = ty_param_bounds_and_ty { generics: ty::Generics { - bounds: ty_generics.bounds, + type_param_defs: ty_generics.type_param_defs, region_param: None }, ty: ty::mk_bare_fn(ccx.tcx, tofd) @@ -979,7 +1048,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } }; ty_param_bounds_and_ty { - generics: ty_generics(ccx, rp, generics), + generics: ty_generics(ccx, rp, generics, 0), ty: ty } }; @@ -989,7 +1058,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } ast::item_enum(_, ref generics) => { // Create a new generic polytype. - let (ty_generics, substs) = mk_substs(ccx, generics, rp); + let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, None); let t = ty::mk_enum(tcx, local_def(it.id), substs); let tpt = ty_param_bounds_and_ty { generics: ty_generics, @@ -1004,7 +1073,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) fmt!("Invoked ty_of_item on trait")); } ast::item_struct(_, ref generics) => { - let (ty_generics, substs) = mk_substs(ccx, generics, rp); + let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, None); let t = ty::mk_struct(tcx, local_def(it.id), substs); let tpt = ty_param_bounds_and_ty { generics: ty_generics, @@ -1031,7 +1100,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item) ast::foreign_item_const(t) => { ty::ty_param_bounds_and_ty { generics: ty::Generics { - bounds: @~[], + type_param_defs: @~[], region_param: None, }, ty: ast_ty_to_ty(ccx, &empty_rscope, t) @@ -1042,16 +1111,25 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item) pub fn ty_generics(ccx: &CrateCtxt, rp: Option, - generics: &ast::Generics) -> ty::Generics { + generics: &ast::Generics, + base_index: uint) -> ty::Generics { return ty::Generics { region_param: rp, - bounds: @generics.ty_params.map_to_vec(|param| { - match ccx.tcx.ty_param_bounds.find(¶m.id) { - Some(&bs) => bs, + type_param_defs: @generics.ty_params.mapi_to_vec(|offset, param| { + match ccx.tcx.ty_param_defs.find(¶m.id) { + Some(&def) => def, None => { - let bounds = compute_bounds(ccx, rp, generics, param.bounds); - ccx.tcx.ty_param_bounds.insert(param.id, bounds); - bounds + let param_ty = ty::param_ty {idx: base_index + offset, + def_id: local_def(param.id)}; + let bounds = compute_bounds(ccx, rp, generics, + param_ty, param.bounds); + let def = ty::TypeParameterDef { + def_id: local_def(param.id), + bounds: bounds + }; + debug!("def for param: %s", def.repr(ccx.tcx)); + ccx.tcx.ty_param_defs.insert(param.id, def); + def } } }) @@ -1061,6 +1139,7 @@ pub fn ty_generics(ccx: &CrateCtxt, ccx: &CrateCtxt, rp: Option, generics: &ast::Generics, + param_ty: ty::param_ty, ast_bounds: @OptVec) -> ty::param_bounds { /*! @@ -1076,7 +1155,8 @@ pub fn ty_generics(ccx: &CrateCtxt, match b { &TraitTyParamBound(b) => { let li = &ccx.tcx.lang_items; - let trait_ref = instantiate_trait_ref(ccx, b, rp, generics); + let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id); + let trait_ref = instantiate_trait_ref(ccx, b, rp, generics, ty); if trait_ref.def_id == li.owned_trait() { ~[ty::bound_owned] } else if trait_ref.def_id == li.copy_trait() { @@ -1104,7 +1184,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, def_id: ast::def_id, ast_generics: &ast::Generics) -> ty::ty_param_bounds_and_ty { - let ty_generics = ty_generics(ccx, None, ast_generics); + let ty_generics = ty_generics(ccx, None, ast_generics, 0); let region_param_names = RegionParamNames::from_generics(ast_generics); let rb = in_binding_rscope(&empty_rscope, region_param_names); let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) ); @@ -1127,17 +1207,18 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, return tpt; } -pub fn mk_substs(ccx: &CrateCtxt, - ast_generics: &ast::Generics, - rp: Option) -> (ty::Generics, ty::substs) +pub fn mk_item_substs(ccx: &CrateCtxt, + ast_generics: &ast::Generics, + rp: Option, + self_ty: Option) -> (ty::Generics, ty::substs) { let mut i = 0; - let ty_generics = ty_generics(ccx, rp, ast_generics); + let ty_generics = ty_generics(ccx, rp, ast_generics, 0); let params = ast_generics.ty_params.map_to_vec(|atp| { let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); i += 1u; t }); let self_r = rscope::bound_self_region(rp); - (ty_generics, substs {self_r: self_r, self_ty: None, tps: params}) + (ty_generics, substs {self_r: self_r, self_ty: self_ty, tps: params}) } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 69c7b1d616b0a..be1d291cfe5c9 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -274,15 +274,14 @@ pub fn super_tps( pub fn super_self_tys( self: &C, a: Option, b: Option) -> cres> { - // Note: the self type parameter is (currently) always treated as - // *invariant* (otherwise the type system would be unsound). - match (a, b) { (None, None) => { Ok(None) } (Some(a), Some(b)) => { - eq_tys(self, a, b).then(|| Ok(Some(a)) ) + // FIXME(#5781) this should be eq_tys + // eq_tys(self, a, b).then(|| Ok(Some(a)) ) + self.contratys(a, b).chain(|t| Ok(Some(t))) } (None, Some(_)) | (Some(_), None) => { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index d3502adb33ab8..fdb8049d79be9 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -53,6 +53,7 @@ use core::prelude::*; use middle::resolve; use middle::ty; use util::common::time; +use util::ppaux::Repr; use util::ppaux; use core::hashmap::HashMap; @@ -153,14 +154,15 @@ pub enum vtable_origin { vtable_param(uint, uint) } -pub impl vtable_origin { - fn to_str(&self, tcx: ty::ctxt) -> ~str { +impl Repr for vtable_origin { + fn repr(&self, tcx: ty::ctxt) -> ~str { match *self { vtable_static(def_id, ref tys, ref vtable_res) => { - fmt!("vtable_static(%?:%s, %?, %?)", - def_id, ty::item_path_str(tcx, def_id), - tys, - vtable_res.map(|o| o.to_str(tcx))) + fmt!("vtable_static(%?:%s, %s, %s)", + def_id, + ty::item_path_str(tcx, def_id), + tys.repr(tcx), + vtable_res.repr(tcx)) } vtable_param(x, y) => { @@ -222,7 +224,7 @@ pub fn lookup_def_ccx(ccx: @mut CrateCtxt, sp: span, id: ast::node_id) pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty { - generics: ty::Generics {bounds: @~[], + generics: ty::Generics {type_param_defs: @~[], region_param: None}, ty: t } diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 456f9743afab4..6cd71cb7e3aae 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -83,6 +83,7 @@ pub mod middle { pub mod asm; } pub mod ty; + pub mod subst; pub mod resolve; #[path = "typeck/mod.rs"] pub mod typeck; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3b3c42d5d8b2e..f26eeeca446c1 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -11,6 +11,7 @@ use core::prelude::*; use middle::ty; +use middle::typeck; use middle::ty::canon_mode; use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid, br_fresh}; @@ -35,6 +36,10 @@ use syntax::abi::AbiSet; use core::str; use core::vec; +pub trait Repr { + fn repr(&self, tcx: ctxt) -> ~str; +} + pub fn note_and_explain_region(cx: ctxt, prefix: ~str, region: ty::Region, @@ -257,18 +262,6 @@ pub fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -pub fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str { - fmt!("expr(%d: %s)", - expr.id, - pprust::expr_to_str(expr, cx.sess.intr())) -} - -pub fn pat_repr(cx: ctxt, pat: @ast::pat) -> ~str { - fmt!("pat(%d: %s)", - pat.id, - pprust::pat_to_str(pat, cx.sess.intr())) -} - pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str { let tstrs = ts.map(|t| ty_to_str(cx, *t)); fmt!("(%s)", str::connect(tstrs, ", ")) @@ -287,7 +280,13 @@ pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str { pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str { let path = ty::item_path(cx, trait_ref.def_id); let base = ast_map::path_to_str(path, cx.sess.intr()); - parameterized(cx, base, trait_ref.substs.self_r, trait_ref.substs.tps) + if cx.sess.verbose() && trait_ref.substs.self_ty.is_some() { + let mut all_tps = copy trait_ref.substs.tps; + for trait_ref.substs.self_ty.each |&t| { all_tps.push(t); } + parameterized(cx, base, trait_ref.substs.self_r, all_tps) + } else { + parameterized(cx, base, trait_ref.substs.self_r, trait_ref.substs.tps) + } } pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { @@ -497,10 +496,261 @@ pub fn ty_to_short_str(cx: ctxt, typ: t) -> ~str { return s; } +impl Repr for Option { + fn repr(&self, tcx: ctxt) -> ~str { + match self { + &None => ~"None", + &Some(ref t) => fmt!("Some(%s)", t.repr(tcx)) + } + } +} + +/* +Annoyingly, these conflict with @ast::expr. + +impl Repr for @T { + fn repr(&self, tcx: ctxt) -> ~str { + (&**self).repr(tcx) + } +} + +impl Repr for ~T { + fn repr(&self, tcx: ctxt) -> ~str { + (&**self).repr(tcx) + } +} +*/ + +fn repr_vec(tcx: ctxt, v: &[T]) -> ~str { + fmt!("[%s]", str::connect(v.map(|t| t.repr(tcx)), ",")) +} + +impl<'self, T:Repr> Repr for &'self [T] { + fn repr(&self, tcx: ctxt) -> ~str { + repr_vec(tcx, *self) + } +} + +// This is necessary to handle types like Option<@~[T]>, for which +// autoderef cannot convert the &[T] handler +impl Repr for @~[T] { + fn repr(&self, tcx: ctxt) -> ~str { + repr_vec(tcx, **self) + } +} + +impl Repr for ty::TypeParameterDef { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("TypeParameterDef {%?, bounds: %s}", + self.def_id, self.bounds.repr(tcx)) + } +} + +impl Repr for ty::t { + fn repr(&self, tcx: ctxt) -> ~str { + ty_to_str(tcx, *self) + } +} + +impl Repr for ty::substs { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("substs(self_r=%s, self_ty=%s, tps=%s)", + self.self_r.repr(tcx), + self.self_ty.repr(tcx), + self.tps.repr(tcx)) + } +} + +impl Repr for ty::param_bound { + fn repr(&self, tcx: ctxt) -> ~str { + match *self { + ty::bound_copy => ~"copy", + ty::bound_durable => ~"'static", + ty::bound_owned => ~"owned", + ty::bound_const => ~"const", + ty::bound_trait(ref t) => t.repr(tcx) + } + } +} + +impl Repr for ty::TraitRef { + fn repr(&self, tcx: ctxt) -> ~str { + trait_ref_to_str(tcx, self) + } +} + +impl Repr for @ast::expr { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("expr(%d: %s)", + self.id, + pprust::expr_to_str(*self, tcx.sess.intr())) + } +} + +impl Repr for @ast::pat { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("pat(%d: %s)", + self.id, + pprust::pat_to_str(*self, tcx.sess.intr())) + } +} + +impl Repr for ty::Region { + fn repr(&self, tcx: ctxt) -> ~str { + region_to_str(tcx, *self) + } +} + +impl Repr for ast::def_id { + fn repr(&self, tcx: ctxt) -> ~str { + // Unfortunately, there seems to be no way to attempt to print + // a path for a def-id, so I'll just make a best effort for now + // and otherwise fallback to just printing the crate/node pair + if self.crate == ast::local_crate { + match tcx.items.find(&self.node) { + Some(&ast_map::node_item(*)) | + Some(&ast_map::node_foreign_item(*)) | + Some(&ast_map::node_method(*)) | + Some(&ast_map::node_trait_method(*)) | + Some(&ast_map::node_variant(*)) | + Some(&ast_map::node_struct_ctor(*)) => { + return fmt!("%?:%s", *self, ty::item_path_str(tcx, *self)); + } + _ => {} + } + } + return fmt!("%?", *self); + } +} + +impl Repr for ty::ty_param_bounds_and_ty { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("ty_param_bounds_and_ty {generics: %s, ty: %s}", + self.generics.repr(tcx), + self.ty.repr(tcx)) + } +} + +impl Repr for ty::Generics { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("Generics {type_param_defs: %s, region_param: %?}", + self.type_param_defs.repr(tcx), + self.region_param) + } +} + +impl Repr for ty::method { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("method {ident: %s, generics: %s, transformed_self_ty: %s, \ + fty: %s, self_ty: %s, vis: %s, def_id: %s}", + self.ident.repr(tcx), + self.generics.repr(tcx), + self.transformed_self_ty.repr(tcx), + self.fty.repr(tcx), + self.self_ty.repr(tcx), + self.vis.repr(tcx), + self.def_id.repr(tcx)) + } +} + +impl Repr for ast::ident { + fn repr(&self, tcx: ctxt) -> ~str { + copy *tcx.sess.intr().get(*self) + } +} + +impl Repr for ast::self_ty_ { + fn repr(&self, _tcx: ctxt) -> ~str { + fmt!("%?", *self) + } +} + +impl Repr for ast::visibility { + fn repr(&self, _tcx: ctxt) -> ~str { + fmt!("%?", *self) + } +} + +impl Repr for ty::BareFnTy { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("BareFnTy {purity: %?, abis: %s, sig: %s}", + self.purity, + self.abis.to_str(), + self.sig.repr(tcx)) + } +} + +impl Repr for ty::FnSig { + fn repr(&self, tcx: ctxt) -> ~str { + fn_sig_to_str(tcx, self) + } +} + +impl Repr for typeck::method_map_entry { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("method_map_entry {self_arg: %s, \ + explicit_self: %s, \ + origin: %s}", + self.self_arg.repr(tcx), + self.explicit_self.repr(tcx), + self.origin.repr(tcx)) + } +} + +impl Repr for ty::arg { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("%?(%s)", self.mode, self.ty.repr(tcx)) + } +} + +impl Repr for typeck::method_origin { + fn repr(&self, tcx: ctxt) -> ~str { + match self { + &typeck::method_super(def_id, n) => { + fmt!("method_super(%s, %?)", + def_id.repr(tcx), n) + } + &typeck::method_static(def_id) => { + fmt!("method_static(%s)", def_id.repr(tcx)) + } + &typeck::method_param(ref p) => { + p.repr(tcx) + } + &typeck::method_trait(def_id, n, st) => { + fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n, + st.repr(tcx)) + } + &typeck::method_self(def_id, n) => { + fmt!("method_self(%s, %?)", def_id.repr(tcx), n) + } + } + } +} + +impl Repr for typeck::method_param { + fn repr(&self, tcx: ctxt) -> ~str { + fmt!("method_param(%s,%?,%?,%?)", + self.trait_id.repr(tcx), + self.method_num, + self.param_num, + self.bound_num) + } +} + +impl Repr for ty::TraitStore { + fn repr(&self, tcx: ctxt) -> ~str { + match self { + &ty::BoxTraitStore => ~"@Trait", + &ty::UniqTraitStore => ~"~Trait", + &ty::RegionTraitStore(r) => fmt!("&%s Trait", r.repr(tcx)) + } + } +} + // Local Variables: // mode: rust // fill-column: 78; // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// End: +// End diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 67c3d19dd0fb7..fd54746f3dc51 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -102,6 +102,16 @@ impl OptVec { self.push(copy *e); } } + + #[inline(always)] + fn mapi_to_vec(&self, op: &fn(uint, &T) -> B) -> ~[B] { + let mut index = 0; + iter::map_to_vec(self, |a| { + let i = index; + index += 1; + op(i, a) + }) + } } impl Eq for OptVec { diff --git a/src/test/run-pass/trait-inheritance-self-in-supertype.rs b/src/test/run-pass/trait-inheritance-self-in-supertype.rs new file mode 100644 index 0000000000000..8105cf23d8004 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-self-in-supertype.rs @@ -0,0 +1,61 @@ +// Test for issue #4183: use of Self in supertraits. + +pub static FUZZY_EPSILON: float = 0.1; + +pub trait FuzzyEq { + fn fuzzy_eq(&self, other: &Self) -> bool; + fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool; +} + +trait Float: FuzzyEq { + fn two_pi() -> Self; +} + +impl FuzzyEq for f32 { + fn fuzzy_eq(&self, other: &f32) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32)) + } + + fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool { + f32::abs(*self - *other) < *epsilon + } +} + +impl Float for f32 { + fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 } +} + +impl FuzzyEq for f64 { + fn fuzzy_eq(&self, other: &f64) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64)) + } + + fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool { + f64::abs(*self - *other) < *epsilon + } +} + +impl Float for f64 { + fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 } +} + +fn compare(f1: F) -> bool { + let f2 = Float::two_pi(); + f1.fuzzy_eq(&f2) +} + +pub fn main() { + assert!(compare::(6.28318530717958647692528676655900576)); + assert!(compare::(6.29)); + assert!(compare::(6.3)); + assert!(compare::(6.19)); + assert!(!compare::(7.28318530717958647692528676655900576)); + assert!(!compare::(6.18)); + + assert!(compare::(6.28318530717958647692528676655900576)); + assert!(compare::(6.29)); + assert!(compare::(6.3)); + assert!(compare::(6.19)); + assert!(!compare::(7.28318530717958647692528676655900576)); + assert!(!compare::(6.18)); +} \ No newline at end of file From 3e67085d7a590ef360e7c85cc6c3931bae6df6a5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 13:16:27 -0400 Subject: [PATCH 094/403] Allow lint modes to be used on unused variables and dead assignments --- src/librustc/middle/lint.rs | 19 +++--- src/librustc/middle/liveness.rs | 79 ++++++++++++++---------- src/test/compile-fail/liveness-unused.rs | 44 +++++++------ 3 files changed, 82 insertions(+), 60 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index b4aff91ed5b28..0adf4b87f3a8e 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -83,9 +83,8 @@ pub enum lint { legacy_modes, - // FIXME(#3266)--make liveness warnings lintable - // unused_variable, - // dead_assignment + unused_variable, + dead_assignment, } pub fn level_to_str(lv: level) -> &'static str { @@ -257,21 +256,19 @@ pub fn get_lint_dict() -> LintDict { default: deny }), - /* FIXME(#3266)--make liveness warnings lintable - (@~"unused_variable", - @LintSpec { + (~"unused_variable", + LintSpec { lint: unused_variable, desc: "detect variables which are not used in any way", default: warn - }), + }), - (@~"dead_assignment", - @LintSpec { + (~"dead_assignment", + LintSpec { lint: dead_assignment, desc: "detect assignments that will never be read", default: warn - }), - */ + }), ]; let mut map = HashMap::new(); do vec::consume(v) |_, (k, v)| { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 01598b118518d..3a649e7cc3b2b 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -105,6 +105,7 @@ use core::prelude::*; +use middle::lint::{unused_variable, dead_assignment}; use middle::pat_util; use middle::ty; use middle::typeck; @@ -118,6 +119,7 @@ use core::ptr; use core::to_str; use core::uint; use core::vec; +use core::util::with; use syntax::ast::*; use syntax::codemap::span; use syntax::parse::token::special_idents; @@ -169,6 +171,7 @@ pub fn check_crate(tcx: ty::ctxt, visit_local: visit_local, visit_expr: visit_expr, visit_arm: visit_arm, + visit_item: visit_item, .. *visit::default_visitor() }); @@ -177,7 +180,8 @@ pub fn check_crate(tcx: ty::ctxt, method_map, variable_moves_map, capture_map, - last_use_map); + last_use_map, + 0); visit::visit_crate(*crate, initial_maps, visitor); tcx.sess.abort_if_errors(); return last_use_map; @@ -269,13 +273,16 @@ struct IrMaps { capture_info_map: HashMap, var_kinds: ~[VarKind], lnks: ~[LiveNodeKind], + + cur_item: node_id, } fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, variable_moves_map: moves::VariableMovesMap, capture_map: moves::CaptureMap, - last_use_map: last_use_map) + last_use_map: last_use_map, + cur_item: node_id) -> IrMaps { IrMaps { tcx: tcx, @@ -289,7 +296,8 @@ fn IrMaps(tcx: ty::ctxt, variable_map: HashMap::new(), capture_info_map: HashMap::new(), var_kinds: ~[], - lnks: ~[] + lnks: ~[], + cur_item: cur_item, } } @@ -394,6 +402,12 @@ pub impl IrMaps { } } +fn visit_item(item: @item, &&self: @mut IrMaps, v: vt<@mut IrMaps>) { + do with(&mut self.cur_item, item.id) { + visit::visit_item(item, self, v) + } +} + fn visit_fn(fk: &visit::fn_kind, decl: &fn_decl, body: &blk, @@ -409,7 +423,8 @@ fn visit_fn(fk: &visit::fn_kind, self.method_map, self.variable_moves_map, self.capture_map, - self.last_use_map); + self.last_use_map, + self.cur_item); debug!("creating fn_maps: %x", ptr::addr_of(&(*fn_maps)) as uint); @@ -692,17 +707,19 @@ pub impl Liveness { } } - fn pat_bindings(&self, pat: @pat, f: &fn(LiveNode, Variable, span)) { + fn pat_bindings(&self, pat: @pat, + f: &fn(LiveNode, Variable, span, node_id)) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, pat) |_bm, p_id, sp, _n| { let ln = self.live_node(p_id, sp); let var = self.variable(p_id, sp); - f(ln, var, sp); + f(ln, var, sp, p_id); } } fn arm_pats_bindings(&self, - pats: &[@pat], f: &fn(LiveNode, Variable, span)) { + pats: &[@pat], + f: &fn(LiveNode, Variable, span, node_id)) { // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoratative" set of ids @@ -718,7 +735,7 @@ pub impl Liveness { fn define_bindings_in_arm_pats(&self, pats: &[@pat], succ: LiveNode) -> LiveNode { let mut succ = succ; - do self.arm_pats_bindings(pats) |ln, var, _sp| { + do self.arm_pats_bindings(pats) |ln, var, _sp, _id| { self.init_from_succ(ln, succ); self.define(ln, var); succ = ln; @@ -1509,8 +1526,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) { // should not be live at this point. debug!("check_local() with no initializer"); - do self.pat_bindings(local.node.pat) |ln, var, sp| { - if !self.warn_about_unused(sp, ln, var) { + do self.pat_bindings(local.node.pat) |ln, var, sp, id| { + if !self.warn_about_unused(sp, id, ln, var) { match self.live_on_exit(ln, var) { None => { /* not live: good */ } Some(lnk) => { @@ -1528,8 +1545,8 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) { } fn check_arm(arm: &arm, &&self: @Liveness, vt: vt<@Liveness>) { - do self.arm_pats_bindings(arm.pats) |ln, var, sp| { - self.warn_about_unused(sp, ln, var); + do self.arm_pats_bindings(arm.pats) |ln, var, sp, id| { + self.warn_about_unused(sp, id, ln, var); } visit::visit_arm(arm, self, vt); } @@ -1691,14 +1708,14 @@ pub impl Liveness { let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); self.check_for_reassignment(ln, var, expr.span); - self.warn_about_dead_assign(expr.span, ln, var); + self.warn_about_dead_assign(expr.span, expr.id, ln, var); } def => { match relevant_def(def) { Some(nid) => { let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); - self.warn_about_dead_assign(expr.span, ln, var); + self.warn_about_dead_assign(expr.span, expr.id, ln, var); } None => {} } @@ -1715,7 +1732,7 @@ pub impl Liveness { } fn check_for_reassignments_in_pat(@self, pat: @pat) { - do self.pat_bindings(pat) |ln, var, sp| { + do self.pat_bindings(pat) |ln, var, sp, _id| { self.check_for_reassignment(ln, var, sp); } } @@ -1861,21 +1878,21 @@ pub impl Liveness { do pat_util::pat_bindings(self.tcx.def_map, arg.pat) |_bm, p_id, sp, _n| { let var = self.variable(p_id, sp); - self.warn_about_unused(sp, entry_ln, var); + self.warn_about_unused(sp, p_id, entry_ln, var); } } } fn warn_about_unused_or_dead_vars_in_pat(@self, pat: @pat) { - do self.pat_bindings(pat) |ln, var, sp| { - if !self.warn_about_unused(sp, ln, var) { - self.warn_about_dead_assign(sp, ln, var); + do self.pat_bindings(pat) |ln, var, sp, id| { + if !self.warn_about_unused(sp, id, ln, var) { + self.warn_about_dead_assign(sp, id, ln, var); } } } - fn warn_about_unused(@self, sp: span, ln: LiveNode, var: Variable) - -> bool { + fn warn_about_unused(@self, sp: span, id: node_id, + ln: LiveNode, var: Variable) -> bool { if !self.used_on_entry(ln, var) { for self.should_warn(var).each |name| { @@ -1889,14 +1906,14 @@ pub impl Liveness { }; if is_assigned { - // FIXME(#3266)--make liveness warnings lintable - self.tcx.sess.span_warn( - sp, fmt!("variable `%s` is assigned to, \ + self.tcx.sess.span_lint(unused_variable, id, + self.ir.cur_item, sp, + fmt!("variable `%s` is assigned to, \ but never used", **name)); } else { - // FIXME(#3266)--make liveness warnings lintable - self.tcx.sess.span_warn( - sp, fmt!("unused variable: `%s`", **name)); + self.tcx.sess.span_lint(unused_variable, id, + self.ir.cur_item, sp, + fmt!("unused variable: `%s`", **name)); } } return true; @@ -1904,12 +1921,12 @@ pub impl Liveness { return false; } - fn warn_about_dead_assign(@self, sp: span, ln: LiveNode, var: Variable) { + fn warn_about_dead_assign(@self, sp: span, id: node_id, + ln: LiveNode, var: Variable) { if self.live_on_exit(ln, var).is_none() { for self.should_warn(var).each |name| { - // FIXME(#3266)--make liveness warnings lintable - self.tcx.sess.span_warn( - sp, + self.tcx.sess.span_lint(dead_assignment, id, + self.ir.cur_item, sp, fmt!("value assigned to `%s` is never read", **name)); } } diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 9e4d16f96e6c3..27db4ff5aaae2 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -8,38 +8,57 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[deny(unused_variable)]; +#[deny(dead_assignment)]; + fn f1(x: int) { - //~^ WARNING unused variable: `x` + //~^ ERROR unused variable: `x` } fn f1b(x: &mut int) { - //~^ WARNING unused variable: `x` + //~^ ERROR unused variable: `x` } +#[allow(unused_variable)] +fn f1c(x: int) {} + fn f2() { let x = 3; - //~^ WARNING unused variable: `x` + //~^ ERROR unused variable: `x` } fn f3() { let mut x = 3; - //~^ WARNING variable `x` is assigned to, but never used + //~^ ERROR variable `x` is assigned to, but never used x += 4; - //~^ WARNING value assigned to `x` is never read + //~^ ERROR value assigned to `x` is never read } fn f3b() { let mut z = 3; - //~^ WARNING variable `z` is assigned to, but never used + //~^ ERROR variable `z` is assigned to, but never used loop { z += 4; } } +#[allow(unused_variable)] +fn f3c() { + let mut z = 3; + loop { z += 4; } +} + +#[allow(unused_variable)] +#[allow(dead_assignment)] +fn f3d() { + let mut x = 3; + x += 4; +} + fn f4() { match Some(3) { Some(i) => { - //~^ WARNING unused variable: `i` + //~^ ERROR unused variable: `i` } None => {} } @@ -57,16 +76,5 @@ fn f4b() -> int { } } -// leave this in here just to trigger compile-fail: -struct r { - x: (), -} - -impl Drop for r { - fn finalize(&self) {} -} - fn main() { - let x = r { x: () }; - || { copy x; }; //~ ERROR copying a value of non-copyable type } From 23251b24389c68dd01ac26dbaa30125aa8f64c35 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 4 Apr 2013 21:46:37 -0700 Subject: [PATCH 095/403] Bump version to 0.7-pre --- src/compiletest/compiletest.rc | 4 ++-- src/driver/driver.rs | 14 +++++++------- src/etc/kate/rust.xml | 2 +- src/libcore/core.rc | 4 ++-- src/libfuzzer/fuzzer.rc | 8 ++++---- src/librust/rust.rc | 4 ++-- src/librustc/front/core_inject.rs | 2 +- src/librustc/front/test.rs | 2 +- src/librustc/rustc.rc | 8 ++++---- src/librustdoc/rustdoc.rc | 10 +++++----- src/librusti/rusti.rc | 10 +++++----- src/librustpkg/rustpkg.rc | 10 +++++----- src/librustpkg/util.rs | 2 +- src/libstd/std.rc | 4 ++-- src/libsyntax/syntax.rc | 6 +++--- src/test/run-pass/use.rs | 2 +- 16 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 585fd1271a8fa..e97383e730bc0 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -17,8 +17,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); use core::*; diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 2fc50eb6e7579..db55d5569ab6e 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -9,24 +9,24 @@ // except according to those terms. #[no_core]; -extern mod core(vers = "0.6"); +extern mod core(vers = "0.7-rc"); #[cfg(rustpkg)] -extern mod this(name = "rustpkg", vers = "0.6"); +extern mod this(name = "rustpkg", vers = "0.7-rc"); #[cfg(fuzzer)] -extern mod this(name = "fuzzer", vers = "0.6"); +extern mod this(name = "fuzzer", vers = "0.7-rc"); #[cfg(rustdoc)] -extern mod this(name = "rustdoc", vers = "0.6"); +extern mod this(name = "rustdoc", vers = "0.7-rc"); #[cfg(rusti)] -extern mod this(name = "rusti", vers = "0.6"); +extern mod this(name = "rusti", vers = "0.7-rc"); #[cfg(rust)] -extern mod this(name = "rust", vers = "0.6"); +extern mod this(name = "rust", vers = "0.7-rc"); #[cfg(rustc)] -extern mod this(name = "rustc", vers = "0.6"); +extern mod this(name = "rustc", vers = "0.7-rc"); fn main() { this::main() } diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index f0c057ff25b49..aa40e316bf845 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -7,7 +7,7 @@ ]> - + fn diff --git a/src/libcore/core.rc b/src/libcore/core.rc index f7c64e3f37445..ed5a255bdb801 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -48,7 +48,7 @@ they contained the following prologue: #[link(name = "core", - vers = "0.6", + vers = "0.7-rc", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; @@ -66,7 +66,7 @@ they contained the following prologue: #[allow(deprecated_drop)]; // Make core testable by not duplicating lang items. See #2912 -#[cfg(test)] extern mod realcore(name = "core", vers = "0.6"); +#[cfg(test)] extern mod realcore(name = "core", vers = "0.7-rc"); #[cfg(test)] pub use kinds = realcore::kinds; #[cfg(test)] pub use ops = realcore::ops; #[cfg(test)] pub use cmp = realcore::cmp; diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index aad48bbb8e636..c67c788cf2abb 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -10,7 +10,7 @@ #[link(name = "fuzzer", - vers = "0.6", + vers = "0.7-rc", uuid = "d6418797-2736-4833-bd82-d3c684b7c1b0", url = "https://github.com/mozilla/rust/tree/master/src/libfuzzer")]; @@ -26,9 +26,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); -extern mod syntax(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); +extern mod syntax(vers = "0.7-rc"); use core::*; use core::io::WriterUtil; diff --git a/src/librust/rust.rc b/src/librust/rust.rc index 714abbba0db1e..f74bd7084a0ae 100644 --- a/src/librust/rust.rc +++ b/src/librust/rust.rc @@ -13,14 +13,14 @@ // FIXME #2238 Make run only accept source that emits an executable #[link(name = "rust", - vers = "0.6", + vers = "0.7-rc", uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c", url = "https://github.com/mozilla/rust/tree/master/src/rust")]; #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod core(vers = "0.6"); +extern mod core(vers = "0.7-rc"); use core::run; diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/core_inject.rs index 6e134d25ff2cf..a7c015d29a187 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -19,7 +19,7 @@ use syntax::codemap; use syntax::codemap::dummy_sp; use syntax::fold; -static CORE_VERSION: &'static str = "0.6"; +static CORE_VERSION: &'static str = "0.7-rc"; pub fn maybe_inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index dbedeeaa5cc80..139ffbb5f5bb3 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -265,7 +265,7 @@ mod __test { */ fn mk_std(cx: &TestCtxt) -> @ast::view_item { - let vers = ast::lit_str(@~"0.6"); + let vers = ast::lit_str(@~"0.7-rc"); let vers = nospan(vers); let mi = ast::meta_name_value(@~"vers", vers); let mi = nospan(mi); diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 456f9743afab4..3a974fcdaae80 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -10,7 +10,7 @@ #[link(name = "rustc", - vers = "0.6", + vers = "0.7-rc", uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; @@ -27,9 +27,9 @@ #[no_core]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); -extern mod syntax(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); +extern mod syntax(vers = "0.7-rc"); use core::prelude::*; diff --git a/src/librustdoc/rustdoc.rc b/src/librustdoc/rustdoc.rc index 9b19063a90866..54a839f53745c 100644 --- a/src/librustdoc/rustdoc.rc +++ b/src/librustdoc/rustdoc.rc @@ -11,7 +11,7 @@ //! Rustdoc - The Rust documentation generator #[link(name = "rustdoc", - vers = "0.6", + vers = "0.7-rc", uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; @@ -23,10 +23,10 @@ #[allow(non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); -extern mod rustc(vers = "0.6"); -extern mod syntax(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); +extern mod rustc(vers = "0.7-rc"); +extern mod syntax(vers = "0.7-rc"); use config::Config; use doc::Item; diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index fcc799b665f5b..a7130f6465754 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -11,7 +11,7 @@ // rusti - REPL using the JIT backend #[link(name = "rusti", - vers = "0.6", + vers = "0.7-rc", uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; @@ -23,10 +23,10 @@ #[allow(vecs_implicitly_copyable, non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); -extern mod rustc(vers = "0.6"); -extern mod syntax(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); +extern mod rustc(vers = "0.7-rc"); +extern mod syntax(vers = "0.7-rc"); use core::*; use core::io::WriterUtil; diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index bf1301868af54..8ff809023a37b 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -11,7 +11,7 @@ // rustpkg - a purely function package manager and build system #[link(name = "rustpkg", - vers = "0.6", + vers = "0.7-rc", uuid = "25de5e6e-279e-4a20-845c-4cabae92daaf", url = "https://github.com/mozilla/rust/tree/master/src/librustpkg")]; @@ -21,10 +21,10 @@ #[allow(vecs_implicitly_copyable, non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); -extern mod rustc(vers = "0.6"); -extern mod syntax(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); +extern mod rustc(vers = "0.7-rc"); +extern mod syntax(vers = "0.7-rc"); use core::*; use core::container::Map; diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 9d3751c3de297..7fd1379fa87d5 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -140,7 +140,7 @@ fn add_pkg_module(ctx: @mut ReadyCtx, m: ast::_mod) -> ast::_mod { let ext_cx = ctx.ext_cx; let item = quote_item! ( mod __pkg { - extern mod rustpkg (vers="0.6"); + extern mod rustpkg (vers="0.7-rc"); static listeners : &[rustpkg::Listener] = $listeners; #[main] fn main() { diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 9aac8d230558d..712490cce24f8 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -18,7 +18,7 @@ not required in or otherwise suitable for the core library. */ #[link(name = "std", - vers = "0.6", + vers = "0.7-rc", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; @@ -32,7 +32,7 @@ not required in or otherwise suitable for the core library. #[no_core]; -extern mod core(vers = "0.6"); +extern mod core(vers = "0.7-rc"); use core::prelude::*; pub mod uv_ll; diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 21c52f1bfcc06..8704534f677a3 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -9,7 +9,7 @@ // except according to those terms. #[link(name = "syntax", - vers = "0.6", + vers = "0.7-rc", uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; @@ -25,8 +25,8 @@ #[no_core]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); +extern mod core(vers = "0.7-rc"); +extern mod std(vers = "0.7-rc"); use core::*; diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 2a24bfe72d295..c5a012ccb7bb2 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -13,7 +13,7 @@ #[no_core]; extern mod core; extern mod zed(name = "core"); -extern mod bar(name = "core", vers = "0.6"); +extern mod bar(name = "core", vers = "0.7-rc"); use core::str; From 7a1394d58f6f8b665f32895ae50e13a7747efefa Mon Sep 17 00:00:00 2001 From: klutzy Date: Wed, 10 Apr 2013 04:15:42 +0900 Subject: [PATCH 096/403] vim: syntax highlight for inner doc comment --- src/etc/vim/syntax/rust.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 303cc0834e8ef..3e6c11c6238b1 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -110,11 +110,11 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9 syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'" -syn region rustCommentDoc start="/\*\*" end="\*/" -syn region rustCommentDoc start="///" skip="\\$" end="$" keepend +syn region rustCommentDoc start="/\*[\*!]" end="\*/" +syn region rustCommentDoc start="//[/!]" skip="\\$" end="$" keepend syn match rustComment "/\*\*/" -syn region rustComment start="/\*\([^\*]\|$\)" end="\*/" contains=rustTodo -syn region rustComment start="//\([^/]\|$\)" skip="\\$" end="$" contains=rustTodo keepend +syn region rustComment start="/\*\([^\*!]\|$\)" end="\*/" contains=rustTodo +syn region rustComment start="//\([^/!]\|$\)" skip="\\$" end="$" contains=rustTodo keepend syn keyword rustTodo contained TODO FIXME XXX NB From e8cd29ba5ecae71cfde24d2e652b50acf63ea155 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 9 Apr 2013 12:33:18 -0700 Subject: [PATCH 097/403] Apply comments from tjc --- src/librustc/middle/subst.rs | 24 +++++++++++++--------- src/librustc/middle/typeck/check/method.rs | 9 +++++++- src/librustc/middle/typeck/collect.rs | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index e40d17bec5a09..a754f93f01038 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -28,12 +28,12 @@ pub trait Subst { // Substitution over types // // Because this is so common, we make a special optimization to avoid -// doing anything is `substs` is a no-op. I tried to generalize these +// doing anything if `substs` is a no-op. I tried to generalize these // to all subst methods but ran into trouble due to the limitations of // our current method/trait matching algorithm. - Niko -trait Subst1 { - fn subst1(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self; +trait EffectfulSubst { + fn effectfulSubst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self; } impl Subst for ty::t { @@ -41,20 +41,24 @@ impl Subst for ty::t { if ty::substs_is_noop(substs) { return *self; } else { - return self.subst1(tcx, substs); + return self.effectfulSubst(tcx, substs); } } } -impl Subst1 for ty::t { - fn subst1(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::t { +impl EffectfulSubst for ty::t { + fn effectfulSubst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::t { if !ty::type_needs_subst(*self) { return *self; } match ty::get(*self).sty { - ty::ty_param(p) => substs.tps[p.idx], - ty::ty_self(_) => substs.self_ty.get(), + ty::ty_param(p) => { + substs.tps[p.idx] + } + ty::ty_self(_) => { + substs.self_ty.expect("ty_self not found in substs") + } _ => { ty::fold_regions_and_ty( tcx, *self, @@ -74,8 +78,8 @@ impl Subst1 for ty::t { } _ => r }, - |t| t.subst1(tcx, substs), - |t| t.subst1(tcx, substs)) + |t| t.effectfulSubst(tcx, substs), + |t| t.effectfulSubst(tcx, substs)) } } } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index af6a114494b1b..6a274e7f9eb07 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -376,7 +376,14 @@ pub impl<'self> LookupContext<'self> { let tcx = self.tcx(); let mut next_bound_idx = 0; // count only trait bounds - let type_param_def = tcx.ty_param_defs.get(¶m_ty.def_id.node); + let type_param_def = match tcx.ty_param_defs.find(¶m_ty.def_id.node) { + Some(t) => t, + None => { + tcx.sess.span_bug( + self.expr.span, + fmt!("No param def for %?", param_ty)); + } + }; for ty::each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |bound_trait_ref| diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index ca1a3a363ea08..a3296f6c20985 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -335,7 +335,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty::mk_bare_fn(tcx, copy m.fty)); // create the type parameter definitions for `foo`, applying - // the substutition to any traits that appear in their bounds. + // the substitution to any traits that appear in their bounds. // add in the type parameters from the trait let mut new_type_param_defs = ~[]; From cd41ee2044c48c2948969ab9f28e3fd8063ba450 Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 9 Apr 2013 20:16:06 +1200 Subject: [PATCH 098/403] Add #[start] attribute to define a new entry point function --- src/librustc/driver/driver.rs | 3 +- src/librustc/driver/session.rs | 13 ++++- src/librustc/middle/resolve.rs | 30 +++++++++-- src/librustc/middle/trans/base.rs | 87 +++++++++++++++++++------------ src/librustc/middle/typeck/mod.rs | 71 ++++++++++++++++++++++--- src/test/run-pass/attr-start.rs | 14 +++++ 6 files changed, 173 insertions(+), 45 deletions(-) create mode 100644 src/test/run-pass/attr-start.rs diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index cd1af369570ef..d725b70003754 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -698,7 +698,8 @@ pub fn build_session_(sopts: @session::options, parse_sess: p_s, codemap: cm, // For a library crate, this is always none - main_fn: @mut None, + entry_fn: @mut None, + entry_type: @mut None, span_diagnostic: span_diagnostic_handler, filesearch: filesearch, building_library: @mut false, diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 95740e0f83750..226905bbab728 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -144,6 +144,16 @@ pub struct crate_metadata { data: ~[u8] } +// The type of entry function, so +// users can have their own entry +// functions that don't start a +// scheduler +#[deriving(Eq)] +pub enum EntryFnType { + EntryMain, + EntryStart +} + pub struct Session_ { targ_cfg: @config, opts: @options, @@ -151,7 +161,8 @@ pub struct Session_ { parse_sess: @mut ParseSess, codemap: @codemap::CodeMap, // For a library crate, this is always none - main_fn: @mut Option<(node_id, codemap::span)>, + entry_fn: @mut Option<(node_id, codemap::span)>, + entry_type: @mut Option, span_diagnostic: @diagnostic::span_handler, filesearch: @filesearch::FileSearch, building_library: @mut bool, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index fcf0b7022a7a7..36f396d4dfc6b 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -801,6 +801,8 @@ pub fn Resolver(session: Session, attr_main_fn: None, main_fns: ~[], + start_fn: None, + def_map: @mut HashMap::new(), export_map2: @mut HashMap::new(), trait_map: HashMap::new(), @@ -860,9 +862,13 @@ pub struct Resolver { // The function that has attribute named 'main' attr_main_fn: Option<(node_id, span)>, - // The functions named 'main' + + // The functions that could be main functions main_fns: ~[Option<(node_id, span)>], + // The function that has the attribute 'start' on it + start_fn: Option<(node_id, span)>, + def_map: DefMap, export_map2: ExportMap2, trait_map: TraitMap, @@ -3538,6 +3544,7 @@ pub impl Resolver { item_fn(ref fn_decl, _, _, ref generics, ref block) => { // If this is the main function, we must record it in the // session. + // FIXME #4404 android JNI hacks if !*self.session.building_library || self.session.targ_cfg.os == session::os_android { @@ -3557,6 +3564,16 @@ pub impl Resolver { ~"multiple 'main' functions"); } } + + if attrs_contains_name(item.attrs, ~"start") { + if self.start_fn.is_none() { + self.start_fn = Some((item.id, item.span)); + } else { + self.session.span_err( + item.span, + ~"multiple 'start' functions"); + } + } } self.resolve_function(OpaqueFunctionRibKind, @@ -5096,7 +5113,7 @@ pub impl Resolver { // fn check_duplicate_main(@mut self) { let this = &mut *self; - if this.attr_main_fn.is_none() { + if this.attr_main_fn.is_none() && this.start_fn.is_none() { if this.main_fns.len() >= 1u { let mut i = 1u; while i < this.main_fns.len() { @@ -5106,10 +5123,15 @@ pub impl Resolver { ~"multiple 'main' functions"); i += 1; } - *this.session.main_fn = this.main_fns[0]; + *this.session.entry_fn = this.main_fns[0]; + *this.session.entry_type = Some(session::EntryMain); } + } else if !this.start_fn.is_none() { + *this.session.entry_fn = this.start_fn; + *this.session.entry_type = Some(session::EntryStart); } else { - *this.session.main_fn = this.attr_main_fn; + *this.session.entry_fn = this.attr_main_fn; + *this.session.entry_type = Some(session::EntryMain); } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a8fe60ba68ee8..91b1b50c81ce6 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2197,28 +2197,32 @@ pub fn register_fn_fuller(ccx: @CrateContext, ccx.item_symbols.insert(node_id, ps); // FIXME #4404 android JNI hacks - let is_main = is_main_fn(&ccx.sess, node_id) && + let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library || (*ccx.sess.building_library && ccx.sess.targ_cfg.os == session::os_android)); - if is_main { create_main_wrapper(ccx, sp, llfn); } + if is_entry { create_entry_wrapper(ccx, sp, llfn); } llfn } -pub fn is_main_fn(sess: &Session, node_id: ast::node_id) -> bool { - match *sess.main_fn { - Some((main_id, _)) => node_id == main_id, +pub fn is_entry_fn(sess: &Session, node_id: ast::node_id) -> bool { + match *sess.entry_fn { + Some((entry_id, _)) => node_id == entry_id, None => false } } // Create a _rust_main(args: ~[str]) function which will be called from the // runtime rust_start function -pub fn create_main_wrapper(ccx: @CrateContext, +pub fn create_entry_wrapper(ccx: @CrateContext, _sp: span, main_llfn: ValueRef) { - - let llfn = create_main(ccx, main_llfn); - create_entry_fn(ccx, llfn); + let et = ccx.sess.entry_type.unwrap(); + if et == session::EntryMain { + let llfn = create_main(ccx, main_llfn); + create_entry_fn(ccx, llfn, true); + } else { + create_entry_fn(ccx, main_llfn, false); + } fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef { let nt = ty::mk_nil(ccx.tcx); @@ -2242,7 +2246,7 @@ pub fn create_main_wrapper(ccx: @CrateContext, return llfdecl; } - fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef) { + fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item:bool) { let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); // FIXME #4404 android JNI hacks @@ -2264,34 +2268,51 @@ pub fn create_main_wrapper(ccx: @CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); } - let crate_map = ccx.crate_map; - let start_def_id = ccx.tcx.lang_items.start_fn(); - let start_fn = if start_def_id.crate == ast::local_crate { - ccx.sess.bug(~"start lang item is never in the local crate") - } else { - let start_fn_type = csearch::get_type(ccx.tcx, - start_def_id).ty; - trans_external_path(ccx, start_def_id, start_fn_type) - }; let retptr = unsafe { llvm::LLVMBuildAlloca(bld, ccx.int_type, noname()) }; - let args = unsafe { - let opaque_rust_main = llvm::LLVMBuildPointerCast( - bld, rust_main, T_ptr(T_i8()), noname()); - let opaque_crate_map = llvm::LLVMBuildPointerCast( - bld, crate_map, T_ptr(T_i8()), noname()); - - ~[ - retptr, - C_null(T_opaque_box_ptr(ccx)), - opaque_rust_main, - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] + let crate_map = ccx.crate_map; + let opaque_crate_map = unsafe {llvm::LLVMBuildPointerCast( + bld, crate_map, T_ptr(T_i8()), noname())}; + + let (start_fn, args) = if use_start_lang_item { + let start_def_id = ccx.tcx.lang_items.start_fn(); + let start_fn = if start_def_id.crate == ast::local_crate { + ccx.sess.bug(~"start lang item is never in the local crate") + } else { + let start_fn_type = csearch::get_type(ccx.tcx, + start_def_id).ty; + trans_external_path(ccx, start_def_id, start_fn_type) + }; + + let args = unsafe { + let opaque_rust_main = llvm::LLVMBuildPointerCast( + bld, rust_main, T_ptr(T_i8()), noname()); + + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ] + }; + (start_fn, args) + } else { + debug!("using user-defined start fn"); + let args = unsafe { + ~[ retptr, + C_null(T_opaque_box_ptr(ccx)), + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ] + }; + + (rust_main, args) }; unsafe { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index d3502adb33ab8..c10a2c80d7ede 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -50,6 +50,8 @@ independently: use core::prelude::*; +use driver::session; + use middle::resolve; use middle::ty; use util::common::time; @@ -62,7 +64,8 @@ use std::list::List; use std::list; use syntax::codemap::span; use syntax::print::pprust::*; -use syntax::{ast, ast_map}; +use syntax::{ast, ast_map, abi}; +use syntax::opt_vec; #[path = "check/mod.rs"] pub mod check; @@ -325,12 +328,68 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt, } } -fn check_for_main_fn(ccx: @mut CrateCtxt) { +fn check_start_fn_ty(ccx: @mut CrateCtxt, + start_id: ast::node_id, + start_span: span) { + + let tcx = ccx.tcx; + let start_t = ty::node_id_to_type(tcx, start_id); + match ty::get(start_t).sty { + ty::ty_bare_fn(_) => { + match tcx.items.find(&start_id) { + Some(&ast_map::node_item(it,_)) => { + match it.node { + ast::item_fn(_,_,_,ref ps,_) + if ps.is_parameterized() => { + tcx.sess.span_err( + start_span, + ~"start function is not allowed to have type \ + parameters"); + return; + } + _ => () + } + } + _ => () + } + + fn arg(m: ast::rmode, ty: ty::t) -> ty::arg { + ty::arg {mode: ast::expl(m), ty: ty} + } + + let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { + purity: ast::impure_fn, + abis: abi::AbiSet::Rust(), + sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty, + inputs: ~[arg(ast::by_copy, ty::mk_int(tcx)), + arg(ast::by_copy, ty::mk_imm_ptr(tcx, + ty::mk_imm_ptr(tcx, ty::mk_u8(tcx)))), + arg(ast::by_copy, ty::mk_imm_ptr(tcx, ty::mk_u8(tcx)))], + output: ty::mk_int(tcx)} + }); + + require_same_types(tcx, None, false, start_span, start_t, se_ty, + || fmt!("start function expects type: `%s`", ppaux::ty_to_str(ccx.tcx, se_ty))); + + } + _ => { + tcx.sess.span_bug(start_span, + ~"start has a non-function type: found `" + + ppaux::ty_to_str(tcx, start_t) + ~"`"); + } + } +} + +fn check_for_entry_fn(ccx: @mut CrateCtxt) { let tcx = ccx.tcx; if !*tcx.sess.building_library { - match *tcx.sess.main_fn { - Some((id, sp)) => check_main_fn_ty(ccx, id, sp), - None => tcx.sess.err(~"main function not found") + match *tcx.sess.entry_fn { + Some((id, sp)) => match *tcx.sess.entry_type { + Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp), + Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp), + None => tcx.sess.bug(~"entry function without a type") + }, + None => tcx.sess.err(~"entry function not found") } } } @@ -357,7 +416,7 @@ pub fn check_crate(tcx: ty::ctxt, time(time_passes, ~"type checking", || check::check_item_types(ccx, crate)); - check_for_main_fn(ccx); + check_for_entry_fn(ccx); tcx.sess.abort_if_errors(); (ccx.method_map, ccx.vtable_map) } diff --git a/src/test/run-pass/attr-start.rs b/src/test/run-pass/attr-start.rs new file mode 100644 index 0000000000000..efbd7da4797e1 --- /dev/null +++ b/src/test/run-pass/attr-start.rs @@ -0,0 +1,14 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[start] +fn start(argc:int, argv: **u8, crate_map: *u8) -> int { + return 0; +} From df5555aa6742afe93805a1e36444b5ff6cd304a5 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Wed, 10 Apr 2013 14:45:12 +0900 Subject: [PATCH 099/403] Rename tydecode::parse_int to parse_uint It does not handle signs. --- src/librustc/metadata/tydecode.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 867fe0cd816cc..0b2c3769916bf 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -171,7 +171,7 @@ fn parse_vstore(st: @mut PState) -> ty::vstore { let c = peek(st); if '0' <= c && c <= '9' { - let n = parse_int(st) as uint; + let n = parse_uint(st); assert!(next(st) == '|'); return ty::vstore_fixed(n); } @@ -214,13 +214,13 @@ fn parse_bound_region(st: @mut PState) -> ty::bound_region { match next(st) { 's' => ty::br_self, 'a' => { - let id = parse_int(st) as uint; + let id = parse_uint(st); assert!(next(st) == '|'); ty::br_anon(id) } '[' => ty::br_named(st.tcx.sess.ident_of(parse_str(st, ']'))), 'c' => { - let id = parse_int(st); + let id = parse_uint(st) as int; assert!(next(st) == '|'); ty::br_cap_avoid(id, @parse_bound_region(st)) }, @@ -235,14 +235,14 @@ fn parse_region(st: @mut PState) -> ty::Region { } 'f' => { assert!(next(st) == '['); - let id = parse_int(st); + let id = parse_uint(st) as int; assert!(next(st) == '|'); let br = parse_bound_region(st); assert!(next(st) == ']'); ty::re_free(id, br) } 's' => { - let id = parse_int(st); + let id = parse_uint(st) as int; assert!(next(st) == '|'); ty::re_scope(id) } @@ -318,7 +318,7 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { 'p' => { let did = parse_def(st, TypeParameter, conv); debug!("parsed ty_param: did=%?", did); - return ty::mk_param(st.tcx, parse_int(st) as uint, did); + return ty::mk_param(st.tcx, parse_uint(st), did); } 's' => { let did = parse_def(st, TypeParameter, conv); @@ -413,14 +413,14 @@ fn parse_def(st: @mut PState, source: DefIdSource, return conv(source, parse_def_id(def)); } -fn parse_int(st: @mut PState) -> int { +fn parse_uint(st: @mut PState) -> uint { let mut n = 0; loop { let cur = peek(st); if cur < '0' || cur > '9' { return n; } st.pos = st.pos + 1u; n *= 10; - n += (cur as int) - ('0' as int); + n += (cur as uint) - ('0' as uint); }; } From 156a307f4b4f354c8e93a16f8ef64e95b9088bc7 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Wed, 10 Apr 2013 14:57:49 +0900 Subject: [PATCH 100/403] LLVM versions --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 71beb8214b9da..f09213404d1ac 100755 --- a/configure +++ b/configure @@ -533,7 +533,7 @@ then LLVM_VERSION=$($LLVM_CONFIG --version) case $LLVM_VERSION in - (3.2svn|3.2|3.1svn|3.1|3.0svn|3.0) + (3.3|3.3svn|3.2|3.2svn) msg "found ok version of LLVM: $LLVM_VERSION" ;; (*) From 0fea2bd8a110bba08964ec3b050e18505a06e21a Mon Sep 17 00:00:00 2001 From: kud1ing Date: Wed, 10 Apr 2013 09:01:15 +0300 Subject: [PATCH 101/403] README: "driver/rust.rs" => "rust.rc" --- src/librustc/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/README.txt b/src/librustc/README.txt index 9ac35aa444877..487a7927d279d 100644 --- a/src/librustc/README.txt +++ b/src/librustc/README.txt @@ -75,7 +75,7 @@ The 3 central data structures: Control and information flow within the compiler: ------------------------------------------------- -- main() in driver/rustc.rs assumes control on startup. Options are +- main() in rustc.rc assumes control on startup. Options are parsed, platform is detected, etc. - libsyntax/parse/parser.rs parses the input files and produces an AST From 1edfed7914f458172f182c13a2451a0120334092 Mon Sep 17 00:00:00 2001 From: James Miller Date: Wed, 10 Apr 2013 18:02:15 +1200 Subject: [PATCH 102/403] Change tests to use new error message --- src/test/compile-fail/elided-test.rs | 2 +- src/test/compile-fail/missing-main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/compile-fail/elided-test.rs b/src/test/compile-fail/elided-test.rs index b62214b12f9a0..eaae721e0e555 100644 --- a/src/test/compile-fail/elided-test.rs +++ b/src/test/compile-fail/elided-test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: main function not found +// error-pattern: entry function not found // Since we're not compiling a test runner this function should be elided // and the build will fail because main doesn't exist diff --git a/src/test/compile-fail/missing-main.rs b/src/test/compile-fail/missing-main.rs index 4bfdaf69480e6..4f1b604b5070d 100644 --- a/src/test/compile-fail/missing-main.rs +++ b/src/test/compile-fail/missing-main.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:main function not found +// error-pattern:entry function not found fn mian() { } From 08bc392d94726fb04154ce3993c3d519e480b24b Mon Sep 17 00:00:00 2001 From: Bryan Dunsmore Date: Wed, 10 Apr 2013 07:06:18 -0500 Subject: [PATCH 103/403] Update destructuring to reference tuples section. --- doc/tutorial.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 1ac33fe658588..92cf5014d87b7 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -498,7 +498,8 @@ matching in order to bind names to the contents of data types. > ***Note:*** The following code makes use of tuples (`(float, float)`) which -> are explained later. For now you can think of tuples as a list of items. +> are explained in section 5.3. For now you can think of tuples as a list of +> items. ~~~~ fn angle(vector: (float, float)) -> float { From cad226025b868c9a1f7ed08b7bfc3000f0f3a5de Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 10 Apr 2013 22:47:22 +1000 Subject: [PATCH 104/403] librustc: implement a #[packed] attribute for structs. A struct (inc. tuple struct) can be annotated with #[packed], so that there is no padding between its elements, like GCC's `__attribute__((packed))`. Closes #1704 --- src/librustc/middle/trans/adt.rs | 20 ++++++----- src/librustc/middle/trans/asm.rs | 4 +-- src/librustc/middle/trans/base.rs | 8 ++--- src/librustc/middle/trans/cabi_arm.rs | 23 +++++++++---- src/librustc/middle/trans/cabi_mips.rs | 27 ++++++++++----- src/librustc/middle/trans/cabi_x86_64.rs | 23 +++++++++---- src/librustc/middle/trans/common.rs | 44 +++++++++++++----------- src/librustc/middle/trans/foreign.rs | 5 +-- src/librustc/middle/trans/machine.rs | 6 ++-- src/librustc/middle/trans/type_of.rs | 36 +++++++++++++------ src/librustc/middle/ty.rs | 25 +++++++++++++- 11 files changed, 150 insertions(+), 71 deletions(-) diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index b854addf0b1a2..36958fa706ed5 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -88,6 +88,7 @@ pub enum Repr { struct Struct { size: u64, align: u64, + packed: bool, fields: ~[ty::t] } @@ -109,17 +110,18 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { } let repr = @match ty::get(t).sty { ty::ty_tup(ref elems) => { - Univariant(mk_struct(cx, *elems), false) + Univariant(mk_struct(cx, *elems, false), false) } ty::ty_struct(def_id, ref substs) => { let fields = ty::lookup_struct_fields(cx.tcx, def_id); let ftys = do fields.map |field| { ty::lookup_field_type(cx.tcx, def_id, field.id, substs) }; + let packed = ty::lookup_packed(cx.tcx, def_id); let dtor = ty::ty_dtor(cx.tcx, def_id).is_present(); let ftys = if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { ftys }; - Univariant(mk_struct(cx, ftys), dtor) + Univariant(mk_struct(cx, ftys, packed), dtor) } ty::ty_enum(def_id, ref substs) => { struct Case { discr: int, tys: ~[ty::t] }; @@ -132,7 +134,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { }; if cases.len() == 0 { // Uninhabitable; represent as unit - Univariant(mk_struct(cx, ~[]), false) + Univariant(mk_struct(cx, ~[], false), false) } else if cases.all(|c| c.tys.len() == 0) { // All bodies empty -> intlike let discrs = cases.map(|c| c.discr); @@ -140,7 +142,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { } else if cases.len() == 1 { // Equivalent to a struct/tuple/newtype. assert!(cases[0].discr == 0); - Univariant(mk_struct(cx, cases[0].tys), false) + Univariant(mk_struct(cx, cases[0].tys, false), false) } else { // The general case. Since there's at least one // non-empty body, explicit discriminants should have @@ -151,7 +153,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { ty::item_path_str(cx.tcx, def_id))) } let discr = ~[ty::mk_int(cx.tcx)]; - General(cases.map(|c| mk_struct(cx, discr + c.tys))) + General(cases.map(|c| mk_struct(cx, discr + c.tys, false))) } } _ => cx.sess.bug(~"adt::represent_type called on non-ADT type") @@ -160,12 +162,13 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { return repr; } -fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct { +fn mk_struct(cx: @CrateContext, tys: &[ty::t], packed: bool) -> Struct { let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty)); - let llty_rec = T_struct(lltys); + let llty_rec = T_struct(lltys, packed); Struct { size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64, align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64, + packed: packed, fields: vec::from_slice(tys) } } @@ -358,7 +361,8 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint, let val = if needs_cast { let real_llty = T_struct(st.fields.map( - |&ty| type_of::type_of(ccx, ty))); + |&ty| type_of::type_of(ccx, ty)), + st.packed); PointerCast(bcx, val, T_ptr(real_llty)) } else { val diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index b3b23a8730d1a..cbcefdd5fdb77 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -108,7 +108,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block { } else if numOutputs == 1 { val_ty(outputs[0]) } else { - T_struct(outputs.map(|o| val_ty(*o))) + T_struct(outputs.map(|o| val_ty(*o)), false) }; let dialect = match ia.dialect { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 2eb7f8332ca92..d94f2bf3c2fe5 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -938,7 +938,7 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef { // The landing pad return type (the type being propagated). Not sure what // this represents but it's determined by the personality function and // this is what the EH proposal example uses. - let llretty = T_struct(~[T_ptr(T_i8()), T_i32()]); + let llretty = T_struct(~[T_ptr(T_i8()), T_i32()], false); // The exception handling personality function. This is the C++ // personality function __gxx_personality_v0, wrapped in our naming // convention. @@ -2837,7 +2837,7 @@ pub fn decl_gc_metadata(ccx: @CrateContext, llmod_id: &str) { } pub fn create_module_map(ccx: @CrateContext) -> ValueRef { - let elttype = T_struct(~[ccx.int_type, ccx.int_type]); + let elttype = T_struct(~[ccx.int_type, ccx.int_type], false); let maptype = T_array(elttype, ccx.module_data.len() + 1); let map = str::as_c_str(~"_rust_mod_map", |buf| { unsafe { @@ -2877,7 +2877,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, }; let sym_name = ~"_rust_crate_map_" + mapname; let arrtype = T_array(int_type, n_subcrates as uint); - let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype]); + let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype], false); let map = str::as_c_str(sym_name, |buf| { unsafe { llvm::LLVMAddGlobal(llmod, maptype, buf) diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs index a16b3672b7afe..1b94e990545ea 100644 --- a/src/librustc/middle/trans/cabi_arm.rs +++ b/src/librustc/middle/trans/cabi_arm.rs @@ -12,6 +12,7 @@ use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array}; use lib::llvm::struct_tys; use lib::llvm::TypeRef; use lib::llvm::{Attribute, StructRetAttribute}; +use lib::llvm::True; use middle::trans::cabi::{ABIInfo, FnType, LLVMType}; use middle::trans::common::{T_i8, T_i16, T_i32, T_i64}; use middle::trans::common::{T_array, T_ptr, T_void}; @@ -39,8 +40,12 @@ fn ty_align(ty: TypeRef) -> uint { Float => 4, Double => 8, Struct => { - do vec::foldl(1, struct_tys(ty)) |a, t| { - uint::max(a, ty_align(*t)) + if llvm::LLVMIsPackedStruct(ty) == True { + 1 + } else { + do vec::foldl(1, struct_tys(ty)) |a, t| { + uint::max(a, ty_align(*t)) + } } } Array => { @@ -62,10 +67,16 @@ fn ty_size(ty: TypeRef) -> uint { Float => 4, Double => 8, Struct => { - let size = do vec::foldl(0, struct_tys(ty)) |s, t| { - align(s, *t) + ty_size(*t) - }; - align(size, ty) + if llvm::LLVMIsPackedStruct(ty) == True { + do vec::foldl(0, struct_tys(ty)) |s, t| { + s + ty_size(*t) + } + } else { + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + align(s, *t) + ty_size(*t) + }; + align(size, ty) + } } Array => { let len = llvm::LLVMGetArrayLength(ty) as uint; diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index 1e05cf258c719..ce37455560b5c 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,6 +14,7 @@ use core::libc::c_uint; use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double}; use lib::llvm::{Struct, Array, Attribute}; use lib::llvm::{StructRetAttribute}; +use lib::llvm::True; use middle::trans::common::*; use middle::trans::cabi::*; @@ -49,8 +50,12 @@ fn ty_align(ty: TypeRef) -> uint { Float => 4, Double => 8, Struct => { - do vec::foldl(1, struct_tys(ty)) |a, t| { - uint::max(a, ty_align(*t)) + if llvm::LLVMIsPackedStruct(ty) == True { + 1 + } else { + do vec::foldl(1, struct_tys(ty)) |a, t| { + uint::max(a, ty_align(*t)) + } } } Array => { @@ -72,10 +77,16 @@ fn ty_size(ty: TypeRef) -> uint { Float => 4, Double => 8, Struct => { - let size = do vec::foldl(0, struct_tys(ty)) |s, t| { - align(s, *t) + ty_size(*t) - }; - align(size, ty) + if llvm::LLVMIsPackedStruct(ty) == True { + do vec::foldl(0, struct_tys(ty)) |s, t| { + s + ty_size(*t) + } + } else { + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + align(s, *t) + ty_size(*t) + }; + align(size, ty) + } } Array => { let len = llvm::LLVMGetArrayLength(ty) as uint; @@ -174,7 +185,7 @@ fn struct_ty(ty: TypeRef, fields.push(ty); } - return T_struct(fields); + return T_struct(fields, false); } enum MIPS_ABIInfo { MIPS_ABIInfo } diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index 896ebd1625755..0e4bf5ce574a1 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -15,6 +15,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double}; use lib::llvm::{Struct, Array, Attribute}; use lib::llvm::{StructRetAttribute, ByValAttribute}; use lib::llvm::struct_tys; +use lib::llvm::True; use middle::trans::common::*; use middle::trans::cabi::*; @@ -76,8 +77,12 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { Float => 4, Double => 8, Struct => { - do vec::foldl(1, struct_tys(ty)) |a, t| { + if llvm::LLVMIsPackedStruct(ty) == True { + 1 + } else { + do vec::foldl(1, struct_tys(ty)) |a, t| { uint::max(a, ty_align(*t)) + } } } Array => { @@ -99,10 +104,16 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { Float => 4, Double => 8, Struct => { - let size = do vec::foldl(0, struct_tys(ty)) |s, t| { + if llvm::LLVMIsPackedStruct(ty) == True { + do vec::foldl(0, struct_tys(ty)) |s, t| { + s + ty_size(*t) + } + } else { + let size = do vec::foldl(0, struct_tys(ty)) |s, t| { align(s, *t) + ty_size(*t) - }; - align(size, ty) + }; + align(size, ty) + } } Array => { let len = llvm::LLVMGetArrayLength(ty) as uint; @@ -308,7 +319,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef { } i += 1u; } - return T_struct(tys); + return T_struct(tys, false); } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 2cfd7a25d6823..4701a166ea766 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -765,7 +765,7 @@ pub fn T_void() -> TypeRef { } pub fn T_nil() -> TypeRef { - return T_struct(~[]) + return T_struct(~[], false) } pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } } @@ -848,7 +848,7 @@ pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef { } pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef { - return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)]); + return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)], false); } pub fn T_ptr(t: TypeRef) -> TypeRef { @@ -863,11 +863,11 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef { } } -pub fn T_struct(elts: &[TypeRef]) -> TypeRef { +pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef { unsafe { return llvm::LLVMStructType(to_ptr(elts), elts.len() as c_uint, - False); + packed as Bool); } } @@ -878,16 +878,16 @@ pub fn T_named_struct(name: &str) -> TypeRef { } } -pub fn set_struct_body(t: TypeRef, elts: &[TypeRef]) { +pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) { unsafe { llvm::LLVMStructSetBody(t, to_ptr(elts), elts.len() as c_uint, - False); + packed as Bool); } } -pub fn T_empty_struct() -> TypeRef { return T_struct(~[]); } +pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); } // A vtable is, in reality, a vtable pointer followed by zero or more pointers // to tydescs and other vtables that it closes over. But the types and number @@ -913,7 +913,7 @@ pub fn T_task(targ_cfg: @session::config) -> TypeRef { let elems = ~[t_int, t_int, t_int, t_int, t_int, t_int, t_int, t_int]; - set_struct_body(t, elems); + set_struct_body(t, elems, false); return t; } @@ -956,7 +956,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef { ~[int_type, int_type, glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty, T_ptr(T_i8()), T_ptr(T_i8())]; - set_struct_body(tydesc, elems); + set_struct_body(tydesc, elems, false); return tydesc; } @@ -969,8 +969,9 @@ pub fn T_array(t: TypeRef, n: uint) -> TypeRef { // Interior vector. pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef { return T_struct(~[T_int(targ_cfg), // fill - T_int(targ_cfg), // alloc - T_array(t, 0u)]); // elements + T_int(targ_cfg), // alloc + T_array(t, 0u)], // elements + false); } pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef { @@ -1001,11 +1002,11 @@ pub fn T_box_header_fields(cx: @CrateContext) -> ~[TypeRef] { } pub fn T_box_header(cx: @CrateContext) -> TypeRef { - return T_struct(T_box_header_fields(cx)); + return T_struct(T_box_header_fields(cx), false); } pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef { - return T_struct(vec::append(T_box_header_fields(cx), ~[t])); + return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false); } pub fn T_box_ptr(t: TypeRef) -> TypeRef { @@ -1023,7 +1024,7 @@ pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef { } pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef { - return T_struct(vec::append(T_box_header_fields(cx), ~[t])); + return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false); } pub fn T_unique_ptr(t: TypeRef) -> TypeRef { @@ -1033,12 +1034,12 @@ pub fn T_unique_ptr(t: TypeRef) -> TypeRef { } pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef { - return T_struct(~[cx.int_type]); // Refcount + return T_struct(~[cx.int_type], false); // Refcount } pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef { - return T_struct(~[cx.int_type]); // Refcount + return T_struct(~[cx.int_type], false); // Refcount } @@ -1056,21 +1057,22 @@ pub fn T_enum_discrim(cx: @CrateContext) -> TypeRef { } pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef { - return T_struct(vec::from_elem::(n, T_ptr(cx.tydesc_type))); + return T_struct(vec::from_elem::(n, T_ptr(cx.tydesc_type)), false); } pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef { match store { ty::BoxTraitStore => { - T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)]) + T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false) } ty::UniqTraitStore => { T_struct(~[T_ptr(cx.tydesc_type), T_unique_ptr(T_unique(cx, T_i8())), - T_ptr(cx.tydesc_type)]) + T_ptr(cx.tydesc_type)], + false) } ty::RegionTraitStore(_) => { - T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())]) + T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())], false) } } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 7dc2e385e2cf6..387caa4d8d31f 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -106,7 +106,8 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { }; let llsig = foreign_signature(ccx, &fn_sig); let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys, - T_ptr(llsig.llret_ty))); + T_ptr(llsig.llret_ty)), + false); let ret_def = !ty::type_is_bot(fn_sig.output) && !ty::type_is_nil(fn_sig.output); diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index 1b9f7bae0e93f..cd90f964e452e 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -142,9 +142,9 @@ pub fn static_size_of_enum(cx: @CrateContext, t: ty::t) -> uint { debug!("static_size_of_enum: variant %s type %s", *cx.tcx.sess.str_of(variant.name), - ty_str(cx.tn, T_struct(lltypes))); + ty_str(cx.tn, T_struct(lltypes, false))); - let this_size = llsize_of_real(cx, T_struct(lltypes)); + let this_size = llsize_of_real(cx, T_struct(lltypes, false)); if max_size < this_size { max_size = this_size; } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index a9381647b3326..1c94fe2842219 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -128,11 +128,11 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_estr(ty::vstore_slice(*)) | ty::ty_evec(_, ty::vstore_slice(*)) => { - T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]) + T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false) } ty::ty_bare_fn(*) => T_ptr(T_i8()), - ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]), + ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false), ty::ty_trait(_, _, store) => T_opaque_trait(cx, store), ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size), @@ -142,9 +142,15 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_unboxed_vec(mt) => T_vec(cx, sizing_type_of(cx, mt.ty)), - ty::ty_tup(*) | ty::ty_struct(*) | ty::ty_enum(*) => { + ty::ty_tup(*) | ty::ty_enum(*) => { let repr = adt::represent_type(cx, t); - T_struct(adt::sizing_fields_of(cx, repr)) + T_struct(adt::sizing_fields_of(cx, repr), false) + } + + ty::ty_struct(did, _) => { + let repr = adt::represent_type(cx, t); + let packed = ty::lookup_packed(cx.tcx, did); + T_struct(adt::sizing_fields_of(cx, repr), packed) } ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => { @@ -223,12 +229,14 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_evec(ref mt, ty::vstore_slice(_)) => { T_struct(~[T_ptr(type_of(cx, mt.ty)), - T_uint_ty(cx, ast::ty_u)]) + T_uint_ty(cx, ast::ty_u)], + false) } ty::ty_estr(ty::vstore_slice(_)) => { T_struct(~[T_ptr(T_i8()), - T_uint_ty(cx, ast::ty_u)]) + T_uint_ty(cx, ast::ty_u)], + false) } ty::ty_estr(ty::vstore_fixed(n)) => { @@ -245,7 +253,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_type => T_ptr(cx.tydesc_type), ty::ty_tup(*) => { let repr = adt::represent_type(cx, t); - T_struct(adt::fields_of(cx, repr)) + T_struct(adt::fields_of(cx, repr), false) } ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx), ty::ty_struct(did, ref substs) => { @@ -268,9 +276,17 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { // If this was an enum or struct, fill in the type now. match ty::get(t).sty { - ty::ty_enum(*) | ty::ty_struct(*) => { + ty::ty_enum(*) => { let repr = adt::represent_type(cx, t); - common::set_struct_body(llty, adt::fields_of(cx, repr)); + common::set_struct_body(llty, adt::fields_of(cx, repr), + false); + } + + ty::ty_struct(did, _) => { + let repr = adt::represent_type(cx, t); + let packed = ty::lookup_packed(cx.tcx, did); + common::set_struct_body(llty, adt::fields_of(cx, repr), + packed); } _ => () } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 742153124346a..335c9824354d2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -44,6 +44,7 @@ use std::smallintmap::SmallIntMap; use syntax::ast::*; use syntax::ast_util::{is_local, local_def}; use syntax::ast_util; +use syntax::attr; use syntax::codemap::span; use syntax::codemap; use syntax::print::pprust; @@ -3933,6 +3934,28 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef { } } +// Determine whether an item is annotated with #[packed] or not +pub fn lookup_packed(tcx: ctxt, + did: def_id) -> bool { + if is_local(did) { + match tcx.items.find(&did.node) { + Some( + &ast_map::node_item(@ast::item { + attrs: ref attrs, + _ + }, _)) => attr::attrs_contains_name(*attrs, "packed"), + _ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item", + did)) + } + } else { + let mut ret = false; + do csearch::get_item_attrs(tcx.cstore, did) |meta_items| { + ret = attr::contains_name(meta_items, "packed"); + } + ret + } +} + // Look up a field ID, whether or not it's local // Takes a list of type substs in case the struct is generic pub fn lookup_field_type(tcx: ctxt, From 7d7e149748846a306df56fae873db66b47a97a12 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 10 Apr 2013 23:47:53 +1000 Subject: [PATCH 105/403] testsuite: tests for #[packed] structs. --- .../packed-struct-generic-transmute.rs | 35 +++++++++++ .../compile-fail/packed-struct-transmute.rs | 35 +++++++++++ .../run-pass/packed-struct-borrow-element.rs | 22 +++++++ .../run-pass/packed-struct-generic-layout.rs | 35 +++++++++++ .../run-pass/packed-struct-generic-size.rs | 25 ++++++++ src/test/run-pass/packed-struct-layout.rs | 34 +++++++++++ src/test/run-pass/packed-struct-match.rs | 25 ++++++++ src/test/run-pass/packed-struct-size.rs | 58 +++++++++++++++++++ src/test/run-pass/packed-struct-vec.rs | 30 ++++++++++ .../run-pass/packed-tuple-struct-layout.rs | 28 +++++++++ src/test/run-pass/packed-tuple-struct-size.rs | 44 ++++++++++++++ 11 files changed, 371 insertions(+) create mode 100644 src/test/compile-fail/packed-struct-generic-transmute.rs create mode 100644 src/test/compile-fail/packed-struct-transmute.rs create mode 100644 src/test/run-pass/packed-struct-borrow-element.rs create mode 100644 src/test/run-pass/packed-struct-generic-layout.rs create mode 100644 src/test/run-pass/packed-struct-generic-size.rs create mode 100644 src/test/run-pass/packed-struct-layout.rs create mode 100644 src/test/run-pass/packed-struct-match.rs create mode 100644 src/test/run-pass/packed-struct-size.rs create mode 100644 src/test/run-pass/packed-struct-vec.rs create mode 100644 src/test/run-pass/packed-tuple-struct-layout.rs create mode 100644 src/test/run-pass/packed-tuple-struct-size.rs diff --git a/src/test/compile-fail/packed-struct-generic-transmute.rs b/src/test/compile-fail/packed-struct-generic-transmute.rs new file mode 100644 index 0000000000000..3ed9d00be28b1 --- /dev/null +++ b/src/test/compile-fail/packed-struct-generic-transmute.rs @@ -0,0 +1,35 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This assumes the packed and non-packed structs are different sizes. + +// the error points to the start of the file, not the line with the +// transmute + +// error-pattern: reinterpret_cast called on types with different size + +#[packed] +struct Foo { + bar: T, + baz: S +} + +struct Oof { + rab: T, + zab: S +} + +fn main() { + let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 }; + unsafe { + let oof: Oof<[u8, .. 5], i32> = cast::transmute(foo); + debug!(oof); + } +} diff --git a/src/test/compile-fail/packed-struct-transmute.rs b/src/test/compile-fail/packed-struct-transmute.rs new file mode 100644 index 0000000000000..d2aca3c0d6b61 --- /dev/null +++ b/src/test/compile-fail/packed-struct-transmute.rs @@ -0,0 +1,35 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This assumes the packed and non-packed structs are different sizes. + +// the error points to the start of the file, not the line with the +// transmute + +// error-pattern: reinterpret_cast called on types with different size + +#[packed] +struct Foo { + bar: u8, + baz: uint +} + +struct Oof { + rab: u8, + zab: uint +} + +fn main() { + let foo = Foo { bar: 1, baz: 10 }; + unsafe { + let oof: Oof = cast::transmute(foo); + debug!(oof); + } +} diff --git a/src/test/run-pass/packed-struct-borrow-element.rs b/src/test/run-pass/packed-struct-borrow-element.rs new file mode 100644 index 0000000000000..a331b80a894ea --- /dev/null +++ b/src/test/run-pass/packed-struct-borrow-element.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct Foo { + bar: u8, + baz: uint +} + +fn main() { + let foo = Foo { bar: 1, baz: 2 }; + let brw = &foo.baz; + + assert_eq!(*brw, 2); +} diff --git a/src/test/run-pass/packed-struct-generic-layout.rs b/src/test/run-pass/packed-struct-generic-layout.rs new file mode 100644 index 0000000000000..fd6e3b670f5ab --- /dev/null +++ b/src/test/run-pass/packed-struct-generic-layout.rs @@ -0,0 +1,35 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S { + a: T, + b: u8, + c: S +} + +fn main() { + unsafe { + let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 }; + let transd : [u8, .. 9] = cast::transmute(s); + // Don't worry about endianness, the numbers are palindromic. + assert_eq!(transd, + [0xff, 0xff, 0xff, 0xff, + 1, + 0xaa, 0xaa, 0xaa, 0xaa]); + + + let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16}; + let transd : [u8, .. 4] = cast::transmute(s); + // Again, no endianness problems. + assert_eq!(transd, + [1, 2, 0b10000001, 0b10000001]); + } +} diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs new file mode 100644 index 0000000000000..a5c4d5385a297 --- /dev/null +++ b/src/test/run-pass/packed-struct-generic-size.rs @@ -0,0 +1,25 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S { + a: T, + b: u8, + c: S +} + +fn main() { + assert_eq!(sys::size_of::>(), 3); + + assert_eq!(sys::size_of::>(), 11); + + assert_eq!(sys::size_of::>(), + 1 + sys::size_of::<~str>() + sys::size_of::<@mut [int]>()); +} diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs new file mode 100644 index 0000000000000..8d27e55e191a4 --- /dev/null +++ b/src/test/run-pass/packed-struct-layout.rs @@ -0,0 +1,34 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S4 { + a: u8, + b: [u8, .. 3], +} + +#[packed] +struct S5 { + a: u8, + b: u32 +} + +fn main() { + unsafe { + let s4 = S4 { a: 1, b: [2,3,4] }; + let transd : [u8, .. 4] = cast::transmute(s4); + assert_eq!(transd, [1, 2, 3, 4]); + + let s5 = S5 { a: 1, b: 0xff_00_00_ff }; + let transd : [u8, .. 5] = cast::transmute(s5); + // Don't worry about endianness, the u32 is palindromic. + assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); + } +} diff --git a/src/test/run-pass/packed-struct-match.rs b/src/test/run-pass/packed-struct-match.rs new file mode 100644 index 0000000000000..15e7b6b0ce0c5 --- /dev/null +++ b/src/test/run-pass/packed-struct-match.rs @@ -0,0 +1,25 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct Foo { + bar: u8, + baz: uint +} + +fn main() { + let foo = Foo { bar: 1, baz: 2 }; + match foo { + Foo {bar, baz} => { + assert_eq!(bar, 1); + assert_eq!(baz, 2); + } + } +} diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs new file mode 100644 index 0000000000000..372fe3d37f69d --- /dev/null +++ b/src/test/run-pass/packed-struct-size.rs @@ -0,0 +1,58 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S4 { + a: u8, + b: [u8, .. 3], +} + +#[packed] +struct S5 { + a: u8, + b: u32 +} + +#[packed] +struct S13_str { + a: i64, + b: f32, + c: u8, + d: ~str +} + +enum Foo { + Bar = 1, + Baz = 2 +} + +#[packed] +struct S3_Foo { + a: u8, + b: u16, + c: Foo +} + +#[packed] +struct S7_Option { + a: f32, + b: u8, + c: u16, + d: Option<@mut f64> +} + + +fn main() { + assert_eq!(sys::size_of::(), 4); + assert_eq!(sys::size_of::(), 5); + assert_eq!(sys::size_of::(), 13 + sys::size_of::<~str>()); + assert_eq!(sys::size_of::(), 3 + sys::size_of::()); + assert_eq!(sys::size_of::(), 7 + sys::size_of::>()); +} diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs new file mode 100644 index 0000000000000..b1ac29b7721a8 --- /dev/null +++ b/src/test/run-pass/packed-struct-vec.rs @@ -0,0 +1,30 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +#[deriving(Eq)] +struct Foo { + bar: u8, + baz: u64 +} + +fn main() { + let foos = [Foo { bar: 1, baz: 2 }, .. 10]; + + assert_eq!(sys::size_of::<[Foo, .. 10]>(), 90); + + for uint::range(0, 10) |i| { + assert_eq!(foos[i], Foo { bar: 1, baz: 2}); + } + + for foos.each |&foo| { + assert_eq!(foo, Foo { bar: 1, baz: 2 }); + } +} diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs new file mode 100644 index 0000000000000..9c2fe621a321a --- /dev/null +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -0,0 +1,28 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S4(u8,[u8, .. 3]); + +#[packed] +struct S5(u8,u32); + +fn main() { + unsafe { + let s4 = S4(1, [2,3,4]); + let transd : [u8, .. 4] = cast::transmute(s4); + assert_eq!(transd, [1, 2, 3, 4]); + + let s5 = S5(1, 0xff_00_00_ff); + let transd : [u8, .. 5] = cast::transmute(s5); + // Don't worry about endianness, the u32 is palindromic. + assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); + } +} diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs new file mode 100644 index 0000000000000..23faa2eb0adc9 --- /dev/null +++ b/src/test/run-pass/packed-tuple-struct-size.rs @@ -0,0 +1,44 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[packed] +struct S4(u8,[u8, .. 3]); + +#[packed] +struct S5(u8, u32); + +#[packed] +struct S13_str(i64, f32, u8, ~str); + +enum Foo { + Bar = 1, + Baz = 2 +} + +#[packed] +struct S3_Foo(u8, u16, Foo); + +#[packed] +struct S7_Option(f32, u8, u16, Option<@mut f64>); + +fn main() { + assert_eq!(sys::size_of::(), 4); + + assert_eq!(sys::size_of::(), 5); + + assert_eq!(sys::size_of::(), + 13 + sys::size_of::<~str>()); + + assert_eq!(sys::size_of::(), + 3 + sys::size_of::()); + + assert_eq!(sys::size_of::(), + 7 + sys::size_of::>()); +} From 5606fc0c90461db40faeca16d7bffd9e61c2be73 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 6 Apr 2013 11:22:36 -0400 Subject: [PATCH 106/403] Revert map.each to something which takes two parameters rather than a tuple. The current setup iterates over `BaseIter<(&'self K, &'self V)>` where 'self is a lifetime declared *in the each method*. You can't place such a type in the impl declaration. The compiler currently allows it, but this will not be legal under #5656 and I'm pretty sure it's not sound now. --- src/libcore/container.rs | 3 + src/libcore/hashmap.rs | 39 +++++------- src/libcore/trie.rs | 62 +++++++++---------- src/librustc/metadata/cstore.rs | 2 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/middle/lint.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/middle/resolve.rs | 16 ++--- src/librustc/middle/trans/base.rs | 4 +- .../middle/typeck/infer/region_inference.rs | 2 +- src/librustc/rustc.rc | 2 +- src/libstd/json.rs | 8 +-- src/libstd/net_url.rs | 2 +- src/libstd/serialize.rs | 6 +- src/libstd/smallintmap.rs | 52 +++++++--------- src/libstd/treemap.rs | 52 +++++++--------- src/libstd/workcache.rs | 4 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- .../class-impl-very-parameterized-trait.rs | 28 ++++----- 19 files changed, 132 insertions(+), 158 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index e20821b919b6c..a1836d16fd733 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -29,6 +29,9 @@ pub trait Map: Mutable { /// Return true if the map contains a value for the specified key fn contains_key(&self, key: &K) -> bool; + // Visits all keys and values + fn each(&self, f: &fn(&K, &V) -> bool); + /// Visit all keys fn each_key(&self, f: &fn(&K) -> bool); diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 5dbf085f09719..d4af0ffe7fe7b 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -279,24 +279,6 @@ priv impl HashMap { } } -impl<'self,K:Hash + IterBytes + Eq,V> - BaseIter<(&'self K, &'self V)> for HashMap { - /// Visit all key-value pairs - fn each(&self, blk: &fn(&(&'self K, &'self V)) -> bool) { - for uint::range(0, self.buckets.len()) |i| { - let mut broke = false; - do self.buckets[i].map |bucket| { - if !blk(&(&bucket.key, &bucket.value)) { - broke = true; // FIXME(#3064) just write "break;" - } - }; - if broke { break; } - } - } - fn size_hint(&self) -> Option { Some(self.len()) } -} - - impl Container for HashMap { /// Return the number of elements in the map fn len(&const self) -> uint { self.size } @@ -315,7 +297,7 @@ impl Mutable for HashMap { } } -impl<'self,K:Hash + IterBytes + Eq,V> Map for HashMap { +impl Map for HashMap { /// Return true if the map contains a value for the specified key fn contains_key(&self, k: &K) -> bool { match self.bucket_for_key(k) { @@ -324,14 +306,25 @@ impl<'self,K:Hash + IterBytes + Eq,V> Map for HashMap { } } + /// Visit all key-value pairs + fn each(&self, blk: &fn(&'self K, &'self V) -> bool) { + for uint::range(0, self.buckets.len()) |i| { + for self.buckets[i].each |bucket| { + if !blk(&bucket.key, &bucket.value) { + return; + } + } + } + } + /// Visit all keys fn each_key(&self, blk: &fn(k: &K) -> bool) { - self.each(|&(k, _)| blk(k)) + self.each(|k, _| blk(k)) } /// Visit all values fn each_value(&self, blk: &fn(v: &V) -> bool) { - self.each(|&(_, v)| blk(v)) + self.each(|_, v| blk(v)) } /// Iterate over the map and mutate the contained values @@ -545,7 +538,7 @@ impl Eq for HashMap { fn eq(&self, other: &HashMap) -> bool { if self.len() != other.len() { return false; } - for self.each |&(key, value)| { + for self.each |key, value| { match other.find(key) { None => return false, Some(v) => if value != v { return false }, @@ -798,7 +791,7 @@ mod test_map { assert!(m.insert(i, i*2)); } let mut observed = 0; - for m.each |&(k, v)| { + for m.each |k, v| { assert!(*v == *k * 2); observed |= (1 << *k); } diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index 5d87e2a296d3d..f6a92a213859e 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -28,24 +28,6 @@ pub struct TrieMap { priv length: uint } -impl<'self,T> BaseIter<(uint, &'self T)> for TrieMap { - /// Visit all key-value pairs in order - #[inline(always)] - fn each(&self, f: &fn(&(uint, &'self T)) -> bool) { - self.root.each(f); - } - #[inline(always)] - fn size_hint(&self) -> Option { Some(self.len()) } -} - -impl<'self,T> ReverseIter<(uint, &'self T)> for TrieMap { - /// Visit all key-value pairs in reverse order - #[inline(always)] - fn each_reverse(&self, f: &fn(&(uint, &'self T)) -> bool) { - self.root.each_reverse(f); - } -} - impl Container for TrieMap { /// Return the number of elements in the map #[inline(always)] @@ -72,16 +54,22 @@ impl Map for TrieMap { self.find(key).is_some() } + /// Visit all key-value pairs in order + #[inline(always)] + fn each(&self, f: &fn(&uint, &'self T) -> bool) { + self.root.each(f); + } + /// Visit all keys in order #[inline(always)] fn each_key(&self, f: &fn(&uint) -> bool) { - self.each(|&(k, _)| f(&k)) + self.each(|k, _| f(k)) } /// Visit all values in order #[inline(always)] fn each_value(&self, f: &fn(&T) -> bool) { - self.each(|&(_, v)| f(v)) + self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values @@ -148,16 +136,22 @@ pub impl TrieMap { TrieMap{root: TrieNode::new(), length: 0} } + /// Visit all key-value pairs in reverse order + #[inline(always)] + fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) { + self.root.each_reverse(f); + } + /// Visit all keys in reverse order #[inline(always)] fn each_key_reverse(&self, f: &fn(&uint) -> bool) { - self.each_reverse(|&(k, _)| f(&k)) + self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order #[inline(always)] fn each_value_reverse(&self, f: &fn(&T) -> bool) { - self.each_reverse(|&(_, v)| f(v)) + self.each_reverse(|_, v| f(v)) } } @@ -239,22 +233,22 @@ impl TrieNode { } impl TrieNode { - fn each(&self, f: &fn(&(uint, &'self T)) -> bool) -> bool { + fn each(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range(0, self.children.len()) |idx| { match self.children[idx] { Internal(ref x) => if !x.each(f) { return false }, - External(k, ref v) => if !f(&(k, v)) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, Nothing => () } } true } - fn each_reverse(&self, f: &fn(&(uint, &'self T)) -> bool) -> bool { + fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range_rev(self.children.len(), 0) |idx| { match self.children[idx - 1] { Internal(ref x) => if !x.each_reverse(f) { return false }, - External(k, ref v) => if !f(&(k, v)) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, Nothing => () } } @@ -438,8 +432,8 @@ mod tests { assert!(m.insert(1, 2)); let mut n = 0; - for m.each |&(k, v)| { - assert!(k == n); + for m.each |k, v| { + assert!(*k == n); assert!(*v == n * 2); n += 1; } @@ -454,11 +448,11 @@ mod tests { } let mut n = uint::max_value - 9999; - for m.each |&(k, v)| { + for m.each |k, v| { if n == uint::max_value - 5000 { break } assert!(n < uint::max_value - 5000); - assert!(k == n); + assert!(*k == n); assert!(*v == n / 2); n += 1; } @@ -475,8 +469,8 @@ mod tests { assert!(m.insert(1, 2)); let mut n = 4; - for m.each_reverse |&(k, v)| { - assert!(k == n); + for m.each_reverse |k, v| { + assert!(*k == n); assert!(*v == n * 2); n -= 1; } @@ -491,11 +485,11 @@ mod tests { } let mut n = uint::max_value; - for m.each_reverse |&(k, v)| { + for m.each_reverse |k, v| { if n == uint::max_value - 5000 { break } assert!(n > uint::max_value - 5000); - assert!(k == n); + assert!(*k == n); assert!(*v == n / 2); n -= 1; } diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 65bd37236b714..d738c3e774794 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -86,7 +86,7 @@ pub fn have_crate_data(cstore: &CStore, cnum: ast::crate_num) -> bool { pub fn iter_crate_data(cstore: &CStore, i: &fn(ast::crate_num, @crate_metadata)) { - for cstore.metas.each |&(&k, &v)| { + for cstore.metas.each |&k, &v| { i(k, v); } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index ab9b8ca0db624..0dd28e5ca7ca1 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -397,7 +397,7 @@ pub impl<'self> LanguageItemCollector<'self> { } fn check_completeness(&self) { - for self.item_refs.each |&(&key, &item_ref)| { + for self.item_refs.each |&key, &item_ref| { match self.items.items[item_ref] { None => { self.session.err(fmt!("no item found for `%s`", *key)); diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 0adf4b87f3a8e..6f8992bf1ca4a 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -460,7 +460,7 @@ pub fn build_settings_crate(sess: session::Session, crate: @ast::crate) { do cx.with_lint_attrs(/*bad*/copy crate.node.attrs) |cx| { // Copy out the default settings - for cx.curr.each |&(k, &v)| { + for cx.curr.each |&k, &v| { sess.lint_settings.default_settings.insert(k, v); } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 1c60c37ed12a0..50c193ab3b095 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -842,7 +842,7 @@ pub fn determine_rp_in_crate(sess: Session, debug!("%s", { debug!("Region variance results:"); let region_paramd_items = cx.region_paramd_items; - for region_paramd_items.each |&(&key, &value)| { + for region_paramd_items.each |&key, &value| { debug!("item %? (%s) is parameterized with variance %?", key, ast_map::node_id_to_str(ast_map, key, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index fcf0b7022a7a7..c7f53c744f1bf 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2369,7 +2369,7 @@ pub impl Resolver { // Add all resolved imports from the containing module. for containing_module.import_resolutions.each - |&(ident, target_import_resolution)| { + |ident, target_import_resolution| { debug!("(resolving glob import) writing module resolution \ %? into `%s`", @@ -2457,13 +2457,13 @@ pub impl Resolver { }; // Add all children from the containing module. - for containing_module.children.each |&(ident, name_bindings)| { + for containing_module.children.each |ident, name_bindings| { merge_import_resolution(ident, *name_bindings); } // Add external module children from the containing module. for containing_module.external_module_children.each - |&(ident, module)| { + |ident, module| { let name_bindings = @mut Resolver::create_name_bindings_from_module(*module); merge_import_resolution(ident, name_bindings); @@ -3111,7 +3111,7 @@ pub impl Resolver { fn add_exports_for_module(@mut self, exports2: &mut ~[Export2], module_: @mut Module) { - for module_.children.each |&(ident, namebindings)| { + for module_.children.each |ident, namebindings| { debug!("(computing exports) maybe export '%s'", *self.session.str_of(*ident)); self.add_exports_of_namebindings(&mut *exports2, @@ -3126,7 +3126,7 @@ pub impl Resolver { false); } - for module_.import_resolutions.each |&(ident, importresolution)| { + for module_.import_resolutions.each |ident, importresolution| { if importresolution.privacy != Public { debug!("(computing exports) not reexporting private `%s`", *self.session.str_of(*ident)); @@ -3934,7 +3934,7 @@ pub impl Resolver { for arm.pats.eachi() |i, p| { let map_i = self.binding_mode_map(*p); - for map_0.each |&(&key, &binding_0)| { + for map_0.each |&key, &binding_0| { match map_i.find(&key) { None => { self.session.span_err( @@ -3955,7 +3955,7 @@ pub impl Resolver { } } - for map_i.each |&(&key, &binding)| { + for map_i.each |&key, &binding| { if !map_0.contains_key(&key) { self.session.span_err( binding.span, @@ -5248,7 +5248,7 @@ pub impl Resolver { } debug!("Import resolutions:"); - for module_.import_resolutions.each |&(name, import_resolution)| { + for module_.import_resolutions.each |name, import_resolution| { let mut value_repr; match import_resolution.target_for_namespace(ValueNS) { None => { value_repr = ~""; } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 2eb7f8332ca92..0a116cdbdd169 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2848,7 +2848,7 @@ pub fn create_module_map(ccx: @CrateContext) -> ValueRef { lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage); } let mut elts: ~[ValueRef] = ~[]; - for ccx.module_data.each |&(key, &val)| { + for ccx.module_data.each |key, &val| { let elt = C_struct(~[p2i(ccx, C_cstr(ccx, @/*bad*/ copy *key)), p2i(ccx, val)]); elts.push(elt); @@ -3139,7 +3139,7 @@ pub fn trans_crate(sess: session::Session, } if ccx.sess.count_llvm_insns() { - for ccx.stats.llvm_insns.each |&(&k, &v)| { + for ccx.stats.llvm_insns.each |&k, &v| { io::println(fmt!("%-7u %s", v, k)); } } diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index 98d12bea6a429..e6354d4ab88f6 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -1223,7 +1223,7 @@ pub impl RegionVarBindings { // It would be nice to write this using map(): let mut edges = vec::with_capacity(num_edges); - for self.constraints.each |&(constraint, span)| { + for self.constraints.each |constraint, span| { edges.push(GraphEdge { next_edge: [uint::max_value, uint::max_value], constraint: *constraint, diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 94fcb85d1d84c..642a94b194582 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -177,7 +177,7 @@ Available lint options: padded(max_key, ~"name"), ~"default", ~"meaning")); io::println(fmt!(" %s %7.7s %s\n", padded(max_key, ~"----"), ~"-------", ~"-------")); - for lint_dict.each |&(k, v)| { + for lint_dict.each |k, v| { let k = str::replace(*k, ~"_", ~"-"); io::println(fmt!(" %s %7.7s %s", padded(max_key, k), diff --git a/src/libstd/json.rs b/src/libstd/json.rs index d733a60f34fff..90a745aaeb9b7 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -926,7 +926,7 @@ impl Eq for Json { &Object(ref d1) => { if d0.len() == d1.len() { let mut equal = true; - for d0.each |&(k, v0)| { + for d0.each |k, v0| { match d1.find(k) { Some(v1) if v0 == v1 => { }, _ => { equal = false; break } @@ -989,12 +989,12 @@ impl Ord for Json { let mut d1_flat = ~[]; // FIXME #4430: this is horribly inefficient... - for d0.each |&(k, v)| { + for d0.each |k, v| { d0_flat.push((@copy *k, @copy *v)); } d0_flat.qsort(); - for d1.each |&(k, v)| { + for d1.each |k, v| { d1_flat.push((@copy *k, @copy *v)); } d1_flat.qsort(); @@ -1125,7 +1125,7 @@ impl ToJson for ~[A] { impl ToJson for HashMap<~str, A> { fn to_json(&self) -> Json { let mut d = HashMap::new(); - for self.each |&(key, value)| { + for self.each |key, value| { d.insert(copy *key, value.to_json()); } Object(~d) diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index f7ffa7435cfa3..b8e0d9d9b2ac4 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -216,7 +216,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str { let mut out = ~""; let mut first = true; - for m.each |&(key, values)| { + for m.each |key, values| { let key = encode_plus(*key); for values.each |value| { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index e1ab59fb2b3ae..c2f0d9cb43f09 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -595,7 +595,7 @@ impl< fn encode(&self, e: &E) { do e.emit_map(self.len()) { let mut i = 0; - for self.each |&(key, val)| { + for self.each |key, val| { e.emit_map_elt_key(i, || key.encode(e)); e.emit_map_elt_val(i, || val.encode(e)); i += 1; @@ -659,7 +659,7 @@ impl< fn encode(&self, e: &E) { do e.emit_map(self.len()) { let mut i = 0; - for self.each |&(key, val)| { + for self.each |key, val| { e.emit_map_elt_key(i, || key.encode(e)); e.emit_map_elt_val(i, || val.encode(e)); i += 1; @@ -717,7 +717,7 @@ impl< fn encode(&self, e: &E) { do e.emit_map(self.len()) { let mut i = 0; - for self.each |&(key, val)| { + for self.each |key, val| { e.emit_map_elt_key(i, || key.encode(e)); e.emit_map_elt_val(i, || val.encode(e)); i += 1; diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index b6c5ec03068cd..811cd710a62cc 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -14,7 +14,7 @@ */ use core::container::{Container, Mutable, Map, Set}; -use core::iter::{BaseIter, ReverseIter}; +use core::iter::{BaseIter}; use core::option::{Some, None}; use core::prelude::*; @@ -22,32 +22,6 @@ pub struct SmallIntMap { priv v: ~[Option], } -impl<'self, V> BaseIter<(uint, &'self V)> for SmallIntMap { - /// Visit all key-value pairs in order - fn each(&self, it: &fn(&(uint, &'self V)) -> bool) { - for uint::range(0, self.v.len()) |i| { - match self.v[i] { - Some(ref elt) => if !it(&(i, elt)) { break }, - None => () - } - } - } - - fn size_hint(&self) -> Option { Some(self.len()) } -} - -impl<'self, V> ReverseIter<(uint, &'self V)> for SmallIntMap { - /// Visit all key-value pairs in reverse order - fn each_reverse(&self, it: &fn(&(uint, &'self V)) -> bool) { - for uint::range_rev(self.v.len(), 0) |i| { - match self.v[i - 1] { - Some(ref elt) => if !it(&(i - 1, elt)) { break }, - None => () - } - } - } -} - impl Container for SmallIntMap { /// Return the number of elements in the map fn len(&const self) -> uint { @@ -76,14 +50,24 @@ impl Map for SmallIntMap { self.find(key).is_some() } + /// Visit all key-value pairs in order + fn each(&self, it: &fn(&uint, &'self V) -> bool) { + for uint::range(0, self.v.len()) |i| { + match self.v[i] { + Some(ref elt) => if !it(&i, elt) { break }, + None => () + } + } + } + /// Visit all keys in order fn each_key(&self, blk: &fn(key: &uint) -> bool) { - self.each(|&(k, _)| blk(&k)) + self.each(|k, _| blk(k)) } /// Visit all values in order fn each_value(&self, blk: &fn(value: &V) -> bool) { - self.each(|&(_, v)| blk(v)) + self.each(|_, v| blk(v)) } /// Iterate over the map and mutate the contained values @@ -149,6 +133,16 @@ pub impl SmallIntMap { /// Create an empty SmallIntMap fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } + /// Visit all key-value pairs in reverse order + fn each_reverse(&self, it: &fn(uint, &'self V) -> bool) { + for uint::range_rev(self.v.len(), 0) |i| { + match self.v[i - 1] { + Some(ref elt) => if !it(i - 1, elt) { break }, + None => () + } + } + } + fn get(&self, key: &uint) -> &'self V { self.find(key).expect("key not present") } diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index d0868da4408d4..041ea855cb39d 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -82,24 +82,6 @@ impl Ord for TreeMap { fn gt(&self, other: &TreeMap) -> bool { lt(other, self) } } -impl<'self, K: TotalOrd, V> BaseIter<(&'self K, &'self V)> for TreeMap { - /// Visit all key-value pairs in order - fn each(&self, f: &fn(&(&'self K, &'self V)) -> bool) { - each(&self.root, f) - } - fn size_hint(&self) -> Option { Some(self.len()) } -} - -impl<'self, K: TotalOrd, V> - ReverseIter<(&'self K, &'self V)> - for TreeMap -{ - /// Visit all key-value pairs in reverse order - fn each_reverse(&self, f: &fn(&(&'self K, &'self V)) -> bool) { - each_reverse(&self.root, f); - } -} - impl Container for TreeMap { /// Return the number of elements in the map fn len(&const self) -> uint { self.length } @@ -122,12 +104,19 @@ impl Map for TreeMap { self.find(key).is_some() } + /// Visit all key-value pairs in order + fn each(&self, f: &fn(&'self K, &'self V) -> bool) { + each(&self.root, f) + } + /// Visit all keys in order - fn each_key(&self, f: &fn(&K) -> bool) { self.each(|&(k, _)| f(k)) } + fn each_key(&self, f: &fn(&K) -> bool) { + self.each(|k, _| f(k)) + } /// Visit all values in order fn each_value(&self, f: &fn(&V) -> bool) { - self.each(|&(_, v)| f(v)) + self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values @@ -180,14 +169,19 @@ pub impl TreeMap { /// Create an empty TreeMap fn new() -> TreeMap { TreeMap{root: None, length: 0} } + /// Visit all key-value pairs in reverse order + fn each_reverse(&'self self, f: &fn(&'self K, &'self V) -> bool) { + each_reverse(&self.root, f); + } + /// Visit all keys in reverse order fn each_key_reverse(&self, f: &fn(&K) -> bool) { - self.each_reverse(|&(k, _)| f(k)) + self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order fn each_value_reverse(&self, f: &fn(&V) -> bool) { - self.each_reverse(|&(_, v)| f(v)) + self.each_reverse(|_, v| f(v)) } /// Get a lazy iterator over the key-value pairs in the map. @@ -538,18 +532,18 @@ pub impl TreeNode { } fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode>, - f: &fn(&(&'r K, &'r V)) -> bool) { + f: &fn(&'r K, &'r V) -> bool) { for node.each |x| { each(&x.left, f); - if f(&(&x.key, &x.value)) { each(&x.right, f) } + if f(&x.key, &x.value) { each(&x.right, f) } } } fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode>, - f: &fn(&(&'r K, &'r V)) -> bool) { + f: &fn(&'r K, &'r V) -> bool) { for node.each |x| { each_reverse(&x.right, f); - if f(&(&x.key, &x.value)) { each_reverse(&x.left, f) } + if f(&x.key, &x.value) { each_reverse(&x.left, f) } } } @@ -796,7 +790,7 @@ mod test_treemap { let &(k, v) = x; assert!(map.find(&k).unwrap() == &v) } - for map.each |&(map_k, map_v)| { + for map.each |map_k, map_v| { let mut found = false; for ctrl.each |x| { let &(ctrl_k, ctrl_v) = x; @@ -912,7 +906,7 @@ mod test_treemap { assert!(m.insert(1, 2)); let mut n = 0; - for m.each |&(k, v)| { + for m.each |k, v| { assert!(*k == n); assert!(*v == n * 2); n += 1; @@ -930,7 +924,7 @@ mod test_treemap { assert!(m.insert(1, 2)); let mut n = 4; - for m.each_reverse |&(k, v)| { + for m.each_reverse |k, v| { assert!(*k == n); assert!(*v == n * 2); n -= 1; diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index 3e494d0236e97..c4b450810aa86 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -145,7 +145,7 @@ impl WorkMap { impl Encodable for WorkMap { fn encode(&self, s: &S) { let mut d = ~[]; - for self.each |&(k, v)| { + for self.each |k, v| { d.push((copy *k, copy *v)) } sort::tim_sort(d); @@ -319,7 +319,7 @@ impl TPrep for Prep { } fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool { - for map.each |&(k, v)| { + for map.each |k, v| { if ! self.is_fresh(cat, k.kind, k.name, *v) { return false; } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 6ba1caa0d1e1a..c8b13a6e27fa3 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -48,7 +48,7 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { let mut pairs = ~[]; // map -> [(k,%)] - for mm.each |&(&key, &val)| { + for mm.each |&key, &val| { pairs.push((key, pct(val, total))); } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index 30ca5ea3881c9..cfde61d74b21b 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -49,18 +49,6 @@ pub impl cat { } } -impl<'self,T> BaseIter<(int, &'self T)> for cat { - fn each(&self, f: &fn(&(int, &'self T)) -> bool) { - let mut n = int::abs(self.meows); - while n > 0 { - if !f(&(n, &self.name)) { break; } - n -= 1; - } - } - - fn size_hint(&self) -> Option { Some(self.len()) } -} - impl Container for cat { fn len(&const self) -> uint { self.meows as uint } fn is_empty(&const self) -> bool { self.meows == 0 } @@ -71,17 +59,25 @@ impl Mutable for cat { } impl Map for cat { + fn each(&self, f: &fn(&int, &T) -> bool) { + let mut n = int::abs(self.meows); + while n > 0 { + if !f(&n, &self.name) { break; } + n -= 1; + } + } + fn contains_key(&self, k: &int) -> bool { *k <= self.meows } fn each_key(&self, f: &fn(v: &int) -> bool) { - for self.each |&(k, _)| { if !f(&k) { break; } loop;}; + for self.each |k, _| { if !f(k) { break; } loop;}; } fn each_value(&self, f: &fn(v: &T) -> bool) { - for self.each |&(_, v)| { if !f(v) { break; } loop;}; + for self.each |_, v| { if !f(v) { break; } loop;}; } - fn mutate_values(&mut self, f: &fn(&int, &mut T) -> bool) { + fn mutate_values(&mut self, _f: &fn(&int, &mut T) -> bool) { fail!(~"nope") } @@ -98,7 +94,7 @@ impl Map for cat { } } - fn find_mut(&mut self, k: &int) -> Option<&'self mut T> { fail!() } + fn find_mut(&mut self, _k: &int) -> Option<&'self mut T> { fail!() } fn remove(&mut self, k: &int) -> bool { if self.find(k).is_some() { From 3322595e896e95c3e19ca33c854ad529f2ef3c19 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 1 Apr 2013 22:32:37 -0700 Subject: [PATCH 107/403] Reason about nested free variables that appear in a function signature. In a nutshell, the idea is to (1) report an error if, for a region pointer `'a T`, the lifetime `'a` is longer than any lifetimes that appear in `T` (in other words, if a borrowed pointer outlives any portion of its contents) and then (2) use this to assume that in a function like `fn(self: &'a &'b T)`, the relationship `'a <= 'b` holds. This is needed for #5656. Fixes #5728. --- src/libcore/cmp.rs | 21 ++ src/libcore/str.rs | 6 +- src/libcore/tuple.rs | 1 - src/librustc/metadata/tydecode.rs | 3 +- src/librustc/metadata/tyencode.rs | 6 +- src/librustc/middle/astencode.rs | 5 +- src/librustc/middle/borrowck/check_loans.rs | 10 +- src/librustc/middle/borrowck/gather_loans.rs | 7 +- src/librustc/middle/borrowck/loan.rs | 4 +- src/librustc/middle/borrowck/mod.rs | 3 +- src/librustc/middle/borrowck/preserve.rs | 18 +- src/librustc/middle/check_match.rs | 7 +- src/librustc/middle/kind.rs | 100 ++++-- src/librustc/middle/region.rs | 308 +++++++++++++----- src/librustc/middle/ty.rs | 140 ++++---- src/librustc/middle/typeck/check/mod.rs | 12 +- src/librustc/middle/typeck/check/regionck.rs | 305 +++++++++++++---- .../middle/typeck/check/regionmanip.rs | 119 ++++++- src/librustc/middle/typeck/collect.rs | 3 +- .../middle/typeck/infer/region_inference.rs | 165 +++++++--- src/librustc/middle/typeck/infer/test.rs | 4 +- src/librustc/util/ppaux.rs | 39 ++- .../kindck-owned-trait-contains.rs | 3 +- .../regions-escape-via-trait-or-not.rs | 4 +- .../regions-free-region-ordering-callee.rs | 37 +++ .../regions-free-region-ordering-caller.rs | 40 +++ src/test/compile-fail/regions-trait-2.rs | 8 +- 27 files changed, 1029 insertions(+), 349 deletions(-) create mode 100644 src/test/compile-fail/regions-free-region-ordering-callee.rs create mode 100644 src/test/compile-fail/regions-free-region-ordering-caller.rs diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index f96575aaf414f..bd4832b6faf6c 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -116,6 +116,19 @@ totalord_impl!(i64) totalord_impl!(int) totalord_impl!(uint) +pub fn cmp2( + a1: &A, b1: &B, + a2: &A, b2: &B) -> Ordering +{ + //! Compares (a1, b1) against (a2, b2), where the a values are more significant. + + match a1.cmp(a2) { + Less => Less, + Greater => Greater, + Equal => b1.cmp(b2) + } +} + /** * Trait for values that can be compared for a sort-order. * @@ -193,6 +206,14 @@ mod test { assert_eq!(12.cmp(-5), Greater); } + #[test] + fn test_cmp2() { + assert_eq!(cmp2(1, 2, 3, 4), Less); + assert_eq!(cmp2(3, 2, 3, 4), Less); + assert_eq!(cmp2(5, 2, 3, 4), Greater); + assert_eq!(cmp2(5, 5, 5, 4), Greater); + } + #[test] fn test_int_totaleq() { assert!(5.equals(&5)); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index f1605309fb488..8d15d6afbda10 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -301,7 +301,11 @@ pub fn slice_shift_char<'a>(s: &'a str) -> (char, &'a str) { /// Prepend a char to a string pub fn unshift_char(s: &mut ~str, ch: char) { - *s = from_char(ch) + *s; + // This could be more efficient. + let mut new_str = ~""; + new_str.push_char(ch); + new_str.push_str(*s); + *s = new_str; } /** diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 35b8496f6c57e..8234129e25474 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -161,7 +161,6 @@ impl Ord for (A,) { fn gt(&self, other: &(A,)) -> bool { other.lt(&(*self)) } } - #[cfg(notest)] impl Eq for (A, B) { #[inline(always)] diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 867fe0cd816cc..c1420822d06e5 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -239,7 +239,8 @@ fn parse_region(st: @mut PState) -> ty::Region { assert!(next(st) == '|'); let br = parse_bound_region(st); assert!(next(st) == ']'); - ty::re_free(id, br) + ty::re_free(ty::FreeRegion {scope_id: id, + bound_region: br}) } 's' => { let id = parse_int(st); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 238f34b8c01b9..2e1dd8b6dad86 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -146,12 +146,12 @@ fn enc_region(w: @io::Writer, cx: @ctxt, r: ty::Region) { w.write_char('b'); enc_bound_region(w, cx, br); } - ty::re_free(id, br) => { + ty::re_free(ref fr) => { w.write_char('f'); w.write_char('['); - w.write_int(id); + w.write_int(fr.scope_id); w.write_char('|'); - enc_bound_region(w, cx, br); + enc_bound_region(w, cx, fr.bound_region); w.write_char(']'); } ty::re_scope(nid) => { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 68989b3142566..b25b975830bd5 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -475,9 +475,12 @@ impl tr for ty::Region { fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region { match *self { ty::re_bound(br) => ty::re_bound(br.tr(xcx)), - ty::re_free(id, br) => ty::re_free(xcx.tr_id(id), br.tr(xcx)), ty::re_scope(id) => ty::re_scope(xcx.tr_id(id)), ty::re_static | ty::re_infer(*) => *self, + ty::re_free(ref fr) => { + ty::re_free(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id), + bound_region: fr.bound_region.tr(xcx)}) + } } } } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 160356567421d..721bb99626249 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -128,9 +128,9 @@ pub impl CheckLoanCtxt { Some(e) => return Some(pc_cmt(*e)) } - match self.tcx().region_map.find(&scope_id) { + match self.tcx().region_maps.opt_encl_scope(scope_id) { None => return default_purity, - Some(&next_scope_id) => scope_id = next_scope_id + Some(next_scope_id) => scope_id = next_scope_id } } } @@ -146,9 +146,9 @@ pub impl CheckLoanCtxt { } } - match self.tcx().region_map.find(&scope_id) { + match self.tcx().region_maps.opt_encl_scope(scope_id) { None => return, - Some(&next_scope_id) => scope_id = next_scope_id, + Some(next_scope_id) => scope_id = next_scope_id, } } } @@ -270,7 +270,7 @@ pub impl CheckLoanCtxt { debug!("new_loans has length %?", new_loans.len()); - let par_scope_id = *self.tcx().region_map.get(&scope_id); + let par_scope_id = self.tcx().region_maps.encl_scope(scope_id); for self.walk_loans(par_scope_id) |old_loan| { debug!("old_loan=%?", self.bccx.loan_to_repr(old_loan)); diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 233b1e191dc24..4e61b5738912f 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -242,7 +242,7 @@ fn req_loans_in_expr(ex: @ast::expr, // (if used like `a.b(...)`), the call where it's an argument // (if used like `x(a.b)`), or the block (if used like `let x // = a.b`). - let scope_r = ty::re_scope(*self.tcx().region_map.get(&ex.id)); + let scope_r = self.tcx().region_maps.encl_region(ex.id); let rcvr_cmt = self.bccx.cat_expr(rcvr); self.guarantee_valid(rcvr_cmt, m_imm, scope_r); visit::visit_expr(ex, self, vt); @@ -524,7 +524,10 @@ pub impl GatherLoanCtxt { // immutable structures, this is just the converse I suppose) let scope_id = match scope_r { - ty::re_scope(scope_id) | ty::re_free(scope_id, _) => scope_id, + ty::re_scope(scope_id) | + ty::re_free(ty::FreeRegion {scope_id, _}) => { + scope_id + } _ => { self.bccx.tcx.sess.span_bug( cmt.span, diff --git a/src/librustc/middle/borrowck/loan.rs b/src/librustc/middle/borrowck/loan.rs index 146e0c712a33d..a38cd015654b5 100644 --- a/src/librustc/middle/borrowck/loan.rs +++ b/src/librustc/middle/borrowck/loan.rs @@ -130,8 +130,8 @@ pub impl LoanContext { } cat_local(local_id) | cat_arg(local_id) | cat_self(local_id) => { // FIXME(#4903) - let local_scope_id = *self.bccx.tcx.region_map.get(&local_id); - self.issue_loan(cmt, ty::re_scope(local_scope_id), loan_kind, + let local_region = self.bccx.tcx.region_maps.encl_region(local_id); + self.issue_loan(cmt, local_region, loan_kind, owns_lent_data) } cat_stack_upvar(cmt) => { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 5e7903f66102f..01fea2a960d4b 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -227,7 +227,6 @@ Borrowck results in two maps. use core::prelude::*; use middle::mem_categorization::*; -use middle::region; use middle::ty; use middle::typeck; use middle::moves; @@ -458,7 +457,7 @@ pub fn root_map() -> root_map { pub impl BorrowckCtxt { fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region) -> bool { - region::is_subregion_of(self.tcx.region_map, r_sub, r_sup) + self.tcx.region_maps.is_subregion_of(r_sub, r_sup) } fn cat_expr(&self, expr: @ast::expr) -> cmt { diff --git a/src/librustc/middle/borrowck/preserve.rs b/src/librustc/middle/borrowck/preserve.rs index 3056edea233fb..40a59e2f89f26 100644 --- a/src/librustc/middle/borrowck/preserve.rs +++ b/src/librustc/middle/borrowck/preserve.rs @@ -108,7 +108,7 @@ pub impl<'self> PreserveCtxt<'self> { // Maybe if we pass in the parent instead here, // we can prevent the "scope not found" error debug!("scope_region thing: %? ", cmt.id); - ty::re_scope(*self.tcx().region_map.get(&cmt.id)) + self.tcx().region_maps.encl_region(cmt.id) }; self.compare_scope(cmt, scope_region) @@ -128,27 +128,27 @@ pub impl<'self> PreserveCtxt<'self> { cmt.span, ~"preserve() called with local and !root_managed_data"); } - let local_scope_id = *self.tcx().region_map.get(&local_id); - self.compare_scope(cmt, ty::re_scope(local_scope_id)) + let local_region = self.tcx().region_maps.encl_region(local_id); + self.compare_scope(cmt, local_region) } cat_binding(local_id) => { // Bindings are these kind of weird implicit pointers (cc // #2329). We require (in gather_loans) that they be // rooted in an immutable location. - let local_scope_id = *self.tcx().region_map.get(&local_id); - self.compare_scope(cmt, ty::re_scope(local_scope_id)) + let local_region = self.tcx().region_maps.encl_region(local_id); + self.compare_scope(cmt, local_region) } cat_arg(local_id) => { // This can happen as not all args are lendable (e.g., && // modes). In that case, the caller guarantees stability // for at least the scope of the fn. This is basically a // deref of a region ptr. - let local_scope_id = *self.tcx().region_map.get(&local_id); - self.compare_scope(cmt, ty::re_scope(local_scope_id)) + let local_region = self.tcx().region_maps.encl_region(local_id); + self.compare_scope(cmt, local_region) } cat_self(local_id) => { - let local_scope_id = *self.tcx().region_map.get(&local_id); - self.compare_scope(cmt, ty::re_scope(local_scope_id)) + let local_region = self.tcx().region_maps.encl_region(local_id); + self.compare_scope(cmt, local_region) } cat_comp(cmt_base, comp_field(*)) | cat_comp(cmt_base, comp_index(*)) | diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index fdea403cc2a00..6898dcca45dd8 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -596,8 +596,11 @@ pub fn specialize(cx: @MatchCheckCtxt, class_id); } _ => { - cx.tcx.sess.span_bug(pat_span, - ~"struct pattern didn't resolve to a struct"); + cx.tcx.sess.span_bug( + pat_span, + fmt!("struct pattern resolved to %s, \ + not a struct", + ty_to_str(cx.tcx, left_ty))); } } let args = vec::map(class_fields, |class_field| { diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index e82b6ba5e7710..1f8401c0d533e 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -478,13 +478,13 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { } } -/// This is rather subtle. When we are casting a value to a -/// instantiated trait like `a as trait<'r>`, regionck already ensures -/// that any borrowed pointers that appear in the type of `a` are -/// bounded by `&r`. However, it is possible that there are *type -/// parameters* in the type of `a`, and those *type parameters* may -/// have borrowed pointers within them. We have to guarantee that the -/// regions which appear in those type parameters are not obscured. +/// This is rather subtle. When we are casting a value to a instantiated +/// trait like `a as trait<'r>`, regionck already ensures that any borrowed +/// pointers that appear in the type of `a` are bounded by `'r` (ed.: modulo +/// FIXME(#5723)). However, it is possible that there are *type parameters* +/// in the type of `a`, and those *type parameters* may have borrowed pointers +/// within them. We have to guarantee that the regions which appear in those +/// type parameters are not obscured. /// /// Therefore, we ensure that one of three conditions holds: /// @@ -501,6 +501,8 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { /// /// (3) The type parameter is owned (and therefore does not contain /// borrowed ptrs). +/// +/// FIXME(#5723)---This code should probably move into regionck. pub fn check_cast_for_escaping_regions( cx: Context, source: @expr, @@ -509,40 +511,78 @@ pub fn check_cast_for_escaping_regions( // Determine what type we are casting to; if it is not an trait, then no // worries. let target_ty = ty::expr_ty(cx.tcx, target); - let target_substs = match ty::get(target_ty).sty { - ty::ty_trait(_, ref substs, _) => {(/*bad*/copy *substs)} - _ => { return; /* not a cast to a trait */ } - }; + match ty::get(target_ty).sty { + ty::ty_trait(*) => {} + _ => { return; } + } + + // Collect up the regions that appear in the target type. We want to + // ensure that these lifetimes are shorter than all lifetimes that are in + // the source type. See test `src/test/compile-fail/regions-trait-2.rs` + let mut target_regions = ~[]; + ty::walk_regions_and_ty( + cx.tcx, + target_ty, + |r| { + if !r.is_bound() { + target_regions.push(r); + } + }, + |_| true); // Check, based on the region associated with the trait, whether it can // possibly escape the enclosing fn item (note that all type parameters - // must have been declared on the enclosing fn item): - match target_substs.self_r { - Some(ty::re_scope(*)) => { return; /* case (1) */ } - None | Some(ty::re_static) | Some(ty::re_free(*)) => {} - Some(ty::re_bound(*)) | Some(ty::re_infer(*)) => { - cx.tcx.sess.span_bug( - source.span, - fmt!("bad region found in kind: %?", target_substs.self_r)); - } + // must have been declared on the enclosing fn item). + if target_regions.any(|r| is_re_scope(*r)) { + return; /* case (1) */ } // Assuming the trait instance can escape, then ensure that each parameter - // either appears in the trait type or is owned: + // either appears in the trait type or is owned. let target_params = ty::param_tys_in_type(target_ty); let source_ty = ty::expr_ty(cx.tcx, source); - do ty::walk_ty(source_ty) |ty| { - match ty::get(ty).sty { - ty::ty_param(source_param) => { - if target_params.contains(&source_param) { - /* case (2) */ - } else { - check_durable(cx.tcx, ty, source.span); /* case (3) */ + ty::walk_regions_and_ty( + cx.tcx, + source_ty, + + |_r| { + // FIXME(#5723) --- turn this check on once &Objects are usable + // + // if !target_regions.any(|t_r| is_subregion_of(cx, *t_r, r)) { + // cx.tcx.sess.span_err( + // source.span, + // fmt!("source contains borrowed pointer with lifetime \ + // not found in the target type `%s`", + // ty_to_str(cx.tcx, target_ty))); + // note_and_explain_region( + // cx.tcx, "source data is only valid for ", r, ""); + // } + }, + + |ty| { + match ty::get(ty).sty { + ty::ty_param(source_param) => { + if target_params.contains(&source_param) { + /* case (2) */ + } else { + check_durable(cx.tcx, ty, source.span); /* case (3) */ + } + } + _ => {} } - } - _ => {} + true + }); + + fn is_re_scope(+r: ty::Region) -> bool { + match r { + ty::re_scope(*) => true, + _ => false } } + + fn is_subregion_of(cx: Context, r_sub: ty::Region, r_sup: ty::Region) -> bool { + cx.tcx.region_maps.is_subregion_of(r_sub, r_sup) + } } /// Ensures that values placed into a ~Trait are copyable and sendable. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 50c193ab3b095..7913009707868 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -11,7 +11,7 @@ /*! This file actually contains two passes related to regions. The first -pass builds up the `region_map`, which describes the parent links in +pass builds up the `scope_map`, which describes the parent links in the region hierarchy. The second pass infers which types must be region parameterized. @@ -23,7 +23,7 @@ use driver::session::Session; use metadata::csearch; use middle::resolve; use middle::ty::{region_variance, rv_covariant, rv_invariant}; -use middle::ty::{rv_contravariant}; +use middle::ty::{rv_contravariant, FreeRegion}; use middle::ty; use core::hashmap::{HashMap, HashSet}; @@ -37,23 +37,31 @@ use syntax::{ast, visit}; pub type parent = Option; /** -Encodes the bounding lifetime for a given AST node: - -- Expressions are mapped to the expression or block encoding the maximum - (static) lifetime of a value produced by that expression. This is - generally the innermost call, statement, match, or block. - -- Variables and bindings are mapped to the block in which they are declared. - +The region maps encode information about region relationships. + +- `scope_map` maps from: + - an expression to the expression or block encoding the maximum + (static) lifetime of a value produced by that expression. This is + generally the innermost call, statement, match, or block. + - a variable or binding id to the block in which that variable is declared. +- `free_region_map` maps from: + - a free region `a` to a list of free regions `bs` such that + `a <= b for all b in bs` + - the free region map is populated during type check as we check + each function. See the function `relate_free_regions` for + more information. */ -pub type region_map = @mut HashMap; +pub struct RegionMaps { + priv scope_map: HashMap, + priv free_region_map: HashMap, +} pub struct ctxt { sess: Session, def_map: resolve::DefMap, // Generated maps: - region_map: region_map, + region_maps: @mut RegionMaps, // Generally speaking, expressions are parented to their innermost // enclosing block. But some kinds of expressions serve as @@ -98,94 +106,215 @@ pub struct ctxt { parent: parent, } -/// Returns true if `subscope` is equal to or is lexically nested inside -/// `superscope` and false otherwise. -pub fn scope_contains(region_map: region_map, superscope: ast::node_id, - subscope: ast::node_id) -> bool { - let mut subscope = subscope; - while superscope != subscope { - match region_map.find(&subscope) { - None => return false, - Some(&scope) => subscope = scope +pub impl RegionMaps { + fn relate_free_regions(&mut self, + sub: FreeRegion, + sup: FreeRegion) + { + match self.free_region_map.find_mut(&sub) { + Some(sups) => { + if !sups.contains(&sup) { + sups.push(sup); + } + return; + } + None => {} } + + debug!("relate_free_regions(sub=%?, sup=%?)", sub, sup); + + self.free_region_map.insert(sub, ~[sup]); } - return true; -} -/// Determines whether one region is a subregion of another. This is -/// intended to run *after inference* and sadly the logic is somewhat -/// duplicated with the code in infer.rs. -pub fn is_subregion_of(region_map: region_map, - sub_region: ty::Region, - super_region: ty::Region) -> bool { - sub_region == super_region || - match (sub_region, super_region) { - (_, ty::re_static) => { - true - } + fn record_parent(&mut self, + sub: ast::node_id, + sup: ast::node_id) + { + debug!("record_parent(sub=%?, sup=%?)", sub, sup); - (ty::re_scope(sub_scope), ty::re_scope(super_scope)) | - (ty::re_scope(sub_scope), ty::re_free(super_scope, _)) => { - scope_contains(region_map, super_scope, sub_scope) - } + self.scope_map.insert(sub, sup); + } - _ => { - false + fn opt_encl_scope(&self, + id: ast::node_id) -> Option + { + //! Returns the narrowest scope that encloses `id`, if any. + + self.scope_map.find(&id).map(|&x| *x) + } + + fn encl_scope(&self, + id: ast::node_id) -> ast::node_id + { + //! Returns the narrowest scope that encloses `id`, if any. + + match self.scope_map.find(&id) { + Some(&r) => r, + None => { fail!(fmt!("No enclosing scope for id %?", id)); } + } + } + + fn encl_region(&self, + id: ast::node_id) -> ty::Region + { + //! Returns the narrowest scope region that encloses `id`, if any. + + ty::re_scope(self.encl_scope(id)) + } + + fn is_sub_scope(&self, + sub_scope: ast::node_id, + superscope: ast::node_id) -> bool + { + /*! + * Returns true if `sub_scope` is equal to or is lexically + * nested inside `superscope` and false otherwise. + */ + + let mut sub_scope = sub_scope; + while superscope != sub_scope { + match self.scope_map.find(&sub_scope) { + None => return false, + Some(&scope) => sub_scope = scope } } -} + return true; + } -/// Finds the nearest common ancestor (if any) of two scopes. That -/// is, finds the smallest scope which is greater than or equal to -/// both `scope_a` and `scope_b`. -pub fn nearest_common_ancestor(region_map: region_map, - scope_a: ast::node_id, - scope_b: ast::node_id) - -> Option { + fn sub_free_region(&self, + sub: FreeRegion, + sup: FreeRegion) -> bool + { + /*! + * Determines whether two free regions have a subregion relationship + * by walking the graph encoded in `free_region_map`. Note that + * it is possible that `sub != sup` and `sub <= sup` and `sup <= sub` + * (that is, the user can give two different names to the same lifetime). + */ + + if sub == sup { + return true; + } - fn ancestors_of(region_map: region_map, scope: ast::node_id) - -> ~[ast::node_id] { - let mut result = ~[scope]; - let mut scope = scope; - loop { - match region_map.find(&scope) { - None => return result, - Some(&superscope) => { - result.push(superscope); - scope = superscope; + // Do a little breadth-first-search here. The `queue` list + // doubles as a way to detect if we've seen a particular FR + // before. Note that we expect this graph to be an *extremely + // shallow* tree. + let mut queue = ~[sub]; + let mut i = 0; + while i < queue.len() { + match self.free_region_map.find(&queue[i]) { + Some(parents) => { + for parents.each |parent| { + if *parent == sup { + return true; + } + + if !queue.contains(parent) { + queue.push(*parent); + } + } } + None => {} } + i += 1; } + return false; } - if scope_a == scope_b { return Some(scope_a); } + fn is_subregion_of(&self, + sub_region: ty::Region, + super_region: ty::Region) -> bool + { + /*! + * Determines whether one region is a subregion of another. This is + * intended to run *after inference* and sadly the logic is somewhat + * duplicated with the code in infer.rs. + */ + + debug!("is_subregion_of(sub_region=%?, super_region=%?)", + sub_region, super_region); + + sub_region == super_region || { + match (sub_region, super_region) { + (_, ty::re_static) => { + true + } - let a_ancestors = ancestors_of(region_map, scope_a); - let b_ancestors = ancestors_of(region_map, scope_b); - let mut a_index = vec::len(a_ancestors) - 1u; - let mut b_index = vec::len(b_ancestors) - 1u; + (ty::re_scope(sub_scope), ty::re_scope(super_scope)) => { + self.is_sub_scope(sub_scope, super_scope) + } - // Here, ~[ab]_ancestors is a vector going from narrow to broad. - // The end of each vector will be the item where the scope is - // defined; if there are any common ancestors, then the tails of - // the vector will be the same. So basically we want to walk - // backwards from the tail of each vector and find the first point - // where they diverge. If one vector is a suffix of the other, - // then the corresponding scope is a superscope of the other. + (ty::re_scope(sub_scope), ty::re_free(ref fr)) => { + self.is_sub_scope(sub_scope, fr.scope_id) + } - if a_ancestors[a_index] != b_ancestors[b_index] { - return None; + (ty::re_free(sub_fr), ty::re_free(super_fr)) => { + self.sub_free_region(sub_fr, super_fr) + } + + _ => { + false + } + } + } } - loop { - // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index] - // for all indices between a_index and the end of the array - if a_index == 0u { return Some(scope_a); } - if b_index == 0u { return Some(scope_b); } - a_index -= 1u; - b_index -= 1u; + fn nearest_common_ancestor(&self, + scope_a: ast::node_id, + scope_b: ast::node_id) -> Option + { + /*! + * Finds the nearest common ancestor (if any) of two scopes. That + * is, finds the smallest scope which is greater than or equal to + * both `scope_a` and `scope_b`. + */ + + if scope_a == scope_b { return Some(scope_a); } + + let a_ancestors = ancestors_of(self, scope_a); + let b_ancestors = ancestors_of(self, scope_b); + let mut a_index = vec::len(a_ancestors) - 1u; + let mut b_index = vec::len(b_ancestors) - 1u; + + // Here, ~[ab]_ancestors is a vector going from narrow to broad. + // The end of each vector will be the item where the scope is + // defined; if there are any common ancestors, then the tails of + // the vector will be the same. So basically we want to walk + // backwards from the tail of each vector and find the first point + // where they diverge. If one vector is a suffix of the other, + // then the corresponding scope is a superscope of the other. + if a_ancestors[a_index] != b_ancestors[b_index] { - return Some(a_ancestors[a_index + 1u]); + return None; + } + + loop { + // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index] + // for all indices between a_index and the end of the array + if a_index == 0u { return Some(scope_a); } + if b_index == 0u { return Some(scope_b); } + a_index -= 1u; + b_index -= 1u; + if a_ancestors[a_index] != b_ancestors[b_index] { + return Some(a_ancestors[a_index + 1u]); + } + } + + fn ancestors_of(self: &RegionMaps, scope: ast::node_id) + -> ~[ast::node_id] + { + let mut result = ~[scope]; + let mut scope = scope; + loop { + match self.scope_map.find(&scope) { + None => return result, + Some(&superscope) => { + result.push(superscope); + scope = superscope; + } + } + } } } } @@ -205,8 +334,7 @@ pub fn parent_id(cx: ctxt, span: span) -> ast::node_id { /// Records the current parent (if any) as the parent of `child_id`. pub fn record_parent(cx: ctxt, child_id: ast::node_id) { for cx.parent.each |parent_id| { - debug!("parent of node %d is node %d", child_id, *parent_id); - cx.region_map.insert(child_id, *parent_id); + cx.region_maps.record_parent(child_id, *parent_id); } } @@ -328,7 +456,7 @@ pub fn resolve_fn(fk: &visit::fn_kind, // Record the ID of `self`. match *fk { visit::fk_method(_, _, method) => { - cx.region_map.insert(method.self_id, body.node.id); + cx.region_maps.record_parent(method.self_id, body.node.id); } _ => {} } @@ -338,7 +466,7 @@ pub fn resolve_fn(fk: &visit::fn_kind, body.node.id, cx.parent, fn_cx.parent); for decl.inputs.each |input| { - cx.region_map.insert(input.id, body.node.id); + cx.region_maps.record_parent(input.id, body.node.id); } visit::visit_fn(fk, decl, body, sp, id, fn_cx, visitor); @@ -346,11 +474,15 @@ pub fn resolve_fn(fk: &visit::fn_kind, pub fn resolve_crate(sess: Session, def_map: resolve::DefMap, - crate: @ast::crate) - -> region_map { + crate: @ast::crate) -> @mut RegionMaps +{ + let region_maps = @mut RegionMaps { + scope_map: HashMap::new(), + free_region_map: HashMap::new() + }; let cx: ctxt = ctxt {sess: sess, def_map: def_map, - region_map: @mut HashMap::new(), + region_maps: region_maps, root_exprs: @mut HashSet::new(), parent: None}; let visitor = visit::mk_vt(@visit::Visitor { @@ -365,7 +497,7 @@ pub fn resolve_crate(sess: Session, .. *visit::default_visitor() }); visit::visit_crate(*crate, cx, visitor); - return cx.region_map; + return region_maps; } // ___________________________________________________________________________ diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 742153124346a..3921764e6afa8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -240,7 +240,7 @@ struct ctxt_ { sess: session::Session, def_map: resolve::DefMap, - region_map: middle::region::region_map, + region_maps: @mut middle::region::RegionMaps, region_paramd_items: middle::region::region_paramd_items, // Stores the types for various nodes in the AST. Note that this table @@ -410,7 +410,7 @@ pub struct param_ty { /// Representation of regions: #[auto_encode] #[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum Region { /// Bound regions are found (primarily) in function types. They indicate /// region parameters that have yet to be replaced with actual regions @@ -426,7 +426,7 @@ pub enum Region { /// When checking a function body, the types of all arguments and so forth /// that refer to bound region parameters are modified to refer to free /// region parameters. - re_free(node_id, bound_region), + re_free(FreeRegion), /// A concrete region naming some expression within the current function. re_scope(node_id), @@ -438,9 +438,26 @@ pub enum Region { re_infer(InferRegion) } +pub impl Region { + fn is_bound(&self) -> bool { + match self { + &re_bound(*) => true, + _ => false + } + } +} + #[auto_encode] #[auto_decode] -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] +pub struct FreeRegion { + scope_id: node_id, + bound_region: bound_region +} + +#[auto_encode] +#[auto_decode] +#[deriving(Eq, IterBytes)] pub enum bound_region { /// The self region for structs, impls (&T in a type defn or &'self T) br_self, @@ -810,7 +827,7 @@ pub fn mk_ctxt(s: session::Session, dm: resolve::DefMap, amap: ast_map::map, freevars: freevars::freevar_map, - region_map: middle::region::region_map, + region_maps: @mut middle::region::RegionMaps, region_paramd_items: middle::region::region_paramd_items, +lang_items: middle::lang_items::LanguageItems, crate: @ast::crate) @@ -837,7 +854,7 @@ pub fn mk_ctxt(s: session::Session, cstore: s.cstore, sess: s, def_map: dm, - region_map: region_map, + region_maps: region_maps, region_paramd_items: region_paramd_items, node_types: @mut SmallIntMap::new(), node_type_substs: @mut HashMap::new(), @@ -1176,15 +1193,6 @@ pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { } } -// Returns the narrowest lifetime enclosing the evaluation of the expression -// with id `id`. -pub fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region { - match cx.region_map.find(&id) { - Some(&encl_scope) => ty::re_scope(encl_scope), - None => ty::re_static - } -} - pub fn walk_ty(ty: t, f: &fn(t)) { maybe_walk_ty(ty, |t| { f(t); true }); } @@ -1308,8 +1316,8 @@ pub fn walk_regions_and_ty( fold_regions_and_ty( cx, ty, |r| { walkr(r); r }, - |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t }, - |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t }); + |t| { walk_regions_and_ty(cx, t, walkr, walkt); t }, + |t| { walk_regions_and_ty(cx, t, walkr, walkt); t }); } } @@ -2506,43 +2514,52 @@ pub fn index_sty(cx: ctxt, sty: &sty) -> Option { } } -impl to_bytes::IterBytes for bound_region { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - match *self { - ty::br_self => 0u8.iter_bytes(lsb0, f), - - ty::br_anon(ref idx) => - to_bytes::iter_bytes_2(&1u8, idx, lsb0, f), - - ty::br_named(ref ident) => - to_bytes::iter_bytes_2(&2u8, ident, lsb0, f), +/** + * Enforces an arbitrary but consistent total ordering over + * free regions. This is needed for establishing a consistent + * LUB in region_inference. */ +impl cmp::TotalOrd for FreeRegion { + fn cmp(&self, other: &FreeRegion) -> Ordering { + cmp::cmp2(&self.scope_id, &self.bound_region, + &other.scope_id, &other.bound_region) + } +} - ty::br_cap_avoid(ref id, ref br) => - to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f), +impl cmp::TotalEq for FreeRegion { + fn equals(&self, other: &FreeRegion) -> bool { + *self == *other + } +} - ty::br_fresh(ref x) => - to_bytes::iter_bytes_2(&4u8, x, lsb0, f) +/** + * Enforces an arbitrary but consistent total ordering over + * bound regions. This is needed for establishing a consistent + * LUB in region_inference. */ +impl cmp::TotalOrd for bound_region { + fn cmp(&self, other: &bound_region) -> Ordering { + match (self, other) { + (&ty::br_self, &ty::br_self) => cmp::Equal, + (&ty::br_self, _) => cmp::Less, + + (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2), + (&ty::br_anon(*), _) => cmp::Less, + + (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.repr.cmp(&a2.repr), + (&ty::br_named(*), _) => cmp::Less, + + (&ty::br_cap_avoid(ref a1, @ref b1), + &ty::br_cap_avoid(ref a2, @ref b2)) => cmp::cmp2(a1, b1, a2, b2), + (&ty::br_cap_avoid(*), _) => cmp::Less, + + (&ty::br_fresh(ref a1), &ty::br_fresh(ref a2)) => a1.cmp(a2), + (&ty::br_fresh(*), _) => cmp::Less, } } } -impl to_bytes::IterBytes for Region { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - match *self { - re_bound(ref br) => - to_bytes::iter_bytes_2(&0u8, br, lsb0, f), - - re_free(ref id, ref br) => - to_bytes::iter_bytes_3(&1u8, id, br, lsb0, f), - - re_scope(ref id) => - to_bytes::iter_bytes_2(&2u8, id, lsb0, f), - - re_infer(ref id) => - to_bytes::iter_bytes_2(&3u8, id, lsb0, f), - - re_static => 4u8.iter_bytes(lsb0, f) - } +impl cmp::TotalEq for bound_region { + fn equals(&self, other: &bound_region) -> bool { + *self == *other } } @@ -2856,8 +2873,17 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { */ let unadjusted_ty = expr_ty(cx, expr); + adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find(&expr.id)) +} + +pub fn adjust_ty(cx: ctxt, + span: span, + unadjusted_ty: ty::t, + adjustment: Option<&@AutoAdjustment>) -> ty::t +{ + /*! See `expr_ty_adjusted` */ - return match cx.adjustments.find(&expr.id) { + return match adjustment { None => unadjusted_ty, Some(&@AutoAddEnv(r, s)) => { @@ -2886,7 +2912,7 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { Some(mt) => { adjusted_ty = mt.ty; } None => { cx.sess.span_bug( - expr.span, + span, fmt!("The %uth autoderef failed: %s", i, ty_to_str(cx, adjusted_ty))); @@ -2905,18 +2931,18 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { } AutoBorrowVec => { - borrow_vec(cx, expr, autoref, adjusted_ty) + borrow_vec(cx, span, autoref, adjusted_ty) } AutoBorrowVecRef => { - adjusted_ty = borrow_vec(cx, expr, autoref, + adjusted_ty = borrow_vec(cx, span, autoref, adjusted_ty); mk_rptr(cx, autoref.region, mt {ty: adjusted_ty, mutbl: ast::m_imm}) } AutoBorrowFn => { - borrow_fn(cx, expr, autoref, adjusted_ty) + borrow_fn(cx, span, autoref, adjusted_ty) } } } @@ -2924,7 +2950,7 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { } }; - fn borrow_vec(cx: ctxt, expr: @ast::expr, + fn borrow_vec(cx: ctxt, span: span, autoref: &AutoRef, ty: ty::t) -> ty::t { match get(ty).sty { ty_evec(mt, _) => { @@ -2938,14 +2964,14 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { ref s => { cx.sess.span_bug( - expr.span, + span, fmt!("borrow-vec associated with bad sty: %?", s)); } } } - fn borrow_fn(cx: ctxt, expr: @ast::expr, + fn borrow_fn(cx: ctxt, span: span, autoref: &AutoRef, ty: ty::t) -> ty::t { match get(ty).sty { ty_closure(ref fty) => { @@ -2958,7 +2984,7 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { ref s => { cx.sess.span_bug( - expr.span, + span, fmt!("borrow-fn associated with bad sty: %?", s)); } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 2455201907447..6bc1317d5f91c 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -95,6 +95,7 @@ use middle::typeck::check::method::{CheckTraitsAndInherentMethods}; use middle::typeck::check::method::{CheckTraitsOnly, DontAutoderefReceiver}; use middle::typeck::check::method::{TransformTypeNormally}; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; +use middle::typeck::check::regionmanip::relate_free_regions; use middle::typeck::check::vtable::{LocationInfo, VtableContext}; use middle::typeck::CrateCtxt; use middle::typeck::infer::{resolve_type, force_tvar}; @@ -308,10 +309,14 @@ pub fn check_fn(ccx: @mut CrateCtxt, // the node_id of the body block. let (isr, self_info, fn_sig) = { - replace_bound_regions_in_fn_sig(tcx, inherited_isr, self_info, fn_sig, - |br| ty::re_free(body.node.id, br)) + replace_bound_regions_in_fn_sig( + tcx, inherited_isr, self_info, fn_sig, + |br| ty::re_free(ty::FreeRegion {scope_id: body.node.id, + bound_region: br})) }; + relate_free_regions(tcx, self_info.map(|s| s.self_ty), &fn_sig); + let arg_tys = fn_sig.inputs.map(|a| a.ty); let ret_ty = fn_sig.output; @@ -2841,8 +2846,7 @@ pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::local) { _ => {} } - let region = - ty::re_scope(*tcx.region_map.get(&local.node.id)); + let region = tcx.region_maps.encl_region(local.node.id); let pcx = pat_ctxt { fcx: fcx, map: pat_id_map(tcx.def_map, local.node.pat), diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 833dbff89a0fc..5594f2a0f658b 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -31,13 +31,15 @@ use core::prelude::*; use middle::freevars::get_freevars; use middle::pat_util::pat_bindings; -use middle::ty::{encl_region, re_scope}; +use middle::ty::{re_scope}; use middle::ty; use middle::typeck::check::FnCtxt; use middle::typeck::check::lookup_def; +use middle::typeck::check::regionmanip::relate_nested_regions; use middle::typeck::infer::resolve_and_force_all_but_regions; use middle::typeck::infer::resolve_type; -use util::ppaux::{note_and_explain_region, ty_to_str}; +use util::ppaux::{note_and_explain_region, ty_to_str, + region_to_str}; use core::result; use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil}; @@ -53,12 +55,13 @@ pub struct Rcx { pub type rvt = visit::vt<@mut Rcx>; -pub fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::def) -> ty::Region { +fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::def) -> ty::Region { let tcx = fcx.tcx(); match def { def_local(node_id, _) | def_arg(node_id, _, _) | - def_self(node_id, _) | def_binding(node_id, _) => - return encl_region(tcx, node_id), + def_self(node_id, _) | def_binding(node_id, _) => { + tcx.region_maps.encl_region(node_id) + } def_upvar(_, subdef, closure_id, body_id) => { match ty::ty_closure_sigil(fcx.node_ty(closure_id)) { BorrowedSigil => encl_region_of_def(fcx, *subdef), @@ -113,6 +116,24 @@ pub impl Rcx { fn resolve_node_type(@mut self, id: ast::node_id) -> ty::t { self.resolve_type(self.fcx.node_ty(id)) } + + /// Try to resolve the type for the given node. + fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t { + let ty_unadjusted = self.resolve_node_type(expr.id); + if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) { + ty_unadjusted + } else { + let tcx = self.fcx.tcx(); + let adjustments = self.fcx.inh.adjustments; + match adjustments.find(&expr.id) { + None => ty_unadjusted, + Some(&adjustment) => { + // FIXME(#3850) --- avoid region scoping errors + ty::adjust_ty(tcx, expr.span, ty_unadjusted, Some(&adjustment)) + } + } + } + } } pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::expr) { @@ -129,7 +150,7 @@ pub fn regionck_fn(fcx: @mut FnCtxt, blk: &ast::blk) { fcx.infcx().resolve_regions(); } -pub fn regionck_visitor() -> rvt { +fn regionck_visitor() -> rvt { visit::mk_vt(@visit::Visitor {visit_item: visit_item, visit_stmt: visit_stmt, visit_expr: visit_expr, @@ -138,11 +159,11 @@ pub fn regionck_visitor() -> rvt { .. *visit::default_visitor()}) } -pub fn visit_item(_item: @ast::item, &&_rcx: @mut Rcx, _v: rvt) { +fn visit_item(_item: @ast::item, &&_rcx: @mut Rcx, _v: rvt) { // Ignore items } -pub fn visit_local(l: @ast::local, &&rcx: @mut Rcx, v: rvt) { +fn visit_local(l: @ast::local, &&rcx: @mut Rcx, v: rvt) { // Check to make sure that the regions in all local variables are // within scope. // @@ -173,19 +194,24 @@ pub fn visit_local(l: @ast::local, &&rcx: @mut Rcx, v: rvt) { } } -pub fn visit_block(b: &ast::blk, &&rcx: @mut Rcx, v: rvt) { +fn visit_block(b: &ast::blk, &&rcx: @mut Rcx, v: rvt) { visit::visit_block(b, rcx, v); } -pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { - debug!("visit_expr(e=%s)", rcx.fcx.expr_to_str(expr)); +fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { + debug!("regionck::visit_expr(e=%s)", rcx.fcx.expr_to_str(expr)); for rcx.fcx.inh.adjustments.find(&expr.id).each |&adjustment| { + debug!("adjustment=%?", adjustment); match *adjustment { @ty::AutoDerefRef( - ty::AutoDerefRef { - autoderefs: autoderefs, autoref: Some(ref autoref)}) => { - guarantor::for_autoref(rcx, expr, autoderefs, autoref); + ty::AutoDerefRef {autoderefs: autoderefs, autoref: opt_autoref}) => + { + let expr_ty = rcx.resolve_node_type(expr.id); + constrain_derefs(rcx, expr, autoderefs, expr_ty); + for opt_autoref.each |autoref| { + guarantor::for_autoref(rcx, expr, autoderefs, autoref); + } } _ => {} } @@ -271,6 +297,16 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { } } + ast::expr_index(vec_expr, _) => { + let vec_type = rcx.resolve_expr_type_adjusted(vec_expr); + constrain_index(rcx, expr, vec_type); + } + + ast::expr_unary(ast::deref, base) => { + let base_ty = rcx.resolve_node_type(base.id); + constrain_derefs(rcx, expr, 1, base_ty); + } + ast::expr_addr_of(_, base) => { guarantor::for_addr_of(rcx, expr, base); } @@ -297,11 +333,11 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { visit::visit_expr(expr, rcx, v); } -pub fn visit_stmt(s: @ast::stmt, &&rcx: @mut Rcx, v: rvt) { +fn visit_stmt(s: @ast::stmt, &&rcx: @mut Rcx, v: rvt) { visit::visit_stmt(s, rcx, v); } -pub fn visit_node(id: ast::node_id, span: span, rcx: @mut Rcx) -> bool { +fn visit_node(id: ast::node_id, span: span, rcx: @mut Rcx) -> bool { /*! * * checks the type of the node `id` and reports an error if it @@ -314,13 +350,119 @@ pub fn visit_node(id: ast::node_id, span: span, rcx: @mut Rcx) -> bool { // find the region where this expr evaluation is taking place let tcx = fcx.ccx.tcx; - let encl_region = ty::encl_region(tcx, id); + let encl_region = match tcx.region_maps.opt_encl_scope(id) { + None => ty::re_static, + Some(r) => ty::re_scope(r) + }; // Otherwise, look at the type and see if it is a region pointer. constrain_regions_in_type_of_node(rcx, id, encl_region, span) } -pub fn constrain_auto_ref(rcx: @mut Rcx, expr: @ast::expr) { +fn encl_region_or_static(rcx: @mut Rcx, expr: @ast::expr) -> ty::Region { + // FIXME(#3850) --- interactions with modes compel overly large granularity + // that is, we would probably prefer to just return re_scope(expr.id) + // here but we cannot just yet. + + let tcx = rcx.fcx.tcx(); + match tcx.region_maps.opt_encl_scope(expr.id) { + Some(s) => ty::re_scope(s), + None => ty::re_static // occurs in constants + } +} + +fn constrain_derefs(rcx: @mut Rcx, + deref_expr: @ast::expr, + derefs: uint, + mut derefd_ty: ty::t) +{ + /*! + * Invoked on any dereference that occurs, whether explicitly + * or through an auto-deref. Checks that if this is a region + * pointer being derefenced, the lifetime of the pointer includes + * the deref expr. + */ + + let tcx = rcx.fcx.tcx(); + let r_deref_expr = encl_region_or_static(rcx, deref_expr); + for uint::range(0, derefs) |i| { + debug!("constrain_derefs(deref_expr=%s, derefd_ty=%s, derefs=%?/%?", + rcx.fcx.expr_to_str(deref_expr), + rcx.fcx.infcx().ty_to_str(derefd_ty), + i, derefs); + + match ty::get(derefd_ty).sty { + ty::ty_rptr(r_ptr, _) => { + match rcx.fcx.mk_subr(true, deref_expr.span, r_deref_expr, r_ptr) { + result::Ok(*) => {} + result::Err(*) => { + tcx.sess.span_err( + deref_expr.span, + fmt!("dereference of reference outside its lifetime")); + note_and_explain_region( + tcx, + "the reference is only valid for ", + r_ptr, + ""); + } + } + } + + _ => {} + } + + match ty::deref(tcx, derefd_ty, true) { + Some(mt) => derefd_ty = mt.ty, + None => { + tcx.sess.span_bug( + deref_expr.span, + fmt!("%?'th deref is of a non-deref'able type `%s`", + i, rcx.fcx.infcx().ty_to_str(derefd_ty))); + } + } + } +} + +fn constrain_index(rcx: @mut Rcx, + index_expr: @ast::expr, + indexed_ty: ty::t) +{ + /*! + * Invoked on any index expression that occurs. Checks that if + * this is a slice being indexed, the lifetime of the pointer + * includes the deref expr. + */ + + let tcx = rcx.fcx.tcx(); + + debug!("constrain_index(index_expr=%s, indexed_ty=%s", + rcx.fcx.expr_to_str(index_expr), + rcx.fcx.infcx().ty_to_str(indexed_ty)); + + let r_index_expr = encl_region_or_static(rcx, index_expr); + match ty::get(indexed_ty).sty { + ty::ty_estr(ty::vstore_slice(r_ptr)) | + ty::ty_evec(_, ty::vstore_slice(r_ptr)) => { + match rcx.fcx.mk_subr(true, index_expr.span, r_index_expr, r_ptr) { + result::Ok(*) => {} + result::Err(*) => { + tcx.sess.span_err( + index_expr.span, + fmt!("index of slice outside its lifetime")); + note_and_explain_region( + tcx, + "the slice is only valid for ", + r_ptr, + ""); + } + } + } + + _ => {} + } +} + +fn constrain_auto_ref(rcx: @mut Rcx, expr: @ast::expr) { /*! * * If `expr` is auto-ref'd (e.g., as part of a borrow), then this @@ -340,7 +482,7 @@ pub fn constrain_auto_ref(rcx: @mut Rcx, expr: @ast::expr) { }; let tcx = rcx.fcx.tcx(); - let encl_region = ty::encl_region(tcx, expr.id); + let encl_region = tcx.region_maps.encl_region(expr.id); match rcx.fcx.mk_subr(true, expr.span, encl_region, region) { result::Ok(()) => {} result::Err(_) => { @@ -366,7 +508,7 @@ pub fn constrain_auto_ref(rcx: @mut Rcx, expr: @ast::expr) { } } -pub fn constrain_free_variables( +fn constrain_free_variables( rcx: @mut Rcx, region: ty::Region, expr: @ast::expr) { @@ -402,81 +544,103 @@ pub fn constrain_free_variables( } } -pub fn constrain_regions_in_type_of_node( +fn constrain_regions_in_type_of_node( rcx: @mut Rcx, id: ast::node_id, encl_region: ty::Region, - span: span) -> bool { + span: span) -> bool +{ let tcx = rcx.fcx.tcx(); // Try to resolve the type. If we encounter an error, then typeck // is going to fail anyway, so just stop here and let typeck // report errors later on in the writeback phase. - let ty = rcx.resolve_node_type(id); + let ty0 = rcx.resolve_node_type(id); + let adjustment = rcx.fcx.inh.adjustments.find(&id); + let ty = ty::adjust_ty(tcx, span, ty0, adjustment); debug!("constrain_regions_in_type_of_node(\ - ty=%s, id=%d, encl_region=%?)", - ty_to_str(tcx, ty), id, encl_region); + ty=%s, ty0=%s, id=%d, encl_region=%?, adjustment=%?)", + ty_to_str(tcx, ty), ty_to_str(tcx, ty0), + id, encl_region, adjustment); constrain_regions_in_type(rcx, encl_region, span, ty) } -pub fn constrain_regions_in_type( +fn constrain_regions_in_type( rcx: @mut Rcx, encl_region: ty::Region, span: span, - ty: ty::t) -> bool { + ty: ty::t) -> bool +{ /*! * * Requires that any regions which appear in `ty` must be - * superregions of `encl_region`. This prevents regions from - * being used outside of the block in which they are valid. - * Recall that regions represent blocks of code or expressions: - * this requirement basically says "any place that uses or may use - * a region R must be within the block of code that R corresponds - * to." */ + * superregions of `encl_region`. Also enforces the constraint + * that given a pointer type `&'r T`, T must not contain regions + * that outlive 'r, as well as analogous constraints for other + * lifetime'd types. + * + * This check prevents regions from being used outside of the block in + * which they are valid. Recall that regions represent blocks of + * code or expressions: this requirement basically says "any place + * that uses or may use a region R must be within the block of + * code that R corresponds to." + */ let e = rcx.errors_reported; - ty::walk_regions_and_ty( - rcx.fcx.ccx.tcx, ty, - |r| constrain_region(rcx, encl_region, span, r), - |t| ty::type_has_regions(t)); - return (e == rcx.errors_reported); + let tcx = rcx.fcx.ccx.tcx; - fn constrain_region(rcx: @mut Rcx, - encl_region: ty::Region, - span: span, - region: ty::Region) { - let tcx = rcx.fcx.ccx.tcx; + debug!("constrain_regions_in_type(encl_region=%s, ty=%s)", + region_to_str(tcx, encl_region), + ty_to_str(tcx, ty)); - debug!("constrain_region(encl_region=%?, region=%?)", - encl_region, region); + do relate_nested_regions(tcx, Some(encl_region), ty) |r_sub, r_sup| { + debug!("relate(r_sub=%s, r_sup=%s)", + region_to_str(tcx, r_sub), + region_to_str(tcx, r_sup)); - match region { - ty::re_bound(_) => { + if r_sup.is_bound() || r_sub.is_bound() { // a bound region is one which appears inside an fn type. // (e.g., the `&` in `fn(&T)`). Such regions need not be // constrained by `encl_region` as they are placeholders // for regions that are as-yet-unknown. - return; - } - _ => () - } - - match rcx.fcx.mk_subr(true, span, encl_region, region) { - result::Err(_) => { - tcx.sess.span_err( - span, - fmt!("reference is not valid outside of its lifetime")); - note_and_explain_region( - tcx, - ~"the reference is only valid for ", - region, - ~""); - rcx.errors_reported += 1u; - } - result::Ok(()) => { - } + } else { + match rcx.fcx.mk_subr(true, span, r_sub, r_sup) { + result::Err(_) => { + if r_sub == encl_region { + tcx.sess.span_err( + span, + fmt!("reference is not valid outside of its lifetime")); + note_and_explain_region( + tcx, + "the reference is only valid for ", + r_sup, + ""); + } else { + tcx.sess.span_err( + span, + fmt!("in type `%s`, pointer has a longer lifetime than \ + the data it references", + rcx.fcx.infcx().ty_to_str(ty))); + note_and_explain_region( + tcx, + "the pointer is valid for ", + r_sub, + ""); + note_and_explain_region( + tcx, + "but the referenced data is only valid for ", + r_sup, + ""); + } + rcx.errors_reported += 1u; + } + result::Ok(()) => { + } + } } } + + return (e == rcx.errors_reported); } pub mod guarantor { @@ -577,10 +741,12 @@ pub mod guarantor { * region pointers. */ - debug!("guarantor::for_autoref(expr=%s)", rcx.fcx.expr_to_str(expr)); + debug!("guarantor::for_autoref(expr=%s, autoref=%?)", + rcx.fcx.expr_to_str(expr), autoref); let _i = ::util::common::indenter(); let mut expr_ct = categorize_unadjusted(rcx, expr); + debug!(" unadjusted cat=%?", expr_ct.cat); expr_ct = apply_autoderefs( rcx, expr, autoderefs, expr_ct); @@ -626,7 +792,7 @@ pub mod guarantor { * to the lifetime of its guarantor (if any). */ - debug!("opt_constrain_region(id=%?, guarantor=%?)", id, guarantor); + debug!("link(id=%?, guarantor=%?)", id, guarantor); let bound = match guarantor { None => { @@ -860,8 +1026,6 @@ pub mod guarantor { match closure_ty.sigil { ast::BorrowedSigil => BorrowedPointer(closure_ty.region), ast::OwnedSigil => OwnedPointer, - - // NOTE This is...not quite right. Deduce a test etc. ast::ManagedSigil => OtherPointer, } } @@ -972,7 +1136,6 @@ pub fn infallibly_mk_subr(rcx: @mut Rcx, a: ty::Region, b: ty::Region) { /*! - * * Constrains `a` to be a subregion of `b`. In many cases, we * know that this can never yield an error due to the way that * region inferencing works. Therefore just report a bug if we diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index abbefd1f7e6f9..359f938d0d997 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -99,7 +99,7 @@ pub fn replace_bound_regions_in_fn_sig( to_r: &fn(ty::bound_region) -> ty::Region, r: ty::Region) -> isr_alist { match r { - ty::re_free(_, _) | ty::re_static | ty::re_scope(_) | + ty::re_free(*) | ty::re_static | ty::re_scope(_) | ty::re_infer(_) => { isr } @@ -167,10 +167,125 @@ pub fn replace_bound_regions_in_fn_sig( // Free regions like these just stay the same: ty::re_static | ty::re_scope(_) | - ty::re_free(_, _) | + ty::re_free(*) | ty::re_infer(_) => r }; r1 } } } + +pub fn relate_nested_regions( + tcx: ty::ctxt, + opt_region: Option, + ty: ty::t, + relate_op: &fn(ty::Region, ty::Region)) +{ + /*! + * + * This rather specialized function walks each region `r` that appear + * in `ty` and invokes `relate_op(r_encl, r)` for each one. `r_encl` + * here is the region of any enclosing `&'r T` pointer. If there is + * no enclosing pointer, and `opt_region` is Some, then `opt_region.get()` + * is used instead. Otherwise, no callback occurs at all). + * + * Here are some examples to give you an intution: + * + * - `relate_nested_regions(Some('r1), &'r2 uint)` invokes + * - `relate_op('r1, 'r2)` + * - `relate_nested_regions(Some('r1), &'r2 &'r3 uint)` invokes + * - `relate_op('r1, 'r2)` + * - `relate_op('r2, 'r3)` + * - `relate_nested_regions(None, &'r2 &'r3 uint)` invokes + * - `relate_op('r2, 'r3)` + * - `relate_nested_regions(None, &'r2 &'r3 &'r4 uint)` invokes + * - `relate_op('r2, 'r3)` + * - `relate_op('r2, 'r4)` + * - `relate_op('r3, 'r4)` + * + * This function is used in various pieces of code because we enforce the + * constraint that a region pointer cannot outlive the things it points at. + * Hence, in the second example above, `'r2` must be a subregion of `'r3`. + */ + + let mut the_stack = ~[]; + for opt_region.each |&r| { the_stack.push(r); } + walk_ty(tcx, &mut the_stack, ty, relate_op); + + fn walk_ty(tcx: ty::ctxt, + the_stack: &mut ~[ty::Region], + ty: ty::t, + relate_op: &fn(ty::Region, ty::Region)) + { + match ty::get(ty).sty { + ty::ty_rptr(r, ref mt) | + ty::ty_evec(ref mt, ty::vstore_slice(r)) => { + relate(*the_stack, r, relate_op); + the_stack.push(r); + walk_ty(tcx, the_stack, mt.ty, relate_op); + the_stack.pop(); + } + _ => { + ty::fold_regions_and_ty( + tcx, + ty, + |r| { relate(*the_stack, r, relate_op); r }, + |t| { walk_ty(tcx, the_stack, t, relate_op); t }, + |t| { walk_ty(tcx, the_stack, t, relate_op); t }); + } + } + } + + fn relate(the_stack: &[ty::Region], + r_sub: ty::Region, + relate_op: &fn(ty::Region, ty::Region)) + { + for the_stack.each |&r| { + if !r.is_bound() && !r_sub.is_bound() { + relate_op(r, r_sub); + } + } + } +} + +pub fn relate_free_regions( + tcx: ty::ctxt, + self_ty: Option, + fn_sig: &ty::FnSig) +{ + /*! + * This function populates the region map's `free_region_map`. + * It walks over the transformed self type and argument types + * for each function just before we check the body of that + * function, looking for types where you have a borrowed + * pointer to other borrowed data (e.g., `&'a &'b [uint]`. + * We do not allow borrowed pointers to outlive the things they + * point at, so we can assume that `'a <= 'b`. + * + * Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` + */ + + debug!("relate_free_regions >>"); + + let mut all_tys = ~[]; + for fn_sig.inputs.each |arg| { + all_tys.push(arg.ty); + } + for self_ty.each |&t| { + all_tys.push(t); + } + + for all_tys.each |&t| { + debug!("relate_free_regions(t=%s)", ppaux::ty_to_str(tcx, t)); + relate_nested_regions(tcx, None, t, |a, b| { + match (&a, &b) { + (&ty::re_free(free_a), &ty::re_free(free_b)) => { + tcx.region_maps.relate_free_regions(free_a, free_b); + } + _ => {} + } + }) + } + + debug!("<< relate_free_regions"); +} \ No newline at end of file diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a3296f6c20985..0ef6e2512f3d5 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -535,7 +535,8 @@ pub fn compare_impl_method(tcx: ty::ctxt, // a free region. So, for example, if the impl type is // "&'self str", then this would replace the self type with a free // region `self`. - let dummy_self_r = ty::re_free(cm.body_id, ty::br_self); + let dummy_self_r = ty::re_free(ty::FreeRegion {scope_id: cm.body_id, + bound_region: ty::br_self}); let self_ty = replace_bound_self(tcx, self_ty, dummy_self_r); // Perform substitutions so that the trait/impl methods are expressed diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index e6354d4ab88f6..7252566d84c17 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -538,10 +538,9 @@ more convincing in the future. use core::prelude::*; -use middle::region::is_subregion_of; -use middle::region; use middle::ty; -use middle::ty::{Region, RegionVid, re_static, re_infer, re_free, re_bound}; +use middle::ty::{FreeRegion, Region, RegionVid}; +use middle::ty::{re_static, re_infer, re_free, re_bound}; use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh}; use middle::typeck::infer::cres; use util::common::indenter; @@ -554,6 +553,7 @@ use core::to_bytes; use core::uint; use core::vec; use syntax::codemap::span; +use syntax::ast; #[deriving(Eq)] enum Constraint { @@ -1025,11 +1025,12 @@ pub impl RegionVarBindings { } priv impl RegionVarBindings { - fn is_subregion_of(&mut self, sub: Region, sup: Region) -> bool { - is_subregion_of(self.tcx.region_map, sub, sup) + fn is_subregion_of(&self, sub: Region, sup: Region) -> bool { + let rm = self.tcx.region_maps; + rm.is_subregion_of(sub, sup) } - fn lub_concrete_regions(&mut self, +a: Region, +b: Region) -> Region { + fn lub_concrete_regions(&self, +a: Region, +b: Region) -> Region { match (a, b) { (re_static, _) | (_, re_static) => { re_static // nothing lives longer than static @@ -1042,17 +1043,17 @@ priv impl RegionVarBindings { non-concrete regions: %?, %?", a, b)); } - (f @ re_free(f_id, _), re_scope(s_id)) | - (re_scope(s_id), f @ re_free(f_id, _)) => { + (f @ re_free(ref fr), re_scope(s_id)) | + (re_scope(s_id), f @ re_free(ref fr)) => { // A "free" region can be interpreted as "some region - // at least as big as the block f_id". So, we can + // at least as big as the block fr.scope_id". So, we can // reasonably compare free regions and scopes: - let rm = self.tcx.region_map; - match region::nearest_common_ancestor(rm, f_id, s_id) { - // if the free region's scope `f_id` is bigger than + let rm = self.tcx.region_maps; + match rm.nearest_common_ancestor(fr.scope_id, s_id) { + // if the free region's scope `fr.scope_id` is bigger than // the scope region `s_id`, then the LUB is the free // region itself: - Some(r_id) if r_id == f_id => f, + Some(r_id) if r_id == fr.scope_id => f, // otherwise, we don't know what the free region is, // so we must conservatively say the LUB is static: @@ -1064,32 +1065,67 @@ priv impl RegionVarBindings { // The region corresponding to an outer block is a // subtype of the region corresponding to an inner // block. - let rm = self.tcx.region_map; - match region::nearest_common_ancestor(rm, a_id, b_id) { + let rm = self.tcx.region_maps; + match rm.nearest_common_ancestor(a_id, b_id) { Some(r_id) => re_scope(r_id), _ => re_static } } + (re_free(ref a_fr), re_free(ref b_fr)) => { + self.lub_free_regions(a_fr, b_fr) + } + // For these types, we cannot define any additional // relationship: (re_infer(ReSkolemized(*)), _) | (_, re_infer(ReSkolemized(*))) | - (re_free(_, _), re_free(_, _)) | (re_bound(_), re_bound(_)) | - (re_bound(_), re_free(_, _)) | + (re_bound(_), re_free(_)) | (re_bound(_), re_scope(_)) | - (re_free(_, _), re_bound(_)) | + (re_free(_), re_bound(_)) | (re_scope(_), re_bound(_)) => { if a == b {a} else {re_static} } } } - fn glb_concrete_regions(&mut self, + fn lub_free_regions(&self, + a: &FreeRegion, + b: &FreeRegion) -> ty::Region + { + /*! + * Computes a region that encloses both free region arguments. + * Guarantee that if the same two regions are given as argument, + * in any order, a consistent result is returned. + */ + + return match a.cmp(b) { + Less => helper(self, a, b), + Greater => helper(self, b, a), + Equal => ty::re_free(*a) + }; + + fn helper(self: &RegionVarBindings, + a: &FreeRegion, + b: &FreeRegion) -> ty::Region + { + let rm = self.tcx.region_maps; + if rm.sub_free_region(*a, *b) { + ty::re_free(*b) + } else if rm.sub_free_region(*b, *a) { + ty::re_free(*a) + } else { + ty::re_static + } + } + } + + fn glb_concrete_regions(&self, +a: Region, +b: Region) -> cres { + debug!("glb_concrete_regions(%?, %?)", a, b); match (a, b) { (re_static, r) | (r, re_static) => { // static lives longer than everything else @@ -1104,37 +1140,26 @@ priv impl RegionVarBindings { non-concrete regions: %?, %?", a, b)); } - (re_free(f_id, _), s @ re_scope(s_id)) | - (s @ re_scope(s_id), re_free(f_id, _)) => { + (re_free(ref fr), s @ re_scope(s_id)) | + (s @ re_scope(s_id), re_free(ref fr)) => { // Free region is something "at least as big as - // `f_id`." If we find that the scope `f_id` is bigger + // `fr.scope_id`." If we find that the scope `fr.scope_id` is bigger // than the scope `s_id`, then we can say that the GLB // is the scope `s_id`. Otherwise, as we do not know // big the free region is precisely, the GLB is undefined. - let rm = self.tcx.region_map; - match region::nearest_common_ancestor(rm, f_id, s_id) { - Some(r_id) if r_id == f_id => Ok(s), + let rm = self.tcx.region_maps; + match rm.nearest_common_ancestor(fr.scope_id, s_id) { + Some(r_id) if r_id == fr.scope_id => Ok(s), _ => Err(ty::terr_regions_no_overlap(b, a)) } } - (re_scope(a_id), re_scope(b_id)) | - (re_free(a_id, _), re_free(b_id, _)) => { - if a == b { - // Same scope or same free identifier, easy case. - Ok(a) - } else { - // We want to generate the intersection of two - // scopes or two free regions. So, if one of - // these scopes is a subscope of the other, return - // it. Otherwise fail. - let rm = self.tcx.region_map; - match region::nearest_common_ancestor(rm, a_id, b_id) { - Some(r_id) if a_id == r_id => Ok(re_scope(b_id)), - Some(r_id) if b_id == r_id => Ok(re_scope(a_id)), - _ => Err(ty::terr_regions_no_overlap(b, a)) - } - } + (re_scope(a_id), re_scope(b_id)) => { + self.intersect_scopes(a, b, a_id, b_id) + } + + (re_free(ref a_fr), re_free(ref b_fr)) => { + self.glb_free_regions(a_fr, b_fr) } // For these types, we cannot define any additional @@ -1142,9 +1167,9 @@ priv impl RegionVarBindings { (re_infer(ReSkolemized(*)), _) | (_, re_infer(ReSkolemized(*))) | (re_bound(_), re_bound(_)) | - (re_bound(_), re_free(_, _)) | + (re_bound(_), re_free(_)) | (re_bound(_), re_scope(_)) | - (re_free(_, _), re_bound(_)) | + (re_free(_), re_bound(_)) | (re_scope(_), re_bound(_)) => { if a == b { Ok(a) @@ -1155,10 +1180,62 @@ priv impl RegionVarBindings { } } + fn glb_free_regions(&self, + a: &FreeRegion, + b: &FreeRegion) -> cres + { + /*! + * Computes a region that is enclosed by both free region arguments, + * if any. Guarantees that if the same two regions are given as argument, + * in any order, a consistent result is returned. + */ + + return match a.cmp(b) { + Less => helper(self, a, b), + Greater => helper(self, b, a), + Equal => Ok(ty::re_free(*a)) + }; + + fn helper(self: &RegionVarBindings, + a: &FreeRegion, + b: &FreeRegion) -> cres + { + let rm = self.tcx.region_maps; + if rm.sub_free_region(*a, *b) { + Ok(ty::re_free(*a)) + } else if rm.sub_free_region(*b, *a) { + Ok(ty::re_free(*b)) + } else { + self.intersect_scopes(ty::re_free(*a), ty::re_free(*b), + a.scope_id, b.scope_id) + } + } + } + fn report_type_error(&mut self, span: span, terr: &ty::type_err) { let terr_str = ty::type_err_to_str(self.tcx, terr); self.tcx.sess.span_err(span, terr_str); } + + fn intersect_scopes(&self, + region_a: ty::Region, + region_b: ty::Region, + scope_a: ast::node_id, + scope_b: ast::node_id) -> cres + { + // We want to generate the intersection of two + // scopes or two free regions. So, if one of + // these scopes is a subscope of the other, return + // it. Otherwise fail. + debug!("intersect_scopes(scope_a=%?, scope_b=%?, region_a=%?, region_b=%?)", + scope_a, scope_b, region_a, region_b); + let rm = self.tcx.region_maps; + match rm.nearest_common_ancestor(scope_a, scope_b) { + Some(r_id) if scope_a == r_id => Ok(re_scope(scope_b)), + Some(r_id) if scope_b == r_id => Ok(re_scope(scope_a)), + _ => Err(ty::terr_regions_no_overlap(region_a, region_b)) + } + } } // ______________________________________________________________________ diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index 52a0300c5a089..bf607e2c36246 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -210,7 +210,9 @@ pub impl Env { } fn t_rptr_free(&self, nid: ast::node_id, id: uint) -> ty::t { - ty::mk_imm_rptr(self.tcx, ty::re_free(nid, ty::br_anon(id)), + ty::mk_imm_rptr(self.tcx, + ty::re_free(ty::FreeRegion {scope_id: nid, + bound_region: ty::br_anon(id)}), self.t_int()) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f26eeeca446c1..f8877f768813d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -41,9 +41,9 @@ pub trait Repr { } pub fn note_and_explain_region(cx: ctxt, - prefix: ~str, + prefix: &str, region: ty::Region, - suffix: ~str) { + suffix: &str) { match explain_region_and_span(cx, region) { (ref str, Some(span)) => { cx.sess.span_note( @@ -98,23 +98,23 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region) } } - re_free(id, br) => { - let prefix = match br { + re_free(ref fr) => { + let prefix = match fr.bound_region { br_anon(idx) => fmt!("the anonymous lifetime #%u defined on", idx + 1), br_fresh(_) => fmt!("an anonymous lifetime defined on"), _ => fmt!("the lifetime %s as defined on", - bound_region_to_str(cx, br)) + bound_region_to_str(cx, fr.bound_region)) }; - match cx.items.find(&id) { + match cx.items.find(&fr.scope_id) { Some(&ast_map::node_block(ref blk)) => { let (msg, opt_span) = explain_span(cx, "block", blk.span); (fmt!("%s %s", prefix, msg), opt_span) } Some(_) | None => { // this really should not happen - (fmt!("%s node %d", prefix, id), None) + (fmt!("%s node %d", prefix, fr.scope_id), None) } } } @@ -215,7 +215,7 @@ pub fn region_to_str_space(cx: ctxt, prefix: &str, region: Region) -> ~str { match region { re_scope(_) => prefix.to_str(), re_bound(br) => bound_region_to_str_space(cx, prefix, br), - re_free(_, br) => bound_region_to_str_space(cx, prefix, br), + re_free(ref fr) => bound_region_to_str_space(cx, prefix, fr.bound_region), re_infer(ReSkolemized(_, br)) => { bound_region_to_str_space(cx, prefix, br) } @@ -225,12 +225,16 @@ pub fn region_to_str_space(cx: ctxt, prefix: &str, region: Region) -> ~str { } pub fn mt_to_str(cx: ctxt, m: &mt) -> ~str { + mt_to_str_wrapped(cx, "", m, "") +} + +pub fn mt_to_str_wrapped(cx: ctxt, before: &str, m: &mt, after: &str) -> ~str { let mstr = match m.mutbl { ast::m_mutbl => "mut ", ast::m_imm => "", ast::m_const => "const " }; - return fmt!("%s%s", mstr, ty_to_str(cx, m.ty)); + return fmt!("%s%s%s%s", mstr, before, ty_to_str(cx, m.ty), after); } pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str { @@ -250,15 +254,14 @@ pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str { } } -pub fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { +pub fn vstore_ty_to_str(cx: ctxt, mt: &mt, vs: ty::vstore) -> ~str { match vs { - ty::vstore_fixed(_) => { - fmt!("[%s, .. %s]", ty, vstore_to_str(cx, vs)) - } - ty::vstore_slice(_) => { - fmt!("%s %s", vstore_to_str(cx, vs), ty) - } - _ => fmt!("%s[%s]", vstore_to_str(cx, vs), ty) + ty::vstore_fixed(_) => { + fmt!("[%s, .. %s]", mt_to_str(cx, mt), vstore_to_str(cx, vs)) + } + _ => { + fmt!("%s%s", vstore_to_str(cx, vs), mt_to_str_wrapped(cx, "[", mt, "]")) + } } } @@ -460,7 +463,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { fmt!("%s%s", trait_store_to_str(cx, s), ty) } ty_evec(ref mt, vs) => { - vstore_ty_to_str(cx, fmt!("%s", mt_to_str(cx, mt)), vs) + vstore_ty_to_str(cx, mt, vs) } ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), ~"str"), ty_opaque_box => ~"@?", diff --git a/src/test/compile-fail/kindck-owned-trait-contains.rs b/src/test/compile-fail/kindck-owned-trait-contains.rs index f5153265308e1..54ee8bcc70e37 100644 --- a/src/test/compile-fail/kindck-owned-trait-contains.rs +++ b/src/test/compile-fail/kindck-owned-trait-contains.rs @@ -27,5 +27,6 @@ fn main() { let x: &'blk int = &3; repeater(@x) }; - assert!(3 == *(y.get())); //~ ERROR reference is not valid + assert!(3 == *(y.get())); //~ ERROR dereference of reference outside its lifetime + //~^ ERROR reference is not valid outside of its lifetime } diff --git a/src/test/compile-fail/regions-escape-via-trait-or-not.rs b/src/test/compile-fail/regions-escape-via-trait-or-not.rs index fb9d963dc80a7..f7165784c7975 100644 --- a/src/test/compile-fail/regions-escape-via-trait-or-not.rs +++ b/src/test/compile-fail/regions-escape-via-trait-or-not.rs @@ -24,9 +24,9 @@ fn with(f: &fn(x: &int) -> R) -> int { fn return_it() -> int { with(|o| o) - //~^ ERROR reference is not valid outside of its lifetime + //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements //~^^ ERROR reference is not valid outside of its lifetime - //~^^^ ERROR cannot infer an appropriate lifetime + //~^^^ ERROR reference is not valid outside of its lifetime } fn main() { diff --git a/src/test/compile-fail/regions-free-region-ordering-callee.rs b/src/test/compile-fail/regions-free-region-ordering-callee.rs new file mode 100644 index 0000000000000..e5399fc7fa3b9 --- /dev/null +++ b/src/test/compile-fail/regions-free-region-ordering-callee.rs @@ -0,0 +1,37 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that callees correctly infer an ordering between free regions +// that appear in their parameter list. See also +// regions-free-region-ordering-caller.rs + +fn ordering1<'a, 'b>(x: &'a &'b uint) -> &'a uint { + // It is safe to assume that 'a <= 'b due to the type of x + let y: &'b uint = &**x; + return y; +} + +fn ordering2<'a, 'b>(x: &'a &'b uint, y: &'a uint) -> &'b uint { + // However, it is not safe to assume that 'b <= 'a + &*y //~ ERROR cannot infer an appropriate lifetime +} + +fn ordering3<'a, 'b>(x: &'a uint, y: &'b uint) -> &'a &'b uint { + // Do not infer an ordering from the return value. + let z: &'b uint = &*x; + //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements + fail!(); +} + +fn ordering4<'a, 'b>(a: &'a uint, b: &'b uint, x: &fn(&'a &'b uint)) { + let z: Option<&'a &'b uint> = None; +} + +fn main() {} \ No newline at end of file diff --git a/src/test/compile-fail/regions-free-region-ordering-caller.rs b/src/test/compile-fail/regions-free-region-ordering-caller.rs new file mode 100644 index 0000000000000..d06dcd8aa86b8 --- /dev/null +++ b/src/test/compile-fail/regions-free-region-ordering-caller.rs @@ -0,0 +1,40 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test various ways to construct a pointer with a longer lifetime +// than the thing it points at and ensure that they result in +// errors. See also regions-free-region-ordering-callee.rs + +struct Paramd<'self> { x: &'self uint } + +fn call1<'a>(x: &'a uint) { + let y: uint = 3; + let z: &'a &'blk uint = &(&y); + //~^ ERROR pointer has a longer lifetime than the data it references +} + +fn call2<'a, 'b>(a: &'a uint, b: &'b uint) { + let z: Option<&'b &'a uint> = None; + //~^ ERROR pointer has a longer lifetime than the data it references +} + +fn call3<'a, 'b>(a: &'a uint, b: &'b uint) { + let y: Paramd<'a> = Paramd { x: a }; + let z: Option<&'b Paramd<'a>> = None; + //~^ ERROR pointer has a longer lifetime than the data it references +} + +fn call4<'a, 'b>(a: &'a uint, b: &'b uint) { + let z: Option<&fn(&'a &'b uint)> = None; + //~^ ERROR pointer has a longer lifetime than the data it references +} + + +fn main() {} \ No newline at end of file diff --git a/src/test/compile-fail/regions-trait-2.rs b/src/test/compile-fail/regions-trait-2.rs index 5811496cab451..9855a234618ab 100644 --- a/src/test/compile-fail/regions-trait-2.rs +++ b/src/test/compile-fail/regions-trait-2.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test #5723 + +// Test that you cannot escape a borrowed pointer +// into a trait. + struct ctxt { v: uint } trait get_ctxt { @@ -24,8 +29,9 @@ fn make_gc() -> @get_ctxt { let ctxt = ctxt { v: 22u }; let hc = has_ctxt { c: &ctxt }; return @hc as @get_ctxt; + //^~ ERROR source contains borrowed pointer } fn main() { - make_gc().get_ctxt().v; //~ ERROR illegal borrow + make_gc().get_ctxt().v; } From 24eee5296bd8ec29285f65ef180d9cc9a9a391bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Wed, 10 Apr 2013 16:57:52 +0200 Subject: [PATCH 108/403] Added iter_to_vec conversion fn --- src/libcore/iter.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 7ed4c3c36ea6d..9c704fbd69915 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -344,3 +344,29 @@ pub fn copy_seq,BT:Buildable>(v: &IT) -> BT { for v.each |x| { push(*x); } } } + +/** + * Helper function to transform an internal iterator into an owned vector. + * + * # Example: + * + * ~~~ + * let v = ~[1, 2, 3]; + * let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) }; + * if v != v2 { fail!() } + * ~~~ + */ +#[inline(always)] +pub fn iter_to_vec(pusher: &fn(it: &fn(T) -> bool)) -> ~[T] { + let mut v = ~[]; + let pushf = |e| {v.push(e); true}; + pusher(pushf); + v +} + +#[test] +fn test_iter_to_vec() { + let v = ~[1, 2, 3]; + let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) }; + if v != v2 { fail!() } +} From 48e7bda8269861df43763b4fb42e68af0eb09b20 Mon Sep 17 00:00:00 2001 From: John Clements Date: Tue, 26 Mar 2013 17:00:35 -0700 Subject: [PATCH 109/403] path -> Path --- src/librustc/front/core_inject.rs | 2 +- src/librustc/front/test.rs | 8 +++--- src/librustc/metadata/tydecode.rs | 4 +-- src/librustc/middle/pat_util.rs | 2 +- src/librustc/middle/privacy.rs | 4 +-- src/librustc/middle/resolve.rs | 10 ++++---- src/librustc/middle/typeck/astconv.rs | 10 ++++---- src/librustc/middle/typeck/check/_match.rs | 8 +++--- src/librustc/middle/typeck/check/mod.rs | 2 +- src/libsyntax/ast.rs | 24 ++++++++--------- src/libsyntax/ast_util.rs | 6 ++--- src/libsyntax/ext/auto_encode.rs | 20 +++++++-------- src/libsyntax/ext/build.rs | 16 ++++++------ src/libsyntax/ext/concat_idents.rs | 2 +- src/libsyntax/ext/deriving/mod.rs | 2 +- src/libsyntax/ext/pipes/ast_builder.rs | 30 +++++++++++----------- src/libsyntax/fold.rs | 10 ++++---- src/libsyntax/parse/parser.rs | 16 ++++++------ src/libsyntax/parse/token.rs | 2 +- src/libsyntax/print/pprust.rs | 4 +-- src/libsyntax/visit.rs | 2 +- 21 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/core_inject.rs index a7c015d29a187..387cc9f80a7f6 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -77,7 +77,7 @@ fn inject_libcore_ref(sess: Session, fold_mod: |module, fld| { let n2 = sess.next_node_id(); - let prelude_path = @ast::path { + let prelude_path = @ast::Path { span: dummy_sp(), global: false, idents: ~[ diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 139ffbb5f5bb3..0cb1fdf91829a 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -336,16 +336,16 @@ fn nospan(t: T) -> codemap::spanned { codemap::spanned { node: t, span: dummy_sp() } } -fn path_node(+ids: ~[ast::ident]) -> @ast::path { - @ast::path { span: dummy_sp(), +fn path_node(+ids: ~[ast::ident]) -> @ast::Path { + @ast::Path { span: dummy_sp(), global: false, idents: ids, rp: None, types: ~[] } } -fn path_node_global(+ids: ~[ast::ident]) -> @ast::path { - @ast::path { span: dummy_sp(), +fn path_node_global(+ids: ~[ast::ident]) -> @ast::Path { + @ast::Path { span: dummy_sp(), global: true, idents: ids, rp: None, diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 867fe0cd816cc..72391b7aec2a1 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -137,7 +137,7 @@ pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, parse_arg(st, conv) } -fn parse_path(st: @mut PState) -> @ast::path { +fn parse_path(st: @mut PState) -> @ast::Path { let mut idents: ~[ast::ident] = ~[]; fn is_last(c: char) -> bool { return c == '(' || c == ':'; } idents.push(parse_ident_(st, is_last)); @@ -146,7 +146,7 @@ fn parse_path(st: @mut PState) -> @ast::path { ':' => { next(st); next(st); } c => { if c == '(' { - return @ast::path { span: dummy_sp(), + return @ast::Path { span: dummy_sp(), global: false, idents: idents, rp: None, diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 2e2048b7ae4cd..df0e508398ee4 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -72,7 +72,7 @@ pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @pat) -> bool { } pub fn pat_bindings(dm: resolve::DefMap, pat: @pat, - it: &fn(binding_mode, node_id, span, @path)) { + it: &fn(binding_mode, node_id, span, @Path)) { do walk_pat(pat) |p| { match p.node { pat_ident(binding_mode, pth, _) if pat_is_binding(dm, p) => { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 50e8ed23446de..e59ca9e658123 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -26,7 +26,7 @@ use syntax::ast::{decl_item, def, def_fn, def_id, def_static_method}; use syntax::ast::{def_variant, expr_field, expr_method_call, expr_path}; use syntax::ast::{expr_struct, expr_unary, ident, inherited, item_enum}; use syntax::ast::{item_foreign_mod, item_fn, item_impl, item_struct}; -use syntax::ast::{item_trait, local_crate, node_id, pat_struct, path}; +use syntax::ast::{item_trait, local_crate, node_id, pat_struct, Path}; use syntax::ast::{private, provided, public, required, stmt_decl, visibility}; use syntax::ast; use syntax::ast_map::{node_foreign_item, node_item, node_method}; @@ -276,7 +276,7 @@ pub fn check_crate(tcx: ty::ctxt, }; // Checks that a private path is in scope. - let check_path: @fn(span: span, def: def, path: @path) = + let check_path: @fn(span: span, def: def, path: @Path) = |span, def, path| { debug!("checking path"); match def { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index fcf0b7022a7a7..1c4a1c4564796 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -48,7 +48,7 @@ use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod}; use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le}; use syntax::ast::{local, local_crate, lt, method, mode, mul}; use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident}; -use syntax::ast::{path, pat_lit, pat_range, pat_struct}; +use syntax::ast::{Path, pat_lit, pat_range, pat_struct}; use syntax::ast::{prim_ty, private, provided}; use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl}; use syntax::ast::{struct_dtor, struct_field, struct_variant_kind}; @@ -4368,7 +4368,7 @@ pub impl Resolver { /// If `check_ribs` is true, checks the local definitions first; i.e. /// doesn't skip straight to the containing module. fn resolve_path(@mut self, - path: @path, + path: @Path, namespace: Namespace, check_ribs: bool, visitor: ResolveVisitor) @@ -4493,7 +4493,7 @@ pub impl Resolver { return NoNameDefinition; } - fn intern_module_part_of_path(@mut self, path: @path) -> ~[ident] { + fn intern_module_part_of_path(@mut self, path: @Path) -> ~[ident] { let mut module_path_idents = ~[]; for path.idents.eachi |index, ident| { if index == path.idents.len() - 1 { @@ -4507,7 +4507,7 @@ pub impl Resolver { } fn resolve_module_relative_path(@mut self, - path: @path, + path: @Path, +xray: XrayFlag, namespace: Namespace) -> Option { @@ -4553,7 +4553,7 @@ pub impl Resolver { /// Invariant: This must be called only during main resolution, not during /// import resolution. fn resolve_crate_relative_path(@mut self, - path: @path, + path: @Path, +xray: XrayFlag, namespace: Namespace) -> Option { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index bfc9d646dbb6c..a0c12ff1a204c 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -136,7 +136,7 @@ fn ast_path_substs( def_id: ast::def_id, decl_generics: &ty::Generics, self_ty: Option, - path: @ast::path) -> ty::substs + path: @ast::Path) -> ty::substs { /*! * @@ -188,7 +188,7 @@ pub fn ast_path_to_substs_and_ty( self: &AC, rscope: &RS, did: ast::def_id, - path: @ast::path) -> ty_param_substs_and_ty + path: @ast::Path) -> ty_param_substs_and_ty { let tcx = self.tcx(); let ty::ty_param_bounds_and_ty { @@ -206,7 +206,7 @@ pub fn ast_path_to_trait_ref( rscope: &RS, trait_def_id: ast::def_id, self_ty: Option, - path: @ast::path) -> @ty::TraitRef + path: @ast::Path) -> @ty::TraitRef { let trait_def = self.get_trait_def(trait_def_id); @@ -229,7 +229,7 @@ pub fn ast_path_to_ty( self: &AC, rscope: &RS, did: ast::def_id, - path: @ast::path) + path: @ast::Path) -> ty_param_substs_and_ty { // Look up the polytype of the item and then substitute the provided types @@ -318,7 +318,7 @@ pub fn ast_ty_to_ty( } fn check_path_args(tcx: ty::ctxt, - path: @ast::path, + path: @ast::Path, flags: uint) { if (flags & NO_TPS) != 0u { if path.types.len() > 0u { diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index aa2414eac6240..e2dd0d1ed9ed2 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -99,7 +99,7 @@ pub struct pat_ctxt { block_region: ty::Region, // Region for the block of the arm } -pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, +pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::Path, subpats: &Option<~[@ast::pat]>, expected: ty::t) { // Typecheck the path. @@ -234,7 +234,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, /// `etc` is true if the pattern said '...' and false otherwise. pub fn check_struct_pat_fields(pcx: pat_ctxt, span: span, - path: @ast::path, + path: @ast::Path, fields: &[ast::field_pat], class_fields: ~[ty::field_ty], class_id: ast::def_id, @@ -285,7 +285,7 @@ pub fn check_struct_pat_fields(pcx: pat_ctxt, } pub fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span, - expected: ty::t, path: @ast::path, + expected: ty::t, path: @ast::Path, fields: &[ast::field_pat], etc: bool, class_id: ast::def_id, substitutions: &ty::substs) { let fcx = pcx.fcx; @@ -326,7 +326,7 @@ pub fn check_struct_like_enum_variant_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span, expected: ty::t, - path: @ast::path, + path: @ast::Path, fields: &[ast::field_pat], etc: bool, enum_id: ast::def_id, diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 2455201907447..0eb2e5387c3bc 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3211,7 +3211,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_path(fcx: @mut FnCtxt, - pth: @ast::path, + pth: @ast::Path, tpt: ty_param_bounds_and_ty, span: span, node_id: ast::node_id, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ec77b54a85371..4add371a36f82 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -113,7 +113,7 @@ pub struct Lifetime { #[auto_encode] #[auto_decode] #[deriving(Eq)] -pub struct path { +pub struct Path { span: span, global: bool, idents: ~[ident], @@ -301,10 +301,10 @@ pub enum pat_ { // which it is. The resolver determines this, and // records this pattern's node_id in an auxiliary // set (of "pat_idents that refer to nullary enums") - pat_ident(binding_mode, @path, Option<@pat>), - pat_enum(@path, Option<~[@pat]>), /* "none" means a * pattern where + pat_ident(binding_mode, @Path, Option<@pat>), + pat_enum(@Path, Option<~[@pat]>), /* "none" means a * pattern where * we don't bind the fields to names */ - pat_struct(@path, ~[field_pat], bool), + pat_struct(@Path, ~[field_pat], bool), pat_tup(~[@pat]), pat_box(@pat), pat_uniq(@pat), @@ -567,7 +567,7 @@ pub enum expr_ { expr_assign_op(binop, @expr, @expr), expr_field(@expr, ident, ~[@Ty]), expr_index(@expr, @expr), - expr_path(@path), + expr_path(@Path), expr_addr_of(mutability, @expr), expr_break(Option), expr_again(Option), @@ -579,7 +579,7 @@ pub enum expr_ { expr_mac(mac), // A struct literal expression. - expr_struct(@path, ~[field], Option<@expr>), + expr_struct(@Path, ~[field], Option<@expr>), // A vector literal constructed from one repeated element. expr_repeat(@expr /* element */, @expr /* count */, mutability), @@ -697,7 +697,7 @@ pub type mac = spanned; #[auto_decode] #[deriving(Eq)] pub enum mac_ { - mac_invoc_tt(@path,~[token_tree]), // new macro-invocation + mac_invoc_tt(@Path,~[token_tree]), // new macro-invocation } pub type lit = spanned; @@ -894,7 +894,7 @@ pub enum ty_ { ty_closure(@TyClosure), ty_bare_fn(@TyBareFn), ty_tup(~[@Ty]), - ty_path(@path, node_id), + ty_path(@Path, node_id), ty_mac(mac), // ty_infer means the type should be inferred instead of it having been // specified. This should only appear at the "top level" of a type and not @@ -1118,13 +1118,13 @@ pub enum view_path_ { // or just // // foo::bar::baz (with 'baz =' implicitly on the left) - view_path_simple(ident, @path, namespace, node_id), + view_path_simple(ident, @Path, namespace, node_id), // foo::bar::* - view_path_glob(@path, node_id), + view_path_glob(@Path, node_id), // foo::bar::{a,b,c} - view_path_list(@path, ~[path_list_ident], node_id) + view_path_list(@Path, ~[path_list_ident], node_id) } #[auto_encode] @@ -1177,7 +1177,7 @@ pub struct attribute_ { #[auto_decode] #[deriving(Eq)] pub struct trait_ref { - path: @path, + path: @Path, ref_id: node_id, } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index c7227fa17687c..e83a3ef8bad52 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -30,7 +30,7 @@ pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str { } -pub fn path_to_ident(p: @path) -> ident { copy *p.idents.last() } +pub fn path_to_ident(p: @Path) -> ident { copy *p.idents.last() } pub fn local_def(id: node_id) -> def_id { ast::def_id { crate: local_crate, node: id } @@ -223,8 +223,8 @@ pub fn default_block( } } -pub fn ident_to_path(s: span, +i: ident) -> @path { - @ast::path { span: s, +pub fn ident_to_path(s: span, +i: ident) -> @Path { + @ast::Path { span: s, global: false, idents: ~[i], rp: None, diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 97bc89248acf2..f9dadb560e3d0 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -224,7 +224,7 @@ priv impl @ext_ctxt { &self, _span: span, ident: ast::ident, - path: @ast::path, + path: @ast::Path, bounds: @OptVec ) -> ast::TyParam { let bound = ast::TraitTyParamBound(@ast::trait_ref { @@ -248,8 +248,8 @@ priv impl @ext_ctxt { } } - fn path(&self, span: span, +strs: ~[ast::ident]) -> @ast::path { - @ast::path { + fn path(&self, span: span, +strs: ~[ast::ident]) -> @ast::Path { + @ast::Path { span: span, global: false, idents: strs, @@ -258,8 +258,8 @@ priv impl @ext_ctxt { } } - fn path_global(&self, span: span, +strs: ~[ast::ident]) -> @ast::path { - @ast::path { + fn path_global(&self, span: span, +strs: ~[ast::ident]) -> @ast::Path { + @ast::Path { span: span, global: true, idents: strs, @@ -273,8 +273,8 @@ priv impl @ext_ctxt { span: span, +strs: ~[ast::ident], +tps: ~[@ast::Ty] - ) -> @ast::path { - @ast::path { + ) -> @ast::Path { + @ast::Path { span: span, global: false, idents: strs, @@ -288,8 +288,8 @@ priv impl @ext_ctxt { span: span, +strs: ~[ast::ident], +tps: ~[@ast::Ty] - ) -> @ast::path { - @ast::path { + ) -> @ast::Path { + @ast::Path { span: span, global: true, idents: strs, @@ -439,7 +439,7 @@ fn mk_impl( span: span, ident: ast::ident, ty_param: ast::TyParam, - path: @ast::path, + path: @ast::Path, generics: &ast::Generics, f: &fn(@ast::Ty) -> @ast::method ) -> @ast::item { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 43f0c9edcb964..0f84ac4153272 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -63,8 +63,8 @@ pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr) cx.next_id(); // see ast_util::op_expr_callee_id mk_expr(cx, sp, ast::expr_unary(op, e)) } -pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::path { - let p = @ast::path { span: sp, +pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::Path { + let p = @ast::Path { span: sp, global: false, idents: idents, rp: None, @@ -74,15 +74,15 @@ pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::path { pub fn mk_raw_path_(sp: span, +idents: ~[ast::ident], +types: ~[@ast::Ty]) - -> @ast::path { - @ast::path { span: sp, + -> @ast::Path { + @ast::Path { span: sp, global: false, idents: idents, rp: None, types: types } } -pub fn mk_raw_path_global(sp: span, +idents: ~[ast::ident]) -> @ast::path { - @ast::path { span: sp, +pub fn mk_raw_path_global(sp: span, +idents: ~[ast::ident]) -> @ast::Path { + @ast::Path { span: sp, global: true, idents: idents, rp: None, @@ -295,7 +295,7 @@ pub fn mk_pat_ident_with_binding_mode(cx: @ext_ctxt, } pub fn mk_pat_enum(cx: @ext_ctxt, span: span, - path: @ast::path, + path: @ast::Path, +subpats: ~[@ast::pat]) -> @ast::pat { let pat = ast::pat_enum(path, Some(subpats)); @@ -303,7 +303,7 @@ pub fn mk_pat_enum(cx: @ext_ctxt, } pub fn mk_pat_struct(cx: @ext_ctxt, span: span, - path: @ast::path, + path: @ast::Path, +field_pats: ~[ast::field_pat]) -> @ast::pat { let pat = ast::pat_struct(path, field_pats, false); diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 0c3bef56459b5..f4901191b8ac9 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -41,7 +41,7 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) id: cx.next_id(), callee_id: cx.next_id(), node: ast::expr_path( - @ast::path { + @ast::Path { span: sp, global: false, idents: ~[res], diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index ccd9a33757dd5..4337546930ff9 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -185,7 +185,7 @@ pub fn create_derived_impl(cx: @ext_ctxt, }); // Create the reference to the trait. - let trait_path = ast::path { + let trait_path = ast::Path { span: span, global: true, idents: trait_path.map(|x| *x), diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 1d1a101d61f1d..5eea58b89b1c6 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -34,16 +34,16 @@ mod syntax { pub use parse; } -pub fn path(+ids: ~[ident], span: span) -> @ast::path { - @ast::path { span: span, +pub fn path(+ids: ~[ident], span: span) -> @ast::Path { + @ast::Path { span: span, global: false, idents: ids, rp: None, types: ~[] } } -pub fn path_global(+ids: ~[ident], span: span) -> @ast::path { - @ast::path { span: span, +pub fn path_global(+ids: ~[ident], span: span) -> @ast::Path { + @ast::Path { span: span, global: true, idents: ids, rp: None, @@ -51,20 +51,20 @@ pub fn path_global(+ids: ~[ident], span: span) -> @ast::path { } pub trait append_types { - fn add_ty(&self, ty: @ast::Ty) -> @ast::path; - fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::path; + fn add_ty(&self, ty: @ast::Ty) -> @ast::Path; + fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::Path; } -impl append_types for @ast::path { - fn add_ty(&self, ty: @ast::Ty) -> @ast::path { - @ast::path { +impl append_types for @ast::Path { + fn add_ty(&self, ty: @ast::Ty) -> @ast::Path { + @ast::Path { types: vec::append_one(copy self.types, ty), .. copy **self } } - fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::path { - @ast::path { + fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::Path { + @ast::Path { types: vec::append(copy self.types, tys), .. copy **self } @@ -108,7 +108,7 @@ pub trait ext_ctxt_ast_builder { span: span, +struct_def: ast::struct_def) -> @ast::item; fn struct_expr(&self, - path: @ast::path, + path: @ast::Path, +fields: ~[ast::field]) -> @ast::expr; fn variant(&self, name: ident, @@ -118,7 +118,7 @@ pub trait ext_ctxt_ast_builder { name: ident, span: span, +items: ~[@ast::item]) -> @ast::item; - fn ty_path_ast_builder(&self, path: @ast::path) -> @ast::Ty; + fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty; fn item_ty_poly(&self, name: ident, span: span, @@ -328,7 +328,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { self.item(name, span, ast::item_struct(@struct_def, generics)) } - fn struct_expr(&self, path: @ast::path, + fn struct_expr(&self, path: @ast::Path, +fields: ~[ast::field]) -> @ast::expr { @ast::expr { id: self.next_id(), @@ -397,7 +397,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { ) } - fn ty_path_ast_builder(&self, path: @ast::path) -> @ast::Ty { + fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty { @ast::Ty { id: self.next_id(), node: ast::ty_path(path, self.next_id()), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 5aa51c262e174..768dba2141250 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -36,7 +36,7 @@ pub trait ast_fold { fn fold_foreign_mod(@self, &foreign_mod) -> foreign_mod; fn fold_variant(@self, &variant) -> variant; fn fold_ident(@self, ident) -> ident; - fn fold_path(@self, @path) -> @path; + fn fold_path(@self, @Path) -> @Path; fn fold_local(@self, @local) -> @local; fn map_exprs(@self, @fn(@expr) -> @expr, &[@expr]) -> ~[@expr]; fn new_id(@self, node_id) -> node_id; @@ -65,7 +65,7 @@ pub struct AstFoldFns { fold_foreign_mod: @fn(&foreign_mod, @ast_fold) -> foreign_mod, fold_variant: @fn(&variant_, span, @ast_fold) -> (variant_, span), fold_ident: @fn(ident, @ast_fold) -> ident, - fold_path: @fn(@path, @ast_fold) -> path, + fold_path: @fn(@Path, @ast_fold) -> Path, fold_local: @fn(&local_, span, @ast_fold) -> (local_, span), map_exprs: @fn(@fn(@expr) -> @expr, &[@expr]) -> ~[@expr], new_id: @fn(node_id) -> node_id, @@ -702,8 +702,8 @@ fn noop_fold_ident(i: ident, _fld: @ast_fold) -> ident { /* FIXME (#2543) */ copy i } -fn noop_fold_path(p: @path, fld: @ast_fold) -> path { - ast::path { +fn noop_fold_path(p: @Path, fld: @ast_fold) -> Path { + ast::Path { span: fld.new_span(p.span), global: p.global, idents: p.idents.map(|x| fld.fold_ident(*x)), @@ -851,7 +851,7 @@ impl ast_fold for AstFoldFns { fn fold_ident(@self, x: ident) -> ident { (self.fold_ident)(x, self as @ast_fold) } - fn fold_path(@self, x: @path) -> @path { + fn fold_path(@self, x: @Path) -> @Path { @(self.fold_path)(x, self as @ast_fold) } fn fold_local(@self, x: @local) -> @local { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3a3597828cd24..ca6fab62e2922 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -897,7 +897,7 @@ pub impl Parser { // parse a path that doesn't have type parameters attached fn parse_path_without_tps(&self) - -> @ast::path { + -> @ast::Path { maybe_whole!(self, nt_path); let lo = self.span.lo; let global = self.eat(&token::MOD_SEP); @@ -917,7 +917,7 @@ pub impl Parser { break; } } - @ast::path { span: mk_sp(lo, self.last_span.hi), + @ast::Path { span: mk_sp(lo, self.last_span.hi), global: global, idents: ids, rp: None, @@ -927,7 +927,7 @@ pub impl Parser { // parse a path optionally with type parameters. If 'colons' // is true, then type parameters must be preceded by colons, // as in a::t:: - fn parse_path_with_tps(&self, colons: bool) -> @ast::path { + fn parse_path_with_tps(&self, colons: bool) -> @ast::Path { debug!("parse_path_with_tps(colons=%b)", colons); maybe_whole!(self, nt_path); @@ -982,7 +982,7 @@ pub impl Parser { } }; - @ast::path { span: mk_sp(lo, hi), + @ast::Path { span: mk_sp(lo, hi), rp: rp, types: tps, .. copy *path } @@ -4215,7 +4215,7 @@ pub impl Parser { let id = self.parse_ident(); path.push(id); } - let path = @ast::path { span: mk_sp(lo, self.span.hi), + let path = @ast::Path { span: mk_sp(lo, self.span.hi), global: false, idents: path, rp: None, @@ -4244,7 +4244,7 @@ pub impl Parser { seq_sep_trailing_allowed(token::COMMA), |p| p.parse_path_list_ident() ); - let path = @ast::path { span: mk_sp(lo, self.span.hi), + let path = @ast::Path { span: mk_sp(lo, self.span.hi), global: false, idents: path, rp: None, @@ -4256,7 +4256,7 @@ pub impl Parser { // foo::bar::* token::BINOP(token::STAR) => { self.bump(); - let path = @ast::path { span: mk_sp(lo, self.span.hi), + let path = @ast::Path { span: mk_sp(lo, self.span.hi), global: false, idents: path, rp: None, @@ -4272,7 +4272,7 @@ pub impl Parser { _ => () } let last = path[vec::len(path) - 1u]; - let path = @ast::path { span: mk_sp(lo, self.span.hi), + let path = @ast::Path { span: mk_sp(lo, self.span.hi), global: false, idents: path, rp: None, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 713a6e8947554..54b2ad8514781 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -113,7 +113,7 @@ pub enum nonterminal { nt_expr(@ast::expr), nt_ty( @ast::Ty), nt_ident(ast::ident, bool), - nt_path(@ast::path), + nt_path(@ast::Path), nt_tt( @ast::token_tree), //needs @ed to break a circularity nt_matchers(~[ast::matcher]) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 20fc99baf2179..fa1b97275660c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -178,7 +178,7 @@ pub fn generics_to_str(generics: &ast::Generics, to_str(generics, print_generics, intr) } -pub fn path_to_str(&&p: @ast::path, intr: @ident_interner) -> ~str { +pub fn path_to_str(&&p: @ast::Path, intr: @ident_interner) -> ~str { to_str(p, |a,b| print_path(a, b, false), intr) } @@ -1486,7 +1486,7 @@ pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) { print_expr(s, coll); } -pub fn print_path(s: @ps, &&path: @ast::path, colons_before_params: bool) { +pub fn print_path(s: @ps, &&path: @ast::Path, colons_before_params: bool) { maybe_print_comment(s, path.span.lo); if path.global { word(s.s, ~"::"); } let mut first = true; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b20c5eeee1f04..c4c187bc4c7c4 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -265,7 +265,7 @@ pub fn visit_ty(t: @Ty, e: E, v: vt) { } } -pub fn visit_path(p: @path, e: E, v: vt) { +pub fn visit_path(p: @Path, e: E, v: vt) { for p.types.each |tp| { (v.visit_ty)(*tp, e, v); } } From 27700472b98862978cd0bd291bbb413e30102f38 Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 1 Apr 2013 11:37:30 -0700 Subject: [PATCH 110/403] removed eval.rs: dead code @brson confirms that eval.rs is now dead code --- src/libsyntax/parse/eval.rs | 174 ------------------------------------ 1 file changed, 174 deletions(-) delete mode 100644 src/libsyntax/parse/eval.rs diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs deleted file mode 100644 index 5d44db084d600..0000000000000 --- a/src/libsyntax/parse/eval.rs +++ /dev/null @@ -1,174 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use parser::Parser; -use attr::parser_attr; -use codemap::{span, mk_sp}; - -type ctx = - @{sess: parse::parse_sess, - cfg: ast::crate_cfg}; - -fn eval_crate_directives(cx: ctx, - cdirs: ~[@ast::crate_directive], - prefix: &Path, - view_items: &mut~[@ast::view_item], - items: &mut~[@ast::item]) { - for cdirs.each |sub_cdir| { - eval_crate_directive(cx, *sub_cdir, prefix, view_items, items); - } -} - -pub fn eval_crate_directives_to_mod(cx: ctx, cdirs: ~[@ast::crate_directive], - prefix: &Path, suffix: &Option) - -> (ast::_mod, ~[ast::attribute]) { - let (cview_items, citems, cattrs) - = parse_companion_mod(cx, prefix, suffix); - let mut view_items: ~[@ast::view_item] = ~[]; - let mut items: ~[@ast::item] = ~[]; - eval_crate_directives(cx, cdirs, prefix, &mut view_items, &mut items); - return ({view_items: vec::append(view_items, cview_items), - items: vec::append(items, citems)}, - cattrs); -} - -/* -The 'companion mod'. So .rc crates and directory mod crate directives define -modules but not a .rs file to fill those mods with stuff. The companion mod is -a convention for location a .rs file to go with them. For .rc files the -companion mod is a .rs file with the same name; for directory mods the -companion mod is a .rs file with the same name as the directory. - -We build the path to the companion mod by combining the prefix and the -optional suffix then adding the .rs extension. -*/ -fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &Option) - -> (~[@ast::view_item], ~[@ast::item], ~[ast::attribute]) { - - fn companion_file(prefix: &Path, suffix: &Option) -> Path { - return match *suffix { - option::Some(s) => prefix.push_many(s.components), - option::None => copy *prefix - }.with_filetype("rs"); - } - - fn file_exists(path: &Path) -> bool { - // Crude, but there's no lib function for this and I'm not - // up to writing it just now - match io::file_reader(path) { - result::Ok(_) => true, - result::Err(_) => false - } - } - - let modpath = &companion_file(prefix, suffix); - if file_exists(modpath) { - debug!("found companion mod"); - // XXX: Using a dummy span, but this code will go away soon - let p0 = new_sub_parser_from_file(cx.sess, cx.cfg, - modpath, - codemap::dummy_sp()); - let (inner, next) = p0.parse_inner_attrs_and_next(); - let m0 = p0.parse_mod_items(token::EOF, next); - return (m0.view_items, m0.items, inner); - } else { - return (~[], ~[], ~[]); - } -} - -fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str { - match ::attr::first_attr_value_str_by_name(attrs, ~"path") { - Some(d) => d, - None => default - } -} - -pub fn eval_src_mod(cx: ctx, prefix: &Path, - outer_attrs: ~[ast::attribute], - id: ast::ident, sp: span) - -> (ast::item_, ~[ast::attribute]) { - let file_path = Path(cdir_path_opt( - cx.sess.interner.get(id) + ~".rs", outer_attrs)); - eval_src_mod_from_path(cx, prefix, &file_path, outer_attrs, sp) -} - -pub fn eval_src_mod_from_path(cx: ctx, prefix: &Path, path: &Path, - outer_attrs: ~[ast::attribute], - sp: span) - -> (ast::item_, ~[ast::attribute]) { - let full_path = if path.is_absolute { - copy *path - } else { - prefix.push_many(path.components) - }; - let p0 = - new_sub_parser_from_file(cx.sess, cx.cfg, - &full_path, sp); - let (inner, next) = p0.parse_inner_attrs_and_next(); - let mod_attrs = vec::append(outer_attrs, inner); - let first_item_outer_attrs = next; - let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs); - return (ast::item_mod(m0), mod_attrs); -} - -// XXX: Duplicated from parser.rs -fn mk_item(ctx: ctx, lo: BytePos, hi: BytePos, +ident: ast::ident, - +node: ast::item_, vis: ast::visibility, - +attrs: ~[ast::attribute]) -> @ast::item { - return @{ident: ident, - attrs: attrs, - id: next_node_id(ctx.sess), - node: node, - vis: vis, - span: mk_sp(lo, hi)}; -} - -fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path, - view_items: &mut ~[@ast::view_item], - items: &mut ~[@ast::item]) { - match cdir.node { - ast::cdir_src_mod(vis, id, attrs) => { - let (m, mod_attrs) = eval_src_mod(cx, prefix, attrs, id, cdir.span); - let i = mk_item(cx, cdir.span.lo, cdir.span.hi, - /* FIXME (#2543) */ copy id, - m, vis, mod_attrs); - items.push(i); - } - ast::cdir_dir_mod(vis, id, cdirs, attrs) => { - let path = Path(cdir_path_opt(*cx.sess.interner.get(id), attrs)); - let full_path = if path.is_absolute { - copy path - } else { - prefix.push_many(path.components) - }; - let (m0, a0) = eval_crate_directives_to_mod( - cx, cdirs, &full_path, &None); - let i = - @{ident: /* FIXME (#2543) */ copy id, - attrs: vec::append(attrs, a0), - id: cx.sess.next_id, - node: ast::item_mod(m0), - vis: vis, - span: cdir.span}; - cx.sess.next_id += 1; - items.push(i); - } - ast::cdir_view_item(vi) => view_items.push(vi), - } -} -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: -// From 09bcd3837c6ae92ef91cb6a63f1b927a465ea89c Mon Sep 17 00:00:00 2001 From: John Clements Date: Thu, 28 Mar 2013 16:56:56 -0700 Subject: [PATCH 111/403] unneccessary since tjc's commit 78ec6fe30cf2b, fixing #2804 --- src/libsyntax/parse/parser.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ca6fab62e2922..b57203765b24f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1629,7 +1629,6 @@ pub impl Parser { self.bump(); let e = self.parse_prefix_expr(); hi = e.span.hi; - self.get_id(); // see ast_util::op_expr_callee_id ex = expr_unary(not, e); } token::BINOP(b) => { @@ -1638,7 +1637,6 @@ pub impl Parser { self.bump(); let e = self.parse_prefix_expr(); hi = e.span.hi; - self.get_id(); // see ast_util::op_expr_callee_id ex = expr_unary(neg, e); } token::STAR => { @@ -1738,7 +1736,6 @@ pub impl Parser { self.bump(); let expr = self.parse_prefix_expr(); let rhs = self.parse_more_binops(expr, cur_prec); - self.get_id(); // see ast_util::op_expr_callee_id let bin = self.mk_expr(lhs.span.lo, rhs.span.hi, expr_binary(cur_op, lhs, rhs)); self.parse_more_binops(bin, min_prec) @@ -1789,7 +1786,6 @@ pub impl Parser { token::SHL => aop = shl, token::SHR => aop = shr } - self.get_id(); // see ast_util::op_expr_callee_id self.mk_expr(lo, rhs.span.hi, expr_assign_op(aop, lhs, rhs)) } From 05bbaf9e9f72b69804aed6ba37bdbe861203defc Mon Sep 17 00:00:00 2001 From: John Clements Date: Tue, 2 Apr 2013 16:40:20 -0700 Subject: [PATCH 112/403] removed test referring to WONTFIX bug #2443 --- src/test/run-pass/by-val-and-by-move.rs | 26 ------------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/test/run-pass/by-val-and-by-move.rs diff --git a/src/test/run-pass/by-val-and-by-move.rs b/src/test/run-pass/by-val-and-by-move.rs deleted file mode 100644 index 47d2f9e1df080..0000000000000 --- a/src/test/run-pass/by-val-and-by-move.rs +++ /dev/null @@ -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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test #2443 -// exec-env:RUST_POISON_ON_FREE - -fn it_takes_two(x: @int, -y: @int) -> int { - free(y); - debug!("about to deref"); - *x -} - -fn free(-_t: T) { -} - -pub fn main() { - let z = @3; - assert!(3 == it_takes_two(z, z)); -} From 9deb2f2dfabd0ad164eedf84fe7e91b0b5dabf66 Mon Sep 17 00:00:00 2001 From: John Clements Date: Fri, 29 Mar 2013 10:35:23 -0700 Subject: [PATCH 113/403] libsyntax comments only --- src/libsyntax/codemap.rs | 4 +++ src/libsyntax/parse/parser.rs | 59 +++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index fc08073686d0d..0ed371d9c9afe 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -206,8 +206,12 @@ pub struct FileLines lines: ~[uint] } +// represents the origin of a file: pub enum FileSubstr { + // indicates that this is a normal standalone file: pub FssNone, + // indicates that this "file" is actually a substring + // of another file that appears earlier in the codemap pub FssInternal(span), } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b57203765b24f..fb3e8a5ded5a8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -705,6 +705,7 @@ pub impl Parser { @Ty {id: self.get_id(), node: t, span: sp} } + // parse the type following a @ or a ~ fn parse_box_or_uniq_pointee( &self, sigil: ast::Sigil, @@ -988,12 +989,8 @@ pub impl Parser { .. copy *path } } + /// parses 0 or 1 lifetime fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> { - /*! - * - * Parses 0 or 1 lifetime. - */ - match *self.token { token::LIFETIME(*) => { Some(@self.parse_lifetime()) @@ -1022,12 +1019,9 @@ pub impl Parser { } } + /// Parses a single lifetime + // matches lifetime = ( LIFETIME ) | ( IDENT / ) fn parse_lifetime(&self) -> ast::Lifetime { - /*! - * - * Parses a single lifetime. - */ - match *self.token { token::LIFETIME(i) => { let span = copy self.span; @@ -1147,6 +1141,9 @@ pub impl Parser { } } + // at the bottom (top?) of the precedence hierarchy, + // parse things like parenthesized exprs, + // macros, return, etc. fn parse_bottom_expr(&self) -> @expr { maybe_whole_expr!(self); @@ -1350,6 +1347,7 @@ pub impl Parser { return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk)); } + // parse a.b or a(13) or just a fn parse_dot_or_call_expr(&self) -> @expr { let b = self.parse_bottom_expr(); self.parse_dot_or_call_expr_with(b) @@ -1618,7 +1616,7 @@ pub impl Parser { return spanned(lo, self.span.hi, m); } - + // parse a prefix-operator expr fn parse_prefix_expr(&self) -> @expr { let lo = self.span.lo; let mut hi; @@ -2552,11 +2550,14 @@ pub impl Parser { } fn parse_block(&self) -> blk { + // disallow inner attrs: let (attrs, blk) = self.parse_inner_attrs_and_block(false); assert!(vec::is_empty(attrs)); return blk; } + // I claim the existence of the 'parse_attrs' flag strongly + // suggests a name-change or refactoring for this function. fn parse_inner_attrs_and_block(&self, parse_attrs: bool) -> (~[attribute], blk) { @@ -2597,6 +2598,7 @@ pub impl Parser { self.parse_block_tail_(lo, s, ~[]) } + // parse the rest of a block expression or function body fn parse_block_tail_(&self, lo: BytePos, s: blk_check_mode, +first_item_attrs: ~[attribute]) -> blk { let mut stmts = ~[]; @@ -2793,6 +2795,10 @@ pub impl Parser { ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds } } + // parse a set of optional generic type parameter declarations + // matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > ) + // | ( < lifetimes , typaramseq ( , )? > ) + // where typaramseq = ( typaram ) | ( typaram , typaramseq ) fn parse_generics(&self) -> ast::Generics { if self.eat(&token::LT) { let lifetimes = self.parse_lifetimes(); @@ -2805,6 +2811,7 @@ pub impl Parser { } } + // parse a generic use site fn parse_generic_values( &self) -> (OptVec, ~[@Ty]) { @@ -3095,6 +3102,7 @@ pub impl Parser { } } + // parse trait Foo { ... } fn parse_item_trait(&self) -> item_info { let ident = self.parse_ident(); self.parse_region_param(); @@ -3173,6 +3181,7 @@ pub impl Parser { (ident, item_impl(generics, opt_trait, ty, meths), None) } + // parse a::B<~str,int> fn parse_trait_ref(&self) -> @trait_ref { @ast::trait_ref { path: self.parse_path_with_tps(false), @@ -3180,6 +3189,7 @@ pub impl Parser { } } + // parse B + C<~str,int> + D fn parse_trait_ref_list(&self, ket: &token::Token) -> ~[@trait_ref] { self.parse_seq_to_before_end( ket, @@ -3188,6 +3198,7 @@ pub impl Parser { ) } + // parse struct Foo { ... } fn parse_item_struct(&self) -> item_info { let class_name = self.parse_ident(); self.parse_region_param(); @@ -3437,6 +3448,7 @@ pub impl Parser { (id, item_const(ty, e), None) } + // parse a mod { ...} item fn parse_item_mod(&self, outer_attrs: ~[ast::attribute]) -> item_info { let id_span = *self.span; let id = self.parse_ident(); @@ -3693,7 +3705,7 @@ pub impl Parser { } }; - // extern mod { ... } + // extern mod foo { ... } or extern { ... } if items_allowed && self.eat(&token::LBRACE) { let abis = opt_abis.get_or_default(AbiSet::C()); @@ -3728,6 +3740,7 @@ pub impl Parser { (lo, id) } + // parse type Foo = Bar; fn parse_item_type(&self) -> item_info { let (_, ident) = self.parse_type_decl(); self.parse_region_param(); @@ -3738,6 +3751,7 @@ pub impl Parser { (ident, item_ty(ty, tps), None) } + // parse obsolete region parameter fn parse_region_param(&self) { if self.eat(&token::BINOP(token::SLASH)) { self.obsolete(*self.last_span, ObsoleteLifetimeNotation); @@ -3855,6 +3869,7 @@ pub impl Parser { let generics = self.parse_generics(); // Newtype syntax if *self.token == token::EQ { + // enum x = ty; self.bump(); let ty = self.parse_ty(false); self.expect(&token::SEMI); @@ -3879,6 +3894,7 @@ pub impl Parser { None ); } + // enum X { ... } self.expect(&token::LBRACE); let enum_definition = self.parse_enum_def(&generics); @@ -3982,7 +3998,7 @@ pub impl Parser { (self.is_keyword(&~"const") || (self.is_keyword(&~"static") && !self.token_is_keyword(&~"fn", &self.look_ahead(1)))) { - // CONST ITEM + // CONST / STATIC ITEM if self.is_keyword(&~"const") { self.obsolete(*self.span, ObsoleteConstItem); } @@ -3998,10 +4014,9 @@ pub impl Parser { let item = self.parse_item_foreign_const(visibility, attrs); return iovi_foreign_item(item); } - if items_allowed && - // FUNCTION ITEM (not sure about lookahead condition...) - self.is_keyword(&~"fn") && + if items_allowed && self.is_keyword(&~"fn") && !self.fn_expr_lookahead(self.look_ahead(1u)) { + // FUNCTION ITEM self.bump(); let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn, AbiSet::Rust()); @@ -4010,7 +4025,7 @@ pub impl Parser { maybe_append(attrs, extra_attrs))); } if items_allowed && self.eat_keyword(&~"pure") { - // PURE FUNCTION ITEM + // PURE FUNCTION ITEM (obsolete) self.obsolete(*self.last_span, ObsoletePurity); self.expect_keyword(&~"fn"); let (ident, item_, extra_attrs) = @@ -4188,6 +4203,12 @@ pub impl Parser { return view_item_use(self.parse_view_paths()); } + + // matches view_path : MOD? IDENT EQ non_global_path + // | MOD? non_global_path MOD_SEP LBRACE RBRACE + // | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE + // | MOD? non_global_path MOD_SEP STAR + // | MOD? non_global_path fn parse_view_path(&self) -> @view_path { let lo = self.span.lo; @@ -4277,6 +4298,7 @@ pub impl Parser { view_path_simple(last, path, namespace, self.get_id())); } + // matches view_paths = view_path | view_path , view_paths fn parse_view_paths(&self) -> ~[@view_path] { let mut vp = ~[self.parse_view_path()]; while *self.token == token::COMMA { @@ -4326,6 +4348,9 @@ pub impl Parser { // Parses a sequence of items. Stops when it finds program // text that can't be parsed as an item + // - mod_items uses VIEW_ITEMS_AND_ITEMS_ALLOWED + // - block_tail_ uses IMPORTS_AND_ITEMS_ALLOWED + // - foreign_mod_items uses FOREIGN_ITEMS_ALLOWED fn parse_items_and_view_items(&self, +first_item_attrs: ~[attribute], mode: view_item_parse_mode, macros_allowed: bool) From 3c08be9b48f5a4413a35728a0c392df3b0bed785 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Fri, 29 Mar 2013 17:14:08 -0400 Subject: [PATCH 114/403] Add debug info for boxes --- src/librustc/middle/trans/debuginfo.rs | 40 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 8c40142335e38..cf8ecacfb8b37 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -542,13 +542,23 @@ fn create_tuple(cx: @CrateContext, t: ty::t, elements: &[ty::t], span: span) return mdval; } -fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t, +// returns (void* type as a ValueRef, size in bytes, align in bytes) +fn voidptr() -> (ValueRef, int, int) { + let null = ptr::null(); + let size = sys::size_of::() as int; + let align = sys::min_align_of::() as int; + let vp = create_derived_type(PointerTypeTag, null, ~"", 0, + size, align, 0, null); + return (vp, size, align); +} + +fn create_boxed_type(cx: @CrateContext, contents: ty::t, span: span, boxed: @Metadata) -> @Metadata { //let tg = StructureTypeTag; /*let cache = cx.llmetadata; match cached_metadata::<@Metadata>( - cache, tg, {|md| ty::hash_ty(outer) == ty::hash_ty(md.data.hash)}) { + cache, tg, {|md| ty::hash_ty(contents) == ty::hash_ty(md.data.hash)}) { option::Some(md) { return md; } option::None {} }*/ @@ -557,18 +567,23 @@ fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t, //let cu_node = create_compile_unit_metadata(cx, fname); let uint_t = ty::mk_uint(cx.tcx); let refcount_type = create_basic_type(cx, uint_t, span); - let scx = create_structure(file_node, - @/*bad*/ copy ty_to_str(cx.tcx, outer), 0); + let name = ty_to_str(cx.tcx, contents); + let scx = create_structure(file_node, @fmt!("box<%s>", name), 0); add_member(scx, ~"refcnt", 0, sys::size_of::() as int, sys::min_align_of::() as int, refcount_type.node); - add_member(scx, ~"boxed", 0, 8, //XXX member_size_and_align(??) - 8, //XXX just a guess - boxed.node); + // the tydesc and other pointers should be irrelevant to the + // debugger, so treat them as void* types + let (vp, vpsize, vpalign) = voidptr(); + add_member(scx, ~"tydesc", 0, vpsize, vpalign, vp); + add_member(scx, ~"prev", 0, vpsize, vpalign, vp); + add_member(scx, ~"next", 0, vpsize, vpalign, vp); + let (size, align) = size_and_align_of(cx, contents); + add_member(scx, ~"boxed", 0, size, align, boxed.node); let llnode = finish_structure(scx); let mdval = @Metadata { node: llnode, data: TyDescMetadata { - hash: ty::type_id(outer) + hash: ty::type_id(contents) } }; //update_cache(cache, tg, tydesc_metadata(mdval)); @@ -655,11 +670,10 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) ty::ty_enum(_did, ref _substs) => { cx.sess.span_bug(span, ~"debuginfo for enum NYI") } - ty::ty_box(ref _mt) => { - cx.sess.span_bug(span, ~"debuginfo for box NYI") - }, - ty::ty_uniq(ref _mt) => { - cx.sess.span_bug(span, ~"debuginfo for uniq NYI") + ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => { + let boxed = create_ty(cx, mt.ty, span); + let box_md = create_boxed_type(cx, mt.ty, span, boxed); + create_pointer_type(cx, t, span, box_md) }, ty::ty_evec(ref _mt, ref _vstore) => { cx.sess.span_bug(span, ~"debuginfo for evec NYI") From 917d5ab34eabab8e2f39e1c0815d67b583e3d422 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Tue, 2 Apr 2013 16:08:34 -0400 Subject: [PATCH 115/403] Add debug info for vectors --- src/librustc/middle/trans/debuginfo.rs | 117 +++++++++++++++++++++---- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index cf8ecacfb8b37..8daf37260ac26 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -565,8 +565,8 @@ fn create_boxed_type(cx: @CrateContext, contents: ty::t, let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); //let cu_node = create_compile_unit_metadata(cx, fname); - let uint_t = ty::mk_uint(cx.tcx); - let refcount_type = create_basic_type(cx, uint_t, span); + let int_t = ty::mk_int(cx.tcx); + let refcount_type = create_basic_type(cx, int_t, span); let name = ty_to_str(cx.tcx, contents); let scx = create_structure(file_node, @fmt!("box<%s>", name), 0); add_member(scx, ~"refcnt", 0, sys::size_of::() as int, @@ -621,33 +621,97 @@ fn create_composite_type(type_tag: int, name: &str, file: ValueRef, return llmdnode(lldata); } -fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, - vec_ty_span: codemap::span) -> @Metadata { +fn create_fixed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, + len: int, span: span) -> @Metadata { + let t_md = create_ty(cx, elem_t, span); + let fname = filename_from_span(cx, span); + let file_node = create_file(cx, fname); + let (size, align) = size_and_align_of(cx, elem_t); + let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(len - 1)]); + let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); + let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0, + size * len, align, 0, Some(t_md.node), + Some(~[subrange])); + @Metadata { + node: array, + data: TyDescMetadata { + hash: ty::type_id(vec_t) + } + } +} + +fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, + vec_ty_span: codemap::span) + -> @Metadata { let fname = filename_from_span(cx, vec_ty_span); let file_node = create_file(cx, fname); let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); - let scx = create_structure(file_node, + let vec_scx = create_structure(file_node, @/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0); let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span); - add_member(scx, ~"fill", 0, sys::size_of::() as int, + add_member(vec_scx, ~"fill", 0, sys::size_of::() as int, sys::min_align_of::() as int, size_t_type.node); - add_member(scx, ~"alloc", 0, sys::size_of::() as int, + add_member(vec_scx, ~"alloc", 0, sys::size_of::() as int, sys::min_align_of::() as int, size_t_type.node); let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]); let (arr_size, arr_align) = size_and_align_of(cx, elem_t); - let data_ptr = create_composite_type(ArrayTypeTag, ~"", file_node.node, 0, + let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); + let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0, arr_size, arr_align, 0, Some(elem_ty_md.node), Some(~[subrange])); - add_member(scx, ~"data", 0, 0, // clang says the size should be 0 + add_member(vec_scx, ~"data", 0, 0, // clang says the size should be 0 sys::min_align_of::() as int, data_ptr); + let llnode = finish_structure(vec_scx); + let vec_md = @Metadata { + node: llnode, + data: TyDescMetadata { + hash: ty::type_id(vec_t) + } + }; + + let box_scx = create_structure(file_node, @fmt!("box<%s>", name), 0); + let int_t = ty::mk_int(cx.tcx); + let refcount_type = create_basic_type(cx, int_t, vec_ty_span); + add_member(box_scx, ~"refcnt", 0, sys::size_of::() as int, + sys::min_align_of::() as int, refcount_type.node); + let (vp, vpsize, vpalign) = voidptr(); + add_member(box_scx, ~"tydesc", 0, vpsize, vpalign, vp); + add_member(box_scx, ~"prev", 0, vpsize, vpalign, vp); + add_member(box_scx, ~"next", 0, vpsize, vpalign, vp); + let size = 2 * sys::size_of::() as int; + let align = sys::min_align_of::() as int; + add_member(box_scx, ~"boxed", 0, size, align, vec_md.node); + let llnode = finish_structure(box_scx); + let mdval = @Metadata { + node: llnode, + data: TyDescMetadata { + hash: ty::type_id(elem_t) + } + }; + return mdval; +} + +fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) + -> @Metadata { + let fname = filename_from_span(cx, span); + let file_node = create_file(cx, fname); + let elem_ty_md = create_ty(cx, elem_t, span); + let uint_type = create_basic_type(cx, ty::mk_uint(cx.tcx), span); + let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md); + let scx = create_structure(file_node, @ty_to_str(cx.tcx, vec_t), 0); + let (_, ptr_size, ptr_align) = voidptr(); + add_member(scx, ~"vec", 0, ptr_size, ptr_align, elem_ptr.node); + add_member(scx, ~"length", 0, sys::size_of::() as int, + sys::min_align_of::() as int, uint_type.node); let llnode = finish_structure(scx); - @Metadata { + let mdval = @Metadata { node: llnode, data: TyDescMetadata { hash: ty::type_id(vec_t) } - } + }; + return mdval; } fn create_ty(cx: @CrateContext, t: ty::t, span: span) @@ -664,8 +728,20 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) match sty { ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) => create_basic_type(cx, t, span), - ty::ty_estr(_vstore) => { - cx.sess.span_bug(span, ~"debuginfo for estr NYI") + ty::ty_estr(ref vstore) => { + let i8_t = ty::mk_i8(cx.tcx); + match *vstore { + ty::vstore_fixed(len) => { + create_fixed_vec(cx, t, i8_t, len as int + 1, span) + }, + ty::vstore_uniq | ty::vstore_box => { + let box_md = create_boxed_vec(cx, t, i8_t, span); + create_pointer_type(cx, t, span, box_md) + } + ty::vstore_slice(_region) => { + create_vec_slice(cx, t, i8_t, span) + } + } }, ty::ty_enum(_did, ref _substs) => { cx.sess.span_bug(span, ~"debuginfo for enum NYI") @@ -675,8 +751,19 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) let box_md = create_boxed_type(cx, mt.ty, span, boxed); create_pointer_type(cx, t, span, box_md) }, - ty::ty_evec(ref _mt, ref _vstore) => { - cx.sess.span_bug(span, ~"debuginfo for evec NYI") + ty::ty_evec(ref mt, ref vstore) => { + match *vstore { + ty::vstore_fixed(len) => { + create_fixed_vec(cx, t, mt.ty, len as int, span) + }, + ty::vstore_uniq | ty::vstore_box => { + let box_md = create_boxed_vec(cx, t, mt.ty, span); + create_pointer_type(cx, t, span, box_md) + }, + ty::vstore_slice(_region) => { + create_vec_slice(cx, t, mt.ty, span) + } + } }, ty::ty_ptr(ref mt) => { let pointee = create_ty(cx, mt.ty, span); From cf22d749eb9717e1e5befa727db5a9f7c47e8f48 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Mon, 8 Apr 2013 23:08:10 -0400 Subject: [PATCH 116/403] Add debug info for bare_fn type --- src/librustc/middle/trans/debuginfo.rs | 29 +++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 8daf37260ac26..c573529fbc23c 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -420,7 +420,8 @@ fn create_pointer_type(cx: @CrateContext, t: ty::t, span: span, let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); //let cu_node = create_compile_unit(cx, fname); - let llnode = create_derived_type(tg, file_node.node, ~"", 0, size * 8, + let name = ty_to_str(cx.tcx, t); + let llnode = create_derived_type(tg, file_node.node, name, 0, size * 8, align * 8, 0, pointee.node); let mdval = @Metadata { node: llnode, @@ -714,6 +715,26 @@ fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) return mdval; } +fn create_fn_ty(cx: @CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t, + span: span) -> @Metadata { + let fname = filename_from_span(cx, span); + let file_node = create_file(cx, fname); + let (vp, _, _) = voidptr(); + let output_md = create_ty(cx, output, span); + let output_ptr_md = create_pointer_type(cx, output, span, output_md); + let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span).node }; + let members = ~[output_ptr_md.node, vp] + inputs_vals; + let llnode = create_composite_type(SubroutineTag, ~"", file_node.node, + 0, 0, 0, 0, None, Some(members)); + let mdval = @Metadata { + node: llnode, + data: TyDescMetadata { + hash: ty::type_id(fn_ty) + } + }; + return mdval; +} + fn create_ty(cx: @CrateContext, t: ty::t, span: span) -> @Metadata { debug!("create_ty: %?", ty::get(t)); @@ -772,8 +793,10 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) ty::ty_rptr(ref _region, ref _mt) => { cx.sess.span_bug(span, ~"debuginfo for rptr NYI") }, - ty::ty_bare_fn(ref _barefnty) => { - cx.sess.span_bug(span, ~"debuginfo for bare_fn NYI") + ty::ty_bare_fn(ref barefnty) => { + let inputs = do barefnty.sig.inputs.map |a| { a.ty }; + let output = barefnty.sig.output; + create_fn_ty(cx, t, inputs, output, span) }, ty::ty_closure(ref _closurety) => { cx.sess.span_bug(span, ~"debuginfo for closure NYI") From 10d930d51ea6a00349c08b53ecf6ffb1ee514219 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Mon, 8 Apr 2013 23:13:00 -0400 Subject: [PATCH 117/403] Prevent debug info generation of zero-span nodes If a node has a (0, 0) span, it was not in the source, so debug symbols should not be generated for it. --- src/librustc/middle/trans/base.rs | 15 ++++++++++++--- src/librustc/middle/trans/debuginfo.rs | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 4faff086098b0..b8a14cb329b04 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -131,6 +131,13 @@ impl get_insn_ctxt for fn_ctxt { } } +fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool { + match fcx.span { + None => true, + Some(span) => *span.lo != 0 || *span.hi != 0 + } +} + pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec, end: time::Timespec) { let elapsed = 1000 * ((end.sec - start.sec) as int) + @@ -1158,7 +1165,8 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block { ast::decl_local(ref locals) => { for locals.each |local| { bcx = init_local(bcx, *local); - if cx.sess().opts.extra_debuginfo { + if cx.sess().opts.extra_debuginfo + && fcx_has_nonzero_span(bcx.fcx) { debuginfo::create_local_var(bcx, *local); } } @@ -1738,7 +1746,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, fcx.llargs.insert(arg_id, local_mem(llarg)); - if fcx.ccx.sess.opts.extra_debuginfo { + if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span); } } @@ -1861,7 +1869,8 @@ pub fn trans_fn(ccx: @CrateContext, trans_closure(ccx, path, decl, body, llfndecl, ty_self, param_substs, id, impl_id, |fcx| { - if ccx.sess.opts.extra_debuginfo { + if ccx.sess.opts.extra_debuginfo + && fcx_has_nonzero_span(fcx) { debuginfo::create_function(fcx); } }, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index c573529fbc23c..31f89deff5d7f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -946,7 +946,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span) } pub fn update_source_pos(cx: block, s: span) { - if !cx.sess().opts.debuginfo { + if !cx.sess().opts.debuginfo || (*s.lo == 0 && *s.hi == 0) { return; } let cm = cx.sess().codemap; From 3e5b98fc741624ae63c600cfb8882f21dd229e67 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Tue, 9 Apr 2013 15:53:15 -0400 Subject: [PATCH 118/403] Add debug info test for boxes --- src/test/debug-info/box.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/debug-info/box.rs diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs new file mode 100644 index 0000000000000..f77ec3f947a05 --- /dev/null +++ b/src/test/debug-info/box.rs @@ -0,0 +1,30 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break 29 +// debugger:run +// debugger:print a->boxed +// check:$1 = 1 +// debugger:print b->boxed +// check:$2 = {2, 3.5} +// debugger:print c->boxed +// check:$3 = 4 +// debugger:print d->boxed +// check:$4 = false + +fn main() { + let a = ~1; + let b = ~(2, 3.5); + let c = @4; + let d = @false; + let _z = 0; +} From a34921ae890a27c99a6880588564a3fae5c45a41 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Tue, 9 Apr 2013 16:27:47 -0400 Subject: [PATCH 119/403] Add debug info test for vectors --- src/test/debug-info/vec.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/debug-info/vec.rs diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs new file mode 100644 index 0000000000000..861af3bdbc21d --- /dev/null +++ b/src/test/debug-info/vec.rs @@ -0,0 +1,30 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Z extra-debug-info +// debugger:set print pretty off +// debugger:break 29 +// debugger:run +// debugger:print a +// check:$1 = {1, 2, 3} +// debugger:print b.vec[0] +// check:$2 = 4 +// debugger:print c->boxed.data[1] +// check:$3 = 8 +// debugger:print d->boxed.data[2] +// check:$4 = 12 + +fn main() { + let a = [1, 2, 3]; + let b = &[4, 5, 6]; + let c = @[7, 8, 9]; + let d = ~[10, 11, 12]; + let _z = 0; +} From 4b7d3634955ca6c7f4632d2c74ccc0137438e744 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Wed, 10 Apr 2013 15:08:19 -0400 Subject: [PATCH 120/403] Add examples for Rng functions. --- src/libcore/rand.rs | 184 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 8 deletions(-) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index a4e53418fc88e..df08c370546f7 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -150,7 +150,21 @@ pub struct Weighted { pub trait RngUtil { fn gen(&self) -> T; - /// Return a random int + /** + * Return a random int + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%d",rng.gen_int())); + * } + * ~~~ + */ fn gen_int(&self) -> int; fn gen_int_range(&self, start: int, end: int) -> int; /// Return a random i8 @@ -176,7 +190,21 @@ pub trait RngUtil { fn gen_u32(&self) -> u32; /// Return a random u64 fn gen_u64(&self) -> u64; - /// Return a random float in the interval [0,1] + /** + * Return random float in the interval [0,1] + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%f",rng.gen_float())); + * } + * ~~~ + */ fn gen_float(&self) -> float; /// Return a random f32 in the interval [0,1] fn gen_f32(&self) -> f32; @@ -188,38 +216,178 @@ pub trait RngUtil { * Return a char randomly chosen from chars, failing if chars is empty */ fn gen_char_from(&self, chars: &str) -> char; - /// Return a random bool + /** + * Return a random bool + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%b",rng.gen_bool())); + * } + * ~~~ + */ fn gen_bool(&self) -> bool; - /// Return a bool with a 1 in n chance of true + /** + * Return a bool with a 1 in n chance of true + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%b",rng.gen_weighted_bool(3))); + * } + * ~~~ + */ fn gen_weighted_bool(&self, n: uint) -> bool; /** * Return a random string of the specified length composed of A-Z,a-z,0-9 + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(rng.gen_str(8)); + * } + * ~~~ */ fn gen_str(&self, len: uint) -> ~str; - /// Return a random byte string of the specified length + /** + * Return a random byte string of the specified length + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%?",rng.gen_bytes(8))); + * } + * ~~~ + */ fn gen_bytes(&self, len: uint) -> ~[u8]; - /// Choose an item randomly, failing if values is empty + /// + /** + * Choose an item randomly, failing if values is empty + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%d",rng.choose([1,2,4,8,16,32]))); + * } + * ~~~ + */ fn choose(&self, values: &[T]) -> T; /// Choose Some(item) randomly, returning None if values is empty fn choose_option(&self, values: &[T]) -> Option; /** * Choose an item respecting the relative weights, failing if the sum of * the weights is 0 + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * println(fmt!("%c",rng.choose_weighted(x))); + * } + * ~~~ */ fn choose_weighted(&self, v : &[Weighted]) -> T; /** * Choose Some(item) respecting the relative weights, returning none if * the sum of the weights is 0 + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * println(fmt!("%?",rng.choose_weighted_option(x))); + * } + * ~~~ */ fn choose_weighted_option(&self, v: &[Weighted]) -> Option; /** * Return a vec containing copies of the items, in order, where * the weight of the item determines how many copies there are + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * println(fmt!("%?",rng.weighted_vec(x))); + * } + * ~~~ */ fn weighted_vec(&self, v: &[Weighted]) -> ~[T]; - /// Shuffle a vec + /** + * Shuffle a vec + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * println(fmt!("%?",rng.shuffle([1,2,3]))); + * } + * ~~~ + */ fn shuffle(&self, values: &[T]) -> ~[T]; - /// Shuffle a mutable vec in place + /** + * Shuffle a mutable vec in place + * + * *Example* + * + * ~~~ + * + * use core::rand::RngUtil; + * + * fn main() { + * rng = rand::Rng(); + * let mut y = [1,2,3]; + * rng.shuffle_mut(y); + * println(fmt!("%?",y)); + * rng.shuffle_mut(y); + * println(fmt!("%?",y)); + * } + * ~~~ + */ fn shuffle_mut(&self, values: &mut [T]); } From ccae209b0db58db1054ede13acfc79c84e0221f3 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Wed, 10 Apr 2013 15:54:28 -0400 Subject: [PATCH 121/403] Clarify comment --- src/libcore/rand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index df08c370546f7..2ee280ff15917 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -505,7 +505,7 @@ impl RngUtil for @Rng { self.next() & 1u32 == 1u32 } - /// Return a bool with a 1 in n chance of true + /// Return a bool with a 1-in-n chance of true fn gen_weighted_bool(&self, n: uint) -> bool { if n == 0u { true From 23e44a529b3a7bccb3db125012d76273ccc06c72 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 4 Apr 2013 21:46:37 -0700 Subject: [PATCH 122/403] Bump version to 0.7-pre --- src/compiletest/compiletest.rc | 4 ++-- src/driver/driver.rs | 14 +++++++------- src/etc/kate/rust.xml | 2 +- src/libcore/core.rc | 4 ++-- src/libfuzzer/fuzzer.rc | 8 ++++---- src/librust/rust.rc | 4 ++-- src/librustc/front/core_inject.rs | 2 +- src/librustc/front/test.rs | 2 +- src/librustc/rustc.rc | 8 ++++---- src/librustdoc/rustdoc.rc | 10 +++++----- src/librusti/rusti.rc | 10 +++++----- src/librustpkg/rustpkg.rc | 10 +++++----- src/librustpkg/util.rs | 2 +- src/libstd/std.rc | 4 ++-- src/libsyntax/syntax.rc | 6 +++--- src/test/run-pass/use.rs | 2 +- 16 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index e97383e730bc0..6626bc039f902 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -17,8 +17,8 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); use core::*; diff --git a/src/driver/driver.rs b/src/driver/driver.rs index db55d5569ab6e..d3ab066929731 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -9,24 +9,24 @@ // except according to those terms. #[no_core]; -extern mod core(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); #[cfg(rustpkg)] -extern mod this(name = "rustpkg", vers = "0.7-rc"); +extern mod this(name = "rustpkg", vers = "0.7-pre"); #[cfg(fuzzer)] -extern mod this(name = "fuzzer", vers = "0.7-rc"); +extern mod this(name = "fuzzer", vers = "0.7-pre"); #[cfg(rustdoc)] -extern mod this(name = "rustdoc", vers = "0.7-rc"); +extern mod this(name = "rustdoc", vers = "0.7-pre"); #[cfg(rusti)] -extern mod this(name = "rusti", vers = "0.7-rc"); +extern mod this(name = "rusti", vers = "0.7-pre"); #[cfg(rust)] -extern mod this(name = "rust", vers = "0.7-rc"); +extern mod this(name = "rust", vers = "0.7-pre"); #[cfg(rustc)] -extern mod this(name = "rustc", vers = "0.7-rc"); +extern mod this(name = "rustc", vers = "0.7-pre"); fn main() { this::main() } diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index aa40e316bf845..59f8c164588b3 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -7,7 +7,7 @@ ]> - + fn diff --git a/src/libcore/core.rc b/src/libcore/core.rc index ed5a255bdb801..3368f6df87090 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -48,7 +48,7 @@ they contained the following prologue: #[link(name = "core", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; @@ -66,7 +66,7 @@ they contained the following prologue: #[allow(deprecated_drop)]; // Make core testable by not duplicating lang items. See #2912 -#[cfg(test)] extern mod realcore(name = "core", vers = "0.7-rc"); +#[cfg(test)] extern mod realcore(name = "core", vers = "0.7-pre"); #[cfg(test)] pub use kinds = realcore::kinds; #[cfg(test)] pub use ops = realcore::ops; #[cfg(test)] pub use cmp = realcore::cmp; diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index c67c788cf2abb..46c7d4da22e4e 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -10,7 +10,7 @@ #[link(name = "fuzzer", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "d6418797-2736-4833-bd82-d3c684b7c1b0", url = "https://github.com/mozilla/rust/tree/master/src/libfuzzer")]; @@ -26,9 +26,9 @@ #[allow(deprecated_mode)]; #[allow(deprecated_pattern)]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); -extern mod syntax(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); +extern mod syntax(vers = "0.7-pre"); use core::*; use core::io::WriterUtil; diff --git a/src/librust/rust.rc b/src/librust/rust.rc index f74bd7084a0ae..624a4701d9802 100644 --- a/src/librust/rust.rc +++ b/src/librust/rust.rc @@ -13,14 +13,14 @@ // FIXME #2238 Make run only accept source that emits an executable #[link(name = "rust", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c", url = "https://github.com/mozilla/rust/tree/master/src/rust")]; #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod core(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); use core::run; diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/core_inject.rs index 387cc9f80a7f6..132023beeb400 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -19,7 +19,7 @@ use syntax::codemap; use syntax::codemap::dummy_sp; use syntax::fold; -static CORE_VERSION: &'static str = "0.7-rc"; +static CORE_VERSION: &'static str = "0.7-pre"; pub fn maybe_inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 0cb1fdf91829a..8d3e9d5e89fb0 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -265,7 +265,7 @@ mod __test { */ fn mk_std(cx: &TestCtxt) -> @ast::view_item { - let vers = ast::lit_str(@~"0.7-rc"); + let vers = ast::lit_str(@~"0.7-pre"); let vers = nospan(vers); let mi = ast::meta_name_value(@~"vers", vers); let mi = nospan(mi); diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 642a94b194582..d1dbb48ba08a4 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -10,7 +10,7 @@ #[link(name = "rustc", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf", url = "https://github.com/mozilla/rust/tree/master/src/rustc")]; @@ -27,9 +27,9 @@ #[no_core]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); -extern mod syntax(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); +extern mod syntax(vers = "0.7-pre"); use core::prelude::*; diff --git a/src/librustdoc/rustdoc.rc b/src/librustdoc/rustdoc.rc index 54a839f53745c..f0c42162e7673 100644 --- a/src/librustdoc/rustdoc.rc +++ b/src/librustdoc/rustdoc.rc @@ -11,7 +11,7 @@ //! Rustdoc - The Rust documentation generator #[link(name = "rustdoc", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "f8abd014-b281-484d-a0c3-26e3de8e2412", url = "https://github.com/mozilla/rust/tree/master/src/rustdoc")]; @@ -23,10 +23,10 @@ #[allow(non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); -extern mod rustc(vers = "0.7-rc"); -extern mod syntax(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); +extern mod rustc(vers = "0.7-pre"); +extern mod syntax(vers = "0.7-pre"); use config::Config; use doc::Item; diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index a7130f6465754..86784c7852afc 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -11,7 +11,7 @@ // rusti - REPL using the JIT backend #[link(name = "rusti", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; @@ -23,10 +23,10 @@ #[allow(vecs_implicitly_copyable, non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); -extern mod rustc(vers = "0.7-rc"); -extern mod syntax(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); +extern mod rustc(vers = "0.7-pre"); +extern mod syntax(vers = "0.7-pre"); use core::*; use core::io::WriterUtil; diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 8ff809023a37b..c0d77f60d69a1 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -11,7 +11,7 @@ // rustpkg - a purely function package manager and build system #[link(name = "rustpkg", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "25de5e6e-279e-4a20-845c-4cabae92daaf", url = "https://github.com/mozilla/rust/tree/master/src/librustpkg")]; @@ -21,10 +21,10 @@ #[allow(vecs_implicitly_copyable, non_implicitly_copyable_typarams)]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); -extern mod rustc(vers = "0.7-rc"); -extern mod syntax(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); +extern mod rustc(vers = "0.7-pre"); +extern mod syntax(vers = "0.7-pre"); use core::*; use core::container::Map; diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 7fd1379fa87d5..0d858afbb8448 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -140,7 +140,7 @@ fn add_pkg_module(ctx: @mut ReadyCtx, m: ast::_mod) -> ast::_mod { let ext_cx = ctx.ext_cx; let item = quote_item! ( mod __pkg { - extern mod rustpkg (vers="0.7-rc"); + extern mod rustpkg (vers="0.7-pre"); static listeners : &[rustpkg::Listener] = $listeners; #[main] fn main() { diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 712490cce24f8..fb340d80c2dbc 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -18,7 +18,7 @@ not required in or otherwise suitable for the core library. */ #[link(name = "std", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; @@ -32,7 +32,7 @@ not required in or otherwise suitable for the core library. #[no_core]; -extern mod core(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); use core::prelude::*; pub mod uv_ll; diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 8704534f677a3..56b17fb8d0a72 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -9,7 +9,7 @@ // except according to those terms. #[link(name = "syntax", - vers = "0.7-rc", + vers = "0.7-pre", uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")]; @@ -25,8 +25,8 @@ #[no_core]; -extern mod core(vers = "0.7-rc"); -extern mod std(vers = "0.7-rc"); +extern mod core(vers = "0.7-pre"); +extern mod std(vers = "0.7-pre"); use core::*; diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index c5a012ccb7bb2..0bd4175d39043 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -13,7 +13,7 @@ #[no_core]; extern mod core; extern mod zed(name = "core"); -extern mod bar(name = "core", vers = "0.7-rc"); +extern mod bar(name = "core", vers = "0.7-pre"); use core::str; From 9a16179fd3ec18e8f3bc4ca68054981f6628fdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Wed, 10 Apr 2013 23:51:41 +0200 Subject: [PATCH 123/403] Added str::from_slice_with_null() to cast a &[u8] to &str Added str::subslice_offset() Renamed slice_bytes_uniqe to slice_bytes_owned --- src/libcore/str.rs | 136 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 8 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index f1605309fb488..a0b78bc22b653 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -38,7 +38,7 @@ Section: Creating a string */ /** - * Convert a vector of bytes to a UTF-8 string + * Convert a vector of bytes to a new UTF-8 string * * # Failure * @@ -49,9 +49,26 @@ pub fn from_bytes(vv: &const [u8]) -> ~str { return unsafe { raw::from_bytes(vv) }; } +/** + * Convert a vector of bytes to a UTF-8 string. + * The vector needs to be one byte longer than the string, and end with a 0 byte. + * + * Compared to `from_bytes()`, this fn doesn't need to allocate a new owned str. + * + * # Failure + * + * Fails if invalid UTF-8 + * Fails if not null terminated + */ +pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str { + assert!(vv[vv.len() - 1] == 0); + assert!(is_utf8(vv)); + return unsafe { raw::from_bytes_with_null(vv) }; +} + /// Copy a slice into a new unique str pub fn from_slice(s: &str) -> ~str { - unsafe { raw::slice_bytes_unique(s, 0, len(s)) } + unsafe { raw::slice_bytes_owned(s, 0, len(s)) } } impl ToStr for ~str { @@ -279,7 +296,7 @@ pub fn pop_char(s: &mut ~str) -> char { */ pub fn shift_char(s: &mut ~str) -> char { let CharRange {ch, next} = char_range_at(*s, 0u); - *s = unsafe { raw::slice_bytes_unique(*s, next, len(*s)) }; + *s = unsafe { raw::slice_bytes_owned(*s, next, len(*s)) }; return ch; } @@ -784,9 +801,9 @@ pub fn replace(s: &str, from: &str, to: &str) -> ~str { if first { first = false; } else { - unsafe { push_str(&mut result, to); } + push_str(&mut result, to); } - unsafe { push_str(&mut result, raw::slice_bytes_unique(s, start, end)); } + push_str(&mut result, unsafe{raw::slice_bytes(s, start, end)}); } result } @@ -2037,6 +2054,25 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { } } +/** + * Returns the byte offset of an inner slice relative to an enclosing outer slice + */ +#[inline(always)] +pub fn subslice_offset(outer: &str, inner: &str) -> uint { + do as_buf(outer) |a, a_len| { + do as_buf(inner) |b, b_len| { + let a_start: uint, a_end: uint, b_start: uint, b_end: uint; + unsafe { + a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); + b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); + } + assert!(a_start <= b_start); + assert!(b_end <= a_end); + b_start - a_start + } + } +} + /** * Reserves capacity for exactly `n` bytes in the given string, not including * the null terminator. @@ -2158,13 +2194,20 @@ pub mod raw { from_buf_len(::cast::reinterpret_cast(&c_str), len) } - /// Converts a vector of bytes to a string. + /// Converts a vector of bytes to a new owned string. pub unsafe fn from_bytes(v: &const [u8]) -> ~str { do vec::as_const_buf(v) |buf, len| { from_buf_len(buf, len) } } + /// Converts a vector of bytes to a string. + /// The byte slice needs to contain valid utf8 and needs to be one byte longer than + /// the string, if possible ending in a 0 byte. + pub unsafe fn from_bytes_with_null<'a>(v: &'a [u8]) -> &'a str { + cast::transmute(v) + } + /// Converts a byte to a string. pub unsafe fn from_byte(u: u8) -> ~str { raw::from_bytes([u]) } @@ -2186,7 +2229,7 @@ pub mod raw { * If begin is greater than end. * If end is greater than the length of the string. */ - pub unsafe fn slice_bytes_unique(s: &str, begin: uint, end: uint) -> ~str { + pub unsafe fn slice_bytes_owned(s: &str, begin: uint, end: uint) -> ~str { do as_buf(s) |sbuf, n| { assert!((begin <= end)); assert!((end <= n)); @@ -2258,7 +2301,7 @@ pub mod raw { let len = len(*s); assert!((len > 0u)); let b = s[0]; - *s = unsafe { raw::slice_bytes_unique(*s, 1u, len) }; + *s = unsafe { raw::slice_bytes_owned(*s, 1u, len) }; return b; } @@ -3289,6 +3332,66 @@ mod tests { let _x = from_bytes(bb); } + #[test] + fn test_unsafe_from_bytes_with_null() { + let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8]; + let b = unsafe { raw::from_bytes_with_null(a) }; + assert_eq!(b, "AAAAAAA"); + } + + #[test] + fn test_from_bytes_with_null() { + let ss = "ศไทย中华Việt Nam"; + let bb = [0xe0_u8, 0xb8_u8, 0xa8_u8, + 0xe0_u8, 0xb9_u8, 0x84_u8, + 0xe0_u8, 0xb8_u8, 0x97_u8, + 0xe0_u8, 0xb8_u8, 0xa2_u8, + 0xe4_u8, 0xb8_u8, 0xad_u8, + 0xe5_u8, 0x8d_u8, 0x8e_u8, + 0x56_u8, 0x69_u8, 0xe1_u8, + 0xbb_u8, 0x87_u8, 0x74_u8, + 0x20_u8, 0x4e_u8, 0x61_u8, + 0x6d_u8, 0x0_u8]; + + assert_eq!(ss, from_bytes_with_null(bb)); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_from_bytes_with_null_fail() { + let bb = [0xff_u8, 0xb8_u8, 0xa8_u8, + 0xe0_u8, 0xb9_u8, 0x84_u8, + 0xe0_u8, 0xb8_u8, 0x97_u8, + 0xe0_u8, 0xb8_u8, 0xa2_u8, + 0xe4_u8, 0xb8_u8, 0xad_u8, + 0xe5_u8, 0x8d_u8, 0x8e_u8, + 0x56_u8, 0x69_u8, 0xe1_u8, + 0xbb_u8, 0x87_u8, 0x74_u8, + 0x20_u8, 0x4e_u8, 0x61_u8, + 0x6d_u8, 0x0_u8]; + + let _x = from_bytes_with_null(bb); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_from_bytes_with_null_fail_2() { + let bb = [0xff_u8, 0xb8_u8, 0xa8_u8, + 0xe0_u8, 0xb9_u8, 0x84_u8, + 0xe0_u8, 0xb8_u8, 0x97_u8, + 0xe0_u8, 0xb8_u8, 0xa2_u8, + 0xe4_u8, 0xb8_u8, 0xad_u8, + 0xe5_u8, 0x8d_u8, 0x8e_u8, + 0x56_u8, 0x69_u8, 0xe1_u8, + 0xbb_u8, 0x87_u8, 0x74_u8, + 0x20_u8, 0x4e_u8, 0x61_u8, + 0x6d_u8, 0x60_u8]; + + let _x = from_bytes_with_null(bb); + } + #[test] fn test_from_buf() { unsafe { @@ -3351,6 +3454,23 @@ mod tests { } } + #[test] + fn test_subslice_offset() { + let a = "kernelsprite"; + let b = slice(a, 7, len(a)); + let c = slice(a, 0, len(a) - 6); + assert!(subslice_offset(a, b) == 7); + assert!(subslice_offset(a, c) == 0); + } + + #[test] + #[should_fail] + fn test_subslice_offset_2() { + let a = "alchemiter"; + let b = "cruxtruder"; + subslice_offset(a, b); + } + #[test] fn vec_str_conversions() { let s1: ~str = ~"All mimsy were the borogoves"; From 4ad76e66aad1813bc927ae1b5cf8205c8c5a8944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Thu, 11 Apr 2013 00:48:31 +0200 Subject: [PATCH 124/403] Add example for str::subslice_offset --- src/libcore/str.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index a0b78bc22b653..2201836c72410 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2056,6 +2056,18 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { /** * Returns the byte offset of an inner slice relative to an enclosing outer slice + * + * # Example + * + * ~~~ + * let string = "a\nb\nc"; + * let mut lines = ~[]; + * for each_line(string) |line| { lines.push(line) } + * + * assert!(subslice_offset(string, lines[0]) == 0); // &"a" + * assert!(subslice_offset(string, lines[1]) == 2); // &"b" + * assert!(subslice_offset(string, lines[2]) == 4); // &"c" + * ~~~ */ #[inline(always)] pub fn subslice_offset(outer: &str, inner: &str) -> uint { @@ -3461,6 +3473,13 @@ mod tests { let c = slice(a, 0, len(a) - 6); assert!(subslice_offset(a, b) == 7); assert!(subslice_offset(a, c) == 0); + + let string = "a\nb\nc"; + let mut lines = ~[]; + for each_line(string) |line| { lines.push(line) } + assert!(subslice_offset(string, lines[0]) == 0); + assert!(subslice_offset(string, lines[1]) == 2); + assert!(subslice_offset(string, lines[2]) == 4); } #[test] From 74807b15944205beb2b86ea5422927c47cac3ecc Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 6 Apr 2013 22:29:37 -0700 Subject: [PATCH 125/403] syntax: match variants use 4 space indent by default --- src/libsyntax/print/pprust.rs | 15 +++++++-------- src/test/pretty/alt-naked-expr-long.rs | 8 ++++---- src/test/pretty/alt-naked-expr-medium.rs | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index fa1b97275660c..4e7e5144a7df2 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -95,7 +95,6 @@ pub fn rust_printer(writer: @io::Writer, intr: @ident_interner) -> @ps { } pub static indent_unit: uint = 4u; -pub static match_indent_unit: uint = 2u; pub static default_columns: uint = 78u; @@ -1227,16 +1226,16 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) { print_block(s, blk); } ast::expr_match(expr, ref arms) => { - cbox(s, match_indent_unit); + cbox(s, indent_unit); ibox(s, 4); word_nbsp(s, ~"match"); print_expr(s, expr); space(s.s); bopen(s); - let len = (*arms).len(); - for (*arms).eachi |i, arm| { + let len = arms.len(); + for arms.eachi |i, arm| { space(s.s); - cbox(s, match_indent_unit); + cbox(s, indent_unit); ibox(s, 0u); let mut first = true; for arm.pats.each |p| { @@ -1269,7 +1268,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) { ast::expr_block(ref blk) => { // the block will close the pattern's ibox print_block_unclosed_indent( - s, blk, match_indent_unit); + s, blk, indent_unit); } _ => { end(s); // close the ibox for the pattern @@ -1286,10 +1285,10 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) { } } else { // the block will close the pattern's ibox - print_block_unclosed_indent(s, &arm.body, match_indent_unit); + print_block_unclosed_indent(s, &arm.body, indent_unit); } } - bclose_(s, expr.span, match_indent_unit); + bclose_(s, expr.span, indent_unit); } ast::expr_fn_block(ref decl, ref body) => { // in do/for blocks we don't want to show an empty diff --git a/src/test/pretty/alt-naked-expr-long.rs b/src/test/pretty/alt-naked-expr-long.rs index 67253c9753ede..66ad3d558201d 100644 --- a/src/test/pretty/alt-naked-expr-long.rs +++ b/src/test/pretty/alt-naked-expr-long.rs @@ -17,9 +17,9 @@ fn main() { let x = Some(3); let y = match x { - Some(_) => - ~"some" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very" - + ~"very" + ~"very" + ~"long" + ~"string", - None => ~"none" + Some(_) => + ~"some" + ~"very" + ~"very" + ~"very" + ~"very" + ~"very" + + ~"very" + ~"very" + ~"very" + ~"long" + ~"string", + None => ~"none" }; } diff --git a/src/test/pretty/alt-naked-expr-medium.rs b/src/test/pretty/alt-naked-expr-medium.rs index 6c6398c3e52c2..4ae129c7b7307 100644 --- a/src/test/pretty/alt-naked-expr-medium.rs +++ b/src/test/pretty/alt-naked-expr-medium.rs @@ -14,7 +14,7 @@ fn main() { let x = Some(3); let _y = match x { - Some(_) => ~[~"some(_)", ~"not", ~"SO", ~"long", ~"string"], - None => ~[~"none"] + Some(_) => ~[~"some(_)", ~"not", ~"SO", ~"long", ~"string"], + None => ~[~"none"] }; } From 4464e447500c98242b536ee4a461fcd8c5d9adc5 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 6 Apr 2013 22:34:09 -0700 Subject: [PATCH 126/403] syntax: update a deriving error message to use the new syntax --- src/libsyntax/ext/deriving/clone.rs | 4 +--- src/libsyntax/ext/deriving/eq.rs | 2 +- src/libsyntax/ext/deriving/iter_bytes.rs | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index c9e1771599939..6d598c95e3a53 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -188,9 +188,7 @@ fn expand_deriving_clone_struct_method(cx: @ext_ctxt, fields.push(field); } unnamed_field => { - cx.span_bug(span, - ~"unnamed fields in \ - expand_deriving_clone_struct_method"); + cx.span_bug(span, ~"unnamed fields in `deriving(Clone)`"); } } } diff --git a/src/libsyntax/ext/deriving/eq.rs b/src/libsyntax/ext/deriving/eq.rs index 07b2835d44cdf..46eec2ede68a9 100644 --- a/src/libsyntax/ext/deriving/eq.rs +++ b/src/libsyntax/ext/deriving/eq.rs @@ -289,7 +289,7 @@ fn expand_deriving_eq_struct_method(cx: @ext_ctxt, &mut outer_expr); } unnamed_field => { - cx.span_unimpl(span, ~"unnamed fields with `deriving_eq`"); + cx.span_unimpl(span, ~"unnamed fields with `deriving(Eq)`"); } } } diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index e2a43591ef026..e832408dd2b1d 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -191,7 +191,7 @@ fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt, } unnamed_field => { cx.span_unimpl(span, - ~"unnamed fields with `deriving_iter_bytes`"); + ~"unnamed fields with `deriving(IterBytes)`"); } } } From 97cc571358c3ac1bc3d562ac60c39c67cda3678d Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Apr 2013 18:56:34 -0700 Subject: [PATCH 127/403] std: clean up the order of {De,En}codable methods --- src/libstd/ebml.rs | 50 ++++++++-------- src/libstd/json.rs | 98 ++++++++++++++++---------------- src/libstd/serialize.rs | 13 ++--- src/libsyntax/ext/auto_encode.rs | 14 ++--- 4 files changed, 87 insertions(+), 88 deletions(-) diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index b117c8d9882ba..3afc49d40addc 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -335,20 +335,6 @@ pub mod reader { f() } - fn read_seq(&self, f: &fn(uint) -> T) -> T { - debug!("read_seq()"); - do self.push_doc(self.next_doc(EsVec)) { - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - f(len) - } - } - - fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T { - debug!("read_seq_elt(idx=%u)", idx); - self.push_doc(self.next_doc(EsVecElt), f) - } - fn read_struct(&self, name: &str, _len: uint, f: &fn() -> T) -> T { debug!("read_struct(name=%s)", name); f() @@ -373,6 +359,20 @@ pub mod reader { } } + fn read_seq(&self, f: &fn(uint) -> T) -> T { + debug!("read_seq()"); + do self.push_doc(self.next_doc(EsVec)) { + let len = self._next_uint(EsVecLen); + debug!(" len=%u", len); + f(len) + } + } + + fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_seq_elt(idx=%u)", idx); + self.push_doc(self.next_doc(EsVecElt), f) + } + fn read_map(&self, _f: &fn(uint) -> T) -> T { debug!("read_map()"); fail!(~"read_map is unimplemented"); @@ -613,17 +613,6 @@ pub mod writer { } fn emit_enum_variant_arg(&self, _idx: uint, f: &fn()) { f() } - fn emit_seq(&self, len: uint, f: &fn()) { - do self.wr_tag(EsVec as uint) { - self._emit_tagged_uint(EsVecLen, len); - f() - } - } - - fn emit_seq_elt(&self, _idx: uint, f: &fn()) { - self.wr_tag(EsVecElt as uint, f) - } - fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { f() } fn emit_field(&self, name: &str, _idx: uint, f: &fn()) { self._emit_label(name); @@ -640,6 +629,17 @@ pub mod writer { self.emit_enum_variant("Some", 1, 1, f) } + fn emit_seq(&self, len: uint, f: &fn()) { + do self.wr_tag(EsVec as uint) { + self._emit_tagged_uint(EsVecLen, len); + f() + } + } + + fn emit_seq_elt(&self, _idx: uint, f: &fn()) { + self.wr_tag(EsVecElt as uint, f) + } + fn emit_map(&self, _len: uint, _f: &fn()) { fail!(~"emit_map is unimplemented"); } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 90a745aaeb9b7..3714adb305561 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -130,17 +130,6 @@ impl serialize::Encoder for Encoder { f(); } - fn emit_seq(&self, _len: uint, f: &fn()) { - self.wr.write_char('['); - f(); - self.wr.write_char(']'); - } - - fn emit_seq_elt(&self, idx: uint, f: &fn()) { - if idx != 0 { self.wr.write_char(','); } - f() - } - fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { self.wr.write_char('{'); f(); @@ -157,6 +146,17 @@ impl serialize::Encoder for Encoder { fn emit_option_none(&self) { self.emit_nil(); } fn emit_option_some(&self, f: &fn()) { f(); } + fn emit_seq(&self, _len: uint, f: &fn()) { + self.wr.write_char('['); + f(); + self.wr.write_char(']'); + } + + fn emit_seq_elt(&self, idx: uint, f: &fn()) { + if idx != 0 { self.wr.write_char(','); } + f() + } + fn emit_map(&self, _len: uint, f: &fn()) { self.wr.write_char('{'); f(); @@ -241,58 +241,58 @@ impl serialize::Encoder for PrettyEncoder { f() } - fn emit_seq(&self, len: uint, f: &fn()) { + fn emit_struct(&self, _name: &str, len: uint, f: &fn()) { if len == 0 { - self.wr.write_str("[]"); + self.wr.write_str("{}"); } else { - self.wr.write_char('['); + self.wr.write_char('{'); self.indent += 2; f(); self.wr.write_char('\n'); self.indent -= 2; self.wr.write_str(spaces(self.indent)); - self.wr.write_char(']'); + self.wr.write_char('}'); } } - fn emit_seq_elt(&self, idx: uint, f: &fn()) { + fn emit_field(&self, name: &str, idx: uint, f: &fn()) { if idx == 0 { self.wr.write_char('\n'); } else { self.wr.write_str(",\n"); } self.wr.write_str(spaces(self.indent)); - f() + self.wr.write_str(escape_str(name)); + self.wr.write_str(": "); + f(); } - fn emit_struct(&self, _name: &str, len: uint, f: &fn()) { + fn emit_option(&self, f: &fn()) { f(); } + fn emit_option_none(&self) { self.emit_nil(); } + fn emit_option_some(&self, f: &fn()) { f(); } + + fn emit_seq(&self, len: uint, f: &fn()) { if len == 0 { - self.wr.write_str("{}"); + self.wr.write_str("[]"); } else { - self.wr.write_char('{'); + self.wr.write_char('['); self.indent += 2; f(); self.wr.write_char('\n'); self.indent -= 2; self.wr.write_str(spaces(self.indent)); - self.wr.write_char('}'); + self.wr.write_char(']'); } } - fn emit_field(&self, name: &str, idx: uint, f: &fn()) { + fn emit_seq_elt(&self, idx: uint, f: &fn()) { if idx == 0 { self.wr.write_char('\n'); } else { self.wr.write_str(",\n"); } self.wr.write_str(spaces(self.indent)); - self.wr.write_str(escape_str(name)); - self.wr.write_str(": "); - f(); + f() } - fn emit_option(&self, f: &fn()) { f(); } - fn emit_option_none(&self) { self.emit_nil(); } - fn emit_option_some(&self, f: &fn()) { f(); } - fn emit_map(&self, len: uint, f: &fn()) { if len == 0 { self.wr.write_str("{}"); @@ -827,26 +827,6 @@ impl serialize::Decoder for Decoder { f() } - fn read_seq(&self, f: &fn(uint) -> T) -> T { - debug!("read_seq()"); - let len = match self.stack.pop() { - List(list) => { - let len = list.len(); - do vec::consume_reverse(list) |_i, v| { - self.stack.push(v); - } - len - } - _ => fail!(~"not a list"), - }; - f(len) - } - - fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T { - debug!("read_seq_elt(idx=%u)", idx); - f() - } - fn read_struct(&self, name: &str, len: uint, f: &fn() -> T) -> T { debug!("read_struct(name=%s, len=%u)", name, len); let value = f(); @@ -880,6 +860,26 @@ impl serialize::Decoder for Decoder { } } + fn read_seq(&self, f: &fn(uint) -> T) -> T { + debug!("read_seq()"); + let len = match self.stack.pop() { + List(list) => { + let len = list.len(); + do vec::consume_reverse(list) |_i, v| { + self.stack.push(v); + } + len + } + _ => fail!(~"not a list"), + }; + f(len) + } + + fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_seq_elt(idx=%u)", idx); + f() + } + fn read_map(&self, f: &fn(uint) -> T) -> T { debug!("read_map()"); let len = match self.stack.pop() { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index c2f0d9cb43f09..a49f43d485b1f 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -44,14 +44,10 @@ pub trait Encoder { fn emit_str(&self, v: &str); // Compound types: - fn emit_enum(&self, name: &str, f: &fn()); fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: &fn()); fn emit_enum_variant_arg(&self, idx: uint, f: &fn()); - fn emit_seq(&self, len: uint, f: &fn()); - fn emit_seq_elt(&self, idx: uint, f: &fn()); - fn emit_struct(&self, name: &str, _len: uint, f: &fn()); fn emit_field(&self, f_name: &str, f_idx: uint, f: &fn()); @@ -60,6 +56,9 @@ pub trait Encoder { fn emit_option_none(&self); fn emit_option_some(&self, f: &fn()); + fn emit_seq(&self, len: uint, f: &fn()); + fn emit_seq_elt(&self, idx: uint, f: &fn()); + fn emit_map(&self, len: uint, f: &fn()); fn emit_map_elt_key(&self, idx: uint, f: &fn()); fn emit_map_elt_val(&self, idx: uint, f: &fn()); @@ -90,15 +89,15 @@ pub trait Decoder { fn read_enum_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T; fn read_enum_variant_arg(&self, idx: uint, f: &fn() -> T) -> T; - fn read_seq(&self, f: &fn(uint) -> T) -> T; - fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T; - fn read_struct(&self, name: &str, _len: uint, f: &fn() -> T) -> T; fn read_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T; // Specialized types: fn read_option(&self, f: &fn(bool) -> T) -> T; + fn read_seq(&self, f: &fn(uint) -> T) -> T; + fn read_seq_elt(&self, idx: uint, f: &fn() -> T) -> T; + fn read_map(&self, f: &fn(uint) -> T) -> T; fn read_map_elt_key(&self, idx: uint, f: &fn() -> T) -> T; fn read_map_elt_val(&self, idx: uint, f: &fn() -> T) -> T; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index f9dadb560e3d0..932c3477cf5bc 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -1253,13 +1253,6 @@ mod test { self.add_to_log(CallToEmitEnumVariantArg (idx)); f(); } - fn emit_seq(&self, +_len: uint, f: &fn()) { - self.add_unknown_to_log(); f(); - } - fn emit_seq_elt(&self, +_idx: uint, f: &fn()) { - self.add_unknown_to_log(); f(); - } - fn emit_struct(&self, name: &str, +len: uint, f: &fn()) { self.add_to_log(CallToEmitStruct (name.to_str(),len)); f(); } @@ -1279,6 +1272,13 @@ mod test { f(); } + fn emit_seq(&self, +_len: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + fn emit_seq_elt(&self, +_idx: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + fn emit_map(&self, _len: uint, f: &fn()) { self.add_unknown_to_log(); f(); } From 419f6acf0e609c18c6df5ee2ca8ed9cb6206bbfe Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Apr 2013 19:41:20 -0700 Subject: [PATCH 128/403] std: rename {read,emit}_field to {read,emit}_struct_field --- src/librustc/middle/astencode.rs | 97 ++++++++++++++++++++++++++++++++ src/libstd/ebml.rs | 20 ++++++- src/libstd/json.rs | 50 +++++++++++++++- src/libstd/serialize.rs | 16 +++++- src/libsyntax/ext/auto_encode.rs | 10 ++-- 5 files changed, 183 insertions(+), 10 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 68989b3142566..f5a31879855ef 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -556,6 +556,7 @@ trait read_method_map_entry_helper { -> method_map_entry; } +#[cfg(stage0)] fn encode_method_map_entry(ecx: @e::EncodeContext, ebml_w: writer::Encoder, mme: method_map_entry) { @@ -572,7 +573,27 @@ fn encode_method_map_entry(ecx: @e::EncodeContext, } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +fn encode_method_map_entry(ecx: @e::EncodeContext, + ebml_w: writer::Encoder, + mme: method_map_entry) { + do ebml_w.emit_struct("method_map_entry", 3) { + do ebml_w.emit_struct_field("self_arg", 0u) { + ebml_w.emit_arg(ecx, mme.self_arg); + } + do ebml_w.emit_struct_field("explicit_self", 2u) { + mme.explicit_self.encode(&ebml_w); + } + do ebml_w.emit_struct_field("origin", 1u) { + mme.origin.encode(&ebml_w); + } + } +} + impl read_method_map_entry_helper for reader::Decoder { + #[cfg(stage0)] fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext) -> method_map_entry { do self.read_struct("method_map_entry", 3) { @@ -592,6 +613,29 @@ impl read_method_map_entry_helper for reader::Decoder { } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext) + -> method_map_entry { + do self.read_struct("method_map_entry", 3) { + method_map_entry { + self_arg: self.read_struct_field("self_arg", 0u, || { + self.read_arg(xcx) + }), + explicit_self: self.read_struct_field("explicit_self", 2u, || { + let self_type: ast::self_ty_ = Decodable::decode(self); + self_type + }), + origin: self.read_struct_field("origin", 1u, || { + let method_origin: method_origin = + Decodable::decode(self); + method_origin.tr(xcx) + }), + } + } + } } impl tr for method_origin { @@ -782,6 +826,7 @@ impl ebml_writer_helpers for writer::Encoder { } } + #[cfg(stage0)] fn emit_tpbt(&self, ecx: @e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty) { do self.emit_struct("ty_param_bounds_and_ty", 2) { @@ -804,6 +849,32 @@ impl ebml_writer_helpers for writer::Encoder { } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn emit_tpbt(&self, ecx: @e::EncodeContext, + tpbt: ty::ty_param_bounds_and_ty) { + do self.emit_struct("ty_param_bounds_and_ty", 2) { + do self.emit_struct_field("generics", 0) { + do self.emit_struct("Generics", 2) { + do self.emit_struct_field("type_param_defs", 0) { + do self.emit_from_vec(*tpbt.generics.type_param_defs) + |type_param_def| + { + self.emit_type_param_def(ecx, type_param_def); + } + } + do self.emit_struct_field("region_param", 1) { + tpbt.generics.region_param.encode(self); + } + } + } + do self.emit_struct_field("ty", 1) { + self.emit_ty(ecx, tpbt.ty); + } + } + } } trait write_tag_and_id { @@ -1053,6 +1124,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { } } + #[cfg(stage0)] fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) -> ty::ty_param_bounds_and_ty { @@ -1075,6 +1147,31 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) + -> ty::ty_param_bounds_and_ty + { + do self.read_struct("ty_param_bounds_and_ty", 2) { + ty::ty_param_bounds_and_ty { + generics: do self.read_struct("Generics", 2) { + ty::Generics { + type_param_defs: self.read_struct_field("type_param_defs", 0, || { + @self.read_to_vec(|| self.read_type_param_def(xcx)) + }), + region_param: self.read_struct_field(~"region_param", 1, || { + Decodable::decode(self) + }) + } + }, + ty: self.read_struct_field("ty", 1, || { + self.read_ty(xcx) + }) + } + } + } + fn convert_def_id(&self, xcx: @ExtendedDecodeContext, source: tydecode::DefIdSource, did: ast::def_id) -> ast::def_id { diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 3afc49d40addc..28933d553e6ef 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -340,8 +340,18 @@ pub mod reader { f() } + #[cfg(stage0)] fn read_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { - debug!("read_field(name=%s, idx=%u)", name, idx); + debug!("read_field(name=%?, idx=%u)", name, idx); + self._check_label(name); + f() + } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_struct_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { + debug!("read_struct_field(name=%?, idx=%u)", name, idx); self._check_label(name); f() } @@ -614,10 +624,18 @@ pub mod writer { fn emit_enum_variant_arg(&self, _idx: uint, f: &fn()) { f() } fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { f() } + #[cfg(stage0)] fn emit_field(&self, name: &str, _idx: uint, f: &fn()) { self._emit_label(name); f() } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn emit_struct_field(&self, name: &str, _idx: uint, f: &fn()) { + self._emit_label(name); + f() + } fn emit_option(&self, f: &fn()) { self.emit_enum("Option", f); diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 3714adb305561..4b5e1f1422990 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -135,12 +135,22 @@ impl serialize::Encoder for Encoder { f(); self.wr.write_char('}'); } + #[cfg(stage0)] fn emit_field(&self, name: &str, idx: uint, f: &fn()) { if idx != 0 { self.wr.write_char(','); } self.wr.write_str(escape_str(name)); self.wr.write_char(':'); f(); } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) { + if idx != 0 { self.wr.write_char(','); } + self.wr.write_str(escape_str(name)); + self.wr.write_char(':'); + f(); + } fn emit_option(&self, f: &fn()) { f(); } fn emit_option_none(&self) { self.emit_nil(); } @@ -254,6 +264,7 @@ impl serialize::Encoder for PrettyEncoder { self.wr.write_char('}'); } } + #[cfg(stage0)] fn emit_field(&self, name: &str, idx: uint, f: &fn()) { if idx == 0 { self.wr.write_char('\n'); @@ -265,6 +276,20 @@ impl serialize::Encoder for PrettyEncoder { self.wr.write_str(": "); f(); } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) { + if idx == 0 { + self.wr.write_char('\n'); + } else { + self.wr.write_str(",\n"); + } + self.wr.write_str(spaces(self.indent)); + self.wr.write_str(escape_str(name)); + self.wr.write_str(": "); + f(); + } fn emit_option(&self, f: &fn()) { f(); } fn emit_option_none(&self) { self.emit_nil(); } @@ -834,8 +859,31 @@ impl serialize::Decoder for Decoder { value } + #[cfg(stage0)] fn read_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { - debug!("read_field(%s, idx=%u)", name, idx); + debug!("read_field(name=%?, idx=%u)", name, idx); + match self.stack.pop() { + Object(obj) => { + let mut obj = obj; + let value = match obj.pop(&name.to_owned()) { + None => fail!(fmt!("no such field: %s", name)), + Some(json) => { + self.stack.push(json); + f() + } + }; + self.stack.push(Object(obj)); + value + } + value => fail!(fmt!("not an object: %?", value)) + } + } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_struct_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { + debug!("read_struct_field(name=%?, idx=%u)", name, idx); match self.stack.pop() { Object(obj) => { let mut obj = obj; diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index a49f43d485b1f..cc3a1ec028983 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -48,8 +48,13 @@ pub trait Encoder { fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: &fn()); fn emit_enum_variant_arg(&self, idx: uint, f: &fn()); - fn emit_struct(&self, name: &str, _len: uint, f: &fn()); + fn emit_struct(&self, name: &str, len: uint, f: &fn()); + #[cfg(stage0)] fn emit_field(&self, f_name: &str, f_idx: uint, f: &fn()); + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn emit_struct_field(&self, f_name: &str, f_idx: uint, f: &fn()); // Specialized types: fn emit_option(&self, f: &fn()); @@ -89,8 +94,13 @@ pub trait Decoder { fn read_enum_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T; fn read_enum_variant_arg(&self, idx: uint, f: &fn() -> T) -> T; - fn read_struct(&self, name: &str, _len: uint, f: &fn() -> T) -> T; - fn read_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T; + fn read_struct(&self, s_name: &str, len: uint, f: &fn() -> T) -> T; + #[cfg(stage0)] + fn read_field(&self, f_name: &str, f_idx: uint, f: &fn() -> T) -> T; + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn read_struct_field(&self, f_name: &str, f_idx: uint, f: &fn() -> T) -> T; // Specialized types: fn read_option(&self, f: &fn(bool) -> T) -> T; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 932c3477cf5bc..38bac6b1f438d 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -732,12 +732,12 @@ fn mk_struct_ser_impl( ) ); - // ast for `__s.emit_field($(name), $(idx), $(expr_lambda))` + // ast for `__s.emit_struct_field($(name), $(idx), $(expr_lambda))` cx.stmt( cx.expr_method_call( span, cx.expr_var(span, ~"__s"), - cx.ident_of(~"emit_field"), + cx.ident_of(~"emit_struct_field"), ~[ cx.lit_str(span, @cx.str_of(field.ident)), cx.lit_uint(span, idx), @@ -786,11 +786,11 @@ fn mk_struct_deser_impl( ) ); - // ast for `__d.read_field($(name), $(idx), $(expr_lambda))` + // ast for `__d.read_struct_field($(name), $(idx), $(expr_lambda))` let expr: @ast::expr = cx.expr_method_call( span, cx.expr_var(span, ~"__d"), - cx.ident_of(~"read_field"), + cx.ident_of(~"read_struct_field"), ~[ cx.lit_str(span, @cx.str_of(field.ident)), cx.lit_uint(span, idx), @@ -1256,7 +1256,7 @@ mod test { fn emit_struct(&self, name: &str, +len: uint, f: &fn()) { self.add_to_log(CallToEmitStruct (name.to_str(),len)); f(); } - fn emit_field(&self, name: &str, +idx: uint, f: &fn()) { + fn emit_struct_field(&self, name: &str, +idx: uint, f: &fn()) { self.add_to_log(CallToEmitField (name.to_str(),idx)); f(); } From f50a8e283398a8857425e80053db8db845980fa8 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Apr 2013 09:02:36 -0700 Subject: [PATCH 129/403] syntax: Simplify deriving to handle classes that take generics, like Encodable --- src/libsyntax/ext/deriving/clone.rs | 6 ++-- src/libsyntax/ext/deriving/eq.rs | 6 ++-- src/libsyntax/ext/deriving/iter_bytes.rs | 6 ++-- src/libsyntax/ext/deriving/mod.rs | 44 +++++++++--------------- 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 6d598c95e3a53..c8ba6b990e47a 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -17,6 +17,7 @@ use ext::build; use ext::deriving::*; use codemap::{span, spanned}; use ast_util; +use opt_vec; use core::uint; @@ -48,12 +49,13 @@ fn create_derived_clone_impl(cx: @ext_ctxt, method: @method) -> @item { let methods = [ method ]; - let trait_path = [ + let trait_path = ~[ cx.ident_of(~"core"), cx.ident_of(~"clone"), cx.ident_of(~"Clone"), ]; - create_derived_impl(cx, span, type_ident, generics, methods, trait_path) + let trait_path = build::mk_raw_path_global(span, trait_path); + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) } // Creates a method from the given expression conforming to the signature of // the `clone` method. diff --git a/src/libsyntax/ext/deriving/eq.rs b/src/libsyntax/ext/deriving/eq.rs index 46eec2ede68a9..c427a206c2e32 100644 --- a/src/libsyntax/ext/deriving/eq.rs +++ b/src/libsyntax/ext/deriving/eq.rs @@ -17,6 +17,7 @@ use ext::build; use ext::deriving::*; use codemap::{span, spanned}; use ast_util; +use opt_vec; use core::uint; @@ -124,12 +125,13 @@ fn create_derived_eq_impl(cx: @ext_ctxt, ne_method: @method) -> @item { let methods = [ eq_method, ne_method ]; - let trait_path = [ + let trait_path = ~[ cx.ident_of(~"core"), cx.ident_of(~"cmp"), cx.ident_of(~"Eq") ]; - create_derived_impl(cx, span, type_ident, generics, methods, trait_path) + let trait_path = build::mk_raw_path_global(span, trait_path); + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) } fn call_substructure_eq_method(cx: @ext_ctxt, diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index e832408dd2b1d..4124e6ee6c165 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -17,6 +17,7 @@ use ext::build; use ext::deriving::*; use codemap::{span, spanned}; use ast_util; +use opt_vec; use core::uint; @@ -49,12 +50,13 @@ fn create_derived_iter_bytes_impl(cx: @ext_ctxt, method: @method) -> @item { let methods = [ method ]; - let trait_path = [ + let trait_path = ~[ cx.ident_of(~"core"), cx.ident_of(~"to_bytes"), cx.ident_of(~"IterBytes") ]; - create_derived_impl(cx, span, type_ident, generics, methods, trait_path) + let trait_path = build::mk_raw_path_global(span, trait_path); + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) } // Creates a method from the given set of statements conforming to the diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 4337546930ff9..95bca7ff230c7 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -14,7 +14,7 @@ use core::prelude::*; use ast; -use ast::{TraitTyParamBound, Ty, bind_by_ref, deref, enum_def}; +use ast::{Ty, bind_by_ref, deref, enum_def}; use ast::{expr, expr_match, ident, item, item_}; use ast::{item_enum, item_impl, item_struct, Generics}; use ast::{m_imm, meta_item, method}; @@ -153,12 +153,13 @@ pub fn create_self_type_with_params(cx: @ext_ctxt, } pub fn create_derived_impl(cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics, - methods: &[@method], - trait_path: &[ident]) - -> @item { + span: span, + type_ident: ident, + generics: &Generics, + methods: &[@method], + trait_path: @ast::Path, + mut impl_ty_params: opt_vec::OptVec) + -> @item { /*! * * Given that we are deriving a trait `Tr` for a type `T<'a, ..., @@ -175,29 +176,16 @@ pub fn create_derived_impl(cx: @ext_ctxt, build::mk_lifetime(cx, l.span, l.ident) }); - // Create the type parameters. - let impl_ty_params = generics.ty_params.map(|ty_param| { - let bound = build::mk_trait_ref_global(cx, - span, - trait_path.map(|x| *x)); - let bounds = @opt_vec::with(TraitTyParamBound(bound)); - build::mk_ty_param(cx, ty_param.ident, bounds) - }); - // Create the reference to the trait. - let trait_path = ast::Path { - span: span, - global: true, - idents: trait_path.map(|x| *x), - rp: None, - types: ~[] - }; - let trait_path = @trait_path; - let trait_ref = ast::trait_ref { - path: trait_path, - ref_id: cx.next_id() + let trait_ref = build::mk_trait_ref_(cx, trait_path); + + // Create the type parameters. + for generics.ty_params.each |ty_param| { + let bounds = @opt_vec::with( + build::mk_trait_ty_param_bound_(cx, trait_path) + ); + impl_ty_params.push(build::mk_ty_param(cx, ty_param.ident, bounds)); }; - let trait_ref = @trait_ref; // Create the type of `self`. let self_type = create_self_type_with_params(cx, From 5841564bf9a9db012fc17d53da514ddf223dfaf5 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 10 Apr 2013 16:31:51 -0700 Subject: [PATCH 130/403] syntax: add support for #[deriving(Encodable)] --- src/libsyntax/ext/build.rs | 72 ++++- src/libsyntax/ext/deriving/encodable.rs | 388 ++++++++++++++++++++++++ src/libsyntax/ext/deriving/mod.rs | 3 + 3 files changed, 455 insertions(+), 8 deletions(-) create mode 100644 src/libsyntax/ext/deriving/encodable.rs diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 0f84ac4153272..530bb8f15417a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -64,12 +64,7 @@ pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr) mk_expr(cx, sp, ast::expr_unary(op, e)) } pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::Path { - let p = @ast::Path { span: sp, - global: false, - idents: idents, - rp: None, - types: ~[] }; - return p; + mk_raw_path_(sp, idents, ~[]) } pub fn mk_raw_path_(sp: span, +idents: ~[ast::ident], @@ -82,11 +77,16 @@ pub fn mk_raw_path_(sp: span, types: types } } pub fn mk_raw_path_global(sp: span, +idents: ~[ast::ident]) -> @ast::Path { + mk_raw_path_global_(sp, idents, ~[]) +} +pub fn mk_raw_path_global_(sp: span, + +idents: ~[ast::ident], + +types: ~[@ast::Ty]) -> @ast::Path { @ast::Path { span: sp, global: true, idents: idents, rp: None, - types: ~[] } + types: types } } pub fn mk_path(cx: @ext_ctxt, sp: span, +idents: ~[ast::ident]) -> @ast::expr { @@ -271,6 +271,29 @@ pub fn mk_simple_block(cx: @ext_ctxt, span: span, } } +pub fn mk_lambda_(cx: @ext_ctxt, + span: span, + fn_decl: ast::fn_decl, + blk: ast::blk) + -> @ast::expr { + mk_expr(cx, span, ast::expr_fn_block(fn_decl, blk)) +} +pub fn mk_lambda(cx: @ext_ctxt, + span: span, + fn_decl: ast::fn_decl, + expr: @ast::expr) + -> @ast::expr { + let blk = mk_simple_block(cx, span, expr); + mk_lambda_(cx, span, fn_decl, blk) +} +pub fn mk_lambda_stmts(cx: @ext_ctxt, + span: span, + fn_decl: ast::fn_decl, + stmts: ~[@ast::stmt]) + -> @ast::expr { + let blk = mk_block(cx, span, ~[], stmts, None); + mk_lambda(cx, span, fn_decl, blk) +} pub fn mk_copy(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { mk_expr(cx, sp, ast::expr_copy(e)) } @@ -337,12 +360,35 @@ pub fn mk_ty_path_global(cx: @ext_ctxt, let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span }; ty } +pub fn mk_ty_rptr(cx: @ext_ctxt, + span: span, + ty: @ast::Ty, + mutbl: ast::mutability) + -> @ast::Ty { + @ast::Ty { + id: cx.next_id(), + span: span, + node: ast::ty_rptr( + None, + ast::mt { ty: ty, mutbl: mutbl } + ), + } +} +pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty { + @ast::Ty { + id: cx.next_id(), + node: ast::ty_infer, + span: span, + } +} pub fn mk_trait_ref_global(cx: @ext_ctxt, span: span, +idents: ~[ ast::ident ]) -> @ast::trait_ref { - let path = build::mk_raw_path_global(span, idents); + mk_trait_ref_(cx, build::mk_raw_path_global(span, idents)) +} +pub fn mk_trait_ref_(cx: @ext_ctxt, path: @ast::Path) -> @ast::trait_ref { @ast::trait_ref { path: path, ref_id: cx.next_id() @@ -371,6 +417,16 @@ pub fn mk_arg(cx: @ext_ctxt, pub fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { ast::fn_decl { inputs: inputs, output: output, cf: ast::return_val } } +pub fn mk_trait_ty_param_bound_global(cx: @ext_ctxt, + span: span, + +idents: ~[ast::ident]) + -> ast::TyParamBound { + ast::TraitTyParamBound(mk_trait_ref_global(cx, span, idents)) +} +pub fn mk_trait_ty_param_bound_(cx: @ext_ctxt, + path: @ast::Path) -> ast::TyParamBound { + ast::TraitTyParamBound(mk_trait_ref_(cx, path)) +} pub fn mk_ty_param(cx: @ext_ctxt, ident: ast::ident, bounds: @OptVec) diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs new file mode 100644 index 0000000000000..81bfb03724f30 --- /dev/null +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -0,0 +1,388 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use ast; +use ast::*; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::*; +use codemap::{span, spanned}; +use ast_util; +use opt_vec; + +use core::uint; + +pub fn expand_deriving_encodable( + cx: @ext_ctxt, + span: span, + _mitem: @meta_item, + in_items: ~[@item] +) -> ~[@item] { + expand_deriving( + cx, + span, + in_items, + expand_deriving_encodable_struct_def, + expand_deriving_encodable_enum_def + ) +} + +fn create_derived_encodable_impl( + cx: @ext_ctxt, + span: span, + type_ident: ident, + generics: &Generics, + method: @method +) -> @item { + let encoder_ty_param = build::mk_ty_param( + cx, + cx.ident_of(~"__E"), + @opt_vec::with( + build::mk_trait_ty_param_bound_global( + cx, + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialize"), + cx.ident_of(~"Encoder"), + ] + ) + ) + ); + + // All the type parameters need to bound to the trait. + let generic_ty_params = opt_vec::with(encoder_ty_param); + + let methods = [method]; + let trait_path = build::mk_raw_path_global_( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialize"), + cx.ident_of(~"Encodable") + ], + ~[ + build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E")) + ] + ); + create_derived_impl( + cx, + span, + type_ident, + generics, + methods, + trait_path, + generic_ty_params + ) +} + +// Creates a method from the given set of statements conforming to the +// signature of the `encodable` method. +fn create_encode_method( + cx: @ext_ctxt, + span: span, + +statements: ~[@stmt] +) -> @method { + // Create the `e` parameter. + let e_arg_type = build::mk_ty_rptr( + cx, + span, + build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E")), + ast::m_imm + ); + let e_ident = cx.ident_of(~"__e"); + let e_arg = build::mk_arg(cx, span, e_ident, e_arg_type); + + // Create the type of the return value. + let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span }; + + // Create the function declaration. + let inputs = ~[e_arg]; + let fn_decl = build::mk_fn_decl(inputs, output_type); + + // Create the body block. + let body_block = build::mk_block_(cx, span, statements); + + // Create the method. + let self_ty = spanned { node: sty_region(None, m_imm), span: span }; + let method_ident = cx.ident_of(~"encode"); + @ast::method { + ident: method_ident, + attrs: ~[], + generics: ast_util::empty_generics(), + self_ty: self_ty, + purity: impure_fn, + decl: fn_decl, + body: body_block, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: public + } +} + +fn call_substructure_encode_method( + cx: @ext_ctxt, + span: span, + self_field: @expr +) -> @ast::expr { + // Gather up the parameters we want to chain along. + let e_ident = cx.ident_of(~"__e"); + let e_expr = build::mk_path(cx, span, ~[e_ident]); + + // Call the substructure method. + let encode_ident = cx.ident_of(~"encode"); + build::mk_method_call( + cx, + span, + self_field, + encode_ident, + ~[e_expr] + ) +} + +fn expand_deriving_encodable_struct_def( + cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident, + generics: &Generics +) -> @item { + // Create the method. + let method = expand_deriving_encodable_struct_method( + cx, + span, + type_ident, + struct_def + ); + + // Create the implementation. + create_derived_encodable_impl( + cx, + span, + type_ident, + generics, + method + ) +} + +fn expand_deriving_encodable_enum_def( + cx: @ext_ctxt, + span: span, + enum_definition: &enum_def, + type_ident: ident, + generics: &Generics +) -> @item { + // Create the method. + let method = expand_deriving_encodable_enum_method( + cx, + span, + type_ident, + enum_definition + ); + + // Create the implementation. + create_derived_encodable_impl( + cx, + span, + type_ident, + generics, + method + ) +} + +fn expand_deriving_encodable_struct_method( + cx: @ext_ctxt, + span: span, + type_ident: ident, + struct_def: &struct_def +) -> @method { + let self_ident = cx.ident_of(~"self"); + + // Create the body of the method. + let mut idx = 0; + let mut statements = ~[]; + for struct_def.fields.each |struct_field| { + match struct_field.node.kind { + named_field(ident, _, _) => { + // Create the accessor for this field. + let self_field = build::mk_access( + cx, + span, + ~[self_ident], + ident + ); + + // Call the substructure method. + let encode_expr = call_substructure_encode_method( + cx, + span, + self_field + ); + + let blk_expr = build::mk_lambda( + cx, + span, + build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)), + encode_expr + ); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__e")]), + cx.ident_of(~"emit_struct_field"), + ~[ + build::mk_base_str(cx, span, cx.str_of(ident)), + build::mk_uint(cx, span, idx), + blk_expr + ] + ); + + statements.push(build::mk_stmt(cx, span, call_expr)); + } + unnamed_field => { + cx.span_unimpl( + span, + ~"unnamed fields with `deriving(Encodable)`" + ); + } + } + idx += 1; + } + + let emit_struct_stmt = build::mk_method_call( + cx, + span, + build::mk_path( + cx, + span, + ~[cx.ident_of(~"__e")] + ), + cx.ident_of(~"emit_struct"), + ~[ + build::mk_base_str(cx, span, cx.str_of(type_ident)), + build::mk_uint(cx, span, statements.len()), + build::mk_lambda_stmts( + cx, + span, + build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)), + statements + ), + ] + ); + + let statements = ~[build::mk_stmt(cx, span, emit_struct_stmt)]; + + // Create the method itself. + return create_encode_method(cx, span, statements); +} + +fn expand_deriving_encodable_enum_method( + cx: @ext_ctxt, + span: span, + type_ident: ast::ident, + enum_definition: &enum_def +) -> @method { + // Create the arms of the match in the method body. + let arms = do enum_definition.variants.mapi |i, variant| { + // Create the matching pattern. + let pat = create_enum_variant_pattern(cx, span, variant, ~"__self"); + + // Feed the discriminant to the encode function. + let mut stmts = ~[]; + + // Feed each argument in this variant to the encode function + // as well. + let variant_arg_len = variant_arg_count(cx, span, variant); + for uint::range(0, variant_arg_len) |j| { + // Create the expression for this field. + let field_ident = cx.ident_of(~"__self" + j.to_str()); + let field = build::mk_path(cx, span, ~[ field_ident ]); + + // Call the substructure method. + let expr = call_substructure_encode_method(cx, span, field); + + let blk_expr = build::mk_lambda( + cx, + span, + build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)), + expr + ); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__e")]), + cx.ident_of(~"emit_enum_variant_arg"), + ~[ + build::mk_uint(cx, span, j), + blk_expr, + ] + ); + + stmts.push(build::mk_stmt(cx, span, call_expr)); + } + + // Create the pattern body. + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__e")]), + cx.ident_of(~"emit_enum_variant"), + ~[ + build::mk_base_str(cx, span, cx.str_of(variant.node.name)), + build::mk_uint(cx, span, i), + build::mk_uint(cx, span, variant_arg_len), + build::mk_lambda_stmts( + cx, + span, + build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)), + stmts + ) + ] + ); + + let match_body_block = build::mk_simple_block(cx, span, call_expr); + + // Create the arm. + ast::arm { + pats: ~[pat], + guard: None, + body: match_body_block, + } + }; + + // Create the method body. + let lambda_expr = build::mk_lambda( + cx, + span, + build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)), + expand_enum_or_struct_match(cx, span, arms) + ); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__e")]), + cx.ident_of(~"emit_enum"), + ~[ + build::mk_base_str(cx, span, cx.str_of(type_ident)), + lambda_expr, + ] + ); + + let stmt = build::mk_stmt(cx, span, call_expr); + + // Create the method. + create_encode_method(cx, span, ~[stmt]) +} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 95bca7ff230c7..5242d54208758 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -33,6 +33,7 @@ use core::uint; pub mod clone; pub mod eq; pub mod iter_bytes; +pub mod encodable; type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, span, @@ -76,6 +77,8 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, titem, in_items), ~"IterBytes" => iter_bytes::expand_deriving_iter_bytes(cx, titem.span, titem, in_items), + ~"Encodable" => encodable::expand_deriving_encodable(cx, + titem.span, titem, in_items), tname => { cx.span_err(titem.span, fmt!("unknown \ `deriving` trait: `%s`", tname)); From 441df26f5a1f76ed0ea185cca22c6b2c6e1307b1 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 8 Apr 2013 18:53:39 -0700 Subject: [PATCH 131/403] syntax: add support for #[deriving(Decodable)] --- src/libsyntax/ext/build.rs | 60 +++- src/libsyntax/ext/deriving/decodable.rs | 454 ++++++++++++++++++++++++ src/libsyntax/ext/deriving/mod.rs | 3 + 3 files changed, 510 insertions(+), 7 deletions(-) create mode 100644 src/libsyntax/ext/deriving/decodable.rs diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 530bb8f15417a..b375adef9263d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -279,10 +279,10 @@ pub fn mk_lambda_(cx: @ext_ctxt, mk_expr(cx, span, ast::expr_fn_block(fn_decl, blk)) } pub fn mk_lambda(cx: @ext_ctxt, - span: span, - fn_decl: ast::fn_decl, - expr: @ast::expr) - -> @ast::expr { + span: span, + fn_decl: ast::fn_decl, + expr: @ast::expr) + -> @ast::expr { let blk = mk_simple_block(cx, span, expr); mk_lambda_(cx, span, fn_decl, blk) } @@ -294,6 +294,13 @@ pub fn mk_lambda_stmts(cx: @ext_ctxt, let blk = mk_block(cx, span, ~[], stmts, None); mk_lambda(cx, span, fn_decl, blk) } +pub fn mk_lambda_no_args(cx: @ext_ctxt, + span: span, + expr: @ast::expr) + -> @ast::expr { + let fn_decl = mk_fn_decl(~[], mk_ty_infer(cx, span)); + mk_lambda(cx, span, fn_decl, expr) +} pub fn mk_copy(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { mk_expr(cx, sp, ast::expr_copy(e)) } @@ -303,11 +310,20 @@ pub fn mk_managed(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { pub fn mk_pat(cx: @ext_ctxt, span: span, +pat: ast::pat_) -> @ast::pat { @ast::pat { id: cx.next_id(), node: pat, span: span } } +pub fn mk_pat_wild(cx: @ext_ctxt, span: span) -> @ast::pat { + mk_pat(cx, span, ast::pat_wild) +} +pub fn mk_pat_lit(cx: @ext_ctxt, + span: span, + expr: @ast::expr) -> @ast::pat { + mk_pat(cx, span, ast::pat_lit(expr)) +} pub fn mk_pat_ident(cx: @ext_ctxt, span: span, ident: ast::ident) -> @ast::pat { mk_pat_ident_with_binding_mode(cx, span, ident, ast::bind_by_copy) } + pub fn mk_pat_ident_with_binding_mode(cx: @ext_ctxt, span: span, ident: ast::ident, @@ -435,8 +451,38 @@ pub fn mk_ty_param(cx: @ext_ctxt, } pub fn mk_lifetime(cx: @ext_ctxt, span: span, - ident: ast::ident) -> ast::Lifetime -{ + ident: ast::ident) + -> ast::Lifetime { ast::Lifetime { id: cx.next_id(), span: span, ident: ident } } - +pub fn mk_arm(cx: @ext_ctxt, + span: span, + pats: ~[@ast::pat], + expr: @ast::expr) + -> ast::arm { + ast::arm { + pats: pats, + guard: None, + body: mk_simple_block(cx, span, expr) + } +} +pub fn mk_unreachable(cx: @ext_ctxt, span: span) -> @ast::expr { + let loc = cx.codemap().lookup_char_pos(span.lo); + mk_call_global( + cx, + span, + ~[ + cx.ident_of(~"core"), + cx.ident_of(~"sys"), + cx.ident_of(~"begin_unwind"), + ], + ~[ + mk_uniq_str(cx, span, ~"internal error: entered unreachable code"), + mk_uniq_str(cx, span, loc.file.name), + mk_uint(cx, span, loc.line), + ] + ) +} +pub fn mk_unreachable_arm(cx: @ext_ctxt, span: span) -> ast::arm { + mk_arm(cx, span, ~[mk_pat_wild(cx, span)], mk_unreachable(cx, span)) +} diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs new file mode 100644 index 0000000000000..11f492316e281 --- /dev/null +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -0,0 +1,454 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use ast; +use ast::*; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::*; +use codemap::{span, spanned}; +use ast_util; +use opt_vec; + +use core::uint; + +pub fn expand_deriving_decodable( + cx: @ext_ctxt, + span: span, + _mitem: @meta_item, + in_items: ~[@item] +) -> ~[@item] { + expand_deriving( + cx, + span, + in_items, + expand_deriving_decodable_struct_def, + expand_deriving_decodable_enum_def + ) +} + +fn create_derived_decodable_impl( + cx: @ext_ctxt, + span: span, + type_ident: ident, + generics: &Generics, + method: @method +) -> @item { + let decoder_ty_param = build::mk_ty_param( + cx, + cx.ident_of(~"__D"), + @opt_vec::with( + build::mk_trait_ty_param_bound_global( + cx, + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialize"), + cx.ident_of(~"Decoder"), + ] + ) + ) + ); + + // All the type parameters need to bound to the trait. + let generic_ty_params = opt_vec::with(decoder_ty_param); + + let methods = [method]; + let trait_path = build::mk_raw_path_global_( + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialize"), + cx.ident_of(~"Decodable") + ], + ~[ + build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D")) + ] + ); + create_derived_impl( + cx, + span, + type_ident, + generics, + methods, + trait_path, + generic_ty_params + ) +} + +// Creates a method from the given set of statements conforming to the +// signature of the `decodable` method. +fn create_decode_method( + cx: @ext_ctxt, + span: span, + type_ident: ast::ident, + generics: &Generics, + expr: @ast::expr +) -> @method { + // Create the `e` parameter. + let d_arg_type = build::mk_ty_rptr( + cx, + span, + build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D")), + ast::m_imm + ); + let d_ident = cx.ident_of(~"__d"); + let d_arg = build::mk_arg(cx, span, d_ident, d_arg_type); + + // Create the type of the return value. + let output_type = create_self_type_with_params( + cx, + span, + type_ident, + generics + ); + + // Create the function declaration. + let inputs = ~[d_arg]; + let fn_decl = build::mk_fn_decl(inputs, output_type); + + // Create the body block. + let body_block = build::mk_simple_block(cx, span, expr); + + // Create the method. + let self_ty = spanned { node: sty_static, span: span }; + let method_ident = cx.ident_of(~"decode"); + @ast::method { + ident: method_ident, + attrs: ~[], + generics: ast_util::empty_generics(), + self_ty: self_ty, + purity: impure_fn, + decl: fn_decl, + body: body_block, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: public + } +} + +fn call_substructure_decode_method( + cx: @ext_ctxt, + span: span +) -> @ast::expr { + // Call the substructure method. + build::mk_call_( + cx, + span, + build::mk_path_global( + cx, + span, + ~[ + cx.ident_of(~"std"), + cx.ident_of(~"serialize"), + cx.ident_of(~"Decodable"), + cx.ident_of(~"decode"), + ] + ), + ~[ + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]) + ] + ) +} + +fn expand_deriving_decodable_struct_def( + cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident, + generics: &Generics +) -> @item { + // Create the method. + let method = expand_deriving_decodable_struct_method( + cx, + span, + struct_def, + type_ident, + generics + ); + + // Create the implementation. + create_derived_decodable_impl( + cx, + span, + type_ident, + generics, + method + ) +} + +fn expand_deriving_decodable_enum_def( + cx: @ext_ctxt, + span: span, + enum_definition: &enum_def, + type_ident: ident, + generics: &Generics +) -> @item { + // Create the method. + let method = expand_deriving_decodable_enum_method( + cx, + span, + enum_definition, + type_ident, + generics + ); + + // Create the implementation. + create_derived_decodable_impl( + cx, + span, + type_ident, + generics, + method + ) +} + +fn create_read_struct_field( + cx: @ext_ctxt, + span: span, + idx: uint, + ident: ident +) -> build::Field { + // Call the substructure method. + let decode_expr = call_substructure_decode_method(cx, span); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]), + cx.ident_of(~"read_struct_field"), + ~[ + build::mk_base_str(cx, span, cx.str_of(ident)), + build::mk_uint(cx, span, idx), + build::mk_lambda_no_args(cx, span, decode_expr), + ] + ); + + build::Field { ident: ident, ex: call_expr } +} + +fn create_read_struct_arg( + cx: @ext_ctxt, + span: span, + idx: uint, + ident: ident +) -> build::Field { + // Call the substructure method. + let decode_expr = call_substructure_decode_method(cx, span); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]), + cx.ident_of(~"read_struct_arg"), + ~[ + build::mk_uint(cx, span, idx), + build::mk_lambda_no_args(cx, span, decode_expr), + ] + ); + + build::Field { ident: ident, ex: call_expr } +} + +fn expand_deriving_decodable_struct_method( + cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident, + generics: &Generics +) -> @method { + // Create the body of the method. + let mut i = 0; + let mut fields = ~[]; + for struct_def.fields.each |struct_field| { + match struct_field.node.kind { + named_field(ident, _, _) => { + fields.push(create_read_struct_field(cx, span, i, ident)); + } + unnamed_field => { + cx.span_unimpl( + span, + ~"unnamed fields with `deriving(Decodable)`" + ); + } + } + i += 1; + } + + let read_struct_expr = build::mk_method_call( + cx, + span, + build::mk_path( + cx, + span, + ~[cx.ident_of(~"__d")] + ), + cx.ident_of(~"read_struct"), + ~[ + build::mk_base_str(cx, span, cx.str_of(type_ident)), + build::mk_uint(cx, span, fields.len()), + build::mk_lambda_no_args( + cx, + span, + build::mk_struct_e( + cx, + span, + ~[type_ident], + fields + ) + ), + ] + ); + + // Create the method itself. + create_decode_method(cx, span, type_ident, generics, read_struct_expr) +} + +fn create_read_variant_arg( + cx: @ext_ctxt, + span: span, + idx: uint, + variant: &ast::variant +) -> ast::arm { + // Create the matching pattern. + let pat = build::mk_pat_lit(cx, span, build::mk_uint(cx, span, idx)); + + // Feed each argument in this variant to the decode function + // as well. + let variant_arg_len = variant_arg_count(cx, span, variant); + + let expr = if variant_arg_len == 0 { + build::mk_path(cx, span, ~[variant.node.name]) + } else { + // Feed the discriminant to the decode function. + let mut args = ~[]; + + for uint::range(0, variant_arg_len) |j| { + // Call the substructure method. + let expr = call_substructure_decode_method(cx, span); + + let call_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]), + cx.ident_of(~"read_enum_variant_arg"), + ~[ + build::mk_uint(cx, span, j), + build::mk_lambda_no_args(cx, span, expr), + ] + ); + + args.push(call_expr); + } + + build::mk_call( + cx, + span, + ~[variant.node.name], + args + ) + }; + + // Create the arm. + build::mk_arm(cx, span, ~[pat], expr) +} + +fn create_read_enum_variant( + cx: @ext_ctxt, + span: span, + enum_definition: &enum_def +) -> @expr { + // Create a vector that contains all the variant names. + let expr_arm_names = build::mk_base_vec_e( + cx, + span, + do enum_definition.variants.map |variant| { + build::mk_base_str( + cx, + span, + cx.str_of(variant.node.name) + ) + } + ); + + // Create the arms of the match in the method body. + let mut arms = do enum_definition.variants.mapi |i, variant| { + create_read_variant_arg(cx, span, i, variant) + }; + + // Add the impossible case arm. + arms.push(build::mk_unreachable_arm(cx, span)); + + // Create the read_enum_variant expression. + build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]), + cx.ident_of(~"read_enum_variant"), + ~[ + expr_arm_names, + build::mk_lambda( + cx, + span, + build::mk_fn_decl( + ~[ + build::mk_arg( + cx, + span, + cx.ident_of(~"__i"), + build::mk_ty_infer(cx, span) + ) + ], + build::mk_ty_infer(cx, span) + ), + build::mk_expr( + cx, + span, + ast::expr_match( + build::mk_path(cx, span, ~[cx.ident_of(~"__i")]), + arms + ) + ) + ) + ] + ) +} + +fn expand_deriving_decodable_enum_method( + cx: @ext_ctxt, + span: span, + enum_definition: &enum_def, + type_ident: ast::ident, + generics: &Generics +) -> @method { + let read_enum_variant_expr = create_read_enum_variant( + cx, + span, + enum_definition + ); + + // Create the read_enum expression + let read_enum_expr = build::mk_method_call( + cx, + span, + build::mk_path(cx, span, ~[cx.ident_of(~"__d")]), + cx.ident_of(~"read_enum"), + ~[ + build::mk_base_str(cx, span, cx.str_of(type_ident)), + build::mk_lambda_no_args(cx, span, read_enum_variant_expr), + ] + ); + + // Create the method. + create_decode_method(cx, span, type_ident, generics, read_enum_expr) +} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 5242d54208758..63106eae48ae8 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -34,6 +34,7 @@ pub mod clone; pub mod eq; pub mod iter_bytes; pub mod encodable; +pub mod decodable; type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, span, @@ -79,6 +80,8 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, titem.span, titem, in_items), ~"Encodable" => encodable::expand_deriving_encodable(cx, titem.span, titem, in_items), + ~"Decodable" => decodable::expand_deriving_decodable(cx, + titem.span, titem, in_items), tname => { cx.span_err(titem.span, fmt!("unknown \ `deriving` trait: `%s`", tname)); From e31f7b7c74f54cc80f908dc074f3efb95e5b36d5 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Apr 2013 19:44:12 -0700 Subject: [PATCH 132/403] std: add serialize {read,emit}_tuple{,_arg,_struct,_struct_arg} --- src/libstd/ebml.rs | 26 ++++++++++++++++++++++++++ src/libstd/json.rs | 32 ++++++++++++++++++++++++++++++++ src/libstd/serialize.rs | 12 ++++++++++++ src/libsyntax/ext/auto_encode.rs | 14 ++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 28933d553e6ef..a7a6e827febe0 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -356,6 +356,26 @@ pub mod reader { f() } + fn read_tuple(&self, f: &fn(uint) -> T) -> T { + debug!("read_tuple()"); + self.read_seq(f) + } + + fn read_tuple_arg(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_tuple_arg(idx=%u)", idx); + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct(&self, name: &str, f: &fn(uint) -> T) -> T { + debug!("read_tuple_struct(name=%?)", name); + self.read_tuple(f) + } + + fn read_tuple_struct_arg(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_tuple_struct_arg(idx=%u)", idx); + self.read_tuple_arg(idx, f) + } + fn read_option(&self, f: &fn(bool) -> T) -> T { debug!("read_option()"); do self.read_enum("Option") || { @@ -637,6 +657,12 @@ pub mod writer { f() } + fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + + fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + fn emit_option(&self, f: &fn()) { self.emit_enum("Option", f); } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 4b5e1f1422990..658a6ce281f20 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -152,6 +152,12 @@ impl serialize::Encoder for Encoder { f(); } + fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + + fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + fn emit_option(&self, f: &fn()) { f(); } fn emit_option_none(&self) { self.emit_nil(); } fn emit_option_some(&self, f: &fn()) { f(); } @@ -291,6 +297,12 @@ impl serialize::Encoder for PrettyEncoder { f(); } + fn emit_tuple(&self, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + + fn emit_tuple_struct(&self, _name: &str, len: uint, f: &fn()) { self.emit_seq(len, f) } + fn emit_tuple_struct_arg(&self, idx: uint, f: &fn()) { self.emit_seq_elt(idx, f) } + fn emit_option(&self, f: &fn()) { f(); } fn emit_option_none(&self) { self.emit_nil(); } fn emit_option_some(&self, f: &fn()) { f(); } @@ -901,6 +913,26 @@ impl serialize::Decoder for Decoder { } } + fn read_tuple(&self, f: &fn(uint) -> T) -> T { + debug!("read_tuple()"); + self.read_seq(f) + } + + fn read_tuple_arg(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_tuple_arg(idx=%u)", idx); + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct(&self, name: &str, f: &fn(uint) -> T) -> T { + debug!("read_tuple_struct(name=%?)", name); + self.read_tuple(f) + } + + fn read_tuple_struct_arg(&self, idx: uint, f: &fn() -> T) -> T { + debug!("read_tuple_struct_arg(idx=%u)", idx); + self.read_tuple_arg(idx, f) + } + fn read_option(&self, f: &fn(bool) -> T) -> T { match self.stack.pop() { Null => f(false), diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index cc3a1ec028983..2a685b2f1d62b 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -56,6 +56,12 @@ pub trait Encoder { #[cfg(stage3)] fn emit_struct_field(&self, f_name: &str, f_idx: uint, f: &fn()); + fn emit_tuple(&self, len: uint, f: &fn()); + fn emit_tuple_arg(&self, idx: uint, f: &fn()); + + fn emit_tuple_struct(&self, name: &str, len: uint, f: &fn()); + fn emit_tuple_struct_arg(&self, f_idx: uint, f: &fn()); + // Specialized types: fn emit_option(&self, f: &fn()); fn emit_option_none(&self); @@ -102,6 +108,12 @@ pub trait Decoder { #[cfg(stage3)] fn read_struct_field(&self, f_name: &str, f_idx: uint, f: &fn() -> T) -> T; + fn read_tuple(&self, f: &fn(uint) -> T) -> T; + fn read_tuple_arg(&self, a_idx: uint, f: &fn() -> T) -> T; + + fn read_tuple_struct(&self, s_name: &str, f: &fn(uint) -> T) -> T; + fn read_tuple_struct_arg(&self, a_idx: uint, f: &fn() -> T) -> T; + // Specialized types: fn read_option(&self, f: &fn(bool) -> T) -> T; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 38bac6b1f438d..287c2d7ba84f8 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -1260,6 +1260,20 @@ mod test { self.add_to_log(CallToEmitField (name.to_str(),idx)); f(); } + fn emit_tuple(&self, _len: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + fn emit_tuple_arg(&self, _idx: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + + fn emit_tuple_struct(&self, _name: &str, _len: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + fn emit_tuple_struct_arg(&self, _idx: uint, f: &fn()) { + self.add_unknown_to_log(); f(); + } + fn emit_option(&self, f: &fn()) { self.add_to_log(CallToEmitOption); f(); From f3ab67ec5f75fc3376e5647dfb7e5b46a535dea7 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Apr 2013 19:45:10 -0700 Subject: [PATCH 133/403] syntax: add {read,emit}_enum_struct_variant{,_field} --- src/libstd/ebml.rs | 24 +++++++++++++++++++++++ src/libstd/json.rs | 33 +++++++++++++++++++++++++++++++- src/libstd/serialize.rs | 14 +++++++++++--- src/libsyntax/ext/auto_encode.rs | 8 ++++++++ 4 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index a7a6e827febe0..4a3447700bc8f 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -335,6 +335,20 @@ pub mod reader { f() } + fn read_enum_struct_variant(&self, _names: &[&str], f: &fn(uint) -> T) -> T { + debug!("read_enum_struct_variant()"); + let idx = self._next_uint(EsEnumVid); + debug!(" idx=%u", idx); + do self.push_doc(self.next_doc(EsEnumBody)) { + f(idx) + } + } + + fn read_enum_struct_variant_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { + debug!("read_enum_struct_variant_arg(name=%?, idx=%u)", name, idx); + f() + } + fn read_struct(&self, name: &str, _len: uint, f: &fn() -> T) -> T { debug!("read_struct(name=%s)", name); f() @@ -636,13 +650,23 @@ pub mod writer { self._emit_label(name); self.wr_tag(EsEnum as uint, f) } + fn emit_enum_variant(&self, _v_name: &str, v_id: uint, _cnt: uint, f: &fn()) { self._emit_tagged_uint(EsEnumVid, v_id); self.wr_tag(EsEnumBody as uint, f) } + fn emit_enum_variant_arg(&self, _idx: uint, f: &fn()) { f() } + fn emit_enum_struct_variant(&self, v_name: &str, v_id: uint, cnt: uint, f: &fn()) { + self.emit_enum_variant(v_name, v_id, cnt, f) + } + + fn emit_enum_struct_variant_field(&self, _f_name: &str, idx: uint, f: &fn()) { + self.emit_enum_variant_arg(idx, f) + } + fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { f() } #[cfg(stage0)] fn emit_field(&self, name: &str, _idx: uint, f: &fn()) { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 658a6ce281f20..f5cd8b4bd6830 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -109,6 +109,7 @@ impl serialize::Encoder for Encoder { fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)) } fn emit_enum(&self, _name: &str, f: &fn()) { f() } + fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) { // enums are encoded as strings or vectors: // Bunny => "Bunny" @@ -126,10 +127,18 @@ impl serialize::Encoder for Encoder { } fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) { - if (idx != 0) {self.wr.write_char(',');} + if idx != 0 {self.wr.write_char(',');} f(); } + fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) { + self.emit_enum_variant(name, id, cnt, f) + } + + fn emit_enum_struct_variant_field(&self, _field: &str, idx: uint, f: &fn()) { + self.emit_enum_variant_arg(idx, f) + } + fn emit_struct(&self, _name: &str, _len: uint, f: &fn()) { self.wr.write_char('{'); f(); @@ -232,6 +241,7 @@ impl serialize::Encoder for PrettyEncoder { fn emit_str(&self, v: &str) { self.wr.write_str(escape_str(v)); } fn emit_enum(&self, _name: &str, f: &fn()) { f() } + fn emit_enum_variant(&self, name: &str, _id: uint, cnt: uint, f: &fn()) { if cnt == 0 { self.wr.write_str(escape_str(name)); @@ -249,6 +259,7 @@ impl serialize::Encoder for PrettyEncoder { self.wr.write_char(']'); } } + fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) { if idx != 0 { self.wr.write_str(",\n"); @@ -257,6 +268,15 @@ impl serialize::Encoder for PrettyEncoder { f() } + fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) { + self.emit_enum_variant(name, id, cnt, f) + } + + fn emit_enum_struct_variant_field(&self, _field: &str, idx: uint, f: &fn()) { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&self, _name: &str, len: uint, f: &fn()) { if len == 0 { self.wr.write_str("{}"); @@ -864,6 +884,17 @@ impl serialize::Decoder for Decoder { f() } + fn read_enum_struct_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T { + debug!("read_enum_struct_variant(names=%?)", names); + self.read_enum_variant(names, f) + } + + + fn read_enum_struct_variant_field(&self, name: &str, idx: uint, f: &fn() -> T) -> T { + debug!("read_enum_struct_variant_field(name=%?, idx=%u)", name, idx); + self.read_enum_variant_arg(idx, f) + } + fn read_struct(&self, name: &str, len: uint, f: &fn() -> T) -> T { debug!("read_struct(name=%s, len=%u)", name, len); let value = f(); diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 2a685b2f1d62b..68ae9a6641726 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -45,8 +45,12 @@ pub trait Encoder { // Compound types: fn emit_enum(&self, name: &str, f: &fn()); - fn emit_enum_variant(&self, v_name: &str, v_id: uint, sz: uint, f: &fn()); - fn emit_enum_variant_arg(&self, idx: uint, f: &fn()); + + fn emit_enum_variant(&self, v_name: &str, v_id: uint, len: uint, f: &fn()); + fn emit_enum_variant_arg(&self, a_idx: uint, f: &fn()); + + fn emit_enum_struct_variant(&self, v_name: &str, v_id: uint, len: uint, f: &fn()); + fn emit_enum_struct_variant_field(&self, f_name: &str, f_idx: uint, f: &fn()); fn emit_struct(&self, name: &str, len: uint, f: &fn()); #[cfg(stage0)] @@ -97,8 +101,12 @@ pub trait Decoder { // Compound types: fn read_enum(&self, name: &str, f: &fn() -> T) -> T; + fn read_enum_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T; - fn read_enum_variant_arg(&self, idx: uint, f: &fn() -> T) -> T; + fn read_enum_variant_arg(&self, a_idx: uint, f: &fn() -> T) -> T; + + fn read_enum_struct_variant(&self, names: &[&str], f: &fn(uint) -> T) -> T; + fn read_enum_struct_variant_field(&self, &f_name: &str, f_idx: uint, f: &fn() -> T) -> T; fn read_struct(&self, s_name: &str, len: uint, f: &fn() -> T) -> T; #[cfg(stage0)] diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 287c2d7ba84f8..e53a8f361b5fe 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -1253,6 +1253,14 @@ mod test { self.add_to_log(CallToEmitEnumVariantArg (idx)); f(); } + fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) { + self.emit_enum_variant(name, id, cnt, f) + } + + fn emit_enum_struct_variant_field(&self, _name: &str, idx: uint, f: &fn()) { + self.emit_enum_variant_arg(idx, f) + } + fn emit_struct(&self, name: &str, +len: uint, f: &fn()) { self.add_to_log(CallToEmitStruct (name.to_str(),len)); f(); } From 26ecb30f550a46d52528a7d45d9327ebce938e81 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 9 Apr 2013 08:36:38 -0700 Subject: [PATCH 134/403] test: update serialization tests to use new macro --- src/test/run-pass/auto-encode.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index e0720876900ff..bfc15acaa763c 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -22,7 +22,7 @@ use EBWriter = std::ebml::writer; use core::cmp::Eq; use core::io::Writer; use std::ebml; -use std::serialize::{Encodable, Decodable}; +use std::serialize::{Decodable, Encodable}; use std::time; fn test_ebml bool { !self.eq(other) } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] +#[deriving(Decodable, Encodable, Eq)] struct Spanned { lo: uint, hi: uint, node: T, } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] struct SomeStruct { v: ~[uint] } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] struct Point {x: uint, y: uint} -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] enum Quark { Top(T), Bottom(T) } -#[auto_encode] -#[auto_decode] +#[deriving(Decodable, Encodable)] enum CLike { A, B, C } pub fn main() { From 49de82cdca2064a909d3104f4e5eccacb0425fd0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 10 Apr 2013 13:11:27 -0700 Subject: [PATCH 135/403] Issue #5656: Make &self not mean "&'self self" Fixes #5656. Fixes #5541. --- src/librustc/middle/kind.rs | 2 +- src/librustc/middle/region.rs | 29 +- src/librustc/middle/subst.rs | 47 +-- src/librustc/middle/ty.rs | 3 +- src/librustc/middle/typeck/check/method.rs | 283 ++++++++---------- src/librustc/middle/typeck/check/mod.rs | 71 ++--- .../middle/typeck/check/regionmanip.rs | 42 +-- src/librustc/middle/typeck/check/vtable.rs | 7 +- src/librustc/middle/typeck/coherence.rs | 2 +- src/librustc/middle/typeck/collect.rs | 97 ++++-- src/librustc/middle/typeck/rscope.rs | 5 +- src/librustc/util/ppaux.rs | 6 + src/libsyntax/ast.rs | 9 - src/libsyntax/ext/base.rs | 13 + src/libsyntax/opt_vec.rs | 11 + src/libsyntax/print/pprust.rs | 4 + 16 files changed, 336 insertions(+), 295 deletions(-) diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 1f8401c0d533e..e5fc9f2d60391 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -16,7 +16,7 @@ use middle::liveness; use middle::pat_util; use middle::ty; use middle::typeck; -use util::ppaux::{Repr, ty_to_str, tys_to_str}; +use util::ppaux::{Repr, ty_to_str}; use syntax::ast::*; use syntax::attr::attrs_contains_name; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 7913009707868..ecb9fc2cd08b8 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -544,10 +544,6 @@ pub struct DetermineRpCtxt { // see long discussion on region_is_relevant(). anon_implies_rp: bool, - // true when we are not within an &self method. - // see long discussion on region_is_relevant(). - self_implies_rp: bool, - // encodes the context of the current type; invariant if // mutable, covariant otherwise ambient_variance: region_variance, @@ -689,7 +685,7 @@ pub impl DetermineRpCtxt { false } Some(ref l) if l.ident == special_idents::self_ => { - self.self_implies_rp + true } Some(_) => { false @@ -700,23 +696,18 @@ pub impl DetermineRpCtxt { fn with(@mut self, item_id: ast::node_id, anon_implies_rp: bool, - self_implies_rp: bool, f: &fn()) { let old_item_id = self.item_id; let old_anon_implies_rp = self.anon_implies_rp; - let old_self_implies_rp = self.self_implies_rp; self.item_id = item_id; self.anon_implies_rp = anon_implies_rp; - self.self_implies_rp = self_implies_rp; - debug!("with_item_id(%d, %b, %b)", + debug!("with_item_id(%d, %b)", item_id, - anon_implies_rp, - self_implies_rp); + anon_implies_rp); let _i = ::util::common::indenter(); f(); self.item_id = old_item_id; self.anon_implies_rp = old_anon_implies_rp; - self.self_implies_rp = old_self_implies_rp; } fn with_ambient_variance(@mut self, variance: region_variance, f: &fn()) { @@ -730,7 +721,7 @@ pub impl DetermineRpCtxt { pub fn determine_rp_in_item(item: @ast::item, &&cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { - do cx.with(item.id, true, true) { + do cx.with(item.id, true) { visit::visit_item(item, cx, visitor); } } @@ -742,12 +733,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind, _: ast::node_id, &&cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { - let self_implies_rp = match fk { - &visit::fk_method(_, _, m) => !m.self_ty.node.is_borrowed(), - _ => true - }; - - do cx.with(cx.item_id, false, self_implies_rp) { + do cx.with(cx.item_id, false) { do cx.with_ambient_variance(rv_contravariant) { for decl.inputs.each |a| { (visitor.visit_ty)(a.ty, cx, visitor); @@ -763,7 +749,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind, pub fn determine_rp_in_ty_method(ty_m: &ast::ty_method, &&cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { - do cx.with(cx.item_id, false, !ty_m.self_ty.node.is_borrowed()) { + do cx.with(cx.item_id, false) { visit::visit_ty_method(ty_m, cx, visitor); } } @@ -868,7 +854,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => { // fn() binds the & region, so do not consider &T types that // appear *inside* a fn() type to affect the enclosing item: - do cx.with(cx.item_id, false, true) { + do cx.with(cx.item_id, false) { // parameters are contravariant do cx.with_ambient_variance(rv_contravariant) { for decl.inputs.each |a| { @@ -929,7 +915,6 @@ pub fn determine_rp_in_crate(sess: Session, worklist: ~[], item_id: 0, anon_implies_rp: false, - self_implies_rp: true, ambient_variance: rv_covariant }; diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index a754f93f01038..35257f9574c36 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -62,22 +62,7 @@ impl EffectfulSubst for ty::t { _ => { ty::fold_regions_and_ty( tcx, *self, - |r| match r { - ty::re_bound(ty::br_self) => { - match substs.self_r { - None => { - tcx.sess.bug( - fmt!("ty::subst: \ - Reference to self region when \ - given substs with no self region, \ - ty = %s", - self.repr(tcx))); - } - Some(self_r) => self_r - } - } - _ => r - }, + |r| r.subst(tcx, substs), |t| t.effectfulSubst(tcx, substs), |t| t.effectfulSubst(tcx, substs)) } @@ -118,7 +103,7 @@ impl Subst for ty::TraitRef { impl Subst for ty::substs { fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::substs { ty::substs { - self_r: self.self_r, + self_r: self.self_r.subst(tcx, substs), self_ty: self.self_ty.map(|typ| typ.subst(tcx, substs)), tps: self.tps.map(|typ| typ.subst(tcx, substs)) } @@ -166,6 +151,34 @@ impl Subst for ty::Generics { } } +impl Subst for ty::Region { + fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Region { + // Note: This routine only handles the self region, because it + // is only concerned with substitutions of regions that appear + // in types. Region substitution of the bound regions that + // appear in a function signature is done using the + // specialized routine + // `middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig()`. + // As we transition to the new region syntax this distinction + // will most likely disappear. + match self { + &ty::re_bound(ty::br_self) => { + match substs.self_r { + None => { + tcx.sess.bug( + fmt!("ty::Region#subst(): \ + Reference to self region when \ + given substs with no self region: %s", + substs.repr(tcx))); + } + Some(self_r) => self_r + } + } + _ => *self + } + } +} + impl Subst for ty::ty_param_bounds_and_ty { fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3921764e6afa8..2b4a4235950c8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -24,8 +24,7 @@ use middle::subst::Subst; use middle::typeck; use middle; use util::ppaux::{note_and_explain_region, bound_region_to_str}; -use util::ppaux::{region_to_str, vstore_to_str}; -use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str}; +use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str}; use util::ppaux::Repr; use util::common::{indenter}; diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 6a274e7f9eb07..6b09133e73a11 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -178,15 +178,6 @@ pub struct Candidate { origin: method_origin, } -/** - * How the self type should be transformed according to the form of explicit - * self provided by the method. - */ -pub enum TransformTypeFlag { - TransformTypeNormally, - TransformTypeForObject, -} - pub impl<'self> LookupContext<'self> { fn do_lookup(&self, self_ty: ty::t) -> Option { let mut self_ty = structurally_resolved_type(self.fcx, @@ -285,13 +276,13 @@ pub impl<'self> LookupContext<'self> { fn push_inherent_candidates(&self, self_ty: ty::t) { /*! - * * Collect all inherent candidates into * `self.inherent_candidates`. See comment at the start of * the file. To find the inherent candidates, we repeatedly * deref the self-ty to find the "base-type". So, for * example, if the receiver is @@C where `C` is a struct type, - * we'll want to find the inherent impls for `C`. */ + * we'll want to find the inherent impls for `C`. + */ let mut enum_dids = ~[]; let mut self_ty = self_ty; @@ -407,16 +398,9 @@ pub impl<'self> LookupContext<'self> { }; let method = trait_methods[pos]; - let (rcvr_ty, rcvr_substs) = - self.create_rcvr_ty_and_substs_for_method( - method.self_ty, - rcvr_ty, - copy bound_trait_ref.substs, - TransformTypeNormally); - let cand = Candidate { rcvr_ty: rcvr_ty, - rcvr_substs: rcvr_substs, + rcvr_substs: copy bound_trait_ref.substs, method_ty: method, origin: method_param( method_param { @@ -476,14 +460,8 @@ pub impl<'self> LookupContext<'self> { ../*bad*/copy *substs }; - let (rcvr_ty, rcvr_substs) = - self.create_rcvr_ty_and_substs_for_method(method.self_ty, - self_ty, - rcvr_substs, - TransformTypeForObject); - self.inherent_candidates.push(Candidate { - rcvr_ty: rcvr_ty, + rcvr_ty: self_ty, rcvr_substs: rcvr_substs, method_ty: method, origin: method_trait(did, index, store) @@ -538,19 +516,13 @@ pub impl<'self> LookupContext<'self> { // We've found a method -- return it let rcvr_substs = substs {self_ty: Some(self_ty), ..copy *substs }; - let (rcvr_ty, rcvr_substs) = - self.create_rcvr_ty_and_substs_for_method( - info.method_ty.self_ty, - self_ty, - rcvr_substs, - TransformTypeNormally); let origin = if did == info.trait_def_id { method_self(info.trait_def_id, info.index) } else { method_super(info.trait_def_id, info.index) }; self.inherent_candidates.push(Candidate { - rcvr_ty: rcvr_ty, + rcvr_ty: self_ty, rcvr_substs: rcvr_substs, method_ty: info.method_ty, origin: origin @@ -598,13 +570,6 @@ pub impl<'self> LookupContext<'self> { ty: impl_ty } = impl_self_ty(&vcx, location_info, impl_info.did); - let (impl_ty, impl_substs) = - self.create_rcvr_ty_and_substs_for_method( - method.self_ty, - impl_ty, - impl_substs, - TransformTypeNormally); - candidates.push(Candidate { rcvr_ty: impl_ty, rcvr_substs: impl_substs, @@ -639,69 +604,16 @@ pub impl<'self> LookupContext<'self> { self_ty: None, tps: ~[] }; - let (impl_ty, impl_substs) = - self.create_rcvr_ty_and_substs_for_method( - method.self_ty, - self_ty, - dummy_substs, - TransformTypeNormally); candidates.push(Candidate { - rcvr_ty: impl_ty, - rcvr_substs: impl_substs, + rcvr_ty: self_ty, + rcvr_substs: dummy_substs, method_ty: method, origin: method_static(provided_method_info.method_info.did) }); } } - fn create_rcvr_ty_and_substs_for_method(&self, - self_decl: ast::self_ty_, - self_ty: ty::t, - +self_substs: ty::substs, - transform_type: TransformTypeFlag) - -> (ty::t, ty::substs) { - // If the self type includes a region (like &self), we need to - // ensure that the receiver substitutions have a self region. - // If the receiver type does not itself contain borrowed - // pointers, there may not be one yet. - // - // FIXME(#3446)--this awkward situation comes about because - // the regions in the receiver are substituted before (and - // differently from) those in the argument types. This - // shouldn't really have to be. - let rcvr_substs = { - match self_decl { - sty_static | sty_value | - sty_box(_) | sty_uniq(_) => { - self_substs - } - sty_region(*) if self_substs.self_r.is_some() => { - // FIXME(#4846) ignoring expl lifetime here - self_substs - } - sty_region(*) => { - // FIXME(#4846) ignoring expl lifetime here - substs { - self_r: - Some(self.infcx().next_region_var( - self.expr.span, - self.expr.id)), - ..self_substs - } - } - } - }; - - let rcvr_ty = transform_self_type_for_method(self.tcx(), - rcvr_substs.self_r, - self_ty, - self_decl, - transform_type); - - (rcvr_ty, rcvr_substs) - } - // ______________________________________________________________________ // Candidate selection (see comment at start of file) @@ -1036,20 +948,34 @@ pub impl<'self> LookupContext<'self> { self.enforce_trait_instance_limitations(fty, candidate); self.enforce_drop_trait_limitations(candidate); - // before we only checked whether self_ty could be a subtype - // of rcvr_ty; now we actually make it so (this may cause - // variables to unify etc). Since we checked beforehand, and - // nothing has changed in the meantime, this unification - // should never fail. - match self.fcx.mk_subty(false, self.self_expr.span, - self_ty, candidate.rcvr_ty) { - result::Ok(_) => (), - result::Err(_) => { - self.bug(fmt!("%s was assignable to %s but now is not?", - self.ty_to_str(self_ty), - self.ty_to_str(candidate.rcvr_ty))); + // static methods should never have gotten this far: + assert!(candidate.method_ty.self_ty != sty_static); + + let transformed_self_ty = match candidate.origin { + method_trait(*) => { + match candidate.method_ty.self_ty { + sty_region(*) => { + // FIXME(#5762) again, preserving existing + // behavior here which (for &self) desires + // &@Trait where @Trait is the type of the + // receiver. Here we fetch the method's + // transformed_self_ty which will be something + // like &'a Self. We then perform a + // substitution which will replace Self with + // @Trait. + let t = candidate.method_ty.transformed_self_ty.get(); + ty::subst(tcx, &candidate.rcvr_substs, t) + } + _ => { + candidate.rcvr_ty + } + } } - } + _ => { + let t = candidate.method_ty.transformed_self_ty.get(); + ty::subst(tcx, &candidate.rcvr_substs, t) + } + }; // Determine the values for the type parameters of the method. // If they were not explicitly supplied, just construct fresh @@ -1100,16 +1026,32 @@ pub impl<'self> LookupContext<'self> { fmt!("Invoking method with non-bare-fn ty: %?", s)); } }; - let (_, _, fn_sig) = + let (_, opt_transformed_self_ty, fn_sig) = replace_bound_regions_in_fn_sig( - tcx, @Nil, None, &bare_fn_ty.sig, + tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig, |_br| self.fcx.infcx().next_region_var( self.expr.span, self.expr.id)); + let transformed_self_ty = opt_transformed_self_ty.get(); let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty}); debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty)); let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty); + // before we only checked whether self_ty could be a subtype + // of rcvr_ty; now we actually make it so (this may cause + // variables to unify etc). Since we checked beforehand, and + // nothing has changed in the meantime, this unification + // should never fail. + match self.fcx.mk_subty(false, self.self_expr.span, + self_ty, transformed_self_ty) { + result::Ok(_) => (), + result::Err(_) => { + self.bug(fmt!("%s was a subtype of %s but now is not?", + self.ty_to_str(self_ty), + self.ty_to_str(transformed_self_ty))); + } + } + self.fcx.write_ty(self.callee_id, fty); self.fcx.write_substs(self.callee_id, all_substs); method_map_entry { @@ -1180,7 +1122,87 @@ pub impl<'self> LookupContext<'self> { debug!("is_relevant(self_ty=%s, candidate=%s)", self.ty_to_str(self_ty), self.cand_to_str(candidate)); - self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok() + // Check for calls to object methods. We resolve these differently. + // + // FIXME(#5762)---we don't check that an @self method is only called + // on an @Trait object here and so forth + match candidate.origin { + method_trait(*) => { + match candidate.method_ty.self_ty { + sty_static | sty_value => { + return false; + } + sty_region(*) => { + // just echoing current behavior here, which treats + // an &self method on an @Trait object as requiring + // an &@Trait receiver (wacky) + } + sty_box(*) | sty_uniq(*) => { + return self.fcx.can_mk_subty(self_ty, + candidate.rcvr_ty).is_ok(); + } + }; + } + _ => {} + } + + return match candidate.method_ty.self_ty { + sty_static => { + false + } + + sty_value => { + self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok() + } + + sty_region(_, m) => { + match ty::get(self_ty).sty { + ty::ty_rptr(_, mt) => { + mutability_matches(mt.mutbl, m) && + self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + } + + _ => false + } + } + + sty_box(m) => { + match ty::get(self_ty).sty { + ty::ty_box(mt) => { + mutability_matches(mt.mutbl, m) && + self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + } + + _ => false + } + } + + sty_uniq(m) => { + match ty::get(self_ty).sty { + ty::ty_uniq(mt) => { + mutability_matches(mt.mutbl, m) && + self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + } + + _ => false + } + } + }; + + fn mutability_matches(self_mutbl: ast::mutability, + candidate_mutbl: ast::mutability) -> bool { + //! True if `self_mutbl <: candidate_mutbl` + + match (self_mutbl, candidate_mutbl) { + (_, m_const) => true, + (m_mutbl, m_mutbl) => true, + (m_imm, m_imm) => true, + (m_mutbl, m_imm) => false, + (m_imm, m_mutbl) => false, + (m_const, m_imm) => false, + (m_const, m_mutbl) => false, + } + } } fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t { @@ -1281,45 +1303,6 @@ pub impl<'self> LookupContext<'self> { } } -pub fn transform_self_type_for_method(tcx: ty::ctxt, - self_region: Option, - impl_ty: ty::t, - self_type: ast::self_ty_, - flag: TransformTypeFlag) - -> ty::t { - match self_type { - sty_static => { - tcx.sess.bug(~"calling transform_self_type_for_method on \ - static method"); - } - sty_value => { - impl_ty - } - sty_region(_, mutability) => { - // FIXME(#4846) ignoring expl lifetime here - mk_rptr(tcx, - self_region.expect(~"self region missing for &self param"), - ty::mt { ty: impl_ty, mutbl: mutability }) - } - sty_box(mutability) => { - match flag { - TransformTypeNormally => { - mk_box(tcx, ty::mt { ty: impl_ty, mutbl: mutability }) - } - TransformTypeForObject => impl_ty - } - } - sty_uniq(mutability) => { - match flag { - TransformTypeNormally => { - mk_uniq(tcx, ty::mt { ty: impl_ty, mutbl: mutability }) - } - TransformTypeForObject => impl_ty - } - } - } -} - pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> ast::rmode { match self_type { sty_value => by_copy, _ => by_ref } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 6bc1317d5f91c..5c7a6d9f52aa6 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -93,7 +93,6 @@ use middle::typeck::check::method::{AutoderefReceiver}; use middle::typeck::check::method::{AutoderefReceiverFlag}; use middle::typeck::check::method::{CheckTraitsAndInherentMethods}; use middle::typeck::check::method::{CheckTraitsOnly, DontAutoderefReceiver}; -use middle::typeck::check::method::{TransformTypeNormally}; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use middle::typeck::check::regionmanip::relate_free_regions; use middle::typeck::check::vtable::{LocationInfo, VtableContext}; @@ -101,9 +100,8 @@ use middle::typeck::CrateCtxt; use middle::typeck::infer::{resolve_type, force_tvar}; use middle::typeck::infer; use middle::typeck::rscope::bound_self_region; -use middle::typeck::rscope::{RegionError, RegionParameterization}; +use middle::typeck::rscope::{RegionError}; use middle::typeck::rscope::region_scope; -use middle::typeck::rscope; use middle::typeck::{isr_alist, lookup_def_ccx}; use middle::typeck::no_params; use middle::typeck::{require_same_types, method_map, vtable_map}; @@ -280,7 +278,7 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt, } pub fn check_fn(ccx: @mut CrateCtxt, - +self_info: Option, + opt_self_info: Option, purity: ast::purity, fn_sig: &ty::FnSig, decl: &ast::fn_decl, @@ -307,23 +305,28 @@ pub fn check_fn(ccx: @mut CrateCtxt, // First, we have to replace any bound regions in the fn and self // types with free ones. The free region references will be bound // the node_id of the body block. - - let (isr, self_info, fn_sig) = { - replace_bound_regions_in_fn_sig( - tcx, inherited_isr, self_info, fn_sig, - |br| ty::re_free(ty::FreeRegion {scope_id: body.node.id, - bound_region: br})) + let (isr, opt_self_info, fn_sig) = { + let opt_self_ty = opt_self_info.map(|i| i.self_ty); + let (isr, opt_self_ty, fn_sig) = + replace_bound_regions_in_fn_sig( + tcx, inherited_isr, opt_self_ty, fn_sig, + |br| ty::re_free(ty::FreeRegion {scope_id: body.node.id, + bound_region: br})); + let opt_self_info = + opt_self_info.map( + |si| SelfInfo {self_ty: opt_self_ty.get(), ..*si}); + (isr, opt_self_info, fn_sig) }; - relate_free_regions(tcx, self_info.map(|s| s.self_ty), &fn_sig); + relate_free_regions(tcx, opt_self_info.map(|s| s.self_ty), &fn_sig); let arg_tys = fn_sig.inputs.map(|a| a.ty); let ret_ty = fn_sig.output; - debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)", - arg_tys.map(|a| ppaux::ty_to_str(tcx, *a)), + debug!("check_fn(arg_tys=%?, ret_ty=%?, opt_self_ty=%?)", + arg_tys.map(|&a| ppaux::ty_to_str(tcx, a)), ppaux::ty_to_str(tcx, ret_ty), - self_info.map(|s| ppaux::ty_to_str(tcx, s.self_ty))); + opt_self_info.map(|si| ppaux::ty_to_str(tcx, si.self_ty))); // ______________________________________________________________________ // Create the function context. This is either derived from scratch or, @@ -348,7 +351,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, } }; - gather_locals(fcx, decl, body, arg_tys, self_info); + gather_locals(fcx, decl, body, arg_tys, opt_self_info); check_block_with_expected(fcx, body, Some(ret_ty)); // We unify the tail expr's type with the @@ -366,7 +369,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, None => () } - for self_info.each |self_info| { + for opt_self_info.each |self_info| { fcx.write_ty(self_info.self_id, self_info.self_ty); } for vec::each2(decl.inputs, arg_tys) |input, arg| { @@ -379,7 +382,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, decl: &ast::fn_decl, body: &ast::blk, arg_tys: &[ty::t], - self_info: Option) { + opt_self_info: Option) { let tcx = fcx.ccx.tcx; let assign: @fn(ast::node_id, Option) = |nid, ty_opt| { @@ -398,7 +401,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, }; // Add the self parameter - for self_info.each |self_info| { + for opt_self_info.each |self_info| { assign(self_info.self_id, Some(self_info.self_ty)); debug!("self is assigned to %s", fcx.infcx().ty_to_str( @@ -484,26 +487,22 @@ pub fn check_fn(ccx: @mut CrateCtxt, } pub fn check_method(ccx: @mut CrateCtxt, - method: @ast::method, - self_ty: ty::t) + method: @ast::method) { - let self_info = if method.self_ty.node == ast::sty_static {None} else { - let ty = method::transform_self_type_for_method( - ccx.tcx, - Some(ty::re_bound(ty::br_self)), - self_ty, - method.self_ty.node, - TransformTypeNormally); - Some(SelfInfo {self_ty: ty, self_id: method.self_id, - span: method.self_ty.span}) - }; + let method_def_id = local_def(method.id); + let method_ty = ty::method(ccx.tcx, method_def_id); + let opt_self_info = method_ty.transformed_self_ty.map(|&ty| { + SelfInfo {self_ty: ty, + self_id: method.self_id, + span: method.self_ty.span} + }); check_bare_fn( ccx, &method.decl, &method.body, method.id, - self_info + opt_self_info ); } @@ -575,15 +574,12 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { ast::item_fn(ref decl, _, _, _, ref body) => { check_bare_fn(ccx, decl, body, it.id, None); } - ast::item_impl(ref generics, _, ty, ref ms) => { + ast::item_impl(_, _, _, ref ms) => { let rp = ccx.tcx.region_paramd_items.find(&it.id).map_consume(|x| *x); debug!("item_impl %s with id %d rp %?", *ccx.tcx.sess.str_of(it.ident), it.id, rp); - let rp = RegionParameterization::from_variance_and_generics( - rp, generics); - let self_ty = ccx.to_ty(&rscope::type_rscope(rp), ty); for ms.each |m| { - check_method(ccx, *m, self_ty); + check_method(ccx, *m); } } ast::item_trait(_, _, ref trait_methods) => { @@ -594,8 +590,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { // bodies to check. } provided(m) => { - let self_ty = ty::mk_self(ccx.tcx, local_def(it.id)); - check_method(ccx, m, self_ty); + check_method(ccx, m); } } } diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 359f938d0d997..1abcefeefac8c 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -13,7 +13,7 @@ use core::prelude::*; use middle::ty; -use middle::typeck::check::SelfInfo; + use middle::typeck::isr_alist; use util::common::indenter; use util::ppaux::region_to_str; @@ -26,29 +26,24 @@ use std::list::Cons; pub fn replace_bound_regions_in_fn_sig( tcx: ty::ctxt, isr: isr_alist, - self_info: Option, + opt_self_ty: Option, fn_sig: &ty::FnSig, mapf: &fn(ty::bound_region) -> ty::Region) - -> (isr_alist, Option, ty::FnSig) + -> (isr_alist, Option, ty::FnSig) { - // Take self_info apart; the self_ty part is the only one we want - // to update here. - let self_ty = self_info.map(|s| s.self_ty); - let rebuild_self_info = |t| self_info.map(|s| SelfInfo{self_ty: t, ..*s}); - let mut all_tys = ty::tys_in_fn_sig(fn_sig); - for self_info.each |self_info| { - all_tys.push(self_info.self_ty); + for opt_self_ty.each |&self_ty| { + all_tys.push(self_ty); } - for self_ty.each |t| { all_tys.push(*t) } + for opt_self_ty.each |&t| { all_tys.push(t) } - debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \ + debug!("replace_bound_regions_in_fn_sig(self_ty=%?, fn_sig=%s, \ all_tys=%?)", - self_ty.map(|t| ppaux::ty_to_str(tcx, *t)), + opt_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)), ppaux::fn_sig_to_str(tcx, fn_sig), - all_tys.map(|t| ppaux::ty_to_str(tcx, *t))); + all_tys.map(|&t| ppaux::ty_to_str(tcx, t))); let _i = indenter(); let isr = do create_bound_region_mapping(tcx, isr, all_tys) |br| { @@ -58,20 +53,15 @@ pub fn replace_bound_regions_in_fn_sig( let new_fn_sig = ty::fold_sig(fn_sig, |t| { replace_bound_regions(tcx, isr, t) }); - let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, *t)); + let new_self_ty = opt_self_ty.map(|&t| replace_bound_regions(tcx, isr, t)); - debug!("result of replace_bound_regions_in_fn_sig: self_info.self_ty=%?, \ - fn_sig=%s", - t_self.map(|t| ppaux::ty_to_str(tcx, *t)), + debug!("result of replace_bound_regions_in_fn_sig: \ + new_self_ty=%?, \ + fn_sig=%s", + new_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)), ppaux::fn_sig_to_str(tcx, &new_fn_sig)); - // Glue updated self_ty back together with its original def_id. - let new_self_info: Option = match t_self { - None => None, - Some(t) => rebuild_self_info(t) - }; - - return (isr, new_self_info, new_fn_sig); + return (isr, new_self_ty, new_fn_sig); // Takes `isr`, a (possibly empty) mapping from in-scope region // names ("isr"s) to their corresponding regions; `tys`, a list of @@ -288,4 +278,4 @@ pub fn relate_free_regions( } debug!("<< relate_free_regions"); -} \ No newline at end of file +} diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 6ea668605fd4d..8245dc88114c8 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -11,7 +11,7 @@ use core::prelude::*; use middle::resolve::Impl; -use middle::ty::{param_ty, substs}; +use middle::ty::{param_ty}; use middle::ty; use middle::typeck::check::{FnCtxt, impl_self_ty}; use middle::typeck::check::{structurally_resolved_type}; @@ -489,6 +489,8 @@ pub fn early_resolve_expr(ex: @ast::expr, match ex.node { ast::expr_path(*) => { for fcx.opt_node_ty_substs(ex.id) |substs| { + debug!("vtable resolution on parameter bounds for expr %s", + ex.repr(fcx.tcx())); let def = *cx.tcx.def_map.get(&ex.id); let did = ast_util::def_id_of_def(def); let item_ty = ty::lookup_item_type(cx.tcx, did); @@ -518,6 +520,8 @@ pub fn early_resolve_expr(ex: @ast::expr, ast::expr_index(*) | ast::expr_method_call(*) => { match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) { Some(type_param_defs) => { + debug!("vtable resolution on parameter bounds for method call %s", + ex.repr(fcx.tcx())); if has_trait_bounds(*type_param_defs) { let callee_id = match ex.node { ast::expr_field(_, _, _) => ex.id, @@ -537,6 +541,7 @@ pub fn early_resolve_expr(ex: @ast::expr, } } ast::expr_cast(src, _) => { + debug!("vtable resolution on expr %s", ex.repr(fcx.tcx())); let target_ty = fcx.expr_ty(ex); match ty::get(target_ty).sty { ty::ty_trait(target_def_id, ref target_substs, store) => { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 174a20dd7f4c7..247b8eae2a8db 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -24,7 +24,7 @@ use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get}; -use middle::ty::{lookup_item_type, param_bounds, subst}; +use middle::ty::{lookup_item_type, subst}; use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err}; use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil}; use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr}; diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 0ef6e2512f3d5..59ea8ea039e1f 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -55,7 +55,7 @@ use syntax::ast_util::{local_def, split_trait_methods}; use syntax::ast_util; use syntax::codemap::span; use syntax::codemap; -use syntax::print::pprust::path_to_str; +use syntax::print::pprust::{path_to_str, self_ty_to_str}; use syntax::visit; use syntax::opt_vec::OptVec; use syntax::opt_vec; @@ -453,31 +453,35 @@ pub fn compare_impl_method(tcx: ty::ctxt, let impl_m = &cm.mty; - // FIXME(#2687)---this check is too strict. For example, a trait - // method with self type `&self` or `&mut self` should be - // implementable by an `&const self` method (the impl assumes less - // than the trait provides). - if impl_m.self_ty != trait_m.self_ty { - if impl_m.self_ty == ast::sty_static { - // Needs to be a fatal error because otherwise, - // method::transform_self_type_for_method ICEs - tcx.sess.span_fatal(cm.span, - fmt!("method `%s` is declared as \ - static in its impl, but not in \ - its trait", *tcx.sess.str_of(impl_m.ident))); - } - else if trait_m.self_ty == ast::sty_static { - tcx.sess.span_fatal(cm.span, - fmt!("method `%s` is declared as \ - static in its trait, but not in \ - its impl", *tcx.sess.str_of(impl_m.ident))); + // Try to give more informative error messages about self typing + // mismatches. Note that any mismatch will also be detected + // below, where we construct a canonical function type that + // includes the self parameter as a normal parameter. It's just + // that the error messages you get out of this code are a bit more + // inscrutable, particularly for cases where one method has no + // self. + match (&trait_m.self_ty, &impl_m.self_ty) { + (&ast::sty_static, &ast::sty_static) => {} + (&ast::sty_static, _) => { + tcx.sess.span_err( + cm.span, + fmt!("method `%s` has a `%s` declaration in the impl, \ + but not in the trait", + *tcx.sess.str_of(trait_m.ident), + self_ty_to_str(impl_m.self_ty, tcx.sess.intr()))); + return; } - else { + (_, &ast::sty_static) => { tcx.sess.span_err( cm.span, - fmt!("method `%s`'s self type does \ - not match the trait method's \ - self type", *tcx.sess.str_of(impl_m.ident))); + fmt!("method `%s` has a `%s` declaration in the trait, \ + but not in the impl", + *tcx.sess.str_of(trait_m.ident), + self_ty_to_str(trait_m.self_ty, tcx.sess.intr()))); + return; + } + _ => { + // Let the type checker catch other errors below } } @@ -539,6 +543,51 @@ pub fn compare_impl_method(tcx: ty::ctxt, bound_region: ty::br_self}); let self_ty = replace_bound_self(tcx, self_ty, dummy_self_r); + // We are going to create a synthetic fn type that includes + // both the method's self argument and its normal arguments. + // So a method like `fn(&self, a: uint)` would be converted + // into a function `fn(self: &T, a: uint)`. + let mut trait_fn_args = ~[]; + let mut impl_fn_args = ~[]; + + // For both the trait and the impl, create an argument to + // represent the self argument (unless this is a static method). + // This argument will have the *transformed* self type. + for trait_m.transformed_self_ty.each |&t| { + trait_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t}); + } + for impl_m.transformed_self_ty.each |&t| { + impl_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t}); + } + + // Add in the normal arguments. + trait_fn_args.push_all(trait_m.fty.sig.inputs); + impl_fn_args.push_all(impl_m.fty.sig.inputs); + + // Create a bare fn type for trait/impl that includes self argument + let trait_fty = + ty::mk_bare_fn( + tcx, + ty::BareFnTy {purity: trait_m.fty.purity, + abis: trait_m.fty.abis, + sig: ty::FnSig { + bound_lifetime_names: + copy trait_m.fty.sig.bound_lifetime_names, + inputs: trait_fn_args, + output: trait_m.fty.sig.output + }}); + let impl_fty = + ty::mk_bare_fn( + tcx, + ty::BareFnTy {purity: impl_m.fty.purity, + abis: impl_m.fty.abis, + sig: ty::FnSig { + bound_lifetime_names: + copy impl_m.fty.sig.bound_lifetime_names, + inputs: impl_fn_args, + output: impl_m.fty.sig.output + }}); + // Perform substitutions so that the trait/impl methods are expressed // in terms of the same set of type/region parameters: // - replace trait type parameters with those from `trait_substs`, @@ -547,7 +596,6 @@ pub fn compare_impl_method(tcx: ty::ctxt, // that correspond to the parameters we will find on the impl // - replace self region with a fresh, dummy region let impl_fty = { - let impl_fty = ty::mk_bare_fn(tcx, copy impl_m.fty); debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty)); replace_bound_self(tcx, impl_fty, dummy_self_r) }; @@ -565,7 +613,6 @@ pub fn compare_impl_method(tcx: ty::ctxt, self_ty: Some(self_ty), tps: vec::append(trait_tps, dummy_tps) }; - let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty); debug!("trait_fty (pre-subst): %s substs=%s", trait_fty.repr(tcx), substs.repr(tcx)); ty::subst(tcx, &substs, trait_fty) diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index eeca90dbecd5d..3ff36a409a71f 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -180,12 +180,11 @@ impl region_scope for MethodRscope { }) } fn self_region(&self, _span: span) -> Result { - assert!(self.variance.is_some() || self.self_ty.is_borrowed()); + assert!(self.variance.is_some()); match self.variance { None => {} // must be borrowed self, so this is OK Some(_) => { - if !self.self_ty.is_borrowed() && - !self.region_param_names.has_self() { + if !self.region_param_names.has_self() { return Err(RegionError { msg: ~"the `self` lifetime must be declared", replacement: ty::re_bound(ty::br_self) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f8877f768813d..9b9e0e81b4346 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -750,6 +750,12 @@ impl Repr for ty::TraitStore { } } +impl Repr for ty::vstore { + fn repr(&self, tcx: ctxt) -> ~str { + vstore_to_str(tcx, *self) + } +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ec77b54a85371..3b2df24e7d9b8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1002,15 +1002,6 @@ pub enum self_ty_ { sty_uniq(mutability) // `~self` } -impl self_ty_ { - fn is_borrowed(&self) -> bool { - match *self { - sty_region(*) => true, - _ => false - } - } -} - pub type self_ty = spanned; #[auto_encode] diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 92f0c7c7679a9..886af694920f7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -454,6 +454,7 @@ impl MapChain{ // ugh: can't get this to compile with mut because of the // lack of flow sensitivity. + #[cfg(stage0)] fn get_map(&self) -> &'self HashMap { match *self { BaseMapChain (~ref map) => map, @@ -461,6 +462,18 @@ impl MapChain{ } } + // ugh: can't get this to compile with mut because of the + // lack of flow sensitivity. + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_map<'a>(&'a self) -> &'a HashMap { + match *self { + BaseMapChain (~ref map) => map, + ConsMapChain (~ref map,_) => map + } + } + // traits just don't work anywhere...? //pub impl Map for MapChain { diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index fd54746f3dc51..1604c40f91763 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -61,6 +61,7 @@ impl OptVec { } } + #[cfg(stage0)] fn get(&self, i: uint) -> &'self T { match *self { Empty => fail!(fmt!("Invalid index %u", i)), @@ -68,6 +69,16 @@ impl OptVec { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get<'a>(&'a self, i: uint) -> &'a T { + match *self { + Empty => fail!(fmt!("Invalid index %u", i)), + Vec(ref v) => &v[i] + } + } + fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 20fc99baf2179..36cd7c06842ae 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1633,6 +1633,10 @@ pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) { (s.ann.post)(ann_node); } +pub fn self_ty_to_str(self_ty: ast::self_ty_, intr: @ident_interner) -> ~str { + to_str(self_ty, |a, b| { print_self_ty(a, b); () }, intr) +} + // Returns whether it printed anything pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool { match self_ty { From 61b9e0ebfa7c96886c45a461c6d8edb22f8153da Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 10 Apr 2013 13:11:35 -0700 Subject: [PATCH 136/403] core: changes in response to #5656 --- src/libcore/condition.rs | 2 +- src/libcore/container.rs | 36 ++++++++ src/libcore/hashmap.rs | 173 +++++++++++++++++++++++++++++++++- src/libcore/option.rs | 104 +++++++++++++++++++++ src/libcore/result.rs | 7 ++ src/libcore/rt/rtio.rs | 5 + src/libcore/rt/sched.rs | 40 ++++++++ src/libcore/rt/uvio.rs | 16 ++++ src/libcore/task/mod.rs | 2 +- src/libcore/trie.rs | 97 ++++++++++++++++++- src/libcore/tuple.rs | 28 ++++++ src/libcore/vec.rs | 195 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 700 insertions(+), 5 deletions(-) diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index ed94f2ef2c45c..dc6c80228dd74 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -28,7 +28,7 @@ pub struct Condition<'self, T, U> { } pub impl<'self, T, U> Condition<'self, T, U> { - fn trap(&self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { + fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { unsafe { let p : *RustClosure = ::cast::transmute(&h); let prev = task::local_data::local_data_get(self.key); diff --git a/src/libcore/container.rs b/src/libcore/container.rs index a1836d16fd733..88c78aebfc5c7 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -25,6 +25,7 @@ pub trait Mutable: Container { fn clear(&mut self); } +#[cfg(stage0)] pub trait Map: Mutable { /// Return true if the map contains a value for the specified key fn contains_key(&self, key: &K) -> bool; @@ -57,6 +58,41 @@ pub trait Map: Mutable { fn remove(&mut self, key: &K) -> bool; } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait Map: Mutable { + /// Return true if the map contains a value for the specified key + fn contains_key(&self, key: &K) -> bool; + + // Visits all keys and values + fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool); + + /// Visit all keys + fn each_key(&self, f: &fn(&K) -> bool); + + /// Visit all values + fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool); + + /// Iterate over the map and mutate the contained values + fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool); + + /// Return a reference to the value corresponding to the key + fn find<'a>(&'a self, key: &K) -> Option<&'a V>; + + /// Return a mutable reference to the value corresponding to the key + fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>; + + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, key: K, value: V) -> bool; + + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, key: &K) -> bool; +} + pub trait Set: Mutable { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index d4af0ffe7fe7b..2869c198ca2fc 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -186,6 +186,7 @@ priv impl HashMap { } } + #[cfg(stage0)] #[inline(always)] fn value_for_bucket(&self, idx: uint) -> &'self V { match self.buckets[idx] { @@ -194,6 +195,18 @@ priv impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V { + match self.buckets[idx] { + Some(ref bkt) => &bkt.value, + None => fail!(~"HashMap::find: internal logic error"), + } + } + + #[cfg(stage0)] #[inline(always)] fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V { match self.buckets[idx] { @@ -202,6 +215,17 @@ priv impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V { + match self.buckets[idx] { + Some(ref mut bkt) => &mut bkt.value, + None => unreachable() + } + } + /// Inserts the key value pair into the buckets. /// Assumes that there will be a bucket. /// True if there was no previous entry with that key @@ -307,6 +331,7 @@ impl Map for HashMap { } /// Visit all key-value pairs + #[cfg(stage0)] fn each(&self, blk: &fn(&'self K, &'self V) -> bool) { for uint::range(0, self.buckets.len()) |i| { for self.buckets[i].each |bucket| { @@ -317,19 +342,41 @@ impl Map for HashMap { } } + /// Visit all key-value pairs + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, blk: &fn(&'a K, &'a V) -> bool) { + for uint::range(0, self.buckets.len()) |i| { + for self.buckets[i].each |bucket| { + if !blk(&bucket.key, &bucket.value) { + return; + } + } + } + } + /// Visit all keys fn each_key(&self, blk: &fn(k: &K) -> bool) { self.each(|k, _| blk(k)) } /// Visit all values + #[cfg(stage0)] fn each_value(&self, blk: &fn(v: &V) -> bool) { self.each(|_, v| blk(v)) } + /// Visit all values + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) { + self.each(|_, v| blk(v)) + } + /// Iterate over the map and mutate the contained values - fn mutate_values(&mut self, blk: &fn(&'self K, - &'self mut V) -> bool) { + fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) { for uint::range(0, self.buckets.len()) |i| { match self.buckets[i] { Some(Bucket{key: ref key, value: ref mut value, _}) => { @@ -341,6 +388,7 @@ impl Map for HashMap { } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] fn find(&self, k: &K) -> Option<&'self V> { match self.bucket_for_key(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), @@ -348,7 +396,19 @@ impl Map for HashMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find<'a>(&'a self, k: &K) -> Option<&'a V> { + match self.bucket_for_key(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, + } + } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage0)] fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { let idx = match self.bucket_for_key(k) { FoundEntry(idx) => idx, @@ -359,6 +419,20 @@ impl Map for HashMap { } } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { + let idx = match self.bucket_for_key(k) { + FoundEntry(idx) => idx, + TableFull | FoundHole(_) => return None + }; + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) + } + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -431,6 +505,7 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, or insert /// and return the value if it doesn't exist. + #[cfg(stage0)] fn find_or_insert(&mut self, k: K, v: V) -> &'self V { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so @@ -459,8 +534,42 @@ pub impl HashMap { } } + /// Return the value corresponding to the key in the map, or insert + /// and return the value if it doesn't exist. + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) + } + } + /// Return the value corresponding to the key in the map, or create, /// insert, and return a new value if it doesn't exist. + #[cfg(stage0)] fn find_or_insert_with(&mut self, k: K, f: &fn(&K) -> V) -> &'self V { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so @@ -490,6 +599,40 @@ pub impl HashMap { } } + /// Return the value corresponding to the key in the map, or create, + /// insert, and return a new value if it doesn't exist. + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V { + if self.size >= self.resize_at { + // n.b.: We could also do this after searching, so + // that we do not resize if this call to insert is + // simply going to update a key in place. My sense + // though is that it's worse to have to search through + // buckets to find the right spot twice than to just + // resize in this corner case. + self.expand(); + } + + let hash = k.hash_keyed(self.k0, self.k1) as uint; + let idx = match self.bucket_for_key_with_hash(hash, &k) { + TableFull => fail!(~"Internal logic error"), + FoundEntry(idx) => idx, + FoundHole(idx) => { + let v = f(&k); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, + value: v}); + self.size += 1; + idx + }, + }; + + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + ::cast::transmute_region(self.value_for_bucket(idx)) + } + } + fn consume(&mut self, f: &fn(K, V)) { let mut buckets = ~[]; self.buckets <-> buckets; @@ -506,6 +649,7 @@ pub impl HashMap { } } + #[cfg(stage0)] fn get(&self, k: &K) -> &'self V { match self.find(k) { Some(v) => v, @@ -513,6 +657,16 @@ pub impl HashMap { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get<'a>(&'a self, k: &K) -> &'a V { + match self.find(k) { + Some(v) => v, + None => fail!(fmt!("No entry found for key: %?", k)), + } + } + /// Return true if the map contains a value for the specified key, /// using equivalence fn contains_key_equiv>(&self, key: &Q) @@ -525,6 +679,7 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, using /// equivalence + #[cfg(stage0)] fn find_equiv>(&self, k: &Q) -> Option<&'self V> { match self.bucket_for_key_equiv(k) { @@ -532,6 +687,20 @@ pub impl HashMap { TableFull | FoundHole(_) => None, } } + + /// Return the value corresponding to the key in the map, using + /// equivalence + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_equiv<'a, Q:Hash + IterBytes + Equiv>( + &'a self, k: &Q) -> Option<&'a V> + { + match self.bucket_for_key_equiv(k) { + FoundEntry(idx) => Some(self.value_for_bucket(idx)), + TableFull | FoundHole(_) => None, + } + } } impl Eq for HashMap { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index de1482e2c3918..9b7276879c123 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -101,11 +101,21 @@ impl> Add, Option> for Option { impl BaseIter for Option { /// Performs an operation on the contained value by reference + #[cfg(stage0)] #[inline(always)] fn each(&self, f: &fn(x: &'self T) -> bool) { match *self { None => (), Some(ref t) => { f(t); } } } + /// Performs an operation on the contained value by reference + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn each<'a>(&'a self, f: &fn(x: &'a T) -> bool) { + match *self { None => (), Some(ref t) => { f(t); } } + } + #[inline(always)] fn size_hint(&self) -> Option { if self.is_some() { Some(1) } else { Some(0) } @@ -113,10 +123,19 @@ impl BaseIter for Option { } impl MutableIter for Option { + #[cfg(stage0)] #[inline(always)] fn each_mut(&mut self, f: &fn(&'self mut T) -> bool) { match *self { None => (), Some(ref mut t) => { f(t); } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn each_mut<'a>(&'a mut self, f: &fn(&'a mut T) -> bool) { + match *self { None => (), Some(ref mut t) => { f(t); } } + } } impl ExtendedIter for Option { @@ -182,17 +201,40 @@ pub impl Option { * Update an optional value by optionally running its content by reference * through a function that returns an option. */ + #[cfg(stage0)] #[inline(always)] fn chain_ref(&self, f: &fn(x: &'self T) -> Option) -> Option { match *self { Some(ref x) => f(x), None => None } } + /** + * Update an optional value by optionally running its content by reference + * through a function that returns an option. + */ + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) -> Option { + match *self { Some(ref x) => f(x), None => None } + } + /// Maps a `some` value from one type to another by reference + #[cfg(stage0)] #[inline(always)] fn map(&self, f: &fn(&'self T) -> U) -> Option { match *self { Some(ref x) => Some(f(x)), None => None } } + /// Maps a `some` value from one type to another by reference + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option { + match *self { Some(ref x) => Some(f(x)), None => None } + } + /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. #[inline(always)] @@ -201,11 +243,21 @@ pub impl Option { } /// Applies a function to the contained value or returns a default + #[cfg(stage0)] #[inline(always)] fn map_default(&self, def: U, f: &fn(&'self T) -> U) -> U { match *self { None => def, Some(ref t) => f(t) } } + /// Applies a function to the contained value or returns a default + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { + match *self { None => def, Some(ref t) => f(t) } + } + /// As `map_default`, but consumes the option and gives `f` /// ownership to avoid copying. #[inline(always)] @@ -244,6 +296,7 @@ pub impl Option { case explicitly. */ #[inline(always)] + #[cfg(stage0)] fn get_ref(&self) -> &'self T { match *self { Some(ref x) => x, @@ -251,6 +304,31 @@ pub impl Option { } } + /** + Gets an immutable reference to the value inside an option. + + # Failure + + Fails if the value equals `None` + + # Safety note + + In general, because this function may fail, its use is discouraged + (calling `get` on `None` is akin to dereferencing a null pointer). + Instead, prefer to use pattern matching and handle the `None` + case explicitly. + */ + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_ref<'a>(&'a self) -> &'a T { + match *self { + Some(ref x) => x, + None => fail!(~"option::get_ref none") + } + } + /** Gets a mutable reference to the value inside an option. @@ -266,6 +344,7 @@ pub impl Option { case explicitly. */ #[inline(always)] + #[cfg(stage0)] fn get_mut_ref(&mut self) -> &'self mut T { match *self { Some(ref mut x) => x, @@ -273,6 +352,31 @@ pub impl Option { } } + /** + Gets a mutable reference to the value inside an option. + + # Failure + + Fails if the value equals `None` + + # Safety note + + In general, because this function may fail, its use is discouraged + (calling `get` on `None` is akin to dereferencing a null pointer). + Instead, prefer to use pattern matching and handle the `None` + case explicitly. + */ + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { + match *self { + Some(ref mut x) => x, + None => fail!(~"option::get_mut_ref none") + } + } + #[inline(always)] fn unwrap(self) -> T { /*! diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 8fd81a2060342..58e281c29c605 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -226,9 +226,16 @@ pub fn map_err(res: &Result, op: &fn(&E) -> F) } pub impl Result { + #[cfg(stage0)] #[inline(always)] fn get_ref(&self) -> &'self T { get_ref(self) } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } + #[inline(always)] fn is_ok(&self) -> bool { is_ok(self) } diff --git a/src/libcore/rt/rtio.rs b/src/libcore/rt/rtio.rs index 55e062de85b06..6a7c3970c0091 100644 --- a/src/libcore/rt/rtio.rs +++ b/src/libcore/rt/rtio.rs @@ -22,7 +22,12 @@ pub trait EventLoop { fn run(&mut self); fn callback(&mut self, ~fn()); /// The asynchronous I/O services. Not all event loops may provide one + #[cfg(stage0)] fn io(&mut self) -> Option<&'self mut IoFactoryObject>; + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject>; } pub trait IoFactory { diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 46ea5713e2af3..25f446fb86d19 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -272,6 +272,7 @@ pub impl Scheduler { // XXX: Hack. This should return &'self mut but I don't know how to // make the borrowcheck happy + #[cfg(stage0)] fn task_from_last_cleanup_job(&mut self) -> &mut Task { assert!(!self.cleanup_jobs.is_empty()); let last_job: &'self mut CleanupJob = &mut self.cleanup_jobs[0]; @@ -285,6 +286,25 @@ pub impl Scheduler { // borrows return unsafe { transmute::<&Task, &mut Task>(last_task) }; } + + // XXX: Hack. This should return &'self mut but I don't know how to + // make the borrowcheck happy + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn task_from_last_cleanup_job<'a>(&'a mut self) -> &mut Task { + assert!(!self.cleanup_jobs.is_empty()); + let last_job: &'a mut CleanupJob = &mut self.cleanup_jobs[0]; + let last_task: &'a Task = match last_job { + &RescheduleTask(~ref task) => task, + &RecycleTask(~ref task) => task, + &GiveTask(~ref task, _) => task, + }; + // XXX: Pattern matching mutable pointers above doesn't work + // because borrowck thinks the three patterns are conflicting + // borrows + return unsafe { transmute::<&Task, &mut Task>(last_task) }; + } } static TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack @@ -354,6 +374,7 @@ impl ThreadLocalScheduler { } } + #[cfg(stage0)] fn get_scheduler(&mut self) -> &'self mut Scheduler { unsafe { let key = match self { &ThreadLocalScheduler(key) => key }; @@ -370,6 +391,25 @@ impl ThreadLocalScheduler { } } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_scheduler<'a>(&'a mut self) -> &'a mut Scheduler { + unsafe { + let key = match self { &ThreadLocalScheduler(key) => key }; + let mut value: *mut c_void = tls::get(key); + assert!(value.is_not_null()); + { + let value_ptr = &mut value; + let sched: &mut ~Scheduler = { + transmute::<&mut *mut c_void, &mut ~Scheduler>(value_ptr) + }; + let sched: &mut Scheduler = &mut **sched; + return sched; + } + } + } + fn take_scheduler(&mut self) -> ~Scheduler { unsafe { let key = match self { &ThreadLocalScheduler(key) => key }; diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 37f29d1a5c0fe..7162ed27a9d77 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -67,9 +67,17 @@ impl EventLoop for UvEventLoop { } } + #[cfg(stage0)] fn io(&mut self) -> Option<&'self mut IoFactoryObject> { Some(&mut self.uvio) } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject> { + Some(&mut self.uvio) + } } #[test] @@ -89,9 +97,17 @@ fn test_callback_run_once() { pub struct UvIoFactory(Loop); pub impl UvIoFactory { + #[cfg(stage0)] fn uv_loop(&mut self) -> &'self mut Loop { match self { &UvIoFactory(ref mut ptr) => ptr } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn uv_loop<'a>(&'a mut self) -> &'a mut Loop { + match self { &UvIoFactory(ref mut ptr) => ptr } + } } impl IoFactory for UvIoFactory { diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 502efcf9dc6cb..e4ee430cdda64 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -39,7 +39,7 @@ use result::Result; use comm::{stream, Chan, GenericChan, GenericPort, Port}; use prelude::*; use result; -use task::rt::{task_id, sched_id, rust_task}; +use task::rt::{task_id, sched_id}; use util; use util::replace; use unstable::finally::Finally; diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index f6a92a213859e..f4e9ddbdd90a1 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -56,10 +56,20 @@ impl Map for TrieMap { /// Visit all key-value pairs in order #[inline(always)] + #[cfg(stage0)] fn each(&self, f: &fn(&uint, &'self T) -> bool) { self.root.each(f); } + /// Visit all key-value pairs in order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { + self.root.each(f); + } + /// Visit all keys in order #[inline(always)] fn each_key(&self, f: &fn(&uint) -> bool) { @@ -68,10 +78,20 @@ impl Map for TrieMap { /// Visit all values in order #[inline(always)] + #[cfg(stage0)] fn each_value(&self, f: &fn(&T) -> bool) { self.each(|_, v| f(v)) } + /// Visit all values in order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) { + self.each(|_, v| f(v)) + } + /// Iterate over the map and mutate the contained values #[inline(always)] fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) { @@ -79,6 +99,7 @@ impl Map for TrieMap { } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] #[inline(hint)] fn find(&self, key: &uint) -> Option<&'self T> { let mut node: &'self TrieNode = &self.root; @@ -99,12 +120,46 @@ impl Map for TrieMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(hint)] + fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { + let mut node: &'a TrieNode = &self.root; + let mut idx = 0; + loop { + match node.children[chunk(*key, idx)] { + Internal(ref x) => node = &**x, + External(stored, ref value) => { + if stored == *key { + return Some(value) + } else { + return None + } + } + Nothing => return None + } + idx += 1; + } + } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage0)] #[inline(always)] fn find_mut(&mut self, key: &uint) -> Option<&'self mut T> { find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline(always)] + fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { + find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -138,10 +193,20 @@ pub impl TrieMap { /// Visit all key-value pairs in reverse order #[inline(always)] + #[cfg(stage0)] fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) { self.root.each_reverse(f); } + /// Visit all key-value pairs in reverse order + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { + self.root.each_reverse(f); + } + /// Visit all keys in reverse order #[inline(always)] fn each_key_reverse(&self, f: &fn(&uint) -> bool) { @@ -233,6 +298,7 @@ impl TrieNode { } impl TrieNode { + #[cfg(stage0)] fn each(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range(0, self.children.len()) |idx| { match self.children[idx] { @@ -244,6 +310,21 @@ impl TrieNode { true } + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { + for uint::range(0, self.children.len()) |idx| { + match self.children[idx] { + Internal(ref x) => if !x.each(f) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, + Nothing => () + } + } + true + } + + #[cfg(stage0)] fn each_reverse(&self, f: &fn(&uint, &'self T) -> bool) -> bool { for uint::range_rev(self.children.len(), 0) |idx| { match self.children[idx - 1] { @@ -255,7 +336,21 @@ impl TrieNode { true } - fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool { + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { + for uint::range_rev(self.children.len(), 0) |idx| { + match self.children[idx - 1] { + Internal(ref x) => if !x.each_reverse(f) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, + Nothing => () + } + } + true + } + + fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool { for vec::each_mut(self.children) |child| { match *child { Internal(ref mut x) => if !x.mutate_values(f) { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 8234129e25474..8e908435f3543 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -56,11 +56,13 @@ impl Clone for (T, U) { } } +#[cfg(stage0)] pub trait ImmutableTuple { fn first_ref(&self) -> &'self T; fn second_ref(&self) -> &'self U; } +#[cfg(stage0)] impl ImmutableTuple for (T, U) { #[inline(always)] fn first_ref(&self) -> &'self T { @@ -76,6 +78,32 @@ impl ImmutableTuple for (T, U) { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait ImmutableTuple { + fn first_ref<'a>(&'a self) -> &'a T; + fn second_ref<'a>(&'a self) -> &'a U; +} + +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl ImmutableTuple for (T, U) { + #[inline(always)] + fn first_ref<'a>(&'a self) -> &'a T { + match *self { + (ref t, _) => t, + } + } + #[inline(always)] + fn second_ref<'a>(&'a self) -> &'a U { + match *self { + (_, ref u) => u, + } + } +} + pub trait ExtendedTupleOps { fn zip(&self) -> ~[(A, B)]; fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 5b06591f9ecc8..7940502d27e48 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1763,6 +1763,7 @@ impl<'self,T:Copy> CopyableVector for &'self const [T] { } } +#[cfg(stage0)] pub trait ImmutableVector { fn slice(&self, start: uint, end: uint) -> &'self [T]; fn head(&self) -> &'self T; @@ -1785,6 +1786,7 @@ pub trait ImmutableVector { } /// Extension methods for vectors +#[cfg(stage0)] impl<'self,T> ImmutableVector for &'self [T] { /// Return a slice that points into another slice. #[inline] @@ -1893,6 +1895,142 @@ impl<'self,T> ImmutableVector for &'self [T] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait ImmutableVector<'self, T> { + fn slice(&self, start: uint, end: uint) -> &'self [T]; + fn head(&self) -> &'self T; + fn head_opt(&self) -> Option<&'self T>; + fn tail(&self) -> &'self [T]; + fn tailn(&self, n: uint) -> &'self [T]; + fn init(&self) -> &'self [T]; + fn initn(&self, n: uint) -> &'self [T]; + fn last(&self) -> &'self T; + fn last_opt(&self) -> Option<&'self T>; + fn each_reverse(&self, blk: &fn(&T) -> bool); + fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool); + fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U; + fn map(&self, f: &fn(t: &T) -> U) -> ~[U]; + fn mapi(&self, f: &fn(uint, t: &T) -> U) -> ~[U]; + fn map_r(&self, f: &fn(x: &T) -> U) -> ~[U]; + fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool; + fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; + fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U]; +} + +/// Extension methods for vectors +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,T> ImmutableVector<'self, T> for &'self [T] { + /// Return a slice that points into another slice. + #[inline] + fn slice(&self, start: uint, end: uint) -> &'self [T] { + slice(*self, start, end) + } + + /// Returns the first element of a vector, failing if the vector is empty. + #[inline] + fn head(&self) -> &'self T { head(*self) } + + /// Returns the first element of a vector + #[inline] + fn head_opt(&self) -> Option<&'self T> { head_opt(*self) } + + /// Returns all but the first element of a vector + #[inline] + fn tail(&self) -> &'self [T] { tail(*self) } + + /// Returns all but the first `n' elements of a vector + #[inline] + fn tailn(&self, n: uint) -> &'self [T] { tailn(*self, n) } + + /// Returns all but the last elemnt of a vector + #[inline] + fn init(&self) -> &'self [T] { init(*self) } + + /// Returns all but the last `n' elemnts of a vector + #[inline] + fn initn(&self, n: uint) -> &'self [T] { initn(*self, n) } + + /// Returns the last element of a `v`, failing if the vector is empty. + #[inline] + fn last(&self) -> &'self T { last(*self) } + + /// Returns the last element of a `v`, failing if the vector is empty. + #[inline] + fn last_opt(&self) -> Option<&'self T> { last_opt(*self) } + + /// Iterates over a vector's elements in reverse. + #[inline] + fn each_reverse(&self, blk: &fn(&T) -> bool) { + each_reverse(*self, blk) + } + + /// Iterates over a vector's elements and indices in reverse. + #[inline] + fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) { + eachi_reverse(*self, blk) + } + + /// Reduce a vector from right to left + #[inline] + fn foldr(&self, z: U, p: &fn(t: &T, u: U) -> U) -> U { + foldr(*self, z, p) + } + + /// Apply a function to each element of a vector and return the results + #[inline] + fn map(&self, f: &fn(t: &T) -> U) -> ~[U] { map(*self, f) } + + /** + * Apply a function to the index and value of each element in the vector + * and return the results + */ + fn mapi(&self, f: &fn(uint, t: &T) -> U) -> ~[U] { + mapi(*self, f) + } + + #[inline] + fn map_r(&self, f: &fn(x: &T) -> U) -> ~[U] { + let mut r = ~[]; + let mut i = 0; + while i < self.len() { + r.push(f(&self[i])); + i += 1; + } + r + } + + /** + * Returns true if the function returns true for all elements. + * + * If the vector is empty, true is returned. + */ + fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool { + alli(*self, f) + } + /** + * Apply a function to each element of a vector and return a concatenation + * of each result vector + */ + #[inline] + fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] { + flat_map(*self, f) + } + /** + * Apply a function to each element of a vector and return the results + * + * If function `f` returns `none` then that element is excluded from + * the resulting vector. + */ + #[inline] + fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U] { + filter_mapped(*self, f) + } +} + pub trait ImmutableEqVector { fn position(&self, f: &fn(t: &T) -> bool) -> Option; fn position_elem(&self, t: &T) -> Option; @@ -2353,6 +2491,7 @@ pub mod bytes { // ___________________________________________________________________________ // ITERATION TRAIT METHODS +#[cfg(stage0)] impl<'self,A> iter::BaseIter for &'self [A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2360,7 +2499,18 @@ impl<'self,A> iter::BaseIter for &'self [A] { fn size_hint(&self) -> Option { Some(self.len()) } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,A> iter::BaseIter for &'self [A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + // FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::BaseIter for ~[A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2369,6 +2519,18 @@ impl iter::BaseIter for ~[A] { } // FIXME(#4148): This should be redundant +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::BaseIter for ~[A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + +// FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::BaseIter for @[A] { #[inline(always)] fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) } @@ -2376,6 +2538,18 @@ impl iter::BaseIter for @[A] { fn size_hint(&self) -> Option { Some(self.len()) } } +// FIXME(#4148): This should be redundant +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::BaseIter for @[A] { + #[inline(always)] + fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) } + #[inline(always)] + fn size_hint(&self) -> Option { Some(self.len()) } +} + +#[cfg(stage0)] impl<'self,A> iter::MutableIter for &'self mut [A] { #[inline(always)] fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) { @@ -2383,7 +2557,18 @@ impl<'self,A> iter::MutableIter for &'self mut [A] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self,A> iter::MutableIter for &'self mut [A] { + #[inline(always)] + fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { + each_mut(*self, blk) + } +} + // FIXME(#4148): This should be redundant +#[cfg(stage0)] impl iter::MutableIter for ~[A] { #[inline(always)] fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) { @@ -2391,6 +2576,16 @@ impl iter::MutableIter for ~[A] { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl iter::MutableIter for ~[A] { + #[inline(always)] + fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { + each_mut(*self, blk) + } +} + // FIXME(#4148): This should be redundant impl iter::MutableIter for @mut [A] { #[inline(always)] From 03396473b879b37d68f26588d136c840280b0ab5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 10 Apr 2013 13:14:06 -0700 Subject: [PATCH 137/403] libstd: changes to in response to #5656 --- src/libstd/arena.rs | 68 +++++++++++++++++-- src/libstd/bitv.rs | 6 +- src/libstd/deque.rs | 122 +++++++++++++++++++++++++++++++++++ src/libstd/future.rs | 30 ++++++++- src/libstd/priority_queue.rs | 16 +++++ src/libstd/smallintmap.rs | 79 ++++++++++++++++++++++- src/libstd/treemap.rs | 83 +++++++++++++++++++++++- 7 files changed, 390 insertions(+), 14 deletions(-) diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 81c28f94d9f27..3d2c3ac70b610 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -171,7 +171,7 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) { pub impl Arena { // Functions for the POD part of the arena - fn alloc_pod_grow(&self, n_bytes: uint, align: uint) -> *u8 { + priv fn alloc_pod_grow(&self, n_bytes: uint, align: uint) -> *u8 { // Allocate a new chunk. let chunk_size = at_vec::capacity(self.pod_head.data); let new_min_chunk_size = uint::max(n_bytes, chunk_size); @@ -183,7 +183,7 @@ pub impl Arena { } #[inline(always)] - fn alloc_pod_inner(&self, n_bytes: uint, align: uint) -> *u8 { + priv fn alloc_pod_inner(&self, n_bytes: uint, align: uint) -> *u8 { let head = &mut self.pod_head; let start = round_up_to(head.fill, align); @@ -202,7 +202,22 @@ pub impl Arena { } #[inline(always)] - fn alloc_pod(&self, op: &fn() -> T) -> &'self T { + #[cfg(stage0)] + priv fn alloc_pod(&self, op: &fn() -> T) -> &'self T { + unsafe { + let tydesc = sys::get_type_desc::(); + let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); + let ptr: *mut T = reinterpret_cast(&ptr); + rusti::move_val_init(&mut (*ptr), op()); + return reinterpret_cast(&ptr); + } + } + + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + priv fn alloc_pod<'a, T>(&'a self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); @@ -213,7 +228,7 @@ pub impl Arena { } // Functions for the non-POD part of the arena - fn alloc_nonpod_grow(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { + priv fn alloc_nonpod_grow(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { // Allocate a new chunk. let chunk_size = at_vec::capacity(self.head.data); let new_min_chunk_size = uint::max(n_bytes, chunk_size); @@ -225,7 +240,7 @@ pub impl Arena { } #[inline(always)] - fn alloc_nonpod_inner(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { + priv fn alloc_nonpod_inner(&self, n_bytes: uint, align: uint) -> (*u8, *u8) { let head = &mut self.head; let tydesc_start = head.fill; @@ -247,7 +262,32 @@ pub impl Arena { } #[inline(always)] - fn alloc_nonpod(&self, op: &fn() -> T) -> &'self T { + #[cfg(stage0)] + priv fn alloc_nonpod(&self, op: &fn() -> T) -> &'self T { + unsafe { + let tydesc = sys::get_type_desc::(); + let (ty_ptr, ptr) = + self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align); + let ty_ptr: *mut uint = reinterpret_cast(&ty_ptr); + let ptr: *mut T = reinterpret_cast(&ptr); + // Write in our tydesc along with a bit indicating that it + // has *not* been initialized yet. + *ty_ptr = reinterpret_cast(&tydesc); + // Actually initialize it + rusti::move_val_init(&mut(*ptr), op()); + // Now that we are done, update the tydesc to indicate that + // the object is there. + *ty_ptr = bitpack_tydesc_ptr(tydesc, true); + + return reinterpret_cast(&ptr); + } + } + + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + priv fn alloc_nonpod<'a, T>(&'a self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); let (ty_ptr, ptr) = @@ -269,6 +309,7 @@ pub impl Arena { // The external interface #[inline(always)] + #[cfg(stage0)] fn alloc(&self, op: &fn() -> T) -> &'self T { unsafe { if !rusti::needs_drop::() { @@ -278,6 +319,21 @@ pub impl Arena { } } } + + // The external interface + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn alloc<'a, T>(&'a self, op: &fn() -> T) -> &'a T { + unsafe { + if !rusti::needs_drop::() { + self.alloc_pod(op) + } else { + self.alloc_nonpod(op) + } + } + } } #[test] diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index f69e2130e7141..632a38e8ca2d8 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -437,8 +437,7 @@ pub impl Bitv { if offset >= bitv.nbits { 0 } else { - // NOTE cannot use bitv[offset] until snapshot - bitv.index(&offset) as u8 << (7 - bit) + bitv[offset] as u8 << (7 - bit) } } @@ -460,8 +459,7 @@ pub impl Bitv { * Transform self into a [bool] by turning each bit into a bool */ fn to_bools(&self) -> ~[bool] { - // NOTE cannot use self[i] until snapshot - vec::from_fn(self.nbits, |i| self.index(&i)) + vec::from_fn(self.nbits, |i| self[i]) } /** diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs index e7ec86963eeb5..a88d13fda6621 100644 --- a/src/libstd/deque.rs +++ b/src/libstd/deque.rs @@ -41,6 +41,7 @@ impl Mutable for Deque { } } +#[cfg(stage0)] pub impl Deque { /// Create an empty Deque fn new() -> Deque { @@ -51,21 +52,142 @@ pub impl Deque { /// Return a reference to the first element in the deque /// /// Fails if the deque is empty + #[cfg(stage0)] fn peek_front(&self) -> &'self T { get(self.elts, self.lo) } + /// Return a reference to the first element in the deque + /// + /// Fails if the deque is empty + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) } + /// Return a reference to the last element in the deque /// /// Fails if the deque is empty + #[cfg(stage0)] fn peek_back(&self) -> &'self T { get(self.elts, self.hi - 1u) } + /// Return a reference to the last element in the deque + /// + /// Fails if the deque is empty + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) } + /// Retrieve an element in the deque by index /// /// Fails if there is no element with the given index + #[cfg(stage0)] fn get(&self, i: int) -> &'self T { let idx = (self.lo + (i as uint)) % self.elts.len(); get(self.elts, idx) } + /// Retrieve an element in the deque by index + /// + /// Fails if there is no element with the given index + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get<'a>(&'a self, i: int) -> &'a T { + let idx = (self.lo + (i as uint)) % self.elts.len(); + get(self.elts, idx) + } + + /// Iterate over the elements in the deque + fn each(&self, f: &fn(&T) -> bool) { + self.eachi(|_i, e| f(e)) + } + + /// Iterate over the elements in the deque by index + fn eachi(&self, f: &fn(uint, &T) -> bool) { + for uint::range(0, self.nelts) |i| { + if !f(i, self.get(i as int)) { return; } + } + } + + /// Remove and return the first element in the deque + /// + /// Fails if the deque is empty + fn pop_front(&mut self) -> T { + let mut result = self.elts[self.lo].swap_unwrap(); + self.lo = (self.lo + 1u) % self.elts.len(); + self.nelts -= 1u; + result + } + + /// Remove and return the last element in the deque + /// + /// Fails if the deque is empty + fn pop_back(&mut self) -> T { + if self.hi == 0u { + self.hi = self.elts.len() - 1u; + } else { self.hi -= 1u; } + let mut result = self.elts[self.hi].swap_unwrap(); + self.elts[self.hi] = None; + self.nelts -= 1u; + result + } + + /// Prepend an element to the deque + fn add_front(&mut self, t: T) { + let oldlo = self.lo; + if self.lo == 0u { + self.lo = self.elts.len() - 1u; + } else { self.lo -= 1u; } + if self.lo == self.hi { + self.elts = grow(self.nelts, oldlo, self.elts); + self.lo = self.elts.len() - 1u; + self.hi = self.nelts; + } + self.elts[self.lo] = Some(t); + self.nelts += 1u; + } + + /// Append an element to the deque + fn add_back(&mut self, t: T) { + if self.lo == self.hi && self.nelts != 0u { + self.elts = grow(self.nelts, self.lo, self.elts); + self.lo = 0u; + self.hi = self.nelts; + } + self.elts[self.hi] = Some(t); + self.hi = (self.hi + 1u) % self.elts.len(); + self.nelts += 1u; + } +} + +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub impl Deque { + /// Create an empty Deque + fn new() -> Deque { + Deque{nelts: 0, lo: 0, hi: 0, + elts: vec::from_fn(initial_capacity, |_| None)} + } + + /// Return a reference to the first element in the deque + /// + /// Fails if the deque is empty + fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) } + + /// Return a reference to the last element in the deque + /// + /// Fails if the deque is empty + fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) } + + /// Retrieve an element in the deque by index + /// + /// Fails if there is no element with the given index + fn get<'a>(&'a self, i: int) -> &'a T { + let idx = (self.lo + (i as uint)) % self.elts.len(); + get(self.elts, idx) + } + /// Iterate over the elements in the deque fn each(&self, f: &fn(&T) -> bool) { self.eachi(|_i, e| f(e)) diff --git a/src/libstd/future.rs b/src/libstd/future.rs index a4887306d2a93..feea8fb4fcda7 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -55,7 +55,7 @@ pub impl Future { } pub impl Future { - + #[cfg(stage0)] fn get_ref(&self) -> &'self A { /*! * Executes the future's closure and then returns a borrowed @@ -80,6 +80,34 @@ pub impl Future { } } } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get_ref<'a>(&'a self) -> &'a A { + /*! + * Executes the future's closure and then returns a borrowed + * pointer to the result. The borrowed pointer lasts as long as + * the future. + */ + unsafe { + match self.state { + Forced(ref mut v) => { return cast::transmute(v); } + Evaluating => fail!(~"Recursive forcing of future!"), + Pending(_) => {} + } + + let mut state = Evaluating; + self.state <-> state; + match state { + Forced(_) | Evaluating => fail!(~"Logic error."), + Pending(f) => { + self.state = Forced(f()); + self.get_ref() + } + } + } + } } pub fn from_value(val: A) -> Future { diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index dd56e41359582..c8d250f90f6c4 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -50,13 +50,29 @@ impl Mutable for PriorityQueue { pub impl PriorityQueue { /// Returns the greatest item in the queue - fails if empty + #[cfg(stage0)] fn top(&self) -> &'self T { &self.data[0] } + /// Returns the greatest item in the queue - fails if empty + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn top<'a>(&'a self) -> &'a T { &self.data[0] } + /// Returns the greatest item in the queue - None if empty + #[cfg(stage0)] fn maybe_top(&self) -> Option<&'self T> { if self.is_empty() { None } else { Some(self.top()) } } + /// Returns the greatest item in the queue - None if empty + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn maybe_top<'a>(&'a self) -> Option<&'a T> { + if self.is_empty() { None } else { Some(self.top()) } + } + /// Returns the number of elements the queue can hold without reallocating fn capacity(&self) -> uint { vec::capacity(&self.data) } diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index 811cd710a62cc..d50804ba47b59 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -51,6 +51,7 @@ impl Map for SmallIntMap { } /// Visit all key-value pairs in order + #[cfg(stage0)] fn each(&self, it: &fn(&uint, &'self V) -> bool) { for uint::range(0, self.v.len()) |i| { match self.v[i] { @@ -60,18 +61,40 @@ impl Map for SmallIntMap { } } + /// Visit all key-value pairs in order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) { + for uint::range(0, self.v.len()) |i| { + match self.v[i] { + Some(ref elt) => if !it(&i, elt) { break }, + None => () + } + } + } + /// Visit all keys in order fn each_key(&self, blk: &fn(key: &uint) -> bool) { self.each(|k, _| blk(k)) } /// Visit all values in order + #[cfg(stage0)] fn each_value(&self, blk: &fn(value: &V) -> bool) { self.each(|_, v| blk(v)) } + /// Visit all values in order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) { + self.each(|_, v| blk(v)) + } + /// Iterate over the map and mutate the contained values - fn mutate_values(&mut self, it: &fn(&uint, &'self mut V) -> bool) { + fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) { for uint::range(0, self.v.len()) |i| { match self.v[i] { Some(ref mut elt) => if !it(&i, elt) { break }, @@ -81,6 +104,7 @@ impl Map for SmallIntMap { } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] fn find(&self, key: &uint) -> Option<&'self V> { if *key < self.v.len() { match self.v[*key] { @@ -92,7 +116,23 @@ impl Map for SmallIntMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find<'a>(&'a self, key: &uint) -> Option<&'a V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref value) => Some(value), + None => None + } + } else { + None + } + } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage0)] fn find_mut(&mut self, key: &uint) -> Option<&'self mut V> { if *key < self.v.len() { match self.v[*key] { @@ -104,6 +144,21 @@ impl Map for SmallIntMap { } } + /// Return a mutable reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref mut value) => Some(value), + None => None + } + } else { + None + } + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -134,6 +189,7 @@ pub impl SmallIntMap { fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } /// Visit all key-value pairs in reverse order + #[cfg(stage0)] fn each_reverse(&self, it: &fn(uint, &'self V) -> bool) { for uint::range_rev(self.v.len(), 0) |i| { match self.v[i - 1] { @@ -143,9 +199,30 @@ pub impl SmallIntMap { } } + /// Visit all key-value pairs in reverse order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) { + for uint::range_rev(self.v.len(), 0) |i| { + match self.v[i - 1] { + Some(ref elt) => if !it(i - 1, elt) { break }, + None => () + } + } + } + + #[cfg(stage0)] fn get(&self, key: &uint) -> &'self V { self.find(key).expect("key not present") } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn get<'a>(&'a self, key: &uint) -> &'a V { + self.find(key).expect("key not present") + } } pub impl SmallIntMap { diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 041ea855cb39d..006455c44e429 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -105,26 +105,45 @@ impl Map for TreeMap { } /// Visit all key-value pairs in order + #[cfg(stage0)] fn each(&self, f: &fn(&'self K, &'self V) -> bool) { each(&self.root, f) } + /// Visit all key-value pairs in order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { + each(&self.root, f) + } + /// Visit all keys in order fn each_key(&self, f: &fn(&K) -> bool) { self.each(|k, _| f(k)) } /// Visit all values in order + #[cfg(stage0)] fn each_value(&self, f: &fn(&V) -> bool) { self.each(|_, v| f(v)) } + /// Visit all values in order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) { + self.each(|_, v| f(v)) + } + /// Iterate over the map and mutate the contained values - fn mutate_values(&mut self, f: &fn(&'self K, &'self mut V) -> bool) { + fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) { mutate_values(&mut self.root, f); } /// Return a reference to the value corresponding to the key + #[cfg(stage0)] fn find(&self, key: &K) -> Option<&'self V> { let mut current: &'self Option<~TreeNode> = &self.root; loop { @@ -141,12 +160,42 @@ impl Map for TreeMap { } } + /// Return a reference to the value corresponding to the key + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find<'a>(&'a self, key: &K) -> Option<&'a V> { + let mut current: &'a Option<~TreeNode> = &self.root; + loop { + match *current { + Some(ref r) => { + match key.cmp(&r.key) { + Less => current = &r.left, + Greater => current = &r.right, + Equal => return Some(&r.value) + } + } + None => return None + } + } + } + /// Return a mutable reference to the value corresponding to the key #[inline(always)] + #[cfg(stage0)] fn find_mut(&mut self, key: &K) -> Option<&'self mut V> { find_mut(&mut self.root, key) } + /// Return a mutable reference to the value corresponding to the key + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { + find_mut(&mut self.root, key) + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -170,7 +219,16 @@ pub impl TreeMap { fn new() -> TreeMap { TreeMap{root: None, length: 0} } /// Visit all key-value pairs in reverse order - fn each_reverse(&'self self, f: &fn(&'self K, &'self V) -> bool) { + #[cfg(stage0)] + fn each_reverse(&self, f: &fn(&'self K, &'self V) -> bool) { + each_reverse(&self.root, f); + } + + /// Visit all key-value pairs in reverse order + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { each_reverse(&self.root, f); } @@ -186,9 +244,19 @@ pub impl TreeMap { /// Get a lazy iterator over the key-value pairs in the map. /// Requires that it be frozen (immutable). + #[cfg(stage0)] fn iter(&self) -> TreeMapIterator<'self, K, V> { TreeMapIterator{stack: ~[], node: &self.root} } + + /// Get a lazy iterator over the key-value pairs in the map. + /// Requires that it be frozen (immutable). + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { + TreeMapIterator{stack: ~[], node: &self.root} + } } /// Lazy forward iterator over a map @@ -490,9 +558,20 @@ pub impl TreeSet { /// Get a lazy iterator over the values in the set. /// Requires that it be frozen (immutable). #[inline(always)] + #[cfg(stage0)] fn iter(&self) -> TreeSetIterator<'self, T> { TreeSetIterator{iter: self.map.iter()} } + + /// Get a lazy iterator over the values in the set. + /// Requires that it be frozen (immutable). + #[inline(always)] + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> { + TreeSetIterator{iter: self.map.iter()} + } } /// Lazy forward iterator over a set From c97c03cd6a5c4ac37f2e68226c9f8ec49c786fcf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Apr 2013 17:43:55 -0700 Subject: [PATCH 138/403] tests: changes in response to #5656 --- src/test/compile-fail/issue-3311.rs | 31 -------------- src/test/compile-fail/issue-3563.rs | 2 +- src/test/compile-fail/issue-3888.rs | 42 ------------------- src/test/compile-fail/issue-3969.rs | 2 +- .../regions-infer-paramd-indirect.rs | 4 +- src/test/compile-fail/staticness-mismatch.rs | 2 +- .../class-impl-very-parameterized-trait.rs | 10 ++--- src/test/run-pass/explicit-self.rs | 2 +- src/test/run-pass/issue-3860.rs | 2 +- ...-parameterization-self-types-issue-5224.rs | 38 ----------------- src/test/run-pass/regions-self-impls.rs | 2 +- src/test/run-pass/regions-trait.rs | 2 +- 12 files changed, 14 insertions(+), 125 deletions(-) delete mode 100644 src/test/compile-fail/issue-3311.rs delete mode 100644 src/test/compile-fail/issue-3888.rs delete mode 100644 src/test/run-pass/regions-parameterization-self-types-issue-5224.rs diff --git a/src/test/compile-fail/issue-3311.rs b/src/test/compile-fail/issue-3311.rs deleted file mode 100644 index 67059e4623e8f..0000000000000 --- a/src/test/compile-fail/issue-3311.rs +++ /dev/null @@ -1,31 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[legacy_mode] -struct Foo<'self> { - s: &'self str, - u: ~() -} - -pub impl<'self> Foo<'self> { - fn get_s(&self) -> &'self str { - self.s - } -} - -fn bar(s: &str, f: &fn(Option)) { - f(Some(Foo {s: s, u: ~()})); -} - -fn main() { - do bar(~"testing") |opt| { - io::println(opt.unwrap().get_s()); //~ ERROR illegal borrow: - }; -} diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs index d56cb0d51d234..38f28bd79dfa1 100644 --- a/src/test/compile-fail/issue-3563.rs +++ b/src/test/compile-fail/issue-3563.rs @@ -10,7 +10,7 @@ trait A { fn a(&self) { - || self.b() //~ ERROR type `&'self Self` does not implement any method in scope named `b` + || self.b() //~ ERROR type `&Self` does not implement any method in scope named `b` } } fn main() {} diff --git a/src/test/compile-fail/issue-3888.rs b/src/test/compile-fail/issue-3888.rs deleted file mode 100644 index 35f8557c32b60..0000000000000 --- a/src/test/compile-fail/issue-3888.rs +++ /dev/null @@ -1,42 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// n.b. This should be a run-pass test, but for now I'm testing -// that we don't see an "unknown scope" error. -fn vec_peek<'r, T>(v: &'r [T]) -> Option< (&'r T, &'r [T]) > { - if v.len() == 0 { - None - } else { - let vec_len = v.len(); - let head = &v[0]; - // note: this *shouldn't* be an illegal borrow! See #3888 - let tail = v.slice(1, vec_len); //~ ERROR illegal borrow: borrowed value does not live long enough - Some( (head, tail) ) - } -} - - -fn test_peek_empty_stack() { - let v : &[int] = &[]; - assert!((None == vec_peek(v))); -} - -fn test_peek_empty_unique() { - let v : ~[int] = ~[]; - assert!((None == vec_peek(v))); -} - -fn test_peek_empty_managed() { - let v : @[int] = @[]; - assert!((None == vec_peek(v))); -} - - -fn main() {} diff --git a/src/test/compile-fail/issue-3969.rs b/src/test/compile-fail/issue-3969.rs index 60991d40a54c3..b60a54a44bbfd 100644 --- a/src/test/compile-fail/issue-3969.rs +++ b/src/test/compile-fail/issue-3969.rs @@ -18,7 +18,7 @@ trait BikeMethods { impl BikeMethods for Bike { fn woops() -> ~str { ~"foo" } - //~^ ERROR method `woops` is declared as static in its impl, but not in its trait + //~^ ERROR has a `&const self` declaration in the trait, but not in the impl } pub fn main() { diff --git a/src/test/compile-fail/regions-infer-paramd-indirect.rs b/src/test/compile-fail/regions-infer-paramd-indirect.rs index e4ad93bde17e6..e8d66ab297b71 100644 --- a/src/test/compile-fail/regions-infer-paramd-indirect.rs +++ b/src/test/compile-fail/regions-infer-paramd-indirect.rs @@ -18,12 +18,12 @@ struct c<'self> { f: @b<'self> } -trait set_f { +trait set_f<'self> { fn set_f_ok(&self, b: @b<'self>); fn set_f_bad(&self, b: @b); } -impl<'self> set_f for c<'self> { +impl<'self> set_f<'self> for c<'self> { fn set_f_ok(&self, b: @b<'self>) { self.f = b; } diff --git a/src/test/compile-fail/staticness-mismatch.rs b/src/test/compile-fail/staticness-mismatch.rs index 719da233335e1..9bcf0777bbd34 100644 --- a/src/test/compile-fail/staticness-mismatch.rs +++ b/src/test/compile-fail/staticness-mismatch.rs @@ -14,7 +14,7 @@ trait foo { } impl foo for int { - fn bar(&self) {} //~ ERROR method `bar` is declared as static in its trait, but not in its impl + fn bar(&self) {} //~ ERROR method `bar` has a `&self` declaration in the impl, but not in the trait } fn main() {} diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index cfde61d74b21b..e4374e4d225a7 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -59,7 +59,7 @@ impl Mutable for cat { } impl Map for cat { - fn each(&self, f: &fn(&int, &T) -> bool) { + fn each<'a>(&'a self, f: &fn(&int, &'a T) -> bool) { let mut n = int::abs(self.meows); while n > 0 { if !f(&n, &self.name) { break; } @@ -73,7 +73,7 @@ impl Map for cat { for self.each |k, _| { if !f(k) { break; } loop;}; } - fn each_value(&self, f: &fn(v: &T) -> bool) { + fn each_value<'a>(&'a self, f: &fn(v: &'a T) -> bool) { for self.each |_, v| { if !f(v) { break; } loop;}; } @@ -86,7 +86,7 @@ impl Map for cat { true } - fn find(&self, k: &int) -> Option<&'self T> { + fn find<'a>(&'a self, k: &int) -> Option<&'a T> { if *k <= self.meows { Some(&self.name) } else { @@ -94,7 +94,7 @@ impl Map for cat { } } - fn find_mut(&mut self, _k: &int) -> Option<&'self mut T> { fail!() } + fn find_mut<'a>(&'a mut self, _k: &int) -> Option<&'a mut T> { fail!() } fn remove(&mut self, k: &int) -> bool { if self.find(k).is_some() { @@ -106,7 +106,7 @@ impl Map for cat { } pub impl cat { - fn get(&self, k: &int) -> &'self T { + fn get<'a>(&'a self, k: &int) -> &'a T { match self.find(k) { Some(v) => { v } None => { fail!(~"epic fail"); } diff --git a/src/test/run-pass/explicit-self.rs b/src/test/run-pass/explicit-self.rs index c5b5016572caa..7e46bf22c4d92 100644 --- a/src/test/run-pass/explicit-self.rs +++ b/src/test/run-pass/explicit-self.rs @@ -58,7 +58,7 @@ pub impl thing { fn foo(@self) -> int { *self.x.a } fn bar(~self) -> int { *self.x.a } fn quux(&self) -> int { *self.x.a } - fn baz(&self) -> &'self A { &self.x } + fn baz<'a>(&'a self) -> &'a A { &self.x } fn spam(self) -> int { *self.x.a } } diff --git a/src/test/run-pass/issue-3860.rs b/src/test/run-pass/issue-3860.rs index 18839fa3c7fc4..46aa7187c9a02 100644 --- a/src/test/run-pass/issue-3860.rs +++ b/src/test/run-pass/issue-3860.rs @@ -11,7 +11,7 @@ struct Foo { x: int } pub impl Foo { - fn stuff(&mut self) -> &'self mut Foo { + fn stuff<'a>(&'a mut self) -> &'a mut Foo { return self; } } diff --git a/src/test/run-pass/regions-parameterization-self-types-issue-5224.rs b/src/test/run-pass/regions-parameterization-self-types-issue-5224.rs deleted file mode 100644 index 346a0fcfe0793..0000000000000 --- a/src/test/run-pass/regions-parameterization-self-types-issue-5224.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test how region-parameterization inference -// interacts with explicit self types. -// -// Issue #5224. - -trait Getter { - // This trait does not need to be - // region-parameterized, because 'self - // is bound in the self type: - fn get(&self) -> &'self int; -} - -struct Foo { - field: int -} - -impl Getter for Foo { - fn get(&self) -> &'self int { &self.field } -} - -fn get_int(g: &G) -> int { - *g.get() -} - -pub fn main() { - let foo = Foo { field: 22 }; - assert!(get_int(&foo) == 22); -} diff --git a/src/test/run-pass/regions-self-impls.rs b/src/test/run-pass/regions-self-impls.rs index 16b6364093e2e..2f4eefe5243ad 100644 --- a/src/test/run-pass/regions-self-impls.rs +++ b/src/test/run-pass/regions-self-impls.rs @@ -16,7 +16,7 @@ trait get_chowder<'self> { fn get_chowder(&self) -> &'self int; } -impl<'self> get_chowder for Clam<'self> { +impl<'self> get_chowder<'self> for Clam<'self> { fn get_chowder(&self) -> &'self int { return self.chowder; } } diff --git a/src/test/run-pass/regions-trait.rs b/src/test/run-pass/regions-trait.rs index f453272057975..a2ed9da67f264 100644 --- a/src/test/run-pass/regions-trait.rs +++ b/src/test/run-pass/regions-trait.rs @@ -16,7 +16,7 @@ trait get_ctxt<'self> { struct HasCtxt<'self> { c: &'self Ctxt } -impl<'self> get_ctxt for HasCtxt<'self> { +impl<'self> get_ctxt<'self> for HasCtxt<'self> { fn get_ctxt(&self) -> &'self Ctxt { self.c } From a9741bd33d7e55401f506bb82b99411d03ce7e3f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 27 Mar 2013 17:55:18 -0700 Subject: [PATCH 139/403] Update LLVM for ARM changes --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index accc36b3e3f22..56dd407f4f97a 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit accc36b3e3f22319b16609460f4cdf964f33f6cb +Subproject commit 56dd407f4f97a01b8df6554c569170d2fc276fcb From 4b4f48283bdd71fa106f1e2ce80c6d2a0d2aff36 Mon Sep 17 00:00:00 2001 From: Young-il Choi Date: Wed, 20 Mar 2013 20:24:39 +0900 Subject: [PATCH 140/403] rustllvm: followup latest LLVM --- src/rustllvm/RustWrapper.cpp | 20 +++++++++++++------- src/rustllvm/rustllvm.def.in | 2 -- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bdf13746f3ebf..68483b0280f4a 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -15,14 +15,12 @@ // //===----------------------------------------------------------------------=== -#include "llvm/InlineAsm.h" -#include "llvm/LLVMContext.h" #include "llvm/Linker.h" #include "llvm/PassManager.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/Passes.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Assembly/Parser.h" @@ -31,11 +29,9 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Support/Host.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DynamicLibrary.h" @@ -45,6 +41,10 @@ #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" #include "llvm-c/Core.h" #include "llvm-c/BitReader.h" #include "llvm-c/Object.h" @@ -218,6 +218,12 @@ class RustMCJITMemoryManager : public JITMemoryManager { virtual void deallocateExceptionTable(void *ET) { llvm_unreachable("Unimplemented call"); } + virtual uint8_t* allocateDataSection(uintptr_t, unsigned int, unsigned int, bool) { + llvm_unreachable("Unimplemented call"); + } + virtual bool applyPermissions(std::string*) { + llvm_unreachable("Unimplemented call"); + } }; bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { @@ -481,7 +487,7 @@ extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { if (m) { return wrap(m); } else { - LLVMRustError = d.getMessage().c_str(); + LLVMRustError = d.getMessage().data(); return NULL; } } diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index 8b1c9d5ec7fbc..73bf1af90cd34 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -383,8 +383,6 @@ LLVMInitializeInstCombine LLVMInitializeScalarOpts LLVMInitializeTarget LLVMInitializeTransformUtils -LLVMInitializeARMAsmLexer -LLVMInitializeX86AsmLexer LLVMInitializeARMAsmParser LLVMInitializeMipsAsmParser LLVMInitializeX86AsmParser From 3d0d144283959bf62368f6965aae14ce95ee286b Mon Sep 17 00:00:00 2001 From: ILyoan Date: Fri, 22 Feb 2013 15:17:54 +0900 Subject: [PATCH 141/403] rust morestack assembly for arm Conflicts: src/rt/arch/arm/morestack.S --- src/rt/arch/arm/morestack.S | 55 ++++++++++++++++++++++++++++++++++++- src/rt/arch/arm/record_sp.S | 47 ++++--------------------------- 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S index 1afce5bd848b7..3af8e898cdbcf 100644 --- a/src/rt/arch/arm/morestack.S +++ b/src/rt/arch/arm/morestack.S @@ -8,6 +8,59 @@ .arm .align -.globl __morestack +.global upcall_new_stack +.global upcall_del_stack +.global __morestack .hidden __morestack + +// r4 and r5 are scratch registers for __morestack due to llvm +// ARMFrameLowering::adjustForSegmentedStacks() implementation. + .align 2 + .type __morestack,%function __morestack: + + // Save frame pointer and return address + push {fp, lr} + + mov fp, sp + + // Save argument registers of the original function + push {r0, r1, r2, r3, lr} + + mov r0, r4 // The amount of stack needed + add r1, fp, #20 // Address of stack arguments + mov r2, r5 // Size of stack arguments + + // Create new stack + bl upcall_new_stack@plt + + // Hold new stack pointer + mov r5, r0 + + // Pop the saved arguments + pop {r0, r1, r2, r3, lr} + + // Grab the return pointer + add r4, lr, #16 // Skip past the return + mov sp, r5 // Swich to the new stack + mov lr, pc + mov pc, r4 // Call the original function + + // Switch back to rust stack + mov sp, fp + + // Save return value + push {r0, r1} + + // Remove the new allocated stack + bl upcall_del_stack@plt + + // Restore return value + pop {r0, r1} + + // Return + pop {fp, lr} + mov pc, lr +.endofmorestack: + .size __morestack, .endofmorestack-__morestack + diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S index abd8fbb6a5b05..fe680004a89aa 100644 --- a/src/rt/arch/arm/record_sp.S +++ b/src/rt/arch/arm/record_sp.S @@ -14,53 +14,18 @@ .globl get_sp record_sp_limit: - mov r3, r0 - ldr r0, =my_cpu - mov r1, #0 - mov r2, #0 - stmfd sp!, {r3, r7} - ldr r7, =345 - swi #0 - ldmfd sp!, {r3, r7} - movs r0, r0 - movmi r0, #0 - - ldr r1, =my_array - str r3, [r1, r0] + mrc p15, #0, r3, c13, c0, #3 + add r3, r3, #252 + str r0, [r3] mov pc, lr - get_sp_limit: - ldr r0, =my_cpu - mov r1, #0 - mov r2, #0 - stmfd sp!, {r4, r7} - ldr r7, =345 - swi #0 - ldmfd sp!, {r4, r7} - movs r0, r0 - movmi r0, #0 - mov r3, r0 - - ldr r1, =my_array - ldr r0, [r1, r3] + mrc p15, #0, r3, c13, c0, #3 + add r3, r3, #252 + ldr r0, [r3] mov pc, lr - get_sp: mov r0, sp mov pc, lr -.data -my_cpu: .long 0 -.global my_array -my_array: - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 - .long 0 -.end From 344628fe91ffa0fad32bc5b3eee3e6b4b48c9990 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Wed, 13 Mar 2013 17:22:01 +0900 Subject: [PATCH 142/403] FIX meta_section_name for macos --- src/librustc/metadata/loader.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 9c61205667750..cfe9c8cd40a66 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -206,7 +206,8 @@ fn get_metadata_section(os: os, while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { let name_buf = llvm::LLVMGetSectionName(si.llsi); let name = unsafe { str::raw::from_c_str(name_buf) }; - if name == meta_section_name(os) { + debug!("get_matadata_section: name %s", name); + if name == read_meta_section_name(os) { let cbuf = llvm::LLVMGetSectionContents(si.llsi); let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let mut found = None; @@ -251,6 +252,16 @@ pub fn meta_section_name(os: os) -> ~str { } } +pub fn read_meta_section_name(os: os) -> ~str { + match os { + os_macos => ~"__note.rustc", + os_win32 => ~".note.rustc", + os_linux => ~".note.rustc", + os_android => ~".note.rustc", + os_freebsd => ~".note.rustc" + } +} + // A diagnostic function for dumping crate metadata to an output stream pub fn list_file_metadata(intr: @ident_interner, os: os, From a34948a2c5d7cd296abda6970652a9513d67feb7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 28 Mar 2013 16:47:33 -0700 Subject: [PATCH 143/403] rustllvm: Initialize target analysis passes Without this the target info for certain optimizations will not be created and the compiler will sometimes crash --- src/rustllvm/RustWrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 68483b0280f4a..5d422b2d2edc3 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -452,6 +452,8 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; + PassManager *PM = unwrap(PMR); + std::string Err; std::string Trip(Triple::normalize(triple)); std::string FeaturesStr; @@ -461,8 +463,9 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, TheTarget->createTargetMachine(Trip, CPUStr, FeaturesStr, Options, Reloc::PIC_, CodeModel::Default, OptLevel); + Target->addAnalysisPasses(*PM); + bool NoVerify = false; - PassManager *PM = unwrap(PMR); std::string ErrorInfo; raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary); From 03116f251d2d53842971b356fb320f6101d1a3e5 Mon Sep 17 00:00:00 2001 From: ILyoan Date: Tue, 19 Mar 2013 14:28:10 +0900 Subject: [PATCH 144/403] add unwind information on morestack --- src/rt/arch/arm/morestack.S | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S index 3af8e898cdbcf..4f1431a33927a 100644 --- a/src/rt/arch/arm/morestack.S +++ b/src/rt/arch/arm/morestack.S @@ -15,14 +15,19 @@ // r4 and r5 are scratch registers for __morestack due to llvm // ARMFrameLowering::adjustForSegmentedStacks() implementation. - .align 2 - .type __morestack,%function + .type __morestack,%function __morestack: + .fnstart + // Save frame pointer and return address + .save {r4, r5} + .save {lr} + .save {r6, fp, lr} + push {r6, fp, lr} - // Save frame pointer and return address - push {fp, lr} - - mov fp, sp + .movsp r6 + mov r6, sp + .setfp fp, sp, #4 + add fp, sp, #4 // Save argument registers of the original function push {r0, r1, r2, r3, lr} @@ -47,20 +52,20 @@ __morestack: mov pc, r4 // Call the original function // Switch back to rust stack - mov sp, fp + mov sp, r6 // Save return value - push {r0, r1} + mov r4, r0 + mov r5, r1 // Remove the new allocated stack bl upcall_del_stack@plt // Restore return value - pop {r0, r1} - + mov r0, r4 + mov r1, r5 + // Return - pop {fp, lr} + pop {r6, fp, lr} mov pc, lr -.endofmorestack: - .size __morestack, .endofmorestack-__morestack - + .fnend From 22786d6c5b3fb94ef64295f5b832ed776954db09 Mon Sep 17 00:00:00 2001 From: Thomas Daede Date: Thu, 11 Apr 2013 09:49:43 +0400 Subject: [PATCH 145/403] Add check for 'file' command which is necessary for 32-bit userspace detection. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 71beb8214b9da..e7a6ce6a7fb6c 100755 --- a/configure +++ b/configure @@ -237,7 +237,7 @@ need_cmd uname need_cmd date need_cmd tr need_cmd sed - +need_cmd file msg "inspecting environment" From 5b457c1469704b69a569724e03667f337fcb4749 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 11 Apr 2013 00:16:09 -0700 Subject: [PATCH 146/403] xail all debuginfo tests The broke with the LLVM upgrade --- src/test/debug-info/basic-types.rs | 2 ++ src/test/debug-info/struct.rs | 2 ++ src/test/debug-info/tuple.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/test/debug-info/basic-types.rs b/src/test/debug-info/basic-types.rs index 2441b35bc320b..20da6b557f18d 100644 --- a/src/test/debug-info/basic-types.rs +++ b/src/test/debug-info/basic-types.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + // Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values) // as its numerical value along with its associated ASCII char, there // doesn't seem to be any way around this. Also, gdb doesn't know diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs index 30f4b657c4e35..16ba6cda5900a 100644 --- a/src/test/debug-info/struct.rs +++ b/src/test/debug-info/struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break 29 diff --git a/src/test/debug-info/tuple.rs b/src/test/debug-info/tuple.rs index a2cdc689fad47..35e2977f562e9 100644 --- a/src/test/debug-info/tuple.rs +++ b/src/test/debug-info/tuple.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break 20 From 5f59012cce2675d805e5a6a3af75b76ee015af24 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 11 Apr 2013 17:56:24 +1000 Subject: [PATCH 147/403] Implement Finally for ~fn and @fn types --- src/libcore/unstable/finally.rs | 43 ++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/libcore/unstable/finally.rs b/src/libcore/unstable/finally.rs index 4d2daa6f15027..559287b529772 100644 --- a/src/libcore/unstable/finally.rs +++ b/src/libcore/unstable/finally.rs @@ -25,7 +25,7 @@ do || { use ops::Drop; -#[cfg(test)] use task::failing; +#[cfg(test)] use task::{failing, spawn}; pub trait Finally { fn finally(&self, dtor: &fn()) -> T; @@ -41,6 +41,26 @@ impl<'self,T> Finally for &'self fn() -> T { } } +impl Finally for ~fn() -> T { + fn finally(&self, dtor: &fn()) -> T { + let _d = Finallyalizer { + dtor: dtor + }; + + (*self)() + } +} + +impl Finally for @fn() -> T { + fn finally(&self, dtor: &fn()) -> T { + let _d = Finallyalizer { + dtor: dtor + }; + + (*self)() + } +} + struct Finallyalizer<'self> { dtor: &'self fn() } @@ -96,3 +116,24 @@ fn test_compact() { do_some_fallible_work.finally( but_always_run_this_function); } + +#[test] +fn test_owned() { + fn spawn_with_finalizer(f: ~fn()) { + do spawn { do f.finally { } } + } + let owned: ~fn() = || { }; + spawn_with_finalizer(owned); +} + +#[test] +fn test_managed() { + let i = @mut 10; + let managed: @fn() -> int = || { + let r = *i; + *i += 10; + r + }; + assert!(do managed.finally {} == 10); + assert!(*i == 20); +} \ No newline at end of file From aff558998ef98b4c80cace32538ba23ee67a4d6d Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Thu, 11 Apr 2013 09:12:26 -0400 Subject: [PATCH 148/403] Fix formatting --- src/libcore/rand.rs | 74 ++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 2ee280ff15917..c6400ccded8a6 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -157,11 +157,11 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(fmt!("%d",rng.gen_int())); + * rng = rand::Rng(); + * println(fmt!("%d",rng.gen_int())); * } * ~~~ */ @@ -197,11 +197,11 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(fmt!("%f",rng.gen_float())); + * rng = rand::Rng(); + * println(fmt!("%f",rng.gen_float())); * } * ~~~ */ @@ -223,10 +223,10 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::Rng(); * println(fmt!("%b",rng.gen_bool())); * } * ~~~ @@ -239,11 +239,11 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(fmt!("%b",rng.gen_weighted_bool(3))); + * rng = rand::Rng(); + * println(fmt!("%b",rng.gen_weighted_bool(3))); * } * ~~~ */ @@ -255,11 +255,11 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(rng.gen_str(8)); + * rng = rand::Rng(); + * println(rng.gen_str(8)); * } * ~~~ */ @@ -271,16 +271,16 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(fmt!("%?",rng.gen_bytes(8))); + * rng = rand::Rng(); + * println(fmt!("%?",rng.gen_bytes(8))); * } * ~~~ */ fn gen_bytes(&self, len: uint) -> ~[u8]; - /// + /// /** * Choose an item randomly, failing if values is empty * @@ -288,11 +288,11 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * println(fmt!("%d",rng.choose([1,2,4,8,16,32]))); + * rng = rand::Rng(); + * println(fmt!("%d",rng.choose([1,2,4,8,16,32]))); * } * ~~~ */ @@ -307,11 +307,13 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, + * rand::Weighted {weight: 2, item: 'b'}, + * rand::Weighted {weight: 2, item: 'c'}]; * println(fmt!("%c",rng.choose_weighted(x))); * } * ~~~ @@ -325,11 +327,13 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, + * rand::Weighted {weight: 2, item: 'b'}, + * rand::Weighted {weight: 2, item: 'c'}]; * println(fmt!("%?",rng.choose_weighted_option(x))); * } * ~~~ @@ -343,11 +347,13 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, rand::Weighted {weight: 2, item: 'b'}, rand::Weighted {weight: 2, item: 'c'}]; + * rng = rand::Rng(); + * let x = [rand::Weighted {weight: 4, item: 'a'}, + * rand::Weighted {weight: 2, item: 'b'}, + * rand::Weighted {weight: 2, item: 'c'}]; * println(fmt!("%?",rng.weighted_vec(x))); * } * ~~~ @@ -360,10 +366,10 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::Rng(); * println(fmt!("%?",rng.shuffle([1,2,3]))); * } * ~~~ @@ -376,10 +382,10 @@ pub trait RngUtil { * * ~~~ * - * use core::rand::RngUtil; + * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::Rng(); * let mut y = [1,2,3]; * rng.shuffle_mut(y); * println(fmt!("%?",y)); From 62c94d3a38985f5f6f12920d14867e73a19fefe2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 11 Apr 2013 11:46:48 -0700 Subject: [PATCH 149/403] Pass the value of python to LLVM's configure script. #5835 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f09213404d1ac..5c4c31c5a2386 100755 --- a/configure +++ b/configure @@ -859,7 +859,7 @@ do LDFLAGS=$LLVM_LDFLAGS LLVM_FLAGS="$LLVM_TARGETS $LLVM_OPTS $LLVM_BUILD \ - $LLVM_HOST $LLVM_TARGET" + $LLVM_HOST $LLVM_TARGET --with-python=$CFG_PYTHON" msg "configuring LLVM with:" msg "$LLVM_FLAGS" From 995d44416b203b5b3ba619250ff8effdcf205049 Mon Sep 17 00:00:00 2001 From: gareth Date: Thu, 11 Apr 2013 21:51:39 +0100 Subject: [PATCH 150/403] Make destroy() send SIGTERM and add a new method called force_destroy() that sends SIGKILL - as suggested by @thestinger. --- src/libcore/libc.rs | 3 +++ src/libcore/run.rs | 53 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index e17a6be3f1f95..02c72bcd2f0d0 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -864,6 +864,7 @@ pub mod consts { pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; pub static SIGKILL : int = 9; + pub static SIGTERM : int = 15; } pub mod posix01 { } @@ -932,6 +933,7 @@ pub mod consts { pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; pub static SIGKILL : int = 9; + pub static SIGTERM : int = 15; } pub mod posix01 { } @@ -1001,6 +1003,7 @@ pub mod consts { pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; pub static SIGKILL : int = 9; + pub static SIGTERM : int = 15; } pub mod posix01 { } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index e7602cff4928d..f6f4b9a397d81 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -63,10 +63,22 @@ pub trait Program { fn finish(&mut self) -> int; /** - * Forcibly terminate the program. On Posix OSs SIGKILL will be sent - * to the process. On Win32 TerminateProcess(..) will be called. + * Terminate the program, giving it a chance to clean itself up if + * this is supported by the operating system. + * + * On Posix OSs SIGTERM will be sent to the process. On Win32 + * TerminateProcess(..) will be called. */ fn destroy(&mut self); + + /** + * Terminate the program as soon as possible without giving it a + * chance to clean itself up. + * + * On Posix OSs SIGKILL will be sent to the process. On Win32 + * TerminateProcess(..) will be called. + */ + fn force_destroy(&mut self); } @@ -266,13 +278,13 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { return waitpid(r.pid); } - fn destroy_repr(r: &mut ProgRepr) { - killpid(r.pid); + fn destroy_repr(r: &mut ProgRepr, force: bool) { + killpid(r.pid, force); finish_repr(&mut *r); close_repr_outputs(&mut *r); #[cfg(windows)] - fn killpid(pid: pid_t) { + fn killpid(pid: pid_t, _force: bool) { unsafe { libc::funcs::extra::kernel32::TerminateProcess( cast::transmute(pid), 1); @@ -280,10 +292,16 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { } #[cfg(unix)] - fn killpid(pid: pid_t) { + fn killpid(pid: pid_t, force: bool) { + + let signal = if force { + libc::consts::os::posix88::SIGKILL + } else { + libc::consts::os::posix88::SIGTERM + }; + unsafe { - libc::funcs::posix88::signal::kill( - pid, libc::consts::os::posix88::SIGKILL as c_int); + libc::funcs::posix88::signal::kill(pid, signal as c_int); } } } @@ -321,7 +339,8 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { } fn close_input(&mut self) { close_repr_input(&mut self.r); } fn finish(&mut self) -> int { finish_repr(&mut self.r) } - fn destroy(&mut self) { destroy_repr(&mut self.r); } + fn destroy(&mut self) { destroy_repr(&mut self.r, false); } + fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); } } let mut repr = ProgRepr { @@ -559,10 +578,9 @@ mod tests { p.destroy(); // ...and nor should this (and nor should the destructor) } - #[test] #[cfg(unix)] // there is no way to sleep on windows from inside libcore... - pub fn test_destroy_actually_kills() { - let path = Path("test/core-run-test-destroy-actually-kills.tmp"); + pub fn test_destroy_actually_kills(force: bool) { + let path = Path(fmt!("test/core-run-test-destroy-actually-kills-%?.tmp", force)); os::remove_file(&path); @@ -580,6 +598,17 @@ mod tests { assert!(!path.exists()); } + #[test] + #[cfg(unix)] + pub fn test_unforced_destroy_actually_kills() { + test_destroy_actually_kills(false); + } + + #[test] + #[cfg(unix)] + pub fn test_forced_destroy_actually_kills() { + test_destroy_actually_kills(true); + } } // Local Variables: From 61b29993ddd531c6f53f7d21ddf28d26d4d63a21 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 11 Apr 2013 08:33:41 -0400 Subject: [PATCH 151/403] bool: implement Ord and TotalOrd --- src/libcore/bool.rs | 99 ++++++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index a30cb92693748..6c60cec2595ef 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Boolean logic +#[cfg(notest)] +use cmp::{Eq, Ord, TotalOrd, Ordering}; use option::{None, Option, Some}; use from_str::FromStr; -#[cfg(notest)] use cmp; - /// Negation / inverse pub fn not(v: bool) -> bool { !v } @@ -73,40 +72,86 @@ pub fn all_values(blk: &fn(v: bool)) { } /// converts truth value to an 8 bit byte +#[inline(always)] pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } } #[cfg(notest)] -impl cmp::Eq for bool { +impl Ord for bool { + #[inline(always)] + fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) } + #[inline(always)] + fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) } + #[inline(always)] + fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) } + #[inline(always)] + fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) } +} + +#[cfg(notest)] +impl TotalOrd for bool { + #[inline(always)] + fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) } +} + +#[cfg(notest)] +impl Eq for bool { + #[inline(always)] fn eq(&self, other: &bool) -> bool { (*self) == (*other) } + #[inline(always)] fn ne(&self, other: &bool) -> bool { (*self) != (*other) } } -#[test] -pub fn test_bool_from_str() { - use from_str::FromStr; +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; - do all_values |v| { - assert!(Some(v) == FromStr::from_str(to_str(v))) + #[test] + fn test_bool_from_str() { + use from_str::FromStr; + + do all_values |v| { + assert!(Some(v) == FromStr::from_str(to_str(v))) + } } -} -#[test] -pub fn test_bool_to_str() { - assert!(to_str(false) == ~"false"); - assert!(to_str(true) == ~"true"); -} + #[test] + fn test_bool_to_str() { + assert!(to_str(false) == ~"false"); + assert!(to_str(true) == ~"true"); + } -#[test] -pub fn test_bool_to_bit() { - do all_values |v| { - assert!(to_bit(v) == if is_true(v) { 1u8 } else { 0u8 }); + #[test] + fn test_bool_to_bit() { + do all_values |v| { + assert!(to_bit(v) == if is_true(v) { 1u8 } else { 0u8 }); + } } -} -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: + #[test] + fn test_bool_ord() { + assert!(true > false); + assert!(!(false > true)); + + assert!(false < true); + assert!(!(true < false)); + + assert!(false <= false); + assert!(false >= false); + assert!(true <= true); + assert!(true >= true); + + assert!(false <= true); + assert!(!(false >= true)); + assert!(true >= false); + assert!(!(true <= false)); + } + + #[test] + fn test_bool_totalord() { + assert_eq!(true.cmp(&true), Equal); + assert_eq!(false.cmp(&false), Equal); + assert_eq!(true.cmp(&false), Greater); + assert_eq!(false.cmp(&true), Less); + } +} From 8158dd7e9a3469b8c0946035b457a953faf29d99 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 11 Apr 2013 17:43:02 -0700 Subject: [PATCH 152/403] rustpkg: Use pkg IDs, remove old code for now that required packages to declare IDs explicitly This is preliminary work on bringing rustpkg up to conformance with #5679 and related issues. This change makes rustpkg infer a package ID from its containing directory, instead of requiring name and vers attributes in the code. Many aspects of it are incomplete; I've only tested one package (see README.txt) and one command, "build". So far it only works for local packages. I also removed code for several of the package commands other than "build", replacing them with stubs that fail, since they used package IDs in ways that didn't jibe well with the new scheme. I will re-implement the commands one at a time. --- src/librustpkg/README.txt | 4 + src/librustpkg/rustpkg.rc | 936 ++++++++++++++------------------------ src/librustpkg/util.rs | 543 +++++++--------------- 3 files changed, 519 insertions(+), 964 deletions(-) create mode 100644 src/librustpkg/README.txt diff --git a/src/librustpkg/README.txt b/src/librustpkg/README.txt new file mode 100644 index 0000000000000..eacf07e01ea57 --- /dev/null +++ b/src/librustpkg/README.txt @@ -0,0 +1,4 @@ +Right now (2013-04-11), only one package works, the branch of rust-sdl at: +https://github.com/catamorphism/rust-sdl/tree/new-rustpkg + +and only one command works, "build". diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 86802c6578144..24c37d2558951 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -27,42 +27,51 @@ extern mod rustc(vers = "0.6"); extern mod syntax(vers = "0.6"); use core::*; +pub use core::path::Path; use core::container::Map; use core::hashmap::HashMap; use core::io::WriterUtil; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::net::url; -use std::{json, semver, getopts}; -use syntax::codemap::spanned; +use std::{getopts}; use syntax::{ast, diagnostic}; -use util::Package; +use util::{ExitCode, Pkg, PkgId}; mod usage; mod util; -struct PackageScript { - id: ~str, - name: ~str, - vers: semver::Version, - crates: ~[~str], - deps: ~[(~str, Option<~str>)], +/// A PkgScript represents user-supplied custom logic for +/// special build hooks. This only exists for packages with +/// an explicit package script. +struct PkgScript { + /// Uniquely identifies this package + id: PkgId, + // Used to have this field: deps: ~[(~str, Option<~str>)] + // but I think it shouldn't be stored here + /// The contents of the package script: either a file path, + /// or a string containing the text of the input input: driver::input, + /// The session to use *only* for compiling the custom + /// build script sess: session::Session, + /// The config for compiling the custom build script cfg: ast::crate_cfg, + /// The crate for the custom build script crate: @ast::crate, - custom: bool + /// Directory in which to store build output + build_dir: Path } -impl PackageScript { - fn parse(parent: &Path) -> Result { - let script = parent.push(~"pkg.rs"); - - if !os::path_exists(&script) { - return result::Err(~"no pkg.rs file"); - } - +impl PkgScript { + /// Given the path name for a package script + /// and a package ID, parse the package script into + /// a PkgScript that we can then execute + fn parse(script: Path, id: PkgId) -> PkgScript { + // Get the executable name that was invoked let binary = os::args()[0]; + // Build the rustc session data structures to pass + // to the compiler let options = @session::options { binary: binary, crate_type: session::bin_crate, @@ -73,190 +82,122 @@ impl PackageScript { let cfg = driver::build_configuration(sess, binary, input); let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, None); - let mut id = None; - let mut vers = None; - let mut crates = ~[]; - let mut deps = ~[]; - - fn load_pkg_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>) { - let mut id = None; - let mut vers = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"id" => id = Some(*s), - ~"vers" => vers = Some(*s), - _ => () - } - } - _ => {} - } - } - - (id, vers) - } + let work_dir = dest_dir(id); - fn load_pkg_dep_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>) { - let mut url = None; - let mut target = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"url" => url = Some(*s), - ~"target" => target = Some(*s), - _ => () - } - } - _ => {} - } - } - - (url, target) - } + debug!("Returning package script with id %?", id); - fn load_pkg_crate_attr(mis: ~[@ast::meta_item]) -> Option<~str> { - let mut file = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"file" => file = Some(*s), - _ => () - } - } - _ => {} - } - } - - file - } - - for crate.node.attrs.each |a| { - match a.node.value.node { - ast::meta_list(v, mis) => { - match *v { - ~"pkg" => { - let (i, v) = load_pkg_attr(mis); - - id = i; - vers = v; - } - ~"pkg_dep" => { - let (u, t) = load_pkg_dep_attr(mis); - - if u.is_none() { - fail!(~"pkg_dep attr without a url value"); - } - - deps.push((u.get(), t)); - } - ~"pkg_crate" => { - let f = load_pkg_crate_attr(mis); - - if f.is_none() { - fail!(~"pkg_file attr without a file value"); - } - - crates.push(f.get()); - } - _ => {} - } - } - _ => {} - } - } - - let mut custom = false; - - // If we hit a function, we assume they want to use - // the build API. - for crate.node.module.items.each |i| { - match i.node { - ast::item_fn(*) => { - custom = true; - - break; - } - _ => {} - } - } - - if id.is_none() || vers.is_none() { - return result::Err(~"pkg attr without (id, vers) values"); - } - - let id = id.get(); - let name = match util::parse_name(id) { - result::Ok(name) => name, - result::Err(err) => return result::Err(err) - }; - let vers = match util::parse_vers(vers.get()) { - result::Ok(vers) => vers, - result::Err(err) => return result::Err(err) - }; - - result::Ok(PackageScript { + PkgScript { id: id, - name: name, - vers: vers, - crates: crates, - deps: deps, input: input, sess: sess, cfg: cfg, crate: crate, - custom: custom - }) + build_dir: work_dir + } } - // Build the bootstrap and run a command + /// Run the contents of this package script, where + /// is the command to pass to it (e.g., "build", "clean", "install") + /// Returns a pair of an exit code and list of configs (obtained by + /// calling the package script's configs() function if it exists // FIXME (#4432): Use workcache to only compile the script when changed - fn run(&self, cmd: ~str, test: bool) -> int { - let work_dir = self.work_dir(); - let input = self.input; + fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) { + debug!("run_custom: %s", what); let sess = self.sess; - let cfg = self.cfg; + + debug!("Working directory = %s", self.build_dir.to_str()); + // Collect together any user-defined commands in the package script let crate = util::ready_crate(sess, self.crate); - let outputs = driver::build_output_filenames(input, &Some(work_dir), - &None, sess); - let exe = work_dir.push(~"pkg" + util::exe_suffix()); - let root = filesearch::get_rustpkg_sysroot().get().pop().pop(); - - driver::compile_rest(sess, cfg, driver::cu_parse, - Some(outputs), Some(crate)); - run::run_program(exe.to_str(), ~[root.to_str(), cmd, test.to_str()]) + debug!("Building output filenames with script name %s", + driver::source_name(self.input)); + match filesearch::get_rustpkg_sysroot() { + Ok(r) => { + let root = r.pop().pop().pop().pop(); // :-\ + debug!("Root is %s, calling compile_rest", root.to_str()); + util::compile_crate_from_input(self.input, Some(self.build_dir), + sess, Some(crate), os::args()[0]); + let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); + debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); + let status = run::run_program(exe.to_str(), ~[root.to_str(), what]); + if status != 0 { + return (~[], status); + } + else { + debug!("Running program (configs): %s %s %s", + exe.to_str(), root.to_str(), ~"configs"); + let output = run::program_output(exe.to_str(), ~[root.to_str(), ~"configs"]); + // Run the configs() function to get the configs + let mut cfgs = ~[]; + for str::each_word(output.out) |w| { + cfgs.push(w.to_owned()); + } + (cfgs, output.status) + } + } + Err(e) => { + fail!(fmt!("Running package script, couldn't find rustpkg sysroot (%s)", + e)) + } + } } fn hash(&self) -> ~str { - fmt!("%s-%s-%s", self.name, util::hash(self.id + self.vers.to_str()), - self.vers.to_str()) + self.id.hash() } - fn work_dir(&self) -> Path { - util::root().push(~"work").push(self.hash()) - } } struct Ctx { - cfgs: ~[~str], + // I'm not sure what this is for json: bool, - dep_cache: @mut HashMap<~str, bool> + // Cache of hashes of things already installed + // though I'm not sure why the value is a bool + dep_cache: @mut HashMap<~str, bool>, +} + + +/// Returns the output directory to use. +/// Right now is always the default, should +/// support changing it. +fn dest_dir(pkgid: PkgId) -> Path { + default_dest_dir(&pkgid.path).expect( + ~"couldn't make default dir?!") + +} + +/// Returns the default output directory for compilation. +/// Creates that directory if it doesn't exist. +fn default_dest_dir(pkg_dir: &Path) -> Option { + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + // For now: assumes that pkg_dir exists and is relative + // to the CWD. Change this later when we do path searching. + let rslt = pkg_dir.push("build"); + let is_dir = os::path_is_dir(&rslt); + if os::path_exists(&rslt) { + if is_dir { + Some(rslt) + } + else { + util::error(fmt!("%s is not a directory", rslt.to_str())); + None + } + } + else { + // Create it + if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { + Some(rslt) + } + else { + util::error(fmt!("Could not create directory %s", + rslt.to_str())); + None // ??? should probably use conditions + } + } } impl Ctx { + fn run(&self, cmd: ~str, args: ~[~str]) { let root = util::root(); @@ -284,20 +225,61 @@ impl Ctx { if args.len() < 1 { return usage::build(); } + // The package id is presumed to be the first command-line + // argument let pkgid = PkgId::new(args[0]); - let mut src = PkgSrc::new(&Path("."), &pkgid); + // Should allow the build directory to be configured. + // Right now it's always the "build" subdirectory in + // the package directory + let dst_dir = dest_dir(pkgid); + debug!("Destination dir = %s", dst_dir.to_str()); + // Right now, we assume the pkgid path is a valid dir + // relative to the CWD. In the future, we should search + // paths + let cwd = os::getcwd().normalize(); + debug!("Current working directory = %?", cwd); + + // Find crates inside the workspace + let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid); + debug!("Package src = %?", src); src.find_crates(); - src.build(&Path(".")); + + // Is there custom build logic? If so, use it + let pkg_src_dir = cwd.push_rel(&pkgid.path); + debug!("Package source directory = %s", pkg_src_dir.to_str()); + let cfgs = match src.package_script_option(&pkg_src_dir) { + Some(package_script_path) => { + let pscript = PkgScript::parse(package_script_path, + pkgid); + // Limited right now -- we're only running the post_build + // hook and probably fail otherwise + // also post_build should be called pre_build + let (cfgs, hook_result) = pscript.run_custom(~"post_build"); + debug!("Command return code = %?", hook_result); + if hook_result != 0 { + fail!(fmt!("Error running custom build command")) + } + // otherwise, the package script succeeded + cfgs + } + None => { + debug!("No package script, continuing"); + ~[] + } + }; + src.build(&dst_dir, cfgs); } ~"clean" => { self.clean(); } ~"do" => { - if args.len() < 1 { + if args.len() < 2 { return usage::do_cmd(); } - self.do_cmd(args[0]); + if !self.do_cmd(args[0], args[1]) { + fail!(~"a command failed!"); + } } ~"info" => { self.info(); @@ -342,7 +324,7 @@ impl Ctx { } } - fn do_cmd(&self, cmd: ~str) -> bool { + fn do_cmd(&self, cmd: ~str, pkgname: ~str) -> bool { match cmd { ~"build" | ~"test" => { util::error(~"that command cannot be manually called"); @@ -353,230 +335,87 @@ impl Ctx { } let cwd = &os::getcwd(); - let script = match PackageScript::parse(cwd) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let status = script.run(cmd, false); - - if status == 42 { - util::error(~"no fns are listening for that cmd"); - - return false; - } - - status == 0 - } - - fn build(&self, dir: &Path, verbose: bool, opt: bool, - test: bool) -> Option { - let cwd = &os::getcwd(); - let script = match PackageScript::parse(dir) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return None; - } - }; - let work_dir = script.work_dir(); - let mut success = true; - - util::need_dir(&work_dir); - - if script.deps.len() >= 1 { - util::note(~"installing dependencies"); - - for script.deps.each |&dep| { - let (url, target) = dep; - - success = self.install(Some(url), target, true); - - if !success { break; } - } - - - if !success { - util::error( - fmt!("building %s v%s failed: a dep wasn't installed", - script.name, script.vers.to_str())); + let pkgid = PkgId::new(pkgname); + // Always use the "build" subdirectory of the package dir, + // but we should allow this to be configured + let dst_dir = dest_dir(pkgid); + + let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid); + + match src.package_script_option(cwd) { + Some(script_path) => { + let script = PkgScript::parse(script_path, pkgid); + let (_, status) = script.run_custom(cmd); // Ignore cfgs? + if status == 42 { // ??? + util::error(~"no fns are listening for that cmd"); + + return false; + } - return None; + status == 0 } - - util::note(~"installed dependencies"); - } - - // Build imperative crates - os::change_dir(dir); - - if script.custom { - let status = script.run(~"build", test); - - if status != 0 && status != 42 { - util::error( - fmt!("building %s v%s failed: custom logic failed (%d)", - script.name, script.vers.to_str(), status)); - - return None; + None => { + util::error(fmt!("invoked `do`, but there is no package script in %s", cwd.to_str())); + false } } + } - os::change_dir(cwd); - - for script.crates.each |&crate| { - let crate = &dir.push_rel(&Path(crate)).normalize(); - - util::note(fmt!("compiling %s", crate.to_str())); - - success = self.compile(crate, &work_dir, ~[], - ~[], opt, test); - - if !success { break; } - } - - if !success { - util::error( - fmt!("building %s v%s failed: a crate failed to compile", - script.name, script.vers.to_str())); - - return None; - } - - if verbose { - util::note(fmt!("built %s v%s", script.name, - script.vers.to_str())); - } - - Some(script) + fn build(&self, _dir: &Path, _verbose: bool, _opt: bool, + _test: bool) -> Option { + // either not needed anymore, + // or needed only when we don't have a package script. Not sure which one. + fail!(); } - fn compile(&self, crate: &Path, dir: &Path, flags: ~[~str], - cfgs: ~[~str], opt: bool, test: bool) -> bool { - util::compile_crate(None, crate, dir, flags, cfgs, opt, test) + fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str], + _cfgs: ~[~str], _opt: bool, _test: bool) -> bool { + // What's the difference between build and compile? + fail!(~"compile not yet implemented"); } fn clean(&self) -> bool { - let script = match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let dir = script.work_dir(); - - util::note(fmt!("cleaning %s v%s (%s)", script.name, - script.vers.to_str(), script.id)); - - if os::path_exists(&dir) { - util::remove_dir_r(&dir); - util::note(fmt!("removed %s", dir.to_str())); - } - - util::note(fmt!("cleaned %s v%s", script.name, - script.vers.to_str())); - - true + // stub + fail!(); } fn info(&self) { - if self.json { - match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => { - let mut map = ~HashMap::new(); - - map.insert(~"id", json::String(script.id)); - map.insert(~"name", json::String(script.name)); - map.insert(~"vers", json::String(script.vers.to_str())); - map.insert(~"deps", json::List(do script.deps.map |&dep| { - let (url, target) = dep; - let mut inner = ~HashMap::new(); - - inner.insert(~"url", json::String(url)); - - if !target.is_none() { - inner.insert(~"target", - json::String(target.get())); - } - - json::Object(inner) - })); - - io::println(json::to_pretty_str(&json::Object(map))); - } - result::Err(_) => io::println(~"{}") - } - } else { - let script = match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return; - } - }; - - util::note(fmt!("id: %s", script.id)); - util::note(fmt!("name: %s", script.name)); - util::note(fmt!("vers: %s", script.vers.to_str())); - util::note(fmt!("deps: %s", - if script.deps.len() > 0 { - ~"" - } else { - ~"none" - })); - - for script.deps.each |&dep| { - let (url, target) = dep; - - util::note(fmt!(" <%s> (%s)", url, match target { - Some(target) => target, - None => ~"" - })); - } - } + // stub + fail!(); } fn install(&self, url: Option<~str>, target: Option<~str>, cache: bool) -> bool { - let mut success; - let mut dir; - - if url.is_none() { - util::note(~"installing from the cwd"); - - dir = os::getcwd(); - } else { - let url = url.get(); - let hash = util::hash(if !target.is_none() { url + target.get() } - else { url }); - - if self.dep_cache.contains_key(&hash) { - util::warn(~"already installed dep this run"); - - return true; + let dir = match url { + None => { + util::note(~"installing from the cwd"); + os::getcwd() } + Some(url) => { + let hash = util::hash(if !target.is_none() { + url + target.get() + } + else { url }); - self.dep_cache.insert(hash, true); + if self.dep_cache.contains_key(&hash) { + util::warn(~"already installed dep this run"); + return true; + } - dir = util::root().push(~"tmp").push(hash); + self.dep_cache.insert(hash, true); - if cache && os::path_exists(&dir) { - return true; - } + let dir = util::root().push(~"tmp").push(hash); - success = self.fetch(&dir, url, target); + if cache && os::path_exists(&dir) { + return true; + } - if !success { - return false; + if !self.fetch(&dir, url, target) { + return false; + } + dir } - } + }; let script = match self.build(&dir, false, true, false) { Some(script) => script, @@ -584,7 +423,7 @@ impl Ctx { return false; } }; - let work_dir = script.work_dir(); + let work_dir = script.build_dir; let from_bin_dir = work_dir.push(~"bin"); let from_lib_dir = work_dir.push(~"lib"); let to_bin_dir = util::root().push(~"bin"); @@ -606,15 +445,13 @@ impl Ctx { libs.push(to.to_str()); } - let package = Package { + let package = Pkg { id: script.id, - vers: script.vers, bins: bins, libs: libs }; - util::note(fmt!("installed %s v%s", script.name, - script.vers.to_str())); + util::note(fmt!("installed %s", script.id.to_str())); util::add_pkg(&package); true @@ -719,17 +556,9 @@ impl Ctx { return false; } }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); + let name = package.id.path.to_str(); // ??? - return false; - } - }; - - util::note(fmt!("preferring %s v%s (%s)", name, package.vers.to_str(), - package.id)); + util::note(fmt!("preferring %s v%s", name, package.id.version.to_str())); let bin_dir = util::root().push(~"bin"); @@ -746,7 +575,7 @@ impl Ctx { util::note(fmt!("linked %s", out.to_str())); } - util::note(fmt!("preferred %s v%s", name, package.vers.to_str())); + util::note(fmt!("preferred %s v%s", name, package.id.version.to_str())); true } @@ -758,126 +587,24 @@ impl Ctx { return false; } }; - let work_dir = script.work_dir(); - let test_dir = work_dir.push(~"test"); - - for os::walk_dir(&test_dir) |test| { - util::note(fmt!("running %s", test.to_str())); - - let status = run::run_program(test.to_str(), ~[]); - - if status != 0 { - os::set_exit_status(status); - } - } - - // Run custom test listener - if script.custom { - let status = script.run(~"test", false); - - if status != 0 && status != 42 { - util::error( - fmt!("testing %s v%s failed: custom logic failed (%d)", - script.name, script.vers.to_str(), status)); - os::set_exit_status(status); - } - } - - util::note(fmt!("tested %s v%s", script.name, script.vers.to_str())); - - true + // To do + util::note(fmt!("Would test %s, but this is a dry run", + script.id.to_str())); + false } - fn uninstall(&self, id: ~str, vers: Option<~str>) -> bool { - let package = match util::get_pkg(id, vers) { - result::Ok(package) => package, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); - - return false; - } - }; - - util::note(fmt!("uninstalling %s v%s (%s)", name, - package.vers.to_str(), package.id)); - - for vec::append(package.bins, package.libs).each |&file| { - let path = Path(file); - - if os::path_exists(&path) { - if os::remove_file(&path) { - util::note(fmt!("removed %s", path.to_str())); - } else { - util::error(fmt!("could not remove %s", path.to_str())); - } - } - } - - util::note(fmt!("uninstalled %s v%s", name, package.vers.to_str())); - util::remove_pkg(&package); - - true + fn uninstall(&self, _id: ~str, _vers: Option<~str>) -> bool { + fail!(~"uninstall not yet implemented"); } - fn unprefer(&self, id: ~str, vers: Option<~str>) -> bool { - let package = match util::get_pkg(id, vers) { - result::Ok(package) => package, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); - - return false; - } - }; - - util::note(fmt!("unpreferring %s v%s (%s)", name, - package.vers.to_str(), package.id)); - - let bin_dir = util::root().push(~"bin"); - - for package.bins.each |&bin| { - let path = Path(bin); - let mut name = None; - for str::each_split_char(path.file_path().to_str(), '-') |s| { - name = Some(s.to_owned()); - break; - } - let out = bin_dir.push(name.unwrap()); - - if os::path_exists(&out) { - if os::remove_file(&out) { - util::note(fmt!("unlinked %s", out.to_str())); - } else { - util::error(fmt!("could not unlink %s", out.to_str())); - } - } - } - - util::note(fmt!("unpreferred %s v%s", name, package.vers.to_str())); - - true + fn unprefer(&self, _id: ~str, _vers: Option<~str>) -> bool { + fail!(~"unprefer not yet implemented"); } } pub fn main() { - io::println("WARNING: The Rust package manager is experimental and may"); - io::println("be unstable."); + io::println("WARNING: The Rust package manager is experimental and may be unstable"); let args = os::args(); let opts = ~[getopts::optflag(~"h"), getopts::optflag(~"help"), @@ -895,8 +622,6 @@ pub fn main() { getopts::opt_present(matches, ~"help"); let json = getopts::opt_present(matches, ~"j") || getopts::opt_present(matches, ~"json"); - let cfgs = vec::append(getopts::opt_strs(matches, ~"cfg"), - getopts::opt_strs(matches, ~"c")); let mut args = copy matches.free; args.shift(); @@ -925,7 +650,6 @@ pub fn main() { } Ctx { - cfgs: cfgs, json: json, dep_cache: @mut HashMap::new() }.run(cmd, args); @@ -966,7 +690,7 @@ pub fn run(listeners: ~[Listener]) { pub impl Crate { - static fn new(p: &Path) -> Crate { + fn new(p: &Path) -> Crate { Crate { file: copy *p, flags: ~[], @@ -1022,68 +746,15 @@ pub fn src_dir() -> Path { os::getcwd() } -/// Build a set of crates, should be called once -pub fn build(crates: ~[Crate]) -> bool { - let args = os::args(); - let dir = src_dir(); - let work_dir = work_dir(); - let mut success = true; - let sysroot = Path(args[1]); - let test = args[3] == ~"true"; - - for crates.each |&crate| { - let path = &dir.push_rel(&crate.file).normalize(); - - util::note(fmt!("compiling %s", path.to_str())); - - success = util::compile_crate(Some(sysroot), path, &work_dir, - crate.flags, crate.cfgs, - false, test); - - if !success { break; } - } - - if !success { - os::set_exit_status(101); - } - - success -} - - -// Path-fragment identifier of a package such as -// 'github.com/graydon/test'; must be a relative -// path with >=1 component. -struct PkgId { - path: Path -} - condition! { - bad_pkg_id: (::core::path::Path, ~str) -> ::PkgId; + bad_pkg_id: (super::Path, ~str) -> ::util::PkgId; } -impl PkgId { - static fn new(s: &str) -> PkgId { - use bad_pkg_id::cond; - - let p = Path(s); - if p.is_absolute { - return cond.raise((p, ~"absolute pkgid")); - } - if p.components.len() < 1 { - return cond.raise((p, ~"0-length pkgid")); - } - PkgId { - path: p - } - } -} - - // An enumeration of the unpacked source of a package workspace. // This contains a list of files found in the source workspace. pub struct PkgSrc { - root: Path, + root: Path, // root of where the package source code lives + dst_dir: Path, // directory where we will put the compiled output id: PkgId, libs: ~[Crate], mains: ~[Crate], @@ -1092,7 +763,7 @@ pub struct PkgSrc { } condition! { - bad_path: (::core::path::Path, ~str) -> ::core::path::Path; + bad_path: (super::Path, ~str) -> super::Path; } condition! { @@ -1102,9 +773,11 @@ condition! { impl PkgSrc { - static fn new(fs_root: &Path, id: &PkgId) -> PkgSrc { + fn new(src_dir: &Path, dst_dir: &Path, + id: &PkgId) -> PkgSrc { PkgSrc { - root: copy *fs_root, + root: copy *src_dir, + dst_dir: copy *dst_dir, id: copy *id, libs: ~[], mains: ~[], @@ -1117,14 +790,20 @@ impl PkgSrc { fn check_dir(&self) -> Path { use bad_path::cond; + debug!("Pushing onto root: %s | %s", self.id.path.to_str(), + self.root.to_str()); + let dir = self.root.push_rel(&self.id.path).normalize(); - if ! os::path_exists(&dir) { + debug!("Checking dir: %s", dir.to_str()); + + if !os::path_exists(&dir) { return cond.raise((dir, ~"missing package dir")); } - - if ! os::path_is_dir(&dir) { - return cond.raise((dir, ~"missing package dir")); + + if !os::path_is_dir(&dir) { + return cond.raise((dir, ~"supplied path for package dir is a \ + non-directory")); } dir @@ -1136,9 +815,40 @@ impl PkgSrc { dir.push("pkg.rs").exists() } + // If a file named "pkg.rs" in the current directory exists, + // return the path for it. Otherwise, None + fn package_script_option(&self, cwd: &Path) -> Option { + let maybe_path = cwd.push("pkg.rs"); + if os::path_exists(&maybe_path) { + Some(maybe_path) + } + else { + None + } + } + + /// True if the given path's stem is self's pkg ID's stem + /// or if the pkg ID's stem is and the given path's + /// stem is foo + fn stem_matches(&self, p: &Path) -> bool { + let self_id = self.id.path.filestem(); + if self_id == p.filestem() { + return true; + } + else { + for self_id.each |pth| { + if pth.starts_with("rust-") + && match p.filestem() { + Some(s) => str::eq_slice(s, pth.slice(5, pth.len())), + None => false + } { return true; } + } + } + false + } - static fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) { - assert p.components.len() > prefix; + fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) { + assert!(p.components.len() > prefix); let mut sub = Path(""); for vec::slice(p.components, prefix, p.components.len()).each |c| { @@ -1150,9 +860,15 @@ impl PkgSrc { fn find_crates(&mut self) { use PkgSrc::push_crate; - assert ! self.has_pkg_file(); + let dir = self.check_dir(); let prefix = dir.components.len(); + // This is ugly, but can go away once we get rid + // of .rc files + let mut saw_rs = false; + let mut saw_rc = false; + debug!("Matching against %?", + self.id.path.filestem()); for os::walk_dir(&dir) |pth| { match pth.filename() { Some(~"lib.rs") => push_crate(&mut self.libs, @@ -1163,7 +879,32 @@ impl PkgSrc { prefix, pth), Some(~"bench.rs") => push_crate(&mut self.benchs, prefix, pth), - _ => () + _ => { + // If the file stem is the same as the + // package ID, with an .rs or .rc extension, + // consider it to be a crate + let ext = pth.filetype(); + let matches = |p: &Path| { + self.stem_matches(p) && (ext == Some(~".rc") + || ext == Some(~".rs")) + }; + debug!("Checking %? which %s and ext = %? %? %?", pth.filestem(), + if matches(pth) { "matches" } else { "does not match" }, + ext, saw_rs, saw_rc); + if matches(pth) && + // Avoid pushing foo.rc *and* foo.rs + !((ext == Some(~".rc") && saw_rs) || + (ext == Some(~".rs") && saw_rc)) { + push_crate(&mut self.libs, // ???? + prefix, pth); + if ext == Some(~".rc") { + saw_rc = true; + } + else if ext == Some(~".rs") { + saw_rs = true; + } + } + } } } debug!("found %u libs, %u mains, %u tests, %u benchs", @@ -1173,31 +914,40 @@ impl PkgSrc { self.benchs.len()) } - - static fn build_crates(dst_dir: &Path, + fn build_crates(dst_dir: &Path, src_dir: &Path, crates: &[Crate], + cfgs: ~[~str], test: bool) { for crates.each |&crate| { let path = &src_dir.push_rel(&crate.file).normalize(); - util::note(fmt!("compiling %s", path.to_str())); - if ! util::compile_crate(None, path, + util::note(fmt!("build_crates: compiling %s", path.to_str())); + util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str())); + + let result = util::compile_crate(None, path, dst_dir, crate.flags, - crate.cfgs, - false, test) { + crate.cfgs + cfgs, + false, test); + if !result { build_err::cond.raise(fmt!("build failure on %s", path.to_str())); } + debug!("Result of compiling %s was %?", + path.to_str(), result); } } - fn build(&self, dst_dir: &Path) { + fn build(&self, dst_dir: &Path, cfgs: ~[~str]) { let dir = self.check_dir(); - PkgSrc::build_crates(dst_dir, &dir, self.libs, false); - PkgSrc::build_crates(dst_dir, &dir, self.mains, false); - PkgSrc::build_crates(dst_dir, &dir, self.tests, true); - PkgSrc::build_crates(dst_dir, &dir, self.benchs, true); + debug!("Building libs"); + PkgSrc::build_crates(dst_dir, &dir, self.libs, cfgs, false); + debug!("Building mains"); + PkgSrc::build_crates(dst_dir, &dir, self.mains, cfgs, false); + debug!("Building tests"); + PkgSrc::build_crates(dst_dir, &dir, self.tests, cfgs, true); + debug!("Building benches"); + PkgSrc::build_crates(dst_dir, &dir, self.benchs, cfgs, true); } -} \ No newline at end of file +} diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 776ca39826834..819823e87447c 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -9,26 +9,125 @@ // except according to those terms. use core::*; +use core::cmp::Ord; use core::hash::Streaming; -use core::hashmap::HashMap; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; use std::semver; -use std::{json, term, sort, getopts}; +use std::{json, term, getopts}; use syntax::ast_util::*; -use syntax::codemap::{dummy_sp, spanned}; +use syntax::codemap::{dummy_sp}; use syntax::ext::base::{mk_ctxt, ext_ctxt}; use syntax::ext::build; use syntax::{ast, attr, codemap, diagnostic, fold}; +use rustc::back::link::output_type_exe; -pub struct Package { - id: ~str, - vers: semver::Version, +pub type ExitCode = int; // For now + +/// A version is either an exact revision, +/// or a semantic version +pub enum Version { + ExactRevision(float), + SemVersion(semver::Version) +} + +impl Ord for Version { + fn lt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 < v2, + _ => false // incomparable, really + } + } + fn le(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 <= v2, + _ => false // incomparable, really + } + } + fn ge(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 > v2, + _ => false // incomparable, really + } + } + fn gt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 >= v2, + _ => false // incomparable, really + } + } + +} + +impl ToStr for Version { + fn to_str(&self) -> ~str { + match *self { + ExactRevision(n) => n.to_str(), + SemVersion(v) => v.to_str() + } + } +} + +/// Placeholder +fn default_version() -> Version { ExactRevision(0.1) } + +// Path-fragment identifier of a package such as +// 'github.com/graydon/test'; path must be a relative +// path with >=1 component. +pub struct PkgId { + path: Path, + version: Version +} + +pub impl PkgId { + fn new(s: &str) -> PkgId { + use bad_pkg_id::cond; + + let p = Path(s); + if p.is_absolute { + return cond.raise((p, ~"absolute pkgid")); + } + if p.components.len() < 1 { + return cond.raise((p, ~"0-length pkgid")); + } + PkgId { + path: p, + version: default_version() + } + } + + fn hash(&self) -> ~str { + fmt!("%s-%s-%s", self.path.to_str(), + hash(self.path.to_str() + self.version.to_str()), + self.version.to_str()) + } + +} + +impl ToStr for PkgId { + fn to_str(&self) -> ~str { + // should probably use the filestem and not the whole path + fmt!("%s-v%s", self.path.to_str(), self.version.to_str()) + } +} + +pub struct Pkg { + id: PkgId, bins: ~[~str], libs: ~[~str], } +impl ToStr for Pkg { + fn to_str(&self) -> ~str { + self.id.to_str() + } +} + pub fn root() -> Path { match filesearch::get_rustpkg_root() { result::Ok(path) => path, @@ -309,294 +408,22 @@ pub fn wait_for_lock(path: &Path) { } } -fn _add_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] { - for packages.each |&package| { - match &package { - &json::Object(ref map) => { - let mut has_id = false; - - match map.get(&~"id") { - &json::String(ref str) => { - if pkg.id == *str { - has_id = true; - } - } - _ => {} - } - - match map.get(&~"vers") { - &json::String(ref str) => { - if has_id && pkg.vers.to_str() == *str { - return copy packages; - } - } - _ => {} - } - } - _ => {} - } - } - - let mut map = ~HashMap::new(); - - map.insert(~"id", json::String(pkg.id)); - map.insert(~"vers", json::String(pkg.vers.to_str())); - map.insert(~"bins", json::List(do pkg.bins.map |&bin| { - json::String(bin) - })); - map.insert(~"libs", json::List(do pkg.libs.map |&lib| { - json::String(lib) - })); - - vec::append(packages, ~[json::Object(map)]) -} - -fn _rm_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] { - do packages.filter_mapped |&package| { - match &package { - &json::Object(ref map) => { - let mut has_id = false; - - match map.get(&~"id") { - &json::String(str) => { - if pkg.id == str { - has_id = true; - } - } - _ => {} - } - - match map.get(&~"vers") { - &json::String(ref str) => { - if has_id && pkg.vers.to_str() == *str { - None - } else { - Some(copy package) - } - } - _ => { Some(copy package) } - } - } - _ => { Some(copy package) } - } - } -} - pub fn load_pkgs() -> result::Result<~[json::Json], ~str> { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - - wait_for_lock(&db_lock); - touch(&db_lock); - - let packages = if os::path_exists(&db) { - match io::read_whole_file_str(&db) { - result::Ok(str) => { - match json::from_str(str) { - result::Ok(json) => { - match json { - json::List(list) => list, - _ => { - os::remove_file(&db_lock); - - return result::Err( - ~"package db's json is not a list"); - } - } - } - result::Err(err) => { - os::remove_file(&db_lock); - - return result::Err( - fmt!("failed to parse package db: %s", - err.to_str())); - } - } - } - result::Err(err) => { - os::remove_file(&db_lock); - - return result::Err(fmt!("failed to read package db: %s", - err)); - } - } - } else { ~[] }; - - os::remove_file(&db_lock); - - result::Ok(packages) -} - -pub fn get_pkg(id: ~str, - vers: Option<~str>) -> result::Result { - let name = match parse_name(id) { - result::Ok(name) => name, - result::Err(err) => return result::Err(err) - }; - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => return result::Err(err) - }; - let mut sel = None; - let mut possibs = ~[]; - let mut err = None; - - for packages.each |&package| { - match package { - json::Object(map) => { - let pid = match map.get(&~"id") { - &json::String(str) => str, - _ => loop - }; - let pname = match parse_name(pid) { - result::Ok(pname) => pname, - result::Err(perr) => { - err = Some(perr); - - break; - } - }; - let pvers = match map.get(&~"vers") { - &json::String(str) => str, - _ => loop - }; - if pid == id || pname == name { - let bins = match map.get(&~"bins") { - &json::List(ref list) => { - do list.map |&bin| { - match bin { - json::String(str) => str, - _ => ~"" - } - } - } - _ => ~[] - }; - let libs = match map.get(&~"libs") { - &json::List(ref list) => { - do list.map |&lib| { - match lib { - json::String(str) => str, - _ => ~"" - } - } - } - _ => ~[] - }; - let package = Package { - id: pid, - vers: match parse_vers(pvers) { - result::Ok(vers) => vers, - result::Err(verr) => { - err = Some(verr); - - break; - } - }, - bins: bins, - libs: libs - }; - - if !vers.is_none() && vers.get() == pvers { - sel = Some(package); - } - else { - possibs.push(package); - } - } - } - _ => {} - } - } - - if !err.is_none() { - return result::Err(err.get()); - } - if !sel.is_none() { - return result::Ok(sel.get()); - } - if !vers.is_none() || possibs.len() < 1 { - return result::Err(~"package not found"); - } - - let possibs = sort::merge_sort(possibs, |v1, v2| { - v1.vers <= v2.vers - }); - - result::Ok(copy *possibs.last()) + fail!(~"load_pkg not implemented"); } -pub fn add_pkg(pkg: &Package) -> bool { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => { - error(err); - - return false; - } - }; - - wait_for_lock(&db_lock); - touch(&db_lock); - os::remove_file(&db); - - match io::mk_file_writer(&db, ~[io::Create]) { - result::Ok(writer) => { - writer.write_line(json::to_pretty_str(&json::List( - _add_pkg(packages, pkg)))); - } - result::Err(err) => { - error(fmt!("failed to dump package db: %s", err)); - os::remove_file(&db_lock); - - return false; - } - } - - os::remove_file(&db_lock); - - true +pub fn get_pkg(_id: ~str, + _vers: Option<~str>) -> result::Result { + fail!(~"get_pkg not implemented"); } -pub fn remove_pkg(pkg: &Package) -> bool { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => { - error(err); - - return false; - } - }; - - wait_for_lock(&db_lock); - touch(&db_lock); - os::remove_file(&db); - - match io::mk_file_writer(&db, ~[io::Create]) { - result::Ok(writer) => { - writer.write_line(json::to_pretty_str(&json::List( - _rm_pkg(packages, pkg)))); - } - result::Err(err) => { - error(fmt!("failed to dump package db: %s", err)); - os::remove_file(&db_lock); - - return false; - } - } - - os::remove_file(&db_lock); - - true +pub fn add_pkg(pkg: &Pkg) -> bool { + note(fmt!("Would be adding package, but add_pkg is not yet implemented %s", + pkg.to_str())); + false } +// FIXME (#4432): Use workcache to only compile when needed pub fn compile_input(sysroot: Option, in_file: &Path, out_dir: &Path, @@ -605,22 +432,41 @@ pub fn compile_input(sysroot: Option, opt: bool, test: bool) -> bool { - assert in_file.components.len() > 1; + assert!(in_file.components.len() > 1); let input = driver::file_input(copy *in_file); - let short_name = in_file.pop().filename().get(); + debug!("compile_input: %s", in_file.to_str()); + // tjc: by default, use the package ID name as the link name + // not sure if we should support anything else + let short_name = in_file.filestem().expect("Can't compile a directory!"); + debug!("short_name = %s", short_name.to_str()); + +// Right now we're always assuming that we're building a library. +// What we should do is parse the crate and infer whether it's a library +// from the absence or presence of a main fn let out_file = out_dir.push(os::dll_filename(short_name)); + let building_library = true; debug!("compiling %s into %s", in_file.to_str(), out_file.to_str()); let binary = os::args()[0]; - let matches = getopts(flags, driver::optgroups()).get(); + + debug!("flags: %s", str::connect(flags, ~" ")); + debug!("cfgs: %s", str::connect(cfgs, ~" ")); +// Again, we assume we're building a library + let matches = getopts(~[~"-Z", ~"time-passes"] + + if building_library { ~[~"--lib"] } else { ~[] } + + flags + + cfgs.flat_map(|&c| { ~[~"--cfg", c] }), + driver::optgroups()).get(); let options = @session::options { - crate_type: session::unknown_crate, + crate_type: if building_library { session::lib_crate } + else { session::bin_crate }, optimize: if opt { session::Aggressive } else { session::No }, test: test, maybe_sysroot: sysroot, + addl_lib_search_paths: ~[copy *out_dir], .. *driver::build_session_options(binary, &matches, diagnostic::emit) }; let mut crate_cfg = options.cfg; @@ -631,94 +477,42 @@ pub fn compile_input(sysroot: Option, let options = @session::options { cfg: vec::append(options.cfg, crate_cfg), + // output_type should be conditional + output_type: output_type_exe, // Use this to get a library? That's weird .. *options }; let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, binary, input); - let mut outputs = driver::build_output_filenames(input, &None, &None, - sess); - let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, - Some(outputs)); - - let mut name = None; - let mut vers = None; - let mut crate_type = None; - - fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>) { - let mut name = None; - let mut vers = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned {node: ast::lit_str(s), - span: _}) => { - match *v { - ~"name" => name = Some(*s), - ~"vers" => vers = Some(*s), - _ => { } - } - } - _ => {} - } - } - - (name, vers) - } - - for crate.node.attrs.each |a| { - match a.node.value.node { - ast::meta_name_value(v, spanned {node: ast::lit_str(s), - span: _}) => { - match *v { - ~"crate_type" => crate_type = Some(*s), - _ => {} - } - } - ast::meta_list(v, mis) => { - match *v { - ~"link" => { - let (n, v) = load_link_attr(mis); - - name = n; - vers = v; - } - _ => {} - } - } - _ => {} - } - } - let is_bin = match crate_type { - Some(crate_type) => { - match crate_type { - ~"bin" => true, - ~"lib" => false, - _ => { - warn(~"unknown crate_type, falling back to lib"); + debug!("calling compile_crate_from_input, out_dir = %s, + building_library = %?", out_dir.to_str(), sess.building_library); + compile_crate_from_input(input, Some(*out_dir), sess, None, binary); + true +} - false - } - } +// Should use workcache to avoid recompiling when not necessary +// Should also rename this to something better +// If crate_opt is present, then finish compilation. If it's None, then +// call compile_upto and return the crate +pub fn compile_crate_from_input(input: driver::input, build_dir_opt: Option, + sess: session::Session, crate_opt: Option<@ast::crate>, + binary: ~str) -> @ast::crate { + debug!("Calling build_output_filenames with %?", build_dir_opt); + let outputs = driver::build_output_filenames(input, &build_dir_opt, &None, sess); + debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); + let cfg = driver::build_configuration(sess, binary, input); + match crate_opt { + Some(c) => { + debug!("Calling compile_rest, outputs = %?", outputs); + driver::compile_rest(sess, cfg, driver::cu_everything, Some(outputs), Some(c)); + c } None => { - warn(~"missing crate_type attr, assuming lib"); - - false + debug!("Calling compile_upto, outputs = %?", outputs); + let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, + Some(outputs)); + crate } - }; - - outputs = driver::build_output_filenames(input, - &Some(copy *out_dir), - &Some(out_file), - sess); - - driver::compile_rest(sess, cfg, driver::cu_everything, - Some(outputs), - Some(crate)); - - true + } } #[cfg(windows)] @@ -731,13 +525,20 @@ pub fn exe_suffix() -> ~str { ~".exe" } pub fn exe_suffix() -> ~str { ~"" } +// Called by build_crates // FIXME (#4432): Use workcache to only compile when needed pub fn compile_crate(sysroot: Option, crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { + debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str()); + debug!("compile_crate: flags =..."); + for flags.each |&fl| { + debug!("+++ %s", fl); + } compile_input(sysroot, crate, dir, flags, cfgs, opt, test) } + #[cfg(windows)] pub fn link_exe(_src: &Path, _dest: &Path) -> bool { /* FIXME (#1768): Investigate how to do this on win32 From 1faa3596b021f391d2b79e4d5287082b519418b2 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 11 Apr 2013 23:05:06 -0400 Subject: [PATCH 153/403] rewrite the ffi tutorial with snappy as an example The example with OpenSSL is incorrect, because OpenSSL is using a static variable for the return value and isn't thread-safe. The gettimeofday example isn't great because it's not very portable. --- doc/tutorial-ffi.md | 334 ++++++++++++++++++-------------------------- 1 file changed, 139 insertions(+), 195 deletions(-) diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index 4a93eecac0da5..fc62fafa70090 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -2,255 +2,199 @@ # Introduction -Because Rust is a systems programming language, one of its goals is to -interoperate well with C code. +This tutorial will use the [snappy](https://code.google.com/p/snappy/) +compression/decompression library as an introduction to writing bindings for +foreign code. Rust is currently unable to call directly into a C++ library, but +snappy includes a C interface (documented in +[`snappy-c.h`](https://code.google.com/p/snappy/source/browse/trunk/snappy-c.h)). -We'll start with an example, which is a bit bigger than usual. We'll -go over it one piece at a time. This is a program that uses OpenSSL's -`SHA1` function to compute the hash of its first command-line -argument, which it then converts to a hexadecimal string and prints to -standard output. If you have the OpenSSL libraries installed, it -should compile and run without any extra effort. +The following is a minimal example of calling a foreign function which will compile if snappy is +installed: ~~~~ {.xfail-test} -extern mod std; -use core::libc::c_uint; +use core::libc::size_t; -extern mod crypto { - fn SHA1(src: *u8, sz: c_uint, out: *u8) -> *u8; -} - -fn as_hex(data: ~[u8]) -> ~str { - let mut acc = ~""; - for data.each |&byte| { acc += fmt!("%02x", byte as uint); } - return acc; -} - -fn sha1(data: ~str) -> ~str { - unsafe { - let bytes = str::to_bytes(data); - let hash = crypto::SHA1(vec::raw::to_ptr(bytes), - vec::len(bytes) as c_uint, - ptr::null()); - return as_hex(vec::from_buf(hash, 20)); - } +#[link_args = "-lsnappy"] +extern { + fn snappy_max_compressed_length(source_length: size_t) -> size_t; } fn main() { - io::println(sha1(core::os::args()[1])); + let x = unsafe { snappy_max_compressed_length(100) }; + println(fmt!("max compressed length of a 100 byte buffer: %?", x)); } ~~~~ -# Foreign modules - -Before we can call the `SHA1` function defined in the OpenSSL library, we have -to declare it. That is what this part of the program does: +The `extern` block is a list of function signatures in a foreign library, in this case with the +platform's C ABI. The `#[link_args]` attribute is used to instruct the linker to link against the +snappy library so the symbols are resolved. -~~~~ {.xfail-test} -extern mod crypto { - fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8; } -~~~~ +Foreign functions are assumed to be unsafe so calls to them need to be wrapped with `unsafe {}` as a +promise to the compiler that everything contained within truly is safe. C libraries often expose +interfaces that aren't thread-safe, and almost any function that takes a pointer argument isn't +valid for all possible inputs since the pointer could be dangling, and raw pointers fall outside of +Rust's safe memory model. -An `extern` module declaration containing function signatures introduces the -functions listed as _foreign functions_. Foreign functions differ from regular -Rust functions in that they are implemented in some other language (usually C) -and called through Rust's foreign function interface (FFI). An extern module -like this is called a foreign module, and implicitly tells the compiler to -link with a library that contains the listed foreign functions, and has the -same name as the module. +When declaring the argument types to a foreign function, the Rust compiler will not check if the +declaration is correct, so specifying it correctly is part of keeping the binding correct at +runtime. -In this case, the Rust compiler changes the name `crypto` to a shared library -name in a platform-specific way (`libcrypto.so` on Linux, for example), -searches for the shared library with that name, and links the library into the -program. If you want the module to have a different name from the actual -library, you can use the `"link_name"` attribute, like: +The `extern` block can be extended to cover the entire snappy API: ~~~~ {.xfail-test} -#[link_name = "crypto"] -extern mod something { - fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8; +use core::libc::{c_int, size_t}; + +#[link_args = "-lsnappy"] +extern { + fn snappy_compress(input: *u8, + input_length: size_t, + compressed: *mut u8, + compressed_length: *mut size_t) -> c_int; + fn snappy_uncompress(compressed: *u8, + compressed_length: size_t, + uncompressed: *mut u8, + uncompressed_length: *mut size_t) -> c_int; + fn snappy_max_compressed_length(source_length: size_t) -> size_t; + fn snappy_uncompressed_length(compressed: *u8, + compressed_length: size_t, + result: *mut size_t) -> c_int; + fn snappy_validate_compressed_buffer(compressed: *u8, + compressed_length: size_t) -> c_int; } ~~~~ -# Foreign calling conventions +# Creating a safe interface -Most foreign code is C code, which usually uses the `cdecl` calling -convention, so that is what Rust uses by default when calling foreign -functions. Some foreign functions, most notably the Windows API, use other -calling conventions. Rust provides the `"abi"` attribute as a way to hint to -the compiler which calling convention to use: +The raw C API needs to be wrapped to provide memory safety and make use higher-level concepts like +vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe +internal details. -~~~~ -#[cfg(target_os = "win32")] -#[abi = "stdcall"] -extern mod kernel32 { - fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int; +Wrapping the functions which expect buffers involves using the `vec::raw` module to manipulate Rust +vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The +length is number of elements currently contained, and the capacity is the total size in elements of +the allocated memory. The length is less than or equal to the capacity. + +~~~~ {.xfail-test} +pub fn validate_compressed_buffer(src: &[u8]) -> bool { + unsafe { + snappy_validate_compressed_buffer(vec::raw::to_ptr(src), src.len() as size_t) == 0 + } } ~~~~ -The `"abi"` attribute applies to a foreign module (it cannot be applied -to a single function within a module), and must be either `"cdecl"` -or `"stdcall"`. We may extend the compiler in the future to support other -calling conventions. +The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the +guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function +signature. -# Unsafe pointers +The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be +allocated to hold the output too. -The foreign `SHA1` function takes three arguments, and returns a pointer. +The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum +required capacity to hold the compressed output. The vector can then be passed to the +`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve +the true length after compression for setting the length. ~~~~ {.xfail-test} -# extern mod crypto { -fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8; -# } -~~~~ +pub fn compress(src: &[u8]) -> ~[u8] { + unsafe { + let srclen = src.len() as size_t; + let psrc = vec::raw::to_ptr(src); -When declaring the argument types to a foreign function, the Rust -compiler has no way to check whether your declaration is correct, so -you have to be careful. If you get the number or types of the -arguments wrong, you're likely to cause a segmentation fault. Or, -probably even worse, your code will work on one platform, but break on -another. + let mut dstlen = snappy_max_compressed_length(srclen); + let mut dst = vec::with_capacity(dstlen as uint); + let pdst = vec::raw::to_mut_ptr(dst); -In this case, we declare that `SHA1` takes two `unsigned char*` -arguments and one `unsigned long`. The Rust equivalents are `*u8` -unsafe pointers and an `uint` (which, like `unsigned long`, is a -machine-word-sized type). + snappy_compress(psrc, srclen, pdst, &mut dstlen); + vec::raw::set_len(&mut dst, dstlen as uint); + dst + } +} +~~~~ -The standard library provides various functions to create unsafe pointers, -such as those in `core::cast`. Most of these functions have `unsafe` in their -name. You can dereference an unsafe pointer with the `*` operator, but use -caution: unlike Rust's other pointer types, unsafe pointers are completely -unmanaged, so they might point at invalid memory, or be null pointers. +Decompression is similar, because snappy stores the uncompressed size as part of the compression +format and `snappy_uncompressed_length` will retrieve the exact buffer size required. -# Unsafe blocks +~~~~ {.xfail-test} +pub fn uncompress(src: &[u8]) -> Option<~[u8]> { + unsafe { + let srclen = src.len() as size_t; + let psrc = vec::raw::to_ptr(src); -The `sha1` function is the most obscure part of the program. + let mut dstlen: size_t = 0; + snappy_uncompressed_length(psrc, srclen, &mut dstlen); -~~~~ -# pub mod crypto { -# pub fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8 { out } -# } -# fn as_hex(data: ~[u8]) -> ~str { ~"hi" } -fn sha1(data: ~str) -> ~str { - unsafe { - let bytes = str::to_bytes(data); - let hash = crypto::SHA1(vec::raw::to_ptr(bytes), - vec::len(bytes), ptr::null()); - return as_hex(vec::from_buf(hash, 20)); + let mut dst = vec::with_capacity(dstlen as uint); + let pdst = vec::raw::to_mut_ptr(dst); + + if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 { + vec::raw::set_len(&mut dst, dstlen as uint); + Some(dst) + } else { + None // SNAPPY_INVALID_INPUT + } } } ~~~~ -First, what does the `unsafe` keyword at the top of the function -mean? `unsafe` is a block modifier—it declares the block following it -to be known to be unsafe. +For reference, the examples used here are also available as an [library on +GitHub](https://github.com/thestinger/rust-snappy). -Some operations, like dereferencing unsafe pointers or calling -functions that have been marked unsafe, are only allowed inside unsafe -blocks. With the `unsafe` keyword, you're telling the compiler 'I know -what I'm doing'. The main motivation for such an annotation is that -when you have a memory error (and you will, if you're using unsafe -constructs), you have some idea where to look—it will most likely be -caused by some unsafe code. +# Linking -Unsafe blocks isolate unsafety. Unsafe functions, on the other hand, -advertise it to the world. An unsafe function is written like this: - -~~~~ -unsafe fn kaboom() { ~"I'm harmless!"; } -~~~~ +In addition to the `#[link_args]` attribute for explicitly passing arguments to the linker, an +`extern mod` block will pass `-lmodname` to the linker by default unless it has a `#[nolink]` +attribute applied. -This function can only be called from an `unsafe` block or another -`unsafe` function. - -# Pointer fiddling +# Unsafe blocks -The standard library defines a number of helper functions for dealing -with unsafe data, casting between types, and generally subverting -Rust's safety mechanisms. +Some operations, like dereferencing unsafe pointers or calling functions that have been marked +unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to +the compiler that the unsafety does not leak out of the block. -Let's look at our `sha1` function again. +Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like +this: ~~~~ -# pub mod crypto { -# pub fn SHA1(src: *u8, sz: uint, out: *u8) -> *u8 { out } -# } -# fn as_hex(data: ~[u8]) -> ~str { ~"hi" } -# fn x(data: ~str) -> ~str { -# unsafe { -let bytes = str::to_bytes(data); -let hash = crypto::SHA1(vec::raw::to_ptr(bytes), - vec::len(bytes), ptr::null()); -return as_hex(vec::from_buf(hash, 20)); -# } -# } +unsafe fn kaboom(ptr: *int) -> int { *ptr } ~~~~ -The `str::to_bytes` function is perfectly safe: it converts a string to a -`~[u8]`. The program then feeds this byte array to `vec::raw::to_ptr`, which -returns an unsafe pointer to its contents. - -This pointer will become invalid at the end of the scope in which the vector -it points to (`bytes`) is valid, so you should be very careful how you use -it. In this case, the local variable `bytes` outlives the pointer, so we're -good. - -Passing a null pointer as the third argument to `SHA1` makes it use a -static buffer, and thus save us the effort of allocating memory -ourselves. `ptr::null` is a generic function that, in this case, returns an -unsafe null pointer of type `*u8`. (Rust generics are awesome -like that: they can take the right form depending on the type that they -are expected to return.) - -Finally, `vec::from_buf` builds up a new `~[u8]` from the -unsafe pointer that `SHA1` returned. SHA1 digests are always -twenty bytes long, so we can pass `20` for the length of the new -vector. - -# Passing structures +This function can only be called from an `unsafe` block or another `unsafe` function. -C functions often take pointers to structs as arguments. Since Rust -`struct`s are binary-compatible with C structs, Rust programs can call -such functions directly. +# Foreign calling conventions -This program uses the POSIX function `gettimeofday` to get a -microsecond-resolution timer. +Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when +calling foreign functions. Some foreign functions, most notably the Windows API, use other calling +conventions. Rust provides the `abi` attribute as a way to hint to the compiler which calling +convention to use: ~~~~ -extern mod std; -use core::libc::c_ulonglong; - -struct timeval { - tv_sec: c_ulonglong, - tv_usec: c_ulonglong +#[cfg(target_os = "win32")] +#[abi = "stdcall"] +extern mod kernel32 { + fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int; } +~~~~ -#[nolink] -extern mod lib_c { - fn gettimeofday(tv: *mut timeval, tz: *()) -> i32; -} -fn unix_time_in_microseconds() -> u64 { - unsafe { - let mut x = timeval { - tv_sec: 0 as c_ulonglong, - tv_usec: 0 as c_ulonglong - }; - lib_c::gettimeofday(&mut x, ptr::null()); - return (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64); - } -} +The `abi` attribute applies to a foreign module (it cannot be applied to a single function within a +module), and must be either `"cdecl"` or `"stdcall"`. The compiler may eventually support other +calling conventions. -# fn main() { assert!(fmt!("%?", unix_time_in_microseconds()) != ~""); } -~~~~ +# Interoperability with foreign code -The `#[nolink]` attribute indicates that there's no foreign library to -link in. The standard C library is already linked with Rust programs. +Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C. +A `#[packed]` attribute is available, which will lay out the struct members without padding. +However, there are currently no guarantees about the layout of an `enum`. -In C, a `timeval` is a struct with two 32-bit integer fields. Thus, we -define a `struct` type with the same contents, and declare -`gettimeofday` to take a pointer to such a `struct`. +Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained +object. However, they should not be manually because they are managed by internal allocators. +Borrowed pointers can safely be assumed to be non-nullable pointers directly to the type. However, +breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer using raw +pointers (`*`) if that's needed because the compiler can't make as many assumptions about them. -This program does not use the second argument to `gettimeofday` (the time - zone), so the `extern mod` declaration for it simply declares this argument - to be a pointer to the unit type (written `()`). Since all null pointers have - the same representation regardless of their referent type, this is safe. +Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and +`str` modules for working with C APIs. Strings are terminated with `\0` for interoperability with C, +but it should not be assumed because a slice will not always be nul-terminated. Instead, the +`str::as_c_str` function should be used. +The standard library includes type aliases and function definitions for the C standard library in +the `libc` module, and Rust links against `libc` and `libm` by default. From 3698ea7e54c46cfde377f95782710ee5e19876d3 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 28 Mar 2013 21:50:10 +1100 Subject: [PATCH 154/403] libsyntax: abstract most of the deriving boilerplate into a simpler(r) interface. Pulls out many of the common patterns from the Eq and Clone deriving code (and invents a few of its own), so that deriving instances are very easy to write for a certain class of traits. (Basically, those which don't have parameters and where all methods only take arguments of type `&Self` and return either `Self` or types with no parameters.) --- src/libsyntax/ext/deriving/clone.rs | 7 +- src/libsyntax/ext/deriving/decodable.rs | 3 +- src/libsyntax/ext/deriving/encodable.rs | 5 +- src/libsyntax/ext/deriving/eq.rs | 10 +- src/libsyntax/ext/deriving/generic.rs | 826 +++++++++++++++++++++++ src/libsyntax/ext/deriving/iter_bytes.rs | 5 +- src/libsyntax/ext/deriving/mod.rs | 101 ++- 7 files changed, 915 insertions(+), 42 deletions(-) create mode 100644 src/libsyntax/ext/deriving/generic.rs diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index c8ba6b990e47a..390b72da3314b 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -55,7 +55,8 @@ fn create_derived_clone_impl(cx: @ext_ctxt, cx.ident_of(~"Clone"), ]; let trait_path = build::mk_raw_path_global(span, trait_path); - create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, + opt_vec::Empty, opt_vec::Empty) } // Creates a method from the given expression conforming to the signature of // the `clone` method. @@ -219,7 +220,7 @@ fn expand_deriving_clone_tuple_struct_method(cx: @ext_ctxt, let mut subcalls = ~[]; for uint::range(0, struct_def.fields.len()) |i| { // Create the expression for this field. - let field_ident = cx.ident_of(~"__self" + i.to_str()); + let field_ident = cx.ident_of(~"__self_" + i.to_str()); let field = build::mk_path(cx, span, ~[ field_ident ]); // Call the substructure method. @@ -262,7 +263,7 @@ fn expand_deriving_clone_enum_method(cx: @ext_ctxt, let mut subcalls = ~[]; for uint::range(0, variant_arg_count(cx, span, variant)) |j| { // Create the expression for this field. - let field_ident = cx.ident_of(~"__self" + j.to_str()); + let field_ident = cx.ident_of(~"__self_" + j.to_str()); let field = build::mk_path(cx, span, ~[ field_ident ]); // Call the substructure method. diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 11f492316e281..df3536a3caef7 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -81,7 +81,8 @@ fn create_derived_decodable_impl( generics, methods, trait_path, - generic_ty_params + generic_ty_params, + opt_vec::Empty ) } diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 81bfb03724f30..9776f484818cc 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -81,7 +81,8 @@ fn create_derived_encodable_impl( generics, methods, trait_path, - generic_ty_params + generic_ty_params, + opt_vec::Empty ) } @@ -306,7 +307,7 @@ fn expand_deriving_encodable_enum_method( let variant_arg_len = variant_arg_count(cx, span, variant); for uint::range(0, variant_arg_len) |j| { // Create the expression for this field. - let field_ident = cx.ident_of(~"__self" + j.to_str()); + let field_ident = cx.ident_of(~"__self_" + j.to_str()); let field = build::mk_path(cx, span, ~[ field_ident ]); // Call the substructure method. diff --git a/src/libsyntax/ext/deriving/eq.rs b/src/libsyntax/ext/deriving/eq.rs index c427a206c2e32..0afb667c69ab9 100644 --- a/src/libsyntax/ext/deriving/eq.rs +++ b/src/libsyntax/ext/deriving/eq.rs @@ -131,7 +131,7 @@ fn create_derived_eq_impl(cx: @ext_ctxt, cx.ident_of(~"Eq") ]; let trait_path = build::mk_raw_path_global(span, trait_path); - create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty, []) } fn call_substructure_eq_method(cx: @ext_ctxt, @@ -338,13 +338,13 @@ fn expand_deriving_eq_enum_method(cx: @ext_ctxt, let mut matching_body_expr = None; for uint::range(0, variant_arg_count(cx, span, self_variant)) |i| { // Create the expression for the other field. - let other_field_ident = cx.ident_of(~"__other" + i.to_str()); + let other_field_ident = cx.ident_of(~"__other_" + i.to_str()); let other_field = build::mk_path(cx, span, ~[ other_field_ident ]); // Create the expression for this field. - let self_field_ident = cx.ident_of(~"__self" + i.to_str()); + let self_field_ident = cx.ident_of(~"__self_" + i.to_str()); let self_field = build::mk_path(cx, span, ~[ self_field_ident ]); // Call the substructure method. @@ -456,10 +456,10 @@ fn expand_deriving_eq_struct_tuple_method(cx: @ext_ctxt, // Create comparison expression, comparing each of the fields let mut match_body = None; for fields.eachi |i, _| { - let other_field_ident = cx.ident_of(other_str + i.to_str()); + let other_field_ident = cx.ident_of(fmt!("%s_%u", other_str, i)); let other_field = build::mk_path(cx, span, ~[ other_field_ident ]); - let self_field_ident = cx.ident_of(self_str + i.to_str()); + let self_field_ident = cx.ident_of(fmt!("%s_%u", self_str, i)); let self_field = build::mk_path(cx, span, ~[ self_field_ident ]); call_substructure_eq_method(cx, span, self_field, other_field, diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs new file mode 100644 index 0000000000000..23a075ef001f6 --- /dev/null +++ b/src/libsyntax/ext/deriving/generic.rs @@ -0,0 +1,826 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Some code that abstracts away much of the boilerplate of writing +`deriving` instances for traits. Among other things it manages getting +access to the fields of the 4 different sorts of structs and enum +variants, as well as creating the method and impl ast instances. + +Supported features (fairly exhaustive): +- Methods taking any number of parameters of type `&Self`, including + none other than `self`. (`MethodDef.nargs`) +- Methods returning `Self` or a non-parameterised type + (e.g. `bool` or `core::cmp::Ordering`). (`MethodDef.output_type`) +- Generating `impl`s for types with type parameters + (e.g. `Option`), the parameters are automatically given the + current trait as a bound. +- Additional bounds on the type parameters, e.g. the `Ord` instance + requires an explicit `Eq` bound at the + moment. (`TraitDef.additional_bounds`) + +(Key unsupported things: methods with arguments of non-`&Self` type, +traits with parameters, methods returning parameterised types, static +methods.) + +The most important thing for implementers is the `Substructure` and +`SubstructureFields` objects. The latter groups 3 possibilities of the +arguments: + +- `Struct`, when `Self` is a struct (including tuple structs, e.g + `struct T(int, char)`). +- `EnumMatching`, when `Self` is an enum and all the arguments are the + same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`) +- `EnumNonMatching` when `Self` is an enum and the arguments are not + the same variant (e.g. `None`, `Some(1)` and `None`) + +In the first two cases, the values from the corresponding fields in +all the arguments are grouped together. In the `EnumNonMatching` case +this isn't possible (different variants have different fields), so the +fields are grouped by which argument they come from. + +All of the cases have `Option` in several places associated +with field `expr`s. This represents the name of the field it is +associated with. It is only not `None` when the associated field has +an identifier in the source code. For example, the `x`s in the +following snippet + + struct A { x : int } + + struct B(int); + + enum C { + C0(int), + C1 { x: int } + } + +The `int`s in `B` and `C0` don't have an identifier, so the +`Option`s would be `None` for them. + +# Examples + +The following simplified `Eq` is used for in-code examples: + + trait Eq { + fn eq(&self, other: &Self); + } + impl Eq for int { + fn eq(&self, other: &int) -> bool { + *self == *other + } + } + +Some examples of the values of `SubstructureFields` follow, using the +above `Eq`, `A`, `B` and `C`. + +## Structs + +When generating the `expr` for the `A` impl, the `SubstructureFields` is + + Struct(~[(Some(), + , + ~[ + ~[])]) + +## Enums + +When generating the `expr` for a call with `self == C0(a)` and `other +== C0(b)`, the SubstructureFields is + + EnumMatching(0, , + ~[None, + , + ~[]]) + +For `C1 {x}` and `C1 {x}`, + + EnumMatching(1, , + ~[Some(), + , + ~[]]) + +For `C0(a)` and `C1 {x}` , + + EnumNonMatching(~[(0, , + ~[(None, )]), + (1, , + ~[(Some(), + )])]) + +(and vice verse, but with the order of the outermost list flipped.) + +*/ + +use core::prelude::*; + +use ast; + +use ast::{ + and, binop, deref, enum_def, expr, expr_match, ident, impure_fn, + item, Generics, m_imm, meta_item, method, named_field, or, public, + struct_def, sty_region, ty_rptr, ty_path, variant}; + +use ast_util; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::*; +use codemap::{span,respan}; +use opt_vec; + +pub fn expand_deriving_generic(cx: @ext_ctxt, + span: span, + _mitem: @meta_item, + in_items: ~[@item], + trait_def: &TraitDef) -> ~[@item] { + let expand_enum: ExpandDerivingEnumDefFn = + |cx, span, enum_def, type_ident, generics| { + trait_def.expand_enum_def(cx, span, enum_def, type_ident, generics) + }; + let expand_struct: ExpandDerivingStructDefFn = + |cx, span, struct_def, type_ident, generics| { + trait_def.expand_struct_def(cx, span, struct_def, type_ident, generics) + }; + + expand_deriving(cx, span, in_items, + expand_struct, + expand_enum) +} + +pub struct TraitDef<'self> { + /// Path of the trait + path: ~[~str], + /// Additional bounds required of any type parameters, other than + /// the current trait + additional_bounds: ~[~[~str]], + methods: ~[MethodDef<'self>] +} + +pub struct MethodDef<'self> { + /// name of the method + name: ~str, + /// The path of return type of the method, e.g. `~[~"core", + /// ~"cmp", ~"Eq"]`. `None` for `Self`. + output_type: Option<~[~str]>, + /// Number of arguments other than `self` (all of type `&Self`) + nargs: uint, + + combine_substructure: CombineSubstructureFunc<'self> +} + +/// All the data about the data structure/method being derived upon. +pub struct Substructure<'self> { + type_ident: ident, + method_ident: ident, + fields: &'self SubstructureFields +} + +/// A summary of the possible sets of fields. See above for details +/// and examples +pub enum SubstructureFields { + /** + Vec of `(field ident, self, [others])` where the field ident is + the ident of the current field (`None` for all fields in tuple + structs) + */ + Struct(~[(Option, @expr, ~[@expr])]), + + /** + Matching variants of the enum: variant index, ast::variant, + fields: `(field ident, self, [others])`, where the field ident is + only non-`None` in the case of a struct variant. + */ + EnumMatching(uint, variant, ~[(Option, @expr, ~[@expr])]), + + /** + non-matching variants of the enum, [(variant index, ast::variant, + [field ident, fields])] (i.e. all fields for self are in the + first tuple, for other1 are in the second tuple, etc.) + */ + EnumNonMatching(~[(uint, variant, ~[(Option, @expr)])]) +} + + +/** +Combine the values of all the fields together. The last argument is +all the fields of all the structures, see above for details. +*/ +pub type CombineSubstructureFunc<'self> = + &'self fn(@ext_ctxt, span, &Substructure) -> @expr; + +/** +Deal with non-matching enum variants, the argument is a list +representing each variant: (variant index, ast::variant instance, +[variant fields]) +*/ +pub type EnumNonMatchFunc<'self> = + &'self fn(@ext_ctxt, span, ~[(uint, variant, ~[(Option, @expr)])]) -> @expr; + + + +impl<'self> TraitDef<'self> { + fn create_derived_impl(&self, cx: @ext_ctxt, span: span, + type_ident: ident, generics: &Generics, + methods: ~[@method]) -> @item { + let trait_path = build::mk_raw_path_global( + span, + do self.path.map |&s| { cx.ident_of(s) }); + + let additional_bounds = opt_vec::from( + do self.additional_bounds.map |v| { + do v.map |&s| { cx.ident_of(s) } + }); + create_derived_impl(cx, span, + type_ident, generics, + methods, trait_path, + opt_vec::Empty, + additional_bounds) + } + + fn expand_struct_def(&self, cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident, + generics: &Generics) + -> @item { + let is_tuple = is_struct_tuple(struct_def); + + let methods = do self.methods.map |method_def| { + let body = if is_tuple { + method_def.expand_struct_tuple_method_body(cx, span, + struct_def, + type_ident) + } else { + method_def.expand_struct_method_body(cx, span, + struct_def, + type_ident) + }; + + method_def.create_method(cx, span, type_ident, generics, body) + }; + + self.create_derived_impl(cx, span, type_ident, generics, methods) + } + + fn expand_enum_def(&self, + cx: @ext_ctxt, span: span, + enum_def: &enum_def, + type_ident: ident, + generics: &Generics) -> @item { + let methods = do self.methods.map |method_def| { + let body = method_def.expand_enum_method_body(cx, span, + enum_def, + type_ident); + + method_def.create_method(cx, span, type_ident, generics, body) + }; + + self.create_derived_impl(cx, span, type_ident, generics, methods) + } +} + +impl<'self> MethodDef<'self> { + fn call_substructure_method(&self, + cx: @ext_ctxt, + span: span, + type_ident: ident, + fields: &SubstructureFields) + -> @expr { + let substructure = Substructure { + type_ident: type_ident, + method_ident: cx.ident_of(self.name), + fields: fields + }; + (self.combine_substructure)(cx, span, + &substructure) + } + + fn get_output_type_path(&self, cx: @ext_ctxt, span: span, + generics: &Generics, type_ident: ident) -> @ast::Path { + match self.output_type { + None => { // Self, add any type parameters + let out_ty_params = do vec::build |push| { + for generics.ty_params.each |ty_param| { + push(build::mk_ty_path(cx, span, ~[ ty_param.ident ])); + } + }; + + build::mk_raw_path_(span, ~[ type_ident ], out_ty_params) + } + Some(str_path) => { + let p = do str_path.map |&s| { cx.ident_of(s) }; + build::mk_raw_path(span, p) + } + } + } + + fn create_method(&self, cx: @ext_ctxt, span: span, + type_ident: ident, + generics: &Generics, body: @expr) -> @method { + // Create the `Self` type of the `other` parameters. + let arg_path_type = create_self_type_with_params(cx, + span, + type_ident, + generics); + let arg_type = ty_rptr( + None, + ast::mt { ty: arg_path_type, mutbl: m_imm } + ); + let arg_type = @ast::Ty { + id: cx.next_id(), + node: arg_type, + span: span, + }; + + // create the arguments + let other_idents = create_other_idents(cx, self.nargs); + let args = do other_idents.map |&id| { + build::mk_arg(cx, span, id, arg_type) + }; + + let output_type = self.get_output_type_path(cx, span, generics, type_ident); + let output_type = ty_path(output_type, cx.next_id()); + let output_type = @ast::Ty { + id: cx.next_id(), + node: output_type, + span: span, + }; + + let method_ident = cx.ident_of(self.name); + let fn_decl = build::mk_fn_decl(args, output_type); + let body_block = build::mk_simple_block(cx, span, body); + + // Create the method. + let self_ty = respan(span, sty_region(None, m_imm)); + @ast::method { + ident: method_ident, + attrs: ~[], + generics: ast_util::empty_generics(), + self_ty: self_ty, + purity: impure_fn, + decl: fn_decl, + body: body_block, + id: cx.next_id(), + span: span, + self_id: cx.next_id(), + vis: public + } + } + + /** + ``` + #[deriving(Eq)] + struct A(int, int); + + // equivalent to: + + impl Eq for A { + fn eq(&self, __other_1: &A) -> bool { + match *self { + (ref self_1, ref self_2) => { + match *__other_1 { + (ref __other_1_1, ref __other_1_2) => { + self_1.eq(__other_1_1) && self_2.eq(__other_1_2) + } + } + } + } + } + } + ``` + */ + fn expand_struct_tuple_method_body(&self, + cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident) -> @expr { + let self_str = ~"self"; + let other_strs = create_other_strs(self.nargs); + let num_fields = struct_def.fields.len(); + + + let fields = do struct_def.fields.mapi |i, _| { + let other_fields = do other_strs.map |&other_str| { + let other_field_ident = cx.ident_of(fmt!("%s_%u", other_str, i)); + build::mk_path(cx, span, ~[ other_field_ident ]) + }; + + let self_field_ident = cx.ident_of(fmt!("%s_%u", self_str, i)); + let self_field = build::mk_path(cx, span, ~[ self_field_ident ]); + + (None, self_field, other_fields) + }; + + let mut match_body = self.call_substructure_method(cx, span, type_ident, &Struct(fields)); + + let type_path = build::mk_raw_path(span, ~[type_ident]); + + // create the matches from inside to out (i.e. other_{self.nargs} to other_1) + for other_strs.each_reverse |&other_str| { + match_body = create_deref_match(cx, span, type_path, + other_str, num_fields, + match_body) + } + + // create the match on self + return create_deref_match(cx, span, type_path, + ~"self", num_fields, match_body); + + /** + Creates a match expression against a tuple that needs to + be dereferenced, but nothing else + + ``` + match *`to_match` { + (`to_match`_1, ..., `to_match`_`num_fields`) => `match_body` + } + ``` + */ + fn create_deref_match(cx: @ext_ctxt, + span: span, + type_path: @ast::Path, + to_match: ~str, + num_fields: uint, + match_body: @expr) -> @expr { + let match_subpats = create_subpatterns(cx, span, to_match, num_fields); + let match_arm = ast::arm { + pats: ~[ build::mk_pat_enum(cx, span, type_path, match_subpats) ], + guard: None, + body: build::mk_simple_block(cx, span, match_body), + }; + + let deref_expr = build::mk_unary(cx, span, deref, + build::mk_path(cx, span, + ~[ cx.ident_of(to_match)])); + let match_expr = build::mk_expr(cx, span, expr_match(deref_expr, ~[match_arm])); + + match_expr + } + } + + /** + ``` + #[deriving(Eq)] + struct A { x: int, y: int } + + // equivalent to: + + impl Eq for A { + fn eq(&self, __other_1: &A) -> bool { + self.x.eq(&__other_1.x) && + self.y.eq(&__other_1.y) + } + } + ``` + */ + fn expand_struct_method_body(&self, + cx: @ext_ctxt, + span: span, + struct_def: &struct_def, + type_ident: ident) + -> @expr { + let self_ident = cx.ident_of(~"self"); + let other_idents = create_other_idents(cx, self.nargs); + + let fields = do struct_def.fields.map |struct_field| { + match struct_field.node.kind { + named_field(ident, _, _) => { + // Create the accessor for this field in the other args. + let other_fields = do other_idents.map |&id| { + build::mk_access(cx, span, ~[id], ident) + }; + let other_field_refs = do other_fields.map |&other_field| { + build::mk_addr_of(cx, span, other_field) + }; + + // Create the accessor for this field in self. + let self_field = + build::mk_access( + cx, span, + ~[ self_ident ], + ident); + + (Some(ident), self_field, other_field_refs) + } + unnamed_field => { + cx.span_unimpl(span, ~"unnamed fields with `deriving_generic`"); + } + } + }; + + self.call_substructure_method(cx, span, type_ident, &Struct(fields)) + } + + /** + ``` + #[deriving(Eq)] + enum A { + A1 + A2(int) + } + + // is equivalent to + + impl Eq for A { + fn eq(&self, __other_1: &A) { + match *self { + A1 => match *__other_1 { + A1 => true, + A2(ref __other_1_1) => false + }, + A2(self_1) => match *__other_1 { + A1 => false, + A2(ref __other_1_1) => self_1.eq(__other_1_1) + } + } + } + } + ``` + */ + fn expand_enum_method_body(&self, + cx: @ext_ctxt, + span: span, + enum_def: &enum_def, + type_ident: ident) + -> @expr { + self.build_enum_match(cx, span, enum_def, type_ident, ~[]) + } + + + /** + Creates the nested matches for an enum definition, i.e. + + ``` + match self { + Variant1 => match other { Variant1 => matching, Variant2 => nonmatching, ... }, + Variant2 => match other { Variant1 => nonmatching, Variant2 => matching, ... }, + ... + } + ``` + + It acts in the most naive way, so every branch (and subbranch, + subsubbranch, etc) exists, not just the ones where all the variants in + the tree are the same. Hopefully the optimisers get rid of any + repetition, otherwise derived methods with many Self arguments will be + exponentially large. + */ + fn build_enum_match(&self, + cx: @ext_ctxt, span: span, + enum_def: &enum_def, + type_ident: ident, + matches_so_far: ~[(uint, variant, + ~[(Option, @expr)])]) -> @expr { + if matches_so_far.len() == self.nargs + 1 { + // we've matched against all arguments, so make the final + // expression at the bottom of the match tree + match matches_so_far { + [] => cx.bug(~"no self match on an enum in `deriving_generic`"), + _ => { + // we currently have a vec of vecs, where each + // subvec is the fields of one of the arguments, + // but if the variants all match, we want this as + // vec of tuples, where each tuple represents a + // field. + + // `ref` inside let matches is buggy. Causes havoc wih rusc. + // let (variant_index, ref self_vec) = matches_so_far[0]; + let (variant_index, variant, self_vec) = match matches_so_far[0] { + (i, v, ref s) => (i, v, s) + }; + + let substructure; + + // most arms don't have matching variants, so do a + // quick check to see if they match (even though + // this means iterating twice) instead of being + // optimistic and doing a pile of allocations etc. + if matches_so_far.all(|&(v_i, _, _)| v_i == variant_index) { + let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]); + + for matches_so_far.tail().each |&(_, _, other_fields)| { + for other_fields.eachi |i, &(_, other_field)| { + enum_matching_fields[i].push(other_field); + } + } + let field_tuples = + do vec::map2(*self_vec, + enum_matching_fields) |&(id, self_f), &other| { + (id, self_f, other) + }; + substructure = EnumMatching(variant_index, variant, field_tuples); + } else { + substructure = EnumNonMatching(matches_so_far); + } + self.call_substructure_method(cx, span, type_ident, &substructure) + } + } + + } else { // there are still matches to create + let (current_match_ident, current_match_str) = if matches_so_far.is_empty() { + (cx.ident_of(~"self"), ~"__self") + } else { + let s = fmt!("__other_%u", matches_so_far.len() - 1); + (cx.ident_of(s), s) + }; + + let mut arms = ~[]; + + // this is used as a stack + let mut matches_so_far = matches_so_far; + + // create an arm matching on each variant + for enum_def.variants.eachi |index, variant| { + let pattern = create_enum_variant_pattern(cx, span, + variant, + current_match_str); + + let idents = do vec::build |push| { + for each_variant_arg_ident(cx, span, variant) |i, field_id| { + let id = cx.ident_of(fmt!("%s_%u", current_match_str, i)); + push((field_id, build::mk_path(cx, span, ~[ id ]))); + } + }; + + + matches_so_far.push((index, *variant, idents)); + let arm_expr = self.build_enum_match(cx, span, + enum_def, + type_ident, + matches_so_far); + matches_so_far.pop(); + + let arm_block = build::mk_simple_block(cx, span, arm_expr); + let arm = ast::arm { + pats: ~[ pattern ], + guard: None, + body: arm_block + }; + arms.push(arm); + } + + let deref_expr = build::mk_unary(cx, span, deref, + build::mk_path(cx, span, + ~[ current_match_ident ])); + let match_expr = build::mk_expr(cx, span, + expr_match(deref_expr, arms)); + + match_expr + } + } +} + +/// Create variable names (as strings) to refer to the non-self +/// parameters +fn create_other_strs(n: uint) -> ~[~str] { + do vec::build |push| { + for uint::range(0, n) |i| { + push(fmt!("__other_%u", i)); + } + } +} +/// Like `create_other_strs`, but returns idents for the strings +fn create_other_idents(cx: @ext_ctxt, n: uint) -> ~[ident] { + do create_other_strs(n).map |&s| { + cx.ident_of(s) + } +} + + + +/* helpful premade recipes */ + +/** +Fold the fields. `use_foldl` controls whether this is done +left-to-right (`true`) or right-to-left (`false`). +*/ +pub fn cs_fold(use_foldl: bool, + f: &fn(@ext_ctxt, span, + old: @expr, + self_f: @expr, other_fs: ~[@expr]) -> @expr, + base: @expr, + enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + match *substructure.fields { + EnumMatching(_, _, all_fields) | Struct(all_fields) => { + if use_foldl { + do all_fields.foldl(base) |&old, &(_, self_f, other_fs)| { + f(cx, span, old, self_f, other_fs) + } + } else { + do all_fields.foldr(base) |&(_, self_f, other_fs), old| { + f(cx, span, old, self_f, other_fs) + } + } + }, + EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span, all_enums) + } +} + + +/** +Call the method that is being derived on all the fields, and then +process the collected results. i.e. + +``` +f(cx, span, ~[self_1.method(__other_1_1, __other_2_1), + self_2.method(__other_1_2, __other_2_2)]) +``` +*/ +pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr, + enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + match *substructure.fields { + EnumMatching(_, _, all_fields) | Struct(all_fields) => { + // call self_n.method(other_1_n, other_2_n, ...) + let called = do all_fields.map |&(_, self_field, other_fields)| { + build::mk_method_call(cx, span, + self_field, + substructure.method_ident, + other_fields) + }; + + f(cx, span, called) + }, + EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span, all_enums) + } +} + +/** +Fold together the results of calling the derived method on all the +fields. `use_foldl` controls whether this is done left-to-right +(`true`) or right-to-left (`false`). +*/ +pub fn cs_same_method_fold(use_foldl: bool, + f: &fn(@ext_ctxt, span, @expr, @expr) -> @expr, + base: @expr, + enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + cs_same_method( + |cx, span, vals| { + if use_foldl { + do vals.foldl(base) |&old, &new| { + f(cx, span, old, new) + } + } else { + do vals.foldr(base) |&new, old| { + f(cx, span, old, new) + } + } + }, + enum_nonmatch_f, + cx, span, substructure) + +} + +/** +Use a given binop to combine the result of calling the derived method +on all the fields. +*/ +pub fn cs_binop(binop: binop, base: @expr, + enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + cs_same_method_fold( + true, // foldl is good enough + |cx, span, old, new| { + build::mk_binary(cx, span, + binop, + old, new) + + }, + base, + enum_nonmatch_f, + cx, span, substructure) +} + +/// cs_binop with binop == or +pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + cs_binop(or, build::mk_bool(cx, span, false), + enum_nonmatch_f, + cx, span, substructure) +} +/// cs_binop with binop == and +pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc, + cx: @ext_ctxt, span: span, + substructure: &Substructure) -> @expr { + cs_binop(and, build::mk_bool(cx, span, true), + enum_nonmatch_f, + cx, span, substructure) +} diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index 4124e6ee6c165..75215b90eb0da 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -56,7 +56,8 @@ fn create_derived_iter_bytes_impl(cx: @ext_ctxt, cx.ident_of(~"IterBytes") ]; let trait_path = build::mk_raw_path_global(span, trait_path); - create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty) + create_derived_impl(cx, span, type_ident, generics, methods, trait_path, + opt_vec::Empty, opt_vec::Empty) } // Creates a method from the given set of statements conforming to the @@ -230,7 +231,7 @@ fn expand_deriving_iter_bytes_enum_method(cx: @ext_ctxt, // as well. for uint::range(0, variant_arg_count(cx, span, variant)) |j| { // Create the expression for this field. - let field_ident = cx.ident_of(~"__self" + j.to_str()); + let field_ident = cx.ident_of(~"__self_" + j.to_str()); let field = build::mk_path(cx, span, ~[ field_ident ]); // Call the substructure method. diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 63106eae48ae8..1241d4fa71139 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -24,30 +24,32 @@ use ast::{tuple_variant_kind}; use ast::{ty_path, unnamed_field, variant}; use ext::base::ext_ctxt; use ext::build; -use codemap::span; +use codemap::{span, respan}; use parse::token::special_idents::clownshoes_extensions; use opt_vec; use core::uint; -pub mod clone; pub mod eq; +pub mod clone; pub mod iter_bytes; pub mod encodable; pub mod decodable; -type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, - span, - x: &struct_def, - ident, - y: &Generics) - -> @item; -type ExpandDerivingEnumDefFn<'self> = &'self fn(@ext_ctxt, - span, - x: &enum_def, - ident, - y: &Generics) - -> @item; +pub mod generic; + +pub type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, + span, + x: &struct_def, + ident, + y: &Generics) + -> @item; +pub type ExpandDerivingEnumDefFn<'self> = &'self fn(@ext_ctxt, + span, + x: &enum_def, + ident, + y: &Generics) + -> @item; pub fn expand_meta_deriving(cx: @ext_ctxt, _span: span, @@ -72,10 +74,10 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, meta_list(tname, _) | meta_word(tname) => { match *tname { + ~"Eq" => eq::expand_deriving_eq(cx, titem.span, + titem, in_items), ~"Clone" => clone::expand_deriving_clone(cx, titem.span, titem, in_items), - ~"Eq" => eq::expand_deriving_eq(cx, titem.span, - titem, in_items), ~"IterBytes" => iter_bytes::expand_deriving_iter_bytes(cx, titem.span, titem, in_items), ~"Encodable" => encodable::expand_deriving_encodable(cx, @@ -126,9 +128,19 @@ pub fn expand_deriving(cx: @ext_ctxt, } fn create_impl_item(cx: @ext_ctxt, span: span, +item: item_) -> @item { + let doc_attr = respan(span, + ast::lit_str(@~"Automatically derived.")); + let doc_attr = respan(span, ast::meta_name_value(@~"doc", doc_attr)); + let doc_attr = ast::attribute_ { + style: ast::attr_outer, + value: @doc_attr, + is_sugared_doc: false + }; + let doc_attr = respan(span, doc_attr); + @ast::item { ident: clownshoes_extensions, - attrs: ~[], + attrs: ~[doc_attr], id: cx.next_id(), node: item, vis: public, @@ -164,14 +176,17 @@ pub fn create_derived_impl(cx: @ext_ctxt, generics: &Generics, methods: &[@method], trait_path: @ast::Path, - mut impl_ty_params: opt_vec::OptVec) + mut impl_ty_params: opt_vec::OptVec, + bounds_paths: opt_vec::OptVec<~[ident]>) -> @item { /*! * * Given that we are deriving a trait `Tr` for a type `T<'a, ..., * 'z, A, ..., Z>`, creates an impl like: * - * impl<'a, ..., 'z, A:Tr, ..., Z: Tr> Tr for T { ... } + * impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T { ... } + * + * where B1, B2, ... are the bounds given by `bounds_paths`. * * FIXME(#5090): Remove code duplication between this and the * code in auto_encode.rs @@ -182,16 +197,21 @@ pub fn create_derived_impl(cx: @ext_ctxt, build::mk_lifetime(cx, l.span, l.ident) }); - // Create the reference to the trait. - let trait_ref = build::mk_trait_ref_(cx, trait_path); - // Create the type parameters. for generics.ty_params.each |ty_param| { - let bounds = @opt_vec::with( - build::mk_trait_ty_param_bound_(cx, trait_path) - ); - impl_ty_params.push(build::mk_ty_param(cx, ty_param.ident, bounds)); - }; + let mut bounds = do bounds_paths.map |&bound_path| { + build::mk_trait_ty_param_bound_global(cx, span, bound_path) + }; + + let this_trait_bound = + build::mk_trait_ty_param_bound_(cx, trait_path); + bounds.push(this_trait_bound); + + impl_ty_params.push(build::mk_ty_param(cx, ty_param.ident, @bounds)); + } + + // Create the reference to the trait. + let trait_ref = build::mk_trait_ref_(cx, trait_path); // Create the type of `self`. let self_type = create_self_type_with_params(cx, @@ -216,8 +236,8 @@ pub fn create_subpatterns(cx: @ext_ctxt, let mut subpats = ~[]; for uint::range(0, n) |_i| { // Create the subidentifier. - let index = subpats.len().to_str(); - let ident = cx.ident_of(prefix + index); + let index = subpats.len(); + let ident = cx.ident_of(fmt!("%s_%u", prefix, index)); // Create the subpattern. let subpath = build::mk_raw_path(span, ~[ ident ]); @@ -287,6 +307,29 @@ pub fn variant_arg_count(_cx: @ext_ctxt, _span: span, variant: &variant) -> uint } } +/// Iterate through the idents of the variant arguments. The field is +/// unnamed (i.e. it's not a struct-like enum), then `None`. +pub fn each_variant_arg_ident(_cx: @ext_ctxt, _span: span, + variant: &variant, it: &fn(uint, Option) -> bool) { + match variant.node.kind { + tuple_variant_kind(ref args) => { + for uint::range(0, args.len()) |i| { + if !it(i, None) { break } + } + } + struct_variant_kind(ref struct_def) => { + for struct_def.fields.eachi |i, f| { + let id = match f.node.kind { + named_field(ident, _, _) => Some(ident), + unnamed_field => None + }; + if !it(i, id) { break } + } + } + } +} + + pub fn expand_enum_or_struct_match(cx: @ext_ctxt, span: span, arms: ~[ ast::arm ]) From 85b82c763bfbfd5de59f4c6b026dca58f3ba4687 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 31 Mar 2013 01:34:37 +1100 Subject: [PATCH 155/403] libcore: combine cmp::Ordering instances in lexical order. --- src/libcore/cmp.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index f96575aaf414f..2c2b7f40f318f 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -116,6 +116,19 @@ totalord_impl!(i64) totalord_impl!(int) totalord_impl!(uint) +/** +Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the +lexical ordering on a type `(int, int)`. +*/ +// used in deriving code in libsyntax +#[inline(always)] +pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { + match o1 { + Equal => o2, + _ => o1 + } +} + /** * Trait for values that can be compared for a sort-order. * @@ -184,6 +197,8 @@ pub fn max(v1: T, v2: T) -> T { #[cfg(test)] mod test { + use super::lexical_ordering; + #[test] fn test_int_totalord() { assert_eq!(5.cmp(&10), Less); @@ -204,4 +219,16 @@ mod test { assert!(Less < Equal); assert_eq!(Greater.cmp(&Less), Greater); } + + #[test] + fn test_lexical_ordering() { + fn t(o1: Ordering, o2: Ordering, e: Ordering) { + assert_eq!(lexical_ordering(o1, o2), e); + } + for [Less, Equal, Greater].each |&o| { + t(Less, o, Less); + t(Equal, o, o); + t(Greater, o, Greater); + } + } } From 7906c5572a8c4c5c0f6aa6e69bb63d64de50d697 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 31 Mar 2013 01:58:05 +1100 Subject: [PATCH 156/403] libsyntax: derive Clone, Eq, TotalEq, Ord, TotalOrd with the new generic deriving code. Closes #4269, #5588 and #5589. --- src/libsyntax/ext/deriving/clone.rs | 322 +++---------- src/libsyntax/ext/deriving/cmp/eq.rs | 65 +++ src/libsyntax/ext/deriving/cmp/ord.rs | 142 ++++++ src/libsyntax/ext/deriving/cmp/totaleq.rs | 45 ++ src/libsyntax/ext/deriving/cmp/totalord.rs | 77 ++++ src/libsyntax/ext/deriving/eq.rs | 500 --------------------- src/libsyntax/ext/deriving/mod.rs | 21 +- 7 files changed, 411 insertions(+), 761 deletions(-) create mode 100644 src/libsyntax/ext/deriving/cmp/eq.rs create mode 100644 src/libsyntax/ext/deriving/cmp/ord.rs create mode 100644 src/libsyntax/ext/deriving/cmp/totaleq.rs create mode 100644 src/libsyntax/ext/deriving/cmp/totalord.rs delete mode 100644 src/libsyntax/ext/deriving/eq.rs diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 390b72da3314b..0c62566702d90 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -8,29 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::prelude::*; - -use ast; -use ast::*; +use ast::{meta_item, item, expr}; +use codemap::span; use ext::base::ext_ctxt; use ext::build; -use ext::deriving::*; -use codemap::{span, spanned}; -use ast_util; -use opt_vec; +use ext::deriving::generic::*; +use core::option::{None,Some}; -use core::uint; pub fn expand_deriving_clone(cx: @ext_ctxt, span: span, - _: @meta_item, + mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { - expand_deriving(cx, - span, - in_items, - expand_deriving_clone_struct_def, - expand_deriving_clone_enum_def) + let trait_def = TraitDef { + path: ~[~"core", ~"clone", ~"Clone"], + additional_bounds: ~[], + methods: ~[ + MethodDef { + name: ~"clone", + nargs: 0, + output_type: None, // return Self + combine_substructure: cs_clone + } + ] + }; + + expand_deriving_generic(cx, span, + mitem, in_items, + &trait_def) } pub fn expand_deriving_obsolete(cx: @ext_ctxt, @@ -42,252 +48,52 @@ pub fn expand_deriving_obsolete(cx: @ext_ctxt, in_items } -fn create_derived_clone_impl(cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics, - method: @method) - -> @item { - let methods = [ method ]; - let trait_path = ~[ - cx.ident_of(~"core"), - cx.ident_of(~"clone"), - cx.ident_of(~"Clone"), - ]; - let trait_path = build::mk_raw_path_global(span, trait_path); - create_derived_impl(cx, span, type_ident, generics, methods, trait_path, - opt_vec::Empty, opt_vec::Empty) -} -// Creates a method from the given expression conforming to the signature of -// the `clone` method. -fn create_clone_method(cx: @ext_ctxt, - span: span, - +type_ident: ast::ident, - generics: &Generics, - expr: @ast::expr) - -> @method { - // Create the type parameters of the return value. - let mut output_ty_params = ~[]; - for generics.ty_params.each |ty_param| { - let path = build::mk_ty_path(cx, span, ~[ ty_param.ident ]); - output_ty_params.push(path); - } - - // Create the type of the return value. - let output_type_path = build::mk_raw_path_(span, - ~[ type_ident ], - output_ty_params); - let output_type = ast::ty_path(output_type_path, cx.next_id()); - let output_type = @ast::Ty { - id: cx.next_id(), - node: output_type, - span: span - }; - - // Create the function declaration. - let fn_decl = build::mk_fn_decl(~[], output_type); - - // Create the body block. - let body_block = build::mk_simple_block(cx, span, expr); - - // Create the self type and method identifier. - let self_ty = spanned { node: sty_region(None, m_imm), span: span }; - let method_ident = cx.ident_of(~"clone"); - - // Create the method. - @ast::method { - ident: method_ident, - attrs: ~[], - generics: ast_util::empty_generics(), - self_ty: self_ty, - purity: impure_fn, - decl: fn_decl, - body: body_block, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: public, +fn cs_clone(cx: @ext_ctxt, span: span, + substr: &Substructure) -> @expr { + let clone_ident = substr.method_ident; + let ctor_ident; + let all_fields; + let subcall = |field| + build::mk_method_call(cx, span, field, clone_ident, ~[]); + + match *substr.fields { + Struct(af) => { + ctor_ident = ~[ substr.type_ident ]; + all_fields = af; + } + EnumMatching(_, variant, af) => { + ctor_ident = ~[ variant.node.name ]; + all_fields = af; + }, + EnumNonMatching(*) => cx.bug("Non-matching enum variants in `deriving(Clone)`") } -} - -fn call_substructure_clone_method(cx: @ext_ctxt, - span: span, - self_field: @expr) - -> @expr { - // Call the substructure method. - let clone_ident = cx.ident_of(~"clone"); - build::mk_method_call(cx, span, - self_field, clone_ident, - ~[]) -} - -fn expand_deriving_clone_struct_def(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics) - -> @item { - // Create the method. - let method = if !is_struct_tuple(struct_def) { - expand_deriving_clone_struct_method(cx, - span, - struct_def, - type_ident, - generics) - } else { - expand_deriving_clone_tuple_struct_method(cx, - span, - struct_def, - type_ident, - generics) - }; - - // Create the implementation. - create_derived_clone_impl(cx, span, type_ident, generics, method) -} - -fn expand_deriving_clone_enum_def(cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ident, - generics: &Generics) - -> @item { - // Create the method. - let method = expand_deriving_clone_enum_method(cx, - span, - enum_definition, - type_ident, - generics); - - // Create the implementation. - create_derived_clone_impl(cx, span, type_ident, generics, method) -} - -fn expand_deriving_clone_struct_method(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics) - -> @method { - let self_ident = cx.ident_of(~"self"); - - // Create the new fields. - let mut fields = ~[]; - for struct_def.fields.each |struct_field| { - match struct_field.node.kind { - named_field(ident, _, _) => { - // Create the accessor for this field. - let self_field = build::mk_access(cx, - span, - ~[ self_ident ], - ident); - // Call the substructure method. - let call = call_substructure_clone_method(cx, - span, - self_field); - - let field = build::Field { ident: ident, ex: call }; - fields.push(field); - } - unnamed_field => { - cx.span_bug(span, ~"unnamed fields in `deriving(Clone)`"); + match all_fields { + [(None, _, _), .. _] => { + // enum-like + let subcalls = all_fields.map(|&(_, self_f, _)| subcall(self_f)); + build::mk_call(cx, span, ctor_ident, subcalls) + }, + _ => { + // struct-like + let fields = do all_fields.map |&(o_id, self_f, _)| { + let ident = match o_id { + Some(i) => i, + None => cx.span_bug(span, + ~"unnamed field in normal struct \ + in `deriving(Clone)`") + }; + build::Field { ident: ident, ex: subcall(self_f) } + }; + + if fields.is_empty() { + // no fields, so construct like `None` + build::mk_path(cx, span, ctor_ident) + } else { + build::mk_struct_e(cx, span, + ctor_ident, + fields) } } } - - // Create the struct literal. - let struct_literal = build::mk_struct_e(cx, - span, - ~[ type_ident ], - fields); - create_clone_method(cx, span, type_ident, generics, struct_literal) -} - -fn expand_deriving_clone_tuple_struct_method(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics) - -> @method { - // Create the pattern for the match. - let matching_path = build::mk_raw_path(span, ~[ type_ident ]); - let field_count = struct_def.fields.len(); - let subpats = create_subpatterns(cx, span, ~"__self", field_count); - let pat = build::mk_pat_enum(cx, span, matching_path, subpats); - - // Create the new fields. - let mut subcalls = ~[]; - for uint::range(0, struct_def.fields.len()) |i| { - // Create the expression for this field. - let field_ident = cx.ident_of(~"__self_" + i.to_str()); - let field = build::mk_path(cx, span, ~[ field_ident ]); - - // Call the substructure method. - let subcall = call_substructure_clone_method(cx, span, field); - subcalls.push(subcall); - } - - // Create the call to the struct constructor. - let call = build::mk_call(cx, span, ~[ type_ident ], subcalls); - - // Create the pattern body. - let match_body_block = build::mk_simple_block(cx, span, call); - - // Create the arm. - let arm = ast::arm { - pats: ~[ pat ], - guard: None, - body: match_body_block - }; - - // Create the method body. - let self_match_expr = expand_enum_or_struct_match(cx, span, ~[ arm ]); - - // Create the method. - create_clone_method(cx, span, type_ident, generics, self_match_expr) -} - -fn expand_deriving_clone_enum_method(cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ident, - generics: &Generics) - -> @method { - // Create the arms of the match in the method body. - let arms = do enum_definition.variants.map |variant| { - // Create the matching pattern. - let pat = create_enum_variant_pattern(cx, span, variant, ~"__self"); - - // Iterate over the variant arguments, creating the subcalls. - let mut subcalls = ~[]; - for uint::range(0, variant_arg_count(cx, span, variant)) |j| { - // Create the expression for this field. - let field_ident = cx.ident_of(~"__self_" + j.to_str()); - let field = build::mk_path(cx, span, ~[ field_ident ]); - - // Call the substructure method. - let subcall = call_substructure_clone_method(cx, span, field); - subcalls.push(subcall); - } - - // Create the call to the enum variant (if necessary). - let call = if subcalls.len() > 0 { - build::mk_call(cx, span, ~[ variant.node.name ], subcalls) - } else { - build::mk_path(cx, span, ~[ variant.node.name ]) - }; - - // Create the pattern body. - let match_body_block = build::mk_simple_block(cx, span, call); - - // Create the arm. - ast::arm { pats: ~[ pat ], guard: None, body: match_body_block } - }; - - // Create the method body. - let self_match_expr = expand_enum_or_struct_match(cx, span, arms); - - // Create the method. - create_clone_method(cx, span, type_ident, generics, self_match_expr) } diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs new file mode 100644 index 0000000000000..142f0565e149e --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -0,0 +1,65 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use ast::{meta_item, item, expr}; +use codemap::span; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::generic::*; + +use core::option::Some; + +pub fn expand_deriving_eq(cx: @ext_ctxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + // structures are equal if all fields are equal, and non equal, if + // any fields are not equal or if the enum variants are different + fn cs_eq(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { + cs_and(|cx, span, _| build::mk_bool(cx, span, false), + cx, span, substr) + } + fn cs_ne(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { + cs_or(|cx, span, _| build::mk_bool(cx, span, true), + cx, span, substr) + } + + + let trait_def = TraitDef { + path: ~[~"core", ~"cmp", ~"Eq"], + additional_bounds: ~[], + methods: ~[ + MethodDef { + name: ~"ne", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: cs_ne + }, + MethodDef { + name: ~"eq", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: cs_eq + } + ] + }; + + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) +} + +pub fn expand_deriving_obsolete(cx: @ext_ctxt, + span: span, + _mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + cx.span_err(span, ~"`#[deriving_eq]` is obsolete; use `#[deriving(Eq)]` instead"); + in_items +} diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs new file mode 100644 index 0000000000000..7f7babab45cc4 --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -0,0 +1,142 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use ast::{meta_item, item, expr_if, expr}; +use codemap::span; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::generic::*; +use core::option::Some; + +macro_rules! mk_cso { + ($less:expr, $equal:expr) => { + |cx, span, substr| + cs_ord($less, $equal, cx, span, substr) + } +} + +pub fn expand_deriving_ord(cx: @ext_ctxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + let trait_def = TraitDef { + path: ~[~"core", ~"cmp", ~"Ord"], + // XXX: Ord doesn't imply Eq yet + additional_bounds: ~[~[~"core", ~"cmp", ~"Eq"]], + methods: ~[ + MethodDef { + name: ~"lt", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: mk_cso!(true, false) + }, + MethodDef { + name: ~"le", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: mk_cso!(true, true) + }, + MethodDef { + name: ~"gt", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: mk_cso!(false, false) + }, + MethodDef { + name: ~"ge", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: mk_cso!(false, true) + }, + ] + }; + + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) +} + +/// `less`: is this `lt` or `le`? `equal`: is this `le` or `ge`? +fn cs_ord(less: bool, equal: bool, + cx: @ext_ctxt, span: span, + substr: &Substructure) -> @expr { + let binop = if less { + cx.ident_of(~"lt") + } else { + cx.ident_of(~"gt") + }; + let false_blk_expr = build::mk_block(cx, span, + ~[], ~[], + Some(build::mk_bool(cx, span, false))); + let true_blk = build::mk_simple_block(cx, span, + build::mk_bool(cx, span, true)); + let base = build::mk_bool(cx, span, equal); + + cs_fold( + false, // need foldr, + |cx, span, subexpr, self_f, other_fs| { + /* + + build up a series of nested ifs from the inside out to get + lexical ordering (hence foldr), i.e. + + ``` + if self.f1 `binop` other.f1 { + true + } else if self.f1 == other.f1 { + if self.f2 `binop` other.f2 { + true + } else if self.f2 == other.f2 { + `equal` + } else { + false + } + } else { + false + } + ``` + + The inner "`equal`" case is only reached if the two + items have all fields equal. + */ + if other_fs.len() != 1 { + cx.span_bug(span, "Not exactly 2 arguments in `deriving(Ord)`"); + } + + let cmp = build::mk_method_call(cx, span, + self_f, cx.ident_of(~"eq"), other_fs); + let subexpr = build::mk_simple_block(cx, span, subexpr); + let elseif = expr_if(cmp, subexpr, Some(false_blk_expr)); + let elseif = build::mk_expr(cx, span, elseif); + + let cmp = build::mk_method_call(cx, span, + self_f, binop, other_fs); + let if_ = expr_if(cmp, true_blk, Some(elseif)); + + build::mk_expr(cx, span, if_) + }, + base, + |cx, span, args| { + // nonmatching enums, order by the order the variants are + // written + match args { + [(self_var, _, _), + (other_var, _, _)] => + build::mk_bool(cx, span, + if less { + self_var < other_var + } else { + self_var > other_var + }), + _ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(Ord)`") + } + }, + cx, span, substr) +} diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs new file mode 100644 index 0000000000000..d71db22591dd6 --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -0,0 +1,45 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use ast::{meta_item, item, expr}; +use codemap::span; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::generic::*; + +use core::option::Some; + +pub fn expand_deriving_totaleq(cx: @ext_ctxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + + fn cs_equals(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { + cs_and(|cx, span, _| build::mk_bool(cx, span, false), + cx, span, substr) + } + + let trait_def = TraitDef { + path: ~[~"core", ~"cmp", ~"TotalEq"], + additional_bounds: ~[], + methods: ~[ + MethodDef { + name: ~"equals", + output_type: Some(~[~"bool"]), + nargs: 1, + combine_substructure: cs_equals + } + ] + }; + + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) +} diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs new file mode 100644 index 0000000000000..d82c63e9dd343 --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -0,0 +1,77 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast::{meta_item, item, expr}; +use codemap::span; +use ext::base::ext_ctxt; +use ext::build; +use ext::deriving::generic::*; +use core::cmp::{Ordering, Equal, Less, Greater}; +use core::option::Some; + +pub fn expand_deriving_totalord(cx: @ext_ctxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + let trait_def = TraitDef { + path: ~[~"core", ~"cmp", ~"TotalOrd"], + additional_bounds: ~[], + methods: ~[ + MethodDef { + name: ~"cmp", + output_type: Some(~[~"core", ~"cmp", ~"Ordering"]), + nargs: 1, + combine_substructure: cs_cmp + } + ] + }; + + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) +} + + +pub fn ordering_const(cx: @ext_ctxt, span: span, cnst: Ordering) -> @expr { + let cnst = match cnst { + Less => ~"Less", + Equal => ~"Equal", + Greater => ~"Greater" + }; + build::mk_path(cx, span, + ~[cx.ident_of(~"core"), + cx.ident_of(~"cmp"), + cx.ident_of(cnst)]) +} + +pub fn cs_cmp(cx: @ext_ctxt, span: span, + substr: &Substructure) -> @expr { + let lexical_ord = ~[cx.ident_of(~"core"), + cx.ident_of(~"cmp"), + cx.ident_of(~"lexical_ordering")]; + + cs_same_method_fold( + // foldr (possibly) nests the matches in lexical_ordering better + false, + |cx, span, old, new| { + build::mk_call(cx, span, lexical_ord, ~[old, new]) + }, + ordering_const(cx, span, Equal), + |cx, span, list| { + match list { + // an earlier nonmatching variant is Less than a + // later one + [(self_var, _, _), + (other_var, _, _)] => ordering_const(cx, span, + self_var.cmp(&other_var)), + _ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`") + } + }, + cx, span, substr) +} diff --git a/src/libsyntax/ext/deriving/eq.rs b/src/libsyntax/ext/deriving/eq.rs deleted file mode 100644 index 0afb667c69ab9..0000000000000 --- a/src/libsyntax/ext/deriving/eq.rs +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use core::prelude::*; - -use ast; -use ast::*; -use ext::base::ext_ctxt; -use ext::build; -use ext::deriving::*; -use codemap::{span, spanned}; -use ast_util; -use opt_vec; - -use core::uint; - -enum Junction { - Conjunction, - Disjunction, -} - -pub impl Junction { - fn to_binop(self) -> binop { - match self { - Conjunction => and, - Disjunction => or, - } - } -} - -pub fn expand_deriving_eq(cx: @ext_ctxt, - span: span, - _mitem: @meta_item, - in_items: ~[@item]) - -> ~[@item] { - expand_deriving(cx, - span, - in_items, - expand_deriving_eq_struct_def, - expand_deriving_eq_enum_def) -} - -pub fn expand_deriving_obsolete(cx: @ext_ctxt, - span: span, - _mitem: @meta_item, - in_items: ~[@item]) - -> ~[@item] { - cx.span_err(span, ~"`#[deriving_eq]` is obsolete; use `#[deriving(Eq)]` instead"); - in_items -} - -/// Creates a method from the given expression, the signature of which -/// conforms to the `eq` or `ne` method. -fn create_eq_method(cx: @ext_ctxt, - span: span, - method_ident: ident, - type_ident: ident, - generics: &Generics, - body: @expr) - -> @method { - // Create the type of the `other` parameter. - let arg_path_type = create_self_type_with_params(cx, - span, - type_ident, - generics); - let arg_type = ty_rptr( - None, - ast::mt { ty: arg_path_type, mutbl: m_imm } - ); - let arg_type = @ast::Ty { - id: cx.next_id(), - node: arg_type, - span: span, - }; - - // Create the `other` parameter. - let other_ident = cx.ident_of(~"__other"); - let arg = build::mk_arg(cx, span, other_ident, arg_type); - - // Create the type of the return value. - let bool_ident = cx.ident_of(~"bool"); - let output_type = build::mk_raw_path(span, ~[ bool_ident ]); - let output_type = ty_path(output_type, cx.next_id()); - let output_type = @ast::Ty { - id: cx.next_id(), - node: output_type, - span: span, - }; - - // Create the function declaration. - let fn_decl = build::mk_fn_decl(~[ arg ], output_type); - - // Create the body block. - let body_block = build::mk_simple_block(cx, span, body); - - // Create the method. - let self_ty = spanned { node: sty_region(None, m_imm), span: span }; - @ast::method { - ident: method_ident, - attrs: ~[], - generics: ast_util::empty_generics(), - self_ty: self_ty, - purity: impure_fn, - decl: fn_decl, - body: body_block, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: public - } -} - -fn create_derived_eq_impl(cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics, - eq_method: @method, - ne_method: @method) - -> @item { - let methods = [ eq_method, ne_method ]; - let trait_path = ~[ - cx.ident_of(~"core"), - cx.ident_of(~"cmp"), - cx.ident_of(~"Eq") - ]; - let trait_path = build::mk_raw_path_global(span, trait_path); - create_derived_impl(cx, span, type_ident, generics, methods, trait_path, opt_vec::Empty, []) -} - -fn call_substructure_eq_method(cx: @ext_ctxt, - span: span, - self_field: @expr, - other_field_ref: @expr, - method_ident: ident, - junction: Junction, - chain_expr: &mut Option<@expr>) { - // Call the substructure method. - let self_call = build::mk_method_call(cx, span, - self_field, method_ident, - ~[ other_field_ref ]); - - // Connect to the outer expression if necessary. - *chain_expr = match *chain_expr { - None => Some(self_call), - Some(copy old_outer_expr) => { - let binop = junction.to_binop(); - let chain_expr = build::mk_binary(cx, - span, - binop, - old_outer_expr, - self_call); - Some(chain_expr) - } - }; -} - -fn finish_eq_chain_expr(cx: @ext_ctxt, - span: span, - chain_expr: Option<@expr>, - junction: Junction) - -> @expr { - match chain_expr { - None => { - match junction { - Conjunction => build::mk_bool(cx, span, true), - Disjunction => build::mk_bool(cx, span, false), - } - } - Some(ref outer_expr) => *outer_expr, - } -} - -fn expand_deriving_eq_struct_def(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics) - -> @item { - // Create the methods. - let eq_ident = cx.ident_of(~"eq"); - let ne_ident = cx.ident_of(~"ne"); - - let derive_struct_fn = if is_struct_tuple(struct_def) { - expand_deriving_eq_struct_tuple_method - } else { - expand_deriving_eq_struct_method - }; - - let eq_method = derive_struct_fn(cx, - span, - struct_def, - eq_ident, - type_ident, - generics, - Conjunction); - let ne_method = derive_struct_fn(cx, - span, - struct_def, - ne_ident, - type_ident, - generics, - Disjunction); - - // Create the implementation. - return create_derived_eq_impl(cx, - span, - type_ident, - generics, - eq_method, - ne_method); -} - -fn expand_deriving_eq_enum_def(cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ident, - generics: &Generics) - -> @item { - // Create the methods. - let eq_ident = cx.ident_of(~"eq"); - let ne_ident = cx.ident_of(~"ne"); - let eq_method = expand_deriving_eq_enum_method(cx, - span, - enum_definition, - eq_ident, - type_ident, - generics, - Conjunction); - let ne_method = expand_deriving_eq_enum_method(cx, - span, - enum_definition, - ne_ident, - type_ident, - generics, - Disjunction); - - // Create the implementation. - return create_derived_eq_impl(cx, - span, - type_ident, - generics, - eq_method, - ne_method); -} - -fn expand_deriving_eq_struct_method(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - method_ident: ident, - type_ident: ident, - generics: &Generics, - junction: Junction) - -> @method { - let self_ident = cx.ident_of(~"self"); - let other_ident = cx.ident_of(~"__other"); - - // Create the body of the method. - let mut outer_expr = None; - for struct_def.fields.each |struct_field| { - match struct_field.node.kind { - named_field(ident, _, _) => { - // Create the accessor for the other field. - let other_field = build::mk_access(cx, - span, - ~[ other_ident ], - ident); - let other_field_ref = build::mk_addr_of(cx, - span, - other_field); - - // Create the accessor for this field. - let self_field = build::mk_access(cx, - span, - ~[ self_ident ], - ident); - - // Call the substructure method. - call_substructure_eq_method(cx, - span, - self_field, - other_field_ref, - method_ident, - junction, - &mut outer_expr); - } - unnamed_field => { - cx.span_unimpl(span, ~"unnamed fields with `deriving(Eq)`"); - } - } - } - - // Create the method itself. - let body = finish_eq_chain_expr(cx, span, outer_expr, junction); - return create_eq_method(cx, - span, - method_ident, - type_ident, - generics, - body); -} - -fn expand_deriving_eq_enum_method(cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - method_ident: ident, - type_ident: ident, - generics: &Generics, - junction: Junction) - -> @method { - let self_ident = cx.ident_of(~"self"); - let other_ident = cx.ident_of(~"__other"); - - let is_eq; - match junction { - Conjunction => is_eq = true, - Disjunction => is_eq = false, - } - - // Create the arms of the self match in the method body. - let mut self_arms = ~[]; - for enum_definition.variants.each |self_variant| { - let mut other_arms = ~[]; - - // Create the matching pattern. - let matching_pat = create_enum_variant_pattern(cx, - span, - self_variant, - ~"__other"); - - // Create the matching pattern body. - let mut matching_body_expr = None; - for uint::range(0, variant_arg_count(cx, span, self_variant)) |i| { - // Create the expression for the other field. - let other_field_ident = cx.ident_of(~"__other_" + i.to_str()); - let other_field = build::mk_path(cx, - span, - ~[ other_field_ident ]); - - // Create the expression for this field. - let self_field_ident = cx.ident_of(~"__self_" + i.to_str()); - let self_field = build::mk_path(cx, span, ~[ self_field_ident ]); - - // Call the substructure method. - call_substructure_eq_method(cx, - span, - self_field, - other_field, - method_ident, - junction, - &mut matching_body_expr); - } - - let matching_body_expr = finish_eq_chain_expr(cx, - span, - matching_body_expr, - junction); - let matching_body_block = build::mk_simple_block(cx, - span, - matching_body_expr); - - // Create the matching arm. - let matching_arm = ast::arm { - pats: ~[ matching_pat ], - guard: None, - body: matching_body_block - }; - other_arms.push(matching_arm); - - // Maybe generate a non-matching case. If there is only one - // variant then there will always be a match. - if enum_definition.variants.len() > 1 { - // Create the nonmatching pattern. - let nonmatching_pat = @ast::pat { - id: cx.next_id(), - node: pat_wild, - span: span - }; - - // Create the nonmatching pattern body. - let nonmatching_expr = build::mk_bool(cx, span, !is_eq); - let nonmatching_body_block = - build::mk_simple_block(cx, - span, - nonmatching_expr); - - // Create the nonmatching arm. - let nonmatching_arm = ast::arm { - pats: ~[ nonmatching_pat ], - guard: None, - body: nonmatching_body_block, - }; - other_arms.push(nonmatching_arm); - } - - // Create the self pattern. - let self_pat = create_enum_variant_pattern(cx, - span, - self_variant, - ~"__self"); - - // Create the self pattern body. - let other_expr = build::mk_path(cx, span, ~[ other_ident ]); - let other_expr = build::mk_unary(cx, span, deref, other_expr); - let other_match_expr = expr_match(other_expr, other_arms); - let other_match_expr = build::mk_expr(cx, - span, - other_match_expr); - let other_match_body_block = build::mk_simple_block(cx, - span, - other_match_expr); - - // Create the self arm. - let self_arm = ast::arm { - pats: ~[ self_pat ], - guard: None, - body: other_match_body_block, - }; - self_arms.push(self_arm); - } - - // Create the method body. - let self_expr = build::mk_path(cx, span, ~[ self_ident ]); - let self_expr = build::mk_unary(cx, span, deref, self_expr); - let self_match_expr = expr_match(self_expr, self_arms); - let self_match_expr = build::mk_expr(cx, span, self_match_expr); - - // Create the method. - return create_eq_method(cx, - span, - method_ident, - type_ident, - generics, - self_match_expr); -} - -fn expand_deriving_eq_struct_tuple_method(cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - method_ident: ident, - type_ident: ident, - generics: &Generics, - junction: Junction) - -> @method { - let self_str = ~"self"; - let other_str = ~"__other"; - let type_path = build::mk_raw_path(span, ~[type_ident]); - let fields = copy struct_def.fields; - - // Create comparison expression, comparing each of the fields - let mut match_body = None; - for fields.eachi |i, _| { - let other_field_ident = cx.ident_of(fmt!("%s_%u", other_str, i)); - let other_field = build::mk_path(cx, span, ~[ other_field_ident ]); - - let self_field_ident = cx.ident_of(fmt!("%s_%u", self_str, i)); - let self_field = build::mk_path(cx, span, ~[ self_field_ident ]); - - call_substructure_eq_method(cx, span, self_field, other_field, - method_ident, junction, &mut match_body); - } - let match_body = finish_eq_chain_expr(cx, span, match_body, junction); - - // Create arm for the '__other' match, containing the comparison expr - let other_subpats = create_subpatterns(cx, span, other_str, fields.len()); - let other_arm = ast::arm { - pats: ~[ build::mk_pat_enum(cx, span, type_path, other_subpats) ], - guard: None, - body: build::mk_simple_block(cx, span, match_body), - }; - - // Create the match on '__other' - let other_expr = build::mk_path(cx, span, ~[ cx.ident_of(other_str) ]); - let other_expr = build::mk_unary(cx, span, deref, other_expr); - let other_match_expr = expr_match(other_expr, ~[other_arm]); - let other_match_expr = build::mk_expr(cx, span, other_match_expr); - - // Create arm for the 'self' match, which contains the '__other' match - let self_subpats = create_subpatterns(cx, span, self_str, fields.len()); - let self_arm = ast::arm { - pats: ~[build::mk_pat_enum(cx, span, type_path, self_subpats)], - guard: None, - body: build::mk_simple_block(cx, span, other_match_expr), - }; - - // Create the match on 'self' - let self_expr = build::mk_path(cx, span, ~[ cx.ident_of(self_str) ]); - let self_expr = build::mk_unary(cx, span, deref, self_expr); - let self_match_expr = expr_match(self_expr, ~[self_arm]); - let self_match_expr = build::mk_expr(cx, span, self_match_expr); - - create_eq_method(cx, span, method_ident, - type_ident, generics, self_match_expr) -} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 1241d4fa71139..78faf5556b2ce 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -30,12 +30,21 @@ use opt_vec; use core::uint; -pub mod eq; pub mod clone; pub mod iter_bytes; pub mod encodable; pub mod decodable; +#[path="cmp/eq.rs"] +pub mod eq; +#[path="cmp/totaleq.rs"] +pub mod totaleq; +#[path="cmp/ord.rs"] +pub mod ord; +#[path="cmp/totalord.rs"] +pub mod totalord; + + pub mod generic; pub type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, @@ -74,8 +83,6 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, meta_list(tname, _) | meta_word(tname) => { match *tname { - ~"Eq" => eq::expand_deriving_eq(cx, titem.span, - titem, in_items), ~"Clone" => clone::expand_deriving_clone(cx, titem.span, titem, in_items), ~"IterBytes" => iter_bytes::expand_deriving_iter_bytes(cx, @@ -84,6 +91,14 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, titem.span, titem, in_items), ~"Decodable" => decodable::expand_deriving_decodable(cx, titem.span, titem, in_items), + ~"Eq" => eq::expand_deriving_eq(cx, titem.span, + titem, in_items), + ~"TotalEq" => totaleq::expand_deriving_totaleq(cx, titem.span, + titem, in_items), + ~"Ord" => ord::expand_deriving_ord(cx, titem.span, + titem, in_items), + ~"TotalOrd" => totalord::expand_deriving_totalord(cx, titem.span, + titem, in_items), tname => { cx.span_err(titem.span, fmt!("unknown \ `deriving` trait: `%s`", tname)); From 99492796dcaac41966dc54f7ab4b8e33e641bb73 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 31 Mar 2013 02:01:44 +1100 Subject: [PATCH 157/403] testsuite: add tests for derived Eq, TotalEq, Ord, TotalOrd. --- src/test/run-pass/deriving-cmp.rs | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/test/run-pass/deriving-cmp.rs diff --git a/src/test/run-pass/deriving-cmp.rs b/src/test/run-pass/deriving-cmp.rs new file mode 100644 index 0000000000000..56968fc12100f --- /dev/null +++ b/src/test/run-pass/deriving-cmp.rs @@ -0,0 +1,75 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +struct S { + x: T, + y: T +} + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +struct TS(T,T); + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +enum E { + E0, + E1(T), + E2(T,T) +} + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +enum ES { + ES1 { x: T }, + ES2 { x: T, y: T } +} + + +pub fn main() { + let s1 = S {x: 1, y: 1}, s2 = S {x: 1, y: 2}; + let ts1 = TS(1, 1), ts2 = TS(1,2); + let e0 = E0, e11 = E1(1), e12 = E1(2), e21 = E2(1,1), e22 = E2(1, 2); + let es11 = ES1 {x: 1}, es12 = ES1 {x: 2}, es21 = ES2 {x: 1, y: 1}, es22 = ES2 {x: 1, y: 2}; + + test([s1, s2]); + test([ts1, ts2]); + test([e0, e11, e12, e21, e22]); + test([es11, es12, es21, es22]); +} + +fn test(ts: &[T]) { + // compare each element against all other elements. The list + // should be in sorted order, so that if i < j, then ts[i] < + // ts[j], etc. + for ts.eachi |i, t1| { + for ts.eachi |j, t2| { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j, le = i <= j; + let gt = i > j, ge = i >= j; + + // Eq + assert_eq!(*t1 == *t2, eq); + + // TotalEq + assert_eq!(t1.equals(t2), eq); + + // Ord + assert_eq!(*t1 < *t2, lt); + assert_eq!(*t1 > *t2, gt); + + assert_eq!(*t1 <= *t2, le); + assert_eq!(*t1 >= *t2, ge); + + // TotalOrd + assert_eq!(t1.cmp(t2), ord); + } + } +} \ No newline at end of file From bff374873136bacf8352e05f73cb3252761dc2d6 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 2 Apr 2013 22:02:46 +1100 Subject: [PATCH 158/403] libsyntax: short-circuit on non-matching variants in deriving code. Allow a deriving instance using the generic code to short-circuit for any non-matching enum variants (grouping them all into a _ match), reducing the number of arms required. Use this to speed up the Eq & TotalEq implementations. --- src/libsyntax/ext/deriving/clone.rs | 1 + src/libsyntax/ext/deriving/cmp/eq.rs | 26 +-- src/libsyntax/ext/deriving/cmp/ord.rs | 42 ++--- src/libsyntax/ext/deriving/cmp/totaleq.rs | 1 + src/libsyntax/ext/deriving/cmp/totalord.rs | 1 + src/libsyntax/ext/deriving/generic.rs | 161 +++++++++++++----- .../run-pass/deriving-cmp-generic-enum.rs | 50 ++++++ .../deriving-cmp-generic-struct-enum.rs | 52 ++++++ .../run-pass/deriving-cmp-generic-struct.rs | 49 ++++++ .../deriving-cmp-generic-tuple-struct.rs | 47 +++++ src/test/run-pass/deriving-cmp.rs | 75 -------- 11 files changed, 349 insertions(+), 156 deletions(-) create mode 100644 src/test/run-pass/deriving-cmp-generic-enum.rs create mode 100644 src/test/run-pass/deriving-cmp-generic-struct-enum.rs create mode 100644 src/test/run-pass/deriving-cmp-generic-struct.rs create mode 100644 src/test/run-pass/deriving-cmp-generic-tuple-struct.rs delete mode 100644 src/test/run-pass/deriving-cmp.rs diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 0c62566702d90..d996bca60a367 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -29,6 +29,7 @@ pub fn expand_deriving_clone(cx: @ext_ctxt, name: ~"clone", nargs: 0, output_type: None, // return Self + const_nonmatching: false, combine_substructure: cs_clone } ] diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 142f0565e149e..c0060cc67dc33 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -31,24 +31,24 @@ pub fn expand_deriving_eq(cx: @ext_ctxt, cs_or(|cx, span, _| build::mk_bool(cx, span, true), cx, span, substr) } - + macro_rules! md ( + ($name:expr, $f:ident) => { + MethodDef { + name: $name, + output_type: Some(~[~"bool"]), + nargs: 1, + const_nonmatching: true, + combine_substructure: $f + }, + } + ) let trait_def = TraitDef { path: ~[~"core", ~"cmp", ~"Eq"], additional_bounds: ~[], methods: ~[ - MethodDef { - name: ~"ne", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: cs_ne - }, - MethodDef { - name: ~"eq", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: cs_eq - } + md!(~"eq", cs_eq), + md!(~"ne", cs_ne) ] }; diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 7f7babab45cc4..398e27eb3e385 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -16,10 +16,16 @@ use ext::build; use ext::deriving::generic::*; use core::option::Some; -macro_rules! mk_cso { - ($less:expr, $equal:expr) => { - |cx, span, substr| - cs_ord($less, $equal, cx, span, substr) +macro_rules! md { + ($name:expr, $less:expr, $equal:expr) => { + MethodDef { + name: $name, + output_type: Some(~[~"bool"]), + nargs: 1, + const_nonmatching: false, + combine_substructure: |cx, span, substr| + cs_ord($less, $equal, cx, span, substr) + } } } @@ -32,30 +38,10 @@ pub fn expand_deriving_ord(cx: @ext_ctxt, // XXX: Ord doesn't imply Eq yet additional_bounds: ~[~[~"core", ~"cmp", ~"Eq"]], methods: ~[ - MethodDef { - name: ~"lt", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: mk_cso!(true, false) - }, - MethodDef { - name: ~"le", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: mk_cso!(true, true) - }, - MethodDef { - name: ~"gt", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: mk_cso!(false, false) - }, - MethodDef { - name: ~"ge", - output_type: Some(~[~"bool"]), - nargs: 1, - combine_substructure: mk_cso!(false, true) - }, + md!(~"lt", true, false), + md!(~"le", true, true), + md!(~"gt", false, false), + md!(~"ge", false, true) ] }; diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index d71db22591dd6..fc8ec103a6021 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -35,6 +35,7 @@ pub fn expand_deriving_totaleq(cx: @ext_ctxt, name: ~"equals", output_type: Some(~[~"bool"]), nargs: 1, + const_nonmatching: true, combine_substructure: cs_equals } ] diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index d82c63e9dd343..9c20a0be87c24 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -28,6 +28,7 @@ pub fn expand_deriving_totalord(cx: @ext_ctxt, name: ~"cmp", output_type: Some(~[~"core", ~"cmp", ~"Ordering"]), nargs: 1, + const_nonmatching: false, combine_substructure: cs_cmp } ] diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 23a075ef001f6..8fe2ca1a1a107 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -40,7 +40,8 @@ arguments: - `EnumMatching`, when `Self` is an enum and all the arguments are the same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`) - `EnumNonMatching` when `Self` is an enum and the arguments are not - the same variant (e.g. `None`, `Some(1)` and `None`) + the same variant (e.g. `None`, `Some(1)` and `None`). If + `const_nonmatching` is true, this will contain an empty list. In the first two cases, the values from the corresponding fields in all the arguments are grouped together. In the `EnumNonMatching` case @@ -129,9 +130,11 @@ use core::prelude::*; use ast; use ast::{ + and, binop, deref, enum_def, expr, expr_match, ident, impure_fn, - item, Generics, m_imm, meta_item, method, named_field, or, public, - struct_def, sty_region, ty_rptr, ty_path, variant}; + item, Generics, m_imm, meta_item, method, named_field, or, + pat_wild, public, struct_def, sty_region, ty_rptr, ty_path, + variant}; use ast_util; use ext::base::ext_ctxt; @@ -177,6 +180,10 @@ pub struct MethodDef<'self> { /// Number of arguments other than `self` (all of type `&Self`) nargs: uint, + /// if the value of the nonmatching enums is independent of the + /// actual enums, i.e. can use _ => .. match. + const_nonmatching: bool, + combine_substructure: CombineSubstructureFunc<'self> } @@ -555,12 +562,13 @@ impl<'self> MethodDef<'self> { enum_def: &enum_def, type_ident: ident) -> @expr { - self.build_enum_match(cx, span, enum_def, type_ident, ~[]) + self.build_enum_match(cx, span, enum_def, type_ident, + None, ~[], 0) } /** - Creates the nested matches for an enum definition, i.e. + Creates the nested matches for an enum definition recursively, i.e. ``` match self { @@ -575,14 +583,20 @@ impl<'self> MethodDef<'self> { the tree are the same. Hopefully the optimisers get rid of any repetition, otherwise derived methods with many Self arguments will be exponentially large. + + `matching` is Some(n) if all branches in the tree above the + current position are variant `n`, `None` otherwise (including on + the first call). */ fn build_enum_match(&self, cx: @ext_ctxt, span: span, enum_def: &enum_def, type_ident: ident, + matching: Option, matches_so_far: ~[(uint, variant, - ~[(Option, @expr)])]) -> @expr { - if matches_so_far.len() == self.nargs + 1 { + ~[(Option, @expr)])], + match_count: uint) -> @expr { + if match_count == self.nargs + 1 { // we've matched against all arguments, so make the final // expression at the bottom of the match tree match matches_so_far { @@ -594,41 +608,44 @@ impl<'self> MethodDef<'self> { // vec of tuples, where each tuple represents a // field. - // `ref` inside let matches is buggy. Causes havoc wih rusc. - // let (variant_index, ref self_vec) = matches_so_far[0]; - let (variant_index, variant, self_vec) = match matches_so_far[0] { - (i, v, ref s) => (i, v, s) - }; - let substructure; // most arms don't have matching variants, so do a // quick check to see if they match (even though // this means iterating twice) instead of being // optimistic and doing a pile of allocations etc. - if matches_so_far.all(|&(v_i, _, _)| v_i == variant_index) { - let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]); - - for matches_so_far.tail().each |&(_, _, other_fields)| { - for other_fields.eachi |i, &(_, other_field)| { - enum_matching_fields[i].push(other_field); + match matching { + Some(variant_index) => { + // `ref` inside let matches is buggy. Causes havoc wih rusc. + // let (variant_index, ref self_vec) = matches_so_far[0]; + let (variant, self_vec) = match matches_so_far[0] { + (_, v, ref s) => (v, s) + }; + + let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]); + + for matches_so_far.tail().each |&(_, _, other_fields)| { + for other_fields.eachi |i, &(_, other_field)| { + enum_matching_fields[i].push(other_field); + } } + let field_tuples = + do vec::map2(*self_vec, + enum_matching_fields) |&(id, self_f), &other| { + (id, self_f, other) + }; + substructure = EnumMatching(variant_index, variant, field_tuples); + } + None => { + substructure = EnumNonMatching(matches_so_far); } - let field_tuples = - do vec::map2(*self_vec, - enum_matching_fields) |&(id, self_f), &other| { - (id, self_f, other) - }; - substructure = EnumMatching(variant_index, variant, field_tuples); - } else { - substructure = EnumNonMatching(matches_so_far); } self.call_substructure_method(cx, span, type_ident, &substructure) } } } else { // there are still matches to create - let (current_match_ident, current_match_str) = if matches_so_far.is_empty() { + let (current_match_ident, current_match_str) = if match_count == 0 { (cx.ident_of(~"self"), ~"__self") } else { let s = fmt!("__other_%u", matches_so_far.len() - 1); @@ -640,8 +657,32 @@ impl<'self> MethodDef<'self> { // this is used as a stack let mut matches_so_far = matches_so_far; - // create an arm matching on each variant - for enum_def.variants.eachi |index, variant| { + macro_rules! mk_arm( + ($pat:expr, $expr:expr) => { + { + let blk = build::mk_simple_block(cx, span, $expr); + let arm = ast::arm { + pats: ~[$ pat ], + guard: None, + body: blk + }; + arm + } + } + ) + + // the code for nonmatching variants only matters when + // we've seen at least one other variant already + if self.const_nonmatching && match_count > 0 { + // make a matching-variant match, and a _ match. + let index = match matching { + Some(i) => i, + None => cx.span_bug(span, ~"Non-matching variants when required to\ + be matching in `deriving_generic`") + }; + + // matching-variant match + let variant = &enum_def.variants[index]; let pattern = create_enum_variant_pattern(cx, span, variant, current_match_str); @@ -653,23 +694,63 @@ impl<'self> MethodDef<'self> { } }; - matches_so_far.push((index, *variant, idents)); let arm_expr = self.build_enum_match(cx, span, enum_def, type_ident, - matches_so_far); + matching, + matches_so_far, + match_count + 1); matches_so_far.pop(); - - let arm_block = build::mk_simple_block(cx, span, arm_expr); - let arm = ast::arm { - pats: ~[ pattern ], - guard: None, - body: arm_block - }; + let arm = mk_arm!(pattern, arm_expr); arms.push(arm); - } + if enum_def.variants.len() > 1 { + // _ match, if necessary + let wild_pat = @ast::pat { + id: cx.next_id(), + node: pat_wild, + span: span + }; + + let wild_expr = self.call_substructure_method(cx, span, type_ident, + &EnumNonMatching(~[])); + let wild_arm = mk_arm!(wild_pat, wild_expr); + arms.push(wild_arm); + } + } else { + // create an arm matching on each variant + for enum_def.variants.eachi |index, variant| { + let pattern = create_enum_variant_pattern(cx, span, + variant, + current_match_str); + + let idents = do vec::build |push| { + for each_variant_arg_ident(cx, span, variant) |i, field_id| { + let id = cx.ident_of(fmt!("%s_%u", current_match_str, i)); + push((field_id, build::mk_path(cx, span, ~[ id ]))); + } + }; + + matches_so_far.push((index, *variant, idents)); + let new_matching = + match matching { + _ if match_count == 0 => Some(index), + Some(i) if index == i => Some(i), + _ => None + }; + let arm_expr = self.build_enum_match(cx, span, + enum_def, + type_ident, + new_matching, + matches_so_far, + match_count + 1); + matches_so_far.pop(); + + let arm = mk_arm!(pattern, arm_expr); + arms.push(arm); + } + } let deref_expr = build::mk_unary(cx, span, deref, build::mk_path(cx, span, ~[ current_match_ident ])); diff --git a/src/test/run-pass/deriving-cmp-generic-enum.rs b/src/test/run-pass/deriving-cmp-generic-enum.rs new file mode 100644 index 0000000000000..a2651ddac3d19 --- /dev/null +++ b/src/test/run-pass/deriving-cmp-generic-enum.rs @@ -0,0 +1,50 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +enum E { + E0, + E1(T), + E2(T,T) +} + +pub fn main() { + let e0 = E0, e11 = E1(1), e12 = E1(2), e21 = E2(1,1), e22 = E2(1, 2); + + // in order for both Ord and TotalOrd + let es = [e0, e11, e12, e21, e22]; + + for es.eachi |i, e1| { + for es.eachi |j, e2| { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j, le = i <= j; + let gt = i > j, ge = i >= j; + + // Eq + assert_eq!(*e1 == *e2, eq); + assert_eq!(*e1 != *e2, !eq); + + // TotalEq + assert_eq!(e1.equals(e2), eq); + + // Ord + assert_eq!(*e1 < *e2, lt); + assert_eq!(*e1 > *e2, gt); + + assert_eq!(*e1 <= *e2, le); + assert_eq!(*e1 >= *e2, ge); + + // TotalOrd + assert_eq!(e1.cmp(e2), ord); + } + } +} diff --git a/src/test/run-pass/deriving-cmp-generic-struct-enum.rs b/src/test/run-pass/deriving-cmp-generic-struct-enum.rs new file mode 100644 index 0000000000000..6f6e8d79d8b92 --- /dev/null +++ b/src/test/run-pass/deriving-cmp-generic-struct-enum.rs @@ -0,0 +1,52 @@ +// xfail-test #5530 + +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +enum ES { + ES1 { x: T }, + ES2 { x: T, y: T } +} + + +pub fn main() { + let es11 = ES1 {x: 1}, es12 = ES1 {x: 2}, es21 = ES2 {x: 1, y: 1}, es22 = ES2 {x: 1, y: 2}; + + // in order for both Ord and TotalOrd + let ess = [es11, es12, es21, es22]; + + for ess.eachi |i, es1| { + for ess.eachi |j, es2| { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j, le = i <= j; + let gt = i > j, ge = i >= j; + + // Eq + assert_eq!(*es1 == *es2, eq); + assert_eq!(*es1 != *es2, !eq); + + // TotalEq + assert_eq!(es1.equals(es2), eq); + + // Ord + assert_eq!(*es1 < *es2, lt); + assert_eq!(*es1 > *es2, gt); + + assert_eq!(*es1 <= *es2, le); + assert_eq!(*es1 >= *es2, ge); + + // TotalOrd + assert_eq!(es1.cmp(es2), ord); + } + } +} \ No newline at end of file diff --git a/src/test/run-pass/deriving-cmp-generic-struct.rs b/src/test/run-pass/deriving-cmp-generic-struct.rs new file mode 100644 index 0000000000000..bd3e02ba29b30 --- /dev/null +++ b/src/test/run-pass/deriving-cmp-generic-struct.rs @@ -0,0 +1,49 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +struct S { + x: T, + y: T +} + +pub fn main() { + let s1 = S {x: 1, y: 1}, s2 = S {x: 1, y: 2}; + + // in order for both Ord and TotalOrd + let ss = [s1, s2]; + + for ss.eachi |i, s1| { + for ss.eachi |j, s2| { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j, le = i <= j; + let gt = i > j, ge = i >= j; + + // Eq + assert_eq!(*s1 == *s2, eq); + assert_eq!(*s1 != *s2, !eq); + + // TotalEq + assert_eq!(s1.equals(s2), eq); + + // Ord + assert_eq!(*s1 < *s2, lt); + assert_eq!(*s1 > *s2, gt); + + assert_eq!(*s1 <= *s2, le); + assert_eq!(*s1 >= *s2, ge); + + // TotalOrd + assert_eq!(s1.cmp(s2), ord); + } + } +} \ No newline at end of file diff --git a/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs new file mode 100644 index 0000000000000..733b19a9ae2da --- /dev/null +++ b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs @@ -0,0 +1,47 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Eq, TotalEq, Ord, TotalOrd)] +struct TS(T,T); + + +pub fn main() { + let ts1 = TS(1, 1), ts2 = TS(1,2); + + // in order for both Ord and TotalOrd + let tss = [ts1, ts2]; + + for tss.eachi |i, ts1| { + for tss.eachi |j, ts2| { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j, le = i <= j; + let gt = i > j, ge = i >= j; + + // Eq + assert_eq!(*ts1 == *ts2, eq); + assert_eq!(*ts1 != *ts2, !eq); + + // TotalEq + assert_eq!(ts1.equals(ts2), eq); + + // Ord + assert_eq!(*ts1 < *ts2, lt); + assert_eq!(*ts1 > *ts2, gt); + + assert_eq!(*ts1 <= *ts2, le); + assert_eq!(*ts1 >= *ts2, ge); + + // TotalOrd + assert_eq!(ts1.cmp(ts2), ord); + } + } +} \ No newline at end of file diff --git a/src/test/run-pass/deriving-cmp.rs b/src/test/run-pass/deriving-cmp.rs deleted file mode 100644 index 56968fc12100f..0000000000000 --- a/src/test/run-pass/deriving-cmp.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -struct S { - x: T, - y: T -} - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -struct TS(T,T); - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -enum E { - E0, - E1(T), - E2(T,T) -} - -#[deriving(Eq, TotalEq, Ord, TotalOrd)] -enum ES { - ES1 { x: T }, - ES2 { x: T, y: T } -} - - -pub fn main() { - let s1 = S {x: 1, y: 1}, s2 = S {x: 1, y: 2}; - let ts1 = TS(1, 1), ts2 = TS(1,2); - let e0 = E0, e11 = E1(1), e12 = E1(2), e21 = E2(1,1), e22 = E2(1, 2); - let es11 = ES1 {x: 1}, es12 = ES1 {x: 2}, es21 = ES2 {x: 1, y: 1}, es22 = ES2 {x: 1, y: 2}; - - test([s1, s2]); - test([ts1, ts2]); - test([e0, e11, e12, e21, e22]); - test([es11, es12, es21, es22]); -} - -fn test(ts: &[T]) { - // compare each element against all other elements. The list - // should be in sorted order, so that if i < j, then ts[i] < - // ts[j], etc. - for ts.eachi |i, t1| { - for ts.eachi |j, t2| { - let ord = i.cmp(&j); - - let eq = i == j; - let lt = i < j, le = i <= j; - let gt = i > j, ge = i >= j; - - // Eq - assert_eq!(*t1 == *t2, eq); - - // TotalEq - assert_eq!(t1.equals(t2), eq); - - // Ord - assert_eq!(*t1 < *t2, lt); - assert_eq!(*t1 > *t2, gt); - - assert_eq!(*t1 <= *t2, le); - assert_eq!(*t1 >= *t2, ge); - - // TotalOrd - assert_eq!(t1.cmp(t2), ord); - } - } -} \ No newline at end of file From a4db39a6fe89e243230a4b7a8601b964e037bb5a Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 12 Apr 2013 03:14:26 -0400 Subject: [PATCH 159/403] tutorial-ffi: add missing word --- doc/tutorial-ffi.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index fc62fafa70090..c86024d75eac1 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -65,8 +65,8 @@ extern { # Creating a safe interface -The raw C API needs to be wrapped to provide memory safety and make use higher-level concepts like -vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe +The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts +like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe internal details. Wrapping the functions which expect buffers involves using the `vec::raw` module to manipulate Rust From 35c73c80887cca62f8bba2eb9b9e277a98c37f93 Mon Sep 17 00:00:00 2001 From: James Miller Date: Fri, 12 Apr 2013 20:59:46 +1200 Subject: [PATCH 160/403] Added xfail-fast to test so the windows buildbot doesn't choke --- src/test/run-pass/attr-start.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-pass/attr-start.rs b/src/test/run-pass/attr-start.rs index efbd7da4797e1..933405bfc448d 100644 --- a/src/test/run-pass/attr-start.rs +++ b/src/test/run-pass/attr-start.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//xfail-fast + #[start] fn start(argc:int, argv: **u8, crate_map: *u8) -> int { return 0; From ea9bdaaed9e4cb91cb8dfc96d0ce2dab10eae1d2 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 12 Apr 2013 19:00:53 +1000 Subject: [PATCH 161/403] libsyntax: (maybe) fix deriving(TotalOrd) on windows --- src/libsyntax/ext/deriving/cmp/totalord.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 9c20a0be87c24..a098a7463d3e7 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -45,10 +45,10 @@ pub fn ordering_const(cx: @ext_ctxt, span: span, cnst: Ordering) -> @expr { Equal => ~"Equal", Greater => ~"Greater" }; - build::mk_path(cx, span, - ~[cx.ident_of(~"core"), - cx.ident_of(~"cmp"), - cx.ident_of(cnst)]) + build::mk_path_global(cx, span, + ~[cx.ident_of(~"core"), + cx.ident_of(~"cmp"), + cx.ident_of(cnst)]) } pub fn cs_cmp(cx: @ext_ctxt, span: span, @@ -61,7 +61,7 @@ pub fn cs_cmp(cx: @ext_ctxt, span: span, // foldr (possibly) nests the matches in lexical_ordering better false, |cx, span, old, new| { - build::mk_call(cx, span, lexical_ord, ~[old, new]) + build::mk_call_global(cx, span, lexical_ord, ~[old, new]) }, ordering_const(cx, span, Equal), |cx, span, list| { @@ -70,7 +70,7 @@ pub fn cs_cmp(cx: @ext_ctxt, span: span, // later one [(self_var, _, _), (other_var, _, _)] => ordering_const(cx, span, - self_var.cmp(&other_var)), + self_var.cmp(&other_var)), _ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`") } }, From 5c376e53d0febb493bcb7de21564d6f60a6da514 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 12 Apr 2013 20:19:11 +1000 Subject: [PATCH 162/403] libsyntax: another fix for deriving on windows. --- src/libsyntax/ext/deriving/generic.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 8fe2ca1a1a107..dfbb98fa23388 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -130,7 +130,6 @@ use core::prelude::*; use ast; use ast::{ - and, binop, deref, enum_def, expr, expr_match, ident, impure_fn, item, Generics, m_imm, meta_item, method, named_field, or, pat_wild, public, struct_def, sty_region, ty_rptr, ty_path, @@ -328,7 +327,7 @@ impl<'self> MethodDef<'self> { } Some(str_path) => { let p = do str_path.map |&s| { cx.ident_of(s) }; - build::mk_raw_path(span, p) + build::mk_raw_path_global(span, p) } } } From 53d2228b37c86ba671cf0029b90c0b349266bc5e Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 12 Apr 2013 06:31:54 -0400 Subject: [PATCH 163/403] tutorial-ffi: add another missing word --- doc/tutorial-ffi.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index fc62fafa70090..61ecc209cac80 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -186,10 +186,11 @@ A `#[packed]` attribute is available, which will lay out the struct members with However, there are currently no guarantees about the layout of an `enum`. Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained -object. However, they should not be manually because they are managed by internal allocators. -Borrowed pointers can safely be assumed to be non-nullable pointers directly to the type. However, -breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer using raw -pointers (`*`) if that's needed because the compiler can't make as many assumptions about them. +object. However, they should not be manually created because they are managed by internal +allocators. Borrowed pointers can safely be assumed to be non-nullable pointers directly to the +type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so +prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions +about them. Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and `str` modules for working with C APIs. Strings are terminated with `\0` for interoperability with C, From 2ec2d99bbd1a15a8f278b3cb82ddfa9ebafa96b3 Mon Sep 17 00:00:00 2001 From: Leah Hanson Date: Fri, 12 Apr 2013 09:41:07 -0400 Subject: [PATCH 164/403] add rustdoc comments with examples for the string versions of to_base64 and from_base64 --- src/libstd/base64.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 0266f2d8631cf..0815e0ff0b502 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -75,6 +75,23 @@ impl<'self> ToBase64 for &'self [u8] { } } +/** + * Convert any string (literal, `@`, `&`, `~`) to base64 encoding. + * + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * + * fn main () { + * let str = "Hello, World".to_base64(); + * println(fmt!("%s",str)); + * } + * ~~~~ + * + */ impl<'self> ToBase64 for &'self str { fn to_base64(&self) -> ~str { str::to_bytes(*self).to_base64() @@ -147,6 +164,34 @@ impl FromBase64 for ~[u8] { } } +/** + * Convert any string (literal, `@`, `&`, `~`) + * that contains a base64 encoded value, to the byte values it encodes. + * + * You can use the `from_bytes` function in `core::str` + * to turn a `[u8]` into a string with characters corresponding to those values. + * + * *Example*: + * + * This is an example of going from a string literal to the base64 encoding + * and back to the same string. + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * use std::base64::FromBase64; + * use core::str; + * + * fn main () { + * let hello_str = "Hello, World".to_base64(); + * println(fmt!("%s",hello_str)); + * let bytes = hello_str.from_base64(); + * println(fmt!("%?",bytes)); + * let result_str = str::from_bytes(bytes); + * println(fmt!("%s",result_str)); + * } + * ~~~~ + */ impl FromBase64 for ~str { fn from_base64(&self) -> ~[u8] { str::to_bytes(*self).from_base64() From 74fee15bc1b6c3c558bab72a644b2600c91d0d2d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Apr 2013 12:49:11 -0700 Subject: [PATCH 165/403] Tidy --- src/librustpkg/rustpkg.rc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 24c37d2558951..399fcec680401 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -162,7 +162,6 @@ struct Ctx { fn dest_dir(pkgid: PkgId) -> Path { default_dest_dir(&pkgid.path).expect( ~"couldn't make default dir?!") - } /// Returns the default output directory for compilation. @@ -339,23 +338,21 @@ impl Ctx { // Always use the "build" subdirectory of the package dir, // but we should allow this to be configured let dst_dir = dest_dir(pkgid); - + let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid); - match src.package_script_option(cwd) { Some(script_path) => { let script = PkgScript::parse(script_path, pkgid); let (_, status) = script.run_custom(cmd); // Ignore cfgs? if status == 42 { // ??? util::error(~"no fns are listening for that cmd"); - return false; } - status == 0 } None => { - util::error(fmt!("invoked `do`, but there is no package script in %s", cwd.to_str())); + util::error(fmt!("invoked `do`, but there is no package script in %s", + cwd.to_str())); false } } @@ -929,8 +926,8 @@ impl PkgSrc { dst_dir, crate.flags, crate.cfgs + cfgs, - false, test); - if !result { + false, test); + if !result { build_err::cond.raise(fmt!("build failure on %s", path.to_str())); } From 884c7c9326a2f6042b4343d41c4fa10fa7740ee2 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 12 Apr 2013 16:15:40 -0700 Subject: [PATCH 166/403] rustpkg: Factor out tests; use a condition instead of returning an option Pulled out tests into their own modules inside the files they test, as per the draft style guidelines. Started a new module, path_util, for utility functions to do with paths and directories. Changed default_dest_dir to use a condition and return Path instead of Option. --- src/librustpkg/conditions.rs | 17 ++++++++ src/librustpkg/path_util.rs | 83 ++++++++++++++++++++++++++++++++++++ src/librustpkg/rustpkg.rc | 51 +++------------------- src/librustpkg/tests.rs | 11 +++++ src/librustpkg/util.rs | 39 +++++++++-------- 5 files changed, 138 insertions(+), 63 deletions(-) create mode 100644 src/librustpkg/conditions.rs create mode 100644 src/librustpkg/path_util.rs create mode 100644 src/librustpkg/tests.rs diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs new file mode 100644 index 0000000000000..353995a816e37 --- /dev/null +++ b/src/librustpkg/conditions.rs @@ -0,0 +1,17 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Useful conditions + +pub use core::path::Path; + +condition! { + bad_path: (super::Path, ~str) -> super::Path; +} diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs new file mode 100644 index 0000000000000..c77106a9a39cb --- /dev/null +++ b/src/librustpkg/path_util.rs @@ -0,0 +1,83 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg utilities having to do with paths and directories + +use core::path::*; +use core::os; +use util::PkgId; + +/// Returns the output directory to use. +/// Right now is always the default, should +/// support changing it. +pub fn dest_dir(pkgid: PkgId) -> Path { + default_dest_dir(&pkgid.path) +} + +/// Returns the default output directory for compilation. +/// Creates that directory if it doesn't exist. +pub fn default_dest_dir(pkg_dir: &Path) -> Path { + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + use conditions::bad_path::cond; + + // For now: assumes that pkg_dir exists and is relative + // to the CWD. Change this later when we do path searching. + let rslt = pkg_dir.push("build"); + let is_dir = os::path_is_dir(&rslt); + if os::path_exists(&rslt) { + if is_dir { + rslt + } + else { + cond.raise((rslt, ~"Path names a file that isn't a directory")) + } + } + else { + // Create it + if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { + rslt + } + else { + cond.raise((rslt, ~"Could not create directory")) + } + } +} + +#[cfg(test)] +mod test { + use core::{os, rand}; + use core::path::Path; + use core::rand::RngUtil; + use path_util::*; + + // Helper function to create a directory name that doesn't exist + pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { + let r = rand::Rng(); + for 1000.times { + let p = tmpdir.push(r.gen_str(16) + suffix); + if !os::path_exists(&p) { + return p; + } + } + fail!(~"Couldn't compute a non-existent path name; this is worrisome") + } + + #[test] + fn default_dir_ok() { + let the_path = os::tmpdir(); + let substitute_path = Path("xyzzy"); + assert!(default_dest_dir(&the_path) == the_path.push(~"build")); + let nonexistent_path = mk_nonexistent(&the_path, "quux"); + let bogus = do ::conditions::bad_path::cond.trap(|_| { + substitute_path + }).in { default_dest_dir(&nonexistent_path) }; + assert!(bogus == substitute_path); + } +} \ No newline at end of file diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 399fcec680401..d61fe30992d85 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// rustpkg - a purely function package manager and build system +// rustpkg - a package manager and build system for Rust #[link(name = "rustpkg", vers = "0.6", @@ -37,8 +37,11 @@ use std::net::url; use std::{getopts}; use syntax::{ast, diagnostic}; use util::{ExitCode, Pkg, PkgId}; +use path_util::dest_dir; +mod conditions; mod usage; +mod path_util; mod util; /// A PkgScript represents user-supplied custom logic for @@ -155,46 +158,6 @@ struct Ctx { dep_cache: @mut HashMap<~str, bool>, } - -/// Returns the output directory to use. -/// Right now is always the default, should -/// support changing it. -fn dest_dir(pkgid: PkgId) -> Path { - default_dest_dir(&pkgid.path).expect( - ~"couldn't make default dir?!") -} - -/// Returns the default output directory for compilation. -/// Creates that directory if it doesn't exist. -fn default_dest_dir(pkg_dir: &Path) -> Option { - use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; - - // For now: assumes that pkg_dir exists and is relative - // to the CWD. Change this later when we do path searching. - let rslt = pkg_dir.push("build"); - let is_dir = os::path_is_dir(&rslt); - if os::path_exists(&rslt) { - if is_dir { - Some(rslt) - } - else { - util::error(fmt!("%s is not a directory", rslt.to_str())); - None - } - } - else { - // Create it - if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { - Some(rslt) - } - else { - util::error(fmt!("Could not create directory %s", - rslt.to_str())); - None // ??? should probably use conditions - } - } -} - impl Ctx { fn run(&self, cmd: ~str, args: ~[~str]) { @@ -759,10 +722,6 @@ pub struct PkgSrc { benchs: ~[Crate], } -condition! { - bad_path: (super::Path, ~str) -> super::Path; -} - condition! { build_err: (~str) -> (); } @@ -785,7 +744,7 @@ impl PkgSrc { fn check_dir(&self) -> Path { - use bad_path::cond; + use conditions::bad_path::cond; debug!("Pushing onto root: %s | %s", self.id.path.to_str(), self.root.to_str()); diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs new file mode 100644 index 0000000000000..f594860607255 --- /dev/null +++ b/src/librustpkg/tests.rs @@ -0,0 +1,11 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg unit tests diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 819823e87447c..602c71cf8be96 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -563,21 +563,26 @@ pub fn link_exe(src: &Path, dest: &Path) -> bool { } } -#[test] -fn test_is_cmd() { - assert!(is_cmd(~"build")); - assert!(is_cmd(~"clean")); - assert!(is_cmd(~"do")); - assert!(is_cmd(~"info")); - assert!(is_cmd(~"install")); - assert!(is_cmd(~"prefer")); - assert!(is_cmd(~"test")); - assert!(is_cmd(~"uninstall")); - assert!(is_cmd(~"unprefer")); -} - -#[test] -fn test_parse_name() { - assert!(parse_name(~"org.mozilla.servo").get() == ~"servo"); - assert!(parse_name(~"org. mozilla.servo 2131").is_err()); +#[cfg(test)] +mod test { + use super::{is_cmd, parse_name}; + + #[test] + fn test_is_cmd() { + assert!(is_cmd(~"build")); + assert!(is_cmd(~"clean")); + assert!(is_cmd(~"do")); + assert!(is_cmd(~"info")); + assert!(is_cmd(~"install")); + assert!(is_cmd(~"prefer")); + assert!(is_cmd(~"test")); + assert!(is_cmd(~"uninstall")); + assert!(is_cmd(~"unprefer")); + } + + #[test] + fn test_parse_name() { + assert!(parse_name(~"org.mozilla.servo").get() == ~"servo"); + assert!(parse_name(~"org. mozilla.servo 2131").is_err()); + } } From 42b4b6771dfbcafb5f0b13e18f4a57aaeb47cf23 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 13 Apr 2013 00:24:08 +1000 Subject: [PATCH 167/403] Add some more generated files to the .gitignore file --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 83d6186c9e19b..b48c5de8931a8 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,8 @@ .valgrindrc lexer.ml TAGS +TAGS.emacs +TAGS.vim version.ml version.texi /Makefile @@ -60,6 +62,7 @@ config.mk /inst/ /mingw-build/ src/.DS_Store +/tmp/ /stage0/ /dl/ /stage1/ @@ -75,6 +78,8 @@ version.md rust.tex keywords.md x86_64-apple-darwin/ +x86_64-unknown-linux-gnu/ +i686-unknown-linux-gnu/ doc/core/ tmp.*.rs config.stamp From a9247e07acc5829473239393b8a9cd367b710585 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 11 Apr 2013 14:31:56 -0700 Subject: [PATCH 168/403] Suppress a bunch of valgrind errors --- src/etc/x86.supp | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/etc/x86.supp b/src/etc/x86.supp index 95508fa12d236..2a955dfdbac85 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -565,3 +565,95 @@ fun:__gxx_personality_v0 ... } + +{ + llvm-optimization-reads-uninitialized-memory-1 + Memcheck:Cond + fun:_ZN4test17run_tests_console4anon13expr_fn* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-2 + Memcheck:Cond + fun:_ZN4test17run_tests_console* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-3 + Memcheck:Cond + fun:_ZN4test9run_tests4anon13expr_fn_* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-4 + Memcheck:Cond + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-5 + Memcheck:Cond + fun:_ZN4fold25noop_fold_item_underscore* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-6 + Memcheck:Cond + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn17* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-9 + Memcheck:Cond + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_foreign_fn* + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-11 + Memcheck:Cond + fun:_ZN4fold22noop_fold_foreign_item17_* + ... +} + + +{ + llvm-optimization-reads-uninitialized-memory-12 + Memcheck:Cond + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_struct* + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-13 + Memcheck:Cond + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_type* + fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-14 + Memcheck:Cond + fun:_ZN7ast_map6map_fn16_* + fun:_ZN5visit30visit_struct_dtor_helper_* + obj:* + fun:_ZN8unstable6extfmt2rt14__extensions__10meth_* + ... +} + +{ + llvm-optimization-reads-uninitialized-memory-15 + Memcheck:Cond + fun:_ZN7ast_map6map_fn16_* + fun:_ZN5visit30visit_struct_dtor_helper_* + ... +} From 27a0269501637d7fa27356caa9c13ab66fe5c8b0 Mon Sep 17 00:00:00 2001 From: Leah Hanson Date: Fri, 12 Apr 2013 22:15:56 -0400 Subject: [PATCH 169/403] Add comments for the implementations of from_base64 and to_base64 for . --- src/libstd/base64.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 0815e0ff0b502..618f5ecccf73c 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -26,6 +26,21 @@ static CHARS: [char, ..64] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' ]; +/** + * Turn a vector of `u8` bytes into a string representing them in base64. + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * + * fn main () { + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); + * } + * ~~~~ + */ impl<'self> ToBase64 for &'self [u8] { fn to_base64(&self) -> ~str { let mut s = ~""; @@ -102,6 +117,25 @@ pub trait FromBase64 { fn from_base64(&self) -> ~[u8]; } +/** + * Turn a vector of `u8`s representing characters + * encoding byte values in base64 into the vector of `u8` byte values. + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * use std::base64::FromBase64; + * + * fn main () { + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); + * let bytes = str.from_base64(); + * println(fmt!("%?",bytes)); + * } + * ~~~~ + */ impl FromBase64 for ~[u8] { fn from_base64(&self) -> ~[u8] { if self.len() % 4u != 0u { fail!(~"invalid base64 length"); } From 4ad8ec351afba3bb7b037b24a3bee1589a10780a Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Mon, 8 Apr 2013 21:21:11 +0800 Subject: [PATCH 170/403] fix index out of bounds error of x86_64 ABI --- src/librustc/middle/trans/cabi_x86_64.rs | 4 ++-- src/test/run-pass/issue-5754.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-5754.rs diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index 0e4bf5ce574a1..fa85588cb0f48 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -256,10 +256,10 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] { cls[i] = sse_int_class; } else if is_sse(cls[i]) { i += 1; - while cls[i] == sseup_class { i += 1u; } + while i != e && cls[i] == sseup_class { i += 1u; } } else if cls[i] == x87_class { i += 1; - while cls[i] == x87up_class { i += 1u; } + while i != e && cls[i] == x87up_class { i += 1u; } } else { i += 1; } diff --git a/src/test/run-pass/issue-5754.rs b/src/test/run-pass/issue-5754.rs new file mode 100644 index 0000000000000..003701b7a20cb --- /dev/null +++ b/src/test/run-pass/issue-5754.rs @@ -0,0 +1,19 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S { + r: float +} + +extern "C" { + fn rust_dbg_extern_identity_double(arg1: S) -> float; +} + +pub fn main() {} From 8bf9fc52f405f2a825cbf2692d872e9e710999b5 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 9 Apr 2013 10:54:32 -0400 Subject: [PATCH 171/403] initial iterator object library --- src/libcore/core.rc | 1 + src/libcore/iterator.rs | 101 ++++++++++++++++ src/libstd/serialize.rs | 15 +++ src/libstd/std.rc | 3 + src/libstd/treemap.rs | 260 +++++++++++++++------------------------- 5 files changed, 216 insertions(+), 164 deletions(-) create mode 100644 src/libcore/iterator.rs diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 3368f6df87090..2415ae1d1941c 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -176,6 +176,7 @@ pub mod from_str; #[path = "num/num.rs"] pub mod num; pub mod iter; +pub mod iterator; pub mod to_str; pub mod to_bytes; pub mod clone; diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs new file mode 100644 index 0000000000000..e7a2f3a392888 --- /dev/null +++ b/src/libcore/iterator.rs @@ -0,0 +1,101 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Composable iterator objects + +use prelude::*; + +pub trait Iterator { + /// Advance the iterator and return the next value. Return `None` when the end is reached. + fn next(&mut self) -> Option; +} + +/// A shim implementing the `for` loop iteration protocol for iterator objects +#[inline] +pub fn advance>(iter: &mut U, f: &fn(T) -> bool) { + loop { + match iter.next() { + Some(x) => { + if !f(x) { return } + } + None => return + } + } +} + +pub struct ZipIterator { + priv a: T, + priv b: U +} + +pub impl, U: Iterator> ZipIterator { + #[inline(always)] + fn new(a: T, b: U) -> ZipIterator { + ZipIterator{a: a, b: b} + } +} + +impl, U: Iterator> Iterator<(A, B)> for ZipIterator { + #[inline] + fn next(&mut self) -> Option<(A, B)> { + match (self.a.next(), self.b.next()) { + (Some(x), Some(y)) => Some((x, y)), + _ => None + } + } +} + +pub struct FilterIterator<'self, A, T> { + priv iter: T, + priv predicate: &'self fn(&A) -> bool +} + +pub impl<'self, A, T: Iterator> FilterIterator<'self, A, T> { + #[inline(always)] + fn new(iter: T, predicate: &'self fn(&A) -> bool) -> FilterIterator<'self, A, T> { + FilterIterator{iter: iter, predicate: predicate} + } +} + +impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + for advance(self) |x| { + if (self.predicate)(&x) { + return Some(x); + } else { + loop + } + } + None + } +} + +pub struct MapIterator<'self, A, B, T> { + priv iter: T, + priv f: &'self fn(A) -> B +} + +pub impl<'self, A, B, T: Iterator> MapIterator<'self, A, B, T> { + #[inline(always)] + fn new(iter: T, f: &'self fn(A) -> B) -> MapIterator<'self, A, B, T> { + MapIterator{iter: iter, f: f} + } +} + +impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(a) => Some((self.f)(a)), + _ => None + } + } +} diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 68ae9a6641726..e4e53b9b61486 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -21,6 +21,9 @@ use core::hashmap::{HashMap, HashSet}; use core::trie::{TrieMap, TrieSet}; use deque::Deque; use dlist::DList; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] use treemap::{TreeMap, TreeSet}; pub trait Encoder { @@ -738,6 +741,9 @@ impl Decodable for TrieSet { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] impl< E: Encoder, K: Encodable + Eq + TotalOrd, @@ -755,6 +761,9 @@ impl< } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] impl< D: Decoder, K: Decodable + Eq + TotalOrd, @@ -773,6 +782,9 @@ impl< } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] impl< S: Encoder, T: Encodable + Eq + TotalOrd @@ -788,6 +800,9 @@ impl< } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] impl< D: Decoder, T: Decodable + Eq + TotalOrd diff --git a/src/libstd/std.rc b/src/libstd/std.rc index fb340d80c2dbc..3dfc3200f0f52 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -76,6 +76,9 @@ pub mod rope; pub mod smallintmap; pub mod sort; pub mod dlist; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] pub mod treemap; // And ... other stuff diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 006455c44e429..bc8cbaa0825ce 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -13,6 +13,7 @@ //! `TotalOrd`. use core::prelude::*; +use core::iterator::*; // This is implemented as an AA tree, which is a simplified variation of // a red-black tree where where red (horizontal) nodes can only be added @@ -43,8 +44,7 @@ impl Eq for TreeMap { let mut x = self.iter(); let mut y = other.iter(); for self.len().times { - if map_next(&mut x).unwrap() != - map_next(&mut y).unwrap() { + if x.next().unwrap() != y.next().unwrap() { return false } } @@ -62,8 +62,8 @@ fn lt(a: &TreeMap, let (a_len, b_len) = (a.len(), b.len()); for uint::min(a_len, b_len).times { - let (key_a,_) = map_next(&mut x).unwrap(); - let (key_b,_) = map_next(&mut y).unwrap(); + let (key_a,_) = x.next().unwrap(); + let (key_b,_) = y.next().unwrap(); if *key_a < *key_b { return true; } if *key_a > *key_b { return false; } }; @@ -105,15 +105,6 @@ impl Map for TreeMap { } /// Visit all key-value pairs in order - #[cfg(stage0)] - fn each(&self, f: &fn(&'self K, &'self V) -> bool) { - each(&self.root, f) - } - - /// Visit all key-value pairs in order - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { each(&self.root, f) } @@ -124,15 +115,6 @@ impl Map for TreeMap { } /// Visit all values in order - #[cfg(stage0)] - fn each_value(&self, f: &fn(&V) -> bool) { - self.each(|_, v| f(v)) - } - - /// Visit all values in order - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) { self.each(|_, v| f(v)) } @@ -143,27 +125,6 @@ impl Map for TreeMap { } /// Return a reference to the value corresponding to the key - #[cfg(stage0)] - fn find(&self, key: &K) -> Option<&'self V> { - let mut current: &'self Option<~TreeNode> = &self.root; - loop { - match *current { - Some(ref r) => { - match key.cmp(&r.key) { - Less => current = &r.left, - Greater => current = &r.right, - Equal => return Some(&r.value) - } - } - None => return None - } - } - } - - /// Return a reference to the value corresponding to the key - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn find<'a>(&'a self, key: &K) -> Option<&'a V> { let mut current: &'a Option<~TreeNode> = &self.root; loop { @@ -182,16 +143,6 @@ impl Map for TreeMap { /// Return a mutable reference to the value corresponding to the key #[inline(always)] - #[cfg(stage0)] - fn find_mut(&mut self, key: &K) -> Option<&'self mut V> { - find_mut(&mut self.root, key) - } - - /// Return a mutable reference to the value corresponding to the key - #[inline(always)] - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { find_mut(&mut self.root, key) } @@ -219,15 +170,6 @@ pub impl TreeMap { fn new() -> TreeMap { TreeMap{root: None, length: 0} } /// Visit all key-value pairs in reverse order - #[cfg(stage0)] - fn each_reverse(&self, f: &fn(&'self K, &'self V) -> bool) { - each_reverse(&self.root, f); - } - - /// Visit all key-value pairs in reverse order - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { each_reverse(&self.root, f); } @@ -244,16 +186,6 @@ pub impl TreeMap { /// Get a lazy iterator over the key-value pairs in the map. /// Requires that it be frozen (immutable). - #[cfg(stage0)] - fn iter(&self) -> TreeMapIterator<'self, K, V> { - TreeMapIterator{stack: ~[], node: &self.root} - } - - /// Get a lazy iterator over the key-value pairs in the map. - /// Requires that it be frozen (immutable). - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { TreeMapIterator{stack: ~[], node: &self.root} } @@ -265,37 +197,33 @@ pub struct TreeMapIterator<'self, K, V> { priv node: &'self Option<~TreeNode> } -/// Advance the iterator to the next node (in order) and return a -/// tuple with a reference to the key and value. If there are no -/// more nodes, return `None`. -pub fn map_next<'r, K, V>(iter: &mut TreeMapIterator<'r, K, V>) - -> Option<(&'r K, &'r V)> { - while !iter.stack.is_empty() || iter.node.is_some() { - match *iter.node { - Some(ref x) => { - iter.stack.push(x); - iter.node = &x.left; - } - None => { - let res = iter.stack.pop(); - iter.node = &res.right; - return Some((&res.key, &res.value)); - } +impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> { + /// Advance the iterator to the next node (in order) and return a + /// tuple with a reference to the key and value. If there are no + /// more nodes, return `None`. + fn next(&mut self) -> Option<(&'self K, &'self V)> { + while !self.stack.is_empty() || self.node.is_some() { + match *self.node { + Some(ref x) => { + self.stack.push(x); + self.node = &x.left; + } + None => { + let res = self.stack.pop(); + self.node = &res.right; + return Some((&res.key, &res.value)); + } + } } + None } - None } -/// Advance the iterator through the map -pub fn map_advance<'r, K, V>(iter: &mut TreeMapIterator<'r, K, V>, - f: &fn((&'r K, &'r V)) -> bool) { - loop { - match map_next(iter) { - Some(x) => { - if !f(x) { return } - } - None => return - } +impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> { + /// Advance the iterator to the next node (in order). If there are no more nodes, return `None`. + #[inline(always)] + fn next(&mut self) -> Option<&'self T> { + do self.iter.next().map |&(value, _)| { value } } } @@ -375,14 +303,14 @@ impl Set for TreeSet { fn is_disjoint(&self, other: &TreeSet) -> bool { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while a.is_some() && b.is_some() { let a1 = a.unwrap(); let b1 = b.unwrap(); match a1.cmp(b1) { - Less => a = set_next(&mut x), - Greater => b = set_next(&mut y), + Less => a = x.next(), + Greater => b = y.next(), Equal => return false } } @@ -399,8 +327,8 @@ impl Set for TreeSet { fn is_superset(&self, other: &TreeSet) -> bool { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while b.is_some() { if a.is_none() { return false @@ -412,10 +340,10 @@ impl Set for TreeSet { match a1.cmp(b1) { Less => (), Greater => return false, - Equal => b = set_next(&mut y), + Equal => b = y.next(), } - a = set_next(&mut x); + a = x.next(); } true } @@ -425,13 +353,13 @@ impl Set for TreeSet { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while a.is_some() { if b.is_none() { return do a.while_some() |a1| { - if f(a1) { set_next(&mut x) } else { None } + if f(a1) { x.next() } else { None } } } @@ -442,10 +370,10 @@ impl Set for TreeSet { if cmp == Less { if !f(a1) { return } - a = set_next(&mut x); + a = x.next(); } else { - if cmp == Equal { a = set_next(&mut x) } - b = set_next(&mut y); + if cmp == Equal { a = x.next() } + b = y.next(); } } } @@ -456,13 +384,13 @@ impl Set for TreeSet { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while a.is_some() { if b.is_none() { return do a.while_some() |a1| { - if f(a1) { set_next(&mut x) } else { None } + if f(a1) { x.next() } else { None } } } @@ -473,18 +401,18 @@ impl Set for TreeSet { if cmp == Less { if !f(a1) { return } - a = set_next(&mut x); + a = x.next(); } else { if cmp == Greater { if !f(b1) { return } } else { - a = set_next(&mut x); + a = x.next(); } - b = set_next(&mut y); + b = y.next(); } } do b.while_some |b1| { - if f(b1) { set_next(&mut y) } else { None } + if f(b1) { y.next() } else { None } } } @@ -493,8 +421,8 @@ impl Set for TreeSet { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while a.is_some() && b.is_some() { let a1 = a.unwrap(); @@ -503,12 +431,12 @@ impl Set for TreeSet { let cmp = a1.cmp(b1); if cmp == Less { - a = set_next(&mut x); + a = x.next(); } else { if cmp == Equal { if !f(a1) { return } } - b = set_next(&mut y); + b = y.next(); } } } @@ -518,13 +446,13 @@ impl Set for TreeSet { let mut x = self.iter(); let mut y = other.iter(); - let mut a = set_next(&mut x); - let mut b = set_next(&mut y); + let mut a = x.next(); + let mut b = y.next(); while a.is_some() { if b.is_none() { return do a.while_some() |a1| { - if f(a1) { set_next(&mut x) } else { None } + if f(a1) { x.next() } else { None } } } @@ -535,17 +463,17 @@ impl Set for TreeSet { if cmp == Greater { if !f(b1) { return } - b = set_next(&mut y); + b = y.next(); } else { if !f(a1) { return } if cmp == Equal { - b = set_next(&mut y); + b = y.next(); } - a = set_next(&mut x); + a = x.next(); } } do b.while_some |b1| { - if f(b1) { set_next(&mut y) } else { None } + if f(b1) { y.next() } else { None } } } } @@ -558,17 +486,6 @@ pub impl TreeSet { /// Get a lazy iterator over the values in the set. /// Requires that it be frozen (immutable). #[inline(always)] - #[cfg(stage0)] - fn iter(&self) -> TreeSetIterator<'self, T> { - TreeSetIterator{iter: self.map.iter()} - } - - /// Get a lazy iterator over the values in the set. - /// Requires that it be frozen (immutable). - #[inline(always)] - #[cfg(stage1)] - #[cfg(stage2)] - #[cfg(stage3)] fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> { TreeSetIterator{iter: self.map.iter()} } @@ -579,20 +496,6 @@ pub struct TreeSetIterator<'self, T> { priv iter: TreeMapIterator<'self, T, ()> } -/// Advance the iterator to the next node (in order). If this iterator is -/// finished, does nothing. -#[inline(always)] -pub fn set_next<'r, T>(iter: &mut TreeSetIterator<'r, T>) -> Option<&'r T> { - do map_next(&mut iter.iter).map |&(value, _)| { value } -} - -/// Advance the iterator through the set -#[inline(always)] -pub fn set_advance<'r, T>(iter: &mut TreeSetIterator<'r, T>, - f: &fn(&'r T) -> bool) { - do map_advance(&mut iter.iter) |(k, _)| { f(k) } -} - // Nodes keep track of their level in the tree, starting at 1 in the // leaves and with a red child sharing the level of the parent. struct TreeNode { @@ -792,6 +695,7 @@ fn remove(node: &mut Option<~TreeNode>, #[cfg(test)] mod test_treemap { use core::prelude::*; + use core::iterator::*; use super::*; use core::rand::RngUtil; use core::rand; @@ -1078,13 +982,13 @@ mod test_treemap { let m = m; let mut a = m.iter(); - assert!(map_next(&mut a).unwrap() == (&x1, &y1)); - assert!(map_next(&mut a).unwrap() == (&x2, &y2)); - assert!(map_next(&mut a).unwrap() == (&x3, &y3)); - assert!(map_next(&mut a).unwrap() == (&x4, &y4)); - assert!(map_next(&mut a).unwrap() == (&x5, &y5)); + assert!(a.next().unwrap() == (&x1, &y1)); + assert!(a.next().unwrap() == (&x2, &y2)); + assert!(a.next().unwrap() == (&x3, &y3)); + assert!(a.next().unwrap() == (&x4, &y4)); + assert!(a.next().unwrap() == (&x5, &y5)); - assert!(map_next(&mut a).is_none()); + assert!(a.next().is_none()); let mut b = m.iter(); @@ -1092,7 +996,7 @@ mod test_treemap { (&x5, &y5)]; let mut i = 0; - for map_advance(&mut b) |x| { + for advance(&mut b) |x| { assert!(expected[i] == x); i += 1; @@ -1101,7 +1005,7 @@ mod test_treemap { } } - for map_advance(&mut b) |x| { + for advance(&mut b) |x| { assert!(expected[i] == x); i += 1; } @@ -1110,6 +1014,8 @@ mod test_treemap { #[cfg(test)] mod test_set { + use core::prelude::*; + use core::iterator::*; use super::*; #[test] @@ -1289,4 +1195,30 @@ mod test_set { [-2, 1, 5, 9, 13, 19], [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); } + + #[test] + fn test_zip() { + let mut x = TreeSet::new(); + x.insert(5u); + x.insert(12u); + x.insert(11u); + + let mut y = TreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = ZipIterator::new(x.iter(), y.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&uint, & &'static str)> = z.next(); + assert!(result.unwrap() == (&5u, & &"bar")); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert!(result.unwrap() == (&11u, & &"foo")); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert!(result.is_none()); + } } From d70f0f1a6e9ae3e2a998c60f4e2843507260f839 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 13 Apr 2013 21:02:43 +1000 Subject: [PATCH 172/403] librust: make `rust run file.rs` past any extra arguments to the compiled program. --- src/librust/rust.rc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librust/rust.rc b/src/librust/rust.rc index 624a4701d9802..bf35cae27ddeb 100644 --- a/src/librust/rust.rc +++ b/src/librust/rust.rc @@ -67,8 +67,8 @@ static commands: &'static [Command<'static>] = &[ usage_line: "build an executable, and run it", usage_full: UsgStr( "The run command is an shortcut for the command line \n\ - \"rustc -o ~ && ./~\".\ - \n\nUsage:\trust run " + \"rustc -o ~ && ./~ [...]\".\ + \n\nUsage:\trust run [...]" ) }, Command{ @@ -169,14 +169,14 @@ fn cmd_test(args: &[~str]) -> ValidUsage { fn cmd_run(args: &[~str]) -> ValidUsage { match args { - [filename] => { + [filename, ..prog_args] => { let exec = Path(filename).filestem().unwrap() + "~"; if run::run_program("rustc", [ filename.to_owned(), ~"-o", exec.to_owned() ]) == 0 { - run::run_program(~"./"+exec, []); + run::run_program(~"./"+exec, prog_args); } Valid } From c2b15345c7aa150212c4121de94e693b3117d618 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 13 Apr 2013 21:30:21 +1000 Subject: [PATCH 173/403] librusti: only use std::rl if stdin is connected to a tty. --- src/librusti/rusti.rc | 74 +++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 86784c7852afc..8e4a58c766e53 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -29,7 +29,7 @@ extern mod rustc(vers = "0.7-pre"); extern mod syntax(vers = "0.7-pre"); use core::*; -use core::io::WriterUtil; +use core::io::{ReaderUtil, WriterUtil}; use rustc::driver::{driver, session}; use syntax::{ast, diagnostic}; use syntax::ast_util::*; @@ -241,23 +241,29 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { /// Tries to get a line from rl after outputting a prompt. Returns /// None if no input was read (e.g. EOF was reached). -fn get_line(prompt: ~str) -> Option<~str> { - let result = unsafe { rl::read(prompt) }; +fn get_line(use_rl: bool, prompt: ~str) -> Option<~str> { + if use_rl { + let result = unsafe { rl::read(prompt) }; - if result.is_none() { - return None; + match result { + None => None, + Some(line) => { + unsafe { rl::add_history(line) }; + Some(line) + } + } + } else { + if io::stdin().eof() { + None + } else { + Some(io::stdin().read_line()) + } } - - let line = result.get(); - - unsafe { rl::add_history(line) }; - - return Some(line); } /// Run a command, e.g. :clear, :exit, etc. fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, - cmd: ~str, args: ~[~str]) -> CmdAction { + cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { let mut action = action_none; match cmd { ~"exit" => repl.running = false, @@ -313,7 +319,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, let mut multiline_cmd = ~""; let mut end_multiline = false; while (!end_multiline) { - match get_line(~"rusti| ") { + match get_line(use_rl, ~"rusti| ") { None => fail!(~"unterminated multiline command :{ .. :}"), Some(line) => { if str::trim(line) == ~":}" { @@ -333,7 +339,8 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, /// Executes a line of input, which may either be rust code or a /// :command. Returns a new Repl if it has changed. -fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str) +fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, + use_rl: bool) -> Option { if line.starts_with(~":") { let full = line.substr(1, line.len() - 1); @@ -349,11 +356,11 @@ fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str) vec::slice(split, 1, len).to_vec() } else { ~[] }; - match run_cmd(repl, in, out, cmd, args) { + match run_cmd(repl, in, out, cmd, args, use_rl) { action_none => { } action_run_line(multiline_cmd) => { if !multiline_cmd.is_empty() { - return run_line(repl, in, out, multiline_cmd); + return run_line(repl, in, out, multiline_cmd, use_rl); } } } @@ -386,30 +393,37 @@ pub fn main() { stmts: ~"" }; - io::println("WARNING: The Rust REPL is experimental and may be"); - io::println("unstable. If you encounter problems, please use the"); - io::println("compiler instead."); - - unsafe { - do rl::complete |line, suggest| { - if line.starts_with(":") { - suggest(~":clear"); - suggest(~":exit"); - suggest(~":help"); - suggest(~":load"); + let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; + + // only print this stuff if the user is actually typing into rusti + if istty { + io::println("WARNING: The Rust REPL is experimental and may be"); + io::println("unstable. If you encounter problems, please use the"); + io::println("compiler instead."); + + unsafe { + do rl::complete |line, suggest| { + if line.starts_with(":") { + suggest(~":clear"); + suggest(~":exit"); + suggest(~":help"); + suggest(~":load"); + } } } } while repl.running { - match get_line(repl.prompt) { + match get_line(istty, repl.prompt) { None => break, Some(line) => { if line.is_empty() { - io::println(~"()"); + if istty { + io::println(~"()"); + } loop; } - match run_line(&mut repl, in, out, line) { + match run_line(&mut repl, in, out, line, istty) { Some(new_repl) => repl = new_repl, None => { } } From 8e64b61df9a9b22dc742fcd25f0533f5b4580477 Mon Sep 17 00:00:00 2001 From: Leah Hanson Date: Sat, 13 Apr 2013 08:11:39 -0400 Subject: [PATCH 174/403] move rustdoc comments so that they attach to the functions rather than the impl blocks. --- src/libstd/base64.rs | 158 +++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 618f5ecccf73c..5b1e82ce1f00e 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -26,22 +26,22 @@ static CHARS: [char, ..64] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' ]; -/** - * Turn a vector of `u8` bytes into a string representing them in base64. - * - * *Example*: - * - * ~~~~ - * extern mod std; - * use std::base64::ToBase64; - * - * fn main () { - * let str = [52,32].to_base64(); - * println(fmt!("%s", str)); - * } - * ~~~~ - */ impl<'self> ToBase64 for &'self [u8] { + /** + * Turn a vector of `u8` bytes into a string representing them in base64. + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * + * fn main () { + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); + * } + * ~~~~ + */ fn to_base64(&self) -> ~str { let mut s = ~""; unsafe { @@ -90,24 +90,24 @@ impl<'self> ToBase64 for &'self [u8] { } } -/** - * Convert any string (literal, `@`, `&`, `~`) to base64 encoding. - * - * - * *Example*: - * - * ~~~~ - * extern mod std; - * use std::base64::ToBase64; - * - * fn main () { - * let str = "Hello, World".to_base64(); - * println(fmt!("%s",str)); - * } - * ~~~~ - * - */ impl<'self> ToBase64 for &'self str { + /** + * Convert any string (literal, `@`, `&`, `~`) to base64 encoding. + * + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * + * fn main () { + * let str = "Hello, World".to_base64(); + * println(fmt!("%s",str)); + * } + * ~~~~ + * + */ fn to_base64(&self) -> ~str { str::to_bytes(*self).to_base64() } @@ -117,26 +117,26 @@ pub trait FromBase64 { fn from_base64(&self) -> ~[u8]; } -/** - * Turn a vector of `u8`s representing characters - * encoding byte values in base64 into the vector of `u8` byte values. - * - * *Example*: - * - * ~~~~ - * extern mod std; - * use std::base64::ToBase64; - * use std::base64::FromBase64; - * - * fn main () { - * let str = [52,32].to_base64(); - * println(fmt!("%s", str)); - * let bytes = str.from_base64(); - * println(fmt!("%?",bytes)); - * } - * ~~~~ - */ impl FromBase64 for ~[u8] { + /** + * Turn a vector of `u8`s representing characters + * encoding byte values in base64 into the vector of `u8` byte values. + * + * *Example*: + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * use std::base64::FromBase64; + * + * fn main () { + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); + * let bytes = str.from_base64(); + * println(fmt!("%?",bytes)); + * } + * ~~~~ + */ fn from_base64(&self) -> ~[u8] { if self.len() % 4u != 0u { fail!(~"invalid base64 length"); } @@ -198,35 +198,35 @@ impl FromBase64 for ~[u8] { } } -/** - * Convert any string (literal, `@`, `&`, `~`) - * that contains a base64 encoded value, to the byte values it encodes. - * - * You can use the `from_bytes` function in `core::str` - * to turn a `[u8]` into a string with characters corresponding to those values. - * - * *Example*: - * - * This is an example of going from a string literal to the base64 encoding - * and back to the same string. - * - * ~~~~ - * extern mod std; - * use std::base64::ToBase64; - * use std::base64::FromBase64; - * use core::str; - * - * fn main () { - * let hello_str = "Hello, World".to_base64(); - * println(fmt!("%s",hello_str)); - * let bytes = hello_str.from_base64(); - * println(fmt!("%?",bytes)); - * let result_str = str::from_bytes(bytes); - * println(fmt!("%s",result_str)); - * } - * ~~~~ - */ impl FromBase64 for ~str { + /** + * Convert any string (literal, `@`, `&`, `~`) + * that contains a base64 encoded value, to the byte values it encodes. + * + * You can use the `from_bytes` function in `core::str` + * to turn a `[u8]` into a string with characters corresponding to those values. + * + * *Example*: + * + * This is an example of going from a string literal to the base64 encoding + * and back to the same string. + * + * ~~~~ + * extern mod std; + * use std::base64::ToBase64; + * use std::base64::FromBase64; + * use core::str; + * + * fn main () { + * let hello_str = "Hello, World".to_base64(); + * println(fmt!("%s",hello_str)); + * let bytes = hello_str.from_base64(); + * println(fmt!("%?",bytes)); + * let result_str = str::from_bytes(bytes); + * println(fmt!("%s",result_str)); + * } + * ~~~~ + */ fn from_base64(&self) -> ~[u8] { str::to_bytes(*self).from_base64() } From a26d9db95f2ff13030bb4a7fdd380165bf8abfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 12 Apr 2013 19:21:46 +0200 Subject: [PATCH 175/403] Avoid excessive allocations and copies in iter::to_vec The foldl based implementation allocates lots of unneeded vectors. iter::map_to_vec is already optimized to avoid these. --- src/libcore/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 9c704fbd69915..a220cd520c32a 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -161,7 +161,7 @@ pub fn foldl>(self: &IA, b0: B, blk: &fn(&B, &A) -> B) #[inline(always)] pub fn to_vec>(self: &IA) -> ~[A] { - foldl::(self, ~[], |r, a| vec::append(copy (*r), ~[*a])) + map_to_vec(self, |&x| x) } #[inline(always)] From 3ffd735b45c821441c7a73fa5beace04b67b7ba1 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 13 Apr 2013 23:31:47 +1000 Subject: [PATCH 176/403] Clarify purpose of NumCast trait --- src/libcore/num/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index daa36f9dc32f5..9a942ec0a5227 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -49,7 +49,7 @@ pub enum RoundMode { } /** - * Cast a number the the enclosing type + * Cast from one machine scalar to another * * # Example * @@ -64,7 +64,7 @@ pub fn cast(n: T) -> U { } /** - * An interface for generic numeric type casts + * An interface for casting between machine scalars */ pub trait NumCast { fn from(n: T) -> Self; From 353ce872e287edf3764ca416d2a8cd8e1f54329b Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 13 Apr 2013 23:44:35 +1000 Subject: [PATCH 177/403] Generate NumCast impls and tests using macros --- src/libcore/num/f32.rs | 70 ---------------- src/libcore/num/f64.rs | 70 ---------------- src/libcore/num/float.rs | 70 ---------------- src/libcore/num/int-template/i16.rs | 71 ---------------- src/libcore/num/int-template/i32.rs | 71 ---------------- src/libcore/num/int-template/i64.rs | 71 ---------------- src/libcore/num/int-template/i8.rs | 71 ---------------- src/libcore/num/int-template/int.rs | 71 ---------------- src/libcore/num/num.rs | 116 +++++++++++++++++++++++++- src/libcore/num/uint-template/u16.rs | 71 ---------------- src/libcore/num/uint-template/u32.rs | 71 ---------------- src/libcore/num/uint-template/u64.rs | 71 ---------------- src/libcore/num/uint-template/u8.rs | 71 ---------------- src/libcore/num/uint-template/uint.rs | 71 ---------------- 14 files changed, 114 insertions(+), 922 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index fa82001151e2a..b9e9e7c3073f5 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -12,7 +12,6 @@ use cmath; use libc::{c_float, c_int}; -use num::NumCast; use num::strconv; use num; use option::Option; @@ -287,30 +286,6 @@ impl num::One for f32 { fn one() -> f32 { 1.0 } } -impl NumCast for f32 { - /** - * Cast `n` to an `f32` - */ - #[inline(always)] - fn from(n: N) -> f32 { n.to_f32() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - #[cfg(notest)] impl ops::Add for f32 { fn add(&self, other: &f32) -> f32 { *self + *other } @@ -592,51 +567,6 @@ pub fn test_num() { assert!((ten.modulo(&two) == num::cast(0))); } -#[test] -fn test_numcast() { - assert!((20u == 20f32.to_uint())); - assert!((20u8 == 20f32.to_u8())); - assert!((20u16 == 20f32.to_u16())); - assert!((20u32 == 20f32.to_u32())); - assert!((20u64 == 20f32.to_u64())); - assert!((20i == 20f32.to_int())); - assert!((20i8 == 20f32.to_i8())); - assert!((20i16 == 20f32.to_i16())); - assert!((20i32 == 20f32.to_i32())); - assert!((20i64 == 20f32.to_i64())); - assert!((20f == 20f32.to_float())); - assert!((20f32 == 20f32.to_f32())); - assert!((20f64 == 20f32.to_f64())); - - assert!((20f32 == NumCast::from(20u))); - assert!((20f32 == NumCast::from(20u8))); - assert!((20f32 == NumCast::from(20u16))); - assert!((20f32 == NumCast::from(20u32))); - assert!((20f32 == NumCast::from(20u64))); - assert!((20f32 == NumCast::from(20i))); - assert!((20f32 == NumCast::from(20i8))); - assert!((20f32 == NumCast::from(20i16))); - assert!((20f32 == NumCast::from(20i32))); - assert!((20f32 == NumCast::from(20i64))); - assert!((20f32 == NumCast::from(20f))); - assert!((20f32 == NumCast::from(20f32))); - assert!((20f32 == NumCast::from(20f64))); - - assert!((20f32 == num::cast(20u))); - assert!((20f32 == num::cast(20u8))); - assert!((20f32 == num::cast(20u16))); - assert!((20f32 == num::cast(20u32))); - assert!((20f32 == num::cast(20u64))); - assert!((20f32 == num::cast(20i))); - assert!((20f32 == num::cast(20i8))); - assert!((20f32 == num::cast(20i16))); - assert!((20f32 == num::cast(20i32))); - assert!((20f32 == num::cast(20i64))); - assert!((20f32 == num::cast(20f))); - assert!((20f32 == num::cast(20f32))); - assert!((20f32 == num::cast(20f64))); -} - // // Local Variables: // mode: rust diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 67dfabacd0b0e..5e8961fa71877 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -12,7 +12,6 @@ use cmath; use libc::{c_double, c_int}; -use num::NumCast; use num::strconv; use num; use option::Option; @@ -299,30 +298,6 @@ impl cmp::Ord for f64 { fn gt(&self, other: &f64) -> bool { (*self) > (*other) } } -impl NumCast for f64 { - /** - * Cast `n` to an `f64` - */ - #[inline(always)] - fn from(n: N) -> f64 { n.to_f64() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - impl num::Zero for f64 { #[inline(always)] fn zero() -> f64 { 0.0 } @@ -614,51 +589,6 @@ pub fn test_num() { assert!((ten.modulo(&two) == num::cast(0))); } -#[test] -fn test_numcast() { - assert!((20u == 20f64.to_uint())); - assert!((20u8 == 20f64.to_u8())); - assert!((20u16 == 20f64.to_u16())); - assert!((20u32 == 20f64.to_u32())); - assert!((20u64 == 20f64.to_u64())); - assert!((20i == 20f64.to_int())); - assert!((20i8 == 20f64.to_i8())); - assert!((20i16 == 20f64.to_i16())); - assert!((20i32 == 20f64.to_i32())); - assert!((20i64 == 20f64.to_i64())); - assert!((20f == 20f64.to_float())); - assert!((20f32 == 20f64.to_f32())); - assert!((20f64 == 20f64.to_f64())); - - assert!((20f64 == NumCast::from(20u))); - assert!((20f64 == NumCast::from(20u8))); - assert!((20f64 == NumCast::from(20u16))); - assert!((20f64 == NumCast::from(20u32))); - assert!((20f64 == NumCast::from(20u64))); - assert!((20f64 == NumCast::from(20i))); - assert!((20f64 == NumCast::from(20i8))); - assert!((20f64 == NumCast::from(20i16))); - assert!((20f64 == NumCast::from(20i32))); - assert!((20f64 == NumCast::from(20i64))); - assert!((20f64 == NumCast::from(20f))); - assert!((20f64 == NumCast::from(20f32))); - assert!((20f64 == NumCast::from(20f64))); - - assert!((20f64 == num::cast(20u))); - assert!((20f64 == num::cast(20u8))); - assert!((20f64 == num::cast(20u16))); - assert!((20f64 == num::cast(20u32))); - assert!((20f64 == num::cast(20u64))); - assert!((20f64 == num::cast(20i))); - assert!((20f64 == num::cast(20i8))); - assert!((20f64 == num::cast(20i16))); - assert!((20f64 == num::cast(20i32))); - assert!((20f64 == num::cast(20i64))); - assert!((20f64 == num::cast(20f))); - assert!((20f64 == num::cast(20f32))); - assert!((20f64 == num::cast(20f64))); -} - // // Local Variables: // mode: rust diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 2508292970303..e8d7b1e532cea 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -21,7 +21,6 @@ // PORT this must match in width according to architecture use f64; -use num::NumCast; use num::strconv; use num; use option::Option; @@ -417,30 +416,6 @@ impl num::One for float { fn one() -> float { 1.0 } } -impl NumCast for float { - /** - * Cast `n` to a `float` - */ - #[inline(always)] - fn from(n: N) -> float { n.to_float() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self } -} - impl num::Round for float { #[inline(always)] fn round(&self, mode: num::RoundMode) -> float { @@ -700,51 +675,6 @@ pub fn test_num() { assert!((ten.modulo(&two) == num::cast(0))); } -#[test] -fn test_numcast() { - assert!((20u == 20f.to_uint())); - assert!((20u8 == 20f.to_u8())); - assert!((20u16 == 20f.to_u16())); - assert!((20u32 == 20f.to_u32())); - assert!((20u64 == 20f.to_u64())); - assert!((20i == 20f.to_int())); - assert!((20i8 == 20f.to_i8())); - assert!((20i16 == 20f.to_i16())); - assert!((20i32 == 20f.to_i32())); - assert!((20i64 == 20f.to_i64())); - assert!((20f == 20f.to_float())); - assert!((20f32 == 20f.to_f32())); - assert!((20f64 == 20f.to_f64())); - - assert!((20f == NumCast::from(20u))); - assert!((20f == NumCast::from(20u8))); - assert!((20f == NumCast::from(20u16))); - assert!((20f == NumCast::from(20u32))); - assert!((20f == NumCast::from(20u64))); - assert!((20f == NumCast::from(20i))); - assert!((20f == NumCast::from(20i8))); - assert!((20f == NumCast::from(20i16))); - assert!((20f == NumCast::from(20i32))); - assert!((20f == NumCast::from(20i64))); - assert!((20f == NumCast::from(20f))); - assert!((20f == NumCast::from(20f32))); - assert!((20f == NumCast::from(20f64))); - - assert!((20f == num::cast(20u))); - assert!((20f == num::cast(20u8))); - assert!((20f == num::cast(20u16))); - assert!((20f == num::cast(20u32))); - assert!((20f == num::cast(20u64))); - assert!((20f == num::cast(20i))); - assert!((20f == num::cast(20i8))); - assert!((20f == num::cast(20i16))); - assert!((20f == num::cast(20i32))); - assert!((20f == num::cast(20i64))); - assert!((20f == num::cast(20f))); - assert!((20f == num::cast(20f32))); - assert!((20f == num::cast(20f64))); -} - // // Local Variables: diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs index 76be224af15b9..34dcd50839785 100644 --- a/src/libcore/num/int-template/i16.rs +++ b/src/libcore/num/int-template/i16.rs @@ -10,78 +10,7 @@ //! Operations and constants for `i16` -use num::NumCast; - mod inst { pub type T = i16; pub static bits: uint = ::u16::bits; } - -impl NumCast for i16 { - /** - * Cast `n` to a `i16` - */ - #[inline(always)] - fn from(n: N) -> i16 { n.to_i16() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20i16.to_uint())); - assert!((20u8 == 20i16.to_u8())); - assert!((20u16 == 20i16.to_u16())); - assert!((20u32 == 20i16.to_u32())); - assert!((20u64 == 20i16.to_u64())); - assert!((20i == 20i16.to_int())); - assert!((20i8 == 20i16.to_i8())); - assert!((20i16 == 20i16.to_i16())); - assert!((20i32 == 20i16.to_i32())); - assert!((20i64 == 20i16.to_i64())); - assert!((20f == 20i16.to_float())); - assert!((20f32 == 20i16.to_f32())); - assert!((20f64 == 20i16.to_f64())); - - assert!((20i16 == NumCast::from(20u))); - assert!((20i16 == NumCast::from(20u8))); - assert!((20i16 == NumCast::from(20u16))); - assert!((20i16 == NumCast::from(20u32))); - assert!((20i16 == NumCast::from(20u64))); - assert!((20i16 == NumCast::from(20i))); - assert!((20i16 == NumCast::from(20i8))); - assert!((20i16 == NumCast::from(20i16))); - assert!((20i16 == NumCast::from(20i32))); - assert!((20i16 == NumCast::from(20i64))); - assert!((20i16 == NumCast::from(20f))); - assert!((20i16 == NumCast::from(20f32))); - assert!((20i16 == NumCast::from(20f64))); - - assert!((20i16 == num::cast(20u))); - assert!((20i16 == num::cast(20u8))); - assert!((20i16 == num::cast(20u16))); - assert!((20i16 == num::cast(20u32))); - assert!((20i16 == num::cast(20u64))); - assert!((20i16 == num::cast(20i))); - assert!((20i16 == num::cast(20i8))); - assert!((20i16 == num::cast(20i16))); - assert!((20i16 == num::cast(20i32))); - assert!((20i16 == num::cast(20i64))); - assert!((20i16 == num::cast(20f))); - assert!((20i16 == num::cast(20f32))); - assert!((20i16 == num::cast(20f64))); -} diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs index 596d29aa2910a..91eea0e8d4709 100644 --- a/src/libcore/num/int-template/i32.rs +++ b/src/libcore/num/int-template/i32.rs @@ -10,78 +10,7 @@ //! Operations and constants for `i32` -use num::NumCast; - mod inst { pub type T = i32; pub static bits: uint = ::u32::bits; } - -impl NumCast for i32 { - /** - * Cast `n` to a `i32` - */ - #[inline(always)] - fn from(n: N) -> i32 { n.to_i32() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20i32.to_uint())); - assert!((20u8 == 20i32.to_u8())); - assert!((20u16 == 20i32.to_u16())); - assert!((20u32 == 20i32.to_u32())); - assert!((20u64 == 20i32.to_u64())); - assert!((20i == 20i32.to_int())); - assert!((20i8 == 20i32.to_i8())); - assert!((20i16 == 20i32.to_i16())); - assert!((20i32 == 20i32.to_i32())); - assert!((20i64 == 20i32.to_i64())); - assert!((20f == 20i32.to_float())); - assert!((20f32 == 20i32.to_f32())); - assert!((20f64 == 20i32.to_f64())); - - assert!((20i32 == NumCast::from(20u))); - assert!((20i32 == NumCast::from(20u8))); - assert!((20i32 == NumCast::from(20u16))); - assert!((20i32 == NumCast::from(20u32))); - assert!((20i32 == NumCast::from(20u64))); - assert!((20i32 == NumCast::from(20i))); - assert!((20i32 == NumCast::from(20i8))); - assert!((20i32 == NumCast::from(20i16))); - assert!((20i32 == NumCast::from(20i32))); - assert!((20i32 == NumCast::from(20i64))); - assert!((20i32 == NumCast::from(20f))); - assert!((20i32 == NumCast::from(20f32))); - assert!((20i32 == NumCast::from(20f64))); - - assert!((20i32 == num::cast(20u))); - assert!((20i32 == num::cast(20u8))); - assert!((20i32 == num::cast(20u16))); - assert!((20i32 == num::cast(20u32))); - assert!((20i32 == num::cast(20u64))); - assert!((20i32 == num::cast(20i))); - assert!((20i32 == num::cast(20i8))); - assert!((20i32 == num::cast(20i16))); - assert!((20i32 == num::cast(20i32))); - assert!((20i32 == num::cast(20i64))); - assert!((20i32 == num::cast(20f))); - assert!((20i32 == num::cast(20f32))); - assert!((20i32 == num::cast(20f64))); -} diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs index d02c46d939310..3834a1e2a0387 100644 --- a/src/libcore/num/int-template/i64.rs +++ b/src/libcore/num/int-template/i64.rs @@ -10,78 +10,7 @@ //! Operations and constants for `i64` -use num::NumCast; - mod inst { pub type T = i64; pub static bits: uint = ::u64::bits; } - -impl NumCast for i64 { - /** - * Cast `n` to a `i64` - */ - #[inline(always)] - fn from(n: N) -> i64 { n.to_i64() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20i64.to_uint())); - assert!((20u8 == 20i64.to_u8())); - assert!((20u16 == 20i64.to_u16())); - assert!((20u32 == 20i64.to_u32())); - assert!((20u64 == 20i64.to_u64())); - assert!((20i == 20i64.to_int())); - assert!((20i8 == 20i64.to_i8())); - assert!((20i16 == 20i64.to_i16())); - assert!((20i32 == 20i64.to_i32())); - assert!((20i64 == 20i64.to_i64())); - assert!((20f == 20i64.to_float())); - assert!((20f32 == 20i64.to_f32())); - assert!((20f64 == 20i64.to_f64())); - - assert!((20i64 == NumCast::from(20u))); - assert!((20i64 == NumCast::from(20u8))); - assert!((20i64 == NumCast::from(20u16))); - assert!((20i64 == NumCast::from(20u32))); - assert!((20i64 == NumCast::from(20u64))); - assert!((20i64 == NumCast::from(20i))); - assert!((20i64 == NumCast::from(20i8))); - assert!((20i64 == NumCast::from(20i16))); - assert!((20i64 == NumCast::from(20i32))); - assert!((20i64 == NumCast::from(20i64))); - assert!((20i64 == NumCast::from(20f))); - assert!((20i64 == NumCast::from(20f32))); - assert!((20i64 == NumCast::from(20f64))); - - assert!((20i64 == num::cast(20u))); - assert!((20i64 == num::cast(20u8))); - assert!((20i64 == num::cast(20u16))); - assert!((20i64 == num::cast(20u32))); - assert!((20i64 == num::cast(20u64))); - assert!((20i64 == num::cast(20i))); - assert!((20i64 == num::cast(20i8))); - assert!((20i64 == num::cast(20i16))); - assert!((20i64 == num::cast(20i32))); - assert!((20i64 == num::cast(20i64))); - assert!((20i64 == num::cast(20f))); - assert!((20i64 == num::cast(20f32))); - assert!((20i64 == num::cast(20f64))); -} diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs index c0dd6e01d4b7f..9486ed748d7d0 100644 --- a/src/libcore/num/int-template/i8.rs +++ b/src/libcore/num/int-template/i8.rs @@ -10,78 +10,7 @@ //! Operations and constants for `i8` -use num::NumCast; - mod inst { pub type T = i8; pub static bits: uint = ::u8::bits; } - -impl NumCast for i8 { - /** - * Cast `n` to a `i8` - */ - #[inline(always)] - fn from(n: N) -> i8 { n.to_i8() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20i8.to_uint())); - assert!((20u8 == 20i8.to_u8())); - assert!((20u16 == 20i8.to_u16())); - assert!((20u32 == 20i8.to_u32())); - assert!((20u64 == 20i8.to_u64())); - assert!((20i == 20i8.to_int())); - assert!((20i8 == 20i8.to_i8())); - assert!((20i16 == 20i8.to_i16())); - assert!((20i32 == 20i8.to_i32())); - assert!((20i64 == 20i8.to_i64())); - assert!((20f == 20i8.to_float())); - assert!((20f32 == 20i8.to_f32())); - assert!((20f64 == 20i8.to_f64())); - - assert!((20i8 == NumCast::from(20u))); - assert!((20i8 == NumCast::from(20u8))); - assert!((20i8 == NumCast::from(20u16))); - assert!((20i8 == NumCast::from(20u32))); - assert!((20i8 == NumCast::from(20u64))); - assert!((20i8 == NumCast::from(20i))); - assert!((20i8 == NumCast::from(20i8))); - assert!((20i8 == NumCast::from(20i16))); - assert!((20i8 == NumCast::from(20i32))); - assert!((20i8 == NumCast::from(20i64))); - assert!((20i8 == NumCast::from(20f))); - assert!((20i8 == NumCast::from(20f32))); - assert!((20i8 == NumCast::from(20f64))); - - assert!((20i8 == num::cast(20u))); - assert!((20i8 == num::cast(20u8))); - assert!((20i8 == num::cast(20u16))); - assert!((20i8 == num::cast(20u32))); - assert!((20i8 == num::cast(20u64))); - assert!((20i8 == num::cast(20i))); - assert!((20i8 == num::cast(20i8))); - assert!((20i8 == num::cast(20i16))); - assert!((20i8 == num::cast(20i32))); - assert!((20i8 == num::cast(20i64))); - assert!((20i8 == num::cast(20f))); - assert!((20i8 == num::cast(20f32))); - assert!((20i8 == num::cast(20f64))); -} diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs index ea8aec1222438..6649b364015d3 100644 --- a/src/libcore/num/int-template/int.rs +++ b/src/libcore/num/int-template/int.rs @@ -10,8 +10,6 @@ //! Operations and constants for `int` -use num::NumCast; - pub use self::inst::pow; mod inst { @@ -57,72 +55,3 @@ mod inst { assert!((::int::min_value + ::int::max_value + 1 == 0)); } } - -impl NumCast for int { - /** - * Cast `n` to a `int` - */ - #[inline(always)] - fn from(n: N) -> int { n.to_int() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20i.to_uint())); - assert!((20u8 == 20i.to_u8())); - assert!((20u16 == 20i.to_u16())); - assert!((20u32 == 20i.to_u32())); - assert!((20u64 == 20i.to_u64())); - assert!((20i == 20i.to_int())); - assert!((20i8 == 20i.to_i8())); - assert!((20i16 == 20i.to_i16())); - assert!((20i32 == 20i.to_i32())); - assert!((20i64 == 20i.to_i64())); - assert!((20f == 20i.to_float())); - assert!((20f32 == 20i.to_f32())); - assert!((20f64 == 20i.to_f64())); - - assert!((20i == NumCast::from(20u))); - assert!((20i == NumCast::from(20u8))); - assert!((20i == NumCast::from(20u16))); - assert!((20i == NumCast::from(20u32))); - assert!((20i == NumCast::from(20u64))); - assert!((20i == NumCast::from(20i))); - assert!((20i == NumCast::from(20i8))); - assert!((20i == NumCast::from(20i16))); - assert!((20i == NumCast::from(20i32))); - assert!((20i == NumCast::from(20i64))); - assert!((20i == NumCast::from(20f))); - assert!((20i == NumCast::from(20f32))); - assert!((20i == NumCast::from(20f64))); - - assert!((20i == num::cast(20u))); - assert!((20i == num::cast(20u8))); - assert!((20i == num::cast(20u16))); - assert!((20i == num::cast(20u32))); - assert!((20i == num::cast(20u64))); - assert!((20i == num::cast(20i))); - assert!((20i == num::cast(20i8))); - assert!((20i == num::cast(20i16))); - assert!((20i == num::cast(20i32))); - assert!((20i == num::cast(20i64))); - assert!((20i == num::cast(20f))); - assert!((20i == num::cast(20f32))); - assert!((20i == num::cast(20f64))); -} diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 9a942ec0a5227..50894b85a49d5 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -9,8 +9,8 @@ // except according to those terms. //! An interface for numeric types -use cmp::Ord; -use ops::{Div, Mul, Neg}; +use cmp::{Eq, Ord}; +use ops::{Neg, Add, Sub, Mul, Div, Modulo}; use option::Option; use kinds::Copy; @@ -86,6 +86,57 @@ pub trait NumCast { fn to_float(&self) -> float; } +macro_rules! impl_num_cast( + ($T:ty, $conv:ident) => ( + // FIXME #4375: This enclosing module is necessary because + // of a bug with macros expanding into multiple items + pub mod $conv { + use num::NumCast; + + #[cfg(notest)] + impl NumCast for $T { + #[doc = "Cast `n` to a `$T`"] + #[inline(always)] + fn from(n: N) -> $T { + // `$conv` could be generated using `concat_idents!`, but that + // macro seems to be broken at the moment + n.$conv() + } + + #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } + #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } + #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } + #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } + #[inline(always)] fn to_uint(&self) -> uint { *self as uint } + + #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } + #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } + #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } + #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } + #[inline(always)] fn to_int(&self) -> int { *self as int } + + #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } + #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } + #[inline(always)] fn to_float(&self) -> float { *self as float } + } + } + ) +) + +impl_num_cast!(u8, to_u8) +impl_num_cast!(u16, to_u16) +impl_num_cast!(u32, to_u32) +impl_num_cast!(u64, to_u64) +impl_num_cast!(uint, to_uint) +impl_num_cast!(i8, to_i8) +impl_num_cast!(i16, to_i16) +impl_num_cast!(i32, to_i32) +impl_num_cast!(i64, to_i64) +impl_num_cast!(int, to_int) +impl_num_cast!(f32, to_f32) +impl_num_cast!(f64, to_f64) +impl_num_cast!(float, to_float) + pub trait ToStrRadix { pub fn to_str_radix(&self, radix: uint) -> ~str; } @@ -129,3 +180,64 @@ pub fn pow_with_uint+Mul>( total } +macro_rules! test_cast_20( + ($_20:expr) => ({ + let _20 = $_20; + + assert!(20u == _20.to_uint()); + assert!(20u8 == _20.to_u8()); + assert!(20u16 == _20.to_u16()); + assert!(20u32 == _20.to_u32()); + assert!(20u64 == _20.to_u64()); + assert!(20i == _20.to_int()); + assert!(20i8 == _20.to_i8()); + assert!(20i16 == _20.to_i16()); + assert!(20i32 == _20.to_i32()); + assert!(20i64 == _20.to_i64()); + assert!(20f == _20.to_float()); + assert!(20f32 == _20.to_f32()); + assert!(20f64 == _20.to_f64()); + + assert!(_20 == NumCast::from(20u)); + assert!(_20 == NumCast::from(20u8)); + assert!(_20 == NumCast::from(20u16)); + assert!(_20 == NumCast::from(20u32)); + assert!(_20 == NumCast::from(20u64)); + assert!(_20 == NumCast::from(20i)); + assert!(_20 == NumCast::from(20i8)); + assert!(_20 == NumCast::from(20i16)); + assert!(_20 == NumCast::from(20i32)); + assert!(_20 == NumCast::from(20i64)); + assert!(_20 == NumCast::from(20f)); + assert!(_20 == NumCast::from(20f32)); + assert!(_20 == NumCast::from(20f64)); + + assert!(_20 == cast(20u)); + assert!(_20 == cast(20u8)); + assert!(_20 == cast(20u16)); + assert!(_20 == cast(20u32)); + assert!(_20 == cast(20u64)); + assert!(_20 == cast(20i)); + assert!(_20 == cast(20i8)); + assert!(_20 == cast(20i16)); + assert!(_20 == cast(20i32)); + assert!(_20 == cast(20i64)); + assert!(_20 == cast(20f)); + assert!(_20 == cast(20f32)); + assert!(_20 == cast(20f64)); + }) +) + +#[test] fn test_u8_cast() { test_cast_20!(20u8) } +#[test] fn test_u16_cast() { test_cast_20!(20u16) } +#[test] fn test_u32_cast() { test_cast_20!(20u32) } +#[test] fn test_u64_cast() { test_cast_20!(20u64) } +#[test] fn test_uint_cast() { test_cast_20!(20u) } +#[test] fn test_i8_cast() { test_cast_20!(20i8) } +#[test] fn test_i16_cast() { test_cast_20!(20i16) } +#[test] fn test_i32_cast() { test_cast_20!(20i32) } +#[test] fn test_i64_cast() { test_cast_20!(20i64) } +#[test] fn test_int_cast() { test_cast_20!(20i) } +#[test] fn test_f32_cast() { test_cast_20!(20f32) } +#[test] fn test_f64_cast() { test_cast_20!(20f64) } +#[test] fn test_float_cast() { test_cast_20!(20f) } \ No newline at end of file diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs index 7445a43e48645..63144162fc50a 100644 --- a/src/libcore/num/uint-template/u16.rs +++ b/src/libcore/num/uint-template/u16.rs @@ -10,80 +10,9 @@ //! Operations and constants for `u16` -use num::NumCast; - mod inst { pub type T = u16; #[allow(non_camel_case_types)] pub type T_SIGNED = i16; pub static bits: uint = 16; } - -impl NumCast for u16 { - /** - * Cast `n` to a `u16` - */ - #[inline(always)] - fn from(n: N) -> u16 { n.to_u16() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20u16.to_uint())); - assert!((20u8 == 20u16.to_u8())); - assert!((20u16 == 20u16.to_u16())); - assert!((20u32 == 20u16.to_u32())); - assert!((20u64 == 20u16.to_u64())); - assert!((20i == 20u16.to_int())); - assert!((20i8 == 20u16.to_i8())); - assert!((20i16 == 20u16.to_i16())); - assert!((20i32 == 20u16.to_i32())); - assert!((20i64 == 20u16.to_i64())); - assert!((20f == 20u16.to_float())); - assert!((20f32 == 20u16.to_f32())); - assert!((20f64 == 20u16.to_f64())); - - assert!((20u16 == NumCast::from(20u))); - assert!((20u16 == NumCast::from(20u8))); - assert!((20u16 == NumCast::from(20u16))); - assert!((20u16 == NumCast::from(20u32))); - assert!((20u16 == NumCast::from(20u64))); - assert!((20u16 == NumCast::from(20i))); - assert!((20u16 == NumCast::from(20i8))); - assert!((20u16 == NumCast::from(20i16))); - assert!((20u16 == NumCast::from(20i32))); - assert!((20u16 == NumCast::from(20i64))); - assert!((20u16 == NumCast::from(20f))); - assert!((20u16 == NumCast::from(20f32))); - assert!((20u16 == NumCast::from(20f64))); - - assert!((20u16 == num::cast(20u))); - assert!((20u16 == num::cast(20u8))); - assert!((20u16 == num::cast(20u16))); - assert!((20u16 == num::cast(20u32))); - assert!((20u16 == num::cast(20u64))); - assert!((20u16 == num::cast(20i))); - assert!((20u16 == num::cast(20i8))); - assert!((20u16 == num::cast(20i16))); - assert!((20u16 == num::cast(20i32))); - assert!((20u16 == num::cast(20i64))); - assert!((20u16 == num::cast(20f))); - assert!((20u16 == num::cast(20f32))); - assert!((20u16 == num::cast(20f64))); -} diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs index cfc112be8a6d1..4d9958fe38aaf 100644 --- a/src/libcore/num/uint-template/u32.rs +++ b/src/libcore/num/uint-template/u32.rs @@ -10,80 +10,9 @@ //! Operations and constants for `u32` -use num::NumCast; - mod inst { pub type T = u32; #[allow(non_camel_case_types)] pub type T_SIGNED = i32; pub static bits: uint = 32; } - -impl NumCast for u32 { - /** - * Cast `n` to a `u32` - */ - #[inline(always)] - fn from(n: N) -> u32 { n.to_u32() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20u64.to_uint())); - assert!((20u8 == 20u64.to_u8())); - assert!((20u16 == 20u64.to_u16())); - assert!((20u32 == 20u64.to_u32())); - assert!((20u64 == 20u64.to_u64())); - assert!((20i == 20u64.to_int())); - assert!((20i8 == 20u64.to_i8())); - assert!((20i16 == 20u64.to_i16())); - assert!((20i32 == 20u64.to_i32())); - assert!((20i64 == 20u64.to_i64())); - assert!((20f == 20u64.to_float())); - assert!((20f32 == 20u64.to_f32())); - assert!((20f64 == 20u64.to_f64())); - - assert!((20u64 == NumCast::from(20u))); - assert!((20u64 == NumCast::from(20u8))); - assert!((20u64 == NumCast::from(20u16))); - assert!((20u64 == NumCast::from(20u32))); - assert!((20u64 == NumCast::from(20u64))); - assert!((20u64 == NumCast::from(20i))); - assert!((20u64 == NumCast::from(20i8))); - assert!((20u64 == NumCast::from(20i16))); - assert!((20u64 == NumCast::from(20i32))); - assert!((20u64 == NumCast::from(20i64))); - assert!((20u64 == NumCast::from(20f))); - assert!((20u64 == NumCast::from(20f32))); - assert!((20u64 == NumCast::from(20f64))); - - assert!((20u64 == num::cast(20u))); - assert!((20u64 == num::cast(20u8))); - assert!((20u64 == num::cast(20u16))); - assert!((20u64 == num::cast(20u32))); - assert!((20u64 == num::cast(20u64))); - assert!((20u64 == num::cast(20i))); - assert!((20u64 == num::cast(20i8))); - assert!((20u64 == num::cast(20i16))); - assert!((20u64 == num::cast(20i32))); - assert!((20u64 == num::cast(20i64))); - assert!((20u64 == num::cast(20f))); - assert!((20u64 == num::cast(20f32))); - assert!((20u64 == num::cast(20f64))); -} diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs index 4e2f6640d6974..af198dd69424b 100644 --- a/src/libcore/num/uint-template/u64.rs +++ b/src/libcore/num/uint-template/u64.rs @@ -10,80 +10,9 @@ //! Operations and constants for `u64` -use num::NumCast; - mod inst { pub type T = u64; #[allow(non_camel_case_types)] pub type T_SIGNED = i64; pub static bits: uint = 64; } - -impl NumCast for u64 { - /** - * Cast `n` to a `u64` - */ - #[inline(always)] - fn from(n: N) -> u64 { n.to_u64() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20u64.to_uint())); - assert!((20u8 == 20u64.to_u8())); - assert!((20u16 == 20u64.to_u16())); - assert!((20u32 == 20u64.to_u32())); - assert!((20u64 == 20u64.to_u64())); - assert!((20i == 20u64.to_int())); - assert!((20i8 == 20u64.to_i8())); - assert!((20i16 == 20u64.to_i16())); - assert!((20i32 == 20u64.to_i32())); - assert!((20i64 == 20u64.to_i64())); - assert!((20f == 20u64.to_float())); - assert!((20f32 == 20u64.to_f32())); - assert!((20f64 == 20u64.to_f64())); - - assert!((20u64 == NumCast::from(20u))); - assert!((20u64 == NumCast::from(20u8))); - assert!((20u64 == NumCast::from(20u16))); - assert!((20u64 == NumCast::from(20u32))); - assert!((20u64 == NumCast::from(20u64))); - assert!((20u64 == NumCast::from(20i))); - assert!((20u64 == NumCast::from(20i8))); - assert!((20u64 == NumCast::from(20i16))); - assert!((20u64 == NumCast::from(20i32))); - assert!((20u64 == NumCast::from(20i64))); - assert!((20u64 == NumCast::from(20f))); - assert!((20u64 == NumCast::from(20f32))); - assert!((20u64 == NumCast::from(20f64))); - - assert!((20u64 == num::cast(20u))); - assert!((20u64 == num::cast(20u8))); - assert!((20u64 == num::cast(20u16))); - assert!((20u64 == num::cast(20u32))); - assert!((20u64 == num::cast(20u64))); - assert!((20u64 == num::cast(20i))); - assert!((20u64 == num::cast(20i8))); - assert!((20u64 == num::cast(20i16))); - assert!((20u64 == num::cast(20i32))); - assert!((20u64 == num::cast(20i64))); - assert!((20u64 == num::cast(20f))); - assert!((20u64 == num::cast(20f32))); - assert!((20u64 == num::cast(20f64))); -} diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs index 52bc56b955cc1..ce23bebacdad1 100644 --- a/src/libcore/num/uint-template/u8.rs +++ b/src/libcore/num/uint-template/u8.rs @@ -12,8 +12,6 @@ pub use self::inst::is_ascii; -use num::NumCast; - mod inst { pub type T = u8; #[allow(non_camel_case_types)] @@ -25,72 +23,3 @@ mod inst { pub fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; } } - -impl NumCast for u8 { - /** - * Cast `n` to a `u8` - */ - #[inline(always)] - fn from(n: N) -> u8 { n.to_u8() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20u8.to_uint())); - assert!((20u8 == 20u8.to_u8())); - assert!((20u16 == 20u8.to_u16())); - assert!((20u32 == 20u8.to_u32())); - assert!((20u64 == 20u8.to_u64())); - assert!((20i == 20u8.to_int())); - assert!((20i8 == 20u8.to_i8())); - assert!((20i16 == 20u8.to_i16())); - assert!((20i32 == 20u8.to_i32())); - assert!((20i64 == 20u8.to_i64())); - assert!((20f == 20u8.to_float())); - assert!((20f32 == 20u8.to_f32())); - assert!((20f64 == 20u8.to_f64())); - - assert!((20u8 == NumCast::from(20u))); - assert!((20u8 == NumCast::from(20u8))); - assert!((20u8 == NumCast::from(20u16))); - assert!((20u8 == NumCast::from(20u32))); - assert!((20u8 == NumCast::from(20u64))); - assert!((20u8 == NumCast::from(20i))); - assert!((20u8 == NumCast::from(20i8))); - assert!((20u8 == NumCast::from(20i16))); - assert!((20u8 == NumCast::from(20i32))); - assert!((20u8 == NumCast::from(20i64))); - assert!((20u8 == NumCast::from(20f))); - assert!((20u8 == NumCast::from(20f32))); - assert!((20u8 == NumCast::from(20f64))); - - assert!((20u8 == num::cast(20u))); - assert!((20u8 == num::cast(20u8))); - assert!((20u8 == num::cast(20u16))); - assert!((20u8 == num::cast(20u32))); - assert!((20u8 == num::cast(20u64))); - assert!((20u8 == num::cast(20i))); - assert!((20u8 == num::cast(20i8))); - assert!((20u8 == num::cast(20i16))); - assert!((20u8 == num::cast(20i32))); - assert!((20u8 == num::cast(20i64))); - assert!((20u8 == num::cast(20f))); - assert!((20u8 == num::cast(20f32))); - assert!((20u8 == num::cast(20f64))); -} diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index 16e53eb4b6c97..efcf68aba3160 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -10,8 +10,6 @@ //! Operations and constants for `uint` -use num::NumCast; - pub use self::inst::{ div_ceil, div_round, div_floor, iterate, next_power_of_two @@ -209,72 +207,3 @@ pub mod inst { assert!((accum == 10)); } } - -impl NumCast for uint { - /** - * Cast `n` to a `uint` - */ - #[inline(always)] - fn from(n: N) -> uint { n.to_uint() } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } -} - -#[test] -fn test_numcast() { - assert!((20u == 20u.to_uint())); - assert!((20u8 == 20u.to_u8())); - assert!((20u16 == 20u.to_u16())); - assert!((20u32 == 20u.to_u32())); - assert!((20u64 == 20u.to_u64())); - assert!((20i == 20u.to_int())); - assert!((20i8 == 20u.to_i8())); - assert!((20i16 == 20u.to_i16())); - assert!((20i32 == 20u.to_i32())); - assert!((20i64 == 20u.to_i64())); - assert!((20f == 20u.to_float())); - assert!((20f32 == 20u.to_f32())); - assert!((20f64 == 20u.to_f64())); - - assert!((20u == NumCast::from(20u))); - assert!((20u == NumCast::from(20u8))); - assert!((20u == NumCast::from(20u16))); - assert!((20u == NumCast::from(20u32))); - assert!((20u == NumCast::from(20u64))); - assert!((20u == NumCast::from(20i))); - assert!((20u == NumCast::from(20i8))); - assert!((20u == NumCast::from(20i16))); - assert!((20u == NumCast::from(20i32))); - assert!((20u == NumCast::from(20i64))); - assert!((20u == NumCast::from(20f))); - assert!((20u == NumCast::from(20f32))); - assert!((20u == NumCast::from(20f64))); - - assert!((20u == num::cast(20u))); - assert!((20u == num::cast(20u8))); - assert!((20u == num::cast(20u16))); - assert!((20u == num::cast(20u32))); - assert!((20u == num::cast(20u64))); - assert!((20u == num::cast(20i))); - assert!((20u == num::cast(20i8))); - assert!((20u == num::cast(20i16))); - assert!((20u == num::cast(20i32))); - assert!((20u == num::cast(20i64))); - assert!((20u == num::cast(20f))); - assert!((20u == num::cast(20f32))); - assert!((20u == num::cast(20f64))); -} From 947ba206e10126be8a03afd58039a99430a824fd Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 13 Apr 2013 23:59:52 +1000 Subject: [PATCH 178/403] Add a test to show how NumCast can be used in type parameters --- src/libcore/num/num.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 50894b85a49d5..a257094368261 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -240,4 +240,27 @@ macro_rules! test_cast_20( #[test] fn test_int_cast() { test_cast_20!(20i) } #[test] fn test_f32_cast() { test_cast_20!(20f32) } #[test] fn test_f64_cast() { test_cast_20!(20f64) } -#[test] fn test_float_cast() { test_cast_20!(20f) } \ No newline at end of file +#[test] fn test_float_cast() { test_cast_20!(20f) } + +#[test] +fn test_generic_cast() { + use ops::Add; + + fn add_2 + NumCast>(n: T) -> T { + n + cast(2) + } + + assert!(add_2(1u) == 3u); + assert!(add_2(1u8) == 3u8); + assert!(add_2(1u16) == 3u16); + assert!(add_2(1u32) == 3u32); + assert!(add_2(1u64) == 3u64); + assert!(add_2(1i) == 3i); + assert!(add_2(1i8) == 3i8); + assert!(add_2(1i16) == 3i16); + assert!(add_2(1i32) == 3i32); + assert!(add_2(1i64) == 3i64); + assert!(add_2(1f) == 3f); + assert!(add_2(1f32) == 3f32); + assert!(add_2(1f64) == 3f64); +} From fde6995229ff1bf99fccbcfee8b55e27afdb11ec Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 14 Apr 2013 01:25:56 +1000 Subject: [PATCH 179/403] Remove trailing whitespace --- src/libcore/num/num.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index a257094368261..d200a68c40049 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -89,10 +89,10 @@ pub trait NumCast { macro_rules! impl_num_cast( ($T:ty, $conv:ident) => ( // FIXME #4375: This enclosing module is necessary because - // of a bug with macros expanding into multiple items + // of a bug with macros expanding into multiple items pub mod $conv { use num::NumCast; - + #[cfg(notest)] impl NumCast for $T { #[doc = "Cast `n` to a `$T`"] @@ -183,7 +183,7 @@ pub fn pow_with_uint+Mul>( macro_rules! test_cast_20( ($_20:expr) => ({ let _20 = $_20; - + assert!(20u == _20.to_uint()); assert!(20u8 == _20.to_u8()); assert!(20u16 == _20.to_u16()); @@ -245,11 +245,11 @@ macro_rules! test_cast_20( #[test] fn test_generic_cast() { use ops::Add; - + fn add_2 + NumCast>(n: T) -> T { n + cast(2) } - + assert!(add_2(1u) == 3u); assert!(add_2(1u8) == 3u8); assert!(add_2(1u16) == 3u16); From ce6ee7bb041044c3e236be7aefae97931e596407 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 14 Apr 2013 02:19:35 +1000 Subject: [PATCH 180/403] Restore Num trait This restores the trait that was lost in 216e85fadf465c25fe7bc4a9f06f8162ec12b552. It will eventually be broken up into a more fine-grained trait hierarchy in the future once a design can be agreed upon. --- src/libcore/core.rc | 2 +- src/libcore/num/num.rs | 22 +++++++++++++++++++++ src/libcore/prelude.rs | 2 +- src/test/run-pass/trait-inheritance-num.rs | 2 +- src/test/run-pass/trait-inheritance-num1.rs | 2 +- src/test/run-pass/trait-inheritance-num2.rs | 2 +- src/test/run-pass/trait-inheritance-num3.rs | 2 +- src/test/run-pass/trait-inheritance-num5.rs | 2 +- 8 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 3368f6df87090..41db07ca34c57 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -99,7 +99,7 @@ pub use vec::{OwnedVector, OwnedCopyableVector}; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; -pub use num::NumCast; +pub use num::{Num, NumCast}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index d200a68c40049..333c7ce02b281 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -16,6 +16,28 @@ use kinds::Copy; pub mod strconv; +pub trait Num: Eq + Zero + One + + Neg + + Add + + Sub + + Mul + + Div + + Modulo {} + +impl Num for u8 {} +impl Num for u16 {} +impl Num for u32 {} +impl Num for u64 {} +impl Num for uint {} +impl Num for i8 {} +impl Num for i16 {} +impl Num for i32 {} +impl Num for i64 {} +impl Num for int {} +impl Num for f32 {} +impl Num for f64 {} +impl Num for float {} + pub trait IntConvertible { fn to_int(&self) -> int; fn from_int(n: int) -> Self; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 9c3bf04b2a8f5..e148493ca4512 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -34,7 +34,7 @@ pub use hash::Hash; pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::Times; -pub use num::NumCast; +pub use num::{Num, NumCast}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs index b800ffefeb694..0fb2a6b2e724b 100644 --- a/src/test/run-pass/trait-inheritance-num.rs +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -16,7 +16,7 @@ use core::cmp::{Eq, Ord}; use core::num::NumCast::from; use std::cmp::FuzzyEq; -pub trait NumExt: NumCast + Eq + Ord {} +pub trait NumExt: Num + NumCast + Eq + Ord {} pub trait FloatExt: NumExt + FuzzyEq {} diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs index 07b9772af2970..d580b99012fa5 100644 --- a/src/test/run-pass/trait-inheritance-num1.rs +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -11,7 +11,7 @@ use core::cmp::Ord; use core::num::NumCast::from; -pub trait NumExt: NumCast + Ord { } +pub trait NumExt: Num + NumCast + Ord { } fn greater_than_one(n: &T) -> bool { *n > from(1) diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index 66d7ee96bb250..b40f647814f0c 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -38,7 +38,7 @@ impl TypeExt for f64 {} impl TypeExt for float {} -pub trait NumExt: TypeExt + Eq + Ord + NumCast {} +pub trait NumExt: TypeExt + Eq + Ord + Num + NumCast {} impl NumExt for u8 {} impl NumExt for u16 {} diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs index 67861709e76f2..5f1fef80ef201 100644 --- a/src/test/run-pass/trait-inheritance-num3.rs +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -11,7 +11,7 @@ use core::cmp::{Eq, Ord}; use core::num::NumCast::from; -pub trait NumExt: Eq + Ord + NumCast {} +pub trait NumExt: Eq + Ord + Num + NumCast {} impl NumExt for f32 {} diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs index 2efe5b23eb57b..02cc9a3d221f8 100644 --- a/src/test/run-pass/trait-inheritance-num5.rs +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -11,7 +11,7 @@ use core::cmp::{Eq, Ord}; use core::num::NumCast::from; -pub trait NumExt: Eq + NumCast {} +pub trait NumExt: Eq + Num + NumCast {} impl NumExt for f32 {} impl NumExt for int {} From c4685477e0771ee21afa6b93ea0d4ca2c7f6abd9 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 14 Apr 2013 02:53:00 +1000 Subject: [PATCH 181/403] Consolidate tests of numeric operations --- src/libcore/num/f32.rs | 12 -------- src/libcore/num/f64.rs | 12 -------- src/libcore/num/float.rs | 12 -------- src/libcore/num/int-template.rs | 12 -------- src/libcore/num/num.rs | 52 ++++++++++++++++++-------------- src/libcore/num/uint-template.rs | 12 -------- 6 files changed, 29 insertions(+), 83 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index b9e9e7c3073f5..5e672ea0dfa86 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -555,18 +555,6 @@ impl num::FromStrRadix for f32 { } } -#[test] -pub fn test_num() { - let ten: f32 = num::cast(10); - let two: f32 = num::cast(2); - - assert!((ten.add(&two) == num::cast(12))); - assert!((ten.sub(&two) == num::cast(8))); - assert!((ten.mul(&two) == num::cast(20))); - assert!((ten.div(&two) == num::cast(5))); - assert!((ten.modulo(&two) == num::cast(0))); -} - // // Local Variables: // mode: rust diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 5e8961fa71877..4c96da73d2130 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -577,18 +577,6 @@ impl num::FromStrRadix for f64 { } } -#[test] -pub fn test_num() { - let ten: f64 = num::cast(10); - let two: f64 = num::cast(2); - - assert!((ten.add(&two) == num::cast(12))); - assert!((ten.sub(&two) == num::cast(8))); - assert!((ten.mul(&two) == num::cast(20))); - assert!((ten.div(&two) == num::cast(5))); - assert!((ten.modulo(&two) == num::cast(0))); -} - // // Local Variables: // mode: rust diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index e8d7b1e532cea..1ab0e24f62dc9 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -663,18 +663,6 @@ pub fn test_round() { assert!(round(-3.5) == -4.0); } -#[test] -pub fn test_num() { - let ten: float = num::cast(10); - let two: float = num::cast(2); - - assert!((ten.add(&two) == num::cast(12))); - assert!((ten.sub(&two) == num::cast(8))); - assert!((ten.mul(&two) == num::cast(20))); - assert!((ten.div(&two) == num::cast(5))); - assert!((ten.modulo(&two) == num::cast(0))); -} - // // Local Variables: diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 4af903908f1f3..6fbe44737d184 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -397,18 +397,6 @@ fn test_int_from_str_overflow() { assert!((i64::from_str(~"-9223372036854775809").is_none())); } -#[test] -pub fn test_num() { - let ten: T = num::cast(10); - let two: T = num::cast(2); - - assert!((ten.add(&two) == num::cast(12))); - assert!((ten.sub(&two) == num::cast(8))); - assert!((ten.mul(&two) == num::cast(20))); - assert!((ten.div(&two) == num::cast(5))); - assert!((ten.modulo(&two) == num::cast(0))); -} - #[test] pub fn test_ranges() { let mut l = ~[]; diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 333c7ce02b281..fc81393693c87 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -202,6 +202,35 @@ pub fn pow_with_uint+Mul>( total } +#[cfg(test)] +fn test_num(ten: T, two: T) { + assert!(ten.add(&two) == cast(12)); + assert!(ten.sub(&two) == cast(8)); + assert!(ten.mul(&two) == cast(20)); + assert!(ten.div(&two) == cast(5)); + assert!(ten.modulo(&two) == cast(0)); + + assert!(ten.add(&two) == ten + two); + assert!(ten.sub(&two) == ten - two); + assert!(ten.mul(&two) == ten * two); + assert!(ten.div(&two) == ten / two); + assert!(ten.modulo(&two) == ten % two); +} + +#[test] fn test_u8_num() { test_num(10u8, 2u8) } +#[test] fn test_u16_num() { test_num(10u16, 2u16) } +#[test] fn test_u32_num() { test_num(10u32, 2u32) } +#[test] fn test_u64_num() { test_num(10u64, 2u64) } +#[test] fn test_uint_num() { test_num(10u, 2u) } +#[test] fn test_i8_num() { test_num(10i8, 2i8) } +#[test] fn test_i16_num() { test_num(10i16, 2i16) } +#[test] fn test_i32_num() { test_num(10i32, 2i32) } +#[test] fn test_i64_num() { test_num(10i64, 2i64) } +#[test] fn test_int_num() { test_num(10i, 2i) } +#[test] fn test_f32_num() { test_num(10f32, 2f32) } +#[test] fn test_f64_num() { test_num(10f64, 2f64) } +#[test] fn test_float_num() { test_num(10f, 2f) } + macro_rules! test_cast_20( ($_20:expr) => ({ let _20 = $_20; @@ -263,26 +292,3 @@ macro_rules! test_cast_20( #[test] fn test_f32_cast() { test_cast_20!(20f32) } #[test] fn test_f64_cast() { test_cast_20!(20f64) } #[test] fn test_float_cast() { test_cast_20!(20f) } - -#[test] -fn test_generic_cast() { - use ops::Add; - - fn add_2 + NumCast>(n: T) -> T { - n + cast(2) - } - - assert!(add_2(1u) == 3u); - assert!(add_2(1u8) == 3u8); - assert!(add_2(1u16) == 3u16); - assert!(add_2(1u32) == 3u32); - assert!(add_2(1u64) == 3u64); - assert!(add_2(1i) == 3i); - assert!(add_2(1i8) == 3i8); - assert!(add_2(1i16) == 3i16); - assert!(add_2(1i32) == 3i32); - assert!(add_2(1i64) == 3i64); - assert!(add_2(1f) == 3f); - assert!(add_2(1f32) == 3f32); - assert!(add_2(1f64) == 3f64); -} diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 412921b8c286e..1cbdabafdab96 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -411,18 +411,6 @@ pub fn test_ranges() { } } -#[test] -pub fn test_num() { - let ten: T = num::cast(10); - let two: T = num::cast(2); - - assert!((ten.add(&two) == num::cast(12))); - assert!((ten.sub(&two) == num::cast(8))); - assert!((ten.mul(&two) == num::cast(20))); - assert!((ten.div(&two) == num::cast(5))); - assert!((ten.modulo(&two) == num::cast(0))); -} - #[test] #[should_fail] #[ignore(cfg(windows))] From 0615fddd80116d63fba7040bdd89ad59117037dd Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 14 Apr 2013 05:27:32 +1000 Subject: [PATCH 182/403] Remove unnecessary enclosing modules for NumCast impls --- src/libcore/num/num.rs | 52 ++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index fc81393693c87..19a1e276d3754 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -110,37 +110,29 @@ pub trait NumCast { macro_rules! impl_num_cast( ($T:ty, $conv:ident) => ( - // FIXME #4375: This enclosing module is necessary because - // of a bug with macros expanding into multiple items - pub mod $conv { - use num::NumCast; - - #[cfg(notest)] - impl NumCast for $T { - #[doc = "Cast `n` to a `$T`"] - #[inline(always)] - fn from(n: N) -> $T { - // `$conv` could be generated using `concat_idents!`, but that - // macro seems to be broken at the moment - n.$conv() - } - - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } + impl NumCast for $T { + #[inline(always)] + fn from(n: N) -> $T { + // `$conv` could be generated using `concat_idents!`, but that + // macro seems to be broken at the moment + n.$conv() } + + #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } + #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } + #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } + #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } + #[inline(always)] fn to_uint(&self) -> uint { *self as uint } + + #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } + #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } + #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } + #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } + #[inline(always)] fn to_int(&self) -> int { *self as int } + + #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } + #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } + #[inline(always)] fn to_float(&self) -> float { *self as float } } ) ) From 78bc10d94bcaecbc45687b82e82dd46a79cd29b3 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sat, 13 Apr 2013 16:17:30 -0400 Subject: [PATCH 183/403] Doc review, as requested :-). Mostly just phrasing things differently, which is a matter of taste. Feel free to use or not use any of the changes I'm suggesting. I would say this one thing should be changed, though, not necessarily the way I changed it here. * Convert any string (literal, `@`, `&`, `~`) * that contains a base64 encoded value, to the byte values it encodes. If this structure is going to be used, either the entire clause, 'that contains a base64 encoded value', should be bracketed by commas, or the comma at the end of the clause should be removed. --- src/libstd/base64.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 5b1e82ce1f00e..054f3a2b10839 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -28,7 +28,7 @@ static CHARS: [char, ..64] = [ impl<'self> ToBase64 for &'self [u8] { /** - * Turn a vector of `u8` bytes into a string representing them in base64. + * Turn a vector of `u8` bytes into a base64 string. * * *Example*: * @@ -92,7 +92,7 @@ impl<'self> ToBase64 for &'self [u8] { impl<'self> ToBase64 for &'self str { /** - * Convert any string (literal, `@`, `&`, `~`) to base64 encoding. + * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding. * * * *Example*: @@ -119,8 +119,8 @@ pub trait FromBase64 { impl FromBase64 for ~[u8] { /** - * Turn a vector of `u8`s representing characters - * encoding byte values in base64 into the vector of `u8` byte values. + * Convert base64 `u8` vector into u8 byte values. + * Every 4 encoded characters is converted into 3 octets, modulo padding. * * *Example*: * @@ -200,16 +200,15 @@ impl FromBase64 for ~[u8] { impl FromBase64 for ~str { /** - * Convert any string (literal, `@`, `&`, `~`) - * that contains a base64 encoded value, to the byte values it encodes. + * Convert any base64 encoded string (literal, `@`, `&`, or `~`) + * to the byte values it encodes. * * You can use the `from_bytes` function in `core::str` * to turn a `[u8]` into a string with characters corresponding to those values. * * *Example*: * - * This is an example of going from a string literal to the base64 encoding - * and back to the same string. + * This converts a string literal to base64 and back. * * ~~~~ * extern mod std; From 4bfa3c6663ad6facdbdb8bd533442b050085f753 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 01:31:10 -0400 Subject: [PATCH 184/403] Add a lint mode for unused unsafe blocks/functions --- src/librustc/middle/borrowck/check_loans.rs | 120 ++++++++++++++------ src/librustc/middle/lint.rs | 57 +++++++++- src/librustc/middle/resolve.rs | 16 +-- src/librustc/middle/ty.rs | 21 ++-- src/librustc/middle/typeck/check/mod.rs | 36 ++++-- src/test/compile-fail/unused-unsafe.rs | 44 +++++++ 6 files changed, 224 insertions(+), 70 deletions(-) create mode 100644 src/test/compile-fail/unused-unsafe.rs diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 721bb99626249..116b70bf7e320 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -33,6 +33,7 @@ use util::ppaux::ty_to_str; use core::hashmap::HashSet; use core::uint; +use core::util::with; use syntax::ast::m_mutbl; use syntax::ast; use syntax::ast_util; @@ -40,13 +41,18 @@ use syntax::codemap::span; use syntax::print::pprust; use syntax::visit; +struct PurityState { + def: ast::node_id, + purity: ast::purity +} + struct CheckLoanCtxt { bccx: @BorrowckCtxt, req_maps: ReqMaps, reported: HashSet, - declared_purity: @mut ast::purity, + declared_purity: @mut PurityState, fn_args: @mut @~[ast::node_id] } @@ -62,6 +68,16 @@ enum purity_cause { pc_cmt(bckerr) } +// if we're not pure, why? +#[deriving(Eq)] +enum impurity_cause { + // some surrounding block was marked as 'unsafe' + pc_unsafe, + + // nothing was unsafe, and nothing was pure + pc_default, +} + pub fn check_loans(bccx: @BorrowckCtxt, +req_maps: ReqMaps, crate: @ast::crate) { @@ -69,7 +85,8 @@ pub fn check_loans(bccx: @BorrowckCtxt, bccx: bccx, req_maps: req_maps, reported: HashSet::new(), - declared_purity: @mut ast::impure_fn, + declared_purity: @mut PurityState { purity: ast::impure_fn, + def: 0 }, fn_args: @mut @~[] }; let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr, @@ -106,16 +123,18 @@ pub impl assignment_type { pub impl CheckLoanCtxt { fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn purity(&mut self, scope_id: ast::node_id) -> Option { - let default_purity = match *self.declared_purity { + fn purity(&mut self, scope_id: ast::node_id) + -> Either + { + let default_purity = match self.declared_purity.purity { // an unsafe declaration overrides all - ast::unsafe_fn => return None, + ast::unsafe_fn => return Right(pc_unsafe), // otherwise, remember what was declared as the // default, but we must scan for requirements // imposed by the borrow check - ast::pure_fn => Some(pc_pure_fn), - ast::extern_fn | ast::impure_fn => None + ast::pure_fn => Left(pc_pure_fn), + ast::extern_fn | ast::impure_fn => Right(pc_default) }; // scan to see if this scope or any enclosing scope requires @@ -125,7 +144,7 @@ pub impl CheckLoanCtxt { loop { match self.req_maps.pure_map.find(&scope_id) { None => (), - Some(e) => return Some(pc_cmt(*e)) + Some(e) => return Left(pc_cmt(*e)) } match self.tcx().region_maps.opt_encl_scope(scope_id) { @@ -171,7 +190,7 @@ pub impl CheckLoanCtxt { // overloaded operators the callee has an id but no expr. // annoying. fn check_pure_callee_or_arg(&mut self, - pc: purity_cause, + pc: Either, opt_expr: Option<@ast::expr>, callee_id: ast::node_id, callee_span: span) { @@ -196,7 +215,7 @@ pub impl CheckLoanCtxt { match opt_expr { Some(expr) => { match expr.node { - ast::expr_path(_) if pc == pc_pure_fn => { + ast::expr_path(_) if pc == Left(pc_pure_fn) => { let def = *self.tcx().def_map.get(&expr.id); let did = ast_util::def_id_of_def(def); let is_fn_arg = @@ -361,10 +380,10 @@ pub impl CheckLoanCtxt { // if this is a pure function, only loan-able state can be // assigned, because it is uniquely tied to this function and // is not visible from the outside - match self.purity(ex.id) { - None => (), - Some(pc_cmt(_)) => { - let purity = self.purity(ex.id).get(); + let purity = self.purity(ex.id); + match purity { + Right(_) => (), + Left(pc_cmt(_)) => { // Subtle: Issue #3162. If we are enforcing purity // because there is a reference to aliasable, mutable data // that we require to be immutable, we can't allow writes @@ -376,10 +395,10 @@ pub impl CheckLoanCtxt { ex.span, at.ing_form(self.bccx.cmt_to_str(cmt))); } - Some(pc_pure_fn) => { + Left(pc_pure_fn) => { if cmt.lp.is_none() { self.report_purity_error( - pc_pure_fn, ex.span, + purity, ex.span, at.ing_form(self.bccx.cmt_to_str(cmt))); } } @@ -462,14 +481,23 @@ pub impl CheckLoanCtxt { } } - fn report_purity_error(&mut self, pc: purity_cause, sp: span, msg: ~str) { + fn report_purity_error(&mut self, pc: Either, + sp: span, msg: ~str) { match pc { - pc_pure_fn => { + Right(pc_default) => { fail!(~"pc_default should be filtered sooner") } + Right(pc_unsafe) => { + // this error was prevented by being marked as unsafe, so flag the + // definition as having contributed to the validity of the program + let def = self.declared_purity.def; + debug!("flagging %? as a used unsafe source", def); + self.tcx().used_unsafe.insert(def); + } + Left(pc_pure_fn) => { self.tcx().sess.span_err( sp, fmt!("%s prohibited in pure context", msg)); } - pc_cmt(ref e) => { + Left(pc_cmt(ref e)) => { if self.reported.insert((*e).cmt.id) { self.tcx().sess.span_err( (*e).cmt.span, @@ -556,16 +584,32 @@ pub impl CheckLoanCtxt { callee_id: ast::node_id, callee_span: span, args: &[@ast::expr]) { - match self.purity(expr.id) { - None => {} - Some(ref pc) => { - self.check_pure_callee_or_arg( - (*pc), callee, callee_id, callee_span); - for args.each |arg| { - self.check_pure_callee_or_arg( - (*pc), Some(*arg), arg.id, arg.span); + let pc = self.purity(expr.id); + match pc { + // no purity, no need to check for anything + Right(pc_default) => return, + + // some form of purity, definitely need to check + Left(_) => (), + + // Unsafe trumped. To see if the unsafe is necessary, see what the + // purity would have been without a trump, and if it's some form + // of purity then we need to go ahead with the check + Right(pc_unsafe) => { + match do with(&mut self.declared_purity.purity, + ast::impure_fn) { self.purity(expr.id) } { + Right(pc_unsafe) => fail!(~"unsafe can't trump twice"), + Right(pc_default) => return, + Left(_) => () + } } - } + + } + self.check_pure_callee_or_arg( + pc, callee, callee_id, callee_span); + for args.each |arg| { + self.check_pure_callee_or_arg( + pc, Some(*arg), arg.id, arg.span); } } } @@ -580,27 +624,32 @@ fn check_loans_in_fn(fk: &visit::fn_kind, let is_stack_closure = self.is_stack_closure(id); let fty = ty::node_id_to_type(self.tcx(), id); - let declared_purity; + let declared_purity, src; match *fk { visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_dtor(*) => { declared_purity = ty::ty_fn_purity(fty); + src = id; } visit::fk_anon(*) | visit::fk_fn_block(*) => { let fty_sigil = ty::ty_closure_sigil(fty); check_moves_from_captured_variables(self, id, fty_sigil); - declared_purity = ty::determine_inherited_purity( - *self.declared_purity, - ty::ty_fn_purity(fty), + let pair = ty::determine_inherited_purity( + (self.declared_purity.purity, self.declared_purity.def), + (ty::ty_fn_purity(fty), id), fty_sigil); + declared_purity = pair.first(); + src = pair.second(); } } debug!("purity on entry=%?", copy self.declared_purity); do save_and_restore_managed(self.declared_purity) { do save_and_restore_managed(self.fn_args) { - *self.declared_purity = declared_purity; + self.declared_purity = @mut PurityState { + purity: declared_purity, def: src + }; match *fk { visit::fk_anon(*) | @@ -754,7 +803,10 @@ fn check_loans_in_block(blk: &ast::blk, ast::default_blk => { } ast::unsafe_blk => { - *self.declared_purity = ast::unsafe_fn; + *self.declared_purity = PurityState { + purity: ast::unsafe_fn, + def: blk.node.id, + }; } } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 6f8992bf1ca4a..876ed76f98741 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -75,6 +75,7 @@ pub enum lint { default_methods, deprecated_mutable_fields, deprecated_drop, + unused_unsafe, foreign_mode, managed_heap_memory, @@ -256,6 +257,13 @@ pub fn get_lint_dict() -> LintDict { default: deny }), + (~"unused_unsafe", + LintSpec { + lint: unused_unsafe, + desc: "unnecessary use of an \"unsafe\" block or function", + default: warn + }), + (~"unused_variable", LintSpec { lint: unused_variable, @@ -490,6 +498,7 @@ fn check_item(i: @ast::item, cx: ty::ctxt) { check_item_default_methods(cx, i); check_item_deprecated_mutable_fields(cx, i); check_item_deprecated_drop(cx, i); + check_item_unused_unsafe(cx, i); } // Take a visitor, and modify it so that it will not proceed past subitems. @@ -923,19 +932,55 @@ fn check_item_non_camel_case_types(cx: ty::ctxt, it: @ast::item) { } } +fn check_item_unused_unsafe(cx: ty::ctxt, it: @ast::item) { + let visit_expr: @fn(@ast::expr) = |e| { + match e.node { + ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => { + if !cx.used_unsafe.contains(&blk.node.id) { + cx.sess.span_lint(unused_unsafe, blk.node.id, it.id, + blk.span, + ~"unnecessary \"unsafe\" block"); + } + } + _ => () + } + }; + + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: visit_expr, + .. *visit::default_simple_visitor() + })); + visit::visit_item(it, (), visit); +} + fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl, _body: &ast::blk, span: span, id: ast::node_id) { debug!("lint check_fn fk=%? id=%?", fk, id); - // don't complain about blocks, since they tend to get their modes - // specified from the outside + // Check for an 'unsafe fn' which doesn't need to be unsafe + match *fk { + visit::fk_item_fn(_, _, ast::unsafe_fn, _) => { + if !tcx.used_unsafe.contains(&id) { + tcx.sess.span_lint(unused_unsafe, id, id, span, + ~"unnecessary \"unsafe\" function"); + } + } + _ => () + } + + // Check for deprecated modes match *fk { - visit::fk_fn_block(*) => { return; } - _ => {} + // don't complain about blocks, since they tend to get their modes + // specified from the outside + visit::fk_fn_block(*) => {} + + _ => { + let fn_ty = ty::node_id_to_type(tcx, id); + check_fn_deprecated_modes(tcx, fn_ty, decl, span, id); + } } - let fn_ty = ty::node_id_to_type(tcx, id); - check_fn_deprecated_modes(tcx, fn_ty, decl, span, id); } fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: &ast::fn_decl, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index fa902b7bf56a4..c9381757d77dc 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5212,17 +5212,11 @@ pub impl Resolver { import_resolution.span != dummy_sp() && import_resolution.privacy != Public { import_resolution.state.warned = true; - match self.unused_import_lint_level(module_) { - warn => { - self.session.span_warn(copy import_resolution.span, - ~"unused import"); - } - deny | forbid => { - self.session.span_err(copy import_resolution.span, - ~"unused import"); - } - allow => () - } + let span = import_resolution.span; + self.session.span_lint_level( + self.unused_import_lint_level(module_), + span, + ~"unused import"); } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index a26c1c1e76635..f62e366ebdcaa 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -300,7 +300,11 @@ struct ctxt_ { destructors: @mut HashSet, // Maps a trait onto a mapping from self-ty to impl - trait_impls: @mut HashMap> + trait_impls: @mut HashMap>, + + // Set of used unsafe nodes (functions or blocks). Unsafe nodes not + // present in this set can be warned about. + used_unsafe: @mut HashSet, } enum tbox_flag { @@ -885,7 +889,8 @@ pub fn mk_ctxt(s: session::Session, supertraits: @mut HashMap::new(), destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), - trait_impls: @mut HashMap::new() + trait_impls: @mut HashMap::new(), + used_unsafe: @mut HashSet::new(), } } @@ -4309,16 +4314,16 @@ pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint { } // Determine what purity to check a nested function under -pub fn determine_inherited_purity(parent_purity: ast::purity, - child_purity: ast::purity, - child_sigil: ast::Sigil) - -> ast::purity { +pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id), + child: (ast::purity, ast::node_id), + child_sigil: ast::Sigil) + -> (ast::purity, ast::node_id) { // If the closure is a stack closure and hasn't had some non-standard // purity inferred for it, then check it under its parent's purity. // Otherwise, use its own match child_sigil { - ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity, - _ => child_purity + ast::BorrowedSigil if child.first() == ast::impure_fn => parent, + _ => child } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 2d1c940103a7a..5ec4c233bc0d2 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -179,6 +179,11 @@ pub enum FnKind { Vanilla } +struct PurityState { + purity: ast::purity, + from: ast::node_id, +} + pub struct FnCtxt { // var_bindings, locals and next_var_id are shared // with any nested functions that capture the environment @@ -187,7 +192,7 @@ pub struct FnCtxt { ret_ty: ty::t, // Used by loop bodies that return from the outer function indirect_ret_ty: Option, - purity: ast::purity, + ps: PurityState, // Sometimes we generate region pointers where the precise region // to use is not known. For example, an expression like `&x.f` @@ -238,7 +243,7 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt, @mut FnCtxt { ret_ty: rty, indirect_ret_ty: None, - purity: ast::pure_fn, + ps: PurityState { purity: ast::pure_fn, from: 0 }, region_lb: region_bnd, in_scope_regions: @Nil, fn_kind: Vanilla, @@ -265,7 +270,7 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt, ty::ty_bare_fn(ref fn_ty) => { let fcx = check_fn(ccx, self_info, fn_ty.purity, - &fn_ty.sig, decl, body, Vanilla, + &fn_ty.sig, decl, id, body, Vanilla, @Nil, blank_inherited(ccx));; vtable::resolve_in_block(fcx, body); @@ -282,6 +287,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, purity: ast::purity, fn_sig: &ty::FnSig, decl: &ast::fn_decl, + id: ast::node_id, body: &ast::blk, fn_kind: FnKind, inherited_isr: isr_alist, @@ -342,7 +348,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, @mut FnCtxt { ret_ty: ret_ty, indirect_ret_ty: indirect_ret_ty, - purity: purity, + ps: PurityState { purity: purity, from: id }, region_lb: body.node.id, in_scope_regions: isr, fn_kind: fn_kind, @@ -867,8 +873,12 @@ pub impl FnCtxt { } fn require_unsafe(&self, sp: span, op: ~str) { - match self.purity { - ast::unsafe_fn => {/*ok*/} + match self.ps.purity { + ast::unsafe_fn => { + // ok, but flag that we used the source of unsafeness + debug!("flagging %? as a used unsafe source", self.ps.from); + self.tcx().used_unsafe.insert(self.ps.from); + } _ => { self.ccx.tcx.sess.span_err( sp, @@ -1679,12 +1689,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(expr.id, fty); - let inherited_purity = - ty::determine_inherited_purity(copy fcx.purity, purity, + let (inherited_purity, id) = + ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.from), + (purity, expr.id), sigil); check_fn(fcx.ccx, None, inherited_purity, &fty_sig, - decl, body, fn_kind, fcx.in_scope_regions, fcx.inh); + decl, id, body, fn_kind, fcx.in_scope_regions, fcx.inh); } @@ -2923,8 +2934,11 @@ pub fn check_block_with_expected(fcx0: @mut FnCtxt, blk: &ast::blk, expected: Option) { let fcx = match blk.node.rules { - ast::unsafe_blk => @mut FnCtxt {purity: ast::unsafe_fn,.. copy *fcx0}, - ast::default_blk => fcx0 + ast::unsafe_blk => @mut FnCtxt { + ps: PurityState { purity: ast::unsafe_fn, from: blk.node.id }, + .. copy *fcx0 + }, + ast::default_blk => fcx0 }; do fcx.with_region_lb(blk.node.id) { let mut warned = false; diff --git a/src/test/compile-fail/unused-unsafe.rs b/src/test/compile-fail/unused-unsafe.rs new file mode 100644 index 0000000000000..368a0fbe9bece --- /dev/null +++ b/src/test/compile-fail/unused-unsafe.rs @@ -0,0 +1,44 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Exercise the unused_unsafe attribute in some positive and negative cases + +#[deny(unused_unsafe)]; + +use core::libc; + +fn callback(_f: &fn() -> T) -> T { fail!() } + +fn bad1() { unsafe {} } //~ ERROR: unnecessary "unsafe" block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary "unsafe" block +unsafe fn bad3() {} //~ ERROR: unnecessary "unsafe" function +unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary "unsafe" function + //~^ ERROR: unnecessary "unsafe" block +fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary "unsafe" block + +unsafe fn good0() { libc::exit(1) } +fn good1() { unsafe { libc::exit(1) } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> ~[~str] { libc::exit(2) } + + do callback { + what(); + } + } +} + +#[allow(unused_unsafe)] unsafe fn allowed0() {} +#[allow(unused_unsafe)] fn allowed1() { unsafe {} } + +fn main() { } From d9595d1737677dd61d9f52f674c34f13d708e39c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 01:31:23 -0400 Subject: [PATCH 185/403] core: remove unnecessary unsafe blocks/functions --- src/libcore/comm.rs | 18 ++--- src/libcore/io.rs | 23 +++--- src/libcore/managed.rs | 4 +- src/libcore/num/float.rs | 12 +-- src/libcore/path.rs | 60 ++++++-------- src/libcore/ptr.rs | 8 +- src/libcore/rt/context.rs | 4 +- src/libcore/rt/thread_local_storage.rs | 6 +- src/libcore/run.rs | 106 ++++++++++++------------- src/libcore/str.rs | 44 +++++----- src/libcore/sys.rs | 12 +-- src/libcore/task/mod.rs | 79 ++++++++++++------ src/libcore/task/spawn.rs | 4 +- src/libcore/unstable.rs | 42 ++++------ src/libcore/unstable/exchange_alloc.rs | 30 ++++--- src/libcore/unstable/extfmt.rs | 12 +-- src/libcore/unstable/lang.rs | 4 +- 17 files changed, 226 insertions(+), 242 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index 9fd6f1db793b0..d665bf311f362 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -188,16 +188,14 @@ impl Peekable for Port { #[inline(always)] fn port_peek(self: &Port) -> bool { - unsafe { - let mut endp = None; - endp <-> self.endp; - let peek = match &endp { - &Some(ref endp) => peek(endp), - &None => fail!(~"peeking empty stream") - }; - self.endp <-> endp; - peek - } + let mut endp = None; + endp <-> self.endp; + let peek = match &endp { + &Some(ref endp) => peek(endp), + &None => fail!(~"peeking empty stream") + }; + self.endp <-> endp; + peek } impl Selectable for Port { diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 3853e7c8f2b0e..3c5900f51a247 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -1536,11 +1536,8 @@ pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] { pub fn with_str_writer(f: &fn(@Writer)) -> ~str { let mut v = with_bytes_writer(f); - // FIXME (#3758): This should not be needed. - unsafe { - // Make sure the vector has a trailing null and is proper utf8. - v.push(0); - } + // Make sure the vector has a trailing null and is proper utf8. + v.push(0); assert!(str::is_utf8(v)); unsafe { ::cast::transmute(v) } @@ -1640,16 +1637,14 @@ pub mod fsync { // outer res pub fn FILE_res_sync(file: &FILERes, opt_level: Option, blk: &fn(v: Res<*libc::FILE>)) { - unsafe { - blk(Res(Arg { - val: file.f, opt_level: opt_level, - fsync_fn: |file, l| { - unsafe { - os::fsync_fd(libc::fileno(file), l) as int - } + blk(Res(Arg { + val: file.f, opt_level: opt_level, + fsync_fn: |file, l| { + unsafe { + os::fsync_fd(libc::fileno(file), l) as int } - })); - } + } + })); } // fsync fd after executing blk diff --git a/src/libcore/managed.rs b/src/libcore/managed.rs index 234b710d238b0..2bd3959acf4de 100644 --- a/src/libcore/managed.rs +++ b/src/libcore/managed.rs @@ -38,13 +38,13 @@ pub mod raw { #[inline(always)] pub fn ptr_eq(a: @T, b: @T) -> bool { //! Determine if two shared boxes point to the same object - unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) } + ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) } #[inline(always)] pub fn mut_ptr_eq(a: @mut T, b: @mut T) -> bool { //! Determine if two mutable shared boxes point to the same object - unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) } + ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) } #[cfg(notest)] diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 1ab0e24f62dc9..87d04b05087c2 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -369,27 +369,27 @@ pub fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) } #[inline(always)] pub fn abs(x: float) -> float { - unsafe { f64::abs(x as f64) as float } + f64::abs(x as f64) as float } #[inline(always)] pub fn sqrt(x: float) -> float { - unsafe { f64::sqrt(x as f64) as float } + f64::sqrt(x as f64) as float } #[inline(always)] pub fn atan(x: float) -> float { - unsafe { f64::atan(x as f64) as float } + f64::atan(x as f64) as float } #[inline(always)] pub fn sin(x: float) -> float { - unsafe { f64::sin(x as f64) as float } + f64::sin(x as f64) as float } #[inline(always)] pub fn cos(x: float) -> float { - unsafe { f64::cos(x as f64) as float } + f64::cos(x as f64) as float } #[inline(always)] pub fn tan(x: float) -> float { - unsafe { f64::tan(x as f64) as float } + f64::tan(x as f64) as float } #[cfg(notest)] diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 7de0f355dd21d..0e8dbd144b143 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -389,13 +389,11 @@ impl GenericPath for PosixPath { } fn dirname(&self) -> ~str { - unsafe { - let s = self.dir_path().to_str(); - if s.len() == 0 { - ~"." - } else { - s - } + let s = self.dir_path().to_str(); + if s.len() == 0 { + ~"." + } else { + s } } @@ -439,10 +437,8 @@ impl GenericPath for PosixPath { } fn with_filename(&self, f: &str) -> PosixPath { - unsafe { - assert!(! str::any(f, |c| windows::is_sep(c as u8))); - self.dir_path().push(f) - } + assert!(! str::any(f, |c| windows::is_sep(c as u8))); + self.dir_path().push(f) } fn with_filestem(&self, s: &str) -> PosixPath { @@ -509,7 +505,7 @@ impl GenericPath for PosixPath { for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| { ss.push(s.to_owned()) } - unsafe { v.push_all_move(ss); } + v.push_all_move(ss); } PosixPath { is_absolute: self.is_absolute, components: v } @@ -521,14 +517,14 @@ impl GenericPath for PosixPath { for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| { ss.push(s.to_owned()) } - unsafe { v.push_all_move(ss); } + v.push_all_move(ss); PosixPath { components: v, ..copy *self } } fn pop(&self) -> PosixPath { let mut cs = copy self.components; if cs.len() != 0 { - unsafe { cs.pop(); } + cs.pop(); } return PosixPath { is_absolute: self.is_absolute, @@ -607,13 +603,11 @@ impl GenericPath for WindowsPath { } fn dirname(&self) -> ~str { - unsafe { - let s = self.dir_path().to_str(); - if s.len() == 0 { - ~"." - } else { - s - } + let s = self.dir_path().to_str(); + if s.len() == 0 { + ~"." + } else { + s } } @@ -770,7 +764,7 @@ impl GenericPath for WindowsPath { for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| { ss.push(s.to_owned()) } - unsafe { v.push_all_move(ss); } + v.push_all_move(ss); } // tedious, but as-is, we can't use ..self return WindowsPath { @@ -787,14 +781,14 @@ impl GenericPath for WindowsPath { for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| { ss.push(s.to_owned()) } - unsafe { v.push_all_move(ss); } + v.push_all_move(ss); return WindowsPath { components: v, ..copy *self } } fn pop(&self) -> WindowsPath { let mut cs = copy self.components; if cs.len() != 0 { - unsafe { cs.pop(); } + cs.pop(); } return WindowsPath { host: copy self.host, @@ -820,18 +814,14 @@ impl GenericPath for WindowsPath { pub fn normalize(components: &[~str]) -> ~[~str] { let mut cs = ~[]; - unsafe { - for components.each |c| { - unsafe { - if *c == ~"." && components.len() > 1 { loop; } - if *c == ~"" { loop; } - if *c == ~".." && cs.len() != 0 { - cs.pop(); - loop; - } - cs.push(copy *c); - } + for components.each |c| { + if *c == ~"." && components.len() > 1 { loop; } + if *c == ~"" { loop; } + if *c == ~".." && cs.len() != 0 { + cs.pop(); + loop; } + cs.push(copy *c); } cs } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 70bdb6f41d8ba..14e17de4fbda0 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -55,17 +55,13 @@ pub fn addr_of(val: &T) -> *T { unsafe { rusti::addr_of(*val) } } /// Calculate the offset from a pointer #[inline(always)] pub fn offset(ptr: *T, count: uint) -> *T { - unsafe { - (ptr as uint + count * sys::size_of::()) as *T - } + (ptr as uint + count * sys::size_of::()) as *T } /// Calculate the offset from a const pointer #[inline(always)] pub fn const_offset(ptr: *const T, count: uint) -> *const T { - unsafe { - (ptr as uint + count * sys::size_of::()) as *T - } + (ptr as uint + count * sys::size_of::()) as *T } /// Calculate the offset from a mut pointer diff --git a/src/libcore/rt/context.rs b/src/libcore/rt/context.rs index 9dc9f5da8c1da..4714be9e3d520 100644 --- a/src/libcore/rt/context.rs +++ b/src/libcore/rt/context.rs @@ -205,8 +205,6 @@ fn align_down(sp: *mut uint) -> *mut uint { #[inline(always)] pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { use core::sys::size_of; - unsafe { - (ptr as int + count * (size_of::() as int)) as *mut T - } + (ptr as int + count * (size_of::() as int)) as *mut T } diff --git a/src/libcore/rt/thread_local_storage.rs b/src/libcore/rt/thread_local_storage.rs index c8a9689bbc67a..366996fb93560 100644 --- a/src/libcore/rt/thread_local_storage.rs +++ b/src/libcore/rt/thread_local_storage.rs @@ -21,17 +21,17 @@ pub type Key = pthread_key_t; #[cfg(unix)] pub unsafe fn create(key: &mut Key) { - unsafe { assert!(0 == pthread_key_create(key, null())); } + assert!(0 == pthread_key_create(key, null())); } #[cfg(unix)] pub unsafe fn set(key: Key, value: *mut c_void) { - unsafe { assert!(0 == pthread_setspecific(key, value)); } + assert!(0 == pthread_setspecific(key, value)); } #[cfg(unix)] pub unsafe fn get(key: Key) -> *mut c_void { - unsafe { pthread_getspecific(key) } + pthread_getspecific(key) } #[cfg(target_os="macos")] diff --git a/src/libcore/run.rs b/src/libcore/run.rs index f6f4b9a397d81..49df2938afd40 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -382,64 +382,62 @@ pub struct ProgramOutput {status: int, out: ~str, err: ~str} * the contents of stdout and the contents of stderr. */ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { - unsafe { - let pipe_in = os::pipe(); - let pipe_out = os::pipe(); - let pipe_err = os::pipe(); - let pid = spawn_process(prog, args, &None, &None, - pipe_in.in, pipe_out.out, pipe_err.out); - - os::close(pipe_in.in); - os::close(pipe_out.out); - os::close(pipe_err.out); - if pid == -1i32 { - os::close(pipe_in.out); - os::close(pipe_out.in); - os::close(pipe_err.in); - fail!(); - } + let pipe_in = os::pipe(); + let pipe_out = os::pipe(); + let pipe_err = os::pipe(); + let pid = spawn_process(prog, args, &None, &None, + pipe_in.in, pipe_out.out, pipe_err.out); + os::close(pipe_in.in); + os::close(pipe_out.out); + os::close(pipe_err.out); + if pid == -1i32 { os::close(pipe_in.out); + os::close(pipe_out.in); + os::close(pipe_err.in); + fail!(); + } - // Spawn two entire schedulers to read both stdout and sterr - // in parallel so we don't deadlock while blocking on one - // or the other. FIXME (#2625): Surely there's a much more - // clever way to do this. - let (p, ch) = stream(); - let ch = SharedChan(ch); - let ch_clone = ch.clone(); - do task::spawn_sched(task::SingleThreaded) { - let errput = readclose(pipe_err.in); - ch.send((2, errput)); - }; - do task::spawn_sched(task::SingleThreaded) { - let output = readclose(pipe_out.in); - ch_clone.send((1, output)); - }; - let status = run::waitpid(pid); - let mut errs = ~""; - let mut outs = ~""; - let mut count = 2; - while count > 0 { - let stream = p.recv(); - match stream { - (1, copy s) => { - outs = s; - } - (2, copy s) => { - errs = s; - } - (n, _) => { - fail!(fmt!("program_output received an unexpected file \ - number: %u", n)); - } - }; - count -= 1; + os::close(pipe_in.out); + + // Spawn two entire schedulers to read both stdout and sterr + // in parallel so we don't deadlock while blocking on one + // or the other. FIXME (#2625): Surely there's a much more + // clever way to do this. + let (p, ch) = stream(); + let ch = SharedChan(ch); + let ch_clone = ch.clone(); + do task::spawn_sched(task::SingleThreaded) { + let errput = readclose(pipe_err.in); + ch.send((2, errput)); + }; + do task::spawn_sched(task::SingleThreaded) { + let output = readclose(pipe_out.in); + ch_clone.send((1, output)); + }; + let status = run::waitpid(pid); + let mut errs = ~""; + let mut outs = ~""; + let mut count = 2; + while count > 0 { + let stream = p.recv(); + match stream { + (1, copy s) => { + outs = s; + } + (2, copy s) => { + errs = s; + } + (n, _) => { + fail!(fmt!("program_output received an unexpected file \ + number: %u", n)); + } }; - return ProgramOutput {status: status, - out: outs, - err: errs}; - } + count -= 1; + }; + return ProgramOutput {status: status, + out: outs, + err: errs}; } pub fn writeclose(fd: c_int, s: ~str) { diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 521c8266e0505..b0653db365e03 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -170,18 +170,16 @@ pub fn push_char(s: &mut ~str, ch: char) { /// Convert a char to a string pub fn from_char(ch: char) -> ~str { let mut buf = ~""; - unsafe { push_char(&mut buf, ch); } + push_char(&mut buf, ch); buf } /// Convert a vector of chars to a string pub fn from_chars(chs: &[char]) -> ~str { let mut buf = ~""; - unsafe { - reserve(&mut buf, chs.len()); - for vec::each(chs) |ch| { - push_char(&mut buf, *ch); - } + reserve(&mut buf, chs.len()); + for vec::each(chs) |ch| { + push_char(&mut buf, *ch); } buf } @@ -226,9 +224,7 @@ pub fn push_str(lhs: &mut ~str, rhs: &str) { #[inline(always)] pub fn append(lhs: ~str, rhs: &str) -> ~str { let mut v = lhs; - unsafe { - push_str_no_overallocate(&mut v, rhs); - } + push_str_no_overallocate(&mut v, rhs); v } @@ -236,7 +232,7 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str { pub fn concat(v: &[~str]) -> ~str { let mut s: ~str = ~""; for vec::each(v) |ss| { - unsafe { push_str(&mut s, *ss) }; + push_str(&mut s, *ss); } s } @@ -245,8 +241,8 @@ pub fn concat(v: &[~str]) -> ~str { pub fn connect(v: &[~str], sep: &str) -> ~str { let mut s = ~"", first = true; for vec::each(v) |ss| { - if first { first = false; } else { unsafe { push_str(&mut s, sep); } } - unsafe { push_str(&mut s, *ss) }; + if first { first = false; } else { push_str(&mut s, sep); } + push_str(&mut s, *ss); } s } @@ -255,8 +251,8 @@ pub fn connect(v: &[~str], sep: &str) -> ~str { pub fn connect_slices(v: &[&str], sep: &str) -> ~str { let mut s = ~"", first = true; for vec::each(v) |ss| { - if first { first = false; } else { unsafe { push_str(&mut s, sep); } } - unsafe { push_str(&mut s, *ss) }; + if first { first = false; } else { push_str(&mut s, sep); } + push_str(&mut s, *ss); } s } @@ -2251,16 +2247,14 @@ pub mod raw { assert!((end <= n)); let mut v = vec::with_capacity(end - begin + 1u); - unsafe { - do vec::as_imm_buf(v) |vbuf, _vlen| { - let vbuf = ::cast::transmute_mut_unsafe(vbuf); - let src = ptr::offset(sbuf, begin); - ptr::copy_memory(vbuf, src, end - begin); - } - vec::raw::set_len(&mut v, end - begin); - v.push(0u8); - ::cast::transmute(v) + do vec::as_imm_buf(v) |vbuf, _vlen| { + let vbuf = ::cast::transmute_mut_unsafe(vbuf); + let src = ptr::offset(sbuf, begin); + ptr::copy_memory(vbuf, src, end - begin); } + vec::raw::set_len(&mut v, end - begin); + v.push(0u8); + ::cast::transmute(v) } } @@ -2304,7 +2298,7 @@ pub mod raw { } /// Removes the last byte from a string and returns it. (Not UTF-8 safe). - pub unsafe fn pop_byte(s: &mut ~str) -> u8 { + pub fn pop_byte(s: &mut ~str) -> u8 { let len = len(*s); assert!((len > 0u)); let b = s[len - 1u]; @@ -2313,7 +2307,7 @@ pub mod raw { } /// Removes the first byte from a string and returns it. (Not UTF-8 safe). - pub unsafe fn shift_byte(s: &mut ~str) -> u8 { + pub fn shift_byte(s: &mut ~str) -> u8 { let len = len(*s); assert!((len > 0u)); let b = s[0]; diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 52ca020412676..678005ce06f96 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -127,10 +127,8 @@ pub fn refcount(t: @T) -> uint { } pub fn log_str(t: &T) -> ~str { - unsafe { - do io::with_str_writer |wr| { - repr::write_repr(wr, t) - } + do io::with_str_writer |wr| { + repr::write_repr(wr, t) } } @@ -157,10 +155,8 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { } pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! { - unsafe { - let (msg, file) = (msg.to_owned(), file.to_owned()); - begin_unwind(~"assertion failed: " + msg, file, line) - } + let (msg, file) = (msg.to_owned(), file.to_owned()); + begin_unwind(~"assertion failed: " + msg, file, line) } #[cfg(test)] diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index e4ee430cdda64..d712bf8f98f44 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -39,10 +39,9 @@ use result::Result; use comm::{stream, Chan, GenericChan, GenericPort, Port}; use prelude::*; use result; -use task::rt::{task_id, sched_id}; +use task::rt::{task_id, sched_id, rust_task}; use util; use util::replace; -use unstable::finally::Finally; #[cfg(test)] use comm::SharedChan; @@ -566,28 +565,48 @@ pub fn get_scheduler() -> Scheduler { * ~~~ */ pub unsafe fn unkillable(f: &fn() -> U) -> U { - unsafe { - let t = rt::rust_get_task(); - rt::rust_task_inhibit_kill(t); - do (|| { - f() - }).finally { - rt::rust_task_allow_kill(t); + struct AllowFailure { + t: *rust_task, + drop { + unsafe { + rt::rust_task_allow_kill(self.t); + } + } + } + + fn AllowFailure(t: *rust_task) -> AllowFailure{ + AllowFailure { + t: t } } + + let t = rt::rust_get_task(); + let _allow_failure = AllowFailure(t); + rt::rust_task_inhibit_kill(t); + f() } /// The inverse of unkillable. Only ever to be used nested in unkillable(). pub unsafe fn rekillable(f: &fn() -> U) -> U { - unsafe { - let t = rt::rust_get_task(); - rt::rust_task_allow_kill(t); - do (|| { - f() - }).finally { - rt::rust_task_inhibit_kill(t); + struct DisallowFailure { + t: *rust_task, + drop { + unsafe { + rt::rust_task_inhibit_kill(self.t); + } } } + + fn DisallowFailure(t: *rust_task) -> DisallowFailure { + DisallowFailure { + t: t + } + } + + let t = rt::rust_get_task(); + let _allow_failure = DisallowFailure(t); + rt::rust_task_allow_kill(t); + f() } /** @@ -595,17 +614,27 @@ pub unsafe fn rekillable(f: &fn() -> U) -> U { * For use with exclusive ARCs, which use pthread mutexes directly. */ pub unsafe fn atomically(f: &fn() -> U) -> U { - unsafe { - let t = rt::rust_get_task(); - rt::rust_task_inhibit_kill(t); - rt::rust_task_inhibit_yield(t); - do (|| { - f() - }).finally { - rt::rust_task_allow_yield(t); - rt::rust_task_allow_kill(t); + struct DeferInterrupts { + t: *rust_task, + drop { + unsafe { + rt::rust_task_allow_yield(self.t); + rt::rust_task_allow_kill(self.t); + } } } + + fn DeferInterrupts(t: *rust_task) -> DeferInterrupts { + DeferInterrupts { + t: t + } + } + + let t = rt::rust_get_task(); + let _interrupts = DeferInterrupts(t); + rt::rust_task_inhibit_kill(t); + rt::rust_task_inhibit_yield(t); + f() } #[test] #[should_fail] #[ignore(cfg(windows))] diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index e1b645cd56272..c71f7d26d40f1 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -157,13 +157,13 @@ struct AncestorList(Option>); // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety. #[inline(always)] fn access_group(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U { - unsafe { x.with(blk) } + x.with(blk) } #[inline(always)] fn access_ancestors(x: &unstable::Exclusive, blk: &fn(x: &mut AncestorNode) -> U) -> U { - unsafe { x.with(blk) } + x.with(blk) } // Iterates over an ancestor list. diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index 9ccce0cfe7654..e43d321dc4d05 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -152,45 +152,37 @@ pub type SharedMutableState = ArcDestruct; pub unsafe fn shared_mutable_state(data: T) -> SharedMutableState { let data = ~ArcData { count: 1, data: Some(data) }; - unsafe { - let ptr = cast::transmute(data); - ArcDestruct(ptr) - } + let ptr = cast::transmute(data); + ArcDestruct(ptr) } #[inline(always)] pub unsafe fn get_shared_mutable_state( rc: *SharedMutableState) -> *mut T { - unsafe { - let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); - assert!(ptr.count > 0); - let r = cast::transmute(ptr.data.get_ref()); - cast::forget(ptr); - return r; - } + let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + assert!(ptr.count > 0); + let r = cast::transmute(ptr.data.get_ref()); + cast::forget(ptr); + return r; } #[inline(always)] pub unsafe fn get_shared_immutable_state<'a,T:Owned>( rc: &'a SharedMutableState) -> &'a T { - unsafe { - let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); - assert!(ptr.count > 0); - // Cast us back into the correct region - let r = cast::transmute_region(ptr.data.get_ref()); - cast::forget(ptr); - return r; - } + let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + assert!(ptr.count > 0); + // Cast us back into the correct region + let r = cast::transmute_region(ptr.data.get_ref()); + cast::forget(ptr); + return r; } pub unsafe fn clone_shared_mutable_state(rc: &SharedMutableState) -> SharedMutableState { - unsafe { - let mut ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); - let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1; - assert!(new_count >= 2); - cast::forget(ptr); - } + let mut ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1; + assert!(new_count >= 2); + cast::forget(ptr); ArcDestruct((*rc).data) } diff --git a/src/libcore/unstable/exchange_alloc.rs b/src/libcore/unstable/exchange_alloc.rs index fdf99e9dffea6..8ca5486d92992 100644 --- a/src/libcore/unstable/exchange_alloc.rs +++ b/src/libcore/unstable/exchange_alloc.rs @@ -19,27 +19,25 @@ use ptr::null; use intrinsic::TyDesc; pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void { - unsafe { - assert!(td.is_not_null()); + assert!(td.is_not_null()); - let total_size = get_box_size(size, (*td).align); - let p = c_malloc(total_size as size_t); - assert!(p.is_not_null()); + let total_size = get_box_size(size, (*td).align); + let p = c_malloc(total_size as size_t); + assert!(p.is_not_null()); - // FIXME #3475: Converting between our two different tydesc types - let td: *TyDesc = transmute(td); + // FIXME #3475: Converting between our two different tydesc types + let td: *TyDesc = transmute(td); - let box: &mut BoxRepr = transmute(p); - box.header.ref_count = -1; // Exchange values not ref counted - box.header.type_desc = td; - box.header.prev = null(); - box.header.next = null(); + let box: &mut BoxRepr = transmute(p); + box.header.ref_count = -1; // Exchange values not ref counted + box.header.type_desc = td; + box.header.prev = null(); + box.header.next = null(); - let exchange_count = &mut *rust_get_exchange_count_ptr(); - atomic_xadd(exchange_count, 1); + let exchange_count = &mut *rust_get_exchange_count_ptr(); + atomic_xadd(exchange_count, 1); - return transmute(box); - } + return transmute(box); } /** Thin wrapper around libc::malloc, none of the box header diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs index be2aecf0c2a3b..ad3dce0a74992 100644 --- a/src/libcore/unstable/extfmt.rs +++ b/src/libcore/unstable/extfmt.rs @@ -512,7 +512,7 @@ pub mod rt { None } } else { Some('-') }; - unsafe { pad(cv, s, head, PadSigned, buf) }; + pad(cv, s, head, PadSigned, buf); } pub fn conv_uint(cv: Conv, u: uint, buf: &mut ~str) { let prec = get_int_precision(cv); @@ -524,7 +524,7 @@ pub mod rt { TyBits => uint_to_str_prec(u, 2, prec), TyOctal => uint_to_str_prec(u, 8, prec) }; - unsafe { pad(cv, rs, None, PadUnsigned, buf) }; + pad(cv, rs, None, PadUnsigned, buf); } pub fn conv_bool(cv: Conv, b: bool, buf: &mut ~str) { let s = if b { "true" } else { "false" }; @@ -533,7 +533,7 @@ pub mod rt { conv_str(cv, s, buf); } pub fn conv_char(cv: Conv, c: char, buf: &mut ~str) { - unsafe { pad(cv, "", Some(c), PadNozero, buf) }; + pad(cv, "", Some(c), PadNozero, buf); } pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) { // For strings, precision is the maximum characters @@ -546,14 +546,14 @@ pub mod rt { s } }; - unsafe { pad(cv, unpadded, None, PadNozero, buf) }; + pad(cv, unpadded, None, PadNozero, buf); } pub fn conv_float(cv: Conv, f: float, buf: &mut ~str) { let (to_str, digits) = match cv.precision { CountIs(c) => (float::to_str_exact, c as uint), CountImplied => (float::to_str_digits, 6u) }; - let mut s = unsafe { to_str(f, digits) }; + let mut s = to_str(f, digits); let head = if 0.0 <= f { if have_flag(cv.flags, flag_sign_always) { Some('+') @@ -563,7 +563,7 @@ pub mod rt { None } } else { None }; - unsafe { pad(cv, s, head, PadFloat, buf) }; + pad(cv, s, head, PadFloat, buf); } pub fn conv_poly(cv: Conv, v: &T, buf: &mut ~str) { let s = sys::log_str(v); diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index dad990c0f97cf..be776a39742f0 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -44,7 +44,7 @@ pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! { } #[lang="fail_bounds_check"] -pub unsafe fn fail_bounds_check(file: *c_char, line: size_t, +pub fn fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t) { let msg = fmt!("index out of bounds: the len is %d but the index is %d", len as int, index as int); @@ -53,7 +53,7 @@ pub unsafe fn fail_bounds_check(file: *c_char, line: size_t, } } -pub unsafe fn fail_borrowed() { +pub fn fail_borrowed() { let msg = "borrowed"; do str::as_buf(msg) |msg_p, _| { do str::as_buf("???") |file_p, _| { From 52445129fdb4ee847332acbf516ced8f73b7990a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 01:31:42 -0400 Subject: [PATCH 186/403] std: remove unused unsafe blocks/functions --- src/libstd/c_vec.rs | 14 +- src/libstd/getopts.rs | 218 ++++++++++++++-------------- src/libstd/net_ip.rs | 52 ++++--- src/libstd/net_tcp.rs | 307 +++++++++++++++++++--------------------- src/libstd/net_url.rs | 57 +++----- src/libstd/rl.rs | 34 ++--- src/libstd/rope.rs | 20 ++- src/libstd/sync.rs | 66 ++++----- src/libstd/timer.rs | 74 +++++----- src/libstd/uv_iotask.rs | 6 +- src/libstd/uv_ll.rs | 12 +- 11 files changed, 405 insertions(+), 455 deletions(-) diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index 113c8130349ff..a59c76c809b13 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -57,11 +57,9 @@ struct DtorRes { #[unsafe_destructor] impl Drop for DtorRes { fn finalize(&self) { - unsafe { - match self.dtor { - option::None => (), - option::Some(f) => f() - } + match self.dtor { + option::None => (), + option::Some(f) => f() } } } @@ -84,7 +82,7 @@ fn DtorRes(dtor: Option<@fn()>) -> DtorRes { * * base - A foreign pointer to a buffer * * len - The number of elements in the buffer */ -pub unsafe fn CVec(base: *mut T, len: uint) -> CVec { +pub fn CVec(base: *mut T, len: uint) -> CVec { return CVec{ base: base, len: len, @@ -103,7 +101,7 @@ pub unsafe fn CVec(base: *mut T, len: uint) -> CVec { * * dtor - A function to run when the value is destructed, useful * for freeing the buffer, etc. */ -pub unsafe fn c_vec_with_dtor(base: *mut T, len: uint, dtor: @fn()) +pub fn c_vec_with_dtor(base: *mut T, len: uint, dtor: @fn()) -> CVec { return CVec{ base: base, @@ -144,7 +142,7 @@ pub fn set(t: CVec, ofs: uint, v: T) { pub fn len(t: CVec) -> uint { t.len } /// Returns a pointer to the first element of the vector -pub unsafe fn ptr(t: CVec) -> *mut T { t.base } +pub fn ptr(t: CVec) -> *mut T { t.base } #[cfg(test)] mod tests { diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index df37c48ebe8b8..b1e80718d8f74 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -223,128 +223,126 @@ pub type Result = result::Result; * Use to get an error message. */ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { - unsafe { - let n_opts = opts.len(); - fn f(_x: uint) -> ~[Optval] { return ~[]; } - let mut vals = vec::from_fn(n_opts, f); - let mut free: ~[~str] = ~[]; - let l = args.len(); - let mut i = 0; - while i < l { - let cur = args[i]; - let curlen = cur.len(); - if !is_arg(cur) { - free.push(cur); - } else if cur == ~"--" { - let mut j = i + 1; - while j < l { free.push(args[j]); j += 1; } - break; - } else { - let mut names; - let mut i_arg = None; - if cur[1] == '-' as u8 { - let tail = str::slice(cur, 2, curlen).to_owned(); - let mut tail_eq = ~[]; - for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) } - if tail_eq.len() <= 1 { - names = ~[Long(tail)]; - } else { - names = - ~[Long(tail_eq[0])]; - i_arg = Some(tail_eq[1]); - } + let n_opts = opts.len(); + fn f(_x: uint) -> ~[Optval] { return ~[]; } + let mut vals = vec::from_fn(n_opts, f); + let mut free: ~[~str] = ~[]; + let l = args.len(); + let mut i = 0; + while i < l { + let cur = args[i]; + let curlen = cur.len(); + if !is_arg(cur) { + free.push(cur); + } else if cur == ~"--" { + let mut j = i + 1; + while j < l { free.push(args[j]); j += 1; } + break; + } else { + let mut names; + let mut i_arg = None; + if cur[1] == '-' as u8 { + let tail = str::slice(cur, 2, curlen).to_owned(); + let mut tail_eq = ~[]; + for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) } + if tail_eq.len() <= 1 { + names = ~[Long(tail)]; } else { - let mut j = 1; - let mut last_valid_opt_id = None; - names = ~[]; - while j < curlen { - let range = str::char_range_at(cur, j); - let opt = Short(range.ch); - - /* In a series of potential options (eg. -aheJ), if we - see one which takes an argument, we assume all - subsequent characters make up the argument. This - allows options such as -L/usr/local/lib/foo to be - interpreted correctly - */ - - match find_opt(opts, opt) { - Some(id) => last_valid_opt_id = Some(id), - None => { - let arg_follows = - last_valid_opt_id.is_some() && - match opts[last_valid_opt_id.get()] - .hasarg { - - Yes | Maybe => true, - No => false - }; - if arg_follows && j < curlen { - i_arg = Some(cur.slice(j, curlen).to_owned()); - break; - } else { - last_valid_opt_id = None; - } - } - } - names.push(opt); - j = range.next; - } + names = + ~[Long(tail_eq[0])]; + i_arg = Some(tail_eq[1]); } - let mut name_pos = 0; - for names.each() |nm| { - name_pos += 1; - let optid = match find_opt(opts, *nm) { - Some(id) => id, - None => return Err(UnrecognizedOption(name_str(nm))) - }; - match opts[optid].hasarg { - No => { - if !i_arg.is_none() { - return Err(UnexpectedArgument(name_str(nm))); + } else { + let mut j = 1; + let mut last_valid_opt_id = None; + names = ~[]; + while j < curlen { + let range = str::char_range_at(cur, j); + let opt = Short(range.ch); + + /* In a series of potential options (eg. -aheJ), if we + see one which takes an argument, we assume all + subsequent characters make up the argument. This + allows options such as -L/usr/local/lib/foo to be + interpreted correctly + */ + + match find_opt(opts, opt) { + Some(id) => last_valid_opt_id = Some(id), + None => { + let arg_follows = + last_valid_opt_id.is_some() && + match opts[last_valid_opt_id.get()] + .hasarg { + + Yes | Maybe => true, + No => false + }; + if arg_follows && j < curlen { + i_arg = Some(cur.slice(j, curlen).to_owned()); + break; + } else { + last_valid_opt_id = None; } - vals[optid].push(Given); - } - Maybe => { - if !i_arg.is_none() { - vals[optid].push(Val(i_arg.get())); - } else if name_pos < names.len() || - i + 1 == l || is_arg(args[i + 1]) { - vals[optid].push(Given); - } else { i += 1; vals[optid].push(Val(args[i])); } - } - Yes => { - if !i_arg.is_none() { - vals[optid].push(Val(i_arg.get())); - } else if i + 1 == l { - return Err(ArgumentMissing(name_str(nm))); - } else { i += 1; vals[optid].push(Val(args[i])); } } } + names.push(opt); + j = range.next; } } - i += 1; - } - i = 0u; - while i < n_opts { - let n = vals[i].len(); - let occ = opts[i].occur; - if occ == Req { - if n == 0 { - return Err(OptionMissing(name_str(&(opts[i].name)))); + let mut name_pos = 0; + for names.each() |nm| { + name_pos += 1; + let optid = match find_opt(opts, *nm) { + Some(id) => id, + None => return Err(UnrecognizedOption(name_str(nm))) + }; + match opts[optid].hasarg { + No => { + if !i_arg.is_none() { + return Err(UnexpectedArgument(name_str(nm))); + } + vals[optid].push(Given); + } + Maybe => { + if !i_arg.is_none() { + vals[optid].push(Val(i_arg.get())); + } else if name_pos < names.len() || + i + 1 == l || is_arg(args[i + 1]) { + vals[optid].push(Given); + } else { i += 1; vals[optid].push(Val(args[i])); } + } + Yes => { + if !i_arg.is_none() { + vals[optid].push(Val(i_arg.get())); + } else if i + 1 == l { + return Err(ArgumentMissing(name_str(nm))); + } else { i += 1; vals[optid].push(Val(args[i])); } + } } } - if occ != Multi { - if n > 1 { - return Err(OptionDuplicated(name_str(&(opts[i].name)))); - } + } + i += 1; + } + i = 0u; + while i < n_opts { + let n = vals[i].len(); + let occ = opts[i].occur; + if occ == Req { + if n == 0 { + return Err(OptionMissing(name_str(&(opts[i].name)))); + } + } + if occ != Multi { + if n > 1 { + return Err(OptionDuplicated(name_str(&(opts[i].name)))); } - i += 1; } - return Ok(Matches {opts: vec::from_slice(opts), - vals: vals, - free: free}); + i += 1; } + return Ok(Matches {opts: vec::from_slice(opts), + vals: vals, + free: free}); } fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] { diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 6403e0eb5c47a..e920ff20ac5dc 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -116,35 +116,33 @@ pub fn get_addr(node: &str, iotask: &iotask) let mut output_ch = Some(SharedChan(output_ch)); do str::as_buf(node) |node_ptr, len| { let output_ch = output_ch.swap_unwrap(); - unsafe { - debug!("slice len %?", len); - let handle = create_uv_getaddrinfo_t(); - let handle_ptr = ptr::addr_of(&handle); - let handle_data = GetAddrData { - output_ch: output_ch.clone() - }; - let handle_data_ptr = ptr::addr_of(&handle_data); - do interact(iotask) |loop_ptr| { - unsafe { - let result = uv_getaddrinfo( - loop_ptr, - handle_ptr, - get_addr_cb, - node_ptr, - ptr::null(), - ptr::null()); - match result { - 0i32 => { - set_data_for_req(handle_ptr, handle_data_ptr); - } - _ => { - output_ch.send(result::Err(GetAddrUnknownError)); - } + debug!("slice len %?", len); + let handle = create_uv_getaddrinfo_t(); + let handle_ptr = ptr::addr_of(&handle); + let handle_data = GetAddrData { + output_ch: output_ch.clone() + }; + let handle_data_ptr = ptr::addr_of(&handle_data); + do interact(iotask) |loop_ptr| { + unsafe { + let result = uv_getaddrinfo( + loop_ptr, + handle_ptr, + get_addr_cb, + node_ptr, + ptr::null(), + ptr::null()); + match result { + 0i32 => { + set_data_for_req(handle_ptr, handle_data_ptr); + } + _ => { + output_ch.send(result::Err(GetAddrUnknownError)); } } - }; - output_po.recv() - } + } + }; + output_po.recv() } } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 9630351b5c9be..a8b2723bcfbc4 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -57,9 +57,7 @@ pub struct TcpSocket { #[unsafe_destructor] impl Drop for TcpSocket { fn finalize(&self) { - unsafe { - tear_down_socket_data(self.socket_data) - } + tear_down_socket_data(self.socket_data) } } @@ -302,11 +300,10 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, * `TcpErrData` value as the `Err` variant */ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) - -> result::Result<(), TcpErrData> { - unsafe { - let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); - write_common_impl(socket_data_ptr, raw_write_data) - } + -> result::Result<(), TcpErrData> +{ + let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); + write_common_impl(socket_data_ptr, raw_write_data) } /** @@ -341,13 +338,12 @@ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) * value as the `Err` variant */ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) - -> future::Future> { - unsafe { - let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); - do future_spawn { - let data_copy = copy(raw_write_data); - write_common_impl(socket_data_ptr, data_copy) - } + -> future::Future> +{ + let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data))); + do future_spawn { + let data_copy = copy(raw_write_data); + write_common_impl(socket_data_ptr, data_copy) } } @@ -369,10 +365,8 @@ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) pub fn read_start(sock: &TcpSocket) -> result::Result<@Port< result::Result<~[u8], TcpErrData>>, TcpErrData> { - unsafe { - let socket_data = ptr::addr_of(&(*(sock.socket_data))); - read_start_common_impl(socket_data) - } + let socket_data = ptr::addr_of(&(*(sock.socket_data))); + read_start_common_impl(socket_data) } /** @@ -382,12 +376,9 @@ pub fn read_start(sock: &TcpSocket) * * * `sock` - a `net::tcp::TcpSocket` that you wish to stop reading on */ -pub fn read_stop(sock: &TcpSocket) -> - result::Result<(), TcpErrData> { - unsafe { - let socket_data = ptr::addr_of(&(*sock.socket_data)); - read_stop_common_impl(socket_data) - } +pub fn read_stop(sock: &TcpSocket) -> result::Result<(), TcpErrData> { + let socket_data = ptr::addr_of(&(*sock.socket_data)); + read_stop_common_impl(socket_data) } /** @@ -654,150 +645,148 @@ fn listen_common(host_ip: ip::IpAddr, on_establish_cb: ~fn(SharedChan>), on_connect_cb: ~fn(*uv::ll::uv_tcp_t)) -> result::Result<(), TcpListenErrData> { - unsafe { - let (stream_closed_po, stream_closed_ch) = stream::<()>(); - let stream_closed_ch = SharedChan(stream_closed_ch); - let (kill_po, kill_ch) = stream::>(); - let kill_ch = SharedChan(kill_ch); - let server_stream = uv::ll::tcp_t(); - let server_stream_ptr = ptr::addr_of(&server_stream); - let server_data: TcpListenFcData = TcpListenFcData { - server_stream_ptr: server_stream_ptr, - stream_closed_ch: stream_closed_ch, - kill_ch: kill_ch.clone(), - on_connect_cb: on_connect_cb, - iotask: iotask.clone(), - ipv6: match &host_ip { - &ip::Ipv4(_) => { false } - &ip::Ipv6(_) => { true } - }, - mut active: true - }; - let server_data_ptr = ptr::addr_of(&server_data); - - let (setup_po, setup_ch) = stream(); - - // this is to address a compiler warning about - // an implicit copy.. it seems that double nested - // will defeat a move sigil, as is done to the host_ip - // arg above.. this same pattern works w/o complaint in - // tcp::connect (because the iotask::interact cb isn't - // nested within a core::comm::listen block) - let loc_ip = copy(host_ip); - do iotask::interact(iotask) |loop_ptr| { - unsafe { - match uv::ll::tcp_init(loop_ptr, server_stream_ptr) { - 0i32 => { - uv::ll::set_data_for_uv_handle( - server_stream_ptr, - server_data_ptr); - let addr_str = ip::format_addr(&loc_ip); - let bind_result = match loc_ip { - ip::Ipv4(ref addr) => { - debug!("addr: %?", addr); - let in_addr = uv::ll::ip4_addr( - addr_str, - port as int); - uv::ll::tcp_bind(server_stream_ptr, - ptr::addr_of(&in_addr)) - } - ip::Ipv6(ref addr) => { - debug!("addr: %?", addr); - let in_addr = uv::ll::ip6_addr( - addr_str, - port as int); - uv::ll::tcp_bind6(server_stream_ptr, - ptr::addr_of(&in_addr)) - } - }; - match bind_result { - 0i32 => { - match uv::ll::listen( - server_stream_ptr, - backlog as libc::c_int, - tcp_lfc_on_connection_cb) { - 0i32 => setup_ch.send(None), - _ => { - debug!( - "failure to uv_tcp_init"); - let err_data = - uv::ll::get_last_err_data( - loop_ptr); - setup_ch.send(Some(err_data)); - } + let (stream_closed_po, stream_closed_ch) = stream::<()>(); + let stream_closed_ch = SharedChan(stream_closed_ch); + let (kill_po, kill_ch) = stream::>(); + let kill_ch = SharedChan(kill_ch); + let server_stream = uv::ll::tcp_t(); + let server_stream_ptr = ptr::addr_of(&server_stream); + let server_data: TcpListenFcData = TcpListenFcData { + server_stream_ptr: server_stream_ptr, + stream_closed_ch: stream_closed_ch, + kill_ch: kill_ch.clone(), + on_connect_cb: on_connect_cb, + iotask: iotask.clone(), + ipv6: match &host_ip { + &ip::Ipv4(_) => { false } + &ip::Ipv6(_) => { true } + }, + mut active: true + }; + let server_data_ptr = ptr::addr_of(&server_data); + + let (setup_po, setup_ch) = stream(); + + // this is to address a compiler warning about + // an implicit copy.. it seems that double nested + // will defeat a move sigil, as is done to the host_ip + // arg above.. this same pattern works w/o complaint in + // tcp::connect (because the iotask::interact cb isn't + // nested within a core::comm::listen block) + let loc_ip = copy(host_ip); + do iotask::interact(iotask) |loop_ptr| { + unsafe { + match uv::ll::tcp_init(loop_ptr, server_stream_ptr) { + 0i32 => { + uv::ll::set_data_for_uv_handle( + server_stream_ptr, + server_data_ptr); + let addr_str = ip::format_addr(&loc_ip); + let bind_result = match loc_ip { + ip::Ipv4(ref addr) => { + debug!("addr: %?", addr); + let in_addr = uv::ll::ip4_addr( + addr_str, + port as int); + uv::ll::tcp_bind(server_stream_ptr, + ptr::addr_of(&in_addr)) + } + ip::Ipv6(ref addr) => { + debug!("addr: %?", addr); + let in_addr = uv::ll::ip6_addr( + addr_str, + port as int); + uv::ll::tcp_bind6(server_stream_ptr, + ptr::addr_of(&in_addr)) + } + }; + match bind_result { + 0i32 => { + match uv::ll::listen( + server_stream_ptr, + backlog as libc::c_int, + tcp_lfc_on_connection_cb) { + 0i32 => setup_ch.send(None), + _ => { + debug!( + "failure to uv_tcp_init"); + let err_data = + uv::ll::get_last_err_data( + loop_ptr); + setup_ch.send(Some(err_data)); } } - _ => { - debug!("failure to uv_tcp_bind"); - let err_data = uv::ll::get_last_err_data( - loop_ptr); - setup_ch.send(Some(err_data)); - } } - } - _ => { - debug!("failure to uv_tcp_bind"); - let err_data = uv::ll::get_last_err_data( - loop_ptr); - setup_ch.send(Some(err_data)); + _ => { + debug!("failure to uv_tcp_bind"); + let err_data = uv::ll::get_last_err_data( + loop_ptr); + setup_ch.send(Some(err_data)); + } } } + _ => { + debug!("failure to uv_tcp_bind"); + let err_data = uv::ll::get_last_err_data( + loop_ptr); + setup_ch.send(Some(err_data)); + } } } + } - let setup_result = setup_po.recv(); + let setup_result = setup_po.recv(); - match setup_result { - Some(ref err_data) => { - do iotask::interact(iotask) |loop_ptr| { - unsafe { - debug!( - "tcp::listen post-kill recv hl interact %?", - loop_ptr); - (*server_data_ptr).active = false; - uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); - } - }; - stream_closed_po.recv(); - match err_data.err_name { - ~"EACCES" => { - debug!("Got EACCES error"); - result::Err(AccessDenied) - } - ~"EADDRINUSE" => { - debug!("Got EADDRINUSE error"); - result::Err(AddressInUse) - } - _ => { - debug!("Got '%s' '%s' libuv error", - err_data.err_name, err_data.err_msg); - result::Err( - GenericListenErr(err_data.err_name, - err_data.err_msg)) - } + match setup_result { + Some(ref err_data) => { + do iotask::interact(iotask) |loop_ptr| { + unsafe { + debug!( + "tcp::listen post-kill recv hl interact %?", + loop_ptr); + (*server_data_ptr).active = false; + uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); + } + }; + stream_closed_po.recv(); + match err_data.err_name { + ~"EACCES" => { + debug!("Got EACCES error"); + result::Err(AccessDenied) + } + ~"EADDRINUSE" => { + debug!("Got EADDRINUSE error"); + result::Err(AddressInUse) + } + _ => { + debug!("Got '%s' '%s' libuv error", + err_data.err_name, err_data.err_msg); + result::Err( + GenericListenErr(err_data.err_name, + err_data.err_msg)) } } - None => { - on_establish_cb(kill_ch.clone()); - let kill_result = kill_po.recv(); - do iotask::interact(iotask) |loop_ptr| { - unsafe { - debug!( - "tcp::listen post-kill recv hl interact %?", - loop_ptr); - (*server_data_ptr).active = false; - uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); - } - }; - stream_closed_po.recv(); - match kill_result { - // some failure post bind/listen - Some(ref err_data) => result::Err(GenericListenErr( - err_data.err_name, - err_data.err_msg)), - // clean exit - None => result::Ok(()) + } + None => { + on_establish_cb(kill_ch.clone()); + let kill_result = kill_po.recv(); + do iotask::interact(iotask) |loop_ptr| { + unsafe { + debug!( + "tcp::listen post-kill recv hl interact %?", + loop_ptr); + (*server_data_ptr).active = false; + uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); } + }; + stream_closed_po.recv(); + match kill_result { + // some failure post bind/listen + Some(ref err_data) => result::Err(GenericListenErr( + err_data.err_name, + err_data.err_msg)), + // clean exit + None => result::Ok(()) } } } @@ -1382,9 +1371,7 @@ extern fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) { } extern fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) { - unsafe { - debug!("closed client tcp handle %?", handle); - } + debug!("closed client tcp handle %?", handle); } extern fn tcp_connect_on_connect_cb(connect_req_ptr: *uv::ll::uv_connect_t, diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index b8e0d9d9b2ac4..9b8b0f9be0bcd 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -118,8 +118,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { * This function is compliant with RFC 3986. */ pub fn encode(s: &str) -> ~str { - // FIXME(#3722): unsafe only because encode_inner does (string) IO - unsafe {encode_inner(s, true)} + encode_inner(s, true) } /** @@ -130,8 +129,7 @@ pub fn encode(s: &str) -> ~str { */ pub fn encode_component(s: &str) -> ~str { - // FIXME(#3722): unsafe only because encode_inner does (string) IO - unsafe {encode_inner(s, false)} + encode_inner(s, false) } fn decode_inner(s: &str, full_url: bool) -> ~str { @@ -178,16 +176,14 @@ fn decode_inner(s: &str, full_url: bool) -> ~str { * This will only decode escape sequences generated by encode. */ pub fn decode(s: &str) -> ~str { - // FIXME(#3722): unsafe only because decode_inner does (string) IO - unsafe {decode_inner(s, true)} + decode_inner(s, true) } /** * Decode a string encoded with percent encoding. */ pub fn decode_component(s: &str) -> ~str { - // FIXME(#3722): unsafe only because decode_inner does (string) IO - unsafe {decode_inner(s, false)} + decode_inner(s, false) } fn encode_plus(s: &str) -> ~str { @@ -301,18 +297,15 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) { let len = str::len(s); let mut index = len; let mut mat = 0; - // FIXME(#3722): unsafe only because decode_inner does (string) IO - unsafe { - do io::with_str_reader(s) |rdr| { - let mut ch; - while !rdr.eof() { - ch = rdr.read_byte() as char; - if ch == c { - // found a match, adjust markers - index = rdr.tell()-1; - mat = 1; - break; - } + do io::with_str_reader(s) |rdr| { + let mut ch; + while !rdr.eof() { + ch = rdr.read_byte() as char; + if ch == c { + // found a match, adjust markers + index = rdr.tell()-1; + mat = 1; + break; } } } @@ -346,29 +339,25 @@ fn query_from_str(rawquery: &str) -> Query { if str::len(rawquery) != 0 { for str::each_split_char(rawquery, '&') |p| { let (k, v) = split_char_first(p, '='); - // FIXME(#3722): unsafe only because decode_inner does (string) IO - unsafe {query.push((decode_component(k), decode_component(v)));} + query.push((decode_component(k), decode_component(v))); }; } return query; } pub fn query_to_str(query: &Query) -> ~str { - unsafe { - // FIXME(#3722): unsafe only because decode_inner does (string) IO - let mut strvec = ~[]; - for query.each |kv| { - match kv { - &(ref k, ref v) => { - strvec.push(fmt!("%s=%s", - encode_component(*k), - encode_component(*v)) - ); - } + let mut strvec = ~[]; + for query.each |kv| { + match kv { + &(ref k, ref v) => { + strvec.push(fmt!("%s=%s", + encode_component(*k), + encode_component(*v)) + ); } } - return str::connect(strvec, ~"&"); } + return str::connect(strvec, ~"&"); } // returns the scheme and the rest of the url, or a parsing error diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs index a8b25767ce595..9f9f2323d271b 100644 --- a/src/libstd/rl.rs +++ b/src/libstd/rl.rs @@ -59,12 +59,10 @@ pub unsafe fn load_history(file: ~str) -> bool { /// Print out a prompt and then wait for input and return it pub unsafe fn read(prompt: ~str) -> Option<~str> { do str::as_c_str(prompt) |buf| { - unsafe { - let line = rustrt::linenoise(buf); + let line = rustrt::linenoise(buf); - if line.is_null() { None } - else { Some(str::raw::from_c_str(line)) } - } + if line.is_null() { None } + else { Some(str::raw::from_c_str(line)) } } } @@ -74,22 +72,20 @@ fn complete_key(_v: @CompletionCb) {} /// Bind to the main completion callback pub unsafe fn complete(cb: CompletionCb) { - unsafe { - task::local_data::local_data_set(complete_key, @(cb)); - - extern fn callback(line: *c_char, completions: *()) { - unsafe { - let cb = *task::local_data::local_data_get(complete_key) - .get(); - - do cb(str::raw::from_c_str(line)) |suggestion| { - do str::as_c_str(suggestion) |buf| { - rustrt::linenoiseAddCompletion(completions, buf); - } + task::local_data::local_data_set(complete_key, @(cb)); + + extern fn callback(line: *c_char, completions: *()) { + unsafe { + let cb = *task::local_data::local_data_get(complete_key) + .get(); + + do cb(str::raw::from_c_str(line)) |suggestion| { + do str::as_c_str(suggestion) |buf| { + rustrt::linenoiseAddCompletion(completions, buf); } } } - - rustrt::linenoiseSetCompletionCallback(callback); } + + rustrt::linenoiseSetCompletionCallback(callback); } diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index 232f46b6676df..653283f2e78b9 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -862,17 +862,15 @@ pub mod node { * This function executes in linear time. */ pub fn flatten(node: @Node) -> @Node { - unsafe { - match (*node) { - Leaf(_) => node, - Concat(ref x) => { - @Leaf(Leaf { - byte_offset: 0u, - byte_len: x.byte_len, - char_len: x.char_len, - content: @serialize_node(node), - }) - } + match (*node) { + Leaf(_) => node, + Concat(ref x) => { + @Leaf(Leaf { + byte_offset: 0u, + byte_len: x.byte_len, + char_len: x.char_len, + content: @serialize_node(node), + }) } } } diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 1bfdd7f99d501..f2de8213a1b9e 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -101,17 +101,15 @@ fn new_sem_and_signal(count: int, num_condvars: uint) pub impl Sem { fn acquire(&self) { let mut waiter_nobe = None; - unsafe { - do (**self).with |state| { - state.count -= 1; - if state.count < 0 { - // Create waiter nobe. - let (WaitEnd, SignalEnd) = comm::oneshot(); - // Tell outer scope we need to block. - waiter_nobe = Some(WaitEnd); - // Enqueue ourself. - state.waiters.tail.send(SignalEnd); - } + do (**self).with |state| { + state.count -= 1; + if state.count < 0 { + // Create waiter nobe. + let (WaitEnd, SignalEnd) = comm::oneshot(); + // Tell outer scope we need to block. + waiter_nobe = Some(WaitEnd); + // Enqueue ourself. + state.waiters.tail.send(SignalEnd); } } // Uncomment if you wish to test for sem races. Not valgrind-friendly. @@ -122,12 +120,10 @@ pub impl Sem { } } fn release(&self) { - unsafe { - do (**self).with |state| { - state.count += 1; - if state.count <= 0 { - signal_waitqueue(&state.waiters); - } + do (**self).with |state| { + state.count += 1; + if state.count <= 0 { + signal_waitqueue(&state.waiters); } } } @@ -169,9 +165,7 @@ struct SemReleaseGeneric<'self, Q> { sem: &'self Sem } #[unsafe_destructor] impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> { fn finalize(&self) { - unsafe { - self.sem.release(); - } + self.sem.release(); } } @@ -291,13 +285,11 @@ pub impl<'self> Condvar<'self> { fn signal_on(&self, condvar_id: uint) -> bool { let mut out_of_bounds = None; let mut result = false; - unsafe { - do (**self.sem).with |state| { - if condvar_id < vec::len(state.blocked) { - result = signal_waitqueue(&state.blocked[condvar_id]); - } else { - out_of_bounds = Some(vec::len(state.blocked)); - } + do (**self.sem).with |state| { + if condvar_id < vec::len(state.blocked) { + result = signal_waitqueue(&state.blocked[condvar_id]); + } else { + out_of_bounds = Some(vec::len(state.blocked)); } } do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { @@ -312,17 +304,15 @@ pub impl<'self> Condvar<'self> { fn broadcast_on(&self, condvar_id: uint) -> uint { let mut out_of_bounds = None; let mut queue = None; - unsafe { - do (**self.sem).with |state| { - if condvar_id < vec::len(state.blocked) { - // To avoid :broadcast_heavy, we make a new waitqueue, - // swap it out with the old one, and broadcast on the - // old one outside of the little-lock. - queue = Some(util::replace(&mut state.blocked[condvar_id], - new_waitqueue())); - } else { - out_of_bounds = Some(vec::len(state.blocked)); - } + do (**self.sem).with |state| { + if condvar_id < vec::len(state.blocked) { + // To avoid :broadcast_heavy, we make a new waitqueue, + // swap it out with the old one, and broadcast on the + // old one outside of the little-lock. + queue = Some(util::replace(&mut state.blocked[condvar_id], + new_waitqueue())); + } else { + out_of_bounds = Some(vec::len(state.blocked)); } } do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index 229d1a07caaab..99e772b0c95a3 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -42,47 +42,45 @@ pub fn delayed_send(iotask: &IoTask, msecs: uint, ch: &Chan, val: T) { + let (timer_done_po, timer_done_ch) = stream::<()>(); + let timer_done_ch = SharedChan(timer_done_ch); + let timer = uv::ll::timer_t(); + let timer_ptr = ptr::addr_of(&timer); + do iotask::interact(iotask) |loop_ptr| { unsafe { - let (timer_done_po, timer_done_ch) = stream::<()>(); - let timer_done_ch = SharedChan(timer_done_ch); - let timer = uv::ll::timer_t(); - let timer_ptr = ptr::addr_of(&timer); - do iotask::interact(iotask) |loop_ptr| { - unsafe { - let init_result = uv::ll::timer_init(loop_ptr, timer_ptr); - if (init_result == 0i32) { - let start_result = uv::ll::timer_start( - timer_ptr, delayed_send_cb, msecs, 0u); - if (start_result == 0i32) { - // Note: putting the channel into a ~ - // to cast to *c_void - let timer_done_ch_clone = ~timer_done_ch.clone(); - let timer_done_ch_ptr = transmute::< - ~SharedChan<()>, *c_void>( - timer_done_ch_clone); - uv::ll::set_data_for_uv_handle( - timer_ptr, - timer_done_ch_ptr); - } else { - let error_msg = uv::ll::get_last_err_info( - loop_ptr); - fail!(~"timer::delayed_send() start failed: " + - error_msg); - } - } else { - let error_msg = uv::ll::get_last_err_info(loop_ptr); - fail!(~"timer::delayed_send() init failed: " + - error_msg); - } + let init_result = uv::ll::timer_init(loop_ptr, timer_ptr); + if (init_result == 0i32) { + let start_result = uv::ll::timer_start( + timer_ptr, delayed_send_cb, msecs, 0u); + if (start_result == 0i32) { + // Note: putting the channel into a ~ + // to cast to *c_void + let timer_done_ch_clone = ~timer_done_ch.clone(); + let timer_done_ch_ptr = transmute::< + ~SharedChan<()>, *c_void>( + timer_done_ch_clone); + uv::ll::set_data_for_uv_handle( + timer_ptr, + timer_done_ch_ptr); + } else { + let error_msg = uv::ll::get_last_err_info( + loop_ptr); + fail!(~"timer::delayed_send() start failed: " + + error_msg); } - }; - // delayed_send_cb has been processed by libuv - timer_done_po.recv(); - // notify the caller immediately - ch.send(val); - // uv_close for this timer has been processed - timer_done_po.recv(); + } else { + let error_msg = uv::ll::get_last_err_info(loop_ptr); + fail!(~"timer::delayed_send() init failed: " + + error_msg); + } + } }; + // delayed_send_cb has been processed by libuv + timer_done_po.recv(); + // notify the caller immediately + ch.send(val); + // uv_close for this timer has been processed + timer_done_po.recv(); } /** diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index fe40fc6a78b41..7a9d2438e6ada 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -75,7 +75,7 @@ pub fn spawn_iotask(task: task::TaskBuilder) -> IoTask { * module. It is not safe to send the `loop_ptr` param to this callback out * via ports/chans. */ -pub unsafe fn interact(iotask: &IoTask, cb: ~fn(*c_void)) { +pub fn interact(iotask: &IoTask, cb: ~fn(*c_void)) { send_msg(iotask, Interaction(cb)); } @@ -87,9 +87,7 @@ pub unsafe fn interact(iotask: &IoTask, cb: ~fn(*c_void)) { * closed, causing a failure otherwise. */ pub fn exit(iotask: &IoTask) { - unsafe { - send_msg(iotask, TeardownLoop); - } + send_msg(iotask, TeardownLoop); } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 7582a7cff513c..3bf297027d4d6 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1111,22 +1111,22 @@ pub unsafe fn freeaddrinfo(res: *addrinfo) { } // libuv struct initializers -pub unsafe fn tcp_t() -> uv_tcp_t { +pub fn tcp_t() -> uv_tcp_t { return uv_ll_struct_stubgen::gen_stub_uv_tcp_t(); } -pub unsafe fn connect_t() -> uv_connect_t { +pub fn connect_t() -> uv_connect_t { return uv_ll_struct_stubgen::gen_stub_uv_connect_t(); } -pub unsafe fn write_t() -> uv_write_t { +pub fn write_t() -> uv_write_t { return uv_ll_struct_stubgen::gen_stub_uv_write_t(); } -pub unsafe fn async_t() -> uv_async_t { +pub fn async_t() -> uv_async_t { return uv_ll_struct_stubgen::gen_stub_uv_async_t(); } -pub unsafe fn timer_t() -> uv_timer_t { +pub fn timer_t() -> uv_timer_t { return uv_ll_struct_stubgen::gen_stub_uv_timer_t(); } -pub unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t { +pub fn getaddrinfo_t() -> uv_getaddrinfo_t { return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t(); } From 72c24e20a9caf49b855b4c0de44aad6b039d09f4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 02:07:50 -0400 Subject: [PATCH 187/403] rustc: remove unnecessary unsafe blocks/methods --- src/librustc/back/link.rs | 4 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/middle/resolve.rs | 2 +- src/librustc/middle/trans/base.rs | 22 +- src/librustc/middle/trans/build.rs | 4 +- src/librustc/middle/trans/debuginfo.rs | 294 ++++++++++++------------- 6 files changed, 153 insertions(+), 175 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index fae56aac38f3c..1c99566280815 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -615,9 +615,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, } pub fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str { - unsafe { - symbol_hasher.result_str() - } + symbol_hasher.result_str() } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 0dd28e5ca7ca1..bacbeb851aa82 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -369,7 +369,7 @@ pub impl<'self> LanguageItemCollector<'self> { } fn collect_local_language_items(&self) { - let this = unsafe { ptr::addr_of(&self) }; + let this = ptr::addr_of(&self); visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { for item.attrs.each |attribute| { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c9381757d77dc..b2225963d2c33 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -19,7 +19,7 @@ use metadata::csearch::get_type_name_if_impl; use metadata::cstore::find_extern_mod_stmt_cnum; use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; use middle::lang_items::LanguageItems; -use middle::lint::{deny, allow, forbid, level, unused_imports, warn}; +use middle::lint::{allow, level, unused_imports}; use middle::lint::{get_lint_level, get_lint_settings_level}; use middle::pat_util::pat_bindings; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 7e64a219ecdd0..f58e066526c24 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -91,10 +91,8 @@ pub struct icx_popper { #[unsafe_destructor] impl Drop for icx_popper { fn finalize(&self) { - unsafe { - if self.ccx.sess.count_llvm_insns() { - self.ccx.stats.llvm_insn_ctxt.pop(); - } + if self.ccx.sess.count_llvm_insns() { + self.ccx.stats.llvm_insn_ctxt.pop(); } } } @@ -145,9 +143,7 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, llvm::LLVMGetOrInsertFunction(llmod, buf, llty) } }); - unsafe { - lib::llvm::SetFunctionCallConv(llfn, cc); - } + lib::llvm::SetFunctionCallConv(llfn, cc); return llfn; } @@ -730,11 +726,9 @@ pub fn cast_shift_expr_rhs(cx: block, op: ast::binop, pub fn cast_shift_const_rhs(op: ast::binop, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - unsafe { - cast_shift_rhs(op, lhs, rhs, - |a, b| unsafe { llvm::LLVMConstTrunc(a, b) }, - |a, b| unsafe { llvm::LLVMConstZExt(a, b) }) - } + cast_shift_rhs(op, lhs, rhs, + |a, b| unsafe { llvm::LLVMConstTrunc(a, b) }, + |a, b| unsafe { llvm::LLVMConstZExt(a, b) }) } pub fn cast_shift_rhs(op: ast::binop, @@ -2865,9 +2859,7 @@ pub fn create_module_map(ccx: @CrateContext) -> ValueRef { llvm::LLVMAddGlobal(ccx.llmod, maptype, buf) } }); - unsafe { - lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage); - } + lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage); let mut elts: ~[ValueRef] = ~[]; for ccx.module_data.each |key, &val| { let elt = C_struct(~[p2i(ccx, C_cstr(ccx, @/*bad*/ copy *key)), diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index fa2be2f415f95..d6c045bb1158b 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -27,9 +27,7 @@ use core::str; use core::vec; pub fn terminate(cx: block, _: &str) { - unsafe { - cx.terminated = true; - } + cx.terminated = true; } pub fn check_not_terminated(cx: block) { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 8c40142335e38..c02417aca8b12 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -172,17 +172,15 @@ fn cast_safely(val: T) -> U { } fn md_from_metadata(val: debug_metadata) -> T { - unsafe { - match val { - file_metadata(md) => cast_safely(md), - compile_unit_metadata(md) => cast_safely(md), - subprogram_metadata(md) => cast_safely(md), - local_var_metadata(md) => cast_safely(md), - tydesc_metadata(md) => cast_safely(md), - block_metadata(md) => cast_safely(md), - argument_metadata(md) => cast_safely(md), - retval_metadata(md) => cast_safely(md) - } + match val { + file_metadata(md) => cast_safely(md), + compile_unit_metadata(md) => cast_safely(md), + subprogram_metadata(md) => cast_safely(md), + local_var_metadata(md) => cast_safely(md), + tydesc_metadata(md) => cast_safely(md), + block_metadata(md) => cast_safely(md), + argument_metadata(md) => cast_safely(md), + retval_metadata(md) => cast_safely(md) } } @@ -190,56 +188,52 @@ fn cached_metadata(cache: metadata_cache, mdtag: int, eq_fn: &fn(md: T) -> bool) -> Option { - unsafe { - if cache.contains_key(&mdtag) { - let items = cache.get(&mdtag); - for items.each |item| { - let md: T = md_from_metadata::(*item); - if eq_fn(md) { - return option::Some(md); - } + if cache.contains_key(&mdtag) { + let items = cache.get(&mdtag); + for items.each |item| { + let md: T = md_from_metadata::(*item); + if eq_fn(md) { + return option::Some(md); } } - return option::None; } + return option::None; } fn create_compile_unit(cx: @CrateContext) -> @Metadata { - unsafe { - let cache = get_cache(cx); - let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; - let tg = CompileUnitTag; - match cached_metadata::<@Metadata>(cache, tg, - |md| md.data.name == crate_name) { - option::Some(md) => return md, - option::None => () - } + let cache = get_cache(cx); + let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; + let tg = CompileUnitTag; + match cached_metadata::<@Metadata>(cache, tg, + |md| md.data.name == crate_name) { + option::Some(md) => return md, + option::None => () + } - let (_, work_dir) = get_file_path_and_dir( - cx.sess.working_dir.to_str(), crate_name); - let unit_metadata = ~[lltag(tg), - llunused(), - lli32(DW_LANG_RUST), - llstr(crate_name), - llstr(work_dir), - llstr(env!("CFG_VERSION")), - lli1(true), // deprecated: main compile unit - lli1(cx.sess.opts.optimize != session::No), - llstr(~""), // flags (???) - lli32(0) // runtime version (???) - ]; - let unit_node = llmdnode(unit_metadata); - add_named_metadata(cx, ~"llvm.dbg.cu", unit_node); - let mdval = @Metadata { - node: unit_node, - data: CompileUnitMetadata { - name: crate_name - } - }; - update_cache(cache, tg, compile_unit_metadata(mdval)); + let (_, work_dir) = get_file_path_and_dir( + cx.sess.working_dir.to_str(), crate_name); + let unit_metadata = ~[lltag(tg), + llunused(), + lli32(DW_LANG_RUST), + llstr(crate_name), + llstr(work_dir), + llstr(env!("CFG_VERSION")), + lli1(true), // deprecated: main compile unit + lli1(cx.sess.opts.optimize != session::No), + llstr(~""), // flags (???) + lli32(0) // runtime version (???) + ]; + let unit_node = llmdnode(unit_metadata); + add_named_metadata(cx, ~"llvm.dbg.cu", unit_node); + let mdval = @Metadata { + node: unit_node, + data: CompileUnitMetadata { + name: crate_name + } + }; + update_cache(cache, tg, compile_unit_metadata(mdval)); - return mdval; - } + return mdval; } fn get_cache(cx: @CrateContext) -> metadata_cache { @@ -710,113 +704,109 @@ fn create_var(type_tag: int, context: ValueRef, name: &str, file: ValueRef, pub fn create_local_var(bcx: block, local: @ast::local) -> @Metadata { - unsafe { - let cx = bcx.ccx(); - let cache = get_cache(cx); - let tg = AutoVariableTag; - match cached_metadata::<@Metadata>( - cache, tg, |md| md.data.id == local.node.id) { - option::Some(md) => return md, - option::None => () + let cx = bcx.ccx(); + let cache = get_cache(cx); + let tg = AutoVariableTag; + match cached_metadata::<@Metadata>( + cache, tg, |md| md.data.id == local.node.id) { + option::Some(md) => return md, + option::None => () + } + + let name = match local.node.pat.node { + ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth), + // FIXME this should be handled (#2533) + _ => fail!(~"no single variable name for local") + }; + let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); + let ty = node_id_type(bcx, local.node.id); + let tymd = create_ty(cx, ty, local.node.ty.span); + let filemd = create_file(cx, /*bad*/copy loc.file.name); + let context = match bcx.parent { + None => create_function(bcx.fcx).node, + Some(_) => create_block(bcx).node + }; + let mdnode = create_var(tg, context, *cx.sess.str_of(name), + filemd.node, loc.line as int, tymd.node); + let mdval = @Metadata { + node: mdnode, + data: LocalVarMetadata { + id: local.node.id } + }; + update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); - let name = match local.node.pat.node { - ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth), - // FIXME this should be handled (#2533) - _ => fail!(~"no single variable name for local") - }; - let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); - let ty = node_id_type(bcx, local.node.id); - let tymd = create_ty(cx, ty, local.node.ty.span); - let filemd = create_file(cx, /*bad*/copy loc.file.name); - let context = match bcx.parent { - None => create_function(bcx.fcx).node, - Some(_) => create_block(bcx).node - }; - let mdnode = create_var(tg, context, *cx.sess.str_of(name), - filemd.node, loc.line as int, tymd.node); - let mdval = @Metadata { - node: mdnode, - data: LocalVarMetadata { - id: local.node.id - } - }; - update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); - - let llptr = match bcx.fcx.lllocals.find(&local.node.id) { - option::Some(&local_mem(v)) => v, - option::Some(_) => { - bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ - something weird"); - } - option::None => { - match *bcx.fcx.lllocals.get(&local.node.pat.id) { - local_imm(v) => v, - _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ - something weird") - } - } - }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; - trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), - declargs); - return mdval; - } + let llptr = match bcx.fcx.lllocals.find(&local.node.id) { + option::Some(&local_mem(v)) => v, + option::Some(_) => { + bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ + something weird"); + } + option::None => { + match *bcx.fcx.lllocals.get(&local.node.pat.id) { + local_imm(v) => v, + _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \ + something weird") + } + } + }; + let declargs = ~[llmdnode(~[llptr]), mdnode]; + trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), + declargs); + return mdval; } pub fn create_arg(bcx: block, arg: ast::arg, sp: span) -> Option<@Metadata> { - unsafe { - let fcx = bcx.fcx, cx = *fcx.ccx; - let cache = get_cache(cx); - let tg = ArgVariableTag; - match cached_metadata::<@Metadata>( - cache, ArgVariableTag, |md| md.data.id == arg.id) { - option::Some(md) => return Some(md), - option::None => () - } + let fcx = bcx.fcx, cx = *fcx.ccx; + let cache = get_cache(cx); + let tg = ArgVariableTag; + match cached_metadata::<@Metadata>( + cache, ArgVariableTag, |md| md.data.id == arg.id) { + option::Some(md) => return Some(md), + option::None => () + } - let loc = cx.sess.codemap.lookup_char_pos(sp.lo); - if loc.file.name == ~"" { - return None; + let loc = cx.sess.codemap.lookup_char_pos(sp.lo); + if loc.file.name == ~"" { + return None; + } + let ty = node_id_type(bcx, arg.id); + let tymd = create_ty(cx, ty, arg.ty.span); + let filemd = create_file(cx, /*bad*/copy loc.file.name); + let context = create_function(bcx.fcx); + + match arg.pat.node { + ast::pat_ident(_, path, _) => { + // XXX: This is wrong; it should work for multiple bindings. + let mdnode = create_var( + tg, + context.node, + *cx.sess.str_of(*path.idents.last()), + filemd.node, + loc.line as int, + tymd.node + ); + + let mdval = @Metadata { + node: mdnode, + data: ArgumentMetadata { + id: arg.id + } + }; + update_cache(cache, tg, argument_metadata(mdval)); + + let llptr = match *fcx.llargs.get(&arg.id) { + local_mem(v) | local_imm(v) => v, + }; + let declargs = ~[llmdnode(~[llptr]), mdnode]; + trans::build::Call(bcx, + *cx.intrinsics.get(&~"llvm.dbg.declare"), + declargs); + return Some(mdval); } - let ty = node_id_type(bcx, arg.id); - let tymd = create_ty(cx, ty, arg.ty.span); - let filemd = create_file(cx, /*bad*/copy loc.file.name); - let context = create_function(bcx.fcx); - - match arg.pat.node { - ast::pat_ident(_, path, _) => { - // XXX: This is wrong; it should work for multiple bindings. - let mdnode = create_var( - tg, - context.node, - *cx.sess.str_of(*path.idents.last()), - filemd.node, - loc.line as int, - tymd.node - ); - - let mdval = @Metadata { - node: mdnode, - data: ArgumentMetadata { - id: arg.id - } - }; - update_cache(cache, tg, argument_metadata(mdval)); - - let llptr = match *fcx.llargs.get(&arg.id) { - local_mem(v) | local_imm(v) => v, - }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; - trans::build::Call(bcx, - *cx.intrinsics.get(&~"llvm.dbg.declare"), - declargs); - return Some(mdval); - } - _ => { - return None; - } + _ => { + return None; } } } From 8978643f92fc8780515d838a9797f9454386618b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 02:08:03 -0400 Subject: [PATCH 188/403] syntax: remove unnecessary unsafe blocks/functions --- src/libsyntax/abi.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 37fed113382a2..a848f97d2e09e 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -274,13 +274,11 @@ impl ToStr for Abi { impl ToStr for AbiSet { fn to_str(&self) -> ~str { - unsafe { // so we can push to strs. - let mut strs = ~[]; - for self.each |abi| { - strs.push(abi.data().name); - } - fmt!("\"%s\"", str::connect_slices(strs, " ")) + let mut strs = ~[]; + for self.each |abi| { + strs.push(abi.data().name); } + fmt!("\"%s\"", str::connect_slices(strs, " ")) } } From 685c4d0b76b26439905b0676069818e757913319 Mon Sep 17 00:00:00 2001 From: Jyun-Yan You Date: Sun, 14 Apr 2013 13:15:46 +0800 Subject: [PATCH 189/403] add rust_dbg_extern_identity_TwoDoubles to prevent check-fast failure --- src/rt/rust_builtin.cpp | 10 ++++++++++ src/rt/rustrt.def.in | 1 + src/test/run-pass/issue-5754.rs | 7 ++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index f586e05772b76..3c6cc9d924522 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -866,6 +866,16 @@ rust_dbg_extern_identity_TwoU64s(TwoU64s u) { return u; } +struct TwoDoubles { + double one; + double two; +}; + +extern "C" CDECL TwoDoubles +rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { + return u; +} + extern "C" CDECL double rust_dbg_extern_identity_double(double u) { return u; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 59fd8991622c6..73dbe661d3f86 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -199,6 +199,7 @@ rust_opendir rust_dbg_extern_identity_u32 rust_dbg_extern_identity_u64 rust_dbg_extern_identity_TwoU64s +rust_dbg_extern_identity_TwoDoubles rust_dbg_extern_identity_double rust_dbg_extern_identity_u8 rust_get_rt_env diff --git a/src/test/run-pass/issue-5754.rs b/src/test/run-pass/issue-5754.rs index 003701b7a20cb..c440fe525eef9 100644 --- a/src/test/run-pass/issue-5754.rs +++ b/src/test/run-pass/issue-5754.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct S { - r: float +struct TwoDoubles { + r: float, + i: float } extern "C" { - fn rust_dbg_extern_identity_double(arg1: S) -> float; + fn rust_dbg_extern_identity_TwoDoubles(arg1: TwoDoubles) -> TwoDoubles; } pub fn main() {} From 59e69aa0e79302887abcb4b6bf3613c84b48e5d7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Apr 2013 02:08:16 -0400 Subject: [PATCH 190/403] test: remove unnecessary unsafe blocks/functions --- src/compiletest/errors.rs | 52 +++++++++++++++++++-------------------- src/compiletest/header.rs | 18 ++++++-------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 63b5c64c6d4a6..5a5c091d9570a 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -30,36 +30,34 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] { } fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { - unsafe { - let error_tag = ~"//~"; - let mut idx; - match str::find_str(line, error_tag) { - None => return ~[], - Some(nn) => { idx = (nn as uint) + str::len(error_tag); } - } + let error_tag = ~"//~"; + let mut idx; + match str::find_str(line, error_tag) { + None => return ~[], + Some(nn) => { idx = (nn as uint) + str::len(error_tag); } + } - // "//~^^^ kind msg" denotes a message expected - // three lines above current line: - let mut adjust_line = 0u; - let len = str::len(line); - while idx < len && line[idx] == ('^' as u8) { - adjust_line += 1u; - idx += 1u; - } + // "//~^^^ kind msg" denotes a message expected + // three lines above current line: + let mut adjust_line = 0u; + let len = str::len(line); + while idx < len && line[idx] == ('^' as u8) { + adjust_line += 1u; + idx += 1u; + } - // Extract kind: - while idx < len && line[idx] == (' ' as u8) { idx += 1u; } - let start_kind = idx; - while idx < len && line[idx] != (' ' as u8) { idx += 1u; } - let kind = str::to_lower(str::slice(line, start_kind, idx).to_owned()); + // Extract kind: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let start_kind = idx; + while idx < len && line[idx] != (' ' as u8) { idx += 1u; } + let kind = str::to_lower(str::slice(line, start_kind, idx).to_owned()); - // Extract msg: - while idx < len && line[idx] == (' ' as u8) { idx += 1u; } - let msg = str::slice(line, idx, len).to_owned(); + // Extract msg: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let msg = str::slice(line, idx, len).to_owned(); - debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); + debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); - return ~[ExpectedError{line: line_num - adjust_line, kind: kind, - msg: msg}]; - } + return ~[ExpectedError{line: line_num - adjust_line, kind: kind, + msg: msg}]; } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 5a35c56c075a7..2b36518833888 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -171,16 +171,14 @@ fn parse_name_directive(line: ~str, directive: ~str) -> bool { fn parse_name_value_directive(line: ~str, directive: ~str) -> Option<~str> { - unsafe { - let keycolon = directive + ~":"; - match str::find_str(line, keycolon) { - Some(colon) => { - let value = str::slice(line, colon + str::len(keycolon), - str::len(line)).to_owned(); - debug!("%s: %s", directive, value); - Some(value) - } - None => None + let keycolon = directive + ~":"; + match str::find_str(line, keycolon) { + Some(colon) => { + let value = str::slice(line, colon + str::len(keycolon), + str::len(line)).to_owned(); + debug!("%s: %s", directive, value); + Some(value) } + None => None } } From ced12a74cd5195852d9f074c5334a678f4aa001c Mon Sep 17 00:00:00 2001 From: Leah Hanson Date: Sun, 14 Apr 2013 08:01:54 -0400 Subject: [PATCH 191/403] update copyright notice on base64.rs --- src/libstd/base64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 054f3a2b10839..1a7c1542f9d56 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // From 6994340ca0ff75fd9fcef7defed8c5bfd7cab448 Mon Sep 17 00:00:00 2001 From: gareth Date: Sun, 14 Apr 2013 14:08:22 +0100 Subject: [PATCH 192/403] Flesh out the SIG* constants: this adds all the posix signal value constants, except for those that have different values on different architectures. The output of the command `man 7 signal` was used to compile these signal values. --- src/libcore/libc.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 02c72bcd2f0d0..e5c5b2f9f2c26 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -863,10 +863,20 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGHUP : int = 1; + pub static SIGINT : int = 2; + pub static SIGQUIT : int = 3; + pub static SIGILL : int = 4; + pub static SIGABRT : int = 6; + pub static SIGFPE : int = 8; pub static SIGKILL : int = 9; + pub static SIGSEGV : int = 11; + pub static SIGPIPE : int = 13; + pub static SIGALRM : int = 14; pub static SIGTERM : int = 15; } pub mod posix01 { + pub static SIGTRAP : int = 5; } pub mod posix08 { } @@ -932,10 +942,20 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGHUP : int = 1; + pub static SIGINT : int = 2; + pub static SIGQUIT : int = 3; + pub static SIGILL : int = 4; + pub static SIGABRT : int = 6; + pub static SIGFPE : int = 8; pub static SIGKILL : int = 9; + pub static SIGSEGV : int = 11; + pub static SIGPIPE : int = 13; + pub static SIGALRM : int = 14; pub static SIGTERM : int = 15; } pub mod posix01 { + pub static SIGTRAP : int = 5; } pub mod posix08 { } @@ -1002,10 +1022,20 @@ pub mod consts { pub static F_TEST : int = 3; pub static F_TLOCK : int = 2; pub static F_ULOCK : int = 0; + pub static SIGHUP : int = 1; + pub static SIGINT : int = 2; + pub static SIGQUIT : int = 3; + pub static SIGILL : int = 4; + pub static SIGABRT : int = 6; + pub static SIGFPE : int = 8; pub static SIGKILL : int = 9; + pub static SIGSEGV : int = 11; + pub static SIGPIPE : int = 13; + pub static SIGALRM : int = 14; pub static SIGTERM : int = 15; } pub mod posix01 { + pub static SIGTRAP : int = 5; } pub mod posix08 { } From b5c9990c387fff415a7de54f5870e5af92169a5d Mon Sep 17 00:00:00 2001 From: Leah Hanson Date: Sun, 14 Apr 2013 09:24:13 -0400 Subject: [PATCH 193/403] Change to 4-space indents in code examples --- src/libstd/base64.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 1a7c1542f9d56..5da7cfa3efed8 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -37,8 +37,8 @@ impl<'self> ToBase64 for &'self [u8] { * use std::base64::ToBase64; * * fn main () { - * let str = [52,32].to_base64(); - * println(fmt!("%s", str)); + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); * } * ~~~~ */ @@ -102,8 +102,8 @@ impl<'self> ToBase64 for &'self str { * use std::base64::ToBase64; * * fn main () { - * let str = "Hello, World".to_base64(); - * println(fmt!("%s",str)); + * let str = "Hello, World".to_base64(); + * println(fmt!("%s",str)); * } * ~~~~ * @@ -130,10 +130,10 @@ impl FromBase64 for ~[u8] { * use std::base64::FromBase64; * * fn main () { - * let str = [52,32].to_base64(); - * println(fmt!("%s", str)); - * let bytes = str.from_base64(); - * println(fmt!("%?",bytes)); + * let str = [52,32].to_base64(); + * println(fmt!("%s", str)); + * let bytes = str.from_base64(); + * println(fmt!("%?",bytes)); * } * ~~~~ */ @@ -217,12 +217,12 @@ impl FromBase64 for ~str { * use core::str; * * fn main () { - * let hello_str = "Hello, World".to_base64(); - * println(fmt!("%s",hello_str)); - * let bytes = hello_str.from_base64(); - * println(fmt!("%?",bytes)); - * let result_str = str::from_bytes(bytes); - * println(fmt!("%s",result_str)); + * let hello_str = "Hello, World".to_base64(); + * println(fmt!("%s",hello_str)); + * let bytes = hello_str.from_base64(); + * println(fmt!("%?",bytes)); + * let result_str = str::from_bytes(bytes); + * println(fmt!("%s",result_str)); * } * ~~~~ */ From caa107925728b2cd725c6e1fdce03f3d25c3863a Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 14 Apr 2013 11:35:58 -0400 Subject: [PATCH 194/403] Fix xfail'd ARC test --- src/test/run-pass/bind-by-move.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/run-pass/bind-by-move.rs b/src/test/run-pass/bind-by-move.rs index 1e836740f8e81..d3d0e48f5b0f7 100644 --- a/src/test/run-pass/bind-by-move.rs +++ b/src/test/run-pass/bind-by-move.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test // xfail-fast extern mod std; use std::arc; -fn dispose(+_x: arc::ARC) unsafe { } +fn dispose(+_x: arc::ARC) { unsafe { } } pub fn main() { - let p = arc::arc(true); + let p = arc::ARC(true); let x = Some(p); match x { Some(z) => { dispose(z); }, From 8e966216c7c59c1b1de08561502f0b78589db59a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 11 Apr 2013 17:34:52 -0700 Subject: [PATCH 195/403] core::rt: Restructure task_from_last_cleanup_job to borrow correctly We need a number of mutable references to contexts so name it `get_contexts` and return a tuple of all of them. --- src/libcore/rt/sched.rs | 111 +++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 48 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 46ea5713e2af3..eff25d22882de 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -151,7 +151,16 @@ pub impl Scheduler { // Store the task in the scheduler so it can be grabbed later self.current_task = Some(task); - self.swap_in_task(); + + // Take pointers to both the task and scheduler's saved registers. + { + let (sched_context, _, next_task_context) = self.get_contexts(); + let next_task_context = next_task_context.unwrap(); + // Context switch to the task, restoring it's registers + // and saving the scheduler's + Context::swap(sched_context, next_task_context); + } + // The running task should have passed ownership elsewhere assert!(self.current_task.is_none()); @@ -171,8 +180,11 @@ pub impl Scheduler { let dead_task = self.current_task.swap_unwrap(); self.enqueue_cleanup_job(RecycleTask(dead_task)); - let dead_task = self.task_from_last_cleanup_job(); - self.swap_out_task(dead_task); + { + let (sched_context, last_task_context, _) = self.get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); + } } /// Block a running task, context switch to the scheduler, then pass the @@ -194,9 +206,13 @@ pub impl Scheduler { }; let f_opaque = HackAroundBorrowCk::from_fn(f_fake_region); self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); - let blocked_task = self.task_from_last_cleanup_job(); + { + let (sched_context, last_task_context, _) = self.get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); + } - self.swap_out_task(blocked_task); + // XXX: Should probably run cleanup jobs } /// Switch directly to another task, without going through the scheduler. @@ -209,43 +225,17 @@ pub impl Scheduler { let old_running_task = self.current_task.swap_unwrap(); self.enqueue_cleanup_job(RescheduleTask(old_running_task)); - let old_running_task = self.task_from_last_cleanup_job(); - self.current_task = Some(next_task); - self.swap_in_task_from_running_task(old_running_task); - } - - - // * Context switching - - // NB: When switching to a task callers are expected to first set - // self.running_task. When switching away from a task likewise move - // out of the self.running_task - - priv fn swap_in_task(&mut self) { - // Take pointers to both the task and scheduler's saved registers. - let running_task: &~Task = self.current_task.get_ref(); - let task_context = &running_task.saved_context; - let scheduler_context = &mut self.saved_context; - - // Context switch to the task, restoring it's registers - // and saving the scheduler's - Context::swap(scheduler_context, task_context); - } - - priv fn swap_out_task(&mut self, running_task: &mut Task) { - let task_context = &mut running_task.saved_context; - let scheduler_context = &self.saved_context; - Context::swap(task_context, scheduler_context); - } + { + let (_, last_task_context, next_task_context) = self.get_contexts(); + let last_task_context = last_task_context.unwrap(); + let next_task_context = next_task_context.unwrap(); + Context::swap(last_task_context, next_task_context); + } - priv fn swap_in_task_from_running_task(&mut self, running_task: &mut Task) { - let running_task_context = &mut running_task.saved_context; - let next_context = &self.current_task.get_ref().saved_context; - Context::swap(running_task_context, next_context); + // XXX: Should probably run cleanup jobs } - // * Other stuff fn in_task_context(&self) -> bool { self.current_task.is_some() } @@ -270,20 +260,42 @@ pub impl Scheduler { } } - // XXX: Hack. This should return &'self mut but I don't know how to - // make the borrowcheck happy - fn task_from_last_cleanup_job(&mut self) -> &mut Task { - assert!(!self.cleanup_jobs.is_empty()); - let last_job: &'self mut CleanupJob = &mut self.cleanup_jobs[0]; - let last_task: &'self Task = match last_job { - &RescheduleTask(~ref task) => task, - &RecycleTask(~ref task) => task, - &GiveTask(~ref task, _) => task, + /// Get mutable references to all the contexts that may be involved in a + /// context switch. + /// + /// Returns (the scheduler context, the optional context of the + /// task in the cleanup list, the optional context of the task in + /// the current task slot). When context switching to a task, + /// callers should first arrange for that task to be located in the + /// Scheduler's current_task slot and set up the + /// post-context-switch cleanup job. + fn get_contexts(&mut self) -> (&'self mut Context, + Option<&'self mut Context>, + Option<&'self mut Context>) { + let last_task = if !self.cleanup_jobs.is_empty() { + let last_job: &'self mut CleanupJob = &mut self.cleanup_jobs[0]; + let last_task: &'self Task = match last_job { + &RescheduleTask(~ref task) => task, + &RecycleTask(~ref task) => task, + &GiveTask(~ref task, _) => task, + }; + Some(last_task) + } else { + None }; // XXX: Pattern matching mutable pointers above doesn't work // because borrowck thinks the three patterns are conflicting // borrows - return unsafe { transmute::<&Task, &mut Task>(last_task) }; + let last_task = unsafe { transmute::, Option<&mut Task>>(last_task) }; + let last_task_context = match last_task { + Some(ref t) => Some(&mut t.saved_context), None => None + }; + let next_task_context = match self.current_task { + Some(ref mut t) => Some(&mut t.saved_context), None => None + }; + return (&mut self.saved_context, + last_task_context, + next_task_context); } } @@ -313,6 +325,9 @@ pub impl Task { priv fn build_start_wrapper(start: ~fn()) -> ~fn() { // XXX: The old code didn't have this extra allocation let wrapper: ~fn() = || { + // XXX: Should probably run scheduler cleanup jobs for situations + // where a task context switches directly to a new task + start(); let mut sched = ThreadLocalScheduler::new(); From 1cb78e736f89cf286d454d7af05b470d570be1a7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 14 Apr 2013 16:12:30 -0700 Subject: [PATCH 196/403] core::rt: Rename block_running_task_and_then to deschedul_... --- src/libcore/rt/sched.rs | 4 ++-- src/libcore/rt/uvio.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index eff25d22882de..2160d62fc537c 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -195,7 +195,7 @@ pub impl Scheduler { /// The closure here is a *stack* closure that lives in the /// running task. It gets transmuted to the scheduler's lifetime /// and called while the task is blocked. - fn block_running_task_and_then(&mut self, f: &fn(&mut Scheduler, ~Task)) { + fn deschedule_running_task_and_then(&mut self, f: &fn(&mut Scheduler, ~Task)) { assert!(self.in_task_context()); rtdebug!("blocking task"); @@ -566,7 +566,7 @@ fn test_block_task() { let task = ~do Task::new(&mut sched.stack_pool) { do Scheduler::local |sched| { assert!(sched.in_task_context()); - do sched.block_running_task_and_then() |sched, task| { + do sched.deschedule_running_task_and_then() |sched, task| { assert!(!sched.in_task_context()); sched.task_queue.push_back(task); } diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 37f29d1a5c0fe..97c65b39f9c92 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -108,7 +108,7 @@ impl IoFactory for UvIoFactory { assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context - do scheduler.block_running_task_and_then |scheduler, task| { + do scheduler.deschedule_running_task_and_then |scheduler, task| { rtdebug!("connect: entered scheduler context"); assert!(!scheduler.in_task_context()); @@ -181,7 +181,7 @@ impl TcpListener for UvTcpListener { do Scheduler::local |scheduler| { assert!(scheduler.in_task_context()); - do scheduler.block_running_task_and_then |_, task| { + do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell(task); let mut server_tcp_watcher = server_tcp_watcher; do server_tcp_watcher.listen |server_stream_watcher, status| { @@ -247,7 +247,7 @@ impl Stream for UvStream { assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; - do scheduler.block_running_task_and_then |scheduler, task| { + do scheduler.deschedule_running_task_and_then |scheduler, task| { rtdebug!("read: entered scheduler context"); assert!(!scheduler.in_task_context()); let mut watcher = watcher; @@ -293,7 +293,7 @@ impl Stream for UvStream { assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; - do scheduler.block_running_task_and_then |_, task| { + do scheduler.deschedule_running_task_and_then |_, task| { let mut watcher = watcher; let task_cell = Cell(task); let buf = unsafe { &*buf_ptr }; @@ -420,7 +420,7 @@ fn test_read_and_block() { // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it - do scheduler.block_running_task_and_then |scheduler, task| { + do scheduler.deschedule_running_task_and_then |scheduler, task| { scheduler.task_queue.push_back(task); } } From 6b084bad250e58c4003a1df40584f6385f44aac1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 14 Apr 2013 16:25:33 -0700 Subject: [PATCH 197/403] core::rt: Insert calls to run_cleanup_tasks after all context switches --- src/libcore/rt/sched.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 2160d62fc537c..62262a5a520d5 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -212,7 +212,7 @@ pub impl Scheduler { Context::swap(last_task_context, sched_context); } - // XXX: Should probably run cleanup jobs + self.run_cleanup_jobs(); } /// Switch directly to another task, without going through the scheduler. @@ -233,7 +233,7 @@ pub impl Scheduler { Context::swap(last_task_context, next_task_context); } - // XXX: Should probably run cleanup jobs + self.run_cleanup_jobs(); } // * Other stuff @@ -245,7 +245,6 @@ pub impl Scheduler { } fn run_cleanup_jobs(&mut self) { - assert!(!self.in_task_context()); rtdebug!("running cleanup jobs"); while !self.cleanup_jobs.is_empty() { @@ -325,8 +324,12 @@ pub impl Task { priv fn build_start_wrapper(start: ~fn()) -> ~fn() { // XXX: The old code didn't have this extra allocation let wrapper: ~fn() = || { - // XXX: Should probably run scheduler cleanup jobs for situations - // where a task context switches directly to a new task + // This is the first code to execute after the initial + // context switch to the task. The previous context may + // have asked us to do some cleanup. + let mut sched = ThreadLocalScheduler::new(); + let sched = sched.get_scheduler(); + sched.run_cleanup_jobs(); start(); From 5f52aecb1e7a53bf46280d057654746c34e89859 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 14 Apr 2013 19:24:43 -0700 Subject: [PATCH 198/403] core::rt: Schedulers only need a single cleanup_job at a time Each context switch has up to one cleanup job and it is always executed immediately after the context switch. --- src/libcore/rt/sched.rs | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 62262a5a520d5..11934d676e660 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -38,12 +38,9 @@ pub struct Scheduler { priv saved_context: Context, /// The currently executing task priv current_task: Option<~Task>, - /// A queue of jobs to perform immediately upon return from task - /// context to scheduler context. - /// XXX: This probably should be a single cleanup action and it - /// should run after a context switch, not on return from the - /// scheduler - priv cleanup_jobs: ~[CleanupJob] + /// An action performed after a context switch on behalf of the + /// code running before the context switch + priv cleanup_job: Option } // XXX: Some hacks to put a &fn in Scheduler without borrowck @@ -84,7 +81,7 @@ pub impl Scheduler { stack_pool: StackPool::new(), saved_context: Context::empty(), current_task: None, - cleanup_jobs: ~[] + cleanup_job: None } } @@ -165,7 +162,7 @@ pub impl Scheduler { assert!(self.current_task.is_none()); // Running tasks may have asked us to do some cleanup - self.run_cleanup_jobs(); + self.run_cleanup_job(); } @@ -212,7 +209,7 @@ pub impl Scheduler { Context::swap(last_task_context, sched_context); } - self.run_cleanup_jobs(); + self.run_cleanup_job(); } /// Switch directly to another task, without going through the scheduler. @@ -233,7 +230,7 @@ pub impl Scheduler { Context::swap(last_task_context, next_task_context); } - self.run_cleanup_jobs(); + self.run_cleanup_job(); } // * Other stuff @@ -241,21 +238,25 @@ pub impl Scheduler { fn in_task_context(&self) -> bool { self.current_task.is_some() } fn enqueue_cleanup_job(&mut self, job: CleanupJob) { - self.cleanup_jobs.unshift(job); + assert!(self.cleanup_job.is_none()); + self.cleanup_job = Some(job); } - fn run_cleanup_jobs(&mut self) { + fn run_cleanup_job(&mut self) { rtdebug!("running cleanup jobs"); - while !self.cleanup_jobs.is_empty() { - match self.cleanup_jobs.pop() { - RescheduleTask(task) => { - // NB: Pushing to the *front* of the queue - self.task_queue.push_front(task); - } - RecycleTask(task) => task.recycle(&mut self.stack_pool), - GiveTask(task, f) => (f.to_fn())(self, task) + if self.cleanup_job.is_none() { + return; + } + + let cleanup_job = self.cleanup_job.swap_unwrap(); + match cleanup_job { + RescheduleTask(task) => { + // NB: Pushing to the *front* of the queue + self.task_queue.push_front(task); } + RecycleTask(task) => task.recycle(&mut self.stack_pool), + GiveTask(task, f) => (f.to_fn())(self, task) } } @@ -271,16 +272,15 @@ pub impl Scheduler { fn get_contexts(&mut self) -> (&'self mut Context, Option<&'self mut Context>, Option<&'self mut Context>) { - let last_task = if !self.cleanup_jobs.is_empty() { - let last_job: &'self mut CleanupJob = &mut self.cleanup_jobs[0]; - let last_task: &'self Task = match last_job { - &RescheduleTask(~ref task) => task, - &RecycleTask(~ref task) => task, - &GiveTask(~ref task, _) => task, - }; - Some(last_task) - } else { - None + let last_task = match self.cleanup_job { + Some(RescheduleTask(~ref task)) | + Some(RecycleTask(~ref task)) | + Some(GiveTask(~ref task, _)) => { + Some(task) + } + None => { + None + } }; // XXX: Pattern matching mutable pointers above doesn't work // because borrowck thinks the three patterns are conflicting @@ -329,7 +329,7 @@ pub impl Task { // have asked us to do some cleanup. let mut sched = ThreadLocalScheduler::new(); let sched = sched.get_scheduler(); - sched.run_cleanup_jobs(); + sched.run_cleanup_job(); start(); From a2e5827866876e9bafcf1f4e94f4e354e500420a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 14 Apr 2013 20:24:15 -0700 Subject: [PATCH 199/403] core::rt: All context switches are followed by a cleanup action --- src/libcore/rt/sched.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 11934d676e660..7cfb5b7903f7f 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -60,6 +60,7 @@ impl HackAroundBorrowCk for UnsafeTaskReceiver { } enum CleanupJob { + DoNothing, RescheduleTask(~Task), RecycleTask(~Task), GiveTask(~Task, UnsafeTaskReceiver) @@ -148,6 +149,7 @@ pub impl Scheduler { // Store the task in the scheduler so it can be grabbed later self.current_task = Some(task); + self.enqueue_cleanup_job(DoNothing); // Take pointers to both the task and scheduler's saved registers. { @@ -243,14 +245,13 @@ pub impl Scheduler { } fn run_cleanup_job(&mut self) { - rtdebug!("running cleanup jobs"); + rtdebug!("running cleanup job"); - if self.cleanup_job.is_none() { - return; - } + assert!(self.cleanup_job.is_some()); let cleanup_job = self.cleanup_job.swap_unwrap(); match cleanup_job { + DoNothing => { } RescheduleTask(task) => { // NB: Pushing to the *front* of the queue self.task_queue.push_front(task); @@ -278,9 +279,10 @@ pub impl Scheduler { Some(GiveTask(~ref task, _)) => { Some(task) } - None => { + Some(DoNothing) => { None } + None => fail!(fmt!("all context switches should have a cleanup job")) }; // XXX: Pattern matching mutable pointers above doesn't work // because borrowck thinks the three patterns are conflicting From 93757d81853302408dd30a3ad1a4102eae26b7c5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 14 Apr 2013 21:34:38 -0700 Subject: [PATCH 200/403] core::rt: Clean up the thread-local scheduler code Remove the ThreadLocalScheduler type in favor of functions. Move everything into the sched::local module. --- src/libcore/rt/sched.rs | 153 +++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 74 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 7cfb5b7903f7f..e4d9c9681d74e 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -11,14 +11,11 @@ use option::*; use sys; use cast::transmute; -use libc::c_void; -use ptr::mut_null; use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; -use tls = super::thread_local_storage; #[cfg(test)] use super::uvio::UvEventLoop; #[cfg(test)] use unstable::run_in_bare_thread; @@ -110,18 +107,13 @@ pub impl Scheduler { } fn install(~self, f: &fn(&mut Scheduler)) -> ~Scheduler { - let mut tlsched = ThreadLocalScheduler::new(); - tlsched.put_scheduler(self); - { - let sched = tlsched.get_scheduler(); - f(sched); + do local::install(self) { + local::borrow(f) } - return tlsched.take_scheduler(); } fn local(f: &fn(&mut Scheduler)) { - let mut tlsched = ThreadLocalScheduler::new(); - f(tlsched.get_scheduler()); + local::borrow(f) } // * Scheduler-context operations @@ -329,15 +321,15 @@ pub impl Task { // This is the first code to execute after the initial // context switch to the task. The previous context may // have asked us to do some cleanup. - let mut sched = ThreadLocalScheduler::new(); - let sched = sched.get_scheduler(); - sched.run_cleanup_job(); + do Scheduler::local |sched| { + sched.run_cleanup_job(); + } start(); - let mut sched = ThreadLocalScheduler::new(); - let sched = sched.get_scheduler(); - sched.terminate_current_task(); + do Scheduler::local |sched| { + sched.terminate_current_task(); + } }; return wrapper; } @@ -352,90 +344,103 @@ pub impl Task { } } -// NB: This is a type so we can use make use of the &self region. -struct ThreadLocalScheduler(tls::Key); +mod local { + + //! Access to the thread-local Scheduler + + use ptr::mut_null; + use libc::c_void; + use cast::transmute; + + use super::Scheduler; + use tls = super::super::thread_local_storage; + #[cfg(test)] use super::super::uvio::UvEventLoop; -impl ThreadLocalScheduler { - fn new() -> ThreadLocalScheduler { + /// Give the Scheduler to thread-local storage + pub fn put(sched: ~Scheduler) { unsafe { - // NB: This assumes that the TLS key has been created prior. - // Currently done in rust_start. - let key: *mut c_void = rust_get_sched_tls_key(); - let key: &mut tls::Key = transmute(key); - ThreadLocalScheduler(*key) + let key = tls_key(); + let void_sched: *mut c_void = transmute::<~Scheduler, *mut c_void>(sched); + tls::set(key, void_sched); } } - fn put_scheduler(&mut self, scheduler: ~Scheduler) { + /// Take ownership of the Scheduler from thread-local storage + pub fn take() -> ~Scheduler { unsafe { - let key = match self { &ThreadLocalScheduler(key) => key }; - let value: *mut c_void = transmute::<~Scheduler, *mut c_void>(scheduler); - tls::set(key, value); + let key = tls_key(); + let void_sched: *mut c_void = tls::get(key); + assert!(void_sched.is_not_null()); + let sched = transmute::<*mut c_void, ~Scheduler>(void_sched); + tls::set(key, mut_null()); + return sched; } } - fn get_scheduler(&mut self) -> &'self mut Scheduler { + /// Give the Scheduler to thread-local storage for the duration of the block + pub fn install(sched: ~Scheduler, f: &fn()) -> ~Scheduler { + put(sched); + f(); + return take(); + } + + /// Borrow a mutable reference to the thread-local Scheduler + /// # Safety Note + /// Because this leaves the Scheduler in thread-local storage it is possible + /// For the Scheduler pointer to be aliased + pub fn borrow(f: &fn(&mut Scheduler)) { unsafe { - let key = match self { &ThreadLocalScheduler(key) => key }; - let mut value: *mut c_void = tls::get(key); - assert!(value.is_not_null()); + let key = tls_key(); + let mut void_sched: *mut c_void = tls::get(key); + assert!(void_sched.is_not_null()); { - let value_ptr = &mut value; + let void_sched_ptr = &mut void_sched; let sched: &mut ~Scheduler = { - transmute::<&mut *mut c_void, &mut ~Scheduler>(value_ptr) + transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) }; let sched: &mut Scheduler = &mut **sched; - return sched; + f(sched); } } } - fn take_scheduler(&mut self) -> ~Scheduler { + fn tls_key() -> tls::Key { unsafe { - let key = match self { &ThreadLocalScheduler(key) => key }; - let value: *mut c_void = tls::get(key); - assert!(value.is_not_null()); - let sched = transmute(value); - tls::set(key, mut_null()); - return sched; + let key: *mut c_void = rust_get_sched_tls_key(); + let key: &mut tls::Key = transmute(key); + return *key; } } -} - -extern { - fn rust_get_sched_tls_key() -> *mut c_void; -} - -#[test] -fn thread_local_scheduler_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - let mut tls_scheduler = ThreadLocalScheduler::new(); - tls_scheduler.put_scheduler(scheduler); - { - let _scheduler = tls_scheduler.get_scheduler(); - } - let _scheduler = tls_scheduler.take_scheduler(); -} -#[test] -fn thread_local_scheduler_two_instances() { - let scheduler = ~UvEventLoop::new_scheduler(); - let mut tls_scheduler = ThreadLocalScheduler::new(); - tls_scheduler.put_scheduler(scheduler); - { + extern { + fn rust_get_sched_tls_key() -> *mut c_void; + } - let _scheduler = tls_scheduler.get_scheduler(); + #[test] + fn thread_local_scheduler_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); } - { - let scheduler = tls_scheduler.take_scheduler(); - tls_scheduler.put_scheduler(scheduler); + + #[test] + fn thread_local_scheduler_two_instances() { + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); } - let mut tls_scheduler = ThreadLocalScheduler::new(); - { - let _scheduler = tls_scheduler.get_scheduler(); + #[test] + fn install_borrow_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + let _scheduler = do install(scheduler) { + do borrow |_sched| { + } + }; } - let _scheduler = tls_scheduler.take_scheduler(); } #[test] From 672ddeac37ba9845de5d525b5a3ea0eeda2e785b Mon Sep 17 00:00:00 2001 From: Saurabh Anand Date: Mon, 15 Apr 2013 22:51:24 +0530 Subject: [PATCH 201/403] Modified submodules to use https instead of git for git URL --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4c61c7e409bd7..52ece628c573f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "src/llvm"] path = src/llvm - url = git://github.com/brson/llvm.git + url = https://github.com/brson/llvm.git [submodule "src/libuv"] path = src/libuv - url = git://github.com/brson/libuv.git + url = https://github.com/brson/libuv.git From 7881bde0271ed4dd68e2a286ed456c2578e70d6a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Apr 2013 11:52:10 -0700 Subject: [PATCH 202/403] Tidy --- src/librustpkg/path_util.rs | 4 ++-- src/librustpkg/util.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index c77106a9a39cb..c821281184d3b 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -75,9 +75,9 @@ mod test { let substitute_path = Path("xyzzy"); assert!(default_dest_dir(&the_path) == the_path.push(~"build")); let nonexistent_path = mk_nonexistent(&the_path, "quux"); - let bogus = do ::conditions::bad_path::cond.trap(|_| { + let bogus = do ::conditions::bad_path::cond.trap(|_| { substitute_path }).in { default_dest_dir(&nonexistent_path) }; assert!(bogus == substitute_path); } -} \ No newline at end of file +} diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 602c71cf8be96..4c38a177e7295 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -579,7 +579,7 @@ mod test { assert!(is_cmd(~"uninstall")); assert!(is_cmd(~"unprefer")); } - + #[test] fn test_parse_name() { assert!(parse_name(~"org.mozilla.servo").get() == ~"servo"); From 9b55d86e74112361c560e49ca28a8fc71964adb9 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Tue, 16 Apr 2013 04:13:37 +0900 Subject: [PATCH 203/403] Prevent eval_const_expr_partial hides prior error in expr_cast arm. This will help not to meet confusing errors. In issue #5873, the error was "expected constant expr for vector length: Can't cast str to int". It was originally "expected constant expr for vector length: Non-constant path in constant expr" This patch make the original error to be printed. --- src/librustc/middle/const_eval.rs | 49 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d6434e469b2d1..63122a82eafdf 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -371,32 +371,31 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) expr_cast(base, _) => { let ety = ty::expr_ty(tcx, e); let base = eval_const_expr_partial(tcx, base); - match ty::get(ety).sty { - ty::ty_float(_) => { - match base { - Ok(const_uint(u)) => Ok(const_float(u as f64)), - Ok(const_int(i)) => Ok(const_float(i as f64)), - Ok(const_float(_)) => base, - _ => Err(~"Can't cast float to str") - } - } - ty::ty_uint(_) => { - match base { - Ok(const_uint(_)) => base, - Ok(const_int(i)) => Ok(const_uint(i as u64)), - Ok(const_float(f)) => Ok(const_uint(f as u64)), - _ => Err(~"Can't cast str to uint") - } - } - ty::ty_int(_) | ty::ty_bool => { - match base { - Ok(const_uint(u)) => Ok(const_int(u as i64)), - Ok(const_int(_)) => base, - Ok(const_float(f)) => Ok(const_int(f as i64)), - _ => Err(~"Can't cast str to int") + match /*bad*/copy base { + Err(_) => base, + Ok(val) => { + match ty::get(ety).sty { + ty::ty_float(_) => match val { + const_uint(u) => Ok(const_float(u as f64)), + const_int(i) => Ok(const_float(i as f64)), + const_float(_) => base, + _ => Err(~"Can't cast float to str"), + }, + ty::ty_uint(_) => match val { + const_uint(_) => base, + const_int(i) => Ok(const_uint(i as u64)), + const_float(f) => Ok(const_uint(f as u64)), + _ => Err(~"Can't cast str to uint"), + }, + ty::ty_int(_) | ty::ty_bool => match val { + const_uint(u) => Ok(const_int(u as i64)), + const_int(_) => base, + const_float(f) => Ok(const_int(f as i64)), + _ => Err(~"Can't cast str to int"), + }, + _ => Err(~"Can't cast this type") + } } - } - _ => Err(~"Can't cast this type") } } expr_path(_) => { From 6beddb966d06d66c07ad3dcd2e42e64fbdddf69e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 13:20:21 -0700 Subject: [PATCH 204/403] Make valgrind suppressions more liberal Hopefully this puts out the final fire --- src/etc/x86.supp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/etc/x86.supp b/src/etc/x86.supp index 2a955dfdbac85..d592e5b7deba2 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -612,7 +612,6 @@ llvm-optimization-reads-uninitialized-memory-9 Memcheck:Cond fun:_ZN5parse6parser14__extensions__10meth_*parse_item_foreign_fn* - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* ... } @@ -628,7 +627,6 @@ llvm-optimization-reads-uninitialized-memory-12 Memcheck:Cond fun:_ZN5parse6parser14__extensions__10meth_*parse_item_struct* - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* ... } @@ -636,7 +634,6 @@ llvm-optimization-reads-uninitialized-memory-13 Memcheck:Cond fun:_ZN5parse6parser14__extensions__10meth_*parse_item_type* - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_or_view_item* ... } From 7cd681684f96c0f59468346384f6f5c5a04a7ff5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 27 Mar 2013 14:12:40 -0700 Subject: [PATCH 205/403] rt: Move test functions to rust_test_helpers.cpp --- mk/rt.mk | 3 +- src/rt/rust_builtin.cpp | 86 ---------------------------- src/rt/rust_test_helpers.cpp | 105 +++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 87 deletions(-) create mode 100644 src/rt/rust_test_helpers.cpp diff --git a/mk/rt.mk b/mk/rt.mk index b2c282e207fbc..015992abf7821 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -76,7 +76,8 @@ RUNTIME_CXXS_$(1) := \ rt/boxed_region.cpp \ rt/arch/$$(HOST_$(1))/context.cpp \ rt/arch/$$(HOST_$(1))/gpr.cpp \ - rt/rust_android_dummy.cpp + rt/rust_android_dummy.cpp \ + rt/rust_test_helpers.cpp RUNTIME_CS_$(1) := rt/linenoise/linenoise.c rt/linenoise/utf8.c diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 3c6cc9d924522..475c030e8f250 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -589,50 +589,6 @@ rust_log_console_off() { log_console_off(task->kernel->env); } -extern "C" CDECL lock_and_signal * -rust_dbg_lock_create() { - return new lock_and_signal(); -} - -extern "C" CDECL void -rust_dbg_lock_destroy(lock_and_signal *lock) { - assert(lock); - delete lock; -} - -extern "C" CDECL void -rust_dbg_lock_lock(lock_and_signal *lock) { - assert(lock); - lock->lock(); -} - -extern "C" CDECL void -rust_dbg_lock_unlock(lock_and_signal *lock) { - assert(lock); - lock->unlock(); -} - -extern "C" CDECL void -rust_dbg_lock_wait(lock_and_signal *lock) { - assert(lock); - lock->wait(); -} - -extern "C" CDECL void -rust_dbg_lock_signal(lock_and_signal *lock) { - assert(lock); - lock->signal(); -} - -typedef void *(*dbg_callback)(void*); - -extern "C" CDECL void * -rust_dbg_call(dbg_callback cb, void *data) { - return cb(data); -} - -extern "C" CDECL void rust_dbg_do_nothing() { } - extern "C" CDECL void rust_dbg_breakpoint() { BREAKPOINT_AWESOME; @@ -844,48 +800,6 @@ rust_readdir() { #endif -// These functions are used in the unit tests for C ABI calls. - -extern "C" CDECL uint32_t -rust_dbg_extern_identity_u32(uint32_t u) { - return u; -} - -extern "C" CDECL uint64_t -rust_dbg_extern_identity_u64(uint64_t u) { - return u; -} - -struct TwoU64s { - uint64_t one; - uint64_t two; -}; - -extern "C" CDECL TwoU64s -rust_dbg_extern_identity_TwoU64s(TwoU64s u) { - return u; -} - -struct TwoDoubles { - double one; - double two; -}; - -extern "C" CDECL TwoDoubles -rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { - return u; -} - -extern "C" CDECL double -rust_dbg_extern_identity_double(double u) { - return u; -} - -extern "C" CDECL char -rust_dbg_extern_identity_u8(char u) { - return u; -} - extern "C" rust_env* rust_get_rt_env() { rust_task *task = rust_get_current_task(); diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.cpp new file mode 100644 index 0000000000000..2c8026f159efa --- /dev/null +++ b/src/rt/rust_test_helpers.cpp @@ -0,0 +1,105 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Helper functions used only in tests + +#include "rust_sched_loop.h" +#include "rust_task.h" +#include "rust_util.h" +#include "rust_scheduler.h" +#include "sync/timer.h" +#include "sync/rust_thread.h" +#include "rust_abi.h" + +// These functions are used in the unit tests for C ABI calls. + +extern "C" CDECL uint32_t +rust_dbg_extern_identity_u32(uint32_t u) { + return u; +} + +extern "C" CDECL uint64_t +rust_dbg_extern_identity_u64(uint64_t u) { + return u; +} + +struct TwoU64s { + uint64_t one; + uint64_t two; +}; + +extern "C" CDECL TwoU64s +rust_dbg_extern_identity_TwoU64s(TwoU64s u) { + return u; +} + +struct TwoDoubles { + double one; + double two; +}; + +extern "C" CDECL TwoDoubles +rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { + return u; +} + +extern "C" CDECL double +rust_dbg_extern_identity_double(double u) { + return u; +} + +extern "C" CDECL char +rust_dbg_extern_identity_u8(char u) { + return u; +} + +extern "C" CDECL lock_and_signal * +rust_dbg_lock_create() { + return new lock_and_signal(); +} + +extern "C" CDECL void +rust_dbg_lock_destroy(lock_and_signal *lock) { + assert(lock); + delete lock; +} + +extern "C" CDECL void +rust_dbg_lock_lock(lock_and_signal *lock) { + assert(lock); + lock->lock(); +} + +extern "C" CDECL void +rust_dbg_lock_unlock(lock_and_signal *lock) { + assert(lock); + lock->unlock(); +} + +extern "C" CDECL void +rust_dbg_lock_wait(lock_and_signal *lock) { + assert(lock); + lock->wait(); +} + +extern "C" CDECL void +rust_dbg_lock_signal(lock_and_signal *lock) { + assert(lock); + lock->signal(); +} + +typedef void *(*dbg_callback)(void*); + +extern "C" CDECL void * +rust_dbg_call(dbg_callback cb, void *data) { + return cb(data); +} + +extern "C" CDECL void rust_dbg_do_nothing() { } From 4f1dd1fd212f51f0a2f4fe20f9ebc7e0dc9081d8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 15:13:34 -0700 Subject: [PATCH 206/403] core::rt: Fix two incorrect uses of the thread-local scheduler These would not be threadsafe --- src/libcore/rt/sched.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index e4d9c9681d74e..6ed212008761d 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -203,7 +203,10 @@ pub impl Scheduler { Context::swap(last_task_context, sched_context); } - self.run_cleanup_job(); + // We could be executing in a different thread now + do local::borrow |sched| { + sched.run_cleanup_job(); + } } /// Switch directly to another task, without going through the scheduler. @@ -224,7 +227,10 @@ pub impl Scheduler { Context::swap(last_task_context, next_task_context); } - self.run_cleanup_job(); + // We could be executing in a different thread now + do local::borrow |sched| { + sched.run_cleanup_job(); + } } // * Other stuff From 1f8ebb6a8ebc5ee490158d3f4264f8aefd509045 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 13:40:36 -0700 Subject: [PATCH 207/403] core::rt: Move thread-local scheduler to its own module --- src/libcore/rt/mod.rs | 1 + src/libcore/rt/sched/local.rs | 106 ++++++++++++++++++++++ src/libcore/rt/{sched.rs => sched/mod.rs} | 101 +-------------------- 3 files changed, 109 insertions(+), 99 deletions(-) create mode 100644 src/libcore/rt/sched/local.rs rename src/libcore/rt/{sched.rs => sched/mod.rs} (85%) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 0f2a6cd7ef9ef..b1227af5f4c33 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -32,6 +32,7 @@ macro_rules! rtdebug ( ($( $arg:expr),+) => ( $(let _ = $arg)*; ) ) +#[path = "sched/mod.rs"] mod sched; mod rtio; pub mod uvll; diff --git a/src/libcore/rt/sched/local.rs b/src/libcore/rt/sched/local.rs new file mode 100644 index 0000000000000..1b1a003301768 --- /dev/null +++ b/src/libcore/rt/sched/local.rs @@ -0,0 +1,106 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Access to the thread-local Scheduler + +use ptr::mut_null; +use libc::c_void; +use cast::transmute; + +use super::Scheduler; +use tls = super::super::thread_local_storage; +#[cfg(test)] use super::super::uvio::UvEventLoop; + +/// Give the Scheduler to thread-local storage +pub fn put(sched: ~Scheduler) { + unsafe { + let key = tls_key(); + let void_sched: *mut c_void = transmute::<~Scheduler, *mut c_void>(sched); + tls::set(key, void_sched); + } +} + +/// Take ownership of the Scheduler from thread-local storage +pub fn take() -> ~Scheduler { + unsafe { + let key = tls_key(); + let void_sched: *mut c_void = tls::get(key); + assert!(void_sched.is_not_null()); + let sched = transmute::<*mut c_void, ~Scheduler>(void_sched); + tls::set(key, mut_null()); + return sched; + } +} + +/// Give the Scheduler to thread-local storage for the duration of the block +pub fn install(sched: ~Scheduler, f: &fn()) -> ~Scheduler { + put(sched); + f(); + return take(); +} + +/// Borrow a mutable reference to the thread-local Scheduler +/// # Safety Note +/// Because this leaves the Scheduler in thread-local storage it is possible +/// For the Scheduler pointer to be aliased +pub fn borrow(f: &fn(&mut Scheduler)) { + unsafe { + let key = tls_key(); + let mut void_sched: *mut c_void = tls::get(key); + assert!(void_sched.is_not_null()); + { + let void_sched_ptr = &mut void_sched; + let sched: &mut ~Scheduler = { + transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) + }; + let sched: &mut Scheduler = &mut **sched; + f(sched); + } + } +} + +fn tls_key() -> tls::Key { + unsafe { + let key: *mut c_void = rust_get_sched_tls_key(); + let key: &mut tls::Key = transmute(key); + return *key; + } +} + +extern { + fn rust_get_sched_tls_key() -> *mut c_void; +} + +#[test] +fn thread_local_scheduler_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); +} + +#[test] +fn thread_local_scheduler_two_instances() { + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); + let scheduler = ~UvEventLoop::new_scheduler(); + put(scheduler); + let _scheduler = take(); +} + +#[test] +fn install_borrow_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + let _scheduler = do install(scheduler) { + do borrow |_sched| { + } + }; +} + diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched/mod.rs similarity index 85% rename from src/libcore/rt/sched.rs rename to src/libcore/rt/sched/mod.rs index 6ed212008761d..bc25023d05ff6 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched/mod.rs @@ -21,6 +21,8 @@ use super::context::Context; #[cfg(test)] use unstable::run_in_bare_thread; #[cfg(test)] use int; +mod local; + /// The Scheduler is responsible for coordinating execution of Tasks /// on a single thread. When the scheduler is running it is owned by /// thread local storage and the running task is owned by the @@ -350,105 +352,6 @@ pub impl Task { } } -mod local { - - //! Access to the thread-local Scheduler - - use ptr::mut_null; - use libc::c_void; - use cast::transmute; - - use super::Scheduler; - use tls = super::super::thread_local_storage; - #[cfg(test)] use super::super::uvio::UvEventLoop; - - /// Give the Scheduler to thread-local storage - pub fn put(sched: ~Scheduler) { - unsafe { - let key = tls_key(); - let void_sched: *mut c_void = transmute::<~Scheduler, *mut c_void>(sched); - tls::set(key, void_sched); - } - } - - /// Take ownership of the Scheduler from thread-local storage - pub fn take() -> ~Scheduler { - unsafe { - let key = tls_key(); - let void_sched: *mut c_void = tls::get(key); - assert!(void_sched.is_not_null()); - let sched = transmute::<*mut c_void, ~Scheduler>(void_sched); - tls::set(key, mut_null()); - return sched; - } - } - - /// Give the Scheduler to thread-local storage for the duration of the block - pub fn install(sched: ~Scheduler, f: &fn()) -> ~Scheduler { - put(sched); - f(); - return take(); - } - - /// Borrow a mutable reference to the thread-local Scheduler - /// # Safety Note - /// Because this leaves the Scheduler in thread-local storage it is possible - /// For the Scheduler pointer to be aliased - pub fn borrow(f: &fn(&mut Scheduler)) { - unsafe { - let key = tls_key(); - let mut void_sched: *mut c_void = tls::get(key); - assert!(void_sched.is_not_null()); - { - let void_sched_ptr = &mut void_sched; - let sched: &mut ~Scheduler = { - transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) - }; - let sched: &mut Scheduler = &mut **sched; - f(sched); - } - } - } - - fn tls_key() -> tls::Key { - unsafe { - let key: *mut c_void = rust_get_sched_tls_key(); - let key: &mut tls::Key = transmute(key); - return *key; - } - } - - extern { - fn rust_get_sched_tls_key() -> *mut c_void; - } - - #[test] - fn thread_local_scheduler_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); - } - - #[test] - fn thread_local_scheduler_two_instances() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); - } - - #[test] - fn install_borrow_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - let _scheduler = do install(scheduler) { - do borrow |_sched| { - } - }; - } -} - #[test] fn test_simple_scheduling() { do run_in_bare_thread { From 3b8a354c21cec6204a268cfd1e2946744c28ed0e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 15:25:29 -0700 Subject: [PATCH 208/403] core::rt: A little bit of cleanup to thread-local scheduler --- src/libcore/rt/sched/local.rs | 17 ++++++----------- src/libcore/rt/sched/mod.rs | 16 +++++++--------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/libcore/rt/sched/local.rs b/src/libcore/rt/sched/local.rs index 1b1a003301768..020d581546aa1 100644 --- a/src/libcore/rt/sched/local.rs +++ b/src/libcore/rt/sched/local.rs @@ -39,18 +39,11 @@ pub fn take() -> ~Scheduler { } } -/// Give the Scheduler to thread-local storage for the duration of the block -pub fn install(sched: ~Scheduler, f: &fn()) -> ~Scheduler { - put(sched); - f(); - return take(); -} - /// Borrow a mutable reference to the thread-local Scheduler /// # Safety Note /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased -pub fn borrow(f: &fn(&mut Scheduler)) { +pub unsafe fn borrow(f: &fn(&mut Scheduler)) { unsafe { let key = tls_key(); let mut void_sched: *mut c_void = tls::get(key); @@ -96,11 +89,13 @@ fn thread_local_scheduler_two_instances() { } #[test] -fn install_borrow_smoke_test() { +fn borrow_smoke_test() { let scheduler = ~UvEventLoop::new_scheduler(); - let _scheduler = do install(scheduler) { + put(scheduler); + unsafe { do borrow |_sched| { } - }; + } + let _scheduler = take(); } diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index bc25023d05ff6..2cdaf9573fb04 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -93,7 +93,9 @@ pub impl Scheduler { assert!(!self.in_task_context()); // Give ownership of the scheduler (self) to the thread - do self.install |scheduler| { + local::put(self); + + do Scheduler::local |scheduler| { fn run_scheduler_once() { do Scheduler::local |scheduler| { if scheduler.resume_task_from_queue() { @@ -106,16 +108,12 @@ pub impl Scheduler { scheduler.event_loop.callback(run_scheduler_once); scheduler.event_loop.run(); } - } - fn install(~self, f: &fn(&mut Scheduler)) -> ~Scheduler { - do local::install(self) { - local::borrow(f) - } + return local::take(); } fn local(f: &fn(&mut Scheduler)) { - local::borrow(f) + unsafe { local::borrow(f) } } // * Scheduler-context operations @@ -206,7 +204,7 @@ pub impl Scheduler { } // We could be executing in a different thread now - do local::borrow |sched| { + do Scheduler::local |sched| { sched.run_cleanup_job(); } } @@ -230,7 +228,7 @@ pub impl Scheduler { } // We could be executing in a different thread now - do local::borrow |sched| { + do Scheduler::local |sched| { sched.run_cleanup_job(); } } From 473b4d19ad51529afb8f1391cf471a20053c781c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 15:32:43 -0700 Subject: [PATCH 209/403] core::rt: Rename Scheduler::local to Scheduler::unsafe_local --- src/libcore/rt/sched/mod.rs | 26 +++++++++++++++----------- src/libcore/rt/uvio.rs | 30 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 2cdaf9573fb04..82f0c3592c49b 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -95,9 +95,9 @@ pub impl Scheduler { // Give ownership of the scheduler (self) to the thread local::put(self); - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { fn run_scheduler_once() { - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { if scheduler.resume_task_from_queue() { // Ok, a task ran. Nice! We'll do it again later scheduler.event_loop.callback(run_scheduler_once); @@ -112,7 +112,11 @@ pub impl Scheduler { return local::take(); } - fn local(f: &fn(&mut Scheduler)) { + /// Get a mutable pointer to the thread-local scheduler. + /// # Safety Note + /// This allows other mutable aliases to the scheduler, both in the current + /// execution context and other execution contexts. + fn unsafe_local(f: &fn(&mut Scheduler)) { unsafe { local::borrow(f) } } @@ -204,7 +208,7 @@ pub impl Scheduler { } // We could be executing in a different thread now - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { sched.run_cleanup_job(); } } @@ -228,7 +232,7 @@ pub impl Scheduler { } // We could be executing in a different thread now - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { sched.run_cleanup_job(); } } @@ -327,13 +331,13 @@ pub impl Task { // This is the first code to execute after the initial // context switch to the task. The previous context may // have asked us to do some cleanup. - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { sched.run_cleanup_job(); } start(); - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { sched.terminate_current_task(); } }; @@ -394,7 +398,7 @@ fn test_swap_tasks() { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let task2 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } }; @@ -427,7 +431,7 @@ fn test_run_a_lot_of_tasks_queued() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -460,7 +464,7 @@ fn test_run_a_lot_of_tasks_direct() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -481,7 +485,7 @@ fn test_block_task() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { assert!(sched.in_task_context()); do sched.deschedule_running_task_and_then() |sched, task| { assert!(!sched.in_task_context()); diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 97c65b39f9c92..7dfc6fff4cdff 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -104,7 +104,7 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context @@ -131,7 +131,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(maybe_stream); } // Context switch - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { scheduler.resume_task_immediately(task_cell.take()); } } @@ -178,7 +178,7 @@ impl TcpListener for UvTcpListener { let server_tcp_watcher = self.watcher(); - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { assert!(scheduler.in_task_context()); do scheduler.deschedule_running_task_and_then |_, task| { @@ -201,7 +201,7 @@ impl TcpListener for UvTcpListener { rtdebug!("resuming task from listen"); // Context switch - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { scheduler.resume_task_immediately(task_cell.take()); } } @@ -243,7 +243,7 @@ impl Stream for UvStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; @@ -275,7 +275,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { scheduler.resume_task_immediately(task_cell.take()); } } @@ -289,7 +289,7 @@ impl Stream for UvStream { fn write(&mut self, buf: &[u8]) -> Result<(), ()> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; @@ -308,7 +308,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { scheduler.resume_task_immediately(task_cell.take()); } } @@ -326,7 +326,7 @@ fn test_simple_io_no_connect() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let addr = Ipv4(127, 0, 0, 1, 2926); let maybe_chan = io.connect(addr); @@ -346,7 +346,7 @@ fn test_simple_tcp_server_and_client() { let addr = Ipv4(127, 0, 0, 1, 2929); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let mut stream = io.connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -355,7 +355,7 @@ fn test_simple_tcp_server_and_client() { }; let server_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let mut listener = io.bind(addr).unwrap(); let mut stream = listener.listen().unwrap(); @@ -385,7 +385,7 @@ fn test_read_and_block() { let addr = Ipv4(127, 0, 0, 1, 2930); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let mut stream = io.connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -397,7 +397,7 @@ fn test_read_and_block() { }; let server_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let mut listener = io.bind(addr).unwrap(); let mut stream = listener.listen().unwrap(); @@ -416,7 +416,7 @@ fn test_read_and_block() { } reads += 1; - do Scheduler::local |scheduler| { + do Scheduler::unsafe_local |scheduler| { // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it @@ -448,7 +448,7 @@ fn test_read_read_read() { let addr = Ipv4(127, 0, 0, 1, 2931); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::local |sched| { + do Scheduler::unsafe_local |sched| { let io = sched.event_loop.io().unwrap(); let mut stream = io.connect(addr).unwrap(); let mut buf = [0, .. 2048]; From ebefe07792caf17c03c6f90fb1979d4e6c935001 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 16:00:15 -0700 Subject: [PATCH 210/403] core::rt: Make Scheduler::unsafe_local return a fabricated region pointer Instead of taking a closure. It's unsafe either way. Rename it to unsafe_local_borrow. --- src/libcore/rt/sched/local.rs | 7 +- src/libcore/rt/sched/mod.rs | 97 +++++---- src/libcore/rt/uvio.rs | 371 ++++++++++++++++------------------ 3 files changed, 228 insertions(+), 247 deletions(-) diff --git a/src/libcore/rt/sched/local.rs b/src/libcore/rt/sched/local.rs index 020d581546aa1..d800101111464 100644 --- a/src/libcore/rt/sched/local.rs +++ b/src/libcore/rt/sched/local.rs @@ -43,7 +43,7 @@ pub fn take() -> ~Scheduler { /// # Safety Note /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased -pub unsafe fn borrow(f: &fn(&mut Scheduler)) { +pub unsafe fn borrow() -> &mut Scheduler { unsafe { let key = tls_key(); let mut void_sched: *mut c_void = tls::get(key); @@ -54,7 +54,7 @@ pub unsafe fn borrow(f: &fn(&mut Scheduler)) { transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) }; let sched: &mut Scheduler = &mut **sched; - f(sched); + return sched; } } } @@ -93,8 +93,7 @@ fn borrow_smoke_test() { let scheduler = ~UvEventLoop::new_scheduler(); put(scheduler); unsafe { - do borrow |_sched| { - } + let _scheduler = borrow(); } let _scheduler = take(); } diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 82f0c3592c49b..a2a440ba76eae 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -95,20 +95,18 @@ pub impl Scheduler { // Give ownership of the scheduler (self) to the thread local::put(self); - do Scheduler::unsafe_local |scheduler| { - fn run_scheduler_once() { - do Scheduler::unsafe_local |scheduler| { - if scheduler.resume_task_from_queue() { - // Ok, a task ran. Nice! We'll do it again later - scheduler.event_loop.callback(run_scheduler_once); - } - } + let scheduler = Scheduler::unsafe_local_borrow(); + fn run_scheduler_once() { + let scheduler = Scheduler::unsafe_local_borrow(); + if scheduler.resume_task_from_queue() { + // Ok, a task ran. Nice! We'll do it again later + scheduler.event_loop.callback(run_scheduler_once); } - - scheduler.event_loop.callback(run_scheduler_once); - scheduler.event_loop.run(); } + scheduler.event_loop.callback(run_scheduler_once); + scheduler.event_loop.run(); + return local::take(); } @@ -116,8 +114,14 @@ pub impl Scheduler { /// # Safety Note /// This allows other mutable aliases to the scheduler, both in the current /// execution context and other execution contexts. - fn unsafe_local(f: &fn(&mut Scheduler)) { - unsafe { local::borrow(f) } + fn unsafe_local_borrow() -> &mut Scheduler { + unsafe { local::borrow() } + } + + fn local_borrow(f: &fn(&mut Scheduler)) { + let mut sched = local::take(); + f(sched); + local::put(sched); } // * Scheduler-context operations @@ -208,9 +212,8 @@ pub impl Scheduler { } // We could be executing in a different thread now - do Scheduler::unsafe_local |sched| { - sched.run_cleanup_job(); - } + let sched = Scheduler::unsafe_local_borrow(); + sched.run_cleanup_job(); } /// Switch directly to another task, without going through the scheduler. @@ -232,9 +235,8 @@ pub impl Scheduler { } // We could be executing in a different thread now - do Scheduler::unsafe_local |sched| { - sched.run_cleanup_job(); - } + let sched = Scheduler::unsafe_local_borrow(); + sched.run_cleanup_job(); } // * Other stuff @@ -331,15 +333,13 @@ pub impl Task { // This is the first code to execute after the initial // context switch to the task. The previous context may // have asked us to do some cleanup. - do Scheduler::unsafe_local |sched| { - sched.run_cleanup_job(); - } + let sched = Scheduler::unsafe_local_borrow(); + sched.run_cleanup_job(); start(); - do Scheduler::unsafe_local |sched| { - sched.terminate_current_task(); - } + let sched = Scheduler::unsafe_local_borrow(); + sched.terminate_current_task(); }; return wrapper; } @@ -398,13 +398,12 @@ fn test_swap_tasks() { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - do Scheduler::unsafe_local |sched| { - let task2 = ~do Task::new(&mut sched.stack_pool) { - unsafe { *count_ptr = *count_ptr + 1; } - }; - // Context switch directly to the new task - sched.resume_task_from_running_task_direct(task2); - } + let sched = Scheduler::unsafe_local_borrow(); + let task2 = ~do Task::new(&mut sched.stack_pool) { + unsafe { *count_ptr = *count_ptr + 1; } + }; + // Context switch directly to the new task + sched.resume_task_from_running_task_direct(task2); unsafe { *count_ptr = *count_ptr + 1; } }; sched.task_queue.push_back(task1); @@ -431,7 +430,7 @@ fn test_run_a_lot_of_tasks_queued() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::unsafe_local |sched| { + do Scheduler::local_borrow |sched| { let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -464,18 +463,17 @@ fn test_run_a_lot_of_tasks_direct() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::unsafe_local |sched| { - let task = ~do Task::new(&mut sched.stack_pool) { - unsafe { - *count_ptr = *count_ptr + 1; - if *count_ptr != MAX { - run_task(count_ptr); - } + let sched = Scheduler::unsafe_local_borrow(); + let task = ~do Task::new(&mut sched.stack_pool) { + unsafe { + *count_ptr = *count_ptr + 1; + if *count_ptr != MAX { + run_task(count_ptr); } - }; - // Context switch directly to the new task - sched.resume_task_from_running_task_direct(task); - } + } + }; + // Context switch directly to the new task + sched.resume_task_from_running_task_direct(task); }; } } @@ -485,12 +483,11 @@ fn test_block_task() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - assert!(sched.in_task_context()); - do sched.deschedule_running_task_and_then() |sched, task| { - assert!(!sched.in_task_context()); - sched.task_queue.push_back(task); - } + let sched = Scheduler::unsafe_local_borrow(); + assert!(sched.in_task_context()); + do sched.deschedule_running_task_and_then() |sched, task| { + assert!(!sched.in_task_context()); + sched.task_queue.push_back(task); } }; sched.task_queue.push_back(task); diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 7dfc6fff4cdff..a43ec07c2de11 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -104,37 +104,35 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::unsafe_local |scheduler| { - assert!(scheduler.in_task_context()); - - // Block this task and take ownership, switch to scheduler context - do scheduler.deschedule_running_task_and_then |scheduler, task| { - - rtdebug!("connect: entered scheduler context"); - assert!(!scheduler.in_task_context()); - let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); - let task_cell = Cell(task); - - // Wait for a connection - do tcp_watcher.connect(addr) |stream_watcher, status| { - rtdebug!("connect: in connect callback"); - let maybe_stream = if status.is_none() { - rtdebug!("status is none"); - Some(~UvStream(stream_watcher)) - } else { - rtdebug!("status is some"); - stream_watcher.close(||()); - None - }; - - // Store the stream in the task's stack - unsafe { (*result_cell_ptr).put_back(maybe_stream); } - - // Context switch - do Scheduler::unsafe_local |scheduler| { - scheduler.resume_task_immediately(task_cell.take()); - } - } + let scheduler = Scheduler::unsafe_local_borrow(); + assert!(scheduler.in_task_context()); + + // Block this task and take ownership, switch to scheduler context + do scheduler.deschedule_running_task_and_then |scheduler, task| { + + rtdebug!("connect: entered scheduler context"); + assert!(!scheduler.in_task_context()); + let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); + let task_cell = Cell(task); + + // Wait for a connection + do tcp_watcher.connect(addr) |stream_watcher, status| { + rtdebug!("connect: in connect callback"); + let maybe_stream = if status.is_none() { + rtdebug!("status is none"); + Some(~UvStream(stream_watcher)) + } else { + rtdebug!("status is some"); + stream_watcher.close(||()); + None + }; + + // Store the stream in the task's stack + unsafe { (*result_cell_ptr).put_back(maybe_stream); } + + // Context switch + let scheduler = Scheduler::unsafe_local_borrow(); + scheduler.resume_task_immediately(task_cell.take()); } } @@ -178,33 +176,31 @@ impl TcpListener for UvTcpListener { let server_tcp_watcher = self.watcher(); - do Scheduler::unsafe_local |scheduler| { - assert!(scheduler.in_task_context()); - - do scheduler.deschedule_running_task_and_then |_, task| { - let task_cell = Cell(task); - let mut server_tcp_watcher = server_tcp_watcher; - do server_tcp_watcher.listen |server_stream_watcher, status| { - let maybe_stream = if status.is_none() { - let mut server_stream_watcher = server_stream_watcher; - let mut loop_ = loop_from_watcher(&server_stream_watcher); - let mut client_tcp_watcher = TcpWatcher::new(&mut loop_); - let mut client_tcp_watcher = client_tcp_watcher.as_stream(); - // XXX: Need's to be surfaced in interface - server_stream_watcher.accept(client_tcp_watcher); - Some(~UvStream::new(client_tcp_watcher)) - } else { - None - }; - - unsafe { (*result_cell_ptr).put_back(maybe_stream); } - - rtdebug!("resuming task from listen"); - // Context switch - do Scheduler::unsafe_local |scheduler| { - scheduler.resume_task_immediately(task_cell.take()); - } - } + let scheduler = Scheduler::unsafe_local_borrow(); + assert!(scheduler.in_task_context()); + + do scheduler.deschedule_running_task_and_then |_, task| { + let task_cell = Cell(task); + let mut server_tcp_watcher = server_tcp_watcher; + do server_tcp_watcher.listen |server_stream_watcher, status| { + let maybe_stream = if status.is_none() { + let mut server_stream_watcher = server_stream_watcher; + let mut loop_ = loop_from_watcher(&server_stream_watcher); + let mut client_tcp_watcher = TcpWatcher::new(&mut loop_); + let mut client_tcp_watcher = client_tcp_watcher.as_stream(); + // XXX: Need's to be surfaced in interface + server_stream_watcher.accept(client_tcp_watcher); + Some(~UvStream::new(client_tcp_watcher)) + } else { + None + }; + + unsafe { (*result_cell_ptr).put_back(maybe_stream); } + + rtdebug!("resuming task from listen"); + // Context switch + let scheduler = Scheduler::unsafe_local_borrow(); + scheduler.resume_task_immediately(task_cell.take()); } } @@ -243,42 +239,40 @@ impl Stream for UvStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::unsafe_local |scheduler| { - assert!(scheduler.in_task_context()); - let watcher = self.watcher(); - let buf_ptr: *&mut [u8] = &buf; - do scheduler.deschedule_running_task_and_then |scheduler, task| { - rtdebug!("read: entered scheduler context"); - assert!(!scheduler.in_task_context()); + let scheduler = Scheduler::unsafe_local_borrow(); + assert!(scheduler.in_task_context()); + let watcher = self.watcher(); + let buf_ptr: *&mut [u8] = &buf; + do scheduler.deschedule_running_task_and_then |scheduler, task| { + rtdebug!("read: entered scheduler context"); + assert!(!scheduler.in_task_context()); + let mut watcher = watcher; + let task_cell = Cell(task); + // XXX: We shouldn't reallocate these callbacks every + // call to read + let alloc: AllocCallback = |_| unsafe { + slice_to_uv_buf(*buf_ptr) + }; + do watcher.read_start(alloc) |watcher, nread, _buf, status| { + + // Stop reading so that no read callbacks are + // triggered before the user calls `read` again. + // XXX: Is there a performance impact to calling + // stop here? let mut watcher = watcher; - let task_cell = Cell(task); - // XXX: We shouldn't reallocate these callbacks every - // call to read - let alloc: AllocCallback = |_| unsafe { - slice_to_uv_buf(*buf_ptr) + watcher.read_stop(); + + let result = if status.is_none() { + assert!(nread >= 0); + Ok(nread as uint) + } else { + Err(()) }; - do watcher.read_start(alloc) |watcher, nread, _buf, status| { - - // Stop reading so that no read callbacks are - // triggered before the user calls `read` again. - // XXX: Is there a performance impact to calling - // stop here? - let mut watcher = watcher; - watcher.read_stop(); - - let result = if status.is_none() { - assert!(nread >= 0); - Ok(nread as uint) - } else { - Err(()) - }; - - unsafe { (*result_cell_ptr).put_back(result); } - - do Scheduler::unsafe_local |scheduler| { - scheduler.resume_task_immediately(task_cell.take()); - } - } + + unsafe { (*result_cell_ptr).put_back(result); } + + let scheduler = Scheduler::unsafe_local_borrow(); + scheduler.resume_task_immediately(task_cell.take()); } } @@ -289,29 +283,27 @@ impl Stream for UvStream { fn write(&mut self, buf: &[u8]) -> Result<(), ()> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - do Scheduler::unsafe_local |scheduler| { - assert!(scheduler.in_task_context()); - let watcher = self.watcher(); - let buf_ptr: *&[u8] = &buf; - do scheduler.deschedule_running_task_and_then |_, task| { - let mut watcher = watcher; - let task_cell = Cell(task); - let buf = unsafe { &*buf_ptr }; - // XXX: OMGCOPIES - let buf = buf.to_vec(); - do watcher.write(buf) |_watcher, status| { - let result = if status.is_none() { - Ok(()) - } else { - Err(()) - }; - - unsafe { (*result_cell_ptr).put_back(result); } - - do Scheduler::unsafe_local |scheduler| { - scheduler.resume_task_immediately(task_cell.take()); - } - } + let scheduler = Scheduler::unsafe_local_borrow(); + assert!(scheduler.in_task_context()); + let watcher = self.watcher(); + let buf_ptr: *&[u8] = &buf; + do scheduler.deschedule_running_task_and_then |_, task| { + let mut watcher = watcher; + let task_cell = Cell(task); + let buf = unsafe { &*buf_ptr }; + // XXX: OMGCOPIES + let buf = buf.to_vec(); + do watcher.write(buf) |_watcher, status| { + let result = if status.is_none() { + Ok(()) + } else { + Err(()) + }; + + unsafe { (*result_cell_ptr).put_back(result); } + + let scheduler = Scheduler::unsafe_local_borrow(); + scheduler.resume_task_immediately(task_cell.take()); } } @@ -326,12 +318,11 @@ fn test_simple_io_no_connect() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let addr = Ipv4(127, 0, 0, 1, 2926); - let maybe_chan = io.connect(addr); - assert!(maybe_chan.is_none()); - } + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let addr = Ipv4(127, 0, 0, 1, 2926); + let maybe_chan = io.connect(addr); + assert!(maybe_chan.is_none()); }; sched.task_queue.push_back(task); sched.run(); @@ -346,29 +337,27 @@ fn test_simple_tcp_server_and_client() { let addr = Ipv4(127, 0, 0, 1, 2929); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let mut stream = io.connect(addr).unwrap(); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.close(); - } + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let mut stream = io.connect(addr).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.close(); }; let server_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let mut listener = io.bind(addr).unwrap(); - let mut stream = listener.listen().unwrap(); - let mut buf = [0, .. 2048]; - let nread = stream.read(buf).unwrap(); - assert!(nread == 8); - for uint::range(0, nread) |i| { - rtdebug!("%u", buf[i] as uint); - assert!(buf[i] == i as u8); - } - stream.close(); - listener.close(); + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let mut listener = io.bind(addr).unwrap(); + let mut stream = listener.listen().unwrap(); + let mut buf = [0, .. 2048]; + let nread = stream.read(buf).unwrap(); + assert!(nread == 8); + for uint::range(0, nread) |i| { + rtdebug!("%u", buf[i] as uint); + assert!(buf[i] == i as u8); } + stream.close(); + listener.close(); }; // Start the server first so it listens before the client connects @@ -385,53 +374,50 @@ fn test_read_and_block() { let addr = Ipv4(127, 0, 0, 1, 2930); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let mut stream = io.connect(addr).unwrap(); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.close(); - } + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let mut stream = io.connect(addr).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.close(); }; let server_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let mut listener = io.bind(addr).unwrap(); - let mut stream = listener.listen().unwrap(); - let mut buf = [0, .. 2048]; - - let expected = 32; - let mut current = 0; - let mut reads = 0; - - while current < expected { - let nread = stream.read(buf).unwrap(); - for uint::range(0, nread) |i| { - let val = buf[i] as uint; - assert!(val == current % 8); - current += 1; - } - reads += 1; - - do Scheduler::unsafe_local |scheduler| { - // Yield to the other task in hopes that it - // will trigger a read callback while we are - // not ready for it - do scheduler.deschedule_running_task_and_then |scheduler, task| { - scheduler.task_queue.push_back(task); - } - } - } + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let mut listener = io.bind(addr).unwrap(); + let mut stream = listener.listen().unwrap(); + let mut buf = [0, .. 2048]; - // Make sure we had multiple reads - assert!(reads > 1); + let expected = 32; + let mut current = 0; + let mut reads = 0; - stream.close(); - listener.close(); + while current < expected { + let nread = stream.read(buf).unwrap(); + for uint::range(0, nread) |i| { + let val = buf[i] as uint; + assert!(val == current % 8); + current += 1; + } + reads += 1; + + let scheduler = Scheduler::unsafe_local_borrow(); + // Yield to the other task in hopes that it + // will trigger a read callback while we are + // not ready for it + do scheduler.deschedule_running_task_and_then |scheduler, task| { + scheduler.task_queue.push_back(task); + } } + + // Make sure we had multiple reads + assert!(reads > 1); + + stream.close(); + listener.close(); }; // Start the server first so it listens before the client connects @@ -448,19 +434,18 @@ fn test_read_read_read() { let addr = Ipv4(127, 0, 0, 1, 2931); let client_task = ~do Task::new(&mut sched.stack_pool) { - do Scheduler::unsafe_local |sched| { - let io = sched.event_loop.io().unwrap(); - let mut stream = io.connect(addr).unwrap(); - let mut buf = [0, .. 2048]; - let mut total_bytes_read = 0; - while total_bytes_read < 500000000 { - let nread = stream.read(buf).unwrap(); - rtdebug!("read %u bytes", nread as uint); - total_bytes_read += nread; - } - rtdebug_!("read %u bytes total", total_bytes_read as uint); - stream.close(); + let sched = Scheduler::unsafe_local_borrow(); + let io = sched.event_loop.io().unwrap(); + let mut stream = io.connect(addr).unwrap(); + let mut buf = [0, .. 2048]; + let mut total_bytes_read = 0; + while total_bytes_read < 500000000 { + let nread = stream.read(buf).unwrap(); + rtdebug!("read %u bytes", nread as uint); + total_bytes_read += nread; } + rtdebug_!("read %u bytes total", total_bytes_read as uint); + stream.close(); }; sched.task_queue.push_back(client_task); From 0ef3e1eb25858297581f639d7095730adb28648d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Apr 2013 16:26:16 -0700 Subject: [PATCH 211/403] Update AUTHORS.txt w/ Brett Cannon, Diggory Hardy, Jack Moffitt, James Miller --- AUTHORS.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index ae583d6409e23..2f80341e21a06 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -31,6 +31,7 @@ Bilal Husain Bill Fallon Brendan Eich Brendan Zabarauskas +Brett Cannon Brian Anderson Brian J. Burg Brian Leibig @@ -50,6 +51,7 @@ Dave Herman David Forsythe David Klein David Rajchenbach-Teller +Diggory Hardy Dimitri Krassovski Donovan Preston Drew Willcoxon @@ -76,9 +78,11 @@ Ian D. Bollinger Ilyong Cho Isaac Aggrey Ivano Coppola +Jack Moffitt Jacob Harris Cryer Kragh Jacob Parker Jakub Wieczorek +James Miller Jason Orendorff Jed Davis Jeff Balogh From d3be98e9f5e721b53dccd0a43c2ff58ddd32ac47 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 16 Apr 2013 01:08:52 +1000 Subject: [PATCH 212/403] libcore,std,syntax,rustc: move tests into `mod tests`, make them private (no pub mod or pub fn). --- src/libcore/at_vec.rs | 71 +++--- src/libcore/cast.rs | 10 +- src/libcore/comm.rs | 6 +- src/libcore/hash.rs | 310 ++++++++++++------------ src/libcore/hashmap.rs | 28 +-- src/libcore/num/float.rs | 395 ++++++++++++++++--------------- src/libcore/num/int-template.rs | 317 +++++++++++++------------ src/libcore/num/uint-template.rs | 316 +++++++++++++------------ src/libcore/pipes.rs | 6 +- src/libcore/ptr.rs | 202 ++++++++-------- src/libcore/rand.rs | 40 ++-- src/libcore/run.rs | 16 +- src/libcore/sys.rs | 18 +- src/libcore/task/mod.rs | 2 +- src/libcore/unstable.rs | 6 +- src/librustc/back/rpath.rs | 34 +-- src/librustc/driver/driver.rs | 6 +- src/librustc/driver/session.rs | 20 +- src/libstd/arc.rs | 24 +- src/libstd/base64.rs | 4 +- src/libstd/bitv.rs | 64 ++--- src/libstd/dlist.rs | 76 +++--- src/libstd/future.rs | 18 +- src/libstd/getopts.rs | 104 ++++---- src/libstd/list.rs | 20 +- src/libstd/net_tcp.rs | 8 +- src/libstd/net_url.rs | 46 ++-- src/libstd/sha1.rs | 2 +- src/libstd/sort.rs | 18 +- src/libstd/sync.rs | 72 +++--- src/libstd/test.rs | 8 +- src/libstd/time.rs | 22 +- src/libstd/timer.rs | 10 +- src/libstd/uv_ll.rs | 12 +- src/libsyntax/parse/lexer.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/util/interner.rs | 80 ++++--- 37 files changed, 1211 insertions(+), 1184 deletions(-) diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 38a663dc24504..337b0722ce7ab 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -277,45 +277,48 @@ pub mod raw { pub unsafe fn reserve_at_least(v: &mut @[T], n: uint) { reserve(v, uint::next_power_of_two(n)); } - } -#[test] -pub fn test() { - // Some code that could use that, then: - fn seq_range(lo: uint, hi: uint) -> @[uint] { - do build |push| { - for uint::range(lo, hi) |i| { - push(i); +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test() { + // Some code that could use that, then: + fn seq_range(lo: uint, hi: uint) -> @[uint] { + do build |push| { + for uint::range(lo, hi) |i| { + push(i); + } } } - } - assert_eq!(seq_range(10, 15), @[10, 11, 12, 13, 14]); - assert!(from_fn(5, |x| x+1) == @[1, 2, 3, 4, 5]); - assert!(from_elem(5, 3.14) == @[3.14, 3.14, 3.14, 3.14, 3.14]); -} - -#[test] -pub fn append_test() { - assert!(@[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6]); -} + assert_eq!(seq_range(10, 15), @[10, 11, 12, 13, 14]); + assert!(from_fn(5, |x| x+1) == @[1, 2, 3, 4, 5]); + assert!(from_elem(5, 3.14) == @[3.14, 3.14, 3.14, 3.14, 3.14]); + } -#[test] -pub fn test_from_owned() { - assert!(from_owned::(~[]) == @[]); - assert!(from_owned(~[true]) == @[true]); - assert!(from_owned(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); - assert!(from_owned(~[~"abc", ~"123"]) == @[~"abc", ~"123"]); - assert!(from_owned(~[~[42]]) == @[~[42]]); -} + #[test] + fn append_test() { + assert!(@[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6]); + } -#[test] -pub fn test_from_slice() { - assert!(from_slice::([]) == @[]); - assert!(from_slice([true]) == @[true]); - assert!(from_slice([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); - assert!(from_slice([@"abc", @"123"]) == @[@"abc", @"123"]); - assert!(from_slice([@[42]]) == @[@[42]]); -} + #[test] + fn test_from_owned() { + assert!(from_owned::(~[]) == @[]); + assert!(from_owned(~[true]) == @[true]); + assert!(from_owned(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); + assert!(from_owned(~[~"abc", ~"123"]) == @[~"abc", ~"123"]); + assert!(from_owned(~[~[42]]) == @[~[42]]); + } + #[test] + fn test_from_slice() { + assert!(from_slice::([]) == @[]); + assert!(from_slice([true]) == @[true]); + assert!(from_slice([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); + assert!(from_slice([@"abc", @"123"]) == @[@"abc", @"123"]); + assert!(from_slice([@[42]]) == @[@[42]]); + } +} \ No newline at end of file diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs index 42464c848efb3..1d214f402f5ac 100644 --- a/src/libcore/cast.rs +++ b/src/libcore/cast.rs @@ -111,16 +111,16 @@ pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T { ****************************************************************************/ #[cfg(test)] -pub mod tests { +mod tests { use cast::{bump_box_refcount, reinterpret_cast, transmute}; #[test] - pub fn test_reinterpret_cast() { + fn test_reinterpret_cast() { assert!(1u == unsafe { reinterpret_cast(&1) }); } #[test] - pub fn test_bump_box_refcount() { + fn test_bump_box_refcount() { unsafe { let box = @~"box box box"; // refcount 1 bump_box_refcount(box); // refcount 2 @@ -135,7 +135,7 @@ pub mod tests { } #[test] - pub fn test_transmute() { + fn test_transmute() { use managed::raw::BoxRepr; unsafe { let x = @100u8; @@ -146,7 +146,7 @@ pub mod tests { } #[test] - pub fn test_transmute2() { + fn test_transmute2() { unsafe { assert!(~[76u8, 0u8] == transmute(~"L")); } diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index d665bf311f362..f8b046e5b8c4f 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -426,12 +426,12 @@ pub fn try_send_one(chan: ChanOne, data: T) } #[cfg(test)] -pub mod test { +mod test { use either::Right; use super::{Chan, Port, oneshot, recv_one, stream}; #[test] - pub fn test_select2() { + fn test_select2() { let (p1, c1) = stream(); let (p2, c2) = stream(); @@ -446,7 +446,7 @@ pub mod test { } #[test] - pub fn test_oneshot() { + fn test_oneshot() { let (c, p) = oneshot::init(); oneshot::client::send(c, ()); diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index c229bc17311c9..ba1f8cebdb01c 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -357,170 +357,176 @@ impl Streaming for SipState { } } -#[test] -pub fn test_siphash() { - let vecs : [[u8, ..8], ..64] = [ - [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], - [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], - [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], - [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], - [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], - [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], - [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], - [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], - [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], - [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], - [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], - [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], - [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], - [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], - [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], - [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], - [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], - [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], - [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], - [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], - [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], - [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], - [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], - [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], - [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], - [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], - [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], - [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], - [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], - [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], - [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], - [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], - [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], - [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], - [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], - [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], - [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], - [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], - [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], - [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], - [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], - [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], - [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], - [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], - [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], - [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], - [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], - [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], - [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], - [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], - [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], - [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], - [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], - [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], - [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], - [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], - [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], - [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], - [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], - [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], - [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], - [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], - [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], - [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] - ]; - - let k0 = 0x_07_06_05_04_03_02_01_00_u64; - let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; - let mut buf : ~[u8] = ~[]; - let mut t = 0; - let stream_inc = &State(k0,k1); - let stream_full = &State(k0,k1); - - fn to_hex_str(r: &[u8, ..8]) -> ~str { - let mut s = ~""; - for vec::each(*r) |b| { - s += uint::to_str_radix(*b as uint, 16u); +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + #[test] + fn test_siphash() { + let vecs : [[u8, ..8], ..64] = [ + [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], + [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], + [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], + [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], + [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], + [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], + [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], + [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], + [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], + [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], + [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], + [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], + [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], + [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], + [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], + [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], + [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], + [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], + [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], + [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], + [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], + [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], + [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], + [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], + [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], + [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], + [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], + [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], + [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], + [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], + [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], + [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], + [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], + [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], + [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], + [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], + [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], + [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], + [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], + [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], + [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], + [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], + [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], + [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], + [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], + [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], + [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], + [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], + [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], + [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], + [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], + [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], + [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], + [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], + [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], + [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], + [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], + [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], + [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], + [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], + [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], + [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], + [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], + [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] + ]; + + let k0 = 0x_07_06_05_04_03_02_01_00_u64; + let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; + let mut buf : ~[u8] = ~[]; + let mut t = 0; + let stream_inc = &State(k0,k1); + let stream_full = &State(k0,k1); + + fn to_hex_str(r: &[u8, ..8]) -> ~str { + let mut s = ~""; + for vec::each(*r) |b| { + s += uint::to_str_radix(*b as uint, 16u); + } + s } - s - } - while t < 64 { - debug!("siphash test %?", t); - let vec = u8to64_le!(vecs[t], 0); - let out = buf.hash_keyed(k0, k1); - debug!("got %?, expected %?", out, vec); - assert!(vec == out); + while t < 64 { + debug!("siphash test %?", t); + let vec = u8to64_le!(vecs[t], 0); + let out = buf.hash_keyed(k0, k1); + debug!("got %?, expected %?", out, vec); + assert!(vec == out); - stream_full.reset(); - stream_full.input(buf); - let f = stream_full.result_str(); - let i = stream_inc.result_str(); - let v = to_hex_str(&vecs[t]); - debug!("%d: (%s) => inc=%s full=%s", t, v, i, f); + stream_full.reset(); + stream_full.input(buf); + let f = stream_full.result_str(); + let i = stream_inc.result_str(); + let v = to_hex_str(&vecs[t]); + debug!("%d: (%s) => inc=%s full=%s", t, v, i, f); - assert!(f == i && f == v); + assert!(f == i && f == v); - buf += ~[t as u8]; - stream_inc.input(~[t as u8]); + buf += ~[t as u8]; + stream_inc.input(~[t as u8]); - t += 1; + t += 1; + } } -} -#[test] #[cfg(target_arch = "arm")] -pub fn test_hash_uint() { - let val = 0xdeadbeef_deadbeef_u64; - assert!((val as u64).hash() != (val as uint).hash()); - assert!((val as u32).hash() == (val as uint).hash()); -} -#[test] #[cfg(target_arch = "x86_64")] -pub fn test_hash_uint() { - let val = 0xdeadbeef_deadbeef_u64; - assert!((val as u64).hash() == (val as uint).hash()); - assert!((val as u32).hash() != (val as uint).hash()); -} -#[test] #[cfg(target_arch = "x86")] -pub fn test_hash_uint() { - let val = 0xdeadbeef_deadbeef_u64; - assert!((val as u64).hash() != (val as uint).hash()); - assert!((val as u32).hash() == (val as uint).hash()); -} + #[test] #[cfg(target_arch = "arm")] + fn test_hash_uint() { + let val = 0xdeadbeef_deadbeef_u64; + assert!((val as u64).hash() != (val as uint).hash()); + assert!((val as u32).hash() == (val as uint).hash()); + } + #[test] #[cfg(target_arch = "x86_64")] + fn test_hash_uint() { + let val = 0xdeadbeef_deadbeef_u64; + assert!((val as u64).hash() == (val as uint).hash()); + assert!((val as u32).hash() != (val as uint).hash()); + } + #[test] #[cfg(target_arch = "x86")] + fn test_hash_uint() { + let val = 0xdeadbeef_deadbeef_u64; + assert!((val as u64).hash() != (val as uint).hash()); + assert!((val as u32).hash() == (val as uint).hash()); + } -#[test] -pub fn test_hash_idempotent() { - let val64 = 0xdeadbeef_deadbeef_u64; - val64.hash() == val64.hash(); - let val32 = 0xdeadbeef_u32; - val32.hash() == val32.hash(); -} + #[test] + fn test_hash_idempotent() { + let val64 = 0xdeadbeef_deadbeef_u64; + val64.hash() == val64.hash(); + let val32 = 0xdeadbeef_u32; + val32.hash() == val32.hash(); + } -#[test] -pub fn test_hash_no_bytes_dropped_64() { - let val = 0xdeadbeef_deadbeef_u64; - - assert!(val.hash() != zero_byte(val, 0).hash()); - assert!(val.hash() != zero_byte(val, 1).hash()); - assert!(val.hash() != zero_byte(val, 2).hash()); - assert!(val.hash() != zero_byte(val, 3).hash()); - assert!(val.hash() != zero_byte(val, 4).hash()); - assert!(val.hash() != zero_byte(val, 5).hash()); - assert!(val.hash() != zero_byte(val, 6).hash()); - assert!(val.hash() != zero_byte(val, 7).hash()); - - fn zero_byte(val: u64, byte: uint) -> u64 { - assert!(byte < 8); - val & !(0xff << (byte * 8)) + #[test] + fn test_hash_no_bytes_dropped_64() { + let val = 0xdeadbeef_deadbeef_u64; + + assert!(val.hash() != zero_byte(val, 0).hash()); + assert!(val.hash() != zero_byte(val, 1).hash()); + assert!(val.hash() != zero_byte(val, 2).hash()); + assert!(val.hash() != zero_byte(val, 3).hash()); + assert!(val.hash() != zero_byte(val, 4).hash()); + assert!(val.hash() != zero_byte(val, 5).hash()); + assert!(val.hash() != zero_byte(val, 6).hash()); + assert!(val.hash() != zero_byte(val, 7).hash()); + + fn zero_byte(val: u64, byte: uint) -> u64 { + assert!(byte < 8); + val & !(0xff << (byte * 8)) + } } -} -#[test] -pub fn test_hash_no_bytes_dropped_32() { - let val = 0xdeadbeef_u32; + #[test] + fn test_hash_no_bytes_dropped_32() { + let val = 0xdeadbeef_u32; - assert!(val.hash() != zero_byte(val, 0).hash()); - assert!(val.hash() != zero_byte(val, 1).hash()); - assert!(val.hash() != zero_byte(val, 2).hash()); - assert!(val.hash() != zero_byte(val, 3).hash()); + assert!(val.hash() != zero_byte(val, 0).hash()); + assert!(val.hash() != zero_byte(val, 1).hash()); + assert!(val.hash() != zero_byte(val, 2).hash()); + assert!(val.hash() != zero_byte(val, 3).hash()); - fn zero_byte(val: u32, byte: uint) -> u32 { - assert!(byte < 4); - val & !(0xff << (byte * 8)) + fn zero_byte(val: u32, byte: uint) -> u32 { + assert!(byte < 4); + val & !(0xff << (byte * 8)) + } } -} +} \ No newline at end of file diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 2869c198ca2fc..3efe21fc42cdb 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -847,7 +847,7 @@ mod test_map { use uint; #[test] - pub fn test_insert() { + fn test_insert() { let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(m.insert(2, 4)); @@ -869,7 +869,7 @@ mod test_map { } #[test] - pub fn test_insert_overwrite() { + fn test_insert_overwrite() { let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(*m.get(&1) == 2); @@ -878,7 +878,7 @@ mod test_map { } #[test] - pub fn test_insert_conflicts() { + fn test_insert_conflicts() { let mut m = linear_map_with_capacity(4); assert!(m.insert(1, 2)); assert!(m.insert(5, 3)); @@ -889,7 +889,7 @@ mod test_map { } #[test] - pub fn test_conflict_remove() { + fn test_conflict_remove() { let mut m = linear_map_with_capacity(4); assert!(m.insert(1, 2)); assert!(m.insert(5, 3)); @@ -900,7 +900,7 @@ mod test_map { } #[test] - pub fn test_is_empty() { + fn test_is_empty() { let mut m = linear_map_with_capacity(4); assert!(m.insert(1, 2)); assert!(!m.is_empty()); @@ -909,7 +909,7 @@ mod test_map { } #[test] - pub fn test_pop() { + fn test_pop() { let mut m = HashMap::new(); m.insert(1, 2); assert!(m.pop(&1) == Some(2)); @@ -917,7 +917,7 @@ mod test_map { } #[test] - pub fn test_swap() { + fn test_swap() { let mut m = HashMap::new(); assert!(m.swap(1, 2) == None); assert!(m.swap(1, 3) == Some(2)); @@ -925,21 +925,21 @@ mod test_map { } #[test] - pub fn test_find_or_insert() { + fn test_find_or_insert() { let mut m = HashMap::new::(); assert!(m.find_or_insert(1, 2) == &2); assert!(m.find_or_insert(1, 3) == &2); } #[test] - pub fn test_find_or_insert_with() { + fn test_find_or_insert_with() { let mut m = HashMap::new::(); assert!(m.find_or_insert_with(1, |_| 2) == &2); assert!(m.find_or_insert_with(1, |_| 3) == &2); } #[test] - pub fn test_consume() { + fn test_consume() { let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(m.insert(2, 3)); @@ -954,7 +954,7 @@ mod test_map { } #[test] - pub fn test_iterate() { + fn test_iterate() { let mut m = linear_map_with_capacity(4); for uint::range(0, 32) |i| { assert!(m.insert(i, i*2)); @@ -968,7 +968,7 @@ mod test_map { } #[test] - pub fn test_find() { + fn test_find() { let mut m = HashMap::new(); assert!(m.find(&1).is_none()); m.insert(1, 2); @@ -979,7 +979,7 @@ mod test_map { } #[test] - pub fn test_eq() { + fn test_eq() { let mut m1 = HashMap::new(); m1.insert(1, 2); m1.insert(2, 3); @@ -997,7 +997,7 @@ mod test_map { } #[test] - pub fn test_expand() { + fn test_expand() { let mut m = HashMap::new(); assert!(m.len() == 0); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 87d04b05087c2..488756787b5cd 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -29,7 +29,6 @@ use from_str; #[cfg(notest)] use cmp::{Eq, Ord}; #[cfg(notest)] use ops; -#[cfg(test)] use option::{Some, None}; pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt}; pub use f64::logarithm; @@ -142,7 +141,7 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, radix, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ - try to_str_radix_special() if those are expected") } + try to_str_radix_special() if those are expected") } r } @@ -177,12 +176,6 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str { r } -#[test] -pub fn test_to_str_exact_do_decimal() { - let s = to_str_exact(5.0, 4u); - assert!(s == ~"5.0000"); -} - /** * Converts a float to a string with a maximum number of * significant digits @@ -474,195 +467,205 @@ impl ops::Neg for float { fn neg(&self) -> float { -*self } } -#[test] -pub fn test_from_str() { - assert!(from_str(~"3") == Some(3.)); - assert!(from_str(~"3.14") == Some(3.14)); - assert!(from_str(~"+3.14") == Some(3.14)); - assert!(from_str(~"-3.14") == Some(-3.14)); - assert!(from_str(~"2.5E10") == Some(25000000000.)); - assert!(from_str(~"2.5e10") == Some(25000000000.)); - assert!(from_str(~"25000000000.E-10") == Some(2.5)); - assert!(from_str(~".") == Some(0.)); - assert!(from_str(~".e1") == Some(0.)); - assert!(from_str(~".e-1") == Some(0.)); - assert!(from_str(~"5.") == Some(5.)); - assert!(from_str(~".5") == Some(0.5)); - assert!(from_str(~"0.5") == Some(0.5)); - assert!(from_str(~"-.5") == Some(-0.5)); - assert!(from_str(~"-5") == Some(-5.)); - assert!(from_str(~"inf") == Some(infinity)); - assert!(from_str(~"+inf") == Some(infinity)); - assert!(from_str(~"-inf") == Some(neg_infinity)); - // note: NaN != NaN, hence this slightly complex test - match from_str(~"NaN") { - Some(f) => assert!(is_NaN(f)), - None => fail!() - } - // note: -0 == 0, hence these slightly more complex tests - match from_str(~"-0") { - Some(v) if is_zero(v) => assert!(is_negative(v)), - _ => fail!() - } - match from_str(~"0") { - Some(v) if is_zero(v) => assert!(is_positive(v)), - _ => fail!() - } - - assert!(from_str(~"").is_none()); - assert!(from_str(~"x").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~"e").is_none()); - assert!(from_str(~"E").is_none()); - assert!(from_str(~"E1").is_none()); - assert!(from_str(~"1e1e1").is_none()); - assert!(from_str(~"1e1.1").is_none()); - assert!(from_str(~"1e1-1").is_none()); -} - -#[test] -pub fn test_from_str_hex() { - assert!(from_str_hex(~"a4") == Some(164.)); - assert!(from_str_hex(~"a4.fe") == Some(164.9921875)); - assert!(from_str_hex(~"-a4.fe") == Some(-164.9921875)); - assert!(from_str_hex(~"+a4.fe") == Some(164.9921875)); - assert!(from_str_hex(~"ff0P4") == Some(0xff00 as float)); - assert!(from_str_hex(~"ff0p4") == Some(0xff00 as float)); - assert!(from_str_hex(~"ff0p-4") == Some(0xff as float)); - assert!(from_str_hex(~".") == Some(0.)); - assert!(from_str_hex(~".p1") == Some(0.)); - assert!(from_str_hex(~".p-1") == Some(0.)); - assert!(from_str_hex(~"f.") == Some(15.)); - assert!(from_str_hex(~".f") == Some(0.9375)); - assert!(from_str_hex(~"0.f") == Some(0.9375)); - assert!(from_str_hex(~"-.f") == Some(-0.9375)); - assert!(from_str_hex(~"-f") == Some(-15.)); - assert!(from_str_hex(~"inf") == Some(infinity)); - assert!(from_str_hex(~"+inf") == Some(infinity)); - assert!(from_str_hex(~"-inf") == Some(neg_infinity)); - // note: NaN != NaN, hence this slightly complex test - match from_str_hex(~"NaN") { - Some(f) => assert!(is_NaN(f)), - None => fail!() - } - // note: -0 == 0, hence these slightly more complex tests - match from_str_hex(~"-0") { - Some(v) if is_zero(v) => assert!(is_negative(v)), - _ => fail!() - } - match from_str_hex(~"0") { - Some(v) if is_zero(v) => assert!(is_positive(v)), - _ => fail!() - } - assert!(from_str_hex(~"e") == Some(14.)); - assert!(from_str_hex(~"E") == Some(14.)); - assert!(from_str_hex(~"E1") == Some(225.)); - assert!(from_str_hex(~"1e1e1") == Some(123361.)); - assert!(from_str_hex(~"1e1.1") == Some(481.0625)); - - assert!(from_str_hex(~"").is_none()); - assert!(from_str_hex(~"x").is_none()); - assert!(from_str_hex(~" ").is_none()); - assert!(from_str_hex(~" ").is_none()); - assert!(from_str_hex(~"p").is_none()); - assert!(from_str_hex(~"P").is_none()); - assert!(from_str_hex(~"P1").is_none()); - assert!(from_str_hex(~"1p1p1").is_none()); - assert!(from_str_hex(~"1p1.1").is_none()); - assert!(from_str_hex(~"1p1-1").is_none()); -} - -#[test] -pub fn test_to_str_hex() { - assert!(to_str_hex(164.) == ~"a4"); - assert!(to_str_hex(164.9921875) == ~"a4.fe"); - assert!(to_str_hex(-164.9921875) == ~"-a4.fe"); - assert!(to_str_hex(0xff00 as float) == ~"ff00"); - assert!(to_str_hex(-(0xff00 as float)) == ~"-ff00"); - assert!(to_str_hex(0.) == ~"0"); - assert!(to_str_hex(15.) == ~"f"); - assert!(to_str_hex(-15.) == ~"-f"); - assert!(to_str_hex(0.9375) == ~"0.f"); - assert!(to_str_hex(-0.9375) == ~"-0.f"); - assert!(to_str_hex(infinity) == ~"inf"); - assert!(to_str_hex(neg_infinity) == ~"-inf"); - assert!(to_str_hex(NaN) == ~"NaN"); - assert!(to_str_hex(0.) == ~"0"); - assert!(to_str_hex(-0.) == ~"-0"); -} - -#[test] -pub fn test_to_str_radix() { - assert!(to_str_radix(36., 36u) == ~"10"); - assert!(to_str_radix(8.125, 2u) == ~"1000.001"); -} - -#[test] -pub fn test_from_str_radix() { - assert!(from_str_radix(~"10", 36u) == Some(36.)); - assert!(from_str_radix(~"1000.001", 2u) == Some(8.125)); -} - -#[test] -pub fn test_positive() { - assert!((is_positive(infinity))); - assert!((is_positive(1.))); - assert!((is_positive(0.))); - assert!((!is_positive(-1.))); - assert!((!is_positive(neg_infinity))); - assert!((!is_positive(1./neg_infinity))); - assert!((!is_positive(NaN))); -} - -#[test] -pub fn test_negative() { - assert!((!is_negative(infinity))); - assert!((!is_negative(1.))); - assert!((!is_negative(0.))); - assert!((is_negative(-1.))); - assert!((is_negative(neg_infinity))); - assert!((is_negative(1./neg_infinity))); - assert!((!is_negative(NaN))); -} - -#[test] -pub fn test_nonpositive() { - assert!((!is_nonpositive(infinity))); - assert!((!is_nonpositive(1.))); - assert!((!is_nonpositive(0.))); - assert!((is_nonpositive(-1.))); - assert!((is_nonpositive(neg_infinity))); - assert!((is_nonpositive(1./neg_infinity))); - assert!((!is_nonpositive(NaN))); -} - -#[test] -pub fn test_nonnegative() { - assert!((is_nonnegative(infinity))); - assert!((is_nonnegative(1.))); - assert!((is_nonnegative(0.))); - assert!((!is_nonnegative(-1.))); - assert!((!is_nonnegative(neg_infinity))); - assert!((!is_nonnegative(1./neg_infinity))); - assert!((!is_nonnegative(NaN))); -} - -#[test] -pub fn test_to_str_inf() { - assert!(to_str_digits(infinity, 10u) == ~"inf"); - assert!(to_str_digits(-infinity, 10u) == ~"-inf"); -} - -#[test] -pub fn test_round() { - assert!(round(5.8) == 6.0); - assert!(round(5.2) == 5.0); - assert!(round(3.0) == 3.0); - assert!(round(2.5) == 3.0); - assert!(round(-3.5) == -4.0); -} +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + #[test] + pub fn test_to_str_exact_do_decimal() { + let s = to_str_exact(5.0, 4u); + assert!(s == ~"5.0000"); + } + + #[test] + pub fn test_from_str() { + assert!(from_str(~"3") == Some(3.)); + assert!(from_str(~"3.14") == Some(3.14)); + assert!(from_str(~"+3.14") == Some(3.14)); + assert!(from_str(~"-3.14") == Some(-3.14)); + assert!(from_str(~"2.5E10") == Some(25000000000.)); + assert!(from_str(~"2.5e10") == Some(25000000000.)); + assert!(from_str(~"25000000000.E-10") == Some(2.5)); + assert!(from_str(~".") == Some(0.)); + assert!(from_str(~".e1") == Some(0.)); + assert!(from_str(~".e-1") == Some(0.)); + assert!(from_str(~"5.") == Some(5.)); + assert!(from_str(~".5") == Some(0.5)); + assert!(from_str(~"0.5") == Some(0.5)); + assert!(from_str(~"-.5") == Some(-0.5)); + assert!(from_str(~"-5") == Some(-5.)); + assert!(from_str(~"inf") == Some(infinity)); + assert!(from_str(~"+inf") == Some(infinity)); + assert!(from_str(~"-inf") == Some(neg_infinity)); + // note: NaN != NaN, hence this slightly complex test + match from_str(~"NaN") { + Some(f) => assert!(is_NaN(f)), + None => fail!() + } + // note: -0 == 0, hence these slightly more complex tests + match from_str(~"-0") { + Some(v) if is_zero(v) => assert!(is_negative(v)), + _ => fail!() + } + match from_str(~"0") { + Some(v) if is_zero(v) => assert!(is_positive(v)), + _ => fail!() + } + + assert!(from_str(~"").is_none()); + assert!(from_str(~"x").is_none()); + assert!(from_str(~" ").is_none()); + assert!(from_str(~" ").is_none()); + assert!(from_str(~"e").is_none()); + assert!(from_str(~"E").is_none()); + assert!(from_str(~"E1").is_none()); + assert!(from_str(~"1e1e1").is_none()); + assert!(from_str(~"1e1.1").is_none()); + assert!(from_str(~"1e1-1").is_none()); + } + + #[test] + pub fn test_from_str_hex() { + assert!(from_str_hex(~"a4") == Some(164.)); + assert!(from_str_hex(~"a4.fe") == Some(164.9921875)); + assert!(from_str_hex(~"-a4.fe") == Some(-164.9921875)); + assert!(from_str_hex(~"+a4.fe") == Some(164.9921875)); + assert!(from_str_hex(~"ff0P4") == Some(0xff00 as float)); + assert!(from_str_hex(~"ff0p4") == Some(0xff00 as float)); + assert!(from_str_hex(~"ff0p-4") == Some(0xff as float)); + assert!(from_str_hex(~".") == Some(0.)); + assert!(from_str_hex(~".p1") == Some(0.)); + assert!(from_str_hex(~".p-1") == Some(0.)); + assert!(from_str_hex(~"f.") == Some(15.)); + assert!(from_str_hex(~".f") == Some(0.9375)); + assert!(from_str_hex(~"0.f") == Some(0.9375)); + assert!(from_str_hex(~"-.f") == Some(-0.9375)); + assert!(from_str_hex(~"-f") == Some(-15.)); + assert!(from_str_hex(~"inf") == Some(infinity)); + assert!(from_str_hex(~"+inf") == Some(infinity)); + assert!(from_str_hex(~"-inf") == Some(neg_infinity)); + // note: NaN != NaN, hence this slightly complex test + match from_str_hex(~"NaN") { + Some(f) => assert!(is_NaN(f)), + None => fail!() + } + // note: -0 == 0, hence these slightly more complex tests + match from_str_hex(~"-0") { + Some(v) if is_zero(v) => assert!(is_negative(v)), + _ => fail!() + } + match from_str_hex(~"0") { + Some(v) if is_zero(v) => assert!(is_positive(v)), + _ => fail!() + } + assert!(from_str_hex(~"e") == Some(14.)); + assert!(from_str_hex(~"E") == Some(14.)); + assert!(from_str_hex(~"E1") == Some(225.)); + assert!(from_str_hex(~"1e1e1") == Some(123361.)); + assert!(from_str_hex(~"1e1.1") == Some(481.0625)); + + assert!(from_str_hex(~"").is_none()); + assert!(from_str_hex(~"x").is_none()); + assert!(from_str_hex(~" ").is_none()); + assert!(from_str_hex(~" ").is_none()); + assert!(from_str_hex(~"p").is_none()); + assert!(from_str_hex(~"P").is_none()); + assert!(from_str_hex(~"P1").is_none()); + assert!(from_str_hex(~"1p1p1").is_none()); + assert!(from_str_hex(~"1p1.1").is_none()); + assert!(from_str_hex(~"1p1-1").is_none()); + } + + #[test] + pub fn test_to_str_hex() { + assert!(to_str_hex(164.) == ~"a4"); + assert!(to_str_hex(164.9921875) == ~"a4.fe"); + assert!(to_str_hex(-164.9921875) == ~"-a4.fe"); + assert!(to_str_hex(0xff00 as float) == ~"ff00"); + assert!(to_str_hex(-(0xff00 as float)) == ~"-ff00"); + assert!(to_str_hex(0.) == ~"0"); + assert!(to_str_hex(15.) == ~"f"); + assert!(to_str_hex(-15.) == ~"-f"); + assert!(to_str_hex(0.9375) == ~"0.f"); + assert!(to_str_hex(-0.9375) == ~"-0.f"); + assert!(to_str_hex(infinity) == ~"inf"); + assert!(to_str_hex(neg_infinity) == ~"-inf"); + assert!(to_str_hex(NaN) == ~"NaN"); + assert!(to_str_hex(0.) == ~"0"); + assert!(to_str_hex(-0.) == ~"-0"); + } + #[test] + pub fn test_to_str_radix() { + assert!(to_str_radix(36., 36u) == ~"10"); + assert!(to_str_radix(8.125, 2u) == ~"1000.001"); + } + + #[test] + pub fn test_from_str_radix() { + assert!(from_str_radix(~"10", 36u) == Some(36.)); + assert!(from_str_radix(~"1000.001", 2u) == Some(8.125)); + } + + #[test] + pub fn test_positive() { + assert!((is_positive(infinity))); + assert!((is_positive(1.))); + assert!((is_positive(0.))); + assert!((!is_positive(-1.))); + assert!((!is_positive(neg_infinity))); + assert!((!is_positive(1./neg_infinity))); + assert!((!is_positive(NaN))); + } + + #[test] + pub fn test_negative() { + assert!((!is_negative(infinity))); + assert!((!is_negative(1.))); + assert!((!is_negative(0.))); + assert!((is_negative(-1.))); + assert!((is_negative(neg_infinity))); + assert!((is_negative(1./neg_infinity))); + assert!((!is_negative(NaN))); + } + + #[test] + pub fn test_nonpositive() { + assert!((!is_nonpositive(infinity))); + assert!((!is_nonpositive(1.))); + assert!((!is_nonpositive(0.))); + assert!((is_nonpositive(-1.))); + assert!((is_nonpositive(neg_infinity))); + assert!((is_nonpositive(1./neg_infinity))); + assert!((!is_nonpositive(NaN))); + } + + #[test] + pub fn test_nonnegative() { + assert!((is_nonnegative(infinity))); + assert!((is_nonnegative(1.))); + assert!((is_nonnegative(0.))); + assert!((!is_nonnegative(-1.))); + assert!((!is_nonnegative(neg_infinity))); + assert!((!is_nonnegative(1./neg_infinity))); + assert!((!is_nonnegative(NaN))); + } + + #[test] + pub fn test_to_str_inf() { + assert!(to_str_digits(infinity, 10u) == ~"inf"); + assert!(to_str_digits(-infinity, 10u) == ~"-inf"); + } + + #[test] + pub fn test_round() { + assert!(round(5.8) == 6.0); + assert!(round(5.2) == 5.0); + assert!(round(3.0) == 3.0); + assert!(round(2.5) == 3.0); + assert!(round(-3.5) == -4.0); + } +} // // Local Variables: diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 6fbe44737d184..b495f9e7088fe 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -277,181 +277,188 @@ impl ToStrRadix for T { } } -#[test] -fn test_from_str() { - assert!(from_str(~"0") == Some(0 as T)); - assert!(from_str(~"3") == Some(3 as T)); - assert!(from_str(~"10") == Some(10 as T)); - assert!(i32::from_str(~"123456789") == Some(123456789 as i32)); - assert!(from_str(~"00100") == Some(100 as T)); - - assert!(from_str(~"-1") == Some(-1 as T)); - assert!(from_str(~"-3") == Some(-3 as T)); - assert!(from_str(~"-10") == Some(-10 as T)); - assert!(i32::from_str(~"-123456789") == Some(-123456789 as i32)); - assert!(from_str(~"-00100") == Some(-100 as T)); - - assert!(from_str(~" ").is_none()); - assert!(from_str(~"x").is_none()); -} +#[cfg(test)] +mod tests { + use super::*; + use super::inst::T; + use prelude::*; + + #[test] + fn test_from_str() { + assert!(from_str(~"0") == Some(0 as T)); + assert!(from_str(~"3") == Some(3 as T)); + assert!(from_str(~"10") == Some(10 as T)); + assert!(i32::from_str(~"123456789") == Some(123456789 as i32)); + assert!(from_str(~"00100") == Some(100 as T)); + + assert!(from_str(~"-1") == Some(-1 as T)); + assert!(from_str(~"-3") == Some(-3 as T)); + assert!(from_str(~"-10") == Some(-10 as T)); + assert!(i32::from_str(~"-123456789") == Some(-123456789 as i32)); + assert!(from_str(~"-00100") == Some(-100 as T)); + + assert!(from_str(~" ").is_none()); + assert!(from_str(~"x").is_none()); + } -#[test] -fn test_parse_bytes() { - use str::to_bytes; - assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123 as T)); - assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9 as T)); - assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83 as T)); - assert!(i32::parse_bytes(to_bytes(~"123"), 16u) == Some(291 as i32)); - assert!(i32::parse_bytes(to_bytes(~"ffff"), 16u) == - Some(65535 as i32)); - assert!(i32::parse_bytes(to_bytes(~"FFFF"), 16u) == - Some(65535 as i32)); - assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35 as T)); - assert!(parse_bytes(to_bytes(~"Z"), 36u) == Some(35 as T)); - - assert!(parse_bytes(to_bytes(~"-123"), 10u) == Some(-123 as T)); - assert!(parse_bytes(to_bytes(~"-1001"), 2u) == Some(-9 as T)); - assert!(parse_bytes(to_bytes(~"-123"), 8u) == Some(-83 as T)); - assert!(i32::parse_bytes(to_bytes(~"-123"), 16u) == - Some(-291 as i32)); - assert!(i32::parse_bytes(to_bytes(~"-ffff"), 16u) == - Some(-65535 as i32)); - assert!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u) == - Some(-65535 as i32)); - assert!(parse_bytes(to_bytes(~"-z"), 36u) == Some(-35 as T)); - assert!(parse_bytes(to_bytes(~"-Z"), 36u) == Some(-35 as T)); - - assert!(parse_bytes(to_bytes(~"Z"), 35u).is_none()); - assert!(parse_bytes(to_bytes(~"-9"), 2u).is_none()); -} + #[test] + fn test_parse_bytes() { + use str::to_bytes; + assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123 as T)); + assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9 as T)); + assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83 as T)); + assert!(i32::parse_bytes(to_bytes(~"123"), 16u) == Some(291 as i32)); + assert!(i32::parse_bytes(to_bytes(~"ffff"), 16u) == + Some(65535 as i32)); + assert!(i32::parse_bytes(to_bytes(~"FFFF"), 16u) == + Some(65535 as i32)); + assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35 as T)); + assert!(parse_bytes(to_bytes(~"Z"), 36u) == Some(35 as T)); + + assert!(parse_bytes(to_bytes(~"-123"), 10u) == Some(-123 as T)); + assert!(parse_bytes(to_bytes(~"-1001"), 2u) == Some(-9 as T)); + assert!(parse_bytes(to_bytes(~"-123"), 8u) == Some(-83 as T)); + assert!(i32::parse_bytes(to_bytes(~"-123"), 16u) == + Some(-291 as i32)); + assert!(i32::parse_bytes(to_bytes(~"-ffff"), 16u) == + Some(-65535 as i32)); + assert!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u) == + Some(-65535 as i32)); + assert!(parse_bytes(to_bytes(~"-z"), 36u) == Some(-35 as T)); + assert!(parse_bytes(to_bytes(~"-Z"), 36u) == Some(-35 as T)); + + assert!(parse_bytes(to_bytes(~"Z"), 35u).is_none()); + assert!(parse_bytes(to_bytes(~"-9"), 2u).is_none()); + } -#[test] -fn test_to_str() { - assert!((to_str_radix(0 as T, 10u) == ~"0")); - assert!((to_str_radix(1 as T, 10u) == ~"1")); - assert!((to_str_radix(-1 as T, 10u) == ~"-1")); - assert!((to_str_radix(127 as T, 16u) == ~"7f")); - assert!((to_str_radix(100 as T, 10u) == ~"100")); + #[test] + fn test_to_str() { + assert!((to_str_radix(0 as T, 10u) == ~"0")); + assert!((to_str_radix(1 as T, 10u) == ~"1")); + assert!((to_str_radix(-1 as T, 10u) == ~"-1")); + assert!((to_str_radix(127 as T, 16u) == ~"7f")); + assert!((to_str_radix(100 as T, 10u) == ~"100")); -} + } -#[test] -fn test_int_to_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert!((i8::to_str(i8_val) == ~"127")); + #[test] + fn test_int_to_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert!((i8::to_str(i8_val) == ~"127")); - i8_val += 1 as i8; - assert!((i8::to_str(i8_val) == ~"-128")); + i8_val += 1 as i8; + assert!((i8::to_str(i8_val) == ~"-128")); - let mut i16_val: i16 = 32_767_i16; - assert!((i16::to_str(i16_val) == ~"32767")); + let mut i16_val: i16 = 32_767_i16; + assert!((i16::to_str(i16_val) == ~"32767")); - i16_val += 1 as i16; - assert!((i16::to_str(i16_val) == ~"-32768")); + i16_val += 1 as i16; + assert!((i16::to_str(i16_val) == ~"-32768")); - let mut i32_val: i32 = 2_147_483_647_i32; - assert!((i32::to_str(i32_val) == ~"2147483647")); + let mut i32_val: i32 = 2_147_483_647_i32; + assert!((i32::to_str(i32_val) == ~"2147483647")); - i32_val += 1 as i32; - assert!((i32::to_str(i32_val) == ~"-2147483648")); + i32_val += 1 as i32; + assert!((i32::to_str(i32_val) == ~"-2147483648")); - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert!((i64::to_str(i64_val) == ~"9223372036854775807")); + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert!((i64::to_str(i64_val) == ~"9223372036854775807")); - i64_val += 1 as i64; - assert!((i64::to_str(i64_val) == ~"-9223372036854775808")); -} + i64_val += 1 as i64; + assert!((i64::to_str(i64_val) == ~"-9223372036854775808")); + } -#[test] -fn test_int_from_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert!((i8::from_str(~"127") == Some(i8_val))); - assert!((i8::from_str(~"128").is_none())); + #[test] + fn test_int_from_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert!((i8::from_str(~"127") == Some(i8_val))); + assert!((i8::from_str(~"128").is_none())); - i8_val += 1 as i8; - assert!((i8::from_str(~"-128") == Some(i8_val))); - assert!((i8::from_str(~"-129").is_none())); + i8_val += 1 as i8; + assert!((i8::from_str(~"-128") == Some(i8_val))); + assert!((i8::from_str(~"-129").is_none())); - let mut i16_val: i16 = 32_767_i16; - assert!((i16::from_str(~"32767") == Some(i16_val))); - assert!((i16::from_str(~"32768").is_none())); + let mut i16_val: i16 = 32_767_i16; + assert!((i16::from_str(~"32767") == Some(i16_val))); + assert!((i16::from_str(~"32768").is_none())); - i16_val += 1 as i16; - assert!((i16::from_str(~"-32768") == Some(i16_val))); - assert!((i16::from_str(~"-32769").is_none())); + i16_val += 1 as i16; + assert!((i16::from_str(~"-32768") == Some(i16_val))); + assert!((i16::from_str(~"-32769").is_none())); - let mut i32_val: i32 = 2_147_483_647_i32; - assert!((i32::from_str(~"2147483647") == Some(i32_val))); - assert!((i32::from_str(~"2147483648").is_none())); + let mut i32_val: i32 = 2_147_483_647_i32; + assert!((i32::from_str(~"2147483647") == Some(i32_val))); + assert!((i32::from_str(~"2147483648").is_none())); - i32_val += 1 as i32; - assert!((i32::from_str(~"-2147483648") == Some(i32_val))); - assert!((i32::from_str(~"-2147483649").is_none())); + i32_val += 1 as i32; + assert!((i32::from_str(~"-2147483648") == Some(i32_val))); + assert!((i32::from_str(~"-2147483649").is_none())); - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert!((i64::from_str(~"9223372036854775807") == Some(i64_val))); - assert!((i64::from_str(~"9223372036854775808").is_none())); + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert!((i64::from_str(~"9223372036854775807") == Some(i64_val))); + assert!((i64::from_str(~"9223372036854775808").is_none())); - i64_val += 1 as i64; - assert!((i64::from_str(~"-9223372036854775808") == Some(i64_val))); - assert!((i64::from_str(~"-9223372036854775809").is_none())); -} + i64_val += 1 as i64; + assert!((i64::from_str(~"-9223372036854775808") == Some(i64_val))); + assert!((i64::from_str(~"-9223372036854775809").is_none())); + } -#[test] -pub fn test_ranges() { - let mut l = ~[]; + #[test] + fn test_ranges() { + let mut l = ~[]; - for range(0,3) |i| { - l.push(i); - } - for range_rev(13,10) |i| { - l.push(i); - } - for range_step(20,26,2) |i| { - l.push(i); - } - for range_step(36,30,-2) |i| { - l.push(i); - } - for range_step(max_value - 2, max_value, 2) |i| { - l.push(i); - } - for range_step(max_value - 3, max_value, 2) |i| { - l.push(i); - } - for range_step(min_value + 2, min_value, -2) |i| { - l.push(i); - } - for range_step(min_value + 3, min_value, -2) |i| { - l.push(i); - } - assert_eq!(l, ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32, - max_value-2, - max_value-3,max_value-1, - min_value+2, - min_value+3,min_value+1]); - - // None of the `fail`s should execute. - for range(10,0) |_i| { - fail!(~"unreachable"); - } - for range_rev(0,10) |_i| { - fail!(~"unreachable"); - } - for range_step(10,0,1) |_i| { - fail!(~"unreachable"); - } - for range_step(0,10,-1) |_i| { - fail!(~"unreachable"); + for range(0,3) |i| { + l.push(i); + } + for range_rev(13,10) |i| { + l.push(i); + } + for range_step(20,26,2) |i| { + l.push(i); + } + for range_step(36,30,-2) |i| { + l.push(i); + } + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); + + // None of the `fail`s should execute. + for range(10,0) |_i| { + fail!(~"unreachable"); + } + for range_rev(0,10) |_i| { + fail!(~"unreachable"); + } + for range_step(10,0,1) |_i| { + fail!(~"unreachable"); + } + for range_step(0,10,-1) |_i| { + fail!(~"unreachable"); + } } -} -#[test] -#[should_fail] -#[ignore(cfg(windows))] -fn test_range_step_zero_step() { - for range_step(0,10,0) |_i| {} -} + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_range_step_zero_step() { + for range_step(0,10,0) |_i| {} + } +} \ No newline at end of file diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 1cbdabafdab96..af6557e9881f2 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -242,184 +242,190 @@ impl ToStrRadix for T { } } -#[test] -pub fn test_to_str() { - assert!(to_str_radix(0 as T, 10u) == ~"0"); - assert!(to_str_radix(1 as T, 10u) == ~"1"); - assert!(to_str_radix(2 as T, 10u) == ~"2"); - assert!(to_str_radix(11 as T, 10u) == ~"11"); - assert!(to_str_radix(11 as T, 16u) == ~"b"); - assert!(to_str_radix(255 as T, 16u) == ~"ff"); - assert!(to_str_radix(0xff as T, 10u) == ~"255"); -} +#[cfg(test)] +mod tests { + use super::*; + use super::inst::T; + use prelude::*; + #[test] + pub fn test_to_str() { + assert!(to_str_radix(0 as T, 10u) == ~"0"); + assert!(to_str_radix(1 as T, 10u) == ~"1"); + assert!(to_str_radix(2 as T, 10u) == ~"2"); + assert!(to_str_radix(11 as T, 10u) == ~"11"); + assert!(to_str_radix(11 as T, 16u) == ~"b"); + assert!(to_str_radix(255 as T, 16u) == ~"ff"); + assert!(to_str_radix(0xff as T, 10u) == ~"255"); + } -#[test] -pub fn test_from_str() { - assert!(from_str(~"0") == Some(0u as T)); - assert!(from_str(~"3") == Some(3u as T)); - assert!(from_str(~"10") == Some(10u as T)); - assert!(u32::from_str(~"123456789") == Some(123456789 as u32)); - assert!(from_str(~"00100") == Some(100u as T)); - - assert!(from_str(~"").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~"x").is_none()); -} + #[test] + pub fn test_from_str() { + assert!(from_str(~"0") == Some(0u as T)); + assert!(from_str(~"3") == Some(3u as T)); + assert!(from_str(~"10") == Some(10u as T)); + assert!(u32::from_str(~"123456789") == Some(123456789 as u32)); + assert!(from_str(~"00100") == Some(100u as T)); + + assert!(from_str(~"").is_none()); + assert!(from_str(~" ").is_none()); + assert!(from_str(~"x").is_none()); + } -#[test] -pub fn test_parse_bytes() { - use str::to_bytes; - assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123u as T)); - assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9u as T)); - assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83u as T)); - assert!(u16::parse_bytes(to_bytes(~"123"), 16u) == - Some(291u as u16)); - assert!(u16::parse_bytes(to_bytes(~"ffff"), 16u) == - Some(65535u as u16)); - assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35u as T)); - - assert!(parse_bytes(to_bytes(~"Z"), 10u).is_none()); - assert!(parse_bytes(to_bytes(~"_"), 2u).is_none()); -} + #[test] + pub fn test_parse_bytes() { + use str::to_bytes; + assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123u as T)); + assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9u as T)); + assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83u as T)); + assert!(u16::parse_bytes(to_bytes(~"123"), 16u) == + Some(291u as u16)); + assert!(u16::parse_bytes(to_bytes(~"ffff"), 16u) == + Some(65535u as u16)); + assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35u as T)); + + assert!(parse_bytes(to_bytes(~"Z"), 10u).is_none()); + assert!(parse_bytes(to_bytes(~"_"), 2u).is_none()); + } -#[test] -fn test_uint_to_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert!((u8::to_str(u8_val) == ~"255")); + #[test] + fn test_uint_to_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert!((u8::to_str(u8_val) == ~"255")); - u8_val += 1 as u8; - assert!((u8::to_str(u8_val) == ~"0")); + u8_val += 1 as u8; + assert!((u8::to_str(u8_val) == ~"0")); - let mut u16_val: u16 = 65_535_u16; - assert!((u16::to_str(u16_val) == ~"65535")); + let mut u16_val: u16 = 65_535_u16; + assert!((u16::to_str(u16_val) == ~"65535")); - u16_val += 1 as u16; - assert!((u16::to_str(u16_val) == ~"0")); + u16_val += 1 as u16; + assert!((u16::to_str(u16_val) == ~"0")); - let mut u32_val: u32 = 4_294_967_295_u32; - assert!((u32::to_str(u32_val) == ~"4294967295")); + let mut u32_val: u32 = 4_294_967_295_u32; + assert!((u32::to_str(u32_val) == ~"4294967295")); - u32_val += 1 as u32; - assert!((u32::to_str(u32_val) == ~"0")); + u32_val += 1 as u32; + assert!((u32::to_str(u32_val) == ~"0")); - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert!((u64::to_str(u64_val) == ~"18446744073709551615")); + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert!((u64::to_str(u64_val) == ~"18446744073709551615")); - u64_val += 1 as u64; - assert!((u64::to_str(u64_val) == ~"0")); -} + u64_val += 1 as u64; + assert!((u64::to_str(u64_val) == ~"0")); + } -#[test] -fn test_uint_from_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert!((u8::from_str(~"255") == Some(u8_val))); - assert!((u8::from_str(~"256").is_none())); + #[test] + fn test_uint_from_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert!((u8::from_str(~"255") == Some(u8_val))); + assert!((u8::from_str(~"256").is_none())); - u8_val += 1 as u8; - assert!((u8::from_str(~"0") == Some(u8_val))); - assert!((u8::from_str(~"-1").is_none())); + u8_val += 1 as u8; + assert!((u8::from_str(~"0") == Some(u8_val))); + assert!((u8::from_str(~"-1").is_none())); - let mut u16_val: u16 = 65_535_u16; - assert!((u16::from_str(~"65535") == Some(u16_val))); - assert!((u16::from_str(~"65536").is_none())); + let mut u16_val: u16 = 65_535_u16; + assert!((u16::from_str(~"65535") == Some(u16_val))); + assert!((u16::from_str(~"65536").is_none())); - u16_val += 1 as u16; - assert!((u16::from_str(~"0") == Some(u16_val))); - assert!((u16::from_str(~"-1").is_none())); + u16_val += 1 as u16; + assert!((u16::from_str(~"0") == Some(u16_val))); + assert!((u16::from_str(~"-1").is_none())); - let mut u32_val: u32 = 4_294_967_295_u32; - assert!((u32::from_str(~"4294967295") == Some(u32_val))); - assert!((u32::from_str(~"4294967296").is_none())); + let mut u32_val: u32 = 4_294_967_295_u32; + assert!((u32::from_str(~"4294967295") == Some(u32_val))); + assert!((u32::from_str(~"4294967296").is_none())); - u32_val += 1 as u32; - assert!((u32::from_str(~"0") == Some(u32_val))); - assert!((u32::from_str(~"-1").is_none())); + u32_val += 1 as u32; + assert!((u32::from_str(~"0") == Some(u32_val))); + assert!((u32::from_str(~"-1").is_none())); - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert!((u64::from_str(~"18446744073709551615") == Some(u64_val))); - assert!((u64::from_str(~"18446744073709551616").is_none())); + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert!((u64::from_str(~"18446744073709551615") == Some(u64_val))); + assert!((u64::from_str(~"18446744073709551616").is_none())); - u64_val += 1 as u64; - assert!((u64::from_str(~"0") == Some(u64_val))); - assert!((u64::from_str(~"-1").is_none())); -} + u64_val += 1 as u64; + assert!((u64::from_str(~"0") == Some(u64_val))); + assert!((u64::from_str(~"-1").is_none())); + } -#[test] -#[should_fail] -#[ignore(cfg(windows))] -pub fn to_str_radix1() { - uint::to_str_radix(100u, 1u); -} + #[test] + #[should_fail] + #[ignore(cfg(windows))] + pub fn to_str_radix1() { + uint::to_str_radix(100u, 1u); + } -#[test] -#[should_fail] -#[ignore(cfg(windows))] -pub fn to_str_radix37() { - uint::to_str_radix(100u, 37u); -} + #[test] + #[should_fail] + #[ignore(cfg(windows))] + pub fn to_str_radix37() { + uint::to_str_radix(100u, 37u); + } -#[test] -pub fn test_ranges() { - let mut l = ~[]; + #[test] + pub fn test_ranges() { + let mut l = ~[]; - for range(0,3) |i| { - l.push(i); - } - for range_rev(13,10) |i| { - l.push(i); - } - for range_step(20,26,2) |i| { - l.push(i); - } - for range_step(36,30,-2) |i| { - l.push(i); - } - for range_step(max_value - 2, max_value, 2) |i| { - l.push(i); - } - for range_step(max_value - 3, max_value, 2) |i| { - l.push(i); - } - for range_step(min_value + 2, min_value, -2) |i| { - l.push(i); - } - for range_step(min_value + 3, min_value, -2) |i| { - l.push(i); - } + for range(0,3) |i| { + l.push(i); + } + for range_rev(13,10) |i| { + l.push(i); + } + for range_step(20,26,2) |i| { + l.push(i); + } + for range_step(36,30,-2) |i| { + l.push(i); + } + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } - assert_eq!(l, ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32, - max_value-2, - max_value-3,max_value-1, - min_value+2, - min_value+3,min_value+1]); - - // None of the `fail`s should execute. - for range(0,0) |_i| { - fail!(~"unreachable"); - } - for range_rev(0,0) |_i| { - fail!(~"unreachable"); + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); + + // None of the `fail`s should execute. + for range(0,0) |_i| { + fail!(~"unreachable"); + } + for range_rev(0,0) |_i| { + fail!(~"unreachable"); + } + for range_step(10,0,1) |_i| { + fail!(~"unreachable"); + } + for range_step(0,1,-10) |_i| { + fail!(~"unreachable"); + } } - for range_step(10,0,1) |_i| { - fail!(~"unreachable"); + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_range_step_zero_step_up() { + for range_step(0,10,0) |_i| {} } - for range_step(0,1,-10) |_i| { - fail!(~"unreachable"); + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_range_step_zero_step_down() { + for range_step(0,-10,0) |_i| {} } -} - -#[test] -#[should_fail] -#[ignore(cfg(windows))] -fn test_range_step_zero_step_up() { - for range_step(0,10,0) |_i| {} -} -#[test] -#[should_fail] -#[ignore(cfg(windows))] -fn test_range_step_zero_step_down() { - for range_step(0,-10,0) |_i| {} -} +} \ No newline at end of file diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 18f8030d5b84e..fddb2af558709 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -957,13 +957,13 @@ pub mod rt { } #[cfg(test)] -pub mod test { +mod test { use either::Right; use comm::{Chan, Port, oneshot, recv_one, stream, Select2, GenericChan, Peekable}; #[test] - pub fn test_select2() { + fn test_select2() { let (p1, c1) = stream(); let (p2, c2) = stream(); @@ -978,7 +978,7 @@ pub mod test { } #[test] - pub fn test_oneshot() { + fn test_oneshot() { let (c, p) = oneshot::init(); oneshot::client::send(c, ()); diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 14e17de4fbda0..ebde37e77b42f 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -15,8 +15,6 @@ use libc; use libc::{c_void, size_t}; use sys; -#[cfg(test)] use vec; -#[cfg(test)] use str; #[cfg(notest)] use cmp::{Eq, Ord}; use uint; @@ -341,101 +339,101 @@ impl<'self,T:Ord> Ord for &'self const T { } } -#[test] -pub fn test() { - unsafe { - struct Pair {mut fst: int, mut snd: int}; - let mut p = Pair {fst: 10, snd: 20}; - let pptr: *mut Pair = &mut p; - let iptr: *mut int = cast::reinterpret_cast(&pptr); - assert!((*iptr == 10));; - *iptr = 30; - assert!((*iptr == 30)); - assert!((p.fst == 30));; - - *pptr = Pair {fst: 50, snd: 60}; - assert!((*iptr == 50)); - assert!((p.fst == 50)); - assert!((p.snd == 60)); - - let mut v0 = ~[32000u16, 32001u16, 32002u16]; - let mut v1 = ~[0u16, 0u16, 0u16]; - - copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 1u), - offset(vec::raw::to_ptr(v0), 1u), 1u); - assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); - copy_memory(vec::raw::to_mut_ptr(v1), - offset(vec::raw::to_ptr(v0), 2u), 1u); - assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && - v1[2] == 0u16)); - copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 2u), - vec::raw::to_ptr(v0), 1u); - assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && - v1[2] == 32000u16)); +#[cfg(test)] +pub mod ptr_tests { + use super::*; + use prelude::*; + + #[test] + fn test() { + unsafe { + struct Pair {mut fst: int, mut snd: int}; + let mut p = Pair {fst: 10, snd: 20}; + let pptr: *mut Pair = &mut p; + let iptr: *mut int = cast::reinterpret_cast(&pptr); + assert!((*iptr == 10));; + *iptr = 30; + assert!((*iptr == 30)); + assert!((p.fst == 30));; + + *pptr = Pair {fst: 50, snd: 60}; + assert!((*iptr == 50)); + assert!((p.fst == 50)); + assert!((p.snd == 60)); + + let mut v0 = ~[32000u16, 32001u16, 32002u16]; + let mut v1 = ~[0u16, 0u16, 0u16]; + + copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 1u), + offset(vec::raw::to_ptr(v0), 1u), 1u); + assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); + copy_memory(vec::raw::to_mut_ptr(v1), + offset(vec::raw::to_ptr(v0), 2u), 1u); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && + v1[2] == 0u16)); + copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 2u), + vec::raw::to_ptr(v0), 1u); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && + v1[2] == 32000u16)); + } } -} -#[test] -pub fn test_position() { - use str::as_c_str; - use libc::c_char; + #[test] + fn test_position() { + use str::as_c_str; + use libc::c_char; - let s = ~"hello"; - unsafe { - assert!(2u == as_c_str(s, |p| position(p, - |c| *c == 'l' as c_char))); - assert!(4u == as_c_str(s, |p| position(p, - |c| *c == 'o' as c_char))); - assert!(5u == as_c_str(s, |p| position(p, - |c| *c == 0 as c_char))); + let s = ~"hello"; + unsafe { + assert!(2u == as_c_str(s, |p| position(p, + |c| *c == 'l' as c_char))); + assert!(4u == as_c_str(s, |p| position(p, + |c| *c == 'o' as c_char))); + assert!(5u == as_c_str(s, |p| position(p, + |c| *c == 0 as c_char))); + } } -} -#[test] -pub fn test_buf_len() { - let s0 = ~"hello"; - let s1 = ~"there"; - let s2 = ~"thing"; - do str::as_c_str(s0) |p0| { - do str::as_c_str(s1) |p1| { - do str::as_c_str(s2) |p2| { - let v = ~[p0, p1, p2, null()]; - do vec::as_imm_buf(v) |vp, len| { - assert!(unsafe { buf_len(vp) } == 3u); - assert!(len == 4u); + #[test] + fn test_buf_len() { + let s0 = ~"hello"; + let s1 = ~"there"; + let s2 = ~"thing"; + do str::as_c_str(s0) |p0| { + do str::as_c_str(s1) |p1| { + do str::as_c_str(s2) |p2| { + let v = ~[p0, p1, p2, null()]; + do vec::as_imm_buf(v) |vp, len| { + assert!(unsafe { buf_len(vp) } == 3u); + assert!(len == 4u); + } } } } } -} - -#[test] -pub fn test_is_null() { - let p: *int = null(); - assert!(p.is_null()); - assert!(!p.is_not_null()); - let q = offset(p, 1u); - assert!(!q.is_null()); - assert!(q.is_not_null()); - - let mp: *mut int = mut_null(); - assert!(mp.is_null()); - assert!(!mp.is_not_null()); + #[test] + fn test_is_null() { + let p: *int = null(); + assert!(p.is_null()); + assert!(!p.is_not_null()); + + let q = offset(p, 1u); + assert!(!q.is_null()); + assert!(q.is_not_null()); + + let mp: *mut int = mut_null(); + assert!(mp.is_null()); + assert!(!mp.is_not_null()); + + let mq = mp.offset(1u); + assert!(!mq.is_null()); + assert!(mq.is_not_null()); + } - let mq = mp.offset(1u); - assert!(!mq.is_null()); - assert!(mq.is_not_null()); -} -#[cfg(test)] -pub mod ptr_tests { - use ptr; - use str; - use libc; - use vec; #[test] - pub fn test_ptr_array_each_with_len() { + fn test_ptr_array_each_with_len() { unsafe { let one = ~"oneOne"; let two = ~"twoTwo"; @@ -451,22 +449,22 @@ pub mod ptr_tests { let arr_ptr = &arr[0]; let mut ctr = 0; let mut iteration_count = 0; - ptr::array_each_with_len(arr_ptr, vec::len(arr), - |e| { - let actual = str::raw::from_c_str(e); - let expected = copy expected_arr[ctr]; - debug!( - "test_ptr_array_each e: %s, a: %s", - expected, actual); - assert!(actual == expected); - ctr += 1; - iteration_count += 1; - }); + array_each_with_len(arr_ptr, vec::len(arr), + |e| { + let actual = str::raw::from_c_str(e); + let expected = copy expected_arr[ctr]; + debug!( + "test_ptr_array_each e: %s, a: %s", + expected, actual); + assert!(actual == expected); + ctr += 1; + iteration_count += 1; + }); assert!(iteration_count == 3u); } } #[test] - pub fn test_ptr_array_each() { + fn test_ptr_array_each() { unsafe { let one = ~"oneOne"; let two = ~"twoTwo"; @@ -484,12 +482,12 @@ pub mod ptr_tests { let arr_ptr = &arr[0]; let mut ctr = 0; let mut iteration_count = 0; - ptr::array_each(arr_ptr, |e| { + array_each(arr_ptr, |e| { let actual = str::raw::from_c_str(e); let expected = copy expected_arr[ctr]; debug!( "test_ptr_array_each e: %s, a: %s", - expected, actual); + expected, actual); assert!(actual == expected); ctr += 1; iteration_count += 1; @@ -500,9 +498,9 @@ pub mod ptr_tests { #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_ptr_array_each_with_len_null_ptr() { + fn test_ptr_array_each_with_len_null_ptr() { unsafe { - ptr::array_each_with_len(0 as **libc::c_char, 1, |e| { + array_each_with_len(0 as **libc::c_char, 1, |e| { str::raw::from_c_str(e); }); } @@ -510,9 +508,9 @@ pub mod ptr_tests { #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_ptr_array_each_null_ptr() { + fn test_ptr_array_each_null_ptr() { unsafe { - ptr::array_each(0 as **libc::c_char, |e| { + array_each(0 as **libc::c_char, |e| { str::raw::from_c_str(e); }); } diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index c6400ccded8a6..0a93a651a8572 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -747,12 +747,12 @@ pub fn random() -> uint { #[cfg(test)] -pub mod tests { +mod tests { use option::{Option, Some}; use rand; #[test] - pub fn rng_seeded() { + fn rng_seeded() { let seed = rand::seed(); let ra = rand::seeded_rng(seed); let rb = rand::seeded_rng(seed); @@ -760,7 +760,7 @@ pub mod tests { } #[test] - pub fn rng_seeded_custom_seed() { + fn rng_seeded_custom_seed() { // much shorter than generated seeds which are 1024 bytes let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; let ra = rand::seeded_rng(seed); @@ -769,7 +769,7 @@ pub mod tests { } #[test] - pub fn rng_seeded_custom_seed2() { + fn rng_seeded_custom_seed2() { let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; let ra = rand::seeded_rng(seed); // Regression test that isaac is actually using the above vector @@ -780,7 +780,7 @@ pub mod tests { } #[test] - pub fn gen_int_range() { + fn gen_int_range() { let r = rand::Rng(); let a = r.gen_int_range(-3, 42); assert!(a >= -3 && a < 42); @@ -791,12 +791,12 @@ pub mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn gen_int_from_fail() { + fn gen_int_from_fail() { rand::Rng().gen_int_range(5, -2); } #[test] - pub fn gen_uint_range() { + fn gen_uint_range() { let r = rand::Rng(); let a = r.gen_uint_range(3u, 42u); assert!(a >= 3u && a < 42u); @@ -807,12 +807,12 @@ pub mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn gen_uint_range_fail() { + fn gen_uint_range_fail() { rand::Rng().gen_uint_range(5u, 2u); } #[test] - pub fn gen_float() { + fn gen_float() { let r = rand::Rng(); let a = r.gen_float(); let b = r.gen_float(); @@ -820,14 +820,14 @@ pub mod tests { } #[test] - pub fn gen_weighted_bool() { + fn gen_weighted_bool() { let r = rand::Rng(); assert!(r.gen_weighted_bool(0u) == true); assert!(r.gen_weighted_bool(1u) == true); } #[test] - pub fn gen_str() { + fn gen_str() { let r = rand::Rng(); debug!(r.gen_str(10u)); debug!(r.gen_str(10u)); @@ -838,7 +838,7 @@ pub mod tests { } #[test] - pub fn gen_bytes() { + fn gen_bytes() { let r = rand::Rng(); assert!(r.gen_bytes(0u).len() == 0u); assert!(r.gen_bytes(10u).len() == 10u); @@ -846,13 +846,13 @@ pub mod tests { } #[test] - pub fn choose() { + fn choose() { let r = rand::Rng(); assert!(r.choose([1, 1, 1]) == 1); } #[test] - pub fn choose_option() { + fn choose_option() { let r = rand::Rng(); let x: Option = r.choose_option([]); assert!(x.is_none()); @@ -860,7 +860,7 @@ pub mod tests { } #[test] - pub fn choose_weighted() { + fn choose_weighted() { let r = rand::Rng(); assert!(r.choose_weighted(~[ rand::Weighted { weight: 1u, item: 42 }, @@ -872,7 +872,7 @@ pub mod tests { } #[test] - pub fn choose_weighted_option() { + fn choose_weighted_option() { let r = rand::Rng(); assert!(r.choose_weighted_option(~[ rand::Weighted { weight: 1u, item: 42 }, @@ -886,7 +886,7 @@ pub mod tests { } #[test] - pub fn weighted_vec() { + fn weighted_vec() { let r = rand::Rng(); let empty: ~[int] = ~[]; assert!(r.weighted_vec(~[]) == empty); @@ -898,7 +898,7 @@ pub mod tests { } #[test] - pub fn shuffle() { + fn shuffle() { let r = rand::Rng(); let empty: ~[int] = ~[]; assert!(r.shuffle(~[]) == empty); @@ -906,7 +906,7 @@ pub mod tests { } #[test] - pub fn task_rng() { + fn task_rng() { let r = rand::task_rng(); r.gen_int(); assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); @@ -914,7 +914,7 @@ pub mod tests { } #[test] - pub fn random() { + fn random() { // not sure how to test this aside from just getting a number let _n : uint = rand::random(); } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 49df2938afd40..8e247a25012f1 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -521,7 +521,7 @@ mod tests { // Regression test for memory leaks #[ignore(cfg(windows))] // FIXME (#2626) - pub fn test_leaks() { + fn test_leaks() { run::run_program("echo", []); run::start_program("echo", []); run::program_output("echo", []); @@ -529,7 +529,7 @@ mod tests { #[test] #[allow(non_implicitly_copyable_typarams)] - pub fn test_pipes() { + fn test_pipes() { let pipe_in = os::pipe(); let pipe_out = os::pipe(); let pipe_err = os::pipe(); @@ -555,7 +555,7 @@ mod tests { } #[test] - pub fn waitpid() { + fn waitpid() { let pid = run::spawn_process("false", [], &None, &None, 0i32, 0i32, 0i32); @@ -564,20 +564,20 @@ mod tests { } #[test] - pub fn test_destroy_once() { + fn test_destroy_once() { let mut p = run::start_program("echo", []); p.destroy(); // this shouldn't crash (and nor should the destructor) } #[test] - pub fn test_destroy_twice() { + fn test_destroy_twice() { let mut p = run::start_program("echo", []); p.destroy(); // this shouldnt crash... p.destroy(); // ...and nor should this (and nor should the destructor) } #[cfg(unix)] // there is no way to sleep on windows from inside libcore... - pub fn test_destroy_actually_kills(force: bool) { + fn test_destroy_actually_kills(force: bool) { let path = Path(fmt!("test/core-run-test-destroy-actually-kills-%?.tmp", force)); os::remove_file(&path); @@ -598,13 +598,13 @@ mod tests { #[test] #[cfg(unix)] - pub fn test_unforced_destroy_actually_kills() { + fn test_unforced_destroy_actually_kills() { test_destroy_actually_kills(false); } #[test] #[cfg(unix)] - pub fn test_forced_destroy_actually_kills() { + fn test_forced_destroy_actually_kills() { test_destroy_actually_kills(true); } } diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 678005ce06f96..04f96f5eb229e 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -160,12 +160,12 @@ pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! { } #[cfg(test)] -pub mod tests { +mod tests { use cast; use sys::{Closure, pref_align_of, size_of, nonzero_size_of}; #[test] - pub fn size_of_basic() { + fn size_of_basic() { assert!(size_of::() == 1u); assert!(size_of::() == 2u); assert!(size_of::() == 4u); @@ -176,20 +176,20 @@ pub mod tests { #[cfg(target_arch = "x86")] #[cfg(target_arch = "arm")] #[cfg(target_arch = "mips")] - pub fn size_of_32() { + fn size_of_32() { assert!(size_of::() == 4u); assert!(size_of::<*uint>() == 4u); } #[test] #[cfg(target_arch = "x86_64")] - pub fn size_of_64() { + fn size_of_64() { assert!(size_of::() == 8u); assert!(size_of::<*uint>() == 8u); } #[test] - pub fn nonzero_size_of_basic() { + fn nonzero_size_of_basic() { type Z = [i8, ..0]; assert!(size_of::() == 0u); assert!(nonzero_size_of::() == 1u); @@ -197,7 +197,7 @@ pub mod tests { } #[test] - pub fn align_of_basic() { + fn align_of_basic() { assert!(pref_align_of::() == 1u); assert!(pref_align_of::() == 2u); assert!(pref_align_of::() == 4u); @@ -207,20 +207,20 @@ pub mod tests { #[cfg(target_arch = "x86")] #[cfg(target_arch = "arm")] #[cfg(target_arch = "mips")] - pub fn align_of_32() { + fn align_of_32() { assert!(pref_align_of::() == 4u); assert!(pref_align_of::<*uint>() == 4u); } #[test] #[cfg(target_arch = "x86_64")] - pub fn align_of_64() { + fn align_of_64() { assert!(pref_align_of::() == 8u); assert!(pref_align_of::<*uint>() == 8u); } #[test] - pub fn synthesize_closure() { + fn synthesize_closure() { unsafe { let x = 10; let f: &fn(int) -> int = |y| x + y; diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index d712bf8f98f44..a6c4b6c526862 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -925,7 +925,7 @@ fn test_spawn_sched_childs_on_default_sched() { } #[cfg(test)] -pub mod testrt { +mod testrt { use libc; #[nolink] diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index e43d321dc4d05..c057fce0abd8c 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -286,14 +286,14 @@ pub impl Exclusive { } #[cfg(test)] -pub mod tests { +mod tests { use comm; use super::exclusive; use task; use uint; #[test] - pub fn exclusive_arc() { + fn exclusive_arc() { let mut futures = ~[]; let num_tasks = 10; @@ -324,7 +324,7 @@ pub mod tests { } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn exclusive_poison() { + fn exclusive_poison() { // Tests that if one task fails inside of an exclusive, subsequent // accesses will also fail. let x = exclusive(1); diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index cc1168bd79ddd..49935eea0e13d 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -212,14 +212,14 @@ mod test { use driver::session; #[test] - pub fn test_rpaths_to_flags() { + fn test_rpaths_to_flags() { let flags = rpaths_to_flags(~[Path("path1"), Path("path2")]); assert!(flags == ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]); } #[test] - pub fn test_prefix_rpath() { + fn test_prefix_rpath() { let res = get_install_prefix_rpath("triple"); let d = Path(env!("CFG_PREFIX")) .push_rel(&Path("lib/rustc/triple/lib")); @@ -230,13 +230,13 @@ mod test { } #[test] - pub fn test_prefix_rpath_abs() { + fn test_prefix_rpath_abs() { let res = get_install_prefix_rpath("triple"); assert!(res.is_absolute); } #[test] - pub fn test_minimize1() { + fn test_minimize1() { let res = minimize_rpaths([Path("rpath1"), Path("rpath2"), Path("rpath1")]); @@ -244,7 +244,7 @@ mod test { } #[test] - pub fn test_minimize2() { + fn test_minimize2() { let res = minimize_rpaths(~[Path("1a"), Path("2"), Path("2"), Path("1a"), Path("4a"),Path("1a"), Path("2"), Path("3"), Path("4a"), @@ -253,7 +253,7 @@ mod test { } #[test] - pub fn test_relative_to1() { + fn test_relative_to1() { let p1 = Path("/usr/bin/rustc"); let p2 = Path("/usr/lib/mylib"); let res = get_relative_to(&p1, &p2); @@ -261,7 +261,7 @@ mod test { } #[test] - pub fn test_relative_to2() { + fn test_relative_to2() { let p1 = Path("/usr/bin/rustc"); let p2 = Path("/usr/bin/../lib/mylib"); let res = get_relative_to(&p1, &p2); @@ -269,7 +269,7 @@ mod test { } #[test] - pub fn test_relative_to3() { + fn test_relative_to3() { let p1 = Path("/usr/bin/whatever/rustc"); let p2 = Path("/usr/lib/whatever/mylib"); let res = get_relative_to(&p1, &p2); @@ -277,7 +277,7 @@ mod test { } #[test] - pub fn test_relative_to4() { + fn test_relative_to4() { let p1 = Path("/usr/bin/whatever/../rustc"); let p2 = Path("/usr/lib/whatever/mylib"); let res = get_relative_to(&p1, &p2); @@ -285,7 +285,7 @@ mod test { } #[test] - pub fn test_relative_to5() { + fn test_relative_to5() { let p1 = Path("/usr/bin/whatever/../rustc"); let p2 = Path("/usr/lib/whatever/../mylib"); let res = get_relative_to(&p1, &p2); @@ -293,7 +293,7 @@ mod test { } #[test] - pub fn test_relative_to6() { + fn test_relative_to6() { let p1 = Path("/1"); let p2 = Path("/2/3"); let res = get_relative_to(&p1, &p2); @@ -301,7 +301,7 @@ mod test { } #[test] - pub fn test_relative_to7() { + fn test_relative_to7() { let p1 = Path("/1/2"); let p2 = Path("/3"); let res = get_relative_to(&p1, &p2); @@ -309,7 +309,7 @@ mod test { } #[test] - pub fn test_relative_to8() { + fn test_relative_to8() { let p1 = Path("/home/brian/Dev/rust/build/").push_rel( &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so")); let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel( @@ -324,7 +324,7 @@ mod test { #[test] #[cfg(target_os = "linux")] #[cfg(target_os = "andorid")] - pub fn test_rpath_relative() { + fn test_rpath_relative() { let o = session::os_linux; let res = get_rpath_relative_to_output(o, &Path("bin/rustc"), &Path("lib/libstd.so")); @@ -333,7 +333,7 @@ mod test { #[test] #[cfg(target_os = "freebsd")] - pub fn test_rpath_relative() { + fn test_rpath_relative() { let o = session::os_freebsd; let res = get_rpath_relative_to_output(o, &Path("bin/rustc"), &Path("lib/libstd.so")); @@ -342,7 +342,7 @@ mod test { #[test] #[cfg(target_os = "macos")] - pub fn test_rpath_relative() { + fn test_rpath_relative() { // this is why refinements would be nice let o = session::os_macos; let res = get_rpath_relative_to_output(o, @@ -352,7 +352,7 @@ mod test { } #[test] - pub fn test_get_absolute_rpath() { + fn test_get_absolute_rpath() { let res = get_absolute_rpath(&Path("lib/libstd.so")); debug!("test_get_absolute_rpath: %s vs. %s", res.to_str(), diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index d725b70003754..a804469ac6511 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -876,7 +876,7 @@ pub fn list_metadata(sess: Session, path: &Path, out: @io::Writer) { } #[cfg(test)] -pub mod test { +mod test { use core::prelude::*; use driver::driver::{build_configuration, build_session}; @@ -890,7 +890,7 @@ pub mod test { // When the user supplies --test we should implicitly supply --cfg test #[test] - pub fn test_switch_implies_cfg_test() { + fn test_switch_implies_cfg_test() { let matches = &match getopts(~[~"--test"], optgroups()) { Ok(copy m) => m, @@ -907,7 +907,7 @@ pub mod test { // When the user supplies --test and --cfg test, don't implicitly add // another --cfg test #[test] - pub fn test_switch_implies_cfg_test_unless_cfg_test() { + fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = &match getopts(~[~"--test", ~"--cfg=test"], optgroups()) { Ok(copy m) => m, diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 226905bbab728..aee5e01e09108 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -354,14 +354,14 @@ pub fn sess_os_to_meta_os(os: os) -> metadata::loader::os { } #[cfg(test)] -pub mod test { +mod test { use driver::session::{bin_crate, building_library, lib_crate}; use driver::session::{unknown_crate}; use syntax::ast; use syntax::codemap; - pub fn make_crate_type_attr(+t: ~str) -> ast::attribute { + fn make_crate_type_attr(+t: ~str) -> ast::attribute { codemap::respan(codemap::dummy_sp(), ast::attribute_ { style: ast::attr_outer, value: @codemap::respan(codemap::dummy_sp(), @@ -373,7 +373,7 @@ pub mod test { }) } - pub fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate { + fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate { let mut attrs = ~[]; if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; } if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; } @@ -385,43 +385,43 @@ pub mod test { } #[test] - pub fn bin_crate_type_attr_results_in_bin_output() { + fn bin_crate_type_attr_results_in_bin_output() { let crate = make_crate(true, false); assert!(!building_library(unknown_crate, crate, false)); } #[test] - pub fn lib_crate_type_attr_results_in_lib_output() { + fn lib_crate_type_attr_results_in_lib_output() { let crate = make_crate(false, true); assert!(building_library(unknown_crate, crate, false)); } #[test] - pub fn bin_option_overrides_lib_crate_type() { + fn bin_option_overrides_lib_crate_type() { let crate = make_crate(false, true); assert!(!building_library(bin_crate, crate, false)); } #[test] - pub fn lib_option_overrides_bin_crate_type() { + fn lib_option_overrides_bin_crate_type() { let crate = make_crate(true, false); assert!(building_library(lib_crate, crate, false)); } #[test] - pub fn bin_crate_type_is_default() { + fn bin_crate_type_is_default() { let crate = make_crate(false, false); assert!(!building_library(unknown_crate, crate, false)); } #[test] - pub fn test_option_overrides_lib_crate_type() { + fn test_option_overrides_lib_crate_type() { let crate = make_crate(false, true); assert!(!building_library(unknown_crate, crate, true)); } #[test] - pub fn test_option_does_not_override_requested_lib_type() { + fn test_option_does_not_override_requested_lib_type() { let crate = make_crate(false, false); assert!(building_library(lib_crate, crate, true)); } diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 585ce2dc81500..da1e4688939cc 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -492,7 +492,7 @@ mod tests { use core::vec; #[test] - pub fn manually_share_arc() { + fn manually_share_arc() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = arc::ARC(v); @@ -517,7 +517,7 @@ mod tests { } #[test] - pub fn test_mutex_arc_condvar() { + fn test_mutex_arc_condvar() { let arc = ~MutexARC(false); let arc2 = ~arc.clone(); let (p,c) = comm::oneshot(); @@ -539,7 +539,7 @@ mod tests { } } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_arc_condvar_poison() { + fn test_arc_condvar_poison() { let arc = ~MutexARC(1); let arc2 = ~arc.clone(); let (p, c) = comm::stream(); @@ -561,7 +561,7 @@ mod tests { } } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_mutex_arc_poison() { + fn test_mutex_arc_poison() { let arc = ~MutexARC(1); let arc2 = ~arc.clone(); do task::try || { @@ -574,7 +574,7 @@ mod tests { } } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_rw_arc_poison_wr() { + fn test_rw_arc_poison_wr() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -587,7 +587,7 @@ mod tests { } } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_rw_arc_poison_ww() { + fn test_rw_arc_poison_ww() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -600,7 +600,7 @@ mod tests { } } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_rw_arc_poison_dw() { + fn test_rw_arc_poison_dw() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -615,7 +615,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_rw_arc_no_poison_rr() { + fn test_rw_arc_no_poison_rr() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -628,7 +628,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_rw_arc_no_poison_rw() { + fn test_rw_arc_no_poison_rw() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -641,7 +641,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_rw_arc_no_poison_dr() { + fn test_rw_arc_no_poison_dr() { let arc = ~RWARC(1); let arc2 = (*arc).clone(); do task::try || { @@ -657,7 +657,7 @@ mod tests { } } #[test] - pub fn test_rw_arc() { + fn test_rw_arc() { let arc = ~RWARC(0); let arc2 = (*arc).clone(); let (p,c) = comm::stream(); @@ -694,7 +694,7 @@ mod tests { do arc.read |num| { assert!(*num == 10); } } #[test] - pub fn test_rw_downgrade() { + fn test_rw_downgrade() { // (1) A downgrader gets in write mode and does cond.wait. // (2) A writer gets in write mode, sets state to 42, and does signal. // (3) Downgrader wakes, sets state to 31337. diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 781a720b1a4db..c960c7186e3d2 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -154,7 +154,7 @@ mod tests { use core::str; #[test] - pub fn test_to_base64() { + fn test_to_base64() { assert!((~"").to_base64() == ~""); assert!((~"f").to_base64() == ~"Zg=="); assert!((~"fo").to_base64() == ~"Zm8="); @@ -165,7 +165,7 @@ mod tests { } #[test] - pub fn test_from_base64() { + fn test_from_base64() { assert!((~"").from_base64() == str::to_bytes(~"")); assert!((~"Zg==").from_base64() == str::to_bytes(~"f")); assert!((~"Zm8=").from_base64() == str::to_bytes(~"fo")); diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 632a38e8ca2d8..d89ce4232b175 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -880,7 +880,7 @@ mod tests { static bench_bits : uint = 1 << 14; #[test] - pub fn test_to_str() { + fn test_to_str() { let zerolen = Bitv::new(0u, false); assert!(zerolen.to_str() == ~""); @@ -889,7 +889,7 @@ mod tests { } #[test] - pub fn test_0_elements() { + fn test_0_elements() { let mut act; let mut exp; act = Bitv::new(0u, false); @@ -898,7 +898,7 @@ mod tests { } #[test] - pub fn test_1_element() { + fn test_1_element() { let mut act; act = Bitv::new(1u, false); assert!(act.eq_vec(~[0u])); @@ -907,7 +907,7 @@ mod tests { } #[test] - pub fn test_2_elements() { + fn test_2_elements() { let mut b = bitv::Bitv::new(2, false); b.set(0, true); b.set(1, false); @@ -915,7 +915,7 @@ mod tests { } #[test] - pub fn test_10_elements() { + fn test_10_elements() { let mut act; // all 0 @@ -954,7 +954,7 @@ mod tests { } #[test] - pub fn test_31_elements() { + fn test_31_elements() { let mut act; // all 0 @@ -1027,7 +1027,7 @@ mod tests { } #[test] - pub fn test_32_elements() { + fn test_32_elements() { let mut act; // all 0 @@ -1102,7 +1102,7 @@ mod tests { } #[test] - pub fn test_33_elements() { + fn test_33_elements() { let mut act; // all 0 @@ -1178,21 +1178,21 @@ mod tests { } #[test] - pub fn test_equal_differing_sizes() { + fn test_equal_differing_sizes() { let v0 = Bitv::new(10u, false); let v1 = Bitv::new(11u, false); assert!(!v0.equal(&v1)); } #[test] - pub fn test_equal_greatly_differing_sizes() { + fn test_equal_greatly_differing_sizes() { let v0 = Bitv::new(10u, false); let v1 = Bitv::new(110u, false); assert!(!v0.equal(&v1)); } #[test] - pub fn test_equal_sneaky_small() { + fn test_equal_sneaky_small() { let mut a = bitv::Bitv::new(1, false); a.set(0, true); @@ -1203,7 +1203,7 @@ mod tests { } #[test] - pub fn test_equal_sneaky_big() { + fn test_equal_sneaky_big() { let mut a = bitv::Bitv::new(100, false); for uint::range(0, 100) |i| { a.set(i, true); @@ -1218,14 +1218,14 @@ mod tests { } #[test] - pub fn test_from_bytes() { + fn test_from_bytes() { let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); let str = ~"10110110" + ~"00000000" + ~"11111111"; assert!(bitv.to_str() == str); } #[test] - pub fn test_to_bytes() { + fn test_to_bytes() { let mut bv = Bitv::new(3, true); bv.set(1, false); assert!(bv.to_bytes() == ~[0b10100000]); @@ -1237,19 +1237,19 @@ mod tests { } #[test] - pub fn test_from_bools() { + fn test_from_bools() { assert!(from_bools([true, false, true, true]).to_str() == ~"1011"); } #[test] - pub fn test_to_bools() { + fn test_to_bools() { let bools = ~[false, false, true, false, false, true, true, false]; assert!(from_bytes([0b00100110]).to_bools() == bools); } #[test] - pub fn test_small_difference() { + fn test_small_difference() { let mut b1 = Bitv::new(3, false); let mut b2 = Bitv::new(3, false); b1.set(0, true); @@ -1263,7 +1263,7 @@ mod tests { } #[test] - pub fn test_big_difference() { + fn test_big_difference() { let mut b1 = Bitv::new(100, false); let mut b2 = Bitv::new(100, false); b1.set(0, true); @@ -1277,7 +1277,7 @@ mod tests { } #[test] - pub fn test_small_clear() { + fn test_small_clear() { let mut b = Bitv::new(14, true); b.clear(); for b.ones |i| { @@ -1286,7 +1286,7 @@ mod tests { } #[test] - pub fn test_big_clear() { + fn test_big_clear() { let mut b = Bitv::new(140, true); b.clear(); for b.ones |i| { @@ -1295,7 +1295,7 @@ mod tests { } #[test] - pub fn test_bitv_set_basic() { + fn test_bitv_set_basic() { let mut b = BitvSet::new(); assert!(b.insert(3)); assert!(!b.insert(3)); @@ -1382,7 +1382,7 @@ mod tests { } #[test] - pub fn test_bitv_set_union() { + fn test_bitv_set_union() { let mut a = BitvSet::new(); let mut b = BitvSet::new(); assert!(a.insert(1)); @@ -1410,7 +1410,7 @@ mod tests { } #[test] - pub fn test_bitv_remove() { + fn test_bitv_remove() { let mut a = BitvSet::new(); assert!(a.insert(1)); @@ -1430,7 +1430,7 @@ mod tests { } #[bench] - pub fn bench_uint_small(b: &mut BenchHarness) { + fn bench_uint_small(b: &mut BenchHarness) { let r = rng(); let mut bitv = 0 as uint; do b.iter { @@ -1439,7 +1439,7 @@ mod tests { } #[bench] - pub fn bench_small_bitv_small(b: &mut BenchHarness) { + fn bench_small_bitv_small(b: &mut BenchHarness) { let r = rng(); let mut bitv = SmallBitv::new(uint::bits); do b.iter { @@ -1448,7 +1448,7 @@ mod tests { } #[bench] - pub fn bench_big_bitv_small(b: &mut BenchHarness) { + fn bench_big_bitv_small(b: &mut BenchHarness) { let r = rng(); let mut bitv = BigBitv::new(~[0]); do b.iter { @@ -1457,7 +1457,7 @@ mod tests { } #[bench] - pub fn bench_big_bitv_big(b: &mut BenchHarness) { + fn bench_big_bitv_big(b: &mut BenchHarness) { let r = rng(); let mut storage = ~[]; storage.grow(bench_bits / uint::bits, &0); @@ -1468,7 +1468,7 @@ mod tests { } #[bench] - pub fn bench_bitv_big(b: &mut BenchHarness) { + fn bench_bitv_big(b: &mut BenchHarness) { let r = rng(); let mut bitv = Bitv::new(bench_bits, false); do b.iter { @@ -1477,7 +1477,7 @@ mod tests { } #[bench] - pub fn bench_bitv_small(b: &mut BenchHarness) { + fn bench_bitv_small(b: &mut BenchHarness) { let r = rng(); let mut bitv = Bitv::new(uint::bits, false); do b.iter { @@ -1486,7 +1486,7 @@ mod tests { } #[bench] - pub fn bench_bitv_set_small(b: &mut BenchHarness) { + fn bench_bitv_set_small(b: &mut BenchHarness) { let r = rng(); let mut bitv = BitvSet::new(); do b.iter { @@ -1495,7 +1495,7 @@ mod tests { } #[bench] - pub fn bench_bitv_set_big(b: &mut BenchHarness) { + fn bench_bitv_set_big(b: &mut BenchHarness) { let r = rng(); let mut bitv = BitvSet::new(); do b.iter { @@ -1504,7 +1504,7 @@ mod tests { } #[bench] - pub fn bench_bitv_big_union(b: &mut BenchHarness) { + fn bench_bitv_big_union(b: &mut BenchHarness) { let mut b1 = Bitv::new(bench_bits, false); let mut b2 = Bitv::new(bench_bits, false); do b.iter { diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs index a490065b835c1..f9de2e0f58ad0 100644 --- a/src/libstd/dlist.rs +++ b/src/libstd/dlist.rs @@ -537,7 +537,7 @@ mod tests { use core::prelude::*; #[test] - pub fn test_dlist_concat() { + fn test_dlist_concat() { let a = from_vec(~[1,2]); let b = from_vec(~[3,4]); let c = from_vec(~[5,6]); @@ -557,7 +557,7 @@ mod tests { abcd.assert_consistent(); assert!(abcd.is_empty()); } #[test] - pub fn test_dlist_append() { + fn test_dlist_append() { let a = from_vec(~[1,2,3]); let b = from_vec(~[4,5,6]); a.append(b); @@ -573,7 +573,7 @@ mod tests { a.assert_consistent(); assert!(a.is_empty()); } #[test] - pub fn test_dlist_append_empty() { + fn test_dlist_append_empty() { let a = from_vec(~[1,2,3]); let b = DList::(); a.append(b); @@ -586,7 +586,7 @@ mod tests { a.assert_consistent(); assert!(a.is_empty()); } #[test] - pub fn test_dlist_append_to_empty() { + fn test_dlist_append_to_empty() { let a = DList::(); let b = from_vec(~[4,5,6]); a.append(b); @@ -599,7 +599,7 @@ mod tests { a.assert_consistent(); assert!(a.is_empty()); } #[test] - pub fn test_dlist_append_two_empty() { + fn test_dlist_append_two_empty() { let a = DList::(); let b = DList::(); a.append(b); @@ -611,19 +611,19 @@ mod tests { #[test] #[ignore(cfg(windows))] #[should_fail] - pub fn test_dlist_append_self() { + fn test_dlist_append_self() { let a = DList::(); a.append(a); } #[test] #[ignore(cfg(windows))] #[should_fail] - pub fn test_dlist_prepend_self() { + fn test_dlist_prepend_self() { let a = DList::(); a.prepend(a); } #[test] - pub fn test_dlist_prepend() { + fn test_dlist_prepend() { let a = from_vec(~[1,2,3]); let b = from_vec(~[4,5,6]); b.prepend(a); @@ -639,7 +639,7 @@ mod tests { b.assert_consistent(); assert!(b.is_empty()); } #[test] - pub fn test_dlist_reverse() { + fn test_dlist_reverse() { let a = from_vec(~[5,4,3,2,1]); a.reverse(); assert_eq!(a.len(), 5); @@ -651,14 +651,14 @@ mod tests { a.assert_consistent(); assert!(a.is_empty()); } #[test] - pub fn test_dlist_reverse_empty() { + fn test_dlist_reverse_empty() { let a = DList::(); a.reverse(); assert_eq!(a.len(), 0); a.assert_consistent(); } #[test] - pub fn test_dlist_each_node() { + fn test_dlist_each_node() { let a = from_vec(~[1,2,4,5]); for a.each_node |nobe| { if nobe.data > 3 { @@ -675,28 +675,28 @@ mod tests { a.assert_consistent(); assert!(a.is_empty()); } #[test] - pub fn test_dlist_clear() { + fn test_dlist_clear() { let a = from_vec(~[5,4,3,2,1]); a.clear(); assert_eq!(a.len(), 0); a.assert_consistent(); } #[test] - pub fn test_dlist_is_empty() { + fn test_dlist_is_empty() { let empty = DList::(); let full1 = from_vec(~[1,2,3]); assert!(empty.is_empty()); assert!(!full1.is_empty()); } #[test] - pub fn test_dlist_head_tail() { + fn test_dlist_head_tail() { let l = from_vec(~[1,2,3]); assert_eq!(l.head(), 1); assert_eq!(l.tail(), 3); assert_eq!(l.len(), 3); } #[test] - pub fn test_dlist_pop() { + fn test_dlist_pop() { let l = from_vec(~[1,2,3]); assert_eq!(l.pop().get(), 1); assert_eq!(l.tail(), 3); @@ -709,7 +709,7 @@ mod tests { assert!(l.pop().is_none()); } #[test] - pub fn test_dlist_pop_tail() { + fn test_dlist_pop_tail() { let l = from_vec(~[1,2,3]); assert_eq!(l.pop_tail().get(), 3); assert_eq!(l.tail(), 2); @@ -722,7 +722,7 @@ mod tests { assert!(l.pop_tail().is_none()); } #[test] - pub fn test_dlist_push() { + fn test_dlist_push() { let l = DList::(); l.push(1); assert_eq!(l.head(), 1); @@ -736,7 +736,7 @@ mod tests { assert_eq!(l.len(), 3); } #[test] - pub fn test_dlist_push_head() { + fn test_dlist_push_head() { let l = DList::(); l.push_head(3); assert_eq!(l.head(), 3); @@ -750,12 +750,12 @@ mod tests { assert_eq!(l.len(), 3); } #[test] - pub fn test_dlist_foldl() { + fn test_dlist_foldl() { let l = from_vec(vec::from_fn(101, |x|x)); assert_eq!(iter::foldl(&l, 0, |accum,elem| *accum+*elem), 5050); } #[test] - pub fn test_dlist_break_early() { + fn test_dlist_break_early() { let l = from_vec(~[1,2,3,4,5]); let mut x = 0; for l.each |i| { @@ -765,7 +765,7 @@ mod tests { assert_eq!(x, 3); } #[test] - pub fn test_dlist_remove_head() { + fn test_dlist_remove_head() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let _two = l.push_n(2); @@ -780,7 +780,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_mid() { + fn test_dlist_remove_mid() { let l = DList::(); l.assert_consistent(); let _one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -795,7 +795,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_tail() { + fn test_dlist_remove_tail() { let l = DList::(); l.assert_consistent(); let _one = l.push_n(1); l.assert_consistent(); let _two = l.push_n(2); @@ -810,7 +810,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_one_two() { + fn test_dlist_remove_one_two() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -826,7 +826,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_one_three() { + fn test_dlist_remove_one_three() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let _two = l.push_n(2); @@ -841,7 +841,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_two_three() { + fn test_dlist_remove_two_three() { let l = DList::(); l.assert_consistent(); let _one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -856,7 +856,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_remove_all() { + fn test_dlist_remove_all() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -869,7 +869,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_insert_n_before() { + fn test_dlist_insert_n_before() { let l = DList::(); l.assert_consistent(); let _one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -885,7 +885,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_insert_n_after() { + fn test_dlist_insert_n_after() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let _two = l.push_n(2); @@ -901,7 +901,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_insert_before_head() { + fn test_dlist_insert_before_head() { let l = DList::(); l.assert_consistent(); let one = l.push_n(1); l.assert_consistent(); let _two = l.push_n(2); @@ -916,7 +916,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] - pub fn test_dlist_insert_after_tail() { + fn test_dlist_insert_after_tail() { let l = DList::(); l.assert_consistent(); let _one = l.push_n(1); l.assert_consistent(); let two = l.push_n(2); @@ -931,7 +931,7 @@ mod tests { l.assert_consistent(); assert!(l.is_empty()); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_asymmetric_link() { + fn test_dlist_asymmetric_link() { let l = DList::(); let _one = l.push_n(1); let two = l.push_n(2); @@ -939,7 +939,7 @@ mod tests { l.assert_consistent(); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_cyclic_list() { + fn test_dlist_cyclic_list() { let l = DList::(); let one = l.push_n(1); let _two = l.push_n(2); @@ -949,32 +949,32 @@ mod tests { l.assert_consistent(); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_headless() { + fn test_dlist_headless() { DList::().head(); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_insert_already_present_before() { + fn test_dlist_insert_already_present_before() { let l = DList::(); let one = l.push_n(1); let two = l.push_n(2); l.insert_n_before(two, one); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_insert_already_present_after() { + fn test_dlist_insert_already_present_after() { let l = DList::(); let one = l.push_n(1); let two = l.push_n(2); l.insert_n_after(one, two); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_insert_before_orphan() { + fn test_dlist_insert_before_orphan() { let l = DList::(); let one = new_dlist_node(1); let two = new_dlist_node(2); l.insert_n_before(one, two); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_dlist_insert_after_orphan() { + fn test_dlist_insert_after_orphan() { let l = DList::(); let one = new_dlist_node(1); let two = new_dlist_node(2); diff --git a/src/libstd/future.rs b/src/libstd/future.rs index feea8fb4fcda7..a36f67fc95a00 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -172,7 +172,7 @@ pub fn spawn(blk: ~fn() -> A) -> Future { #[allow(non_implicitly_copyable_typarams)] #[cfg(test)] -pub mod test { +mod test { use core::prelude::*; use future::*; @@ -181,13 +181,13 @@ pub mod test { use core::task; #[test] - pub fn test_from_value() { + fn test_from_value() { let f = from_value(~"snail"); assert!(f.get() == ~"snail"); } #[test] - pub fn test_from_port() { + fn test_from_port() { let (ch, po) = oneshot::init(); send_one(ch, ~"whale"); let f = from_port(po); @@ -195,25 +195,25 @@ pub mod test { } #[test] - pub fn test_from_fn() { + fn test_from_fn() { let f = from_fn(|| ~"brail"); assert!(f.get() == ~"brail"); } #[test] - pub fn test_interface_get() { + fn test_interface_get() { let f = from_value(~"fail"); assert!(f.get() == ~"fail"); } #[test] - pub fn test_get_ref_method() { + fn test_get_ref_method() { let f = from_value(22); assert!(*f.get_ref() == 22); } #[test] - pub fn test_spawn() { + fn test_spawn() { let f = spawn(|| ~"bale"); assert!(f.get() == ~"bale"); } @@ -221,13 +221,13 @@ pub mod test { #[test] #[should_fail] #[ignore(cfg(target_os = "win32"))] - pub fn test_futurefail() { + fn test_futurefail() { let f = spawn(|| fail!()); let _x: ~str = f.get(); } #[test] - pub fn test_sendable_future() { + fn test_sendable_future() { let expected = ~"schlorf"; let f = do spawn { copy expected }; do task::spawn || { diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index b1e80718d8f74..d710a7b873548 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -662,7 +662,7 @@ mod tests { use core::result::{Err, Ok}; use core::result; - pub fn check_fail_type(f: Fail_, ft: FailType) { + fn check_fail_type(f: Fail_, ft: FailType) { match f { ArgumentMissing(_) => assert!(ft == ArgumentMissing_), UnrecognizedOption(_) => assert!(ft == UnrecognizedOption_), @@ -675,7 +675,7 @@ mod tests { // Tests for reqopt #[test] - pub fn test_reqopt_long() { + fn test_reqopt_long() { let args = ~[~"--test=20"]; let opts = ~[reqopt(~"test")]; let rs = getopts(args, opts); @@ -689,7 +689,7 @@ mod tests { } #[test] - pub fn test_reqopt_long_missing() { + fn test_reqopt_long_missing() { let args = ~[~"blah"]; let opts = ~[reqopt(~"test")]; let rs = getopts(args, opts); @@ -700,7 +700,7 @@ mod tests { } #[test] - pub fn test_reqopt_long_no_arg() { + fn test_reqopt_long_no_arg() { let args = ~[~"--test"]; let opts = ~[reqopt(~"test")]; let rs = getopts(args, opts); @@ -711,7 +711,7 @@ mod tests { } #[test] - pub fn test_reqopt_long_multi() { + fn test_reqopt_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; let opts = ~[reqopt(~"test")]; let rs = getopts(args, opts); @@ -722,7 +722,7 @@ mod tests { } #[test] - pub fn test_reqopt_short() { + fn test_reqopt_short() { let args = ~[~"-t", ~"20"]; let opts = ~[reqopt(~"t")]; let rs = getopts(args, opts); @@ -736,7 +736,7 @@ mod tests { } #[test] - pub fn test_reqopt_short_missing() { + fn test_reqopt_short_missing() { let args = ~[~"blah"]; let opts = ~[reqopt(~"t")]; let rs = getopts(args, opts); @@ -747,7 +747,7 @@ mod tests { } #[test] - pub fn test_reqopt_short_no_arg() { + fn test_reqopt_short_no_arg() { let args = ~[~"-t"]; let opts = ~[reqopt(~"t")]; let rs = getopts(args, opts); @@ -758,7 +758,7 @@ mod tests { } #[test] - pub fn test_reqopt_short_multi() { + fn test_reqopt_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; let opts = ~[reqopt(~"t")]; let rs = getopts(args, opts); @@ -771,7 +771,7 @@ mod tests { // Tests for optopt #[test] - pub fn test_optopt_long() { + fn test_optopt_long() { let args = ~[~"--test=20"]; let opts = ~[optopt(~"test")]; let rs = getopts(args, opts); @@ -785,7 +785,7 @@ mod tests { } #[test] - pub fn test_optopt_long_missing() { + fn test_optopt_long_missing() { let args = ~[~"blah"]; let opts = ~[optopt(~"test")]; let rs = getopts(args, opts); @@ -796,7 +796,7 @@ mod tests { } #[test] - pub fn test_optopt_long_no_arg() { + fn test_optopt_long_no_arg() { let args = ~[~"--test"]; let opts = ~[optopt(~"test")]; let rs = getopts(args, opts); @@ -807,7 +807,7 @@ mod tests { } #[test] - pub fn test_optopt_long_multi() { + fn test_optopt_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; let opts = ~[optopt(~"test")]; let rs = getopts(args, opts); @@ -818,7 +818,7 @@ mod tests { } #[test] - pub fn test_optopt_short() { + fn test_optopt_short() { let args = ~[~"-t", ~"20"]; let opts = ~[optopt(~"t")]; let rs = getopts(args, opts); @@ -832,7 +832,7 @@ mod tests { } #[test] - pub fn test_optopt_short_missing() { + fn test_optopt_short_missing() { let args = ~[~"blah"]; let opts = ~[optopt(~"t")]; let rs = getopts(args, opts); @@ -843,7 +843,7 @@ mod tests { } #[test] - pub fn test_optopt_short_no_arg() { + fn test_optopt_short_no_arg() { let args = ~[~"-t"]; let opts = ~[optopt(~"t")]; let rs = getopts(args, opts); @@ -854,7 +854,7 @@ mod tests { } #[test] - pub fn test_optopt_short_multi() { + fn test_optopt_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; let opts = ~[optopt(~"t")]; let rs = getopts(args, opts); @@ -867,7 +867,7 @@ mod tests { // Tests for optflag #[test] - pub fn test_optflag_long() { + fn test_optflag_long() { let args = ~[~"--test"]; let opts = ~[optflag(~"test")]; let rs = getopts(args, opts); @@ -878,7 +878,7 @@ mod tests { } #[test] - pub fn test_optflag_long_missing() { + fn test_optflag_long_missing() { let args = ~[~"blah"]; let opts = ~[optflag(~"test")]; let rs = getopts(args, opts); @@ -889,7 +889,7 @@ mod tests { } #[test] - pub fn test_optflag_long_arg() { + fn test_optflag_long_arg() { let args = ~[~"--test=20"]; let opts = ~[optflag(~"test")]; let rs = getopts(args, opts); @@ -903,7 +903,7 @@ mod tests { } #[test] - pub fn test_optflag_long_multi() { + fn test_optflag_long_multi() { let args = ~[~"--test", ~"--test"]; let opts = ~[optflag(~"test")]; let rs = getopts(args, opts); @@ -914,7 +914,7 @@ mod tests { } #[test] - pub fn test_optflag_short() { + fn test_optflag_short() { let args = ~[~"-t"]; let opts = ~[optflag(~"t")]; let rs = getopts(args, opts); @@ -925,7 +925,7 @@ mod tests { } #[test] - pub fn test_optflag_short_missing() { + fn test_optflag_short_missing() { let args = ~[~"blah"]; let opts = ~[optflag(~"t")]; let rs = getopts(args, opts); @@ -936,7 +936,7 @@ mod tests { } #[test] - pub fn test_optflag_short_arg() { + fn test_optflag_short_arg() { let args = ~[~"-t", ~"20"]; let opts = ~[optflag(~"t")]; let rs = getopts(args, opts); @@ -951,7 +951,7 @@ mod tests { } #[test] - pub fn test_optflag_short_multi() { + fn test_optflag_short_multi() { let args = ~[~"-t", ~"-t"]; let opts = ~[optflag(~"t")]; let rs = getopts(args, opts); @@ -963,7 +963,7 @@ mod tests { // Tests for optflagmulti #[test] - pub fn test_optflagmulti_short1() { + fn test_optflagmulti_short1() { let args = ~[~"-v"]; let opts = ~[optflagmulti(~"v")]; let rs = getopts(args, opts); @@ -976,7 +976,7 @@ mod tests { } #[test] - pub fn test_optflagmulti_short2a() { + fn test_optflagmulti_short2a() { let args = ~[~"-v", ~"-v"]; let opts = ~[optflagmulti(~"v")]; let rs = getopts(args, opts); @@ -989,7 +989,7 @@ mod tests { } #[test] - pub fn test_optflagmulti_short2b() { + fn test_optflagmulti_short2b() { let args = ~[~"-vv"]; let opts = ~[optflagmulti(~"v")]; let rs = getopts(args, opts); @@ -1002,7 +1002,7 @@ mod tests { } #[test] - pub fn test_optflagmulti_long1() { + fn test_optflagmulti_long1() { let args = ~[~"--verbose"]; let opts = ~[optflagmulti(~"verbose")]; let rs = getopts(args, opts); @@ -1015,7 +1015,7 @@ mod tests { } #[test] - pub fn test_optflagmulti_long2() { + fn test_optflagmulti_long2() { let args = ~[~"--verbose", ~"--verbose"]; let opts = ~[optflagmulti(~"verbose")]; let rs = getopts(args, opts); @@ -1029,7 +1029,7 @@ mod tests { // Tests for optmulti #[test] - pub fn test_optmulti_long() { + fn test_optmulti_long() { let args = ~[~"--test=20"]; let opts = ~[optmulti(~"test")]; let rs = getopts(args, opts); @@ -1043,7 +1043,7 @@ mod tests { } #[test] - pub fn test_optmulti_long_missing() { + fn test_optmulti_long_missing() { let args = ~[~"blah"]; let opts = ~[optmulti(~"test")]; let rs = getopts(args, opts); @@ -1054,7 +1054,7 @@ mod tests { } #[test] - pub fn test_optmulti_long_no_arg() { + fn test_optmulti_long_no_arg() { let args = ~[~"--test"]; let opts = ~[optmulti(~"test")]; let rs = getopts(args, opts); @@ -1065,7 +1065,7 @@ mod tests { } #[test] - pub fn test_optmulti_long_multi() { + fn test_optmulti_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; let opts = ~[optmulti(~"test")]; let rs = getopts(args, opts); @@ -1082,7 +1082,7 @@ mod tests { } #[test] - pub fn test_optmulti_short() { + fn test_optmulti_short() { let args = ~[~"-t", ~"20"]; let opts = ~[optmulti(~"t")]; let rs = getopts(args, opts); @@ -1096,7 +1096,7 @@ mod tests { } #[test] - pub fn test_optmulti_short_missing() { + fn test_optmulti_short_missing() { let args = ~[~"blah"]; let opts = ~[optmulti(~"t")]; let rs = getopts(args, opts); @@ -1107,7 +1107,7 @@ mod tests { } #[test] - pub fn test_optmulti_short_no_arg() { + fn test_optmulti_short_no_arg() { let args = ~[~"-t"]; let opts = ~[optmulti(~"t")]; let rs = getopts(args, opts); @@ -1118,7 +1118,7 @@ mod tests { } #[test] - pub fn test_optmulti_short_multi() { + fn test_optmulti_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; let opts = ~[optmulti(~"t")]; let rs = getopts(args, opts); @@ -1135,7 +1135,7 @@ mod tests { } #[test] - pub fn test_unrecognized_option_long() { + fn test_unrecognized_option_long() { let args = ~[~"--untest"]; let opts = ~[optmulti(~"t")]; let rs = getopts(args, opts); @@ -1146,7 +1146,7 @@ mod tests { } #[test] - pub fn test_unrecognized_option_short() { + fn test_unrecognized_option_short() { let args = ~[~"-t"]; let opts = ~[optmulti(~"test")]; let rs = getopts(args, opts); @@ -1157,7 +1157,7 @@ mod tests { } #[test] - pub fn test_combined() { + fn test_combined() { let args = ~[~"prog", ~"free1", ~"-s", ~"20", ~"free2", ~"--flag", ~"--long=30", ~"-f", ~"-m", ~"40", @@ -1189,7 +1189,7 @@ mod tests { } #[test] - pub fn test_multi() { + fn test_multi() { let args = ~[~"-e", ~"foo", ~"--encrypt", ~"foo"]; let opts = ~[optopt(~"e"), optopt(~"encrypt"), optopt(~"f")]; let matches = &match getopts(args, opts) { @@ -1211,7 +1211,7 @@ mod tests { } #[test] - pub fn test_nospace() { + fn test_nospace() { let args = ~[~"-Lfoo", ~"-M."]; let opts = ~[optmulti(~"L"), optmulti(~"M")]; let matches = &match getopts(args, opts) { @@ -1226,7 +1226,7 @@ mod tests { } #[test] - pub fn test_groups_reqopt() { + fn test_groups_reqopt() { let opt = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL"); assert!(opt == OptGroup { short_name: ~"b", long_name: ~"banana", @@ -1237,7 +1237,7 @@ mod tests { } #[test] - pub fn test_groups_optopt() { + fn test_groups_optopt() { let opt = groups::optopt(~"a", ~"apple", ~"some apples", ~"VAL"); assert!(opt == OptGroup { short_name: ~"a", long_name: ~"apple", @@ -1248,7 +1248,7 @@ mod tests { } #[test] - pub fn test_groups_optflag() { + fn test_groups_optflag() { let opt = groups::optflag(~"k", ~"kiwi", ~"some kiwis"); assert!(opt == OptGroup { short_name: ~"k", long_name: ~"kiwi", @@ -1259,7 +1259,7 @@ mod tests { } #[test] - pub fn test_groups_optflagopt() { + fn test_groups_optflagopt() { let opt = groups::optflagopt(~"p", ~"pineapple", ~"some pineapples", ~"VAL"); assert!(opt == OptGroup { short_name: ~"p", @@ -1271,7 +1271,7 @@ mod tests { } #[test] - pub fn test_groups_optmulti() { + fn test_groups_optmulti() { let opt = groups::optmulti(~"l", ~"lime", ~"some limes", ~"VAL"); assert!(opt == OptGroup { short_name: ~"l", @@ -1283,7 +1283,7 @@ mod tests { } #[test] - pub fn test_groups_long_to_short() { + fn test_groups_long_to_short() { let short = ~[reqopt(~"b"), reqopt(~"banana")]; let verbose = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL"); @@ -1292,7 +1292,7 @@ mod tests { } #[test] - pub fn test_groups_getopts() { + fn test_groups_getopts() { let short = ~[ reqopt(~"b"), reqopt(~"banana"), optopt(~"a"), optopt(~"apple"), @@ -1318,7 +1318,7 @@ mod tests { } #[test] - pub fn test_groups_usage() { + fn test_groups_usage() { let optgroups = ~[ groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), groups::optopt(~"a", ~"012345678901234567890123456789", @@ -1349,7 +1349,7 @@ Options: } #[test] - pub fn test_groups_usage_description_wrapping() { + fn test_groups_usage_description_wrapping() { // indentation should be 24 spaces // lines wrap after 78: or rather descriptions wrap after 54 diff --git a/src/libstd/list.rs b/src/libstd/list.rs index 63d461ed4d3bf..8e173ff8a9c6a 100644 --- a/src/libstd/list.rs +++ b/src/libstd/list.rs @@ -160,7 +160,7 @@ mod tests { use core::option; #[test] - pub fn test_is_empty() { + fn test_is_empty() { let empty : @list::List = from_vec(~[]); let full1 = from_vec(~[1]); let full2 = from_vec(~['r', 'u']); @@ -171,7 +171,7 @@ mod tests { } #[test] - pub fn test_from_vec() { + fn test_from_vec() { let l = from_vec(~[0, 1, 2]); assert!((head(l) == 0)); @@ -184,13 +184,13 @@ mod tests { } #[test] - pub fn test_from_vec_empty() { + fn test_from_vec_empty() { let empty : @list::List = from_vec(~[]); assert!((empty == @list::Nil::)); } #[test] - pub fn test_foldl() { + fn test_foldl() { fn add(a: &uint, b: &int) -> uint { return *a + (*b as uint); } let l = from_vec(~[0, 1, 2, 3, 4]); let empty = @list::Nil::; @@ -199,7 +199,7 @@ mod tests { } #[test] - pub fn test_foldl2() { + fn test_foldl2() { fn sub(a: &int, b: &int) -> int { *a - *b } @@ -208,14 +208,14 @@ mod tests { } #[test] - pub fn test_find_success() { + fn test_find_success() { fn match_(i: &int) -> bool { return *i == 2; } let l = from_vec(~[0, 1, 2]); assert!((list::find(l, match_) == option::Some(2))); } #[test] - pub fn test_find_fail() { + fn test_find_fail() { fn match_(_i: &int) -> bool { return false; } let l = from_vec(~[0, 1, 2]); let empty = @list::Nil::; @@ -224,7 +224,7 @@ mod tests { } #[test] - pub fn test_has() { + fn test_has() { let l = from_vec(~[5, 8, 6]); let empty = @list::Nil::; assert!((list::has(l, 5))); @@ -234,7 +234,7 @@ mod tests { } #[test] - pub fn test_len() { + fn test_len() { let l = from_vec(~[0, 1, 2]); let empty = @list::Nil::; assert!((list::len(l) == 3u)); @@ -242,7 +242,7 @@ mod tests { } #[test] - pub fn test_append() { + fn test_append() { assert!(from_vec(~[1,2,3,4]) == list::append(list::from_vec(~[1,2]), list::from_vec(~[3,4]))); } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index a8b2723bcfbc4..b32df75063d97 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1426,7 +1426,7 @@ struct TcpBufferedSocketData { } #[cfg(test)] -pub mod test { +mod test { use net::ip; use net::tcp::{GenericListenErr, TcpConnectErrData, TcpListenErrData}; use net::tcp::{connect, accept, read, listen, TcpSocket, socket_buf}; @@ -1447,9 +1447,9 @@ pub mod test { #[cfg(target_os="darwin")] #[cfg(target_os="linux")] #[cfg(target_os="android")] - pub mod tcp_ipv4_server_and_client_test { + mod tcp_ipv4_server_and_client_test { #[cfg(target_arch="x86_64")] - pub mod impl64 { + mod impl64 { use net::tcp::test::*; #[test] @@ -1497,7 +1497,7 @@ pub mod test { #[cfg(target_arch="x86")] #[cfg(target_arch="arm")] #[cfg(target_arch="mips")] - pub mod impl32 { + mod impl32 { use net::tcp::test::*; #[test] diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index 9b8b0f9be0bcd..4cb9a98036b19 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -810,7 +810,7 @@ mod tests { use core::hashmap::HashMap; #[test] - pub fn test_url_parse() { + fn test_url_parse() { let url = ~"http://user:pass@rust-lang.org/doc?s=v#something"; let up = from_str(url); @@ -826,7 +826,7 @@ mod tests { } #[test] - pub fn test_url_parse_host_slash() { + fn test_url_parse_host_slash() { let urlstr = ~"http://0.42.42.42/"; let url = from_str(urlstr).unwrap(); assert!(url.host == ~"0.42.42.42"); @@ -834,87 +834,87 @@ mod tests { } #[test] - pub fn test_url_with_underscores() { + fn test_url_with_underscores() { let urlstr = ~"http://dotcom.com/file_name.html"; let url = from_str(urlstr).unwrap(); assert!(url.path == ~"/file_name.html"); } #[test] - pub fn test_url_with_dashes() { + fn test_url_with_dashes() { let urlstr = ~"http://dotcom.com/file-name.html"; let url = from_str(urlstr).unwrap(); assert!(url.path == ~"/file-name.html"); } #[test] - pub fn test_no_scheme() { + fn test_no_scheme() { assert!(get_scheme("noschemehere.html").is_err()); } #[test] - pub fn test_invalid_scheme_errors() { + fn test_invalid_scheme_errors() { assert!(from_str("99://something").is_err()); assert!(from_str("://something").is_err()); } #[test] - pub fn test_full_url_parse_and_format() { + fn test_full_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?s=v#something"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_userless_url_parse_and_format() { + fn test_userless_url_parse_and_format() { let url = ~"http://rust-lang.org/doc?s=v#something"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_queryless_url_parse_and_format() { + fn test_queryless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc#something"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_empty_query_url_parse_and_format() { + fn test_empty_query_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?#something"; let should_be = ~"http://user:pass@rust-lang.org/doc#something"; assert!(from_str(url).unwrap().to_str() == should_be); } #[test] - pub fn test_fragmentless_url_parse_and_format() { + fn test_fragmentless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?q=v"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_minimal_url_parse_and_format() { + fn test_minimal_url_parse_and_format() { let url = ~"http://rust-lang.org/doc"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_scheme_host_only_url_parse_and_format() { + fn test_scheme_host_only_url_parse_and_format() { let url = ~"http://rust-lang.org"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_pathless_url_parse_and_format() { + fn test_pathless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org?q=v#something"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_scheme_host_fragment_only_url_parse_and_format() { + fn test_scheme_host_fragment_only_url_parse_and_format() { let url = ~"http://rust-lang.org#something"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_url_component_encoding() { + fn test_url_component_encoding() { let url = ~"http://rust-lang.org/doc%20uments?ba%25d%20=%23%26%2B"; let u = from_str(url).unwrap(); assert!(u.path == ~"/doc uments"); @@ -922,13 +922,13 @@ mod tests { } #[test] - pub fn test_url_without_authority() { + fn test_url_without_authority() { let url = ~"mailto:test@email.com"; assert!(from_str(url).unwrap().to_str() == url); } #[test] - pub fn test_encode() { + fn test_encode() { assert!(encode("") == ~""); assert!(encode("http://example.com") == ~"http://example.com"); assert!(encode("foo bar% baz") == ~"foo%20bar%25%20baz"); @@ -956,7 +956,7 @@ mod tests { } #[test] - pub fn test_encode_component() { + fn test_encode_component() { assert!(encode_component("") == ~""); assert!(encode_component("http://example.com") == ~"http%3A%2F%2Fexample.com"); @@ -985,7 +985,7 @@ mod tests { } #[test] - pub fn test_decode() { + fn test_decode() { assert!(decode("") == ~""); assert!(decode("abc/def 123") == ~"abc/def 123"); assert!(decode("abc%2Fdef%20123") == ~"abc%2Fdef 123"); @@ -1013,7 +1013,7 @@ mod tests { } #[test] - pub fn test_decode_component() { + fn test_decode_component() { assert!(decode_component("") == ~""); assert!(decode_component("abc/def 123") == ~"abc/def 123"); assert!(decode_component("abc%2Fdef%20123") == ~"abc/def 123"); @@ -1041,7 +1041,7 @@ mod tests { } #[test] - pub fn test_encode_form_urlencoded() { + fn test_encode_form_urlencoded() { let mut m = HashMap::new(); assert!(encode_form_urlencoded(&m) == ~""); @@ -1060,7 +1060,7 @@ mod tests { } #[test] - pub fn test_decode_form_urlencoded() { + fn test_decode_form_urlencoded() { // FIXME #4449: Commented out because this causes an ICE, but only // on FreeBSD /* diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index f5f7f5e326a79..6aa4d1c54bc9e 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -282,7 +282,7 @@ mod tests { use core::vec; #[test] - pub fn test() { + fn test() { struct Test { input: ~str, output: ~[u8], diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 39ca9bb5ba66f..72a888fcc917b 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -733,7 +733,7 @@ mod test_qsort3 { use core::vec; - pub fn check_sort(v1: &mut [int], v2: &mut [int]) { + fn check_sort(v1: &mut [int], v2: &mut [int]) { let len = vec::len::(v1); quick_sort3::(v1); let mut i = 0; @@ -745,7 +745,7 @@ mod test_qsort3 { } #[test] - pub fn test() { + fn test() { { let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; @@ -777,7 +777,7 @@ mod test_qsort { use core::int; use core::vec; - pub fn check_sort(v1: &mut [int], v2: &mut [int]) { + fn check_sort(v1: &mut [int], v2: &mut [int]) { let len = vec::len::(v1); fn leual(a: &int, b: &int) -> bool { *a <= *b } quick_sort::(v1, leual); @@ -790,7 +790,7 @@ mod test_qsort { } #[test] - pub fn test() { + fn test() { { let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; @@ -816,7 +816,7 @@ mod test_qsort { // Regression test for #750 #[test] - pub fn test_simple() { + fn test_simple() { let mut names = ~[2, 1, 3]; let expected = ~[1, 2, 3]; @@ -842,7 +842,7 @@ mod tests { use core::vec; - pub fn check_sort(v1: &[int], v2: &[int]) { + fn check_sort(v1: &[int], v2: &[int]) { let len = vec::len::(v1); pub fn le(a: &int, b: &int) -> bool { *a <= *b } let f = le; @@ -856,7 +856,7 @@ mod tests { } #[test] - pub fn test() { + fn test() { { let v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; let v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; @@ -873,7 +873,7 @@ mod tests { } #[test] - pub fn test_merge_sort_mutable() { + fn test_merge_sort_mutable() { pub fn le(a: &int, b: &int) -> bool { *a <= *b } let mut v1 = ~[3, 2, 1]; let v2 = merge_sort(v1, le); @@ -881,7 +881,7 @@ mod tests { } #[test] - pub fn test_merge_sort_stability() { + fn test_merge_sort_stability() { // tjc: funny that we have to use parens fn ile(x: &(&'static str), y: &(&'static str)) -> bool { diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index f2de8213a1b9e..971bb51f7e9f4 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -728,19 +728,19 @@ mod tests { * Semaphore tests ************************************************************************/ #[test] - pub fn test_sem_acquire_release() { + fn test_sem_acquire_release() { let s = ~semaphore(1); s.acquire(); s.release(); s.acquire(); } #[test] - pub fn test_sem_basic() { + fn test_sem_basic() { let s = ~semaphore(1); do s.access { } } #[test] - pub fn test_sem_as_mutex() { + fn test_sem_as_mutex() { let s = ~semaphore(1); let s2 = ~s.clone(); do task::spawn || { @@ -753,7 +753,7 @@ mod tests { } } #[test] - pub fn test_sem_as_cvar() { + fn test_sem_as_cvar() { /* Child waits and parent signals */ let (p,c) = comm::stream(); let s = ~semaphore(0); @@ -779,7 +779,7 @@ mod tests { c.send(()); } #[test] - pub fn test_sem_multi_resource() { + fn test_sem_multi_resource() { // Parent and child both get in the critical section at the same // time, and shake hands. let s = ~semaphore(2); @@ -798,7 +798,7 @@ mod tests { } } #[test] - pub fn test_sem_runtime_friendly_blocking() { + fn test_sem_runtime_friendly_blocking() { // Force the runtime to schedule two threads on the same sched_loop. // When one blocks, it should schedule the other one. do task::spawn_sched(task::ManualThreads(1)) { @@ -823,7 +823,7 @@ mod tests { * Mutex tests ************************************************************************/ #[test] - pub fn test_mutex_lock() { + fn test_mutex_lock() { // Unsafely achieve shared state, and do the textbook // "load tmp = move ptr; inc tmp; store ptr <- tmp" dance. let (p,c) = comm::stream(); @@ -854,7 +854,7 @@ mod tests { } } #[test] - pub fn test_mutex_cond_wait() { + fn test_mutex_cond_wait() { let m = ~Mutex(); // Child wakes up parent @@ -886,7 +886,7 @@ mod tests { let _ = port.recv(); // Wait until child wakes up } #[cfg(test)] - pub fn test_mutex_cond_broadcast_helper(num_waiters: uint) { + fn test_mutex_cond_broadcast_helper(num_waiters: uint) { let m = ~Mutex(); let mut ports = ~[]; @@ -913,15 +913,15 @@ mod tests { for ports.each |port| { let _ = port.recv(); } } #[test] - pub fn test_mutex_cond_broadcast() { + fn test_mutex_cond_broadcast() { test_mutex_cond_broadcast_helper(12); } #[test] - pub fn test_mutex_cond_broadcast_none() { + fn test_mutex_cond_broadcast_none() { test_mutex_cond_broadcast_helper(0); } #[test] - pub fn test_mutex_cond_no_waiter() { + fn test_mutex_cond_no_waiter() { let m = ~Mutex(); let m2 = ~m.clone(); do task::try || { @@ -932,7 +932,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_mutex_killed_simple() { + fn test_mutex_killed_simple() { // Mutex must get automatically unlocked if failed/killed within. let m = ~Mutex(); let m2 = ~m.clone(); @@ -947,7 +947,7 @@ mod tests { do m.lock { } } #[test] #[ignore(cfg(windows))] - pub fn test_mutex_killed_cond() { + fn test_mutex_killed_cond() { // Getting killed during cond wait must not corrupt the mutex while // unwinding (e.g. double unlock). let m = ~Mutex(); @@ -973,7 +973,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_mutex_killed_broadcast() { + fn test_mutex_killed_broadcast() { let m = ~Mutex(); let m2 = ~m.clone(); let (p,c) = comm::stream(); @@ -1026,7 +1026,7 @@ mod tests { } } #[test] - pub fn test_mutex_cond_signal_on_0() { + fn test_mutex_cond_signal_on_0() { // Tests that signal_on(0) is equivalent to signal(). let m = ~Mutex(); do m.lock_cond |cond| { @@ -1040,7 +1040,7 @@ mod tests { } } #[test] #[ignore(cfg(windows))] - pub fn test_mutex_different_conds() { + fn test_mutex_different_conds() { let result = do task::try { let m = ~mutex_with_condvars(2); let m2 = ~m.clone(); @@ -1061,7 +1061,7 @@ mod tests { assert!(result.is_err()); } #[test] #[ignore(cfg(windows))] - pub fn test_mutex_no_condvars() { + fn test_mutex_no_condvars() { let result = do task::try { let m = ~mutex_with_condvars(0); do m.lock_cond |cond| { cond.wait(); } @@ -1084,7 +1084,7 @@ mod tests { #[cfg(test)] pub enum RWlockMode { Read, Write, Downgrade, DowngradeRead } #[cfg(test)] - pub fn lock_rwlock_in_mode(x: &RWlock, mode: RWlockMode, blk: &fn()) { + fn lock_rwlock_in_mode(x: &RWlock, mode: RWlockMode, blk: &fn()) { match mode { Read => x.read(blk), Write => x.write(blk), @@ -1100,7 +1100,7 @@ mod tests { } } #[cfg(test)] - pub fn test_rwlock_exclusion(x: ~RWlock, + fn test_rwlock_exclusion(x: ~RWlock, mode1: RWlockMode, mode2: RWlockMode) { // Test mutual exclusion between readers and writers. Just like the @@ -1132,21 +1132,21 @@ mod tests { } } #[test] - pub fn test_rwlock_readers_wont_modify_the_data() { + fn test_rwlock_readers_wont_modify_the_data() { test_rwlock_exclusion(~RWlock(), Read, Write); test_rwlock_exclusion(~RWlock(), Write, Read); test_rwlock_exclusion(~RWlock(), Read, Downgrade); test_rwlock_exclusion(~RWlock(), Downgrade, Read); } #[test] - pub fn test_rwlock_writers_and_writers() { + fn test_rwlock_writers_and_writers() { test_rwlock_exclusion(~RWlock(), Write, Write); test_rwlock_exclusion(~RWlock(), Write, Downgrade); test_rwlock_exclusion(~RWlock(), Downgrade, Write); test_rwlock_exclusion(~RWlock(), Downgrade, Downgrade); } #[cfg(test)] - pub fn test_rwlock_handshake(x: ~RWlock, + fn test_rwlock_handshake(x: ~RWlock, mode1: RWlockMode, mode2: RWlockMode, make_mode2_go_first: bool) { @@ -1178,7 +1178,7 @@ mod tests { } } #[test] - pub fn test_rwlock_readers_and_readers() { + fn test_rwlock_readers_and_readers() { test_rwlock_handshake(~RWlock(), Read, Read, false); // The downgrader needs to get in before the reader gets in, otherwise // they cannot end up reading at the same time. @@ -1187,7 +1187,7 @@ mod tests { // Two downgrade_reads can never both end up reading at the same time. } #[test] - pub fn test_rwlock_downgrade_unlock() { + fn test_rwlock_downgrade_unlock() { // Tests that downgrade can unlock the lock in both modes let x = ~RWlock(); do lock_rwlock_in_mode(x, Downgrade) { } @@ -1197,12 +1197,12 @@ mod tests { test_rwlock_exclusion(y, Write, Write); } #[test] - pub fn test_rwlock_read_recursive() { + fn test_rwlock_read_recursive() { let x = ~RWlock(); do x.read { do x.read { } } } #[test] - pub fn test_rwlock_cond_wait() { + fn test_rwlock_cond_wait() { // As test_mutex_cond_wait above. let x = ~RWlock(); @@ -1237,7 +1237,7 @@ mod tests { do x.read { } // Just for good measure } #[cfg(test)] - pub fn test_rwlock_cond_broadcast_helper(num_waiters: uint, + fn test_rwlock_cond_broadcast_helper(num_waiters: uint, dg1: bool, dg2: bool) { // Much like the mutex broadcast test. Downgrade-enabled. @@ -1276,7 +1276,7 @@ mod tests { for ports.each |port| { let _ = port.recv(); } } #[test] - pub fn test_rwlock_cond_broadcast() { + fn test_rwlock_cond_broadcast() { test_rwlock_cond_broadcast_helper(0, true, true); test_rwlock_cond_broadcast_helper(0, true, false); test_rwlock_cond_broadcast_helper(0, false, true); @@ -1287,7 +1287,7 @@ mod tests { test_rwlock_cond_broadcast_helper(12, false, false); } #[cfg(test)] #[ignore(cfg(windows))] - pub fn rwlock_kill_helper(mode1: RWlockMode, mode2: RWlockMode) { + fn rwlock_kill_helper(mode1: RWlockMode, mode2: RWlockMode) { // Mutex must get automatically unlocked if failed/killed within. let x = ~RWlock(); let x2 = (*x).clone(); @@ -1302,23 +1302,23 @@ mod tests { do lock_rwlock_in_mode(x, mode2) { } } #[test] #[ignore(cfg(windows))] - pub fn test_rwlock_reader_killed_writer() { + fn test_rwlock_reader_killed_writer() { rwlock_kill_helper(Read, Write); } #[test] #[ignore(cfg(windows))] - pub fn test_rwlock_writer_killed_reader() { + fn test_rwlock_writer_killed_reader() { rwlock_kill_helper(Write,Read ); } #[test] #[ignore(cfg(windows))] - pub fn test_rwlock_reader_killed_reader() { + fn test_rwlock_reader_killed_reader() { rwlock_kill_helper(Read, Read ); } #[test] #[ignore(cfg(windows))] - pub fn test_rwlock_writer_killed_writer() { + fn test_rwlock_writer_killed_writer() { rwlock_kill_helper(Write,Write); } #[test] #[ignore(cfg(windows))] - pub fn test_rwlock_kill_downgrader() { + fn test_rwlock_kill_downgrader() { rwlock_kill_helper(Downgrade, Read); rwlock_kill_helper(Read, Downgrade); rwlock_kill_helper(Downgrade, Write); @@ -1333,7 +1333,7 @@ mod tests { rwlock_kill_helper(Downgrade, DowngradeRead); } #[test] #[should_fail] #[ignore(cfg(windows))] - pub fn test_rwlock_downgrade_cant_swap() { + fn test_rwlock_downgrade_cant_swap() { // Tests that you can't downgrade with a different rwlock's token. let x = ~RWlock(); let y = ~RWlock(); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 04fa319b25530..ee83a0c9bd652 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -823,7 +823,7 @@ mod tests { #[test] #[ignore(cfg(windows))] - pub fn test_should_fail() { + fn test_should_fail() { fn f() { fail!(); } let desc = TestDescAndFn { desc: TestDesc { @@ -841,7 +841,7 @@ mod tests { } #[test] - pub fn test_should_fail_but_succeeds() { + fn test_should_fail_but_succeeds() { fn f() { } let desc = TestDescAndFn { desc: TestDesc { @@ -859,7 +859,7 @@ mod tests { } #[test] - pub fn first_free_arg_should_be_a_filter() { + fn first_free_arg_should_be_a_filter() { let args = ~[~"progname", ~"filter"]; let opts = match parse_opts(args) { either::Left(copy o) => o, @@ -869,7 +869,7 @@ mod tests { } #[test] - pub fn parse_ignored_flag() { + fn parse_ignored_flag() { let args = ~[~"progname", ~"filter", ~"--ignored"]; let opts = match parse_opts(args) { either::Left(copy o) => o, diff --git a/src/libstd/time.rs b/src/libstd/time.rs index adfa12594aac1..70dc4d8cfebbf 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -872,7 +872,7 @@ mod tests { use core::str; use core::vec; - pub fn test_get_time() { + fn test_get_time() { static some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z static some_future_date: i64 = 1577836800i64; // 2020-01-01T00:00:00Z @@ -893,7 +893,7 @@ mod tests { } } - pub fn test_precise_time() { + fn test_precise_time() { let s0 = precise_time_s(); let ns1 = precise_time_ns(); @@ -910,7 +910,7 @@ mod tests { assert!(ns2 >= ns1); } - pub fn test_at_utc() { + fn test_at_utc() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -931,7 +931,7 @@ mod tests { assert!(utc.tm_nsec == 54321_i32); } - pub fn test_at() { + fn test_at() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -959,7 +959,7 @@ mod tests { assert!(local.tm_nsec == 54321_i32); } - pub fn test_to_timespec() { + fn test_to_timespec() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -970,7 +970,7 @@ mod tests { assert!(utc.to_local().to_timespec() == time); } - pub fn test_conversions() { + fn test_conversions() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -986,7 +986,7 @@ mod tests { assert!(utc.to_local().to_utc() == utc); } - pub fn test_strptime() { + fn test_strptime() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -1144,7 +1144,7 @@ mod tests { assert!(test(~"%", ~"%%")); } - pub fn test_ctime() { + fn test_ctime() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -1158,7 +1158,7 @@ mod tests { assert!(local.ctime() == ~"Fri Feb 13 15:31:30 2009"); } - pub fn test_strftime() { + fn test_strftime() { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); @@ -1231,7 +1231,7 @@ mod tests { assert!(utc.rfc3339() == ~"2009-02-13T23:31:30Z"); } - pub fn test_timespec_eq_ord() { + fn test_timespec_eq_ord() { use core::cmp::{eq, ge, gt, le, lt, ne}; let a = &Timespec::new(-2, 1); @@ -1265,7 +1265,7 @@ mod tests { } #[test] - pub fn run_tests() { + fn run_tests() { // The tests race on tzset. So instead of having many independent // tests, we will just call the functions now. test_get_time(); diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index 99e772b0c95a3..c229e72ae5d4a 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -183,13 +183,13 @@ mod test { use core::pipes::{stream, SharedChan}; #[test] - pub fn test_gl_timer_simple_sleep_test() { + fn test_gl_timer_simple_sleep_test() { let hl_loop = &uv::global_loop::get(); sleep(hl_loop, 1u); } #[test] - pub fn test_gl_timer_sleep_stress1() { + fn test_gl_timer_sleep_stress1() { let hl_loop = &uv::global_loop::get(); for iter::repeat(50u) { sleep(hl_loop, 1u); @@ -197,7 +197,7 @@ mod test { } #[test] - pub fn test_gl_timer_sleep_stress2() { + fn test_gl_timer_sleep_stress2() { let (po, ch) = stream(); let ch = SharedChan(ch); let hl_loop = &uv::global_loop::get(); @@ -241,7 +241,7 @@ mod test { #[test] #[cfg(ignore)] - pub fn test_gl_timer_recv_timeout_before_time_passes() { + fn test_gl_timer_recv_timeout_before_time_passes() { let times = 100; let mut successes = 0; let mut failures = 0; @@ -270,7 +270,7 @@ mod test { } #[test] - pub fn test_gl_timer_recv_timeout_after_time_passes() { + fn test_gl_timer_recv_timeout_after_time_passes() { let times = 100; let mut successes = 0; let mut failures = 0; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 3bf297027d4d6..740ecec001f83 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1225,7 +1225,7 @@ pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { } #[cfg(test)] -pub mod test { +mod test { use core::prelude::*; use core::comm::{SharedChan, stream, GenericChan, GenericPort}; use super::*; @@ -1759,11 +1759,11 @@ pub mod test { #[cfg(target_os="darwin")] #[cfg(target_os="linux")] #[cfg(target_os="android")] - pub mod tcp_and_server_client_test { + mod tcp_and_server_client_test { #[cfg(target_arch="x86_64")] - pub mod impl64 { + mod impl64 { #[test] - pub fn test_uv_ll_tcp_server_and_request() { + fn test_uv_ll_tcp_server_and_request() { unsafe { super::super::impl_uv_tcp_server_and_request(); } @@ -1772,10 +1772,10 @@ pub mod test { #[cfg(target_arch="x86")] #[cfg(target_arch="arm")] #[cfg(target_arch="mips")] - pub mod impl32 { + mod impl32 { #[test] #[ignore(cfg(target_os = "linux"))] - pub fn test_uv_ll_tcp_server_and_request() { + fn test_uv_ll_tcp_server_and_request() { unsafe { super::super::impl_uv_tcp_server_and_request(); } diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 59e4dddc73be9..bc930515a5d89 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -781,7 +781,7 @@ fn consume_whitespace(rdr: @mut StringReader) { } #[cfg(test)] -pub mod test { +mod test { use super::*; use ast; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cf29f170f4061..88ecabe28f526 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2248,7 +2248,7 @@ pub fn print_onceness(s: @ps, o: ast::Onceness) { } #[cfg(test)] -pub mod test { +mod test { use super::*; use ast; diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 4108871d0089c..1133fd850d84b 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -66,43 +66,47 @@ pub impl Interner { fn len(&self) -> uint { let vect = &*self.vect; vect.len() } } -#[test] -#[should_fail] -pub fn i1 () { - let i : Interner<@~str> = Interner::new(); - i.get(13); -} +#[cfg(test)] +mod tests { + use super::*; + #[test] + #[should_fail] + fn i1 () { + let i : Interner<@~str> = Interner::new(); + i.get(13); + } -#[test] -pub fn i2 () { - let i : Interner<@~str> = Interner::new(); - // first one is zero: - assert_eq!(i.intern (@~"dog"), 0); - // re-use gets the same entry: - assert_eq!(i.intern (@~"dog"), 0); - // different string gets a different #: - assert_eq!(i.intern (@~"cat"), 1); - assert_eq!(i.intern (@~"cat"), 1); - // dog is still at zero - assert_eq!(i.intern (@~"dog"), 0); - // gensym gets 3 - assert_eq!(i.gensym (@~"zebra" ), 2); - // gensym of same string gets new number : - assert_eq!(i.gensym (@~"zebra" ), 3); - // gensym of *existing* string gets new number: - assert_eq!(i.gensym (@~"dog"), 4); - assert_eq!(i.get(0), @~"dog"); - assert_eq!(i.get(1), @~"cat"); - assert_eq!(i.get(2), @~"zebra"); - assert_eq!(i.get(3), @~"zebra"); - assert_eq!(i.get(4), @~"dog"); -} + #[test] + fn i2 () { + let i : Interner<@~str> = Interner::new(); + // first one is zero: + assert_eq!(i.intern (@~"dog"), 0); + // re-use gets the same entry: + assert_eq!(i.intern (@~"dog"), 0); + // different string gets a different #: + assert_eq!(i.intern (@~"cat"), 1); + assert_eq!(i.intern (@~"cat"), 1); + // dog is still at zero + assert_eq!(i.intern (@~"dog"), 0); + // gensym gets 3 + assert_eq!(i.gensym (@~"zebra" ), 2); + // gensym of same string gets new number : + assert_eq!(i.gensym (@~"zebra" ), 3); + // gensym of *existing* string gets new number: + assert_eq!(i.gensym (@~"dog"), 4); + assert_eq!(i.get(0), @~"dog"); + assert_eq!(i.get(1), @~"cat"); + assert_eq!(i.get(2), @~"zebra"); + assert_eq!(i.get(3), @~"zebra"); + assert_eq!(i.get(4), @~"dog"); + } -#[test] -pub fn i3 () { - let i : Interner<@~str> = Interner::prefill([@~"Alan",@~"Bob",@~"Carol"]); - assert_eq!(i.get(0), @~"Alan"); - assert_eq!(i.get(1), @~"Bob"); - assert_eq!(i.get(2), @~"Carol"); - assert_eq!(i.intern(@~"Bob"), 1); -} + #[test] + fn i3 () { + let i : Interner<@~str> = Interner::prefill([@~"Alan",@~"Bob",@~"Carol"]); + assert_eq!(i.get(0), @~"Alan"); + assert_eq!(i.get(1), @~"Bob"); + assert_eq!(i.get(2), @~"Carol"); + assert_eq!(i.intern(@~"Bob"), 1); + } +} \ No newline at end of file From ef3a8ebb9bbc55bea4e0b62a1dcb6abb5512b223 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 16 Apr 2013 01:09:55 +1000 Subject: [PATCH 213/403] librustdoc: move tests into dedicated tests module. --- src/librustdoc/attr_parser.rs | 177 +++-- src/librustdoc/attr_pass.rs | 213 +++--- src/librustdoc/config.rs | 238 +++---- src/librustdoc/desc_to_brief_pass.rs | 163 ++--- src/librustdoc/extract.rs | 132 ++-- src/librustdoc/markdown_index_pass.rs | 216 +++--- src/librustdoc/markdown_pass.rs | 918 +++++++++++++------------- src/librustdoc/markdown_writer.rs | 123 ++-- src/librustdoc/page_pass.rs | 47 +- src/librustdoc/prune_hidden_pass.rs | 20 +- src/librustdoc/prune_private_pass.rs | 176 ++--- src/librustdoc/sectionalize_pass.rs | 177 ++--- src/librustdoc/text_pass.rs | 310 ++++----- src/librustdoc/trim_pass.rs | 22 +- src/librustdoc/tystr_pass.rs | 311 ++++----- 15 files changed, 1624 insertions(+), 1619 deletions(-) diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs index 213198e6f2158..efd061209a503 100644 --- a/src/librustdoc/attr_parser.rs +++ b/src/librustdoc/attr_parser.rs @@ -25,26 +25,6 @@ pub struct CrateAttrs { name: Option<~str> } -#[cfg(test)] -mod test { - use syntax::ast; - use syntax; - - use core::option::None; - - pub fn parse_attributes(source: ~str) -> ~[ast::attribute] { - use syntax::parse; - use syntax::parse::attr::parser_attr; - use syntax::codemap; - - let parse_sess = syntax::parse::new_parse_sess(None); - let parser = parse::new_parser_from_source_str( - parse_sess, ~[], ~"-", codemap::FssNone, @source); - - parser.parse_outer_attributes() - } -} - fn doc_metas( attrs: ~[ast::attribute] ) -> ~[@ast::meta_item] { @@ -66,30 +46,6 @@ pub fn parse_crate(attrs: ~[ast::attribute]) -> CrateAttrs { } } -#[test] -fn should_extract_crate_name_from_link_attribute() { - let source = ~"#[link(name = \"snuggles\")]"; - let attrs = test::parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == Some(~"snuggles")); -} - -#[test] -fn should_not_extract_crate_name_if_no_link_attribute() { - let source = ~""; - let attrs = test::parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == None); -} - -#[test] -fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() { - let source = ~"#[link(whatever)]"; - let attrs = test::parse_attributes(source); - let attrs = parse_crate(attrs); - assert!(attrs.name == None); -} - pub fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> { let doc_strs = do doc_metas(attrs).filter_mapped |meta| { attr::get_meta_item_value_str(*meta).map(|s| copy **s) @@ -101,60 +57,103 @@ pub fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> { } } -#[test] -fn parse_desc_should_handle_undocumented_mods() { - let source = ~""; - let attrs = test::parse_attributes(source); - let attrs = parse_desc(attrs); - assert!(attrs == None); -} - -#[test] -fn parse_desc_should_parse_simple_doc_attributes() { - let source = ~"#[doc = \"basic\"]"; - let attrs = test::parse_attributes(source); - let attrs = parse_desc(attrs); - assert!(attrs == Some(~"basic")); -} - pub fn parse_hidden(attrs: ~[ast::attribute]) -> bool { do doc_metas(attrs).find |meta| { match attr::get_meta_item_list(*meta) { - Some(metas) => { - let hiddens = attr::find_meta_items_by_name(metas, ~"hidden"); - !hiddens.is_empty() - } - None => false + Some(metas) => { + let hiddens = attr::find_meta_items_by_name(metas, ~"hidden"); + !hiddens.is_empty() + } + None => false } }.is_some() } -#[test] -fn should_parse_hidden_attribute() { - let source = ~"#[doc(hidden)]"; - let attrs = test::parse_attributes(source); - assert!(parse_hidden(attrs) == true); -} +#[cfg(test)] +mod test { + use syntax::ast; + use syntax; + use super::{parse_hidden, parse_crate, parse_desc}; + use core::prelude::*; -#[test] -fn should_parse_hidden_attribute_with_other_docs() { - let source = ~"#[doc = \"foo\"] #[doc(hidden)] #[doc = \"foo\"]"; - let attrs = test::parse_attributes(source); - assert!(parse_hidden(attrs) == true); -} + fn parse_attributes(source: ~str) -> ~[ast::attribute] { + use syntax::parse; + use syntax::parse::attr::parser_attr; + use syntax::codemap; -#[test] -fn should_not_parse_non_hidden_attribute() { - let source = ~"#[doc = \"\"]"; - let attrs = test::parse_attributes(source); - assert!(parse_hidden(attrs) == false); -} + let parse_sess = syntax::parse::new_parse_sess(None); + let parser = parse::new_parser_from_source_str( + parse_sess, ~[], ~"-", codemap::FssNone, @source); + + parser.parse_outer_attributes() + } -#[test] -fn should_concatenate_multiple_doc_comments() { - let source = ~"/// foo\n/// bar"; - let desc = parse_desc(test::parse_attributes(source)); - assert!(desc == Some(~"foo\nbar")); -} + #[test] + fn should_extract_crate_name_from_link_attribute() { + let source = ~"#[link(name = \"snuggles\")]"; + let attrs = parse_attributes(source); + let attrs = parse_crate(attrs); + assert!(attrs.name == Some(~"snuggles")); + } + #[test] + fn should_not_extract_crate_name_if_no_link_attribute() { + let source = ~""; + let attrs = parse_attributes(source); + let attrs = parse_crate(attrs); + assert!(attrs.name == None); + } + + #[test] + fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() { + let source = ~"#[link(whatever)]"; + let attrs = parse_attributes(source); + let attrs = parse_crate(attrs); + assert!(attrs.name == None); + } + + #[test] + fn parse_desc_should_handle_undocumented_mods() { + let source = ~""; + let attrs = parse_attributes(source); + let attrs = parse_desc(attrs); + assert!(attrs == None); + } + + #[test] + fn parse_desc_should_parse_simple_doc_attributes() { + let source = ~"#[doc = \"basic\"]"; + let attrs = parse_attributes(source); + let attrs = parse_desc(attrs); + assert!(attrs == Some(~"basic")); + } + + #[test] + fn should_parse_hidden_attribute() { + let source = ~"#[doc(hidden)]"; + let attrs = parse_attributes(source); + assert!(parse_hidden(attrs) == true); + } + + #[test] + fn should_parse_hidden_attribute_with_other_docs() { + let source = ~"#[doc = \"foo\"] #[doc(hidden)] #[doc = \"foo\"]"; + let attrs = parse_attributes(source); + assert!(parse_hidden(attrs) == true); + } + + #[test] + fn should_not_parse_non_hidden_attribute() { + let source = ~"#[doc = \"\"]"; + let attrs = parse_attributes(source); + assert!(parse_hidden(attrs) == false); + } + + #[test] + fn should_concatenate_multiple_doc_comments() { + let source = ~"/// foo\n/// bar"; + let desc = parse_desc(parse_attributes(source)); + assert!(desc == Some(~"foo\nbar")); + } +} diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index b550155140f0b..a666bff18c97c 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -78,12 +78,6 @@ fn fold_crate( } } -#[test] -fn should_replace_top_module_name_with_crate_name() { - let doc = test::mk_doc(~"#[link(name = \"bond\")];"); - assert!(doc.cratemod().name() == ~"bond"); -} - fn fold_item( fold: &fold::Fold, doc: doc::ItemDoc @@ -113,38 +107,14 @@ fn parse_item_attrs( parse_attrs: ~fn(a: ~[ast::attribute]) -> T) -> T { do astsrv::exec(srv) |ctxt| { let attrs = match *ctxt.ast_map.get(&id) { - ast_map::node_item(item, _) => copy item.attrs, - ast_map::node_foreign_item(item, _, _, _) => copy item.attrs, - _ => fail!(~"parse_item_attrs: not an item") + ast_map::node_item(item, _) => copy item.attrs, + ast_map::node_foreign_item(item, _, _, _) => copy item.attrs, + _ => fail!(~"parse_item_attrs: not an item") }; parse_attrs(attrs) } } -#[test] -fn should_should_extract_mod_attributes() { - let doc = test::mk_doc(~"#[doc = \"test\"] mod a { }"); - assert!(doc.cratemod().mods()[0].desc() == Some(~"test")); -} - -#[test] -fn should_extract_top_mod_attributes() { - let doc = test::mk_doc(~"#[doc = \"test\"];"); - assert!(doc.cratemod().desc() == Some(~"test")); -} - -#[test] -fn should_extract_foreign_fn_attributes() { - let doc = test::mk_doc(~"extern { #[doc = \"test\"] fn a(); }"); - assert!(doc.cratemod().nmods()[0].fns[0].desc() == Some(~"test")); -} - -#[test] -fn should_extract_fn_attributes() { - let doc = test::mk_doc(~"#[doc = \"test\"] fn a() -> int { }"); - assert!(doc.cratemod().fns()[0].desc() == Some(~"test")); -} - fn fold_enum( fold: &fold::Fold, doc: doc::EnumDoc @@ -174,8 +144,8 @@ fn fold_enum( } _ => { fail!(fmt!("Enum variant %s has id that's \ - not bound to an enum item", - variant.name)) + not bound to an enum item", + variant.name)) } } } @@ -190,19 +160,6 @@ fn fold_enum( } } -#[test] -fn should_extract_enum_docs() { - let doc = test::mk_doc(~"#[doc = \"b\"]\ - enum a { v }"); - assert!(doc.cratemod().enums()[0].desc() == Some(~"b")); -} - -#[test] -fn should_extract_variant_docs() { - let doc = test::mk_doc(~"enum a { #[doc = \"c\"] v }"); - assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"c")); -} - fn fold_trait( fold: &fold::Fold, doc: doc::TraitDoc @@ -225,30 +182,30 @@ fn merge_method_attrs( // Create an assoc list from method name to attributes let attrs: ~[(~str, Option<~str>)] = do astsrv::exec(srv) |ctxt| { match *ctxt.ast_map.get(&item_id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(_, _, ref methods), _ - }, _) => { - vec::map(*methods, |method| { - match copy *method { - ast::required(ty_m) => { - (to_str(ty_m.ident), - attr_parser::parse_desc(copy ty_m.attrs)) - } - ast::provided(m) => { - (to_str(m.ident), attr_parser::parse_desc(copy m.attrs)) - } - } - }) - } - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref methods), _ - }, _) => { - vec::map(*methods, |method| { - (to_str(method.ident), - attr_parser::parse_desc(copy method.attrs)) - }) - } - _ => fail!(~"unexpected item") + ast_map::node_item(@ast::item { + node: ast::item_trait(_, _, ref methods), _ + }, _) => { + vec::map(*methods, |method| { + match copy *method { + ast::required(ty_m) => { + (to_str(ty_m.ident), + attr_parser::parse_desc(copy ty_m.attrs)) + } + ast::provided(m) => { + (to_str(m.ident), attr_parser::parse_desc(copy m.attrs)) + } + } + }) + } + ast_map::node_item(@ast::item { + node: ast::item_impl(_, _, _, ref methods), _ + }, _) => { + vec::map(*methods, |method| { + (to_str(method.ident), + attr_parser::parse_desc(copy method.attrs)) + }) + } + _ => fail!(~"unexpected item") } }; @@ -263,22 +220,6 @@ fn merge_method_attrs( } } -#[test] -fn should_extract_trait_docs() { - let doc = test::mk_doc(~"#[doc = \"whatever\"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].desc() == Some(~"whatever")); -} - -#[test] -fn should_extract_trait_method_docs() { - let doc = test::mk_doc( - ~"trait i {\ - #[doc = \"desc\"]\ - fn f(a: bool) -> bool;\ - }"); - assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"desc")); -} - fn fold_impl( fold: &fold::Fold, @@ -293,34 +234,94 @@ fn fold_impl( } } -#[test] -fn should_extract_impl_docs() { - let doc = test::mk_doc( - ~"#[doc = \"whatever\"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].desc() == Some(~"whatever")); -} - -#[test] -fn should_extract_impl_method_docs() { - let doc = test::mk_doc( - ~"impl int {\ - #[doc = \"desc\"]\ - fn f(a: bool) -> bool { }\ - }"); - assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"desc")); -} - #[cfg(test)] mod test { use astsrv; use attr_pass::run; use doc; use extract; + use core::prelude::*; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); run(srv.clone(), doc) } } + + #[test] + fn should_replace_top_module_name_with_crate_name() { + let doc = mk_doc(~"#[link(name = \"bond\")];"); + assert!(doc.cratemod().name() == ~"bond"); + } + + #[test] + fn should_should_extract_mod_attributes() { + let doc = mk_doc(~"#[doc = \"test\"] mod a { }"); + assert!(doc.cratemod().mods()[0].desc() == Some(~"test")); + } + + #[test] + fn should_extract_top_mod_attributes() { + let doc = mk_doc(~"#[doc = \"test\"];"); + assert!(doc.cratemod().desc() == Some(~"test")); + } + + #[test] + fn should_extract_foreign_fn_attributes() { + let doc = mk_doc(~"extern { #[doc = \"test\"] fn a(); }"); + assert!(doc.cratemod().nmods()[0].fns[0].desc() == Some(~"test")); + } + + #[test] + fn should_extract_fn_attributes() { + let doc = mk_doc(~"#[doc = \"test\"] fn a() -> int { }"); + assert!(doc.cratemod().fns()[0].desc() == Some(~"test")); + } + + #[test] + fn should_extract_enum_docs() { + let doc = mk_doc(~"#[doc = \"b\"]\ + enum a { v }"); + assert!(doc.cratemod().enums()[0].desc() == Some(~"b")); + } + + #[test] + fn should_extract_variant_docs() { + let doc = mk_doc(~"enum a { #[doc = \"c\"] v }"); + assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"c")); + } + + #[test] + fn should_extract_trait_docs() { + let doc = mk_doc(~"#[doc = \"whatever\"] trait i { fn a(); }"); + assert!(doc.cratemod().traits()[0].desc() == Some(~"whatever")); + } + + #[test] + fn should_extract_trait_method_docs() { + let doc = mk_doc( + ~"trait i {\ + #[doc = \"desc\"]\ + fn f(a: bool) -> bool;\ + }"); + assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"desc")); + } + + #[test] + fn should_extract_impl_docs() { + let doc = mk_doc( + ~"#[doc = \"whatever\"] impl int { fn a() { } }"); + assert!(doc.cratemod().impls()[0].desc() == Some(~"whatever")); + } + + #[test] + fn should_extract_impl_method_docs() { + let doc = mk_doc( + ~"impl int {\ + #[doc = \"desc\"]\ + fn f(a: bool) -> bool { }\ + }"); + assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"desc")); + } } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 62ddec7a1199c..ed1a54c49a731 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -209,7 +209,7 @@ fn parse_output_style(output_style: &str) -> Result { } } -fn maybe_find_pandoc( +pub fn maybe_find_pandoc( config: &Config, maybe_pandoc_cmd: Option<~str>, program_output: Process @@ -243,140 +243,140 @@ fn maybe_find_pandoc( } } -#[test] -fn should_find_pandoc() { - let config = Config { - output_format: PandocHtml, - .. default_config(&Path("test")) - }; - let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { - ProgramOutput { status: 0, out: ~"pandoc 1.8.2.1", err: ~"" } - }; - let result = maybe_find_pandoc(&config, None, mock_program_output); - assert!(result == result::Ok(Some(~"pandoc"))); -} - -#[test] -fn should_error_with_no_pandoc() { - let config = Config { - output_format: PandocHtml, - .. default_config(&Path("test")) - }; - let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { - ProgramOutput { status: 1, out: ~"", err: ~"" } - }; - let result = maybe_find_pandoc(&config, None, mock_program_output); - assert!(result == result::Err(~"couldn't find pandoc")); -} - #[cfg(test)] mod test { - use config::{Config, mock_program_output, parse_config_}; - - use core::result::Result; + use config::*; + use core::prelude::*; + use core::run::ProgramOutput; - pub fn parse_config(args: &[~str]) -> Result { + fn parse_config(args: &[~str]) -> Result { parse_config_(args, mock_program_output) } -} -#[test] -fn should_error_with_no_crates() { - let config = test::parse_config(~[~"rustdoc"]); - assert!(config.get_err() == ~"no crates specified"); -} + #[test] + fn should_find_pandoc() { + let config = Config { + output_format: PandocHtml, + .. default_config(&Path("test")) + }; + let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { + ProgramOutput { status: 0, out: ~"pandoc 1.8.2.1", err: ~"" } + }; + let result = maybe_find_pandoc(&config, None, mock_program_output); + assert!(result == result::Ok(Some(~"pandoc"))); + } -#[test] -fn should_error_with_multiple_crates() { - let config = - test::parse_config(~[~"rustdoc", ~"crate1.rc", ~"crate2.rc"]); - assert!(config.get_err() == ~"multiple crates specified"); -} + #[test] + fn should_error_with_no_pandoc() { + let config = Config { + output_format: PandocHtml, + .. default_config(&Path("test")) + }; + let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { + ProgramOutput { status: 1, out: ~"", err: ~"" } + }; + let result = maybe_find_pandoc(&config, None, mock_program_output); + assert!(result == result::Err(~"couldn't find pandoc")); + } -#[test] -fn should_set_output_dir_to_cwd_if_not_provided() { - let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]); - assert!(config.get().output_dir == Path(".")); -} + #[test] + fn should_error_with_no_crates() { + let config = parse_config(~[~"rustdoc"]); + assert!(config.get_err() == ~"no crates specified"); + } -#[test] -fn should_set_output_dir_if_provided() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles" - ]); - assert!(config.get().output_dir == Path("snuggles")); -} + #[test] + fn should_error_with_multiple_crates() { + let config = + parse_config(~[~"rustdoc", ~"crate1.rc", ~"crate2.rc"]); + assert!(config.get_err() == ~"multiple crates specified"); + } -#[test] -fn should_set_output_format_to_pandoc_html_if_not_provided() { - let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]); - assert!(config.get().output_format == PandocHtml); -} + #[test] + fn should_set_output_dir_to_cwd_if_not_provided() { + let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + assert!(config.get().output_dir == Path(".")); + } -#[test] -fn should_set_output_format_to_markdown_if_requested() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"markdown" - ]); - assert!(config.get().output_format == Markdown); -} + #[test] + fn should_set_output_dir_if_provided() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles" + ]); + assert!(config.get().output_dir == Path("snuggles")); + } -#[test] -fn should_set_output_format_to_pandoc_html_if_requested() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"html" - ]); - assert!(config.get().output_format == PandocHtml); -} + #[test] + fn should_set_output_format_to_pandoc_html_if_not_provided() { + let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + assert!(config.get().output_format == PandocHtml); + } -#[test] -fn should_error_on_bogus_format() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-format", ~"bogus" - ]); - assert!(config.get_err() == ~"unknown output format 'bogus'"); -} + #[test] + fn should_set_output_format_to_markdown_if_requested() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-format", ~"markdown" + ]); + assert!(config.get().output_format == Markdown); + } -#[test] -fn should_set_output_style_to_doc_per_mod_by_default() { - let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]); - assert!(config.get().output_style == DocPerMod); -} + #[test] + fn should_set_output_format_to_pandoc_html_if_requested() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-format", ~"html" + ]); + assert!(config.get().output_format == PandocHtml); + } -#[test] -fn should_set_output_style_to_one_doc_if_requested() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-crate" - ]); - assert!(config.get().output_style == DocPerCrate); -} + #[test] + fn should_error_on_bogus_format() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-format", ~"bogus" + ]); + assert!(config.get_err() == ~"unknown output format 'bogus'"); + } -#[test] -fn should_set_output_style_to_doc_per_mod_if_requested() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-mod" - ]); - assert!(config.get().output_style == DocPerMod); -} + #[test] + fn should_set_output_style_to_doc_per_mod_by_default() { + let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + assert!(config.get().output_style == DocPerMod); + } -#[test] -fn should_error_on_bogus_output_style() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--output-style", ~"bogus" - ]); - assert!(config.get_err() == ~"unknown output style 'bogus'"); -} + #[test] + fn should_set_output_style_to_one_doc_if_requested() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-crate" + ]); + assert!(config.get().output_style == DocPerCrate); + } -#[test] -fn should_set_pandoc_command_if_requested() { - let config = test::parse_config(~[ - ~"rustdoc", ~"crate.rc", ~"--pandoc-cmd", ~"panda-bear-doc" - ]); - assert!(config.get().pandoc_cmd == Some(~"panda-bear-doc")); -} + #[test] + fn should_set_output_style_to_doc_per_mod_if_requested() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-mod" + ]); + assert!(config.get().output_style == DocPerMod); + } -#[test] -fn should_set_pandoc_command_when_using_pandoc() { - let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]); - assert!(config.get().pandoc_cmd == Some(~"pandoc")); -} + #[test] + fn should_error_on_bogus_output_style() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--output-style", ~"bogus" + ]); + assert!(config.get_err() == ~"unknown output style 'bogus'"); + } + + #[test] + fn should_set_pandoc_command_if_requested() { + let config = parse_config(~[ + ~"rustdoc", ~"crate.rc", ~"--pandoc-cmd", ~"panda-bear-doc" + ]); + assert!(config.get().pandoc_cmd == Some(~"panda-bear-doc")); + } + + #[test] + fn should_set_pandoc_command_when_using_pandoc() { + let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + assert!(config.get().pandoc_cmd == Some(~"pandoc")); + } +} \ No newline at end of file diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 7c50af40f337a..5027b24435599 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -81,44 +81,7 @@ fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc { } } -#[test] -fn should_promote_desc() { - let doc = test::mk_doc(~"#[doc = \"desc\"] mod m { }"); - assert!(doc.cratemod().mods()[0].brief() == Some(~"desc")); -} - -#[test] -fn should_promote_trait_method_desc() { - let doc = test::mk_doc(~"trait i { #[doc = \"desc\"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].brief == - Some(~"desc")); -} - -#[test] -fn should_promote_impl_method_desc() { - let doc = test::mk_doc( - ~"impl int { #[doc = \"desc\"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"desc")); -} - -#[cfg(test)] -pub mod test { - use astsrv; - use attr_pass; - use desc_to_brief_pass::run; - use doc; - use extract; - - pub fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(copy source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - run(srv.clone(), doc) - } - } -} - -fn extract(desc: Option<~str>) -> Option<~str> { +pub fn extract(desc: Option<~str>) -> Option<~str> { if desc.is_none() { return None } @@ -182,7 +145,7 @@ fn first_sentence_(s: &str) -> ~str { } } -fn paragraphs(s: &str) -> ~[~str] { +pub fn paragraphs(s: &str) -> ~[~str] { let mut lines = ~[]; for str::each_line_any(s) |line| { lines.push(line.to_owned()); } let mut whitespace_lines = 0; @@ -219,28 +182,65 @@ fn paragraphs(s: &str) -> ~[~str] { } } -#[test] -fn test_paragraphs_1() { - let paras = paragraphs(~"1\n\n2"); - assert!(paras == ~[~"1", ~"2"]); -} +#[cfg(test)] +mod test { + use astsrv; + use attr_pass; + use super::{extract, paragraphs, run}; + use doc; + use extract; + use core::prelude::*; -#[test] -fn test_paragraphs_2() { - let paras = paragraphs(~"\n\n1\n1\n\n2\n\n"); - assert!(paras == ~[~"1\n1", ~"2"]); -} + fn mk_doc(source: ~str) -> doc::Doc { + do astsrv::from_str(copy source) |srv| { + let doc = extract::from_srv(srv.clone(), ~""); + let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); + run(srv.clone(), doc) + } + } -#[test] -fn should_promote_short_descs() { - let desc = Some(~"desc"); - let brief = extract(copy desc); - assert!(brief == desc); -} + #[test] + fn should_promote_desc() { + let doc = mk_doc(~"#[doc = \"desc\"] mod m { }"); + assert!(doc.cratemod().mods()[0].brief() == Some(~"desc")); + } + + #[test] + fn should_promote_trait_method_desc() { + let doc = mk_doc(~"trait i { #[doc = \"desc\"] fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].brief == + Some(~"desc")); + } + + #[test] + fn should_promote_impl_method_desc() { + let doc = mk_doc( + ~"impl int { #[doc = \"desc\"] fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"desc")); + } -#[test] -fn should_not_promote_long_descs() { - let desc = Some(~"Warkworth Castle is a ruined medieval building + #[test] + fn test_paragraphs_1() { + let paras = paragraphs(~"1\n\n2"); + assert!(paras == ~[~"1", ~"2"]); + } + + #[test] + fn test_paragraphs_2() { + let paras = paragraphs(~"\n\n1\n1\n\n2\n\n"); + assert!(paras == ~[~"1\n1", ~"2"]); + } + + #[test] + fn should_promote_short_descs() { + let desc = Some(~"desc"); + let brief = extract(copy desc); + assert!(brief == desc); + } + + #[test] + fn should_not_promote_long_descs() { + let desc = Some(~"Warkworth Castle is a ruined medieval building in the town of the same name in the English county of Northumberland, and the town and castle occupy a loop of the River Coquet, less than a mile from England's north-east coast. When the castle was founded is uncertain, @@ -248,13 +248,13 @@ but traditionally its construction has been ascribed to Prince Henry of Scotland in the mid 12th century, although it may have been built by King Henry II of England when he took control of England'snorthern counties."); - let brief = extract(desc); - assert!(brief == None); -} + let brief = extract(desc); + assert!(brief == None); + } -#[test] -fn should_promote_first_sentence() { - let desc = Some(~"Warkworth Castle is a ruined medieval building + #[test] + fn should_promote_first_sentence() { + let desc = Some(~"Warkworth Castle is a ruined medieval building in the town. of the same name in the English county of Northumberland, and the town and castle occupy a loop of the River Coquet, less than a mile from England's north-east coast. When the castle was founded is uncertain, @@ -262,14 +262,14 @@ but traditionally its construction has been ascribed to Prince Henry of Scotland in the mid 12th century, although it may have been built by King Henry II of England when he took control of England'snorthern counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth Castle is a ruined medieval building in the town")); -} + let brief = extract(desc); + assert!(brief == Some( + ~"Warkworth Castle is a ruined medieval building in the town")); + } -#[test] -fn should_not_consider_double_period_to_end_sentence() { - let desc = Some(~"Warkworth..Castle is a ruined medieval building + #[test] + fn should_not_consider_double_period_to_end_sentence() { + let desc = Some(~"Warkworth..Castle is a ruined medieval building in the town. of the same name in the English county of Northumberland, and the town and castle occupy a loop of the River Coquet, less than a mile from England's north-east coast. When the castle was founded is uncertain, @@ -277,14 +277,14 @@ but traditionally its construction has been ascribed to Prince Henry of Scotland in the mid 12th century, although it may have been built by King Henry II of England when he took control of England'snorthern counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth..Castle is a ruined medieval building in the town")); -} + let brief = extract(desc); + assert!(brief == Some( + ~"Warkworth..Castle is a ruined medieval building in the town")); + } -#[test] -fn should_not_consider_triple_period_to_end_sentence() { - let desc = Some(~"Warkworth... Castle is a ruined medieval building + #[test] + fn should_not_consider_triple_period_to_end_sentence() { + let desc = Some(~"Warkworth... Castle is a ruined medieval building in the town. of the same name in the English county of Northumberland, and the town and castle occupy a loop of the River Coquet, less than a mile from England's north-east coast. When the castle was founded is uncertain, @@ -292,7 +292,8 @@ but traditionally its construction has been ascribed to Prince Henry of Scotland in the mid 12th century, although it may have been built by King Henry II of England when he took control of England'snorthern counties."); - let brief = extract(desc); - assert!(brief == Some( - ~"Warkworth... Castle is a ruined medieval building in the town")); + let brief = extract(desc); + assert!(brief == Some( + ~"Warkworth... Castle is a ruined medieval building in the town")); + } } diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index 1d6d569e1c29d..fa3f7d6432489 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -182,13 +182,6 @@ fn constdoc_from_const(itemdoc: doc::ItemDoc) -> doc::ConstDoc { } } -#[test] -fn should_extract_const_name_and_id() { - let doc = test::mk_doc(~"static a: int = 0;"); - assert!(doc.cratemod().consts()[0].id() != 0); - assert!(doc.cratemod().consts()[0].name() == ~"a"); -} - fn enumdoc_from_enum( itemdoc: doc::ItemDoc, variants: ~[ast::variant] @@ -213,19 +206,6 @@ fn variantdoc_from_variant(variant: &ast::variant) -> doc::VariantDoc { } } -#[test] -fn should_extract_enums() { - let doc = test::mk_doc(~"enum e { v }"); - assert!(doc.cratemod().enums()[0].id() != 0); - assert!(doc.cratemod().enums()[0].name() == ~"e"); -} - -#[test] -fn should_extract_enum_variants() { - let doc = test::mk_doc(~"enum e { v }"); - assert!(doc.cratemod().enums()[0].variants[0].name == ~"v"); -} - fn traitdoc_from_trait( itemdoc: doc::ItemDoc, methods: ~[ast::trait_method] @@ -259,18 +239,6 @@ fn traitdoc_from_trait( } } -#[test] -fn should_extract_traits() { - let doc = test::mk_doc(~"trait i { fn f(); }"); - assert!(doc.cratemod().traits()[0].name() == ~"i"); -} - -#[test] -fn should_extract_trait_methods() { - let doc = test::mk_doc(~"trait i { fn f(); }"); - assert!(doc.cratemod().traits()[0].methods[0].name == ~"f"); -} - fn impldoc_from_impl( itemdoc: doc::ItemDoc, methods: ~[@ast::method] @@ -293,12 +261,6 @@ fn impldoc_from_impl( } } -#[test] -fn should_extract_impl_methods() { - let doc = test::mk_doc(~"impl int { fn f() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].name == ~"f"); -} - fn tydoc_from_ty( itemdoc: doc::ItemDoc ) -> doc::TyDoc { @@ -308,12 +270,6 @@ fn tydoc_from_ty( } } -#[test] -fn should_extract_tys() { - let doc = test::mk_doc(~"type a = int;"); - assert!(doc.cratemod().types()[0].name() == ~"a"); -} - fn structdoc_from_struct( itemdoc: doc::ItemDoc, struct_def: @ast::struct_def @@ -330,18 +286,6 @@ fn structdoc_from_struct( } } -#[test] -fn should_extract_structs() { - let doc = test::mk_doc(~"struct Foo { field: () }"); - assert!(doc.cratemod().structs()[0].name() == ~"Foo"); -} - -#[test] -fn should_extract_struct_fields() { - let doc = test::mk_doc(~"struct Foo { field: () }"); - assert!(doc.cratemod().structs()[0].fields[0] == ~"field"); -} - #[cfg(test)] mod test { use astsrv; @@ -351,20 +295,20 @@ mod test { use core::vec; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { let ast = parse::from_str(source); extract(ast, ~"") } #[test] - pub fn extract_empty_crate() { + fn extract_empty_crate() { let doc = mk_doc(~""); assert!(vec::is_empty(doc.cratemod().mods())); assert!(vec::is_empty(doc.cratemod().fns())); } #[test] - pub fn extract_mods() { + fn extract_mods() { let doc = mk_doc(~"mod a { mod b { } mod c { } }"); assert!(doc.cratemod().mods()[0].name() == ~"a"); assert!(doc.cratemod().mods()[0].mods()[0].name() == ~"b"); @@ -372,26 +316,26 @@ mod test { } #[test] - pub fn extract_fns_from_foreign_mods() { + fn extract_fns_from_foreign_mods() { let doc = mk_doc(~"extern { fn a(); }"); assert!(doc.cratemod().nmods()[0].fns[0].name() == ~"a"); } #[test] - pub fn extract_mods_deep() { + fn extract_mods_deep() { let doc = mk_doc(~"mod a { mod b { mod c { } } }"); assert!(doc.cratemod().mods()[0].mods()[0].mods()[0].name() == ~"c"); } #[test] - pub fn extract_should_set_mod_ast_id() { + fn extract_should_set_mod_ast_id() { let doc = mk_doc(~"mod a { }"); assert!(doc.cratemod().mods()[0].id() != 0); } #[test] - pub fn extract_fns() { + fn extract_fns() { let doc = mk_doc( ~"fn a() { } \ mod b { fn c() { @@ -401,13 +345,13 @@ mod test { } #[test] - pub fn extract_should_set_fn_ast_id() { + fn extract_should_set_fn_ast_id() { let doc = mk_doc(~"fn a() { }"); assert!(doc.cratemod().fns()[0].id() != 0); } #[test] - pub fn extract_should_use_default_crate_name() { + fn extract_should_use_default_crate_name() { let source = ~""; let ast = parse::from_str(source); let doc = extract(ast, ~"burp"); @@ -415,11 +359,67 @@ mod test { } #[test] - pub fn extract_from_seq_srv() { + fn extract_from_seq_srv() { let source = ~""; do astsrv::from_str(source) |srv| { let doc = from_srv(srv, ~"name"); assert!(doc.cratemod().name() == ~"name"); } } + + #[test] + fn should_extract_const_name_and_id() { + let doc = mk_doc(~"static a: int = 0;"); + assert!(doc.cratemod().consts()[0].id() != 0); + assert!(doc.cratemod().consts()[0].name() == ~"a"); + } + + #[test] + fn should_extract_enums() { + let doc = mk_doc(~"enum e { v }"); + assert!(doc.cratemod().enums()[0].id() != 0); + assert!(doc.cratemod().enums()[0].name() == ~"e"); + } + + #[test] + fn should_extract_enum_variants() { + let doc = mk_doc(~"enum e { v }"); + assert!(doc.cratemod().enums()[0].variants[0].name == ~"v"); + } + + #[test] + fn should_extract_traits() { + let doc = mk_doc(~"trait i { fn f(); }"); + assert!(doc.cratemod().traits()[0].name() == ~"i"); + } + + #[test] + fn should_extract_trait_methods() { + let doc = mk_doc(~"trait i { fn f(); }"); + assert!(doc.cratemod().traits()[0].methods[0].name == ~"f"); + } + + #[test] + fn should_extract_impl_methods() { + let doc = mk_doc(~"impl int { fn f() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].name == ~"f"); + } + + #[test] + fn should_extract_tys() { + let doc = mk_doc(~"type a = int;"); + assert!(doc.cratemod().types()[0].name() == ~"a"); + } + + #[test] + fn should_extract_structs() { + let doc = mk_doc(~"struct Foo { field: () }"); + assert!(doc.cratemod().structs()[0].name() == ~"Foo"); + } + + #[test] + fn should_extract_struct_fields() { + let doc = mk_doc(~"struct Foo { field: () }"); + assert!(doc.cratemod().structs()[0].fields[0] == ~"field"); + } } diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 55901b4904aa3..866fbba2be87a 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -115,7 +115,7 @@ fn item_to_entry( } } -fn pandoc_header_id(header: &str) -> ~str { +pub fn pandoc_header_id(header: &str) -> ~str { // http://johnmacfarlane.net/pandoc/README.html#headers @@ -162,110 +162,6 @@ fn pandoc_header_id(header: &str) -> ~str { fn maybe_use_section_id(s: &str) -> ~str { s.to_str() } } -#[test] -fn should_remove_punctuation_from_headers() { - assert!(pandoc_header_id(~"impl foo of bar") == - ~"impl-foo-of-bara"); - assert!(pandoc_header_id(~"impl of num::num for int") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl of num::num for int/&") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl of num::num for ^int") - == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl for & condvar") - == ~"impl-for-condvar"); - assert!(pandoc_header_id(~"impl of Select for (Left, Right)") - == ~"impl-of-selectt-u-for-left-right"); - assert!(pandoc_header_id(~"impl of Condition<'self, T, U>") - == ~"impl-of-conditionself-t-u"); - assert!(pandoc_header_id(~"impl of Condition") - == ~"impl-of-conditiont-copy-clone"); -} - -#[test] -fn should_trim_whitespace_after_removing_punctuation() { - assert!(pandoc_header_id("impl foo for ()") == ~"impl-foo-for"); -} - -#[test] -fn should_index_mod_contents() { - let doc = test::mk_doc( - config::DocPerCrate, - ~"mod a { } fn b() { }" - ); - assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { - kind: ~"Module", - name: ~"a", - brief: None, - link: ~"#module-a" - }); - assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); -} - -#[test] -fn should_index_mod_contents_multi_page() { - let doc = test::mk_doc( - config::DocPerMod, - ~"mod a { } fn b() { }" - ); - assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { - kind: ~"Module", - name: ~"a", - brief: None, - link: ~"a.html" - }); - assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); -} - -#[test] -fn should_index_foreign_mod_pages() { - let doc = test::mk_doc( - config::DocPerMod, - ~"extern mod a { }" - ); - assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { - kind: ~"Foreign module", - name: ~"a", - brief: None, - link: ~"a.html" - }); -} - -#[test] -fn should_add_brief_desc_to_index() { - let doc = test::mk_doc( - config::DocPerMod, - ~"#[doc = \"test\"] mod a { }" - ); - assert!((&doc.cratemod().index).get().entries[0].brief - == Some(~"test")); -} - -#[test] -fn should_index_foreign_mod_contents() { - let doc = test::mk_doc( - config::DocPerCrate, - ~"extern mod a { fn b(); }" - ); - assert!((&doc.cratemod().nmods()[0].index).get().entries[0] - == doc::IndexEntry { - kind: ~"Function", - name: ~"b", - brief: None, - link: ~"#function-b" - }); -} - #[cfg(test)] mod test { use astsrv; @@ -276,10 +172,10 @@ mod test { use extract; use markdown_index_pass::run; use path_pass; + use super::pandoc_header_id; + use core::prelude::*; - use core::path::Path; - - pub fn mk_doc(output_style: config::OutputStyle, source: ~str) + fn mk_doc(output_style: config::OutputStyle, source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let config = config::Config { @@ -293,4 +189,108 @@ mod test { run(srv.clone(), doc, config) } } + + #[test] + fn should_remove_punctuation_from_headers() { + assert!(pandoc_header_id(~"impl foo of bar") == + ~"impl-foo-of-bara"); + assert!(pandoc_header_id(~"impl of num::num for int") + == ~"impl-of-numnum-for-int"); + assert!(pandoc_header_id(~"impl of num::num for int/&") + == ~"impl-of-numnum-for-int"); + assert!(pandoc_header_id(~"impl of num::num for ^int") + == ~"impl-of-numnum-for-int"); + assert!(pandoc_header_id(~"impl for & condvar") + == ~"impl-for-condvar"); + assert!(pandoc_header_id(~"impl of Select for (Left, Right)") + == ~"impl-of-selectt-u-for-left-right"); + assert!(pandoc_header_id(~"impl of Condition<'self, T, U>") + == ~"impl-of-conditionself-t-u"); + assert!(pandoc_header_id(~"impl of Condition") + == ~"impl-of-conditiont-copy-clone"); + } + + #[test] + fn should_trim_whitespace_after_removing_punctuation() { + assert!(pandoc_header_id("impl foo for ()") == ~"impl-foo-for"); + } + + #[test] + fn should_index_mod_contents() { + let doc = mk_doc( + config::DocPerCrate, + ~"mod a { } fn b() { }" + ); + assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { + kind: ~"Module", + name: ~"a", + brief: None, + link: ~"#module-a" + }); + assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { + kind: ~"Function", + name: ~"b", + brief: None, + link: ~"#function-b" + }); + } + + #[test] + fn should_index_mod_contents_multi_page() { + let doc = mk_doc( + config::DocPerMod, + ~"mod a { } fn b() { }" + ); + assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { + kind: ~"Module", + name: ~"a", + brief: None, + link: ~"a.html" + }); + assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { + kind: ~"Function", + name: ~"b", + brief: None, + link: ~"#function-b" + }); + } + + #[test] + fn should_index_foreign_mod_pages() { + let doc = mk_doc( + config::DocPerMod, + ~"extern mod a { }" + ); + assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { + kind: ~"Foreign module", + name: ~"a", + brief: None, + link: ~"a.html" + }); + } + + #[test] + fn should_add_brief_desc_to_index() { + let doc = mk_doc( + config::DocPerMod, + ~"#[doc = \"test\"] mod a { }" + ); + assert!((&doc.cratemod().index).get().entries[0].brief + == Some(~"test")); + } + + #[test] + fn should_index_foreign_mod_contents() { + let doc = mk_doc( + config::DocPerCrate, + ~"extern mod a { fn b(); }" + ); + assert!((&doc.cratemod().nmods()[0].index).get().entries[0] + == doc::IndexEntry { + kind: ~"Function", + name: ~"b", + brief: None, + link: ~"#function-b" + }); + } } diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 8c4cd26bb7c11..2dfc04e8ec709 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -22,10 +22,6 @@ use markdown_writer::WriterFactory; use pass::Pass; use sort_pass; -#[cfg(test)] use config; -#[cfg(test)] use markdown_writer; -#[cfg(test)] use page_pass; - use core::cell::Cell; use core::str; use core::vec; @@ -48,8 +44,8 @@ fn run( fn mods_last(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { fn is_mod(item: &doc::ItemTag) -> bool { match *item { - doc::ModTag(_) => true, - _ => false + doc::ModTag(_) => true, + _ => false } } @@ -69,33 +65,6 @@ fn run( return doc; } -#[test] -fn should_write_modules_last() { - /* - Because the markdown pass writes all modules at the same level of - indentation (it doesn't 'nest' them), we need to make sure that we - write all of the modules contained in each module after all other - types of items, or else the header nesting will end up wrong, with - modules appearing to contain items that they do not. - */ - let markdown = test::render( - ~"mod a { }\ - fn b() { }\ - mod c { - }\ - fn d() { }" - ); - - let idx_a = str::find_str(markdown, ~"# Module `a`").get(); - let idx_b = str::find_str(markdown, ~"## Function `b`").get(); - let idx_c = str::find_str(markdown, ~"# Module `c`").get(); - let idx_d = str::find_str(markdown, ~"## Function `d`").get(); - - assert!(idx_b < idx_d); - assert!(idx_d < idx_a); - assert!(idx_a < idx_c); -} - struct Ctxt { w: Writer } @@ -118,33 +87,18 @@ pub fn write_markdown( fn write_page(ctxt: &Ctxt, page: &doc::Page) { write_title(ctxt, copy *page); match copy *page { - doc::CratePage(doc) => { - write_crate(ctxt, doc); - } - doc::ItemPage(doc) => { - // We don't write a header for item's pages because their - // header in the html output is created by the page title - write_item_no_header(ctxt, doc); - } + doc::CratePage(doc) => { + write_crate(ctxt, doc); + } + doc::ItemPage(doc) => { + // We don't write a header for item's pages because their + // header in the html output is created by the page title + write_item_no_header(ctxt, doc); + } } ctxt.w.put_done(); } -#[test] -fn should_request_new_writer_for_each_page() { - // This port will send us a (page, str) pair for every writer - // that was created - let (writer_factory, po) = markdown_writer::future_writer_factory(); - let (srv, doc) = test::create_doc_srv(~"mod a { }"); - // Split the document up into pages - let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); - write_markdown(doc, writer_factory); - // We expect two pages to have been written - for iter::repeat(2) { - po.recv(); - } -} - fn write_title(ctxt: &Ctxt, page: doc::Page) { ctxt.w.put_line(fmt!("%% %s", make_title(page))); ctxt.w.put_line(~""); @@ -152,38 +106,18 @@ fn write_title(ctxt: &Ctxt, page: doc::Page) { fn make_title(page: doc::Page) -> ~str { let item = match page { - doc::CratePage(CrateDoc) => { - doc::ModTag(copy CrateDoc.topmod) - } - doc::ItemPage(ItemTag) => { - ItemTag - } + doc::CratePage(CrateDoc) => { + doc::ModTag(copy CrateDoc.topmod) + } + doc::ItemPage(ItemTag) => { + ItemTag + } }; let title = markdown_pass::header_text(item); let title = str::replace(title, ~"`", ~""); return title; } -#[test] -fn should_write_title_for_each_page() { - let (writer_factory, po) = markdown_writer::future_writer_factory(); - let (srv, doc) = test::create_doc_srv( - ~"#[link(name = \"core\")]; mod a { }"); - let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); - write_markdown(doc, writer_factory); - for iter::repeat(2) { - let (page, markdown) = po.recv(); - match page { - doc::CratePage(_) => { - assert!(str::contains(markdown, ~"% Crate core")); - } - doc::ItemPage(_) => { - assert!(str::contains(markdown, ~"% Module a")); - } - } - } -} - enum Hlvl { H1 = 1, H2 = 2, @@ -204,94 +138,94 @@ fn write_header_(ctxt: &Ctxt, lvl: Hlvl, title: ~str) { pub fn header_kind(doc: doc::ItemTag) -> ~str { match doc { - doc::ModTag(_) => { - if doc.id() == syntax::ast::crate_node_id { - ~"Crate" - } else { - ~"Module" + doc::ModTag(_) => { + if doc.id() == syntax::ast::crate_node_id { + ~"Crate" + } else { + ~"Module" + } + } + doc::NmodTag(_) => { + ~"Foreign module" + } + doc::FnTag(_) => { + ~"Function" + } + doc::ConstTag(_) => { + ~"Const" + } + doc::EnumTag(_) => { + ~"Enum" + } + doc::TraitTag(_) => { + ~"Trait" + } + doc::ImplTag(_) => { + ~"Implementation" + } + doc::TyTag(_) => { + ~"Type" + } + doc::StructTag(_) => { + ~"Struct" } - } - doc::NmodTag(_) => { - ~"Foreign module" - } - doc::FnTag(_) => { - ~"Function" - } - doc::ConstTag(_) => { - ~"Const" - } - doc::EnumTag(_) => { - ~"Enum" - } - doc::TraitTag(_) => { - ~"Trait" - } - doc::ImplTag(_) => { - ~"Implementation" - } - doc::TyTag(_) => { - ~"Type" - } - doc::StructTag(_) => { - ~"Struct" - } } } pub fn header_name(doc: doc::ItemTag) -> ~str { let fullpath = str::connect(doc.path() + ~[doc.name()], ~"::"); match &doc { - &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => { - fullpath - } - &doc::NmodTag(_) => { - fullpath - } - &doc::ImplTag(ref doc) => { - assert!(doc.self_ty.is_some()); - let bounds = if (&doc.bounds_str).is_some() { - fmt!(" where %s", (&doc.bounds_str).get()) - } else { - ~"" - }; - let self_ty = (&doc.self_ty).get(); - let mut trait_part = ~""; - for doc.trait_types.eachi |i, trait_type| { - if i == 0 { - trait_part += ~" of "; + &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => { + fullpath + } + &doc::NmodTag(_) => { + fullpath + } + &doc::ImplTag(ref doc) => { + assert!(doc.self_ty.is_some()); + let bounds = if (&doc.bounds_str).is_some() { + fmt!(" where %s", (&doc.bounds_str).get()) } else { - trait_part += ~", "; + ~"" + }; + let self_ty = (&doc.self_ty).get(); + let mut trait_part = ~""; + for doc.trait_types.eachi |i, trait_type| { + if i == 0 { + trait_part += ~" of "; + } else { + trait_part += ~", "; + } + trait_part += *trait_type; } - trait_part += *trait_type; + fmt!("%s for %s%s", trait_part, self_ty, bounds) + } + _ => { + doc.name() } - fmt!("%s for %s%s", trait_part, self_ty, bounds) - } - _ => { - doc.name() - } } } pub fn header_text(doc: doc::ItemTag) -> ~str { match &doc { - &doc::ImplTag(ref ImplDoc) => { - let header_kind = header_kind(copy doc); - let bounds = if (&ImplDoc.bounds_str).is_some() { - fmt!(" where `%s`", (&ImplDoc.bounds_str).get()) - } else { - ~"" - }; - let desc = if ImplDoc.trait_types.is_empty() { - fmt!("for `%s`%s", (&ImplDoc.self_ty).get(), bounds) - } else { - fmt!("of `%s` for `%s`%s", - ImplDoc.trait_types[0], - (&ImplDoc.self_ty).get(), - bounds) - }; - return fmt!("%s %s", header_kind, desc); - } - _ => {} + &doc::ImplTag(ref ImplDoc) => { + let header_kind = header_kind(copy doc); + let bounds = if (&ImplDoc.bounds_str).is_some() { + fmt!(" where `%s`", (&ImplDoc.bounds_str).get()) + } else { + ~"" + }; + let desc = if ImplDoc.trait_types.is_empty() { + fmt!("for `%s`%s", (&ImplDoc.self_ty).get(), bounds) + } else { + fmt!("of `%s` for `%s`%s", + ImplDoc.trait_types[0], + (&ImplDoc.self_ty).get(), + bounds) + }; + return fmt!("%s %s", header_kind, desc); + } + _ => {} } header_text_(header_kind(copy doc), @@ -323,12 +257,6 @@ fn write_mod( write_mod_contents(ctxt, ModDoc); } -#[test] -fn should_write_full_path_to_mod() { - let markdown = test::render(~"mod a { mod b { mod c { } } }"); - assert!(str::contains(markdown, ~"# Module `a::b::c`")); -} - fn write_common( ctxt: &Ctxt, desc: Option<~str>, @@ -363,17 +291,6 @@ fn write_section(ctxt: &Ctxt, section: doc::Section) { ctxt.w.put_line(~""); } -#[test] -fn should_write_sections() { - let markdown = test::render( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { - }"); - assert!(str::contains(markdown, ~"#### Header\n\nBody\n\n")); -} - fn write_mod_contents( ctxt: &Ctxt, doc: doc::ModDoc @@ -402,15 +319,15 @@ fn write_item_(ctxt: &Ctxt, doc: doc::ItemTag, write_header: bool) { } match doc { - doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc), - doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc), - doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc), - doc::ConstTag(ConstDoc) => write_const(ctxt, ConstDoc), - doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc), - doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc), - doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc), - doc::TyTag(TyDoc) => write_type(ctxt, TyDoc), - doc::StructTag(StructDoc) => put_struct(ctxt, StructDoc), + doc::ModTag(ModDoc) => write_mod(ctxt, ModDoc), + doc::NmodTag(nModDoc) => write_nmod(ctxt, nModDoc), + doc::FnTag(FnDoc) => write_fn(ctxt, FnDoc), + doc::ConstTag(ConstDoc) => write_const(ctxt, ConstDoc), + doc::EnumTag(EnumDoc) => write_enum(ctxt, EnumDoc), + doc::TraitTag(TraitDoc) => write_trait(ctxt, TraitDoc), + doc::ImplTag(ImplDoc) => write_impl(ctxt, ImplDoc), + doc::TyTag(TyDoc) => write_type(ctxt, TyDoc), + doc::StructTag(StructDoc) => put_struct(ctxt, StructDoc), } } @@ -420,17 +337,11 @@ fn write_item_header(ctxt: &Ctxt, doc: doc::ItemTag) { fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl { match doc { - &doc::ModTag(_) | &doc::NmodTag(_) => H1, - _ => H2 + &doc::ModTag(_) | &doc::NmodTag(_) => H1, + _ => H2 } } -#[test] -fn should_write_crate_description() { - let markdown = test::render(~"#[doc = \"this is the crate\"];"); - assert!(str::contains(markdown, ~"this is the crate")); -} - fn write_index(ctxt: &Ctxt, index: doc::Index) { if vec::is_empty(index.entries) { return; @@ -444,7 +355,7 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) { let id = copy entry.link; if entry.brief.is_some() { ctxt.w.put_line(fmt!("* [%s](%s) - %s", - header, id, (&entry.brief).get())); + header, id, (&entry.brief).get())); } else { ctxt.w.put_line(fmt!("* [%s](%s)", header, id)); } @@ -454,37 +365,6 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) { ctxt.w.put_line(~""); } -#[test] -fn should_write_index() { - let markdown = test::render(~"mod a { } mod b { }"); - assert!(str::contains( - markdown, - ~"\n\n* [Module `a`](#module-a)\n\ - * [Module `b`](#module-b)\n\n" - )); -} - -#[test] -fn should_write_index_brief() { - let markdown = test::render(~"#[doc = \"test\"] mod a { }"); - assert!(str::contains(markdown, ~"(#module-a) - test\n")); -} - -#[test] -fn should_not_write_index_if_no_entries() { - let markdown = test::render(~""); - assert!(!str::contains(markdown, ~"\n\n\n")); -} - -#[test] -fn should_write_index_for_foreign_mods() { - let markdown = test::render(~"extern mod a { fn a(); }"); - assert!(str::contains( - markdown, - ~"\n\n* [Function `a`](#function-a)\n\n" - )); -} - fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) { write_common(ctxt, doc.desc(), doc.sections()); if doc.index.is_some() { @@ -497,27 +377,6 @@ fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) { } } -#[test] -fn should_write_foreign_mods() { - let markdown = test::render(~"#[doc = \"test\"] extern mod a { }"); - assert!(str::contains(markdown, ~"Foreign module `a`")); - assert!(str::contains(markdown, ~"test")); -} - -#[test] -fn should_write_foreign_fns() { - let markdown = test::render( - ~"extern mod a { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, ~"test")); -} - -#[test] -fn should_write_foreign_fn_headers() { - let markdown = test::render( - ~"extern mod a { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, ~"## Function `a`")); -} - fn write_fn( ctxt: &Ctxt, doc: doc::FnDoc @@ -542,11 +401,11 @@ fn write_fnlike( fn write_sig(ctxt: &Ctxt, sig: Option<~str>) { match sig { - Some(sig) => { - ctxt.w.put_line(code_block_indent(sig)); - ctxt.w.put_line(~""); - } - None => fail!(~"unimplemented") + Some(sig) => { + ctxt.w.put_line(code_block_indent(sig)); + ctxt.w.put_line(~""); + } + None => fail!(~"unimplemented") } } @@ -558,51 +417,6 @@ fn code_block_indent(s: ~str) -> ~str { str::connect(indented, "\n") } -#[test] -fn write_markdown_should_write_function_header() { - let markdown = test::render(~"fn func() { }"); - assert!(str::contains(markdown, ~"## Function `func`")); -} - -#[test] -fn should_write_the_function_signature() { - let markdown = test::render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, ~"\n fn a()\n")); -} - -#[test] -fn should_insert_blank_line_after_fn_signature() { - let markdown = test::render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, ~"fn a()\n\n")); -} - -#[test] -fn should_correctly_indent_fn_signature() { - let doc = test::create_doc(~"fn a() { }"); - let doc = doc::Doc{ - pages: ~[ - doc::CratePage(doc::CrateDoc{ - topmod: doc::ModDoc{ - items: ~[doc::FnTag(doc::SimpleItemDoc{ - sig: Some(~"line 1\nline 2"), - .. copy doc.cratemod().fns()[0] - })], - .. doc.cratemod() - }, - .. doc.CrateDoc() - }) - ] - }; - let markdown = test::write_markdown_str(doc); - assert!(str::contains(markdown, ~" line 1\n line 2")); -} - -#[test] -fn should_leave_blank_line_between_fn_header_and_sig() { - let markdown = test::render(~"fn a() { }"); - assert!(str::contains(markdown, ~"Function `a`\n\n fn a()")); -} - fn write_const( ctxt: &Ctxt, doc: doc::ConstDoc @@ -611,20 +425,6 @@ fn write_const( write_common(ctxt, doc.desc(), doc.sections()); } -#[test] -fn should_write_const_header() { - let markdown = test::render(~"static a: bool = true;"); - assert!(str::contains(markdown, ~"## Const `a`\n\n")); -} - -#[test] -fn should_write_const_description() { - let markdown = test::render( - ~"#[doc = \"b\"]\ - static a: bool = true;"); - assert!(str::contains(markdown, ~"\n\nb\n\n")); -} - fn write_enum( ctxt: &Ctxt, doc: doc::EnumDoc @@ -633,19 +433,6 @@ fn write_enum( write_variants(ctxt, doc.variants); } -#[test] -fn should_write_enum_header() { - let markdown = test::render(~"enum a { b }"); - assert!(str::contains(markdown, ~"## Enum `a`\n\n")); -} - -#[test] -fn should_write_enum_description() { - let markdown = test::render( - ~"#[doc = \"b\"] enum a { b }"); - assert!(str::contains(markdown, ~"\n\nb\n\n")); -} - fn write_variants( ctxt: &Ctxt, docs: &[doc::VariantDoc] @@ -667,46 +454,13 @@ fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) { assert!(doc.sig.is_some()); let sig = (&doc.sig).get(); match copy doc.desc { - Some(desc) => { - ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc)); - } - None => { - ctxt.w.put_line(fmt!("* `%s`", sig)); - } - } -} - -#[test] -fn should_write_variant_list() { - let markdown = test::render( - ~"enum a { \ - #[doc = \"test\"] b, \ - #[doc = \"test\"] c }"); - assert!(str::contains( - markdown, - ~"\n\n#### Variants\n\ - \n* `b` - test\ - \n* `c` - test\n\n")); -} - -#[test] -fn should_write_variant_list_without_descs() { - let markdown = test::render(~"enum a { b, c }"); - assert!(str::contains( - markdown, - ~"\n\n#### Variants\n\ - \n* `b`\ - \n* `c`\n\n")); -} - -#[test] -fn should_write_variant_list_with_signatures() { - let markdown = test::render(~"enum a { b(int), #[doc = \"a\"] c(int) }"); - assert!(str::contains( - markdown, - ~"\n\n#### Variants\n\ - \n* `b(int)`\ - \n* `c(int)` - a\n\n")); + Some(desc) => { + ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc)); + } + None => { + ctxt.w.put_line(fmt!("* `%s`", sig)); + } + } } fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) { @@ -730,78 +484,11 @@ fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) { ); } -#[test] -fn should_write_trait_header() { - let markdown = test::render(~"trait i { fn a(); }"); - assert!(str::contains(markdown, ~"## Trait `i`")); -} - -#[test] -fn should_write_trait_desc() { - let markdown = test::render( - ~"#[doc = \"desc\"] trait i { fn a(); }"); - assert!(str::contains(markdown, ~"desc")); -} - -#[test] -fn should_write_trait_method_header() { - let markdown = test::render( - ~"trait i { fn a(); }"); - assert!(str::contains(markdown, ~"### Method `a`")); -} - -#[test] -fn should_write_trait_method_signature() { - let markdown = test::render( - ~"trait i { fn a(&self); }"); - assert!(str::contains(markdown, ~"\n fn a(&self)")); -} - fn write_impl(ctxt: &Ctxt, doc: doc::ImplDoc) { write_common(ctxt, doc.desc(), doc.sections()); write_methods(ctxt, doc.methods); } -#[test] -fn should_write_impl_header() { - let markdown = test::render(~"impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"## Implementation for `int`")); -} - -#[test] -fn should_write_impl_header_with_bounds() { - let markdown = test::render(~"impl int { }"); - assert!(str::contains(markdown, ~"## Implementation for `int` where ``")); -} - -#[test] -fn should_write_impl_header_with_trait() { - let markdown = test::render(~"impl j for int { fn a() { } }"); - assert!(str::contains(markdown, - ~"## Implementation of `j` for `int`")); -} - -#[test] -fn should_write_impl_desc() { - let markdown = test::render( - ~"#[doc = \"desc\"] impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"desc")); -} - -#[test] -fn should_write_impl_method_header() { - let markdown = test::render( - ~"impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"### Method `a`")); -} - -#[test] -fn should_write_impl_method_signature() { - let markdown = test::render( - ~"impl int { fn a(&mut self) { } }"); - assert!(str::contains(markdown, ~"\n fn a(&mut self)")); -} - fn write_type( ctxt: &Ctxt, doc: doc::TyDoc @@ -810,25 +497,6 @@ fn write_type( write_common(ctxt, doc.desc(), doc.sections()); } -#[test] -fn should_write_type_header() { - let markdown = test::render(~"type t = int;"); - assert!(str::contains(markdown, ~"## Type `t`")); -} - -#[test] -fn should_write_type_desc() { - let markdown = test::render( - ~"#[doc = \"desc\"] type t = int;"); - assert!(str::contains(markdown, ~"\n\ndesc\n\n")); -} - -#[test] -fn should_write_type_signature() { - let markdown = test::render(~"type t = int;"); - assert!(str::contains(markdown, ~"\n\n type t = int\n\n")); -} - fn put_struct( ctxt: &Ctxt, doc: doc::StructDoc @@ -837,12 +505,6 @@ fn put_struct( write_common(ctxt, doc.desc(), doc.sections()); } -#[test] -fn should_put_struct_header() { - let markdown = test::render(~"struct S { field: () }"); - assert!(str::contains(markdown, ~"## Struct `S`\n\n")); -} - #[cfg(test)] mod test { use astsrv; @@ -855,22 +517,21 @@ mod test { use markdown_pass::{mk_pass, write_markdown}; use markdown_writer; use path_pass; + use page_pass; use sectionalize_pass; use trim_pass; use tystr_pass; use unindent_pass; + use core::prelude::*; - use core::path::Path; - use core::str; - - pub fn render(source: ~str) -> ~str { + fn render(source: ~str) -> ~str { let (srv, doc) = create_doc_srv(source); let markdown = write_markdown_str_srv(srv, doc); debug!("markdown: %s", markdown); markdown } - pub fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) { + fn create_doc_srv(source: ~str) -> (astsrv::Srv, doc::Doc) { do astsrv::from_str(source) |srv| { let config = config::Config { @@ -901,12 +562,12 @@ mod test { } } - pub fn create_doc(source: ~str) -> doc::Doc { + fn create_doc(source: ~str) -> doc::Doc { let (_, doc) = create_doc_srv(source); doc } - pub fn write_markdown_str( + fn write_markdown_str( doc: doc::Doc ) -> ~str { let (writer_factory, po) = markdown_writer::future_writer_factory(); @@ -914,7 +575,7 @@ mod test { return po.recv().second(); } - pub fn write_markdown_str_srv( + fn write_markdown_str_srv( srv: astsrv::Srv, doc: doc::Doc ) -> ~str { @@ -925,14 +586,349 @@ mod test { } #[test] - pub fn write_markdown_should_write_mod_headers() { + fn write_markdown_should_write_mod_headers() { let markdown = render(~"mod moo { }"); assert!(str::contains(markdown, ~"# Module `moo`")); } #[test] - pub fn should_leave_blank_line_after_header() { + fn should_leave_blank_line_after_header() { let markdown = render(~"mod morp { }"); assert!(str::contains(markdown, ~"Module `morp`\n\n")); } + + #[test] + fn should_write_modules_last() { + /* + Because the markdown pass writes all modules at the same level of + indentation (it doesn't 'nest' them), we need to make sure that we + write all of the modules contained in each module after all other + types of items, or else the header nesting will end up wrong, with + modules appearing to contain items that they do not. + */ + let markdown = render( + ~"mod a { }\ + fn b() { }\ + mod c { +}\ + fn d() { }" + ); + + let idx_a = str::find_str(markdown, ~"# Module `a`").get(); + let idx_b = str::find_str(markdown, ~"## Function `b`").get(); + let idx_c = str::find_str(markdown, ~"# Module `c`").get(); + let idx_d = str::find_str(markdown, ~"## Function `d`").get(); + + assert!(idx_b < idx_d); + assert!(idx_d < idx_a); + assert!(idx_a < idx_c); + } + + #[test] + fn should_request_new_writer_for_each_page() { + // This port will send us a (page, str) pair for every writer + // that was created + let (writer_factory, po) = markdown_writer::future_writer_factory(); + let (srv, doc) = create_doc_srv(~"mod a { }"); + // Split the document up into pages + let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); + write_markdown(doc, writer_factory); + // We expect two pages to have been written + for iter::repeat(2) { + po.recv(); + } + } + + #[test] + fn should_write_title_for_each_page() { + let (writer_factory, po) = markdown_writer::future_writer_factory(); + let (srv, doc) = create_doc_srv( + ~"#[link(name = \"core\")]; mod a { }"); + let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); + write_markdown(doc, writer_factory); + for iter::repeat(2) { + let (page, markdown) = po.recv(); + match page { + doc::CratePage(_) => { + assert!(str::contains(markdown, ~"% Crate core")); + } + doc::ItemPage(_) => { + assert!(str::contains(markdown, ~"% Module a")); + } + } + } + } + + #[test] + fn should_write_full_path_to_mod() { + let markdown = render(~"mod a { mod b { mod c { } } }"); + assert!(str::contains(markdown, ~"# Module `a::b::c`")); + } + + #[test] + fn should_write_sections() { + let markdown = render( + ~"#[doc = \"\ + # Header\n\ + Body\"]\ + mod a { +}"); + assert!(str::contains(markdown, ~"#### Header\n\nBody\n\n")); + } + + #[test] + fn should_write_crate_description() { + let markdown = render(~"#[doc = \"this is the crate\"];"); + assert!(str::contains(markdown, ~"this is the crate")); + } + + + #[test] + fn should_write_index() { + let markdown = render(~"mod a { } mod b { }"); + assert!(str::contains( + markdown, + ~"\n\n* [Module `a`](#module-a)\n\ + * [Module `b`](#module-b)\n\n" + )); + } + + #[test] + fn should_write_index_brief() { + let markdown = render(~"#[doc = \"test\"] mod a { }"); + assert!(str::contains(markdown, ~"(#module-a) - test\n")); + } + + #[test] + fn should_not_write_index_if_no_entries() { + let markdown = render(~""); + assert!(!str::contains(markdown, ~"\n\n\n")); + } + + #[test] + fn should_write_index_for_foreign_mods() { + let markdown = render(~"extern mod a { fn a(); }"); + assert!(str::contains( + markdown, + ~"\n\n* [Function `a`](#function-a)\n\n" + )); + } + + #[test] + fn should_write_foreign_mods() { + let markdown = render(~"#[doc = \"test\"] extern mod a { }"); + assert!(str::contains(markdown, ~"Foreign module `a`")); + assert!(str::contains(markdown, ~"test")); + } + + #[test] + fn should_write_foreign_fns() { + let markdown = render( + ~"extern mod a { #[doc = \"test\"] fn a(); }"); + assert!(str::contains(markdown, ~"test")); + } + + #[test] + fn should_write_foreign_fn_headers() { + let markdown = render( + ~"extern mod a { #[doc = \"test\"] fn a(); }"); + assert!(str::contains(markdown, ~"## Function `a`")); + } + + #[test] + fn write_markdown_should_write_function_header() { + let markdown = render(~"fn func() { }"); + assert!(str::contains(markdown, ~"## Function `func`")); + } + + #[test] + fn should_write_the_function_signature() { + let markdown = render(~"#[doc = \"f\"] fn a() { }"); + assert!(str::contains(markdown, ~"\n fn a()\n")); + } + + #[test] + fn should_insert_blank_line_after_fn_signature() { + let markdown = render(~"#[doc = \"f\"] fn a() { }"); + assert!(str::contains(markdown, ~"fn a()\n\n")); + } + + #[test] + fn should_correctly_indent_fn_signature() { + let doc = create_doc(~"fn a() { }"); + let doc = doc::Doc{ + pages: ~[ + doc::CratePage(doc::CrateDoc{ + topmod: doc::ModDoc{ + items: ~[doc::FnTag(doc::SimpleItemDoc{ + sig: Some(~"line 1\nline 2"), + .. copy doc.cratemod().fns()[0] + })], + .. doc.cratemod() + }, + .. doc.CrateDoc() + }) + ] + }; + let markdown = write_markdown_str(doc); + assert!(str::contains(markdown, ~" line 1\n line 2")); + } + + #[test] + fn should_leave_blank_line_between_fn_header_and_sig() { + let markdown = render(~"fn a() { }"); + assert!(str::contains(markdown, ~"Function `a`\n\n fn a()")); + } + + #[test] + fn should_write_const_header() { + let markdown = render(~"static a: bool = true;"); + assert!(str::contains(markdown, ~"## Const `a`\n\n")); + } + + #[test] + fn should_write_const_description() { + let markdown = render( + ~"#[doc = \"b\"]\ + static a: bool = true;"); + assert!(str::contains(markdown, ~"\n\nb\n\n")); + } + + #[test] + fn should_write_enum_header() { + let markdown = render(~"enum a { b }"); + assert!(str::contains(markdown, ~"## Enum `a`\n\n")); + } + + #[test] + fn should_write_enum_description() { + let markdown = render( + ~"#[doc = \"b\"] enum a { b }"); + assert!(str::contains(markdown, ~"\n\nb\n\n")); + } + + #[test] + fn should_write_variant_list() { + let markdown = render( + ~"enum a { \ + #[doc = \"test\"] b, \ + #[doc = \"test\"] c }"); + assert!(str::contains( + markdown, + ~"\n\n#### Variants\n\ + \n* `b` - test\ + \n* `c` - test\n\n")); + } + + #[test] + fn should_write_variant_list_without_descs() { + let markdown = render(~"enum a { b, c }"); + assert!(str::contains( + markdown, + ~"\n\n#### Variants\n\ + \n* `b`\ + \n* `c`\n\n")); + } + + #[test] + fn should_write_variant_list_with_signatures() { + let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }"); + assert!(str::contains( + markdown, + ~"\n\n#### Variants\n\ + \n* `b(int)`\ + \n* `c(int)` - a\n\n")); + } + + #[test] + fn should_write_trait_header() { + let markdown = render(~"trait i { fn a(); }"); + assert!(str::contains(markdown, ~"## Trait `i`")); + } + + #[test] + fn should_write_trait_desc() { + let markdown = render( + ~"#[doc = \"desc\"] trait i { fn a(); }"); + assert!(str::contains(markdown, ~"desc")); + } + + #[test] + fn should_write_trait_method_header() { + let markdown = render( + ~"trait i { fn a(); }"); + assert!(str::contains(markdown, ~"### Method `a`")); + } + + #[test] + fn should_write_trait_method_signature() { + let markdown = render( + ~"trait i { fn a(&self); }"); + assert!(str::contains(markdown, ~"\n fn a(&self)")); + } + + #[test] + fn should_write_impl_header() { + let markdown = render(~"impl int { fn a() { } }"); + assert!(str::contains(markdown, ~"## Implementation for `int`")); + } + + #[test] + fn should_write_impl_header_with_bounds() { + let markdown = render(~"impl int { }"); + assert!(str::contains(markdown, ~"## Implementation for `int` where ``")); + } + + #[test] + fn should_write_impl_header_with_trait() { + let markdown = render(~"impl j for int { fn a() { } }"); + assert!(str::contains(markdown, + ~"## Implementation of `j` for `int`")); + } + + #[test] + fn should_write_impl_desc() { + let markdown = render( + ~"#[doc = \"desc\"] impl int { fn a() { } }"); + assert!(str::contains(markdown, ~"desc")); + } + + #[test] + fn should_write_impl_method_header() { + let markdown = render( + ~"impl int { fn a() { } }"); + assert!(str::contains(markdown, ~"### Method `a`")); + } + + #[test] + fn should_write_impl_method_signature() { + let markdown = render( + ~"impl int { fn a(&mut self) { } }"); + assert!(str::contains(markdown, ~"\n fn a(&mut self)")); + } + + #[test] + fn should_write_type_header() { + let markdown = render(~"type t = int;"); + assert!(str::contains(markdown, ~"## Type `t`")); + } + + #[test] + fn should_write_type_desc() { + let markdown = render( + ~"#[doc = \"desc\"] type t = int;"); + assert!(str::contains(markdown, ~"\n\ndesc\n\n")); + } + + #[test] + fn should_write_type_signature() { + let markdown = render(~"type t = int;"); + assert!(str::contains(markdown, ~"\n\n type t = int\n\n")); + } + + #[test] + fn should_put_struct_header() { + let markdown = render(~"struct S { field: () }"); + assert!(str::contains(markdown, ~"## Struct `S`\n\n")); + } } diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index 2011649995ecd..fcf7011cbc309 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -182,7 +182,7 @@ fn generic_writer(process: ~fn(markdown: ~str)) -> Writer { result } -fn make_local_filename( +pub fn make_local_filename( config: config::Config, page: doc::Page ) -> Path { @@ -218,65 +218,6 @@ pub fn make_filename( Path(filename).with_filetype(ext) } -#[test] -fn should_use_markdown_file_name_based_off_crate() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::Markdown, - output_style: config::DocPerCrate, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = test::mk_doc(~"test", ~""); - let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(config, page); - assert!(filename.to_str() == ~"output/dir/test.md"); -} - -#[test] -fn should_name_html_crate_file_name_index_html_when_doc_per_mod() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::PandocHtml, - output_style: config::DocPerMod, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = test::mk_doc(~"", ~""); - let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(config, page); - assert!(filename.to_str() == ~"output/dir/index.html"); -} - -#[test] -fn should_name_mod_file_names_by_path() { - let config = config::Config { - output_dir: Path("output/dir"), - output_format: config::PandocHtml, - output_style: config::DocPerMod, - .. config::default_config(&Path("input/test.rc")) - }; - let doc = test::mk_doc(~"", ~"mod a { mod b { } }"); - let modb = copy doc.cratemod().mods()[0].mods()[0]; - let page = doc::ItemPage(doc::ModTag(modb)); - let filename = make_local_filename(config, page); - assert!(filename == Path("output/dir/a_b.html")); -} - -#[cfg(test)] -mod test { - use astsrv; - use doc; - use extract; - use path_pass; - - pub fn mk_doc(name: ~str, source: ~str) -> doc::Doc { - do astsrv::from_str(source) |srv| { - let doc = extract::from_srv(srv.clone(), copy name); - let doc = (path_pass::mk_pass().f)(srv.clone(), doc); - doc - } - } -} - fn write_file(path: &Path, s: ~str) { use core::io::WriterUtil; @@ -322,3 +263,65 @@ fn future_writer() -> (Writer, future::Future<~str>) { }; (writer, future) } + +#[cfg(test)] +mod test { + use astsrv; + use doc; + use extract; + use path_pass; + use config; + use super::make_local_filename; + use core::prelude::*; + + fn mk_doc(name: ~str, source: ~str) -> doc::Doc { + do astsrv::from_str(source) |srv| { + let doc = extract::from_srv(srv.clone(), copy name); + let doc = (path_pass::mk_pass().f)(srv.clone(), doc); + doc + } + } + + #[test] + fn should_use_markdown_file_name_based_off_crate() { + let config = config::Config { + output_dir: Path("output/dir"), + output_format: config::Markdown, + output_style: config::DocPerCrate, + .. config::default_config(&Path("input/test.rc")) + }; + let doc = mk_doc(~"test", ~""); + let page = doc::CratePage(doc.CrateDoc()); + let filename = make_local_filename(config, page); + assert!(filename.to_str() == ~"output/dir/test.md"); + } + + #[test] + fn should_name_html_crate_file_name_index_html_when_doc_per_mod() { + let config = config::Config { + output_dir: Path("output/dir"), + output_format: config::PandocHtml, + output_style: config::DocPerMod, + .. config::default_config(&Path("input/test.rc")) + }; + let doc = mk_doc(~"", ~""); + let page = doc::CratePage(doc.CrateDoc()); + let filename = make_local_filename(config, page); + assert!(filename.to_str() == ~"output/dir/index.html"); + } + + #[test] + fn should_name_mod_file_names_by_path() { + let config = config::Config { + output_dir: Path("output/dir"), + output_format: config::PandocHtml, + output_style: config::DocPerMod, + .. config::default_config(&Path("input/test.rc")) + }; + let doc = mk_doc(~"", ~"mod a { mod b { } }"); + let modb = copy doc.cratemod().mods()[0].mods()[0]; + let page = doc::ItemPage(doc::ModTag(modb)); + let filename = make_local_filename(config, page); + assert!(filename == Path("output/dir/a_b.html")); + } +} diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index 55f17f5c1501d..c620e20530e66 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -149,27 +149,6 @@ fn fold_nmod( return doc; } -#[test] -fn should_not_split_the_doc_into_pages_for_doc_per_crate() { - let doc = test::mk_doc_( - config::DocPerCrate, - ~"mod a { } mod b { mod c { } }" - ); - assert!(doc.pages.len() == 1u); -} - -#[test] -fn should_make_a_page_for_every_mod() { - let doc = test::mk_doc(~"mod a { }"); - assert!(doc.pages.mods()[0].name() == ~"a"); -} - -#[test] -fn should_remove_mods_from_containing_mods() { - let doc = test::mk_doc(~"mod a { }"); - assert!(vec::is_empty(doc.cratemod().mods())); -} - #[cfg(test)] mod test { use astsrv; @@ -177,8 +156,9 @@ mod test { use doc; use extract; use page_pass::run; + use core::vec; - pub fn mk_doc_( + fn mk_doc_( output_style: config::OutputStyle, source: ~str ) -> doc::Doc { @@ -188,7 +168,28 @@ mod test { } } - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { mk_doc_(config::DocPerMod, copy source) } + + #[test] + fn should_not_split_the_doc_into_pages_for_doc_per_crate() { + let doc = mk_doc_( + config::DocPerCrate, + ~"mod a { } mod b { mod c { } }" + ); + assert!(doc.pages.len() == 1u); + } + + #[test] + fn should_make_a_page_for_every_mod() { + let doc = mk_doc(~"mod a { }"); + assert!(doc.pages.mods()[0].name() == ~"a"); + } + + #[test] + fn should_remove_mods_from_containing_mods() { + let doc = mk_doc(~"mod a { }"); + assert!(vec::is_empty(doc.cratemod().mods())); + } } diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index f46d183ffcfaf..a50f1f51765f9 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -61,25 +61,25 @@ fn is_hidden(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { } } -#[test] -fn should_prune_hidden_items() { - use core::vec; - - let doc = test::mk_doc(~"#[doc(hidden)] mod a { }"); - assert!(vec::is_empty(doc.cratemod().mods())) -} - #[cfg(test)] -pub mod test { +mod test { use astsrv; use doc; use extract; use prune_hidden_pass::run; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); run(srv.clone(), doc) } } + + #[test] + fn should_prune_hidden_items() { + use core::vec; + + let doc = mk_doc(~"#[doc(hidden)] mod a { }"); + assert!(vec::is_empty(doc.cratemod().mods())) + } } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index 08008ab2bcae0..0578169e257d4 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -154,106 +154,106 @@ fn is_visible(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { } } -#[test] -fn should_prune_items_without_pub_modifier() { - let doc = test::mk_doc(~"mod a { }"); - assert!(vec::is_empty(doc.cratemod().mods())); -} - -#[test] -fn should_not_prune_trait_impls() { - // Impls are more complicated - let doc = test::mk_doc( - ~" \ - trait Foo { } \ - impl Foo for int { } \ - "); - assert!(!doc.cratemod().impls().is_empty()); -} - -#[test] -fn should_prune_associated_methods_without_vis_modifier_on_impls_without_vis_modifier() { - let doc = test::mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); -} - -#[test] -fn should_prune_priv_associated_methods_on_impls_without_vis_modifier() { - let doc = test::mk_doc( - ~"impl Foo {\ - pub fn bar() { }\ - priv fn baz() { }\ - }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); -} - -#[test] -fn should_prune_priv_associated_methods_on_pub_impls() { - let doc = test::mk_doc( - ~"pub impl Foo {\ - fn bar() { }\ - priv fn baz() { }\ - }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); -} - -#[test] -fn should_prune_associated_methods_without_vis_modifier_on_priv_impls() { - let doc = test::mk_doc( - ~"priv impl Foo {\ - pub fn bar() { }\ - fn baz() { }\ - }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); -} - -#[test] -fn should_prune_priv_associated_methods_on_priv_impls() { - let doc = test::mk_doc( - ~"priv impl Foo {\ - pub fn bar() { }\ - priv fn baz() { }\ - }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); -} - -#[test] -fn should_prune_associated_impls_with_no_pub_methods() { - let doc = test::mk_doc( - ~"priv impl Foo {\ - fn baz() { }\ - }"); - assert!(doc.cratemod().impls().is_empty()); -} - -#[test] -fn should_not_prune_associated_impls_with_pub_methods() { - let doc = test::mk_doc( - ~" \ - impl Foo { pub fn bar() { } } \ - "); - assert!(!doc.cratemod().impls().is_empty()); -} - #[cfg(test)] -pub mod test { +mod test { use astsrv; use doc; use extract; use tystr_pass; use prune_private_pass::run; + use core::vec; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = tystr_pass::run(srv.clone(), doc); run(srv.clone(), doc) } } -} + #[test] + fn should_prune_items_without_pub_modifier() { + let doc = mk_doc(~"mod a { }"); + assert!(vec::is_empty(doc.cratemod().mods())); + } + + #[test] + fn should_not_prune_trait_impls() { + // Impls are more complicated + let doc = mk_doc( + ~" \ + trait Foo { } \ + impl Foo for int { } \ + "); + assert!(!doc.cratemod().impls().is_empty()); + } + + #[test] + fn should_prune_associated_methods_without_vis_modifier_on_impls_without_vis_modifier() { + let doc = mk_doc( + ~"impl Foo {\ + pub fn bar() { }\ + fn baz() { }\ + }"); + assert!(doc.cratemod().impls()[0].methods.len() == 1); + } + + #[test] + fn should_prune_priv_associated_methods_on_impls_without_vis_modifier() { + let doc = mk_doc( + ~"impl Foo {\ + pub fn bar() { }\ + priv fn baz() { }\ + }"); + assert!(doc.cratemod().impls()[0].methods.len() == 1); + } + + #[test] + fn should_prune_priv_associated_methods_on_pub_impls() { + let doc = mk_doc( + ~"pub impl Foo {\ + fn bar() { }\ + priv fn baz() { }\ + }"); + assert!(doc.cratemod().impls()[0].methods.len() == 1); + } + + #[test] + fn should_prune_associated_methods_without_vis_modifier_on_priv_impls() { + let doc = mk_doc( + ~"priv impl Foo {\ + pub fn bar() { }\ + fn baz() { }\ + }"); + assert!(doc.cratemod().impls()[0].methods.len() == 1); + } + + #[test] + fn should_prune_priv_associated_methods_on_priv_impls() { + let doc = mk_doc( + ~"priv impl Foo {\ + pub fn bar() { }\ + priv fn baz() { }\ + }"); + assert!(doc.cratemod().impls()[0].methods.len() == 1); + } + + #[test] + fn should_prune_associated_impls_with_no_pub_methods() { + let doc = mk_doc( + ~"priv impl Foo {\ + fn baz() { }\ + }"); + assert!(doc.cratemod().impls().is_empty()); + } + + #[test] + fn should_not_prune_associated_impls_with_pub_methods() { + let doc = mk_doc( + ~" \ + impl Foo { pub fn bar() { } } \ + "); + assert!(!doc.cratemod().impls().is_empty()); + } +} diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 788f84b06c2e8..1cf43043004cf 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -160,106 +160,109 @@ fn parse_header(line: ~str) -> Option<~str> { } } -#[test] -fn should_create_section_headers() { - let doc = test::mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { - }"); - assert!(str::contains( - doc.cratemod().mods()[0].item.sections[0].header, - ~"Header")); -} - -#[test] -fn should_create_section_bodies() { - let doc = test::mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { - }"); - assert!(str::contains( - doc.cratemod().mods()[0].item.sections[0].body, - ~"Body")); -} -#[test] -fn should_not_create_sections_from_indented_headers() { - let doc = test::mk_doc( - ~"#[doc = \"\n\ - Text\n # Header\n\ - Body\"]\ - mod a { - }"); - assert!(vec::is_empty(doc.cratemod().mods()[0].item.sections)); -} - -#[test] -fn should_remove_section_text_from_main_desc() { - let doc = test::mk_doc( - ~"#[doc = \"\ - Description\n\n\ - # Header\n\ - Body\"]\ - mod a { - }"); - assert!(!str::contains( - doc.cratemod().mods()[0].desc().get(), - ~"Header")); - assert!(!str::contains( - doc.cratemod().mods()[0].desc().get(), - ~"Body")); -} - -#[test] -fn should_eliminate_desc_if_it_is_just_whitespace() { - let doc = test::mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body\"]\ - mod a { - }"); - assert!(doc.cratemod().mods()[0].desc() == None); -} - -#[test] -fn should_sectionalize_trait_methods() { - let doc = test::mk_doc( - ~"trait i { - #[doc = \"\ - # Header\n\ - Body\"]\ - fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections.len() == 1u); -} - -#[test] -fn should_sectionalize_impl_methods() { - let doc = test::mk_doc( - ~"impl bool { - #[doc = \"\ - # Header\n\ - Body\"]\ - fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections.len() == 1u); -} #[cfg(test)] -pub mod test { +mod test { use astsrv; use attr_pass; use doc; use extract; use sectionalize_pass::run; + use core::prelude::*; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); run(srv.clone(), doc) } } + + #[test] + fn should_create_section_headers() { + let doc = mk_doc( + ~"#[doc = \"\ + # Header\n\ + Body\"]\ + mod a { +}"); + assert!(str::contains( + doc.cratemod().mods()[0].item.sections[0].header, + ~"Header")); + } + + #[test] + fn should_create_section_bodies() { + let doc = mk_doc( + ~"#[doc = \"\ + # Header\n\ + Body\"]\ + mod a { +}"); + assert!(str::contains( + doc.cratemod().mods()[0].item.sections[0].body, + ~"Body")); + } + + #[test] + fn should_not_create_sections_from_indented_headers() { + let doc = mk_doc( + ~"#[doc = \"\n\ + Text\n # Header\n\ + Body\"]\ + mod a { +}"); + assert!(vec::is_empty(doc.cratemod().mods()[0].item.sections)); + } + + #[test] + fn should_remove_section_text_from_main_desc() { + let doc = mk_doc( + ~"#[doc = \"\ + Description\n\n\ + # Header\n\ + Body\"]\ + mod a { +}"); + assert!(!str::contains( + doc.cratemod().mods()[0].desc().get(), + ~"Header")); + assert!(!str::contains( + doc.cratemod().mods()[0].desc().get(), + ~"Body")); + } + + #[test] + fn should_eliminate_desc_if_it_is_just_whitespace() { + let doc = mk_doc( + ~"#[doc = \"\ + # Header\n\ + Body\"]\ + mod a { +}"); + assert!(doc.cratemod().mods()[0].desc() == None); + } + + #[test] + fn should_sectionalize_trait_methods() { + let doc = mk_doc( + ~"trait i { +#[doc = \"\ + # Header\n\ + Body\"]\ + fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].sections.len() == 1u); + } + + #[test] + fn should_sectionalize_impl_methods() { + let doc = mk_doc( + ~"impl bool { +#[doc = \"\ + # Header\n\ + Body\"]\ + fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].sections.len() == 1u); + } } diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index b5e9b452d148b..785428f00775d 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -137,181 +137,181 @@ fn fold_impl( } } -#[test] -fn should_execute_op_on_enum_brief() { - let doc = test::mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert!(doc.cratemod().enums()[0].brief() == Some(~"a")); -} +#[cfg(test)] +mod test { + use astsrv; + use attr_pass; + use desc_to_brief_pass; + use doc; + use extract; + use sectionalize_pass; + use text_pass::mk_pass; -#[test] -fn should_execute_op_on_enum_desc() { - let doc = test::mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert!(doc.cratemod().enums()[0].desc() == Some(~"a")); -} + use core::prelude::*; -#[test] -fn should_execute_op_on_variant_desc() { - let doc = test::mk_doc(~"enum a { #[doc = \" a \"] b }"); - assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"a")); -} + fn mk_doc(source: ~str) -> doc::Doc { + do astsrv::from_str(copy source) |srv| { + let doc = extract::from_srv(srv.clone(), ~""); + let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); + let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); + let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc); + (mk_pass(~"", |s| str::trim(s).to_owned() ).f)(srv.clone(), doc) + } + } -#[test] -fn should_execute_op_on_trait_brief() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].brief() == Some(~"a")); -} + #[test] + fn should_execute_op_on_enum_brief() { + let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); + assert!(doc.cratemod().enums()[0].brief() == Some(~"a")); + } -#[test] -fn should_execute_op_on_trait_desc() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].desc() == Some(~"a")); -} + #[test] + fn should_execute_op_on_enum_desc() { + let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); + assert!(doc.cratemod().enums()[0].desc() == Some(~"a")); + } -#[test] -fn should_execute_op_on_trait_method_brief() { - let doc = test::mk_doc( - ~"trait i { #[doc = \" a \"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].brief == Some(~"a")); -} + #[test] + fn should_execute_op_on_variant_desc() { + let doc = mk_doc(~"enum a { #[doc = \" a \"] b }"); + assert!(doc.cratemod().enums()[0].variants[0].desc == Some(~"a")); + } -#[test] -fn should_execute_op_on_trait_method_desc() { - let doc = test::mk_doc( - ~"trait i { #[doc = \" a \"] fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"a")); -} + #[test] + fn should_execute_op_on_trait_brief() { + let doc = mk_doc( + ~"#[doc = \" a \"] trait i { fn a(); }"); + assert!(doc.cratemod().traits()[0].brief() == Some(~"a")); + } -#[test] -fn should_execute_op_on_impl_brief() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].brief() == Some(~"a")); -} + #[test] + fn should_execute_op_on_trait_desc() { + let doc = mk_doc( + ~"#[doc = \" a \"] trait i { fn a(); }"); + assert!(doc.cratemod().traits()[0].desc() == Some(~"a")); + } -#[test] -fn should_execute_op_on_impl_desc() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].desc() == Some(~"a")); -} + #[test] + fn should_execute_op_on_trait_method_brief() { + let doc = mk_doc( + ~"trait i { #[doc = \" a \"] fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].brief == Some(~"a")); + } -#[test] -fn should_execute_op_on_impl_method_brief() { - let doc = test::mk_doc( - ~"impl int { #[doc = \" a \"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"a")); -} + #[test] + fn should_execute_op_on_trait_method_desc() { + let doc = mk_doc( + ~"trait i { #[doc = \" a \"] fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].desc == Some(~"a")); + } -#[test] -fn should_execute_op_on_impl_method_desc() { - let doc = test::mk_doc( - ~"impl int { #[doc = \" a \"] fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"a")); -} + #[test] + fn should_execute_op_on_impl_brief() { + let doc = mk_doc( + ~"#[doc = \" a \"] impl int { fn a() { } }"); + assert!(doc.cratemod().impls()[0].brief() == Some(~"a")); + } -#[test] -fn should_execute_op_on_type_brief() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] type t = int;"); - assert!(doc.cratemod().types()[0].brief() == Some(~"a")); -} + #[test] + fn should_execute_op_on_impl_desc() { + let doc = mk_doc( + ~"#[doc = \" a \"] impl int { fn a() { } }"); + assert!(doc.cratemod().impls()[0].desc() == Some(~"a")); + } -#[test] -fn should_execute_op_on_type_desc() { - let doc = test::mk_doc( - ~"#[doc = \" a \"] type t = int;"); - assert!(doc.cratemod().types()[0].desc() == Some(~"a")); -} + #[test] + fn should_execute_op_on_impl_method_brief() { + let doc = mk_doc( + ~"impl int { #[doc = \" a \"] fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].brief == Some(~"a")); + } -#[test] -fn should_execute_on_item_section_headers() { - let doc = test::mk_doc( - ~"#[doc = \"\ - # Header \n\ - Body\"]\ - fn a() { }"); - assert!(doc.cratemod().fns()[0].sections()[0].header == ~"Header"); -} + #[test] + fn should_execute_op_on_impl_method_desc() { + let doc = mk_doc( + ~"impl int { #[doc = \" a \"] fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].desc == Some(~"a")); + } -#[test] -fn should_execute_on_item_section_bodies() { - let doc = test::mk_doc( - ~"#[doc = \"\ - # Header\n\ - Body \"]\ - fn a() { }"); - assert!(doc.cratemod().fns()[0].sections()[0].body == ~"Body"); -} + #[test] + fn should_execute_op_on_type_brief() { + let doc = mk_doc( + ~"#[doc = \" a \"] type t = int;"); + assert!(doc.cratemod().types()[0].brief() == Some(~"a")); + } -#[test] -fn should_execute_on_trait_method_section_headers() { - let doc = test::mk_doc( - ~"trait i { - #[doc = \"\ - # Header \n\ - Body\"]\ - fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections[0].header - == ~"Header"); -} + #[test] + fn should_execute_op_on_type_desc() { + let doc = mk_doc( + ~"#[doc = \" a \"] type t = int;"); + assert!(doc.cratemod().types()[0].desc() == Some(~"a")); + } -#[test] -fn should_execute_on_trait_method_section_bodies() { - let doc = test::mk_doc( - ~"trait i { - #[doc = \"\ - # Header\n\ - Body \"]\ - fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections[0].body == - ~"Body"); -} + #[test] + fn should_execute_on_item_section_headers() { + let doc = mk_doc( + ~"#[doc = \"\ + # Header \n\ + Body\"]\ + fn a() { }"); + assert!(doc.cratemod().fns()[0].sections()[0].header == ~"Header"); + } -#[test] -fn should_execute_on_impl_method_section_headers() { - let doc = test::mk_doc( - ~"impl bool { - #[doc = \"\ - # Header \n\ - Body\"]\ - fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections[0].header - == ~"Header"); -} + #[test] + fn should_execute_on_item_section_bodies() { + let doc = mk_doc( + ~"#[doc = \"\ + # Header\n\ + Body \"]\ + fn a() { }"); + assert!(doc.cratemod().fns()[0].sections()[0].body == ~"Body"); + } -#[test] -fn should_execute_on_impl_method_section_bodies() { - let doc = test::mk_doc( - ~"impl bool { - #[doc = \"\ - # Header\n\ - Body \"]\ - fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections[0].body == - ~"Body"); -} + #[test] + fn should_execute_on_trait_method_section_headers() { + let doc = mk_doc( + ~"trait i { +#[doc = \"\ + # Header \n\ + Body\"]\ + fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].sections[0].header + == ~"Header"); + } -#[cfg(test)] -mod test { - use astsrv; - use attr_pass; - use desc_to_brief_pass; - use doc; - use extract; - use sectionalize_pass; - use text_pass::mk_pass; + #[test] + fn should_execute_on_trait_method_section_bodies() { + let doc = mk_doc( + ~"trait i { +#[doc = \"\ + # Header\n\ + Body \"]\ + fn a(); }"); + assert!(doc.cratemod().traits()[0].methods[0].sections[0].body == + ~"Body"); + } - use core::str; + #[test] + fn should_execute_on_impl_method_section_headers() { + let doc = mk_doc( + ~"impl bool { +#[doc = \"\ + # Header \n\ + Body\"]\ + fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].sections[0].header + == ~"Header"); + } - pub fn mk_doc(source: ~str) -> doc::Doc { - do astsrv::from_str(copy source) |srv| { - let doc = extract::from_srv(srv.clone(), ~""); - let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); - let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); - let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc); - (mk_pass(~"", |s| str::trim(s).to_owned() ).f)(srv.clone(), doc) - } + #[test] + fn should_execute_on_impl_method_section_bodies() { + let doc = mk_doc( + ~"impl bool { +#[doc = \"\ + # Header\n\ + Body \"]\ + fn a() { } }"); + assert!(doc.cratemod().impls()[0].methods[0].sections[0].body == + ~"Body"); } } diff --git a/src/librustdoc/trim_pass.rs b/src/librustdoc/trim_pass.rs index ca543a27189dc..e56a5f18ac6f7 100644 --- a/src/librustdoc/trim_pass.rs +++ b/src/librustdoc/trim_pass.rs @@ -22,16 +22,6 @@ pub fn mk_pass() -> Pass { text_pass::mk_pass(~"trim", |s| s.trim().to_owned() ) } -#[test] -fn should_trim_text() { - use core::option::Some; - - let doc = test::mk_doc(~"#[doc = \" desc \"] \ - mod m { - }"); - assert!(doc.cratemod().mods()[0].desc() == Some(~"desc")); -} - #[cfg(test)] mod test { use astsrv; @@ -40,11 +30,21 @@ mod test { use extract; use trim_pass::mk_pass; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); (mk_pass().f)(srv.clone(), doc) } } + + #[test] + fn should_trim_text() { + use core::option::Some; + + let doc = mk_doc(~"#[doc = \" desc \"] \ + mod m { +}"); + assert!(doc.cratemod().mods()[0].desc() == Some(~"desc")); + } } diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index 6ccfb1bb8c4b9..c0562d306398a 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -67,35 +67,22 @@ fn fold_fn( fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> { do astsrv::exec(srv) |ctxt| { match *ctxt.ast_map.get(&fn_id) { - ast_map::node_item(@ast::item { - ident: ident, - node: ast::item_fn(ref decl, purity, _, ref tys, _), _ - }, _) | - ast_map::node_foreign_item(@ast::foreign_item { - ident: ident, - node: ast::foreign_item_fn(ref decl, purity, ref tys), _ - }, _, _, _) => { - Some(pprust::fun_to_str(decl, purity, ident, None, tys, - extract::interner())) - } - _ => fail!(~"get_fn_sig: fn_id not bound to a fn item") + ast_map::node_item(@ast::item { + ident: ident, + node: ast::item_fn(ref decl, purity, _, ref tys, _), _ + }, _) | + ast_map::node_foreign_item(@ast::foreign_item { + ident: ident, + node: ast::foreign_item_fn(ref decl, purity, ref tys), _ + }, _, _, _) => { + Some(pprust::fun_to_str(decl, purity, ident, None, tys, + extract::interner())) + } + _ => fail!(~"get_fn_sig: fn_id not bound to a fn item") } } } -#[test] -fn should_add_fn_sig() { - let doc = test::mk_doc(~"fn a() -> int { }"); - assert!(doc.cratemod().fns()[0].sig == Some(~"fn a() -> int")); -} - -#[test] -fn should_add_foreign_fn_sig() { - let doc = test::mk_doc(~"extern mod a { fn a() -> int; }"); - assert!(doc.cratemod().nmods()[0].fns[0].sig == - Some(~"fn a() -> int")); -} - fn fold_const( fold: &fold::Fold, doc: doc::ConstDoc @@ -119,12 +106,6 @@ fn fold_const( } } -#[test] -fn should_add_const_types() { - let doc = test::mk_doc(~"static a: bool = true;"); - assert!(doc.cratemod().consts()[0].sig == Some(~"bool")); -} - fn fold_enum( fold: &fold::Fold, doc: doc::EnumDoc @@ -163,13 +144,6 @@ fn fold_enum( } } -#[test] -fn should_add_variant_sigs() { - let doc = test::mk_doc(~"enum a { b(int) }"); - assert!(doc.cratemod().enums()[0].variants[0].sig == - Some(~"b(int)")); -} - fn fold_trait( fold: &fold::Fold, doc: doc::TraitDoc @@ -200,73 +174,66 @@ fn get_method_sig( ) -> Option<~str> { do astsrv::exec(srv) |ctxt| { match *ctxt.ast_map.get(&item_id) { - ast_map::node_item(@ast::item { - node: ast::item_trait(_, _, ref methods), _ - }, _) => { - match vec::find(*methods, |method| { - match copy *method { - ast::required(ty_m) => to_str(ty_m.ident) == method_name, - ast::provided(m) => to_str(m.ident) == method_name, - } - }) { - Some(method) => { - match method { - ast::required(ty_m) => { - Some(pprust::fun_to_str( - &ty_m.decl, - ty_m.purity, - ty_m.ident, - Some(ty_m.self_ty.node), - &ty_m.generics, - extract::interner() - )) + ast_map::node_item(@ast::item { + node: ast::item_trait(_, _, ref methods), _ + }, _) => { + match vec::find(*methods, |method| { + match copy *method { + ast::required(ty_m) => to_str(ty_m.ident) == method_name, + ast::provided(m) => to_str(m.ident) == method_name, } - ast::provided(m) => { - Some(pprust::fun_to_str( - &m.decl, - m.purity, - m.ident, - Some(m.self_ty.node), - &m.generics, - extract::interner() - )) + }) { + Some(method) => { + match method { + ast::required(ty_m) => { + Some(pprust::fun_to_str( + &ty_m.decl, + ty_m.purity, + ty_m.ident, + Some(ty_m.self_ty.node), + &ty_m.generics, + extract::interner() + )) + } + ast::provided(m) => { + Some(pprust::fun_to_str( + &m.decl, + m.purity, + m.ident, + Some(m.self_ty.node), + &m.generics, + extract::interner() + )) + } + } } - } + _ => fail!(~"method not found") } - _ => fail!(~"method not found") } - } - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref methods), _ - }, _) => { - match vec::find(*methods, |method| { - to_str(method.ident) == method_name - }) { - Some(method) => { - Some(pprust::fun_to_str( - &method.decl, - method.purity, - method.ident, - Some(method.self_ty.node), - &method.generics, - extract::interner() - )) + ast_map::node_item(@ast::item { + node: ast::item_impl(_, _, _, ref methods), _ + }, _) => { + match vec::find(*methods, |method| { + to_str(method.ident) == method_name + }) { + Some(method) => { + Some(pprust::fun_to_str( + &method.decl, + method.purity, + method.ident, + Some(method.self_ty.node), + &method.generics, + extract::interner() + )) + } + None => fail!(~"method not found") } - None => fail!(~"method not found") } - } - _ => fail!(~"get_method_sig: item ID not bound to trait or impl") + _ => fail!(~"get_method_sig: item ID not bound to trait or impl") } } } -#[test] -fn should_add_trait_method_sigs() { - let doc = test::mk_doc(~"trait i { fn a(&mut self) -> int; }"); - assert!(doc.cratemod().traits()[0].methods[0].sig - == Some(~"fn a(&mut self) -> int")); -} - fn fold_impl( fold: &fold::Fold, doc: doc::ImplDoc @@ -305,37 +272,6 @@ fn fold_impl( } } -#[test] -fn should_add_impl_bounds() { - let doc = test::mk_doc(~"impl Option { }"); - assert!(doc.cratemod().impls()[0].bounds_str == Some(~"")); -} - -#[test] -fn should_add_impl_trait_types() { - let doc = test::mk_doc(~"impl j for int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].trait_types[0] == ~"j"); -} - -#[test] -fn should_not_add_impl_trait_types_if_none() { - let doc = test::mk_doc(~"impl int { fn a() { } }"); - assert!(vec::len(doc.cratemod().impls()[0].trait_types) == 0); -} - -#[test] -fn should_add_impl_self_ty() { - let doc = test::mk_doc(~"impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].self_ty == Some(~"int")); -} - -#[test] -fn should_add_impl_method_sigs() { - let doc = test::mk_doc(~"impl int { fn a(&self) -> int { fail!() } }"); - assert!(doc.cratemod().impls()[0].methods[0].sig - == Some(~"fn a(&self) -> int")); -} - fn fold_type( fold: &fold::Fold, doc: doc::TyDoc @@ -369,12 +305,6 @@ fn fold_type( } } -#[test] -fn should_add_type_signatures() { - let doc = test::mk_doc(~"type t = int;"); - assert!(doc.cratemod().types()[0].sig == Some(~"type t = int")); -} - fn fold_struct( fold: &fold::Fold, doc: doc::StructDoc @@ -422,38 +352,109 @@ fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item { } } -#[test] -fn should_add_struct_defs() { - let doc = test::mk_doc(~"struct S { field: () }"); - assert!((&doc.cratemod().structs()[0].sig).get().contains( - "struct S {")); -} - -#[test] -fn should_not_serialize_struct_drop_blocks() { - // All we care about are the fields - let doc = test::mk_doc(~"struct S { field: (), drop { } }"); - assert!(!(&doc.cratemod().structs()[0].sig).get().contains("drop")); -} - -#[test] -fn should_not_serialize_struct_attrs() { - // All we care about are the fields - let doc = test::mk_doc(~"#[wut] struct S { field: () }"); - assert!(!(&doc.cratemod().structs()[0].sig).get().contains("wut")); -} - #[cfg(test)] -pub mod test { +mod test { use astsrv; use doc; use extract; use tystr_pass::run; + use core::prelude::*; - pub fn mk_doc(source: ~str) -> doc::Doc { + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); run(srv.clone(), doc) } } + + #[test] + fn should_add_fn_sig() { + let doc = mk_doc(~"fn a() -> int { }"); + assert!(doc.cratemod().fns()[0].sig == Some(~"fn a() -> int")); + } + + #[test] + fn should_add_foreign_fn_sig() { + let doc = mk_doc(~"extern mod a { fn a() -> int; }"); + assert!(doc.cratemod().nmods()[0].fns[0].sig == + Some(~"fn a() -> int")); + } + + #[test] + fn should_add_const_types() { + let doc = mk_doc(~"static a: bool = true;"); + assert!(doc.cratemod().consts()[0].sig == Some(~"bool")); + } + + #[test] + fn should_add_variant_sigs() { + let doc = mk_doc(~"enum a { b(int) }"); + assert!(doc.cratemod().enums()[0].variants[0].sig == + Some(~"b(int)")); + } + + #[test] + fn should_add_trait_method_sigs() { + let doc = mk_doc(~"trait i { fn a(&mut self) -> int; }"); + assert!(doc.cratemod().traits()[0].methods[0].sig + == Some(~"fn a(&mut self) -> int")); + } + + #[test] + fn should_add_impl_bounds() { + let doc = mk_doc(~"impl Option { }"); + assert!(doc.cratemod().impls()[0].bounds_str == Some(~"")); + } + + #[test] + fn should_add_impl_trait_types() { + let doc = mk_doc(~"impl j for int { fn a() { } }"); + assert!(doc.cratemod().impls()[0].trait_types[0] == ~"j"); + } + + #[test] + fn should_not_add_impl_trait_types_if_none() { + let doc = mk_doc(~"impl int { fn a() { } }"); + assert!(vec::len(doc.cratemod().impls()[0].trait_types) == 0); + } + + #[test] + fn should_add_impl_self_ty() { + let doc = mk_doc(~"impl int { fn a() { } }"); + assert!(doc.cratemod().impls()[0].self_ty == Some(~"int")); + } + + #[test] + fn should_add_impl_method_sigs() { + let doc = mk_doc(~"impl int { fn a(&self) -> int { fail!() } }"); + assert!(doc.cratemod().impls()[0].methods[0].sig + == Some(~"fn a(&self) -> int")); + } + + #[test] + fn should_add_type_signatures() { + let doc = mk_doc(~"type t = int;"); + assert!(doc.cratemod().types()[0].sig == Some(~"type t = int")); + } + + #[test] + fn should_add_struct_defs() { + let doc = mk_doc(~"struct S { field: () }"); + assert!((&doc.cratemod().structs()[0].sig).get().contains( + "struct S {")); + } + + #[test] + fn should_not_serialize_struct_drop_blocks() { + // All we care about are the fields + let doc = mk_doc(~"struct S { field: (), drop { } }"); + assert!(!(&doc.cratemod().structs()[0].sig).get().contains("drop")); + } + + #[test] + fn should_not_serialize_struct_attrs() { + // All we care about are the fields + let doc = mk_doc(~"#[wut] struct S { field: () }"); + assert!(!(&doc.cratemod().structs()[0].sig).get().contains("wut")); + } } From 68583a25a0b31bc113cf1f4ec479339cbf876e4d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 16:19:01 -0700 Subject: [PATCH 214/403] core::rt: Restructure context switches to take ownership of the Scheduler In order to do a context switch you have to give up ownership of the scheduler, effectively passing it to the next execution context. This could help avoid some situations here tasks retain unsafe pointers to schedulers between context switches, across which they may have changed threads. There are still a number of uses of unsafe scheduler pointers. --- src/libcore/rt/sched/mod.rs | 115 ++++++++++++++++++++++-------------- src/libcore/rt/uvio.rs | 41 +++++++------ 2 files changed, 94 insertions(+), 62 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index a2a440ba76eae..2aaf0a444551c 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -20,6 +20,7 @@ use super::context::Context; #[cfg(test)] use super::uvio::UvEventLoop; #[cfg(test)] use unstable::run_in_bare_thread; #[cfg(test)] use int; +#[cfg(test)] use cell::Cell; mod local; @@ -46,14 +47,14 @@ pub struct Scheduler { // complaining type UnsafeTaskReceiver = sys::Closure; trait HackAroundBorrowCk { - fn from_fn(&fn(&mut Scheduler, ~Task)) -> Self; - fn to_fn(self) -> &fn(&mut Scheduler, ~Task); + fn from_fn(&fn(~Task)) -> Self; + fn to_fn(self) -> &fn(~Task); } impl HackAroundBorrowCk for UnsafeTaskReceiver { - fn from_fn(f: &fn(&mut Scheduler, ~Task)) -> UnsafeTaskReceiver { + fn from_fn(f: &fn(~Task)) -> UnsafeTaskReceiver { unsafe { transmute(f) } } - fn to_fn(self) -> &fn(&mut Scheduler, ~Task) { + fn to_fn(self) -> &fn(~Task) { unsafe { transmute(self) } } } @@ -97,10 +98,12 @@ pub impl Scheduler { let scheduler = Scheduler::unsafe_local_borrow(); fn run_scheduler_once() { - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); if scheduler.resume_task_from_queue() { // Ok, a task ran. Nice! We'll do it again later - scheduler.event_loop.callback(run_scheduler_once); + do Scheduler::local_borrow |scheduler| { + scheduler.event_loop.callback(run_scheduler_once); + } } } @@ -124,9 +127,13 @@ pub impl Scheduler { local::put(sched); } + fn local_take() -> ~Scheduler { + local::take() + } + // * Scheduler-context operations - fn resume_task_from_queue(&mut self) -> bool { + fn resume_task_from_queue(~self) -> bool { assert!(!self.in_task_context()); let mut self = self; @@ -137,12 +144,14 @@ pub impl Scheduler { } None => { rtdebug!("no tasks in queue"); + local::put(self); return false; } } } - fn resume_task_immediately(&mut self, task: ~Task) { + fn resume_task_immediately(~self, task: ~Task) { + let mut self = self; assert!(!self.in_task_context()); rtdebug!("scheduling a task"); @@ -151,20 +160,22 @@ pub impl Scheduler { self.current_task = Some(task); self.enqueue_cleanup_job(DoNothing); + local::put(self); + // Take pointers to both the task and scheduler's saved registers. - { - let (sched_context, _, next_task_context) = self.get_contexts(); - let next_task_context = next_task_context.unwrap(); - // Context switch to the task, restoring it's registers - // and saving the scheduler's - Context::swap(sched_context, next_task_context); - } + let sched = Scheduler::unsafe_local_borrow(); + let (sched_context, _, next_task_context) = sched.get_contexts(); + let next_task_context = next_task_context.unwrap(); + // Context switch to the task, restoring it's registers + // and saving the scheduler's + Context::swap(sched_context, next_task_context); + let sched = Scheduler::unsafe_local_borrow(); // The running task should have passed ownership elsewhere - assert!(self.current_task.is_none()); + assert!(sched.current_task.is_none()); // Running tasks may have asked us to do some cleanup - self.run_cleanup_job(); + sched.run_cleanup_job(); } @@ -172,18 +183,23 @@ pub impl Scheduler { /// Called by a running task to end execution, after which it will /// be recycled by the scheduler for reuse in a new task. - fn terminate_current_task(&mut self) { + fn terminate_current_task(~self) { + let mut self = self; assert!(self.in_task_context()); rtdebug!("ending running task"); let dead_task = self.current_task.swap_unwrap(); self.enqueue_cleanup_job(RecycleTask(dead_task)); - { - let (sched_context, last_task_context, _) = self.get_contexts(); - let last_task_context = last_task_context.unwrap(); - Context::swap(last_task_context, sched_context); - } + + local::put(self); + + let sched = Scheduler::unsafe_local_borrow(); + let (sched_context, last_task_context, _) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); + + // Control never reaches here } /// Block a running task, context switch to the scheduler, then pass the @@ -194,22 +210,25 @@ pub impl Scheduler { /// The closure here is a *stack* closure that lives in the /// running task. It gets transmuted to the scheduler's lifetime /// and called while the task is blocked. - fn deschedule_running_task_and_then(&mut self, f: &fn(&mut Scheduler, ~Task)) { + fn deschedule_running_task_and_then(~self, f: &fn(~Task)) { + let mut self = self; assert!(self.in_task_context()); rtdebug!("blocking task"); let blocked_task = self.current_task.swap_unwrap(); let f_fake_region = unsafe { - transmute::<&fn(&mut Scheduler, ~Task), &fn(&mut Scheduler, ~Task)>(f) + transmute::<&fn(~Task), &fn(~Task)>(f) }; let f_opaque = HackAroundBorrowCk::from_fn(f_fake_region); self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); - { - let (sched_context, last_task_context, _) = self.get_contexts(); - let last_task_context = last_task_context.unwrap(); - Context::swap(last_task_context, sched_context); - } + + local::put(self); + + let sched = Scheduler::unsafe_local_borrow(); + let (sched_context, last_task_context, _) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); // We could be executing in a different thread now let sched = Scheduler::unsafe_local_borrow(); @@ -219,7 +238,8 @@ pub impl Scheduler { /// Switch directly to another task, without going through the scheduler. /// You would want to think hard about doing this, e.g. if there are /// pending I/O events it would be a bad idea. - fn resume_task_from_running_task_direct(&mut self, next_task: ~Task) { + fn resume_task_from_running_task_direct(~self, next_task: ~Task) { + let mut self = self; assert!(self.in_task_context()); rtdebug!("switching tasks"); @@ -227,12 +247,14 @@ pub impl Scheduler { let old_running_task = self.current_task.swap_unwrap(); self.enqueue_cleanup_job(RescheduleTask(old_running_task)); self.current_task = Some(next_task); - { - let (_, last_task_context, next_task_context) = self.get_contexts(); - let last_task_context = last_task_context.unwrap(); - let next_task_context = next_task_context.unwrap(); - Context::swap(last_task_context, next_task_context); - } + + local::put(self); + + let sched = Scheduler::unsafe_local_borrow(); + let (_, last_task_context, next_task_context) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + let next_task_context = next_task_context.unwrap(); + Context::swap(last_task_context, next_task_context); // We could be executing in a different thread now let sched = Scheduler::unsafe_local_borrow(); @@ -261,7 +283,7 @@ pub impl Scheduler { self.task_queue.push_front(task); } RecycleTask(task) => task.recycle(&mut self.stack_pool), - GiveTask(task, f) => (f.to_fn())(self, task) + GiveTask(task, f) => (f.to_fn())(task) } } @@ -338,7 +360,7 @@ pub impl Task { start(); - let sched = Scheduler::unsafe_local_borrow(); + let sched = Scheduler::local_take(); sched.terminate_current_task(); }; return wrapper; @@ -398,7 +420,7 @@ fn test_swap_tasks() { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - let sched = Scheduler::unsafe_local_borrow(); + let mut sched = Scheduler::local_take(); let task2 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } }; @@ -463,7 +485,7 @@ fn test_run_a_lot_of_tasks_direct() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - let sched = Scheduler::unsafe_local_borrow(); + let mut sched = Scheduler::local_take(); let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -483,11 +505,14 @@ fn test_block_task() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); + let sched = Scheduler::local_take(); assert!(sched.in_task_context()); - do sched.deschedule_running_task_and_then() |sched, task| { - assert!(!sched.in_task_context()); - sched.task_queue.push_back(task); + do sched.deschedule_running_task_and_then() |task| { + let task = Cell(task); + do Scheduler::local_borrow |sched| { + assert!(!sched.in_task_context()); + sched.task_queue.push_back(task.take()); + } } }; sched.task_queue.push_back(task); diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index a43ec07c2de11..e3fed29ddd283 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -104,14 +104,16 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context - do scheduler.deschedule_running_task_and_then |scheduler, task| { + do scheduler.deschedule_running_task_and_then |task| { rtdebug!("connect: entered scheduler context"); - assert!(!scheduler.in_task_context()); + do Scheduler::local_borrow |scheduler| { + assert!(!scheduler.in_task_context()); + } let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); let task_cell = Cell(task); @@ -131,7 +133,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(maybe_stream); } // Context switch - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -176,10 +178,10 @@ impl TcpListener for UvTcpListener { let server_tcp_watcher = self.watcher(); - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); assert!(scheduler.in_task_context()); - do scheduler.deschedule_running_task_and_then |_, task| { + do scheduler.deschedule_running_task_and_then |task| { let task_cell = Cell(task); let mut server_tcp_watcher = server_tcp_watcher; do server_tcp_watcher.listen |server_stream_watcher, status| { @@ -199,7 +201,7 @@ impl TcpListener for UvTcpListener { rtdebug!("resuming task from listen"); // Context switch - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -239,13 +241,15 @@ impl Stream for UvStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; - do scheduler.deschedule_running_task_and_then |scheduler, task| { + do scheduler.deschedule_running_task_and_then |task| { rtdebug!("read: entered scheduler context"); - assert!(!scheduler.in_task_context()); + do Scheduler::local_borrow |scheduler| { + assert!(!scheduler.in_task_context()); + } let mut watcher = watcher; let task_cell = Cell(task); // XXX: We shouldn't reallocate these callbacks every @@ -271,7 +275,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -283,11 +287,11 @@ impl Stream for UvStream { fn write(&mut self, buf: &[u8]) -> Result<(), ()> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; - do scheduler.deschedule_running_task_and_then |_, task| { + do scheduler.deschedule_running_task_and_then |task| { let mut watcher = watcher; let task_cell = Cell(task); let buf = unsafe { &*buf_ptr }; @@ -302,7 +306,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -404,12 +408,15 @@ fn test_read_and_block() { } reads += 1; - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = Scheduler::local_take(); // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it - do scheduler.deschedule_running_task_and_then |scheduler, task| { - scheduler.task_queue.push_back(task); + do scheduler.deschedule_running_task_and_then |task| { + let task = Cell(task); + do Scheduler::local_borrow |scheduler| { + scheduler.task_queue.push_back(task.take()); + } } } From a581926f57d8fe9afaa792f26240ad1ff1288377 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 15 Apr 2013 03:12:19 -0400 Subject: [PATCH 215/403] update RELEASES.txt --- RELEASES.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/RELEASES.txt b/RELEASES.txt index 19ba7d3466dc2..13e4e0c2039cc 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -1,5 +1,17 @@ +Version 0.7 (July 2013) +----------------------- + + * ??? changes, numerous bugfixes + + * Semantic changes + * The `self` parameter no longer implicitly means `&'self self`, and can be explicitly marked + with a lifetime. + + * Libraries + * New `core::iterator` module for external iterator objects + Version 0.6 (April 2013) ---------------------------- +------------------------ * ~2100 changes, numerous bugfixes From f82c96446f7577cc29c71ed793a531c9189e7039 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 15 Apr 2013 10:30:16 -0400 Subject: [PATCH 216/403] iterator: use an IteratorUtil trait --- src/libcore/iterator.rs | 69 ++++++++++++++++++++++------------------- src/libstd/treemap.rs | 6 ++-- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index e7a2f3a392888..fcb5102d4c07c 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -12,20 +12,46 @@ use prelude::*; -pub trait Iterator { +pub trait Iterator { /// Advance the iterator and return the next value. Return `None` when the end is reached. - fn next(&mut self) -> Option; + fn next(&mut self) -> Option; } -/// A shim implementing the `for` loop iteration protocol for iterator objects -#[inline] -pub fn advance>(iter: &mut U, f: &fn(T) -> bool) { - loop { - match iter.next() { - Some(x) => { - if !f(x) { return } +pub trait IteratorUtil { + fn zip>(self, other: U) -> ZipIterator; + // FIXME: #5898: should be called map + fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; + fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; + fn advance(&mut self, f: &fn(A) -> bool); +} + +impl> IteratorUtil for T { + #[inline(always)] + fn zip>(self, other: U) -> ZipIterator { + ZipIterator{a: self, b: other} + } + + // FIXME: #5898: should be called map + #[inline(always)] + fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> { + MapIterator{iter: self, f: f} + } + + #[inline(always)] + fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> { + FilterIterator{iter: self, predicate: predicate} + } + + /// A shim implementing the `for` loop iteration protocol for iterator objects + #[inline] + fn advance(&mut self, f: &fn(A) -> bool) { + loop { + match self.next() { + Some(x) => { + if !f(x) { return } + } + None => return } - None => return } } } @@ -35,13 +61,6 @@ pub struct ZipIterator { priv b: U } -pub impl, U: Iterator> ZipIterator { - #[inline(always)] - fn new(a: T, b: U) -> ZipIterator { - ZipIterator{a: a, b: b} - } -} - impl, U: Iterator> Iterator<(A, B)> for ZipIterator { #[inline] fn next(&mut self) -> Option<(A, B)> { @@ -57,17 +76,10 @@ pub struct FilterIterator<'self, A, T> { priv predicate: &'self fn(&A) -> bool } -pub impl<'self, A, T: Iterator> FilterIterator<'self, A, T> { - #[inline(always)] - fn new(iter: T, predicate: &'self fn(&A) -> bool) -> FilterIterator<'self, A, T> { - FilterIterator{iter: iter, predicate: predicate} - } -} - impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { #[inline] fn next(&mut self) -> Option { - for advance(self) |x| { + for self.iter.advance |x| { if (self.predicate)(&x) { return Some(x); } else { @@ -83,13 +95,6 @@ pub struct MapIterator<'self, A, B, T> { priv f: &'self fn(A) -> B } -pub impl<'self, A, B, T: Iterator> MapIterator<'self, A, B, T> { - #[inline(always)] - fn new(iter: T, f: &'self fn(A) -> B) -> MapIterator<'self, A, B, T> { - MapIterator{iter: iter, f: f} - } -} - impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { #[inline] fn next(&mut self) -> Option { diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index bc8cbaa0825ce..ac887c7fdc41d 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -996,7 +996,7 @@ mod test_treemap { (&x5, &y5)]; let mut i = 0; - for advance(&mut b) |x| { + for b.advance |x| { assert!(expected[i] == x); i += 1; @@ -1005,7 +1005,7 @@ mod test_treemap { } } - for advance(&mut b) |x| { + for b.advance |x| { assert!(expected[i] == x); i += 1; } @@ -1209,7 +1209,7 @@ mod test_set { let x = x; let y = y; - let mut z = ZipIterator::new(x.iter(), y.iter()); + let mut z = x.iter().zip(y.iter()); // FIXME: #5801: this needs a type hint to compile... let result: Option<(&uint, & &'static str)> = z.next(); From ed74ac169e3e79ff4ce59329a06223e23f2b99b6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 18:26:05 -0700 Subject: [PATCH 217/403] core::rt: Narrow down the unsafety of the thread-local scheduler Only when borrowing the I/O implementation do we need unsafety --- src/libcore/rt/sched/mod.rs | 52 +++++++++++++++++++++---------------- src/libcore/rt/uvio.rs | 42 +++++++++++++----------------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 2aaf0a444551c..8fb8e2a1d102a 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -14,7 +14,7 @@ use cast::transmute; use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; -use super::rtio::{EventLoop, EventLoopObject}; +use super::rtio::{EventLoop, EventLoopObject, IoFactoryObject}; use super::context::Context; #[cfg(test)] use super::uvio::UvEventLoop; @@ -96,12 +96,12 @@ pub impl Scheduler { // Give ownership of the scheduler (self) to the thread local::put(self); - let scheduler = Scheduler::unsafe_local_borrow(); + let scheduler = unsafe { local::borrow() }; fn run_scheduler_once() { - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); if scheduler.resume_task_from_queue() { // Ok, a task ran. Nice! We'll do it again later - do Scheduler::local_borrow |scheduler| { + do Scheduler::borrow_local |scheduler| { scheduler.event_loop.callback(run_scheduler_once); } } @@ -113,21 +113,27 @@ pub impl Scheduler { return local::take(); } - /// Get a mutable pointer to the thread-local scheduler. + /// Get a mutable pointer to the thread-local I/O /// # Safety Note /// This allows other mutable aliases to the scheduler, both in the current /// execution context and other execution contexts. - fn unsafe_local_borrow() -> &mut Scheduler { - unsafe { local::borrow() } + unsafe fn borrow_local_io() -> &mut IoFactoryObject { + unsafe { + let io = local::borrow().event_loop.io().unwrap(); + transmute::<&mut IoFactoryObject, &mut IoFactoryObject>(io) + } } - fn local_borrow(f: &fn(&mut Scheduler)) { + /// Borrow the thread-local scheduler from thread-local storage. + /// While the scheduler is borrowed it is not available in TLS. + fn borrow_local(f: &fn(&mut Scheduler)) { let mut sched = local::take(); f(sched); local::put(sched); } - fn local_take() -> ~Scheduler { + /// Take ownership of the scheduler from thread local storage + fn take_local() -> ~Scheduler { local::take() } @@ -163,14 +169,14 @@ pub impl Scheduler { local::put(self); // Take pointers to both the task and scheduler's saved registers. - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; let (sched_context, _, next_task_context) = sched.get_contexts(); let next_task_context = next_task_context.unwrap(); // Context switch to the task, restoring it's registers // and saving the scheduler's Context::swap(sched_context, next_task_context); - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; // The running task should have passed ownership elsewhere assert!(sched.current_task.is_none()); @@ -194,7 +200,7 @@ pub impl Scheduler { local::put(self); - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; let (sched_context, last_task_context, _) = sched.get_contexts(); let last_task_context = last_task_context.unwrap(); Context::swap(last_task_context, sched_context); @@ -225,13 +231,13 @@ pub impl Scheduler { local::put(self); - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; let (sched_context, last_task_context, _) = sched.get_contexts(); let last_task_context = last_task_context.unwrap(); Context::swap(last_task_context, sched_context); // We could be executing in a different thread now - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; sched.run_cleanup_job(); } @@ -250,14 +256,14 @@ pub impl Scheduler { local::put(self); - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; let (_, last_task_context, next_task_context) = sched.get_contexts(); let last_task_context = last_task_context.unwrap(); let next_task_context = next_task_context.unwrap(); Context::swap(last_task_context, next_task_context); // We could be executing in a different thread now - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; sched.run_cleanup_job(); } @@ -355,12 +361,12 @@ pub impl Task { // This is the first code to execute after the initial // context switch to the task. The previous context may // have asked us to do some cleanup. - let sched = Scheduler::unsafe_local_borrow(); + let sched = unsafe { local::borrow() }; sched.run_cleanup_job(); start(); - let sched = Scheduler::local_take(); + let sched = Scheduler::take_local(); sched.terminate_current_task(); }; return wrapper; @@ -420,7 +426,7 @@ fn test_swap_tasks() { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - let mut sched = Scheduler::local_take(); + let mut sched = Scheduler::take_local(); let task2 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } }; @@ -452,7 +458,7 @@ fn test_run_a_lot_of_tasks_queued() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::local_borrow |sched| { + do Scheduler::borrow_local |sched| { let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -485,7 +491,7 @@ fn test_run_a_lot_of_tasks_direct() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - let mut sched = Scheduler::local_take(); + let mut sched = Scheduler::take_local(); let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -505,11 +511,11 @@ fn test_block_task() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::local_take(); + let sched = Scheduler::take_local(); assert!(sched.in_task_context()); do sched.deschedule_running_task_and_then() |task| { let task = Cell(task); - do Scheduler::local_borrow |sched| { + do Scheduler::borrow_local |sched| { assert!(!sched.in_task_context()); sched.task_queue.push_back(task.take()); } diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index e3fed29ddd283..051d4ee7df9d3 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -104,14 +104,14 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context do scheduler.deschedule_running_task_and_then |task| { rtdebug!("connect: entered scheduler context"); - do Scheduler::local_borrow |scheduler| { + do Scheduler::borrow_local |scheduler| { assert!(!scheduler.in_task_context()); } let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); @@ -133,7 +133,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(maybe_stream); } // Context switch - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -178,7 +178,7 @@ impl TcpListener for UvTcpListener { let server_tcp_watcher = self.watcher(); - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); assert!(scheduler.in_task_context()); do scheduler.deschedule_running_task_and_then |task| { @@ -201,7 +201,7 @@ impl TcpListener for UvTcpListener { rtdebug!("resuming task from listen"); // Context switch - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -241,13 +241,13 @@ impl Stream for UvStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; do scheduler.deschedule_running_task_and_then |task| { rtdebug!("read: entered scheduler context"); - do Scheduler::local_borrow |scheduler| { + do Scheduler::borrow_local |scheduler| { assert!(!scheduler.in_task_context()); } let mut watcher = watcher; @@ -275,7 +275,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -287,7 +287,7 @@ impl Stream for UvStream { fn write(&mut self, buf: &[u8]) -> Result<(), ()> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; @@ -306,7 +306,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -322,8 +322,7 @@ fn test_simple_io_no_connect() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let addr = Ipv4(127, 0, 0, 1, 2926); let maybe_chan = io.connect(addr); assert!(maybe_chan.is_none()); @@ -341,16 +340,14 @@ fn test_simple_tcp_server_and_client() { let addr = Ipv4(127, 0, 0, 1, 2929); let client_task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let mut stream = io.connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.close(); }; let server_task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let mut listener = io.bind(addr).unwrap(); let mut stream = listener.listen().unwrap(); let mut buf = [0, .. 2048]; @@ -378,8 +375,7 @@ fn test_read_and_block() { let addr = Ipv4(127, 0, 0, 1, 2930); let client_task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let mut stream = io.connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -389,8 +385,7 @@ fn test_read_and_block() { }; let server_task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let mut listener = io.bind(addr).unwrap(); let mut stream = listener.listen().unwrap(); let mut buf = [0, .. 2048]; @@ -408,13 +403,13 @@ fn test_read_and_block() { } reads += 1; - let scheduler = Scheduler::local_take(); + let scheduler = Scheduler::take_local(); // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it do scheduler.deschedule_running_task_and_then |task| { let task = Cell(task); - do Scheduler::local_borrow |scheduler| { + do Scheduler::borrow_local |scheduler| { scheduler.task_queue.push_back(task.take()); } } @@ -441,8 +436,7 @@ fn test_read_read_read() { let addr = Ipv4(127, 0, 0, 1, 2931); let client_task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::unsafe_local_borrow(); - let io = sched.event_loop.io().unwrap(); + let io = unsafe { Scheduler::borrow_local_io() }; let mut stream = io.connect(addr).unwrap(); let mut buf = [0, .. 2048]; let mut total_bytes_read = 0; From 1f94364aeff935eebadd3ae47dbae3eb099023da Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 15 Apr 2013 18:56:39 -0700 Subject: [PATCH 218/403] core::rt: Clean up some more hacks --- src/libcore/rt/sched/mod.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 8fb8e2a1d102a..08c52d8e8d4e4 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -46,17 +46,13 @@ pub struct Scheduler { // XXX: Some hacks to put a &fn in Scheduler without borrowck // complaining type UnsafeTaskReceiver = sys::Closure; -trait HackAroundBorrowCk { +trait ClosureConverter { fn from_fn(&fn(~Task)) -> Self; fn to_fn(self) -> &fn(~Task); } -impl HackAroundBorrowCk for UnsafeTaskReceiver { - fn from_fn(f: &fn(~Task)) -> UnsafeTaskReceiver { - unsafe { transmute(f) } - } - fn to_fn(self) -> &fn(~Task) { - unsafe { transmute(self) } - } +impl ClosureConverter for UnsafeTaskReceiver { + fn from_fn(f: &fn(~Task)) -> UnsafeTaskReceiver { unsafe { transmute(f) } } + fn to_fn(self) -> &fn(~Task) { unsafe { transmute(self) } } } enum CleanupJob { @@ -223,10 +219,8 @@ pub impl Scheduler { rtdebug!("blocking task"); let blocked_task = self.current_task.swap_unwrap(); - let f_fake_region = unsafe { - transmute::<&fn(~Task), &fn(~Task)>(f) - }; - let f_opaque = HackAroundBorrowCk::from_fn(f_fake_region); + let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) }; + let f_opaque = ClosureConverter::from_fn(f_fake_region); self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); local::put(self); From 40e3577b0834794b2d44e6c527fda90d1adbc88e Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 16 Apr 2013 12:04:49 +1000 Subject: [PATCH 219/403] libcore: missed an import for a test --- src/libcore/at_vec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 337b0722ce7ab..532dcf6157b54 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -282,6 +282,7 @@ pub mod raw { #[cfg(test)] mod test { use super::*; + use prelude::*; #[test] fn test() { From 39d45b75cc4971a9fd5797c120b362612ff23b13 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 15 Apr 2013 19:06:36 -0700 Subject: [PATCH 220/403] rustc: Anti-copy police --- src/librustc/metadata/encoder.rs | 6 +++--- src/librustc/middle/trans/base.rs | 13 +++++-------- src/librustc/middle/trans/common.rs | 4 ++-- src/librustc/middle/trans/glue.rs | 26 ++++++++++++-------------- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index b9f0f63040aef..cc86d50af4288 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -63,7 +63,7 @@ pub struct EncodeParams { reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: @mut HashMap, - discrim_symbols: @mut HashMap, + discrim_symbols: @mut HashMap, link_meta: LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item @@ -90,7 +90,7 @@ pub struct EncodeContext { reachable: reachable::map, reexports2: middle::resolve::ExportMap2, item_symbols: @mut HashMap, - discrim_symbols: @mut HashMap, + discrim_symbols: @mut HashMap, link_meta: LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item, @@ -285,7 +285,7 @@ fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) { fn encode_discriminant(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); - ebml_w.writer.write(str::to_bytes(*ecx.discrim_symbols.get(&id))); + ebml_w.writer.write(str::to_bytes(**ecx.discrim_symbols.get(&id))); ebml_w.end_tag(); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f58e066526c24..cd6b23aadadd5 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -468,11 +468,9 @@ pub fn set_glue_inlining(f: ValueRef, t: ty::t) { // Double-check that we never ask LLVM to declare the same symbol twice. It // silently mangles such symbols, breaking our linkage model. -pub fn note_unique_llvm_symbol(ccx: @CrateContext, +sym: ~str) { - // XXX: this should not be necessary - use core::container::Set; +pub fn note_unique_llvm_symbol(ccx: @CrateContext, sym: @~str) { if ccx.all_llvm_symbols.contains(&sym) { - ccx.sess.bug(~"duplicate LLVM symbol: " + sym); + ccx.sess.bug(~"duplicate LLVM symbol: " + *sym); } ccx.all_llvm_symbols.insert(sym); } @@ -2576,11 +2574,10 @@ pub fn trans_constant(ccx: @CrateContext, it: @ast::item) { path_name(variant.node.name), path_name(special_idents::descrim) ]); - let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); + let s = @mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); let disr_val = vi[i].disr_val; - // XXX: Bad copy. - note_unique_llvm_symbol(ccx, copy s); - let discrim_gvar = str::as_c_str(s, |buf| { + note_unique_llvm_symbol(ccx, s); + let discrim_gvar = str::as_c_str(*s, |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf) } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 4701a166ea766..f14096443b2b7 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -173,7 +173,7 @@ pub struct CrateContext { link_meta: LinkMeta, enum_sizes: @mut HashMap, discrims: @mut HashMap, - discrim_symbols: @mut HashMap, + discrim_symbols: @mut HashMap, tydescs: @mut HashMap, // Set when running emit_tydescs to enforce that no more tydescs are // created. @@ -215,7 +215,7 @@ pub struct CrateContext { symbol_hasher: @hash::State, type_hashcodes: @mut HashMap, type_short_names: @mut HashMap, - all_llvm_symbols: @mut HashSet<~str>, + all_llvm_symbols: @mut HashSet<@~str>, tcx: ty::ctxt, maps: astencode::Maps, stats: @mut Stats, diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index d8c8301a83563..827f4afaf783c 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -684,15 +684,14 @@ pub fn declare_tydesc(ccx: @CrateContext, t: ty::t) -> @mut tydesc_info { let llalign = llalign_of(ccx, llty); let addrspace = declare_tydesc_addrspace(ccx, t); //XXX this triggers duplicate LLVM symbols - let name = if false /*ccx.sess.opts.debuginfo*/ { + let name = @(if false /*ccx.sess.opts.debuginfo*/ { mangle_internal_name_by_type_only(ccx, t, ~"tydesc") } else { mangle_internal_name_by_seq(ccx, ~"tydesc") - }; - // XXX: Bad copy. - note_unique_llvm_symbol(ccx, copy name); - debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name); - let gvar = str::as_c_str(name, |buf| { + }); + note_unique_llvm_symbol(ccx, name); + debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), *name); + let gvar = str::as_c_str(*name, |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf) } @@ -718,17 +717,16 @@ pub fn declare_generic_glue(ccx: @CrateContext, t: ty::t, llfnty: TypeRef, +name: ~str) -> ValueRef { let _icx = ccx.insn_ctxt("declare_generic_glue"); let name = name; - let mut fn_nm; //XXX this triggers duplicate LLVM symbols - if false /*ccx.sess.opts.debuginfo*/ { - fn_nm = mangle_internal_name_by_type_only(ccx, t, (~"glue_" + name)); + let fn_nm = @(if false /*ccx.sess.opts.debuginfo*/ { + mangle_internal_name_by_type_only(ccx, t, (~"glue_" + name)) } else { - fn_nm = mangle_internal_name_by_seq(ccx, (~"glue_" + name)); - } - debug!("%s is for type %s", fn_nm, ppaux::ty_to_str(ccx.tcx, t)); + mangle_internal_name_by_seq(ccx, (~"glue_" + name)) + }); + debug!("%s is for type %s", *fn_nm, ppaux::ty_to_str(ccx.tcx, t)); // XXX: Bad copy. - note_unique_llvm_symbol(ccx, copy fn_nm); - let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty); + note_unique_llvm_symbol(ccx, fn_nm); + let llfn = decl_cdecl_fn(ccx.llmod, *fn_nm, llfnty); set_glue_inlining(llfn, t); return llfn; } From 21723d5bdc7032d1b541a68aaed4e313b72280ee Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 16 Apr 2013 23:00:16 +1000 Subject: [PATCH 221/403] libcore: vec::windowed iterates, not allocates. --- src/libcore/vec.rs | 57 +++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 7940502d27e48..30201304d6191 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1495,16 +1495,35 @@ pub fn each_permutation(v: &[T], put: &fn(ts: &[T]) -> bool) { } } -pub fn windowed(nn: uint, xx: &[TT]) -> ~[~[TT]] { - let mut ww = ~[]; - assert!(1u <= nn); - for vec::eachi (xx) |ii, _x| { - let len = xx.len(); - if ii+nn <= len { - ww.push(slice(xx, ii, ii+nn).to_vec()); - } +/** + * Iterate over all contiguous windows of length `n` of the vector `v`. + * + * # Example + * + * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`) + * + * ~~~ + * for windowed(2, &[1,2,3,4]) |v| { + * io::println(fmt!("%?", v)); + * } + * ~~~ + * + */ +#[cfg(stage0)] // XXX: lifetimes! +pub fn windowed(n: uint, v: &[T], it: &fn(&[T]) -> bool) { + assert!(1u <= n); + for uint::range(0, v.len() - n + 1) |i| { + if !it(v.slice(i, i+n)) { return } + } +} +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) { + assert!(1u <= n); + for uint::range(0, v.len() - n + 1) |i| { + if !it(v.slice(i, i + n)) { return } } - ww } /** @@ -3761,20 +3780,26 @@ mod tests { #[test] fn test_windowed () { - assert!(~[~[1u,2u,3u],~[2u,3u,4u],~[3u,4u,5u],~[4u,5u,6u]] - == windowed (3u, ~[1u,2u,3u,4u,5u,6u])); - - assert!(~[~[1u,2u,3u,4u],~[2u,3u,4u,5u],~[3u,4u,5u,6u]] - == windowed (4u, ~[1u,2u,3u,4u,5u,6u])); + fn t(n: uint, expected: &[&[int]]) { + let mut i = 0; + for windowed(n, ~[1,2,3,4,5,6]) |v| { + assert_eq!(v, expected[i]); + i += 1; + } - assert!(~[] == windowed (7u, ~[1u,2u,3u,4u,5u,6u])); + // check that we actually iterated the right number of times + assert_eq!(i, expected.len()); + } + t(3, &[&[1,2,3],&[2,3,4],&[3,4,5],&[4,5,6]]); + t(4, &[&[1,2,3,4],&[2,3,4,5],&[3,4,5,6]]); + t(7, &[]); } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_windowed_() { - let _x = windowed (0u, ~[1u,2u,3u,4u,5u,6u]); + for windowed (0u, ~[1u,2u,3u,4u,5u,6u]) |_v| {} } #[test] From 313a5ab94622532c4de316ed6d82b0788be31266 Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 3 Apr 2013 09:41:40 -0700 Subject: [PATCH 222/403] move interner_key macro --- src/libsyntax/ast.rs | 8 -------- src/libsyntax/parse/token.rs | 10 ---------- src/libsyntax/syntax.rc | 10 +++++++--- src/libsyntax/util/interner.rs | 16 +++++++++++++++- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9c20012d42e6b..5b5768d1d1c75 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -22,14 +22,6 @@ use core::to_str::ToStr; use std::serialize::{Encodable, Decodable, Encoder, Decoder}; -/* can't import macros yet, so this is copied from token.rs. See its comment - * there. */ -macro_rules! interner_key ( - () => (cast::transmute::<(uint, uint), - &fn(+v: @@::parse::token::ident_interner)>( - (-3 as uint, 0u))) -) - // an identifier contains an index into the interner // table and a SyntaxContext to track renaming and // macro expansion per Flatt et al., "Macros diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 54b2ad8514781..706821e198536 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -374,16 +374,6 @@ pub impl ident_interner { } } -/* Key for thread-local data for sneaking interner information to the - * encoder/decoder. It sounds like a hack because it is one. - * Bonus ultra-hack: functions as keys don't work across crates, - * so we have to use a unique number. See taskgroup_key! in task.rs - * for another case of this. */ -macro_rules! interner_key ( - () => (cast::transmute::<(uint, uint), &fn(+v: @@token::ident_interner)>( - (-3 as uint, 0u))) -) - pub fn mk_ident_interner() -> @ident_interner { unsafe { match task::local_data::local_data_get(interner_key!()) { diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 56b17fb8d0a72..c1b857a6cdba7 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -30,6 +30,13 @@ extern mod std(vers = "0.7-pre"); use core::*; +// allow the interner_key macro +// to escape this module: +#[macro_escape] +pub mod util { + pub mod interner; +} + pub mod syntax { pub use ext; pub use parse; @@ -45,9 +52,6 @@ pub mod ast_util; pub mod ast_map; pub mod visit; pub mod fold; -pub mod util { - pub mod interner; -} #[path = "parse/mod.rs"] diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 1133fd850d84b..75bcac1b16306 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -12,6 +12,9 @@ // allows bidirectional lookup; i.e. given a value, one can easily find the // type, and vice versa. +// allow the interner_key macro to escape this module: +#[macro_escape]; + use core::prelude::*; use core::hashmap::HashMap; @@ -66,6 +69,17 @@ pub impl Interner { fn len(&self) -> uint { let vect = &*self.vect; vect.len() } } +/* Key for thread-local data for sneaking interner information to the +* encoder/decoder. It sounds like a hack because it is one. +* Bonus ultra-hack: functions as keys don't work across crates, +* so we have to use a unique number. See taskgroup_key! in task.rs +* for another case of this. */ +macro_rules! interner_key ( + () => (cast::transmute::<(uint, uint), + &fn(+v: @@::parse::token::ident_interner)>( + (-3 as uint, 0u))) +) + #[cfg(test)] mod tests { use super::*; @@ -109,4 +123,4 @@ mod tests { assert_eq!(i.get(2), @~"Carol"); assert_eq!(i.intern(@~"Bob"), 1); } -} \ No newline at end of file +} From 1083ae6b06939292c104f2a71fb2ebfaf9a2c70e Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 10 Apr 2013 16:19:54 -0700 Subject: [PATCH 223/403] better error message on failure to parse type --- src/libsyntax/parse/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fb3e8a5ded5a8..360742b37b7dc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -698,7 +698,8 @@ pub impl Parser { let path = self.parse_path_with_tps(false); ty_path(path, self.get_id()) } else { - self.fatal(~"expected type"); + self.fatal(fmt!("expected type, found token %?", + *self.token)); }; let sp = mk_sp(lo, self.last_span.hi); From 7e4cd09e2e57aae38d837531a7af1de00461d416 Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 3 Apr 2013 10:28:14 -0700 Subject: [PATCH 224/403] added MTWT functions --- src/libsyntax/ast.rs | 124 +++++++++++---- src/libsyntax/ast_util.rs | 275 ++++++++++++++++++++++++++++++++++ src/libsyntax/ext/expand.rs | 47 ++++++ src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/parse/token.rs | 80 +++++----- 5 files changed, 462 insertions(+), 66 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5b5768d1d1c75..6f4693adb9f4a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -27,32 +27,48 @@ use std::serialize::{Encodable, Decodable, Encoder, Decoder}; // macro expansion per Flatt et al., "Macros // That Work Together" #[deriving(Eq)] -pub struct ident { repr: Name } +pub struct ident { repr: Name, ctxt: SyntaxContext } // a SyntaxContext represents a chain of macro-expandings // and renamings. Each macro expansion corresponds to // a fresh uint + +// I'm representing this syntax context as an index into +// a table, in order to work around a compiler bug +// that's causing unreleased memory to cause core dumps +// and also perhaps to save some work in destructor checks. +// the special uint '0' will be used to indicate an empty +// syntax context + +// this uint is a reference to a table stored in thread-local +// storage. +pub type SyntaxContext = uint; + +pub type SCTable = ~[SyntaxContext_]; +pub static empty_ctxt : uint = 0; + #[deriving(Eq)] -pub enum SyntaxContext { - MT, - Mark (Mrk,~SyntaxContext), - Rename (~ident,Name,~SyntaxContext) +#[auto_encode] +#[auto_decode] +pub enum SyntaxContext_ { + EmptyCtxt, + Mark (Mrk,SyntaxContext), + // flattening the name and syntaxcontext into the rename... + // HIDDEN INVARIANTS: + // 1) the first name in a Rename node + // can only be a programmer-supplied name. + // 2) Every Rename node with a given Name in the + // "to" slot must have the same name and context + // in the "from" slot. In essence, they're all + // pointers to a single "rename" event node. + Rename (ident,Name,SyntaxContext) } -/* -// ** this is going to have to apply to paths, not to idents. -// Returns true if these two identifiers access the same -// local binding or top-level binding... that's what it -// should do. For now, it just compares the names. -pub fn free_ident_eq (a : ident, b: ident) -> bool{ - a.repr == b.repr -} -*/ -// a name represents a string, interned -type Name = uint; +// a name represents an identifier +pub type Name = uint; // a mark represents a unique id associated // with a macro expansion -type Mrk = uint; +pub type Mrk = uint; impl Encodable for ident { fn encode(&self, s: &S) { @@ -1302,22 +1318,77 @@ pub enum inlined_item { ii_dtor(struct_dtor, ident, Generics, def_id /* parent id */) } +/* hold off on tests ... they appear in a later merge. #[cfg(test)] mod test { - //are asts encodable? - - // it looks like this *will* be a compiler bug, after - // I get deriving_eq for crates into incoming :) - /* + use core::option::{None, Option, Some}; + use core::uint; use std; use codemap::*; use super::*; + + #[test] fn xorpush_test () { + let mut s = ~[]; + xorPush(&mut s,14); + assert_eq!(s,~[14]); + xorPush(&mut s,14); + assert_eq!(s,~[]); + xorPush(&mut s,14); + assert_eq!(s,~[14]); + xorPush(&mut s,15); + assert_eq!(s,~[14,15]); + xorPush (&mut s,16); + assert_eq! (s,~[14,15,16]); + xorPush (&mut s,16); + assert_eq! (s,~[14,15]); + xorPush (&mut s,15); + assert_eq! (s,~[14]); + } + + #[test] fn test_marksof () { + let stopname = uints_to_name(&~[12,14,78]); + let name1 = uints_to_name(&~[4,9,7]); + assert_eq!(marksof (MT,stopname),~[]); + assert_eq! (marksof (Mark (4,@Mark(98,@MT)),stopname),~[4,98]); + // does xoring work? + assert_eq! (marksof (Mark (5, @Mark (5, @Mark (16,@MT))),stopname), + ~[16]); + // does nested xoring work? + assert_eq! (marksof (Mark (5, + @Mark (10, + @Mark (10, + @Mark (5, + @Mark (16,@MT))))), + stopname), + ~[16]); + // stop has no effect on marks + assert_eq! (marksof (Mark (9, @Mark (14, @Mark (12, @MT))),stopname), + ~[9,14,12]); + // rename where stop doesn't match: + assert_eq! (marksof (Mark (9, @Rename + (name1, + @Mark (4, @MT), + uints_to_name(&~[100,101,102]), + @Mark (14, @MT))), + stopname), + ~[9,14]); + // rename where stop does match + ; + assert_eq! (marksof (Mark(9, @Rename (name1, + @Mark (4, @MT), + stopname, + @Mark (14, @MT))), + stopname), + ~[9]); + } + + // are ASTs encodable? #[test] fn check_asts_encodable() { let bogus_span = span {lo:BytePos(10), hi:BytePos(20), expn_info:None}; - let _e : crate = + let e : crate = spanned{ node: crate_{ module: _mod {view_items: ~[], items: ~[]}, @@ -1326,10 +1397,13 @@ mod test { }, span: bogus_span}; // doesn't matter which encoder we use.... - let _f = (_e as std::serialize::Encodable::); + let _f = (@e as @std::serialize::Encodable); } - */ + + } + +*/ // // Local Variables: // mode: rust diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index e83a3ef8bad52..59a640bb57163 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -24,6 +24,7 @@ use core::str; use core::to_bytes; use core::vec; + pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str { // FIXME: Bad copies (#2543 -- same for everything else that says "bad") str::connect(idents.map(|i| copy *intr.get(*i)), ~"::") @@ -587,6 +588,280 @@ pub enum Privacy { Public } +// HYGIENE FUNCTIONS + +/// Construct an identifier with the given repr and an empty context: +pub fn mk_ident(repr: uint) -> ident { ident {repr: repr, ctxt: 0}} + +/// Extend a syntax context with a given mark +pub fn mk_mark (m:Mrk,ctxt:SyntaxContext,table:&mut SCTable) + -> SyntaxContext { + idx_push(table,Mark(m,ctxt)) +} + +/// Extend a syntax context with a given rename +pub fn mk_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable) + -> SyntaxContext { + idx_push(table,Rename(id,to,tail)) +} + +/// Make a fresh syntax context table with EmptyCtxt in slot zero +pub fn mk_sctable() -> SCTable { ~[EmptyCtxt] } + +/// Add a value to the end of a vec, return its index +fn idx_push(vec: &mut ~[T], +val: T) -> uint { + vec.push(val); + vec.len() - 1 +} + +/// Resolve a syntax object to a name, per MTWT. +pub fn resolve (id : ident, table : &SCTable) -> Name { + match table[id.ctxt] { + EmptyCtxt => id.repr, + // ignore marks here: + Mark(_,subctxt) => resolve (ident{repr:id.repr, ctxt: subctxt},table), + // do the rename if necessary: + Rename(ident{repr,ctxt},toname,subctxt) => { + // this could be cached or computed eagerly: + let resolvedfrom = resolve(ident{repr:repr,ctxt:ctxt},table); + let resolvedthis = resolve(ident{repr:id.repr,ctxt:subctxt},table); + if ((resolvedthis == resolvedfrom) + && (marksof (ctxt,resolvedthis,table) + == marksof (subctxt,resolvedthis,table))) { + toname + } else { + resolvedthis + } + } + } +} + +/// Compute the marks associated with a syntax context. +// it's not clear to me whether it's better to use a [] mutable +// vector or a cons-list for this. +pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] { + let mut result = ~[]; + let mut loopvar = ctxt; + loop { + match table[loopvar] { + EmptyCtxt => {return result;}, + Mark(mark,tl) => { + xorPush(&mut result,mark); + loopvar = tl; + }, + Rename(_,name,tl) => { + // see MTWT for details on the purpose of the stopname. + // short version: it prevents duplication of effort. + if (name == stopname) { + return result; + } else { + loopvar = tl; + } + } + } + } +} + +/// Push a name... unless it matches the one on top, in which +/// case pop and discard (so two of the same marks cancel) +pub fn xorPush(marks: &mut ~[uint], mark: uint) { + if ((marks.len() > 0) && (getLast(marks) == mark)) { + marks.pop(); + } else { + marks.push(mark); + } +} + +// get the last element of a mutable array. +// FIXME #4903: , must be a separate procedure for now. +pub fn getLast(arr: &~[Mrk]) -> uint { + *arr.last() +} + + +#[cfg(test)] +mod test { + use ast::*; + use super::*; + use core::io; + + #[test] fn xorpush_test () { + let mut s = ~[]; + xorPush(&mut s,14); + assert_eq!(s,~[14]); + xorPush(&mut s,14); + assert_eq!(s,~[]); + xorPush(&mut s,14); + assert_eq!(s,~[14]); + xorPush(&mut s,15); + assert_eq!(s,~[14,15]); + xorPush (&mut s,16); + assert_eq! (s,~[14,15,16]); + xorPush (&mut s,16); + assert_eq! (s,~[14,15]); + xorPush (&mut s,15); + assert_eq! (s,~[14]); + } + + // convert a list of uints to an @~[ident] + // (ignores the interner completely) + fn uints_to_idents (uints: &~[uint]) -> @~[ident] { + @uints.map(|u|{ ident {repr:*u, ctxt: empty_ctxt} }) + } + + fn id (u : uint, s: SyntaxContext) -> ident { + ident{repr:u, ctxt: s} + } + + // because of the SCTable, I now need a tidy way of + // creating syntax objects. Sigh. + #[deriving(Eq)] + enum TestSC { + M(Mrk), + R(ident,Name) + } + + // unfold a vector of TestSC values into a SCTable, + // returning the resulting index + fn unfold_test_sc(tscs : ~[TestSC], tail: SyntaxContext, table : &mut SCTable) + -> SyntaxContext { + tscs.foldr(tail, |tsc : &TestSC,tail : SyntaxContext| + {match *tsc { + M(mrk) => mk_mark(mrk,tail,table), + R(ident,name) => mk_rename(ident,name,tail,table)}}) + } + + // gather a SyntaxContext back into a vector of TestSCs + fn refold_test_sc(mut sc: SyntaxContext, table : &SCTable) -> ~[TestSC] { + let mut result = ~[]; + loop { + match table[sc] { + EmptyCtxt => {return result;}, + Mark(mrk,tail) => { + result.push(M(mrk)); + sc = tail; + loop; + }, + Rename(id,name,tail) => { + result.push(R(id,name)); + sc = tail; + loop; + } + } + } + } + + #[test] fn test_unfold_refold(){ + let mut t = mk_sctable(); + + let test_sc = ~[M(3),R(id(101,0),14),M(9)]; + assert_eq!(unfold_test_sc(test_sc,empty_ctxt,&mut t),3); + assert_eq!(t[1],Mark(9,0)); + assert_eq!(t[2],Rename(id(101,0),14,1)); + assert_eq!(t[3],Mark(3,2)); + assert_eq!(refold_test_sc(3,&t),test_sc); + } + + + // extend a syntax context with a sequence of marks given + // in a vector. v[0] will be the outermost mark. + fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext { + mrks.foldr(tail, |mrk:&Mrk,tail:SyntaxContext| + {mk_mark(*mrk,tail,table)}) + } + + #[test] fn unfold_marks_test() { + let mut t = ~[EmptyCtxt]; + + assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),2); + assert_eq!(t[1],Mark(7,0)); + assert_eq!(t[2],Mark(3,1)); + } + + #[test] fn test_marksof () { + let stopname = 242; + let name1 = 243; + let mut t = mk_sctable(); + assert_eq!(marksof (empty_ctxt,stopname,&t),~[]); + // FIXME #5074: ANF'd to dodge nested calls + { let ans = unfold_marks(~[4,98],empty_ctxt,&mut t); + assert_eq! (marksof (ans,stopname,&t),~[4,98]);} + // does xoring work? + { let ans = unfold_marks(~[5,5,16],empty_ctxt,&mut t); + assert_eq! (marksof (ans,stopname,&t), ~[16]);} + // does nested xoring work? + { let ans = unfold_marks(~[5,10,10,5,16],empty_ctxt,&mut t); + assert_eq! (marksof (ans, stopname,&t), ~[16]);} + // rename where stop doesn't match: + { let chain = ~[M(9), + R(id(name1, + mk_mark (4, empty_ctxt,&mut t)), + 100101102), + M(14)]; + let ans = unfold_test_sc(chain,empty_ctxt,&mut t); + assert_eq! (marksof (ans, stopname, &t), ~[9,14]);} + // rename where stop does match + { let name1sc = mk_mark(4, empty_ctxt, &mut t); + let chain = ~[M(9), + R(id(name1, name1sc), + stopname), + M(14)]; + let ans = unfold_test_sc(chain,empty_ctxt,&mut t); + assert_eq! (marksof (ans, stopname, &t), ~[9]); } + } + + + #[test] fn resolve_tests () { + let a = 40; + let mut t = mk_sctable(); + // - ctxt is MT + assert_eq!(resolve(id(a,empty_ctxt),&t),a); + // - simple ignored marks + { let sc = unfold_marks(~[1,2,3],empty_ctxt,&mut t); + assert_eq!(resolve(id(a,sc),&t),a);} + // - orthogonal rename where names don't match + { let sc = unfold_test_sc(~[R(id(50,empty_ctxt),51),M(12)],empty_ctxt,&mut t); + assert_eq!(resolve(id(a,sc),&t),a);} + // - rename where names do match, but marks don't + { let sc1 = mk_mark(1,empty_ctxt,&mut t); + let sc = unfold_test_sc(~[R(id(a,sc1),50), + M(1), + M(2)], + empty_ctxt,&mut t); + assert_eq!(resolve(id(a,sc),&t), a);} + // - rename where names and marks match + { let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t); + let sc = unfold_test_sc(~[R(id(a,sc1),50),M(1),M(2)],empty_ctxt,&mut t); + assert_eq!(resolve(id(a,sc),&t), 50); } + // - rename where names and marks match by literal sharing + { let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t); + let sc = unfold_test_sc(~[R(id(a,sc1),50)],sc1,&mut t); + assert_eq!(resolve(id(a,sc),&t), 50); } + // - two renames of the same var.. can only happen if you use + // local-expand to prevent the inner binding from being renamed + // during the rename-pass caused by the first: + io::println("about to run bad test"); + { let sc = unfold_test_sc(~[R(id(a,empty_ctxt),50), + R(id(a,empty_ctxt),51)], + empty_ctxt,&mut t); + assert_eq!(resolve(id(a,sc),&t), 51); } + // the simplest double-rename: + { let a_to_a50 = mk_rename(id(a,empty_ctxt),50,empty_ctxt,&mut t); + let a50_to_a51 = mk_rename(id(a,a_to_a50),51,a_to_a50,&mut t); + assert_eq!(resolve(id(a,a50_to_a51),&t),51); + // mark on the outside doesn't stop rename: + let sc = mk_mark(9,a50_to_a51,&mut t); + assert_eq!(resolve(id(a,sc),&t),51); + // but mark on the inside does: + let a50_to_a51_b = unfold_test_sc(~[R(id(a,a_to_a50),51), + M(9)], + a_to_a50, + &mut t); + assert_eq!(resolve(id(a,a50_to_a51_b),&t),50);} + } + +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 09498f09a2927..430402a8982fc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -547,6 +547,53 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess, @f.fold_crate(&*c) } +// given a function from paths to paths, produce +// an ast_fold that applies that function: +fn fun_to_path_folder(f: @fn(&ast::Path)->ast::Path) -> @ast_fold{ + let afp = default_ast_fold(); + let f_pre = @AstFoldFns{ + fold_path : |p, _| f(p), + .. *afp + }; + make_fold(f_pre) +} +/* going to have to figure out whether the table is passed in or +extracted from TLS... +// update the ctxts in a path to get a rename node +fn ctxt_update_rename(from: ast::Name, + fromctx: ast::SyntaxContext, to: ast::Name) -> + @fn(&ast::Path,@ast_fold)->ast::Path { + return |p:&ast::Path,_| + ast::Path {span: p.span, + global: p.global, + idents: p.idents.map(|id| + ast::ident{ + repr: id.repr, + // this needs to be cached.... + ctxt: Some(@ast::Rename(from,fromctx, + to,id.ctxt)) + }), + rp: p.rp, + types: p.types}; +} + +// update the ctxts in a path to get a mark node +fn ctxt_update_mark(mark: uint) -> + @fn(&ast::Path,@ast_fold)->ast::Path { + return |p:&ast::Path,_| + ast::Path {span: p.span, + global: p.global, + idents: p.idents.map(|id| + ast::ident{ + repr: id.repr, + // this needs to be cached.... + ctxt: Some(@ast::Mark(mark,id.ctxt)) + }), + rp: p.rp, + types: p.types}; +} +*/ + #[cfg(test)] mod test { use super::*; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 360742b37b7dc..dbdf30b434ff5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4280,7 +4280,7 @@ pub impl Parser { rp: None, types: ~[] }; return @spanned(lo, self.span.hi, - view_path_glob(path, self.get_id())); + view_path_glob(path, self.get_id())); } _ => break diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 706821e198536..cf05a4375a8a5 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -309,50 +309,50 @@ pub fn is_bar(t: &Token) -> bool { pub mod special_idents { use ast::ident; - pub static underscore : ident = ident { repr: 0u }; - pub static anon : ident = ident { repr: 1u }; - pub static dtor : ident = ident { repr: 2u }; // 'drop', but that's + pub static underscore : ident = ident { repr: 0u, ctxt: 0}; + pub static anon : ident = ident { repr: 1u, ctxt: 0}; + pub static dtor : ident = ident { repr: 2u, ctxt: 0}; // 'drop', but that's // reserved - pub static invalid : ident = ident { repr: 3u }; // '' - pub static unary : ident = ident { repr: 4u }; - pub static not_fn : ident = ident { repr: 5u }; - pub static idx_fn : ident = ident { repr: 6u }; - pub static unary_minus_fn : ident = ident { repr: 7u }; - pub static clownshoes_extensions : ident = ident { repr: 8u }; + pub static invalid : ident = ident { repr: 3u, ctxt: 0}; // '' + pub static unary : ident = ident { repr: 4u, ctxt: 0}; + pub static not_fn : ident = ident { repr: 5u, ctxt: 0}; + pub static idx_fn : ident = ident { repr: 6u, ctxt: 0}; + pub static unary_minus_fn : ident = ident { repr: 7u, ctxt: 0}; + pub static clownshoes_extensions : ident = ident { repr: 8u, ctxt: 0}; - pub static self_ : ident = ident { repr: 9u }; // 'self' + pub static self_ : ident = ident { repr: 9u, ctxt: 0}; // 'self' /* for matcher NTs */ - pub static item : ident = ident { repr: 10u }; - pub static block : ident = ident { repr: 11u }; - pub static stmt : ident = ident { repr: 12u }; - pub static pat : ident = ident { repr: 13u }; - pub static expr : ident = ident { repr: 14u }; - pub static ty : ident = ident { repr: 15u }; - pub static ident : ident = ident { repr: 16u }; - pub static path : ident = ident { repr: 17u }; - pub static tt : ident = ident { repr: 18u }; - pub static matchers : ident = ident { repr: 19u }; - - pub static str : ident = ident { repr: 20u }; // for the type + pub static item : ident = ident { repr: 10u, ctxt: 0}; + pub static block : ident = ident { repr: 11u, ctxt: 0}; + pub static stmt : ident = ident { repr: 12u, ctxt: 0}; + pub static pat : ident = ident { repr: 13u, ctxt: 0}; + pub static expr : ident = ident { repr: 14u, ctxt: 0}; + pub static ty : ident = ident { repr: 15u, ctxt: 0}; + pub static ident : ident = ident { repr: 16u, ctxt: 0}; + pub static path : ident = ident { repr: 17u, ctxt: 0}; + pub static tt : ident = ident { repr: 18u, ctxt: 0}; + pub static matchers : ident = ident { repr: 19u, ctxt: 0}; + + pub static str : ident = ident { repr: 20u, ctxt: 0}; // for the type /* outside of libsyntax */ - pub static ty_visitor : ident = ident { repr: 21u }; - pub static arg : ident = ident { repr: 22u }; - pub static descrim : ident = ident { repr: 23u }; - pub static clownshoe_abi : ident = ident { repr: 24u }; - pub static clownshoe_stack_shim : ident = ident { repr: 25u }; - pub static tydesc : ident = ident { repr: 26u }; - pub static literally_dtor : ident = ident { repr: 27u }; - pub static main : ident = ident { repr: 28u }; - pub static opaque : ident = ident { repr: 29u }; - pub static blk : ident = ident { repr: 30u }; - pub static static : ident = ident { repr: 31u }; - pub static intrinsic : ident = ident { repr: 32u }; - pub static clownshoes_foreign_mod: ident = ident { repr: 33 }; - pub static unnamed_field: ident = ident { repr: 34 }; - pub static c_abi: ident = ident { repr: 35 }; - pub static type_self: ident = ident { repr: 36 }; // `Self` + pub static ty_visitor : ident = ident { repr: 21u, ctxt: 0}; + pub static arg : ident = ident { repr: 22u, ctxt: 0}; + pub static descrim : ident = ident { repr: 23u, ctxt: 0}; + pub static clownshoe_abi : ident = ident { repr: 24u, ctxt: 0}; + pub static clownshoe_stack_shim : ident = ident { repr: 25u, ctxt: 0}; + pub static tydesc : ident = ident { repr: 26u, ctxt: 0}; + pub static literally_dtor : ident = ident { repr: 27u, ctxt: 0}; + pub static main : ident = ident { repr: 28u, ctxt: 0}; + pub static opaque : ident = ident { repr: 29u, ctxt: 0}; + pub static blk : ident = ident { repr: 30u, ctxt: 0}; + pub static static : ident = ident { repr: 31u, ctxt: 0}; + pub static intrinsic : ident = ident { repr: 32u, ctxt: 0}; + pub static clownshoes_foreign_mod: ident = ident { repr: 33u, ctxt: 0}; + pub static unnamed_field: ident = ident { repr: 34u, ctxt: 0}; + pub static c_abi: ident = ident { repr: 35u, ctxt: 0}; + pub static type_self: ident = ident { repr: 36u, ctxt: 0}; // `Self` } pub struct ident_interner { @@ -361,10 +361,10 @@ pub struct ident_interner { pub impl ident_interner { fn intern(&self, val: @~str) -> ast::ident { - ast::ident { repr: self.interner.intern(val) } + ast::ident { repr: self.interner.intern(val), ctxt: 0} } fn gensym(&self, val: @~str) -> ast::ident { - ast::ident { repr: self.interner.gensym(val) } + ast::ident { repr: self.interner.gensym(val), ctxt: 0} } fn get(&self, idx: ast::ident) -> @~str { self.interner.get(idx.repr) From e7aa24de18bb1be6764c90bc08fecb322aeb7154 Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 15 Apr 2013 16:13:42 -0700 Subject: [PATCH 225/403] add self.token_to_str and is_any_keyword convenience abstractions --- src/libsyntax/parse/common.rs | 35 ++++++++++++++++++++------- src/libsyntax/parse/parser.rs | 45 ++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index ae7dd8ff96fce..f353d94894a43 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -47,17 +47,29 @@ pub fn seq_sep_none() -> SeqSep { } } +// maps any token back to a string. not necessary if you know it's +// an identifier.... pub fn token_to_str(reader: @reader, token: &token::Token) -> ~str { token::to_str(reader.interner(), token) } pub impl Parser { + // convert a token to a string using self's reader + fn token_to_str(&self, token: &token::Token) -> ~str { + token::to_str(self.reader.interner(), token) + } + + // convert the current token to a string using self's reader + fn this_token_to_str(&self) -> ~str { + self.token_to_str(self.token) + } + fn unexpected_last(&self, t: &token::Token) -> ! { self.span_fatal( *self.last_span, fmt!( "unexpected token: `%s`", - token_to_str(self.reader, t) + self.token_to_str(t) ) ); } @@ -66,7 +78,7 @@ pub impl Parser { self.fatal( fmt!( "unexpected token: `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -80,8 +92,8 @@ pub impl Parser { self.fatal( fmt!( "expected `%s` but found `%s`", - token_to_str(self.reader, t), - token_to_str(self.reader, © *self.token) + self.token_to_str(t), + self.this_token_to_str() ) ) } @@ -104,7 +116,7 @@ pub impl Parser { self.fatal( fmt!( "expected ident, found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -128,12 +140,15 @@ pub impl Parser { // Storing keywords as interned idents instead of strings would be nifty. // A sanity check that the word we are asking for is a known keyword + // NOTE: this could be done statically.... fn require_keyword(&self, word: &~str) { if !self.keywords.contains(word) { self.bug(fmt!("unknown keyword: %s", *word)); } } + // return true when this token represents the given string, and is not + // followed immediately by :: . fn token_is_word(&self, word: &~str, tok: &token::Token) -> bool { match *tok { token::IDENT(sid, false) => { *self.id_to_str(sid) == *word } @@ -150,6 +165,10 @@ pub impl Parser { self.token_is_keyword(word, © *self.token) } + fn id_is_any_keyword(&self, id: ast::ident) -> bool { + self.keywords.contains(self.id_to_str(id)) + } + fn is_any_keyword(&self, tok: &token::Token) -> bool { match *tok { token::IDENT(sid, false) => { @@ -182,7 +201,7 @@ pub impl Parser { fmt!( "expected `%s`, found `%s`", *word, - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -248,9 +267,9 @@ pub impl Parser { ); } else { let mut s: ~str = ~"expected `"; - s += token_to_str(self.reader, &token::GT); + s += self.token_to_str(&token::GT); s += ~"`, found `"; - s += token_to_str(self.reader, © *self.token); + s += self.this_token_to_str(); s += ~"`"; self.fatal(s); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index dbdf30b434ff5..c1f781f8570e0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -66,7 +66,7 @@ use codemap::{span, BytePos, spanned, mk_sp}; use codemap; use parse::attr::parser_attr; use parse::classify; -use parse::common::{seq_sep_none, token_to_str}; +use parse::common::{seq_sep_none}; use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed}; use parse::lexer::reader; use parse::lexer::TokenAndSpan; @@ -252,8 +252,11 @@ pub fn Parser(sess: @mut ParseSess, pub struct Parser { sess: @mut ParseSess, cfg: crate_cfg, + // the current token: token: @mut token::Token, + // the span of the current token: span: @mut span, + // the span of the prior token: last_span: @mut span, buffer: @mut [TokenAndSpan, ..4], buffer_start: @mut int, @@ -499,7 +502,7 @@ pub impl Parser { let hi = p.last_span.hi; debug!("parse_trait_methods(): trait method signature ends in \ `%s`", - token_to_str(p.reader, © *p.token)); + self.this_token_to_str()); match *p.token { token::SEMI => { p.bump(); @@ -541,7 +544,7 @@ pub impl Parser { p.fatal( fmt!( "expected `;` or `}` but found `%s`", - token_to_str(p.reader, © *p.token) + self.this_token_to_str() ) ); } @@ -1456,6 +1459,11 @@ pub impl Parser { fn parse_token_tree(&self) -> token_tree { maybe_whole!(deref self, nt_tt); + // this is the fall-through for the 'match' below. + // invariants: the current token is not a left-delimiter, + // not an EOF, and not the desired right-delimiter (if + // it were, parse_seq_to_before_end would have prevented + // reaching this point. fn parse_non_delim_tt_tok(p: &Parser) -> token_tree { maybe_whole!(deref p, nt_tt); match *p.token { @@ -1464,7 +1472,7 @@ pub impl Parser { p.fatal( fmt!( "incorrect close delimiter: `%s`", - token_to_str(p.reader, © *p.token) + p.this_token_to_str() ) ); } @@ -1506,18 +1514,17 @@ pub impl Parser { match *self.token { token::EOF => { - self.fatal(~"file ended in the middle of a macro invocation"); + self.fatal(~"file ended with unbalanced delimiters"); } token::LPAREN | token::LBRACE | token::LBRACKET => { - // tjc: ?????? - let ket = token::flip_delimiter(&*self.token); + let close_delim = token::flip_delimiter(&*self.token); tt_delim( vec::append( // the open delimiter: ~[parse_any_tt_tok(self)], vec::append( self.parse_seq_to_before_end( - &ket, + &close_delim, seq_sep_none(), |p| p.parse_token_tree() ), @@ -1531,6 +1538,8 @@ pub impl Parser { } } + // parse a stream of tokens into a list of token_trees, + // up to EOF. fn parse_all_token_trees(&self) -> ~[token_tree] { let mut tts = ~[]; while *self.token != token::EOF { @@ -2053,6 +2062,7 @@ pub impl Parser { return e; } + // parse the RHS of a local variable declaration (e.g. '= 14;') fn parse_initializer(&self) -> Option<@expr> { match *self.token { token::EQ => { @@ -2139,7 +2149,7 @@ pub impl Parser { self.fatal( fmt!( "expected `}`, found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -2407,6 +2417,7 @@ pub impl Parser { pat_ident(binding_mode, name, sub) } + // parse a local variable declaration fn parse_local(&self, is_mutbl: bool, allow_init: bool) -> @local { let lo = self.span.lo; @@ -2652,7 +2663,7 @@ pub impl Parser { fmt!( "expected `;` or `}` after \ expression but found `%s`", - token_to_str(self.reader, &t) + self.token_to_str(&t) ) ); } @@ -2867,7 +2878,7 @@ pub impl Parser { self.fatal( fmt!( "expected `self` but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -2991,7 +3002,7 @@ pub impl Parser { self.fatal( fmt!( "expected `,` or `)`, found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -3271,7 +3282,7 @@ pub impl Parser { fmt!( "expected `{`, `(`, or `;` after struct name \ but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -3321,7 +3332,7 @@ pub impl Parser { copy *self.span, fmt!( "expected `;`, `,`, or '}' but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -3423,7 +3434,7 @@ pub impl Parser { self.fatal( fmt!( "expected item but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -3683,7 +3694,7 @@ pub impl Parser { copy *self.span, fmt!( "expected `{` or `mod` but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } @@ -3696,7 +3707,7 @@ pub impl Parser { copy *self.span, fmt!( "expected foreign module name but found `%s`", - token_to_str(self.reader, © *self.token) + self.this_token_to_str() ) ); } From caffe127c78617b4c5eea8adaae17f20a816b651 Mon Sep 17 00:00:00 2001 From: gareth Date: Tue, 16 Apr 2013 21:23:44 +0100 Subject: [PATCH 226/403] Fix issue 2626 by un-ignoring the mysterious test_leaks, which does currently seem to work on win32 (and linux). --- src/libcore/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 8e247a25012f1..9e6524c25cb29 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -520,7 +520,7 @@ mod tests { use run; // Regression test for memory leaks - #[ignore(cfg(windows))] // FIXME (#2626) + #[test] fn test_leaks() { run::run_program("echo", []); run::start_program("echo", []); From c6f7b595f0bb3d8388a6bb89afc457a4702ec374 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 13:40:47 -0700 Subject: [PATCH 227/403] More valgrind suppressions --- src/etc/x86.supp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/etc/x86.supp b/src/etc/x86.supp index d592e5b7deba2..028bde2e73ff8 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -654,3 +654,11 @@ fun:_ZN5visit30visit_struct_dtor_helper_* ... } + +{ + llvm-optimization-reads-uninitialized-memory-16 + Memcheck:Cond + fun:_ZN7ast_map6map_fn* + fun:_ZN5visit30visit_struct_dtor_helper* + ... +} From 97303703eec8e80003b4ffe729ad4df3ded1445c Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 2 Apr 2013 03:40:57 -0400 Subject: [PATCH 228/403] Allow casting to mutable trait objects. --- src/librustc/metadata/tydecode.rs | 16 ++++--- src/librustc/metadata/tyencode.rs | 13 ++++-- src/librustc/middle/kind.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/glue.rs | 8 ++-- src/librustc/middle/trans/monomorphize.rs | 2 +- src/librustc/middle/trans/reflect.rs | 2 +- src/librustc/middle/trans/type_of.rs | 4 +- src/librustc/middle/trans/type_use.rs | 2 +- src/librustc/middle/ty.rs | 46 ++++++++++--------- src/librustc/middle/typeck/astconv.rs | 7 +-- src/librustc/middle/typeck/check/method.rs | 2 +- src/librustc/middle/typeck/check/regionck.rs | 2 +- src/librustc/middle/typeck/check/vtable.rs | 20 ++++++-- src/librustc/middle/typeck/coherence.rs | 4 +- src/librustc/middle/typeck/infer/combine.rs | 8 ++-- src/librustc/middle/typeck/infer/mod.rs | 5 +- src/librustc/util/ppaux.rs | 18 +++++--- .../cast-immutable-mutable-trait.rs | 28 +++++++++++ src/test/run-pass/cast-mutable-trait.rs | 34 ++++++++++++++ 21 files changed, 162 insertions(+), 65 deletions(-) create mode 100644 src/test/compile-fail/cast-immutable-mutable-trait.rs create mode 100644 src/test/run-pass/cast-mutable-trait.rs diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index f52ff056472f9..41ebf14a9a8bc 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -313,8 +313,9 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { let def = parse_def(st, NominalType, conv); let substs = parse_substs(st, conv); let store = parse_trait_store(st); + let mt = parse_mutability(st); assert!(next(st) == ']'); - return ty::mk_trait(st.tcx, def, substs, store); + return ty::mk_trait(st.tcx, def, substs, store, mt); } 'p' => { let did = parse_def(st, TypeParameter, conv); @@ -396,13 +397,16 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } } -fn parse_mt(st: @mut PState, conv: conv_did) -> ty::mt { - let mut m; +fn parse_mutability(st: @mut PState) -> ast::mutability { match peek(st) { - 'm' => { next(st); m = ast::m_mutbl; } - '?' => { next(st); m = ast::m_const; } - _ => { m = ast::m_imm; } + 'm' => { next(st); ast::m_mutbl } + '?' => { next(st); ast::m_const } + _ => { ast::m_imm } } +} + +fn parse_mt(st: @mut PState, conv: conv_did) -> ty::mt { + let m = parse_mutability(st); ty::mt { ty: parse_ty(st, conv), mutbl: m } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 2e1dd8b6dad86..a9a07d1b41d9d 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -22,6 +22,7 @@ use core::io; use core::uint; use core::vec; use syntax::abi::AbiSet; +use syntax::ast; use syntax::ast::*; use syntax::diagnostic::span_handler; use syntax::print::pprust::*; @@ -113,12 +114,17 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) { } } } -fn enc_mt(w: @io::Writer, cx: @ctxt, mt: ty::mt) { - match mt.mutbl { + +fn enc_mutability(w: @io::Writer, mt: ast::mutability) { + match mt { m_imm => (), m_mutbl => w.write_char('m'), m_const => w.write_char('?') } +} + +fn enc_mt(w: @io::Writer, cx: @ctxt, mt: ty::mt) { + enc_mutability(w, mt.mutbl); enc_ty(w, cx, mt.ty); } @@ -269,12 +275,13 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) { enc_substs(w, cx, (*substs)); w.write_char(']'); } - ty::ty_trait(def, ref substs, store) => { + ty::ty_trait(def, ref substs, store, mt) => { w.write_str(&"x["); w.write_str((cx.ds)(def)); w.write_char('|'); enc_substs(w, cx, (*substs)); enc_trait_store(w, cx, store); + enc_mutability(w, mt); w.write_char(']'); } ty::ty_tup(ts) => { diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index e5fc9f2d60391..59ae4812f2778 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -589,7 +589,7 @@ pub fn check_cast_for_escaping_regions( pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) { let target_ty = ty::expr_ty(cx.tcx, target); match ty::get(target_ty).sty { - ty::ty_trait(_, _, ty::UniqTraitStore) => { + ty::ty_trait(_, _, ty::UniqTraitStore, _) => { let source_ty = ty::expr_ty(cx.tcx, source); if !ty::type_is_owned(cx.tcx, source_ty) { cx.tcx.sess.span_err( diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index c02417aca8b12..c10086aa56c92 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -671,7 +671,7 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) ty::ty_closure(ref _closurety) => { cx.sess.span_bug(span, ~"debuginfo for closure NYI") }, - ty::ty_trait(_did, ref _substs, ref _vstore) => { + ty::ty_trait(_did, ref _substs, ref _vstore, _) => { cx.sess.span_bug(span, ~"debuginfo for trait NYI") }, ty::ty_struct(did, ref substs) => { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index d4a1013e83c85..e75e49f18f380 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -667,7 +667,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, } ast::expr_cast(val, _) => { match ty::get(node_id_type(bcx, expr.id)).sty { - ty::ty_trait(_, _, store) => { + ty::ty_trait(_, _, store, _) => { return meth::trans_trait_cast(bcx, val, expr.id, dest, store); } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 827f4afaf783c..51d4622d6a163 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -551,11 +551,11 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { ty::ty_closure(_) => { closure::make_closure_glue(bcx, v0, t, drop_ty) } - ty::ty_trait(_, _, ty::BoxTraitStore) => { + ty::ty_trait(_, _, ty::BoxTraitStore, _) => { let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u])); decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx)) } - ty::ty_trait(_, _, ty::UniqTraitStore) => { + ty::ty_trait(_, _, ty::UniqTraitStore, _) => { let lluniquevalue = GEPi(bcx, v0, [0, 1]); let lltydesc = Load(bcx, GEPi(bcx, v0, [0, 2])); call_tydesc_glue_full(bcx, lluniquevalue, lltydesc, @@ -617,12 +617,12 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { ty::ty_closure(_) => { closure::make_closure_glue(bcx, v, t, take_ty) } - ty::ty_trait(_, _, ty::BoxTraitStore) => { + ty::ty_trait(_, _, ty::BoxTraitStore, _) => { let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u])); incr_refcnt_of_boxed(bcx, llbox); bcx } - ty::ty_trait(_, _, ty::UniqTraitStore) => { + ty::ty_trait(_, _, ty::UniqTraitStore, _) => { let llval = GEPi(bcx, v, [0, 1]); let lltydesc = Load(bcx, GEPi(bcx, v, [0, 2])); call_tydesc_glue_full(bcx, llval, lltydesc, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 97dc3fed780f0..7aab6367d405a 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -303,7 +303,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, ty::ty_closure(ref fty) => { Some(normalized_closure_ty(tcx, fty.sigil)) } - ty::ty_trait(_, _, ref store) => { + ty::ty_trait(_, _, ref store, _) => { let sigil = match *store { ty::UniqTraitStore => ast::OwnedSigil, ty::BoxTraitStore => ast::ManagedSigil, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 596c55a68f872..e62e19f636a4e 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -323,7 +323,7 @@ pub impl Reflector { } // Miscallaneous extra types - ty::ty_trait(_, _, _) => self.leaf(~"trait"), + ty::ty_trait(_, _, _, _) => self.leaf(~"trait"), ty::ty_infer(_) => self.leaf(~"infer"), ty::ty_err => self.leaf(~"err"), ty::ty_param(ref p) => { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 1c94fe2842219..b9e4bad42dd43 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -133,7 +133,7 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_bare_fn(*) => T_ptr(T_i8()), ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false), - ty::ty_trait(_, _, store) => T_opaque_trait(cx, store), + ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store), ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size), ty::ty_evec(mt, ty::vstore_fixed(size)) => { @@ -249,7 +249,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)), ty::ty_closure(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)), - ty::ty_trait(_, _, store) => T_opaque_trait(cx, store), + ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store), ty::ty_type => T_ptr(cx.tydesc_type), ty::ty_tup(*) => { let repr = adt::represent_type(cx, t); diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 572e9348f63f0..25e3ed0f400a8 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -216,7 +216,7 @@ pub fn type_needs_inner(cx: Context, ty::ty_bare_fn(*) | ty::ty_ptr(_) | ty::ty_rptr(_, _) | - ty::ty_trait(_, _, _) => false, + ty::ty_trait(_, _, _, _) => false, ty::ty_enum(did, ref substs) => { if list::find(enums_seen, |id| *id == did).is_none() { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index f62e366ebdcaa..4212b03c41653 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -532,7 +532,7 @@ pub enum sty { ty_rptr(Region, mt), ty_bare_fn(BareFnTy), ty_closure(ClosureTy), - ty_trait(def_id, substs, TraitStore), + ty_trait(def_id, substs, TraitStore, ast::mutability), ty_struct(def_id, substs), ty_tup(~[t]), @@ -946,7 +946,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { &ty_infer(_) => flags |= needs_infer as uint, &ty_self(_) => flags |= has_self as uint, &ty_enum(_, ref substs) | &ty_struct(_, ref substs) | - &ty_trait(_, ref substs, _) => { + &ty_trait(_, ref substs, _, _) => { flags |= sflags(substs); } &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) | @@ -1115,10 +1115,11 @@ pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t { pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, - store: TraitStore) + store: TraitStore, + mutability: ast::mutability) -> t { // take a copy of substs so that we own the vectors inside - mk_t(cx, ty_trait(did, substs, store)) + mk_t(cx, ty_trait(did, substs, store, mutability)) } pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, +substs: substs) -> t { @@ -1214,7 +1215,7 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) { maybe_walk_ty(tm.ty, f); } ty_enum(_, ref substs) | ty_struct(_, ref substs) | - ty_trait(_, ref substs, _) => { + ty_trait(_, ref substs, _, _) => { for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); } } ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } } @@ -1277,8 +1278,8 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty { ty_enum(tid, ref substs) => { ty_enum(tid, fold_substs(substs, fldop)) } - ty_trait(did, ref substs, st) => { - ty_trait(did, fold_substs(substs, fldop), st) + ty_trait(did, ref substs, st, mutbl) => { + ty_trait(did, fold_substs(substs, fldop), st, mutbl) } ty_tup(ref ts) => { let new_ts = ts.map(|tt| fldop(*tt)); @@ -1367,8 +1368,8 @@ pub fn fold_regions_and_ty( ty_struct(def_id, ref substs) => { ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt)) } - ty_trait(def_id, ref substs, st) => { - ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st) + ty_trait(def_id, ref substs, st, mutbl) => { + ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl) } ty_bare_fn(ref f) => { ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt), @@ -1911,16 +1912,19 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { TC_MANAGED + nonowned(tc_mt(cx, mt, cache)) } - ty_trait(_, _, UniqTraitStore) => { + ty_trait(_, _, UniqTraitStore, _) => { TC_OWNED_CLOSURE } - ty_trait(_, _, BoxTraitStore) => { - TC_MANAGED + ty_trait(_, _, BoxTraitStore, mutbl) => { + match mutbl { + ast::m_mutbl => TC_MANAGED + TC_MUTABLE, + _ => TC_MANAGED + } } - ty_trait(_, _, RegionTraitStore(r)) => { - borrowed_contents(r, m_imm) + ty_trait(_, _, RegionTraitStore(r), mutbl) => { + borrowed_contents(r, mutbl) } ty_rptr(r, mt) => { @@ -2241,7 +2245,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool { false // unsafe ptrs can always be NULL } - ty_trait(_, _, _) => { + ty_trait(_, _, _, _) => { false } @@ -2385,7 +2389,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool { ty_box(_) | ty_uniq(_) | ty_closure(_) | ty_estr(vstore_uniq) | ty_estr(vstore_box) | ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) | - ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false, + ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false, // Structural types ty_enum(did, ref substs) => { let variants = enum_variants(cx, did); @@ -2673,8 +2677,8 @@ impl to_bytes::IterBytes for sty { ty_uniq(ref mt) => to_bytes::iter_bytes_2(&19u8, mt, lsb0, f), - ty_trait(ref did, ref substs, ref v) => - to_bytes::iter_bytes_4(&20u8, did, substs, v, lsb0, f), + ty_trait(ref did, ref substs, ref v, ref mutbl) => + to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f), ty_opaque_closure_ptr(ref ck) => to_bytes::iter_bytes_2(&21u8, ck, lsb0, f), @@ -3366,7 +3370,7 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str { ty_rptr(_, _) => ~"&-ptr", ty_bare_fn(_) => ~"extern fn", ty_closure(_) => ~"fn", - ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)), + ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)), ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)), ty_tup(_) => ~"tuple", ty_infer(TyVar(_)) => ~"inferred type", @@ -3679,7 +3683,7 @@ pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] { pub fn ty_to_def_id(ty: t) -> Option { match get(ty).sty { - ty_trait(id, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id), + ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id), _ => None } } @@ -4413,7 +4417,7 @@ pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) { assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name)); let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name); (trait_ref, - mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore)) + mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm)) } // Local Variables: diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index a0c12ff1a204c..9f6ab8704cbd6 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -277,9 +277,9 @@ pub fn ast_ty_to_ty( } return ty::mk_evec(tcx, mt, vst); } - ast::ty_path(path, id) if a_seq_ty.mutbl == ast::m_imm => { + ast::ty_path(path, id) => { match tcx.def_map.find(&id) { - Some(&ast::def_prim_ty(ast::ty_str)) => { + Some(&ast::def_prim_ty(ast::ty_str)) if a_seq_ty.mutbl == ast::m_imm => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); return ty::mk_estr(tcx, vst); } @@ -305,7 +305,8 @@ pub fn ast_ty_to_ty( return ty::mk_trait(tcx, result.def_id, copy result.substs, - trait_store); + trait_store, + a_seq_ty.mutbl); } _ => {} } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 6b09133e73a11..131cef1c7f2f0 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -291,7 +291,7 @@ pub impl<'self> LookupContext<'self> { ty_param(p) => { self.push_inherent_candidates_from_param(self_ty, p); } - ty_trait(did, ref substs, store) => { + ty_trait(did, ref substs, store, _) => { self.push_inherent_candidates_from_trait( self_ty, did, substs, store); self.push_inherent_impl_candidates_for_type(did); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 5594f2a0f658b..dff794c548bd5 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -288,7 +288,7 @@ fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { // explaining how it goes about doing that. let target_ty = rcx.resolve_node_type(expr.id); match ty::get(target_ty).sty { - ty::ty_trait(_, _, ty::RegionTraitStore(trait_region)) => { + ty::ty_trait(_, _, ty::RegionTraitStore(trait_region), _) => { let source_ty = rcx.fcx.expr_ty(source); constrain_regions_in_type(rcx, trait_region, expr.span, source_ty); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 8245dc88114c8..cc7519c1db4ed 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -141,10 +141,11 @@ fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, // use a dummy type just to package up the substs that need fixing up let t = ty::mk_trait(tcx, id, substs, - ty::RegionTraitStore(ty::re_static)); + ty::RegionTraitStore(ty::re_static), + ast::m_imm); do fixup_ty(vcx, location_info, t, is_early).map |t_f| { match ty::get(*t_f).sty { - ty::ty_trait(_, ref substs_f, _) => (/*bad*/copy *substs_f), + ty::ty_trait(_, ref substs_f, _, _) => (/*bad*/copy *substs_f), _ => fail!(~"t_f should be a trait") } } @@ -544,7 +545,12 @@ pub fn early_resolve_expr(ex: @ast::expr, debug!("vtable resolution on expr %s", ex.repr(fcx.tcx())); let target_ty = fcx.expr_ty(ex); match ty::get(target_ty).sty { - ty::ty_trait(target_def_id, ref target_substs, store) => { + ty::ty_trait(target_def_id, ref target_substs, store, target_mutbl) => { + fn mutability_allowed(a_mutbl: ast::mutability, + b_mutbl: ast::mutability) -> bool { + a_mutbl == b_mutbl || + (a_mutbl == ast::m_mutbl && b_mutbl == ast::m_imm) + } // Look up vtables for the type we're casting to, // passing in the source and target type. The source // must be a pointer type suitable to the object sigil, @@ -552,6 +558,14 @@ pub fn early_resolve_expr(ex: @ast::expr, let ty = structurally_resolved_type(fcx, ex.span, fcx.expr_ty(src)); match (&ty::get(ty).sty, store) { + (&ty::ty_box(mt), ty::BoxTraitStore) | + (&ty::ty_uniq(mt), ty::UniqTraitStore) | + (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) + if !mutability_allowed(mt.mutbl, target_mutbl) => { + fcx.tcx().sess.span_err(ex.span, + fmt!("types differ in mutability")); + } + (&ty::ty_box(mt), ty::BoxTraitStore) | (&ty::ty_uniq(mt), ty::UniqTraitStore) | (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 247b8eae2a8db..2afe674db9c55 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -114,7 +114,7 @@ pub fn type_is_defined_in_local_crate(original_type: t) -> bool { do ty::walk_ty(original_type) |t| { match get(t).sty { ty_enum(def_id, _) | - ty_trait(def_id, _, _) | + ty_trait(def_id, _, _, _) | ty_struct(def_id, _) => { if def_id.crate == ast::local_crate { found_nominal = true; @@ -140,7 +140,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt, match get(base_type).sty { ty_enum(def_id, _) | ty_struct(def_id, _) | - ty_trait(def_id, _, _) => { + ty_trait(def_id, _, _, _) => { return Some(def_id); } _ => { diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index be1d291cfe5c9..0bdf2842ccac3 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -525,13 +525,13 @@ pub fn super_tys( } } - (ty::ty_trait(a_id, ref a_substs, a_store), - ty::ty_trait(b_id, ref b_substs, b_store)) - if a_id == b_id => { + (ty::ty_trait(a_id, ref a_substs, a_store, a_mutbl), + ty::ty_trait(b_id, ref b_substs, b_store, b_mutbl)) + if a_id == b_id && a_mutbl == b_mutbl => { let trait_def = ty::lookup_trait_def(tcx, a_id); do self.substs(&trait_def.generics, a_substs, b_substs).chain |substs| { do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| { - Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s)) + Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s, a_mutbl)) } } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 58de0122c8c9b..3cefe7646def2 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -737,10 +737,11 @@ pub impl InferCtxt { let dummy0 = ty::mk_trait(self.tcx, trait_ref.def_id, copy trait_ref.substs, - ty::UniqTraitStore); + ty::UniqTraitStore, + ast::m_imm); let dummy1 = self.resolve_type_vars_if_possible(dummy0); match ty::get(dummy1).sty { - ty::ty_trait(ref def_id, ref substs, _) => { + ty::ty_trait(ref def_id, ref substs, _, _) => { ty::TraitRef {def_id: *def_id, substs: copy *substs} } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9b9e0e81b4346..c0c6fe2d9d323 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -224,16 +224,20 @@ pub fn region_to_str_space(cx: ctxt, prefix: &str, region: Region) -> ~str { } } +fn mutability_to_str(m: ast::mutability) -> ~str { + match m { + ast::m_mutbl => ~"mut ", + ast::m_imm => ~"", + ast::m_const => ~"const " + } +} + pub fn mt_to_str(cx: ctxt, m: &mt) -> ~str { mt_to_str_wrapped(cx, "", m, "") } pub fn mt_to_str_wrapped(cx: ctxt, before: &str, m: &mt, after: &str) -> ~str { - let mstr = match m.mutbl { - ast::m_mutbl => "mut ", - ast::m_imm => "", - ast::m_const => "const " - }; + let mstr = mutability_to_str(m.mutbl); return fmt!("%s%s%s%s", mstr, before, ty_to_str(cx, m.ty), after); } @@ -456,11 +460,11 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { let base = ast_map::path_to_str(path, cx.sess.intr()); parameterized(cx, base, substs.self_r, substs.tps) } - ty_trait(did, ref substs, s) => { + ty_trait(did, ref substs, s, mutbl) => { let path = ty::item_path(cx, did); let base = ast_map::path_to_str(path, cx.sess.intr()); let ty = parameterized(cx, base, substs.self_r, substs.tps); - fmt!("%s%s", trait_store_to_str(cx, s), ty) + fmt!("%s%s%s", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty) } ty_evec(ref mt, vs) => { vstore_ty_to_str(cx, mt, vs) diff --git a/src/test/compile-fail/cast-immutable-mutable-trait.rs b/src/test/compile-fail/cast-immutable-mutable-trait.rs new file mode 100644 index 0000000000000..1047a99577143 --- /dev/null +++ b/src/test/compile-fail/cast-immutable-mutable-trait.rs @@ -0,0 +1,28 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait T { + fn foo(@mut self); +} + +struct S { + unused: int +} + +impl T for S { + fn foo(@mut self) { + } +} + +fn main() { + let s = @S { unused: 0 }; + let _s2 = s as @mut T; //~ error: types differ in mutability + let _s3 = &s as &mut T; //~ error: types differ in mutability +} \ No newline at end of file diff --git a/src/test/run-pass/cast-mutable-trait.rs b/src/test/run-pass/cast-mutable-trait.rs new file mode 100644 index 0000000000000..633188b9a623b --- /dev/null +++ b/src/test/run-pass/cast-mutable-trait.rs @@ -0,0 +1,34 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait T { + fn foo(@mut self); +} + +struct S { + unused: int +} + +impl T for S { + fn foo(@mut self) { + } +} + +fn bar(t: @mut T) { + t.foo(); +} + +fn main() { + let s = @mut S { unused: 0 }; + let s2 = s as @mut T; + s2.foo(); + bar(s2); + bar(s as @mut T); +} \ No newline at end of file From 7373c64a4c0c7e72c8632be255d930d121481f1f Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Wed, 17 Apr 2013 11:51:43 -0400 Subject: [PATCH 229/403] Explain use of debug\! in tutorial --- doc/tutorial.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/tutorial.md b/doc/tutorial.md index 18bc94bdba534..01dd76647f5fd 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1669,6 +1669,9 @@ do spawn { } ~~~~ +If you want to see the output of `debug!` statements, you will need to turn on `debug!` logging. +To enable `debug!` logging, set the RUST_LOG environment variable to `debug` (e.g., with bash, `export RUST_LOG=debug`) + ## For loops The most common way to express iteration in Rust is with a `for` From f86bf0ee6ecddcbcf220a376b16311d9a5115448 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 13:35:34 -0700 Subject: [PATCH 230/403] Warning police --- src/libcore/repr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 530f80ef764cd..ca67e6366b5f4 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -23,9 +23,9 @@ use io::{Writer, WriterUtil}; use libc::c_void; use managed; use ptr; +#[cfg(stage0)] use sys; use reflect; use reflect::{MovePtr, align}; -use sys; use to_str::ToStr; use vec::UnboxedVecRepr; use vec::raw::{VecRepr, SliceRepr}; @@ -479,7 +479,7 @@ impl TyVisitor for ReprVisitor { } #[cfg(not(stage0))] - fn visit_enter_enum(&self, n_variants: uint, + fn visit_enter_enum(&self, _n_variants: uint, get_disr: extern unsafe fn(ptr: *Opaque) -> int, _sz: uint, _align: uint) -> bool { let disr = unsafe { get_disr(transmute(self.ptr)) }; From 2793e4962291c02839253b6212b0b9a02b7686e4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 13:51:55 -0700 Subject: [PATCH 231/403] gitignore: Add build/ subdirectory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b48c5de8931a8..cc892f2a3d400 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,4 @@ config.stamp .DS_Store src/etc/dl .settings/ +build/ From c01c3d9fc6e28b8260894c9522eb29e29874dcbd Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 13:53:34 -0700 Subject: [PATCH 232/403] rustpkg: Fail when crate inference fails; inject link attributes 1. Fail when there's no package script and no crates named main.rs, lib.rs, bench.rs, or test.rs. 2. Inject the crate link_meta "name" and "vers" attributes, so that the output file gets named correctly in the library case. 3. Normalize '-' to '_' in package names. --- src/librustpkg/path_util.rs | 21 ++++++- src/librustpkg/rustpkg.rc | 92 ++++++++++++----------------- src/librustpkg/util.rs | 114 ++++++++++++++++++++++++++---------- 3 files changed, 142 insertions(+), 85 deletions(-) diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index c821281184d3b..140d9ced5808d 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -11,7 +11,8 @@ // rustpkg utilities having to do with paths and directories use core::path::*; -use core::os; +use core::{os, str}; +use core::option::*; use util::PkgId; /// Returns the output directory to use. @@ -50,6 +51,24 @@ pub fn default_dest_dir(pkg_dir: &Path) -> Path { } } +/// Replace all occurrences of '-' in the stem part of path with '_' +/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux +/// as the same name +pub fn normalize(p: ~Path) -> ~Path { + match p.filestem() { + None => p, + Some(st) => { + let replaced = str::replace(st, "-", "_"); + if replaced != st { + ~p.with_filestem(replaced) + } + else { + p + } + } + } +} + #[cfg(test)] mod test { use core::{os, rand}; diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index f8805142769c1..b663c8742ff01 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -36,8 +36,9 @@ use rustc::metadata::filesearch; use std::net::url; use std::{getopts}; use syntax::{ast, diagnostic}; -use util::{ExitCode, Pkg, PkgId}; -use path_util::dest_dir; +use util::*; +use path_util::{dest_dir, normalize}; +use rustc::driver::session::{lib_crate, bin_crate, unknown_crate, crate_type}; mod conditions; mod usage; @@ -117,9 +118,12 @@ impl PkgScript { Ok(r) => { let root = r.pop().pop().pop().pop(); // :-\ debug!("Root is %s, calling compile_rest", root.to_str()); - util::compile_crate_from_input(self.input, Some(self.build_dir), - sess, Some(crate), os::args()[0]); let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); + util::compile_crate_from_input(self.input, self.id, + Some(self.build_dir), + sess, Some(crate), + exe, os::args()[0], + driver::cu_everything); debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); let status = run::run_program(exe.to_str(), ~[root.to_str(), what]); if status != 0 { @@ -199,15 +203,15 @@ impl Ctx { // relative to the CWD. In the future, we should search // paths let cwd = os::getcwd().normalize(); - debug!("Current working directory = %?", cwd); + debug!("Current working directory = %s", cwd.to_str()); - // Find crates inside the workspace + // Create the package source let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid); debug!("Package src = %?", src); - src.find_crates(); // Is there custom build logic? If so, use it let pkg_src_dir = cwd.push_rel(&pkgid.path); + let mut custom = false;; debug!("Package source directory = %s", pkg_src_dir.to_str()); let cfgs = match src.package_script_option(&pkg_src_dir) { Some(package_script_path) => { @@ -221,6 +225,7 @@ impl Ctx { if hook_result != 0 { fail!(fmt!("Error running custom build command")) } + custom = true; // otherwise, the package script succeeded cfgs } @@ -229,6 +234,13 @@ impl Ctx { ~[] } }; + + // Find crates inside the workspace + if !custom { + src.find_crates(); + } + + // Build it! src.build(&dst_dir, cfgs); } ~"clean" => { @@ -728,7 +740,6 @@ condition! { impl PkgSrc { - fn new(src_dir: &Path, dst_dir: &Path, id: &PkgId) -> PkgSrc { PkgSrc { @@ -765,12 +776,6 @@ impl PkgSrc { dir } - - fn has_pkg_file(&self) -> bool { - let dir = self.check_dir(); - dir.push("pkg.rs").exists() - } - // If a file named "pkg.rs" in the current directory exists, // return the path for it. Otherwise, None fn package_script_option(&self, cwd: &Path) -> Option { @@ -786,14 +791,16 @@ impl PkgSrc { /// True if the given path's stem is self's pkg ID's stem /// or if the pkg ID's stem is and the given path's /// stem is foo + /// Requires that dashes in p have already been normalized to + /// underscores fn stem_matches(&self, p: &Path) -> bool { - let self_id = self.id.path.filestem(); + let self_id = normalize(~self.id.path).filestem(); if self_id == p.filestem() { return true; } else { for self_id.each |pth| { - if pth.starts_with("rust-") + if pth.starts_with("rust_") // because p is already normalized && match p.filestem() { Some(s) => str::eq_slice(s, pth.slice(5, pth.len())), None => false @@ -814,17 +821,14 @@ impl PkgSrc { cs.push(Crate::new(&sub)); } + /// Infers crates to build. Called only in the case where there + /// is no custom build logic fn find_crates(&mut self) { use PkgSrc::push_crate; let dir = self.check_dir(); let prefix = dir.components.len(); - // This is ugly, but can go away once we get rid - // of .rc files - let mut saw_rs = false; - let mut saw_rc = false; - debug!("Matching against %?", - self.id.path.filestem()); + debug!("Matching against %?", self.id.path.filestem()); for os::walk_dir(&dir) |pth| { match pth.filename() { Some(~"lib.rs") => push_crate(&mut self.libs, @@ -836,30 +840,10 @@ impl PkgSrc { Some(~"bench.rs") => push_crate(&mut self.benchs, prefix, pth), _ => { - // If the file stem is the same as the - // package ID, with an .rs or .rc extension, - // consider it to be a crate - let ext = pth.filetype(); - let matches = |p: &Path| { - self.stem_matches(p) && (ext == Some(~".rc") - || ext == Some(~".rs")) - }; - debug!("Checking %? which %s and ext = %? %? %?", pth.filestem(), - if matches(pth) { "matches" } else { "does not match" }, - ext, saw_rs, saw_rc); - if matches(pth) && - // Avoid pushing foo.rc *and* foo.rs - !((ext == Some(~".rc") && saw_rs) || - (ext == Some(~".rs") && saw_rc)) { - push_crate(&mut self.libs, // ???? - prefix, pth); - if ext == Some(~".rc") { - saw_rc = true; - } - else if ext == Some(~".rs") { - saw_rs = true; - } - } + util::note(~"Couldn't infer any crates to build.\n\ + Try naming a crate `main.rs`, `lib.rs`, \ + `test.rs`, or `bench.rs`."); + fail!(~"Failed to infer crates to build"); } } } @@ -870,22 +854,22 @@ impl PkgSrc { self.benchs.len()) } - fn build_crates(dst_dir: &Path, + fn build_crates(&self, dst_dir: &Path, src_dir: &Path, crates: &[Crate], cfgs: ~[~str], - test: bool) { + test: bool, crate_type: crate_type) { for crates.each |&crate| { let path = &src_dir.push_rel(&crate.file).normalize(); util::note(fmt!("build_crates: compiling %s", path.to_str())); util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str())); - let result = util::compile_crate(None, path, + let result = util::compile_crate(None, self.id, path, dst_dir, crate.flags, crate.cfgs + cfgs, - false, test); + false, test, crate_type); if !result { build_err::cond.raise(fmt!("build failure on %s", path.to_str())); @@ -898,12 +882,12 @@ impl PkgSrc { fn build(&self, dst_dir: &Path, cfgs: ~[~str]) { let dir = self.check_dir(); debug!("Building libs"); - PkgSrc::build_crates(dst_dir, &dir, self.libs, cfgs, false); + self.build_crates(dst_dir, &dir, self.libs, cfgs, false, lib_crate); debug!("Building mains"); - PkgSrc::build_crates(dst_dir, &dir, self.mains, cfgs, false); + self.build_crates(dst_dir, &dir, self.mains, cfgs, false, bin_crate); debug!("Building tests"); - PkgSrc::build_crates(dst_dir, &dir, self.tests, cfgs, true); + self.build_crates(dst_dir, &dir, self.tests, cfgs, true, bin_crate); debug!("Building benches"); - PkgSrc::build_crates(dst_dir, &dir, self.benchs, cfgs, true); + self.build_crates(dst_dir, &dir, self.benchs, cfgs, true, bin_crate); } } diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 19938e8c5f178..1709a8d06ad15 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -12,16 +12,20 @@ use core::*; use core::cmp::Ord; use core::hash::Streaming; use rustc::driver::{driver, session}; +use rustc::driver::session::{lib_crate, bin_crate, unknown_crate}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; use std::semver; use std::{json, term, getopts}; use syntax::ast_util::*; -use syntax::codemap::{dummy_sp}; +use syntax::codemap::{dummy_sp, spanned, dummy_spanned}; use syntax::ext::base::{mk_ctxt, ext_ctxt}; use syntax::ext::build; use syntax::{ast, attr, codemap, diagnostic, fold}; +use syntax::ast::{meta_name_value, meta_list, attribute, crate_}; +use syntax::attr::{mk_attr}; use rustc::back::link::output_type_exe; +use rustc::driver::session::{lib_crate, bin_crate, unknown_crate, crate_type}; pub type ExitCode = int; // For now @@ -112,7 +116,7 @@ pub impl PkgId { impl ToStr for PkgId { fn to_str(&self) -> ~str { // should probably use the filestem and not the whole path - fmt!("%s-v%s", self.path.to_str(), self.version.to_str()) + fmt!("%s-%s", self.path.to_str(), self.version.to_str()) } } @@ -425,44 +429,51 @@ pub fn add_pkg(pkg: &Pkg) -> bool { // FIXME (#4432): Use workcache to only compile when needed pub fn compile_input(sysroot: Option, + pkg_id: PkgId, in_file: &Path, out_dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, - test: bool) -> bool { + test: bool, + crate_type: session::crate_type) -> bool { + + let short_name = pkg_id.to_str(); assert!(in_file.components.len() > 1); let input = driver::file_input(copy *in_file); - debug!("compile_input: %s", in_file.to_str()); + debug!("compile_input: %s / %?", in_file.to_str(), crate_type); // tjc: by default, use the package ID name as the link name // not sure if we should support anything else - let short_name = in_file.filestem().expect("Can't compile a directory!"); - debug!("short_name = %s", short_name.to_str()); -// Right now we're always assuming that we're building a library. -// What we should do is parse the crate and infer whether it's a library -// from the absence or presence of a main fn - let out_file = out_dir.push(os::dll_filename(short_name)); - let building_library = true; + let binary = os::args()[0]; + let building_library = match crate_type { + lib_crate | unknown_crate => true, + _ => false + }; + + let out_file = if building_library { + out_dir.push(os::dll_filename(short_name)) + } + else { + out_dir.push(short_name + if test { ~"test" } else { ~"" } + + os::EXE_SUFFIX) + }; debug!("compiling %s into %s", in_file.to_str(), out_file.to_str()); - - let binary = os::args()[0]; - debug!("flags: %s", str::connect(flags, ~" ")); debug!("cfgs: %s", str::connect(cfgs, ~" ")); -// Again, we assume we're building a library + let matches = getopts(~[~"-Z", ~"time-passes"] - + if building_library { ~[~"--lib"] } else { ~[] } + + if building_library { ~[~"--lib"] } + else { ~[] } + flags + cfgs.flat_map(|&c| { ~[~"--cfg", c] }), driver::optgroups()).get(); let options = @session::options { - crate_type: if building_library { session::lib_crate } - else { session::bin_crate }, + crate_type: crate_type, optimize: if opt { session::Aggressive } else { session::No }, test: test, maybe_sysroot: sysroot, @@ -485,7 +496,9 @@ pub fn compile_input(sysroot: Option, debug!("calling compile_crate_from_input, out_dir = %s, building_library = %?", out_dir.to_str(), sess.building_library); - compile_crate_from_input(input, Some(*out_dir), sess, None, binary); + let _ = compile_crate_from_input(input, pkg_id, Some(*out_dir), sess, None, + out_file, binary, + driver::cu_everything); true } @@ -493,24 +506,45 @@ pub fn compile_input(sysroot: Option, // Should also rename this to something better // If crate_opt is present, then finish compilation. If it's None, then // call compile_upto and return the crate -pub fn compile_crate_from_input(input: driver::input, build_dir_opt: Option, - sess: session::Session, crate_opt: Option<@ast::crate>, - binary: ~str) -> @ast::crate { +// also, too many arguments +pub fn compile_crate_from_input(input: driver::input, + pkg_id: PkgId, + build_dir_opt: Option, + sess: session::Session, + crate_opt: Option<@ast::crate>, + out_file: Path, + binary: ~str, + what: driver::compile_upto) -> @ast::crate { debug!("Calling build_output_filenames with %?", build_dir_opt); - let outputs = driver::build_output_filenames(input, &build_dir_opt, &None, sess); + let outputs = driver::build_output_filenames(input, &build_dir_opt, &Some(out_file), sess); debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); let cfg = driver::build_configuration(sess, binary, input); match crate_opt { Some(c) => { debug!("Calling compile_rest, outputs = %?", outputs); + assert!(what == driver::cu_everything); driver::compile_rest(sess, cfg, driver::cu_everything, Some(outputs), Some(c)); c } None => { debug!("Calling compile_upto, outputs = %?", outputs); - let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, - Some(outputs)); - crate + let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, Some(outputs)); + + // Inject the inferred link_meta info if it's not already there + // (assumes that name and vers are the only linkage metas) + let mut crate_to_use = crate; + if attr::find_linkage_metas(crate.node.attrs).is_empty() { + crate_to_use = add_attrs(*crate, ~[mk_attr(@dummy_spanned(meta_list(@~"link", + // change PkgId to have a field? + ~[@dummy_spanned(meta_name_value(@~"name", + mk_string_lit(@pkg_id.path.filestem().get()))), + @dummy_spanned(meta_name_value(@~"vers", + mk_string_lit(@pkg_id.version.to_str())))])))]); + } + + + driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate_to_use)); + crate_to_use } } } @@ -525,17 +559,30 @@ pub fn exe_suffix() -> ~str { ~".exe" } pub fn exe_suffix() -> ~str { ~"" } +/// Returns a copy of crate `c` with attributes `attrs` added to its +/// attributes +fn add_attrs(c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate { + @spanned { + node: crate_ { + attrs: c.node.attrs + new_attrs, ..c.node + }, + span: c.span + } +} + // Called by build_crates // FIXME (#4432): Use workcache to only compile when needed -pub fn compile_crate(sysroot: Option, crate: &Path, dir: &Path, +pub fn compile_crate(sysroot: Option, pkg_id: PkgId, + crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, - test: bool) -> bool { + test: bool, crate_type: crate_type) -> bool { debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str()); - debug!("compile_crate: flags =..."); + debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str()); for flags.each |&fl| { debug!("+++ %s", fl); } - compile_input(sysroot, crate, dir, flags, cfgs, opt, test) + compile_input(sysroot, pkg_id, + crate, dir, flags, cfgs, opt, test, crate_type) } @@ -563,6 +610,13 @@ pub fn link_exe(src: &Path, dest: &Path) -> bool { } } +pub fn mk_string_lit(s: @~str) -> ast::lit { + spanned { + node: ast::lit_str(s), + span: dummy_sp() + } +} + #[cfg(test)] mod test { use super::{is_cmd, parse_name}; From e6c3c371a554de6079c1c0b27885b8792431e516 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 13:53:48 -0700 Subject: [PATCH 233/403] rustpkg: Add a few tests There's no test runner for rustpkg yet; just sketching out a few basic test scenarios. pass/ contains packages that should compile successfully, whereas fail/ contains packages that should fail to build. --- .../fail/no-inferred-crates/zzyzx.rs | 22 +++++++++++++++++ .../testsuite/pass/fancy-lib/bar.rs | 3 +++ .../testsuite/pass/fancy-lib/fancy-lib.rc | 24 +++++++++++++++++++ .../testsuite/pass/fancy-lib/fancy-lib.rs | 24 +++++++++++++++++++ .../testsuite/pass/fancy-lib/foo.rs | 2 ++ .../testsuite/pass/fancy-lib/pkg.rs | 17 +++++++++++++ .../testsuite/pass/hello-world/main.rs | 22 +++++++++++++++++ .../testsuite/pass/simple-lib/bar.rs | 3 +++ .../testsuite/pass/simple-lib/foo.rs | 2 ++ .../testsuite/pass/simple-lib/lib.rs | 21 ++++++++++++++++ .../testsuite/pass/simple-lib/simple-lib.rc | 21 ++++++++++++++++ 11 files changed, 161 insertions(+) create mode 100644 src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs create mode 100644 src/librustpkg/testsuite/pass/fancy-lib/bar.rs create mode 100644 src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc create mode 100644 src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs create mode 100644 src/librustpkg/testsuite/pass/fancy-lib/foo.rs create mode 100644 src/librustpkg/testsuite/pass/fancy-lib/pkg.rs create mode 100644 src/librustpkg/testsuite/pass/hello-world/main.rs create mode 100644 src/librustpkg/testsuite/pass/simple-lib/bar.rs create mode 100644 src/librustpkg/testsuite/pass/simple-lib/foo.rs create mode 100644 src/librustpkg/testsuite/pass/simple-lib/lib.rs create mode 100644 src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc diff --git a/src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs b/src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs new file mode 100644 index 0000000000000..c9c1f00fb082a --- /dev/null +++ b/src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build hello-world`: + * testsuite/hello-world/build/ exists + * testsuite/hello-world/build/ contains an executable named hello-world + * testsuite/hello-world/build/ does not contain a library +*/ + +use core::io; + +fn main() { + io::println(~"Hello world!"); +} diff --git a/src/librustpkg/testsuite/pass/fancy-lib/bar.rs b/src/librustpkg/testsuite/pass/fancy-lib/bar.rs new file mode 100644 index 0000000000000..e300c2a3295a3 --- /dev/null +++ b/src/librustpkg/testsuite/pass/fancy-lib/bar.rs @@ -0,0 +1,3 @@ +pub fn assert_true() { + assert!(true); +} diff --git a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc new file mode 100644 index 0000000000000..55261a820981a --- /dev/null +++ b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc @@ -0,0 +1,24 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build fancy-lib`: + * testsuite/fancy-lib/build/ exists + * testsuite/fancy-lib/build/ contains a file called generated.rs + * testsuite/fancy-lib/build/ contains a library named libfancy_lib + * testsuite/fancy-lib/build/ does not contain an executable + * +*/ + +extern mod std; + +pub mod foo; +pub mod bar; +#[path = "build/generated.rs"] pub mod generated; diff --git a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs new file mode 100644 index 0000000000000..16c384ad8b8c1 --- /dev/null +++ b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs @@ -0,0 +1,24 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build fancy-lib`: + * testsuite/fancy-lib/build/ exists + * testsuite/fancy-lib/build/ contains a file called generated.rs + * testsuite/fancy-lib/build/ contains a library named libfancy_lib + * testsuite/fancy-lib/build/ does not contain an executable + * +*/ + +extern mod std; + +pub mod foo; +pub mod bar; +pub mod generated; diff --git a/src/librustpkg/testsuite/pass/fancy-lib/foo.rs b/src/librustpkg/testsuite/pass/fancy-lib/foo.rs new file mode 100644 index 0000000000000..4b3f3923d058f --- /dev/null +++ b/src/librustpkg/testsuite/pass/fancy-lib/foo.rs @@ -0,0 +1,2 @@ +pub fn do_nothing() { +} \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs new file mode 100644 index 0000000000000..6d3495f2b2869 --- /dev/null +++ b/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs @@ -0,0 +1,17 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + let cwd = os::getcwd(); + debug!("cwd = %s", cwd.to_str()); + let file = io::file_writer(&Path(~"fancy-lib/build/generated.rs"), + [io::Create]).get(); + file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }"); +} \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/hello-world/main.rs b/src/librustpkg/testsuite/pass/hello-world/main.rs new file mode 100644 index 0000000000000..c9c1f00fb082a --- /dev/null +++ b/src/librustpkg/testsuite/pass/hello-world/main.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build hello-world`: + * testsuite/hello-world/build/ exists + * testsuite/hello-world/build/ contains an executable named hello-world + * testsuite/hello-world/build/ does not contain a library +*/ + +use core::io; + +fn main() { + io::println(~"Hello world!"); +} diff --git a/src/librustpkg/testsuite/pass/simple-lib/bar.rs b/src/librustpkg/testsuite/pass/simple-lib/bar.rs new file mode 100644 index 0000000000000..e300c2a3295a3 --- /dev/null +++ b/src/librustpkg/testsuite/pass/simple-lib/bar.rs @@ -0,0 +1,3 @@ +pub fn assert_true() { + assert!(true); +} diff --git a/src/librustpkg/testsuite/pass/simple-lib/foo.rs b/src/librustpkg/testsuite/pass/simple-lib/foo.rs new file mode 100644 index 0000000000000..4b3f3923d058f --- /dev/null +++ b/src/librustpkg/testsuite/pass/simple-lib/foo.rs @@ -0,0 +1,2 @@ +pub fn do_nothing() { +} \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/simple-lib/lib.rs b/src/librustpkg/testsuite/pass/simple-lib/lib.rs new file mode 100644 index 0000000000000..1cdca6cdd5d87 --- /dev/null +++ b/src/librustpkg/testsuite/pass/simple-lib/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build simple-lib`: + * testsuite/simple-lib/build/ exists + * testsuite/simple-lib/build/ contains a library named libsimple_lib + * testsuite/simple-lib/build/ does not contain an executable +*/ + +extern mod std; + +pub mod foo; +pub mod bar; diff --git a/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc b/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc new file mode 100644 index 0000000000000..1cdca6cdd5d87 --- /dev/null +++ b/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg build simple-lib`: + * testsuite/simple-lib/build/ exists + * testsuite/simple-lib/build/ contains a library named libsimple_lib + * testsuite/simple-lib/build/ does not contain an executable +*/ + +extern mod std; + +pub mod foo; +pub mod bar; From a5ddc009829bef149a9e2f127e80609589604443 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 1 Apr 2013 17:47:38 -0700 Subject: [PATCH 234/403] rustc: Use an out pointer to return structs in x86 C ABI. #5347 This Adds a bunch of tests for passing and returning structs of various sizes to C. It fixes the struct return rules on unix, and on windows for structs of size > 8 bytes. Struct passing on unix for structs under a certain size appears to still be broken. --- src/libcore/rt/uv/net.rs | 2 - src/librustc/lib/llvm.rs | 41 ++++---- src/librustc/middle/trans/cabi.rs | 34 ------- src/librustc/middle/trans/cabi_mips.rs | 2 +- src/librustc/middle/trans/cabi_x86.rs | 77 ++++++++++++++ src/librustc/middle/trans/cabi_x86_64.rs | 2 +- src/librustc/middle/trans/foreign.rs | 17 ++-- src/librustc/rustc.rc | 1 + src/rt/rust_test_helpers.cpp | 102 +++++++++++++++---- src/rt/rustrt.def.in | 8 +- src/test/run-pass/extern-pass-TwoU16s.rs | 32 ++++++ src/test/run-pass/extern-pass-TwoU32s.rs | 30 ++++++ src/test/run-pass/extern-pass-TwoU64s-ref.rs | 2 - src/test/run-pass/extern-pass-TwoU64s.rs | 2 +- src/test/run-pass/extern-pass-TwoU8s.rs | 32 ++++++ src/test/run-pass/extern-return-TwoU16s.rs | 27 +++++ src/test/run-pass/extern-return-TwoU32s.rs | 25 +++++ src/test/run-pass/extern-return-TwoU64s.rs | 25 +++++ src/test/run-pass/extern-return-TwoU8s.rs | 27 +++++ 19 files changed, 397 insertions(+), 91 deletions(-) create mode 100644 src/librustc/middle/trans/cabi_x86.rs create mode 100644 src/test/run-pass/extern-pass-TwoU16s.rs create mode 100644 src/test/run-pass/extern-pass-TwoU32s.rs create mode 100644 src/test/run-pass/extern-pass-TwoU8s.rs create mode 100644 src/test/run-pass/extern-return-TwoU16s.rs create mode 100644 src/test/run-pass/extern-return-TwoU32s.rs create mode 100644 src/test/run-pass/extern-return-TwoU64s.rs create mode 100644 src/test/run-pass/extern-return-TwoU8s.rs diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index 29ea36cd88b03..4b9ff4504ddac 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -356,7 +356,6 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest { #[test] -#[ignore(reason = "ffi struct issues")] fn connect_close() { do run_in_bare_thread() { let mut loop_ = Loop::new(); @@ -409,7 +408,6 @@ fn connect_read() { } #[test] -#[ignore(reason = "ffi struct issues")] fn listen() { do run_in_bare_thread() { static MAX: int = 10; diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index b6d3fce7e7546..06f7261040c5d 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -125,27 +125,25 @@ pub enum RealPredicate { RealPredicateTrue = 15, } -// enum for the LLVM TypeKind type - must stay in sync with the def of +// The LLVM TypeKind type - must stay in sync with the def of // LLVMTypeKind in llvm/include/llvm-c/Core.h -#[deriving(Eq)] -pub enum TypeKind { - Void = 0, - Half = 1, - Float = 2, - Double = 3, - X86_FP80 = 4, - FP128 = 5, - PPC_FP128 = 6, - Label = 7, - Integer = 8, - Function = 9, - Struct = 10, - Array = 11, - Pointer = 12, - Vector = 13, - Metadata = 14, - X86_MMX = 15 -} +pub type TypeKind = u32; +pub static Void: TypeKind = 0; +pub static Half: TypeKind = 1; +pub static Float: TypeKind = 2; +pub static Double: TypeKind = 3; +pub static X86_FP80: TypeKind = 4; +pub static FP128: TypeKind = 5; +pub static PPC_FP128: TypeKind = 6; +pub static Label: TypeKind = 7; +pub static Integer: TypeKind = 8; +pub static Function: TypeKind = 9; +pub static Struct: TypeKind = 10; +pub static Array: TypeKind = 11; +pub static Pointer: TypeKind = 12; +pub static Vector: TypeKind = 13; +pub static Metadata: TypeKind = 14; +pub static X86_MMX: TypeKind = 15; pub enum AtomicBinOp { Xchg = 0, @@ -1582,7 +1580,8 @@ pub fn type_to_str_inner(names: @TypeNames, +outer0: &[TypeRef], ty: TypeRef) } Vector => return @"Vector", Metadata => return @"Metadata", - X86_MMX => return @"X86_MMAX" + X86_MMX => return @"X86_MMAX", + _ => fail!() } } } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 7e159ef606242..60b502873e2d5 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -180,37 +180,3 @@ pub impl FnType { Ret(bcx, llretval); } } - -enum LLVM_ABIInfo { LLVM_ABIInfo } - -impl ABIInfo for LLVM_ABIInfo { - fn compute_info(&self, - atys: &[TypeRef], - rty: TypeRef, - _ret_def: bool) -> FnType { - let arg_tys = do atys.map |a| { - LLVMType { cast: false, ty: *a } - }; - let ret_ty = LLVMType { - cast: false, - ty: rty - }; - let attrs = do atys.map |_| { - option::None - }; - let sret = false; - - return FnType { - arg_tys: arg_tys, - ret_ty: ret_ty, - attrs: attrs, - sret: sret - }; - } -} - -pub fn llvm_abi_info() -> @ABIInfo { - return @LLVM_ABIInfo as @ABIInfo; -} - - diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index ce37455560b5c..9a1c95e5184c0 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -227,6 +227,6 @@ impl ABIInfo for MIPS_ABIInfo { } } -pub fn mips_abi_info() -> @ABIInfo { +pub fn abi_info() -> @ABIInfo { return @MIPS_ABIInfo as @ABIInfo; } diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs new file mode 100644 index 0000000000000..a549f9121716f --- /dev/null +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -0,0 +1,77 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use driver::session::os_win32; +use core::option::*; +use lib::llvm::*; +use lib::llvm::llvm::*; +use super::cabi::*; +use super::common::*; +use super::machine::*; + +struct X86_ABIInfo { + ccx: @CrateContext +} + +impl ABIInfo for X86_ABIInfo { + fn compute_info(&self, + atys: &[TypeRef], + rty: TypeRef, + ret_def: bool) -> FnType { + let mut arg_tys = do atys.map |a| { + LLVMType { cast: false, ty: *a } + }; + let mut ret_ty = LLVMType { + cast: false, + ty: rty + }; + let mut attrs = do atys.map |_| { + None + }; + + // Rules for returning structs taken from + // http://www.angelcode.com/dev/callconv/callconv.html + let sret = { + let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def }; + let big_struct = if self.ccx.sess.targ_cfg.os != os_win32 { + true + } else { + llsize_of_alloc(self.ccx, rty) > 8 + }; + returning_a_struct && big_struct + }; + + if sret { + let ret_ptr_ty = LLVMType { + cast: false, + ty: T_ptr(ret_ty.ty) + }; + arg_tys = ~[ret_ptr_ty] + arg_tys; + attrs = ~[Some(StructRetAttribute)] + attrs; + ret_ty = LLVMType { + cast: false, + ty: T_void(), + }; + } + + return FnType { + arg_tys: arg_tys, + ret_ty: ret_ty, + attrs: attrs, + sret: sret + }; + } +} + +pub fn abi_info(ccx: @CrateContext) -> @ABIInfo { + return @X86_ABIInfo { + ccx: ccx + } as @ABIInfo; +} diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index fa85588cb0f48..31ac4534462a5 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -410,6 +410,6 @@ impl ABIInfo for X86_64_ABIInfo { } } -pub fn x86_64_abi_info() -> @ABIInfo { +pub fn abi_info() -> @ABIInfo { return @X86_64_ABIInfo as @ABIInfo; } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 387caa4d8d31f..1037a4c071041 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -16,9 +16,10 @@ use lib::llvm::{TypeRef, ValueRef}; use lib; use middle::trans::base::*; use middle::trans::cabi; -use middle::trans::cabi_x86_64::*; +use middle::trans::cabi_x86; +use middle::trans::cabi_x86_64; use middle::trans::cabi_arm; -use middle::trans::cabi_mips::*; +use middle::trans::cabi_mips; use middle::trans::build::*; use middle::trans::callee::*; use middle::trans::common::*; @@ -42,12 +43,12 @@ use syntax::abi::{Architecture, X86, X86_64, Arm, Mips}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, Cdecl, Aapcs, C}; -fn abi_info(arch: Architecture) -> @cabi::ABIInfo { - return match arch { - X86_64 => x86_64_abi_info(), +fn abi_info(ccx: @CrateContext) -> @cabi::ABIInfo { + return match ccx.sess.targ_cfg.arch { + X86 => cabi_x86::abi_info(ccx), + X86_64 => cabi_x86_64::abi_info(), Arm => cabi_arm::abi_info(), - Mips => mips_abi_info(), - X86 => cabi::llvm_abi_info() + Mips => cabi_mips::abi_info(), } } @@ -112,7 +113,7 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { !ty::type_is_bot(fn_sig.output) && !ty::type_is_nil(fn_sig.output); let fn_ty = - abi_info(ccx.sess.targ_cfg.arch).compute_info( + abi_info(ccx).compute_info( llsig.llarg_tys, llsig.llret_ty, ret_def); diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index d1dbb48ba08a4..3fbe1b96ef7aa 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -69,6 +69,7 @@ pub mod middle { pub mod tvec; pub mod meth; pub mod cabi; + pub mod cabi_x86; pub mod cabi_x86_64; pub mod cabi_arm; pub mod cabi_mips; diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.cpp index 2c8026f159efa..64966bd345489 100644 --- a/src/rt/rust_test_helpers.cpp +++ b/src/rt/rust_test_helpers.cpp @@ -30,26 +30,6 @@ rust_dbg_extern_identity_u64(uint64_t u) { return u; } -struct TwoU64s { - uint64_t one; - uint64_t two; -}; - -extern "C" CDECL TwoU64s -rust_dbg_extern_identity_TwoU64s(TwoU64s u) { - return u; -} - -struct TwoDoubles { - double one; - double two; -}; - -extern "C" CDECL TwoDoubles -rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { - return u; -} - extern "C" CDECL double rust_dbg_extern_identity_double(double u) { return u; @@ -103,3 +83,85 @@ rust_dbg_call(dbg_callback cb, void *data) { } extern "C" CDECL void rust_dbg_do_nothing() { } + +struct TwoU8s { + uint8_t one; + uint8_t two; +}; + +extern "C" CDECL TwoU8s +rust_dbg_extern_return_TwoU8s() { + struct TwoU8s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU8s +rust_dbg_extern_identity_TwoU8s(TwoU8s u) { + return u; +} + +struct TwoU16s { + uint16_t one; + uint16_t two; +}; + +extern "C" CDECL TwoU16s +rust_dbg_extern_return_TwoU16s() { + struct TwoU16s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU16s +rust_dbg_extern_identity_TwoU16s(TwoU16s u) { + return u; +} + +struct TwoU32s { + uint32_t one; + uint32_t two; +}; + +extern "C" CDECL TwoU32s +rust_dbg_extern_return_TwoU32s() { + struct TwoU32s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU32s +rust_dbg_extern_identity_TwoU32s(TwoU32s u) { + return u; +} + +struct TwoU64s { + uint64_t one; + uint64_t two; +}; + +extern "C" CDECL TwoU64s +rust_dbg_extern_return_TwoU64s() { + struct TwoU64s s; + s.one = 10; + s.two = 20; + return s; +} + +extern "C" CDECL TwoU64s +rust_dbg_extern_identity_TwoU64s(TwoU64s u) { + return u; +} + +struct TwoDoubles { + double one; + double two; +}; + +extern "C" CDECL TwoDoubles +rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { + return u; +} diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 73dbe661d3f86..f63e3f53a7caf 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -198,8 +198,15 @@ rust_readdir rust_opendir rust_dbg_extern_identity_u32 rust_dbg_extern_identity_u64 +rust_dbg_extern_identity_TwoU8s +rust_dbg_extern_identity_TwoU16s +rust_dbg_extern_identity_TwoU32s rust_dbg_extern_identity_TwoU64s rust_dbg_extern_identity_TwoDoubles +rust_dbg_extern_return_TwoU8s +rust_dbg_extern_return_TwoU16s +rust_dbg_extern_return_TwoU32s +rust_dbg_extern_return_TwoU64s rust_dbg_extern_identity_double rust_dbg_extern_identity_u8 rust_get_rt_env @@ -214,4 +221,3 @@ rust_uv_free_ip6_addr rust_call_nullary_fn rust_initialize_global_state - diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs new file mode 100644 index 0000000000000..f0343c4d2a267 --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +// xfail-test #5744 + +#[deriving(Eq)] +struct TwoU16s { + one: u16, two: u16 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; +} + +pub fn main() { + unsafe { + let x = TwoU16s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU16s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs new file mode 100644 index 0000000000000..16d14a96cfe4f --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +#[deriving(Eq)] +struct TwoU32s { + one: u32, two: u32 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; +} + +pub fn main() { + unsafe { + let x = TwoU32s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU32s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-pass-TwoU64s-ref.rs b/src/test/run-pass/extern-pass-TwoU64s-ref.rs index 87bec86d8de70..56d3f8ebbff7f 100644 --- a/src/test/run-pass/extern-pass-TwoU64s-ref.rs +++ b/src/test/run-pass/extern-pass-TwoU64s-ref.rs @@ -10,8 +10,6 @@ // Test that we ignore modes when calling extern functions. -// xfail-test --- broken on 32-bit ABIs! (#5347) - #[deriving(Eq)] struct TwoU64s { one: u64, two: u64 diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index fb91d5495e16f..eb2e3b1158f1c 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -// xfail-test --- broken on 32-bit ABIs! (#5347) +// xfail-fast This works standalone on windows but not with check-fast. don't know why #[deriving(Eq)] struct TwoU64s { diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs new file mode 100644 index 0000000000000..213e9a68a7f89 --- /dev/null +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a foreign function that accepts and returns a struct +// by value. + +// xfail-test #5744 + +#[deriving(Eq)] +struct TwoU8s { + one: u8, two: u8 +} + +pub extern { + pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; +} + +pub fn main() { + unsafe { + let x = TwoU8s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU8s(x); + assert!(x == y); + } +} + diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs new file mode 100644 index 0000000000000..0ea649a65b05f --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 #5745 + +struct TwoU16s { + one: u16, two: u16 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU16s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs new file mode 100644 index 0000000000000..9e374687855b0 --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct TwoU32s { + one: u32, two: u32 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU32s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs new file mode 100644 index 0000000000000..250d3b8f562b0 --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU64s.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct TwoU64s { + one: u64, two: u64 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU64s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs new file mode 100644 index 0000000000000..9007d12a4514f --- /dev/null +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-win32 #5745 + +struct TwoU8s { + one: u8, two: u8 +} + +pub extern { + pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU8s(); + assert!(y.one == 10); + assert!(y.two == 20); + } +} From 82765a0b48aa79ecd9a3fe20bf693c6e68464ef5 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 15:47:24 -0700 Subject: [PATCH 235/403] rustpkg: Implement clean; replace boolean result flags with fail!() 1. Implemented the `clean` command 2. The methods implementing rustpkg commands all returned `bool`. Since most of not all of the error situations seem unrecoverable, I changed the methods to return unit (and also stubbed out several more methods that were assuming a package script existed, to be re-implemented in the future) --- src/librustpkg/rustpkg.rc | 217 +++++------------- .../testsuite/pass/hello-world/main.rs | 9 +- 2 files changed, 67 insertions(+), 159 deletions(-) diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index b663c8742ff01..b3b47e7aeda19 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -33,7 +33,6 @@ use core::hashmap::HashMap; use core::io::WriterUtil; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; -use std::net::url; use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; @@ -244,16 +243,21 @@ impl Ctx { src.build(&dst_dir, cfgs); } ~"clean" => { - self.clean(); + if args.len() < 1 { + return usage::build(); + } + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(args[0]); + + self.clean(pkgid); } ~"do" => { if args.len() < 2 { return usage::do_cmd(); } - if !self.do_cmd(args[0], args[1]) { - fail!(~"a command failed!"); - } + self.do_cmd(args[0], args[1]); } ~"info" => { self.info(); @@ -298,12 +302,11 @@ impl Ctx { } } - fn do_cmd(&self, cmd: ~str, pkgname: ~str) -> bool { + fn do_cmd(&self, cmd: ~str, pkgname: ~str) { match cmd { ~"build" | ~"test" => { util::error(~"that command cannot be manually called"); - - return false; + fail!(~"do_cmd"); } _ => {} } @@ -319,16 +322,15 @@ impl Ctx { Some(script_path) => { let script = PkgScript::parse(script_path, pkgid); let (_, status) = script.run_custom(cmd); // Ignore cfgs? - if status == 42 { // ??? + if status == 42 { util::error(~"no fns are listening for that cmd"); - return false; + fail!(~"do_cmd"); } - status == 0 } None => { util::error(fmt!("invoked `do`, but there is no package script in %s", cwd.to_str())); - false + fail!(~"do_cmd"); } } } @@ -341,128 +343,44 @@ impl Ctx { } fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str], - _cfgs: ~[~str], _opt: bool, _test: bool) -> bool { + _cfgs: ~[~str], _opt: bool, _test: bool) { // What's the difference between build and compile? fail!(~"compile not yet implemented"); } - fn clean(&self) -> bool { - // stub - fail!(); + fn clean(&self, id: PkgId) { + // Could also support a custom build hook in the pkg + // script for cleaning files rustpkg doesn't know about. + // Do something reasonable for now + + let dir = dest_dir(id); + util::note(fmt!("Cleaning package %s (removing directory %s)", + id.to_str(), dir.to_str())); + if os::path_exists(&dir) { + util::remove_dir_r(&dir); + util::note(fmt!("Removed directory %s", dir.to_str())); + } + + util::note(fmt!("Cleaned package %s", id.to_str())); } fn info(&self) { // stub - fail!(); + fail!(~"info not yet implemented"); } - fn install(&self, url: Option<~str>, - target: Option<~str>, cache: bool) -> bool { - let dir = match url { - None => { - util::note(~"installing from the cwd"); - os::getcwd() - } - Some(url) => { - let hash = util::hash(if !target.is_none() { - url + target.get() - } - else { url }); - - if self.dep_cache.contains_key(&hash) { - util::warn(~"already installed dep this run"); - return true; - } - - self.dep_cache.insert(hash, true); - - let dir = util::root().push(~"tmp").push(hash); - - if cache && os::path_exists(&dir) { - return true; - } - - if !self.fetch(&dir, url, target) { - return false; - } - dir - } - }; - - let script = match self.build(&dir, false, true, false) { - Some(script) => script, - None => { - return false; - } - }; - let work_dir = script.build_dir; - let from_bin_dir = work_dir.push(~"bin"); - let from_lib_dir = work_dir.push(~"lib"); - let to_bin_dir = util::root().push(~"bin"); - let to_lib_dir = util::root().push(~"lib"); - let mut bins = ~[]; - let mut libs = ~[]; - - for os::walk_dir(&from_bin_dir) |bin| { - let to = to_bin_dir.push_rel(&bin.file_path()); - - os::copy_file(bin, &to); - bins.push(to.to_str()); - } - - for os::walk_dir(&from_lib_dir) |lib| { - let to = to_lib_dir.push_rel(&lib.file_path()); - - os::copy_file(lib, &to); - libs.push(to.to_str()); - } - - let package = Pkg { - id: script.id, - bins: bins, - libs: libs - }; - - util::note(fmt!("installed %s", script.id.to_str())); - util::add_pkg(&package); - - true + fn install(&self, _url: Option<~str>, + _target: Option<~str>, _cache: bool) { + // stub + fail!(~"install not yet implemented"); } - fn fetch(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool { - let url = if str::find_str(url, "://").is_none() { - ~"http://" + url } - else { url }; - let url = match url::from_str(url) { - result::Ok(url) => url, - result::Err(err) => { - util::error(fmt!("failed parsing %s", err.to_lower())); - - return false; - } - }; - let str = url.to_str(); - - match Path(url.path).filetype() { - Some(ext) => { - if ext == ~".git" { - return self.fetch_git(dir, str, target); - } - } - None => {} - } - - match url.scheme { - ~"git" => self.fetch_git(dir, str, target), - ~"http" | ~"ftp" | ~"file" => self.fetch_curl(dir, str), - _ => { - util::warn(~"unknown url scheme to fetch, using curl"); - self.fetch_curl(dir, str) - } - } + fn fetch(&self, _dir: &Path, _url: ~str, _target: Option<~str>) { + // stub + fail!(~"fetch not yet implemented"); } - fn fetch_curl(&self, dir: &Path, url: ~str) -> bool { + fn fetch_curl(&self, dir: &Path, url: ~str) { util::note(fmt!("fetching from %s using curl", url)); let tar = dir.dir_path().push(&dir.file_path().to_str() + ~".tar"); @@ -472,7 +390,7 @@ impl Ctx { url]).status != 0 { util::error(~"fetching failed: downloading using curl failed"); - return false; + fail!(); } if run::program_output(~"tar", ~[~"-x", ~"--strip-components=1", @@ -481,13 +399,11 @@ impl Ctx { util::error(~"fetching failed: extracting using tar failed" + ~"(is it a valid tar archive?)"); - return false; + fail!(); } - - true } - fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool { + fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) { util::note(fmt!("fetching from %s using git", url)); // Git can't clone into a non-empty directory @@ -496,8 +412,7 @@ impl Ctx { if run::program_output(~"git", ~[~"clone", url, dir.to_str()]).status != 0 { util::error(~"fetching failed: can't clone repository"); - - return false; + fail!(); } if !target.is_none() { @@ -511,21 +426,17 @@ impl Ctx { if !success { util::error(~"fetching failed: can't checkout target"); - - return false; + fail!(); } } - - true } - fn prefer(&self, id: ~str, vers: Option<~str>) -> bool { + fn prefer(&self, id: ~str, vers: Option<~str>) { let package = match util::get_pkg(id, vers) { result::Ok(package) => package, result::Err(err) => { util::error(err); - - return false; + fail!(); // Condition? } }; let name = package.id.path.to_str(); // ??? @@ -548,29 +459,18 @@ impl Ctx { } util::note(fmt!("preferred %s v%s", name, package.id.version.to_str())); - - true } - fn test(&self) -> bool { - let script = match self.build(&os::getcwd(), false, false, true) { - Some(script) => script, - None => { - return false; - } - }; - - // To do - util::note(fmt!("Would test %s, but this is a dry run", - script.id.to_str())); - false + fn test(&self) { + // stub + fail!(~"test not yet implemented"); } - fn uninstall(&self, _id: ~str, _vers: Option<~str>) -> bool { + fn uninstall(&self, _id: ~str, _vers: Option<~str>) { fail!(~"uninstall not yet implemented"); } - fn unprefer(&self, _id: ~str, _vers: Option<~str>) -> bool { + fn unprefer(&self, _id: ~str, _vers: Option<~str>) { fail!(~"unprefer not yet implemented"); } } @@ -839,14 +739,19 @@ impl PkgSrc { prefix, pth), Some(~"bench.rs") => push_crate(&mut self.benchs, prefix, pth), - _ => { - util::note(~"Couldn't infer any crates to build.\n\ - Try naming a crate `main.rs`, `lib.rs`, \ - `test.rs`, or `bench.rs`."); - fail!(~"Failed to infer crates to build"); - } + _ => () } } + + if self.libs.is_empty() && self.mains.is_empty() + && self.tests.is_empty() && self.benchs.is_empty() { + + util::note(~"Couldn't infer any crates to build.\n\ + Try naming a crate `main.rs`, `lib.rs`, \ + `test.rs`, or `bench.rs`."); + fail!(~"Failed to infer crates to build"); + } + debug!("found %u libs, %u mains, %u tests, %u benchs", self.libs.len(), self.mains.len(), diff --git a/src/librustpkg/testsuite/pass/hello-world/main.rs b/src/librustpkg/testsuite/pass/hello-world/main.rs index c9c1f00fb082a..2ef387d962000 100644 --- a/src/librustpkg/testsuite/pass/hello-world/main.rs +++ b/src/librustpkg/testsuite/pass/hello-world/main.rs @@ -10,9 +10,12 @@ /* The test runner should check that, after `rustpkg build hello-world`: - * testsuite/hello-world/build/ exists - * testsuite/hello-world/build/ contains an executable named hello-world - * testsuite/hello-world/build/ does not contain a library + * testsuite/pass/hello-world/build/ exists + * testsuite/pass/hello-world/build/ contains an executable named hello-world + * testsuite/pass/hello-world/build/ does not contain a library + + It should also check that after `rustpkg clean hello-world`: + * testsuite/pass/hello-world/build is empty */ use core::io; From c98f0cb3627fbdc2f1e56cfe1aad20a96730d208 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 17 Apr 2013 19:34:53 -0400 Subject: [PATCH 236/403] vec: add an external iterator --- src/libcore/vec.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 30201304d6191..0403ae64f0205 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -18,6 +18,10 @@ use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use iter::BaseIter; use iter; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +use iterator::Iterator; use kinds::Copy; use libc; use option::{None, Option, Some}; @@ -1919,6 +1923,7 @@ impl<'self,T> ImmutableVector for &'self [T] { #[cfg(stage3)] pub trait ImmutableVector<'self, T> { fn slice(&self, start: uint, end: uint) -> &'self [T]; + fn iter(self) -> VecIterator<'self, T>; fn head(&self) -> &'self T; fn head_opt(&self) -> Option<&'self T>; fn tail(&self) -> &'self [T]; @@ -1949,6 +1954,15 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { slice(*self, start, end) } + #[inline] + fn iter(self) -> VecIterator<'self, T> { + unsafe { + let p = vec::raw::to_ptr(self); + VecIterator{ptr: p, end: p.offset(self.len()), + lifetime: cast::transmute(p)} + } + } + /// Returns the first element of a vector, failing if the vector is empty. #[inline] fn head(&self) -> &'self T { head(*self) } @@ -2795,7 +2809,33 @@ impl Clone for ~[A] { } } -// ___________________________________________________________________________ +// could be implemented with &[T] with .slice(), but this avoids bounds checks +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub struct VecIterator<'self, T> { + priv ptr: *T, + priv end: *T, + priv lifetime: &'self T // FIXME: #5922 +} + +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> { + #[inline] + fn next(&mut self) -> Option<&'self T> { + unsafe { + if self.ptr == self.end { + None + } else { + let old = self.ptr; + self.ptr = self.ptr.offset(1); + Some(cast::transmute(old)) + } + } + } +} #[cfg(test)] mod tests { @@ -4421,6 +4461,19 @@ mod tests { [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less; [2, 2].cmp(& &[1, 2, 3, 4]) == Greater; } + + #[test] + fn test_iterator() { + use iterator::*; + let xs = [1, 2, 5, 10, 11]; + let ys = [1, 2, 5, 10, 11, 19]; + let mut it = xs.iter(); + let mut i = 0; + for it.advance |&x| { + assert_eq!(x, ys[i]); + i += 1; + } + } } // Local Variables: From 35f3b6324f1dc1f68539346d6bcda69a555910da Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 18:58:12 -0700 Subject: [PATCH 237/403] rustpkg: Remove bogus .rc file --- .../testsuite/pass/fancy-lib/fancy-lib.rc | 24 ------------------- .../testsuite/pass/fancy-lib/fancy-lib.rs | 2 +- 2 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc diff --git a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc deleted file mode 100644 index 55261a820981a..0000000000000 --- a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -The test runner should check that, after `rustpkg build fancy-lib`: - * testsuite/fancy-lib/build/ exists - * testsuite/fancy-lib/build/ contains a file called generated.rs - * testsuite/fancy-lib/build/ contains a library named libfancy_lib - * testsuite/fancy-lib/build/ does not contain an executable - * -*/ - -extern mod std; - -pub mod foo; -pub mod bar; -#[path = "build/generated.rs"] pub mod generated; diff --git a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs index 16c384ad8b8c1..55261a820981a 100644 --- a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs +++ b/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs @@ -21,4 +21,4 @@ extern mod std; pub mod foo; pub mod bar; -pub mod generated; +#[path = "build/generated.rs"] pub mod generated; From a2761ac7b528eeeba375e0b0be0140fc1e5c50b3 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 18:58:41 -0700 Subject: [PATCH 238/403] rustpkg: Change this example to show how to do a custom build --- src/librustpkg/testsuite/pass/fancy-lib/pkg.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs index 6d3495f2b2869..be3c68d731b23 100644 --- a/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs +++ b/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::run; + pub fn main() { let cwd = os::getcwd(); debug!("cwd = %s", cwd.to_str()); let file = io::file_writer(&Path(~"fancy-lib/build/generated.rs"), [io::Create]).get(); file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }"); + + // now compile the crate itself + run::run_program("rustc", ~[~"fancy-lib/fancy-lib.rs", ~"--lib", + ~"-o", ~"fancy-lib/build/fancy_lib"]); } \ No newline at end of file From e2d947d72f78ea195585fd2fc10e2a7bd8d274a4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 18:58:59 -0700 Subject: [PATCH 239/403] rustpkg: Don't execute the standard build logic if there is a pkg.rs --- src/librustpkg/rustpkg.rc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index b3b47e7aeda19..ca8161067c2b6 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -234,13 +234,14 @@ impl Ctx { } }; - // Find crates inside the workspace + // If there was a package script, it should have finished + // the build already. Otherwise... if !custom { + // Find crates inside the workspace src.find_crates(); + // Build it! + src.build(&dst_dir, cfgs); } - - // Build it! - src.build(&dst_dir, cfgs); } ~"clean" => { if args.len() < 1 { From 958189dba10536bd3f41004c4806893ec5deadd9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 18:59:32 -0700 Subject: [PATCH 240/403] rustpkg: Add a list of rustpkg commands that should pass This is a test file containing examples of commands that should succeed. When we write the test runner, we will have to figure out how to automate them. --- src/librustpkg/testsuite/pass/commands.txt | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/librustpkg/testsuite/pass/commands.txt diff --git a/src/librustpkg/testsuite/pass/commands.txt b/src/librustpkg/testsuite/pass/commands.txt new file mode 100644 index 0000000000000..e1a1b2462b253 --- /dev/null +++ b/src/librustpkg/testsuite/pass/commands.txt @@ -0,0 +1,35 @@ +Commands that should succeed: + +1. rustpkg install github.com/mozilla-servo/rust-http-client + +2. Create a git repo containing a package "foo", add a tag called "1.0" -- `rustpkg install foo` should install a library called "libfoo-....-1.0..." + +3. rustpkg install foo, if ./.rust/foo exists and is a valid package directory + +4. RUST_PATH=/home/rust rustpkg install foo installs an executable in /home/rust/foo if ./foo exists and is a valid package directory + +5. RUST_PATH=/home/rust:/home/more_rust rustpkg install foo succeeds if /home/more_rust/foo exists and is a valid package directory + +6. rustpkg install foo; rustpkg install bar; rustpkg install quux; rustpkg list should show foo, bar, and quux + 6a. then, rustpkg remove foo; rustpkg list should show bar and quux, but not foo + +7. Execute `rustpkg build foo`. Check the datestamp on build/foo. Execute the same command again. Make sure the datestamp hasn't changed. + +8. Execute `rustpkg build foo` where foo has a dependency on bar, which hasn't been built before. Check the datestamps on build/foo and build/bar and make sure bar's datestamp is earlier than foo's. + +9. Execute `rustpkg build foo` where foo has a dependency on bar, which hasn't been built before. Then, change one of the source files in bar. Execute `rustpkg build foo` again. Make sure, based on datestamps, that foo was really rebuilt. + +10. Repeat test 9 in the case where the contents of the source file in bar change but its datestamp doesn't change. + +11. If the current directory contains package directories for foo-0.1 and foo.0.2, `rustpkg install foo#0.1` installs foo#0.1 and doesn't install foo#0.2. + +12. `rustpkg do fancy-pkg frob` succeeds if `fancy-pkg` has a package script that defines a custom build hook named `frob`. + +13. `rustpkg info foo` prints out something about foo, if foo is installed. + +14. (Not sure what prefer and unprefer do) + +15. `rustpkg test foo` runs tests and prints their output, if foo contains #[test]s. + +16. If foo is installed, `rustpkg uninstall foo; rustpkg list` doesn't include foo in the list + From 128e95b89df851fdecec348a40c49feb61a7bee7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 19:00:52 -0700 Subject: [PATCH 241/403] rustpkg: Add more tests These are examples of what *should* work, and probably don't work yet. --- .../pass/deeply/nested/path/foo/main.rs | 18 +++++++++++++++ .../testsuite/pass/external-crate/main.rs | 21 ++++++++++++++++++ .../testsuite/pass/install-paths/bench.rs | 7 ++++++ .../testsuite/pass/install-paths/lib.rs | 11 ++++++++++ .../testsuite/pass/install-paths/main.rs | 22 +++++++++++++++++++ .../testsuite/pass/install-paths/test.rs | 14 ++++++++++++ 6 files changed, 93 insertions(+) create mode 100644 src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs create mode 100644 src/librustpkg/testsuite/pass/external-crate/main.rs create mode 100644 src/librustpkg/testsuite/pass/install-paths/bench.rs create mode 100644 src/librustpkg/testsuite/pass/install-paths/lib.rs create mode 100644 src/librustpkg/testsuite/pass/install-paths/main.rs create mode 100644 src/librustpkg/testsuite/pass/install-paths/test.rs diff --git a/src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs b/src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs new file mode 100644 index 0000000000000..41041ccb50912 --- /dev/null +++ b/src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs @@ -0,0 +1,18 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg install deeply/nested/path/foo`: + with RUST_PATH undefined in the environment: + * ./deeply/nested/path/foo exists and is an executable +*/ + +fn main() {} + diff --git a/src/librustpkg/testsuite/pass/external-crate/main.rs b/src/librustpkg/testsuite/pass/external-crate/main.rs new file mode 100644 index 0000000000000..d094bcd6bba62 --- /dev/null +++ b/src/librustpkg/testsuite/pass/external-crate/main.rs @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg install external crate` + with RUST_PATH undefined in the environment + and with `rustpkg install deeply/nested/path/foo` already + executed: + * ./.rust/external_crate exists and is an executable +*/ + +extern mod foo; // refers to deeply/nested/path/foo + +fn main() {} diff --git a/src/librustpkg/testsuite/pass/install-paths/bench.rs b/src/librustpkg/testsuite/pass/install-paths/bench.rs new file mode 100644 index 0000000000000..5aa6d2455cf3b --- /dev/null +++ b/src/librustpkg/testsuite/pass/install-paths/bench.rs @@ -0,0 +1,7 @@ +#[bench] +fn g() { + let mut x = 0; + while(x < 1000) { + x += 1; + } +} \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/install-paths/lib.rs b/src/librustpkg/testsuite/pass/install-paths/lib.rs new file mode 100644 index 0000000000000..baf90446f7aac --- /dev/null +++ b/src/librustpkg/testsuite/pass/install-paths/lib.rs @@ -0,0 +1,11 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() -> int { 42 } diff --git a/src/librustpkg/testsuite/pass/install-paths/main.rs b/src/librustpkg/testsuite/pass/install-paths/main.rs new file mode 100644 index 0000000000000..37e606dcb1ab3 --- /dev/null +++ b/src/librustpkg/testsuite/pass/install-paths/main.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/* +The test runner should check that, after `rustpkg install install-paths` + with RUST_PATH undefined in the environment: + * ./.rust/install_paths exists and is an executable + * ./.rust/libinstall_paths exists and is a library + * ./.rust/install_pathstest does not exist + * ./.rust/install_pathsbench does not exist + * install-paths/build/install_pathstest exists and is an executable + * install-paths/build/install_pathsbench exists and is an executable +*/ + +fn main() {} diff --git a/src/librustpkg/testsuite/pass/install-paths/test.rs b/src/librustpkg/testsuite/pass/install-paths/test.rs new file mode 100644 index 0000000000000..acfae9e04fb59 --- /dev/null +++ b/src/librustpkg/testsuite/pass/install-paths/test.rs @@ -0,0 +1,14 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[test] +fn test_two_plus_two() { + assert!(2 + 2 == 4); +} From 6030e3982a52c8d9ede225f992088bb75fba4ef1 Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Thu, 18 Apr 2013 17:19:41 +0900 Subject: [PATCH 242/403] Errors with the same span print the span once --- src/libsyntax/diagnostic.rs | 160 +++++++++++++++++++++++++++++++++--- 1 file changed, 147 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 24360734520e3..807371490dbc2 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -33,6 +33,7 @@ pub trait handler { fn bump_err_count(@mut self); fn has_errors(@mut self) -> bool; fn abort_if_errors(@mut self); + fn abort_error_print(@mut self); fn warn(@mut self, msg: &str); fn note(@mut self, msg: &str); // used to indicate a bug in the compiler: @@ -42,6 +43,7 @@ pub trait handler { cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level); + fn emit_print(@mut self, lvl: level); } // a span-handler is like a handler but also @@ -57,8 +59,15 @@ pub trait span_handler { fn handler(@mut self) -> @handler; } +struct emitter_arg { + cmsp: Option<(@codemap::CodeMap, span)>, + msg: ~str, + lvl: level, +} + struct HandlerT { err_count: uint, + emitters: ~[emitter_arg], emit: Emitter, } @@ -69,7 +78,11 @@ struct CodemapT { impl span_handler for CodemapT { fn span_fatal(@mut self, sp: span, msg: &str) -> ! { + self.handler.bump_err_count(); self.handler.emit(Some((self.cm, sp)), msg, fatal); + self.handler.emit_print(error); + self.handler.emit_print(note); + self.handler.abort_error_print(); fail!(); } fn span_err(@mut self, sp: span, msg: &str) { @@ -77,7 +90,7 @@ impl span_handler for CodemapT { self.handler.bump_err_count(); } fn span_warn(@mut self, sp: span, msg: &str) { - self.handler.emit(Some((self.cm, sp)), msg, warning); + emit_one(Some((self.cm, sp)), msg, warning); } fn span_note(@mut self, sp: span, msg: &str) { self.handler.emit(Some((self.cm, sp)), msg, note); @@ -95,11 +108,13 @@ impl span_handler for CodemapT { impl handler for HandlerT { fn fatal(@mut self, msg: &str) -> ! { - (self.emit)(None, msg, fatal); + self.emit_print(error); + self.emit_print(note); + emit_one(None, msg, fatal); fail!(); } fn err(@mut self, msg: &str) { - (self.emit)(None, msg, error); + emit_one(None, msg, error); self.bump_err_count(); } fn bump_err_count(@mut self) { @@ -118,13 +133,26 @@ impl handler for HandlerT { } self.fatal(s); } + fn abort_error_print(@mut self) { + let s; + match self.err_count { + 0u => return, + 1u => s = ~"aborting due to previous error", + _ => { + s = fmt!("aborting due to %u previous errors", + self.err_count); + } + } + emit_one(None, s, fatal); + } fn warn(@mut self, msg: &str) { - (self.emit)(None, msg, warning); + emit_one(None, msg, warning); } fn note(@mut self, msg: &str) { - (self.emit)(None, msg, note); + self.emit(None, msg, note); } fn bug(@mut self, msg: &str) -> ! { + self.bump_err_count(); self.fatal(ice_msg(msg)); } fn unimpl(@mut self, msg: &str) -> ! { @@ -135,6 +163,50 @@ impl handler for HandlerT { msg: &str, lvl: level) { (self.emit)(cmsp, msg, lvl); + let emitter = emitter_arg { cmsp: cmsp, + msg: str::from_slice(msg), + lvl: lvl }; + self.emitters.push(emitter); + } + + fn emit_print(@mut self, lvl: level) { + let mut old_cmsp = None; + let mut old_line = 0u; + + let emitters = self.emitters; + let length = emitters.len(); + for uint::range(0, length) |i| { + let emitter = copy self.emitters[i]; + let cmsp = emitter.cmsp; + let msg = emitter.msg; + if diagnosticstr(lvl) == diagnosticstr(emitter.lvl) { + match cmsp { + Some((cm, sp)) => { + let lo = cm.lookup_char_pos_adj(sp.lo); + let sp = cm.adjust_span(sp); + let ss = cm.span_to_str(sp); + if i == 0 || old_line == lo.line { + if old_line == lo.line { + highlight_lines_cmp(cmsp, old_cmsp); + } + print_diagnostic(ss, lvl, msg); + highlight_lines_cmp(old_cmsp, cmsp); + } else { + highlight_lines(old_cmsp); + print_macro_backtrace(old_cmsp); + print_diagnostic(ss, lvl, msg); + } + old_line = lo.line; + old_cmsp = emitter.cmsp; + } + None => { + print_diagnostic(~"", lvl, msg); + } + } + } + } + highlight_lines(old_cmsp); + print_macro_backtrace(old_cmsp); } } @@ -156,7 +228,9 @@ pub fn mk_handler(emitter: Option) -> @handler { } }; - @mut HandlerT { err_count: 0, emit: emit } as @handler + @mut HandlerT { err_count: 0, + emitters: ~[], + emit: emit } as @handler } #[deriving(Eq)] @@ -208,15 +282,19 @@ pub fn collect(messages: @mut ~[~str]) f } -pub fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) { +pub fn emit(_cmsp: Option<(@codemap::CodeMap, span)>, _msg: &str, _lvl: level) { + // Nothing to do +} + +pub fn emit_one(cmsp: Option<(@codemap::CodeMap, span)>, + msg: &str, lvl: level) { match cmsp { Some((cm, sp)) => { let sp = cm.adjust_span(sp); let ss = cm.span_to_str(sp); - let lines = cm.span_to_lines(sp); print_diagnostic(ss, lvl, msg); - highlight_lines(cm, sp, lines); - print_macro_backtrace(cm, sp); + highlight_lines(cmsp); + print_macro_backtrace(cmsp); } None => { print_diagnostic(~"", lvl, msg); @@ -224,7 +302,7 @@ pub fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) { } } -fn highlight_lines(cm: @codemap::CodeMap, +fn highlight_lines_internal(cm: @codemap::CodeMap, sp: span, lines: @codemap::FileLines) { let fm = lines.file; @@ -291,14 +369,70 @@ fn highlight_lines(cm: @codemap::CodeMap, } } -fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) { +fn highlight_lines(cmsp: Option<(@codemap::CodeMap, span)>) { + match cmsp { + Some((cm, sp)) => { + let sp = cm.adjust_span(sp); + let lines = cm.span_to_lines(sp); + highlight_lines_internal(cm, sp, lines); + } + None => () + } +} + +fn highlight_lines_cmp(old_cmsp: Option<(@codemap::CodeMap, span)>, + cmsp: Option<(@codemap::CodeMap, span)> ){ + let mut old_line = ~[]; + let mut new_line = ~[]; + let mut old_lo = 0u; + let mut new_lo = 0u; + let mut flag = true; + match old_cmsp { + Some((cm, sp)) => { + let lo = cm.lookup_char_pos(sp.lo); + let sp = cm.adjust_span(sp); + let lines = cm.span_to_lines(sp); + old_line = lines.lines; + old_lo = lo.col.to_uint(); + } + None => { flag = false; } + } + + match cmsp { + Some((cm, sp)) => { + let lo = cm.lookup_char_pos(sp.lo); + let sp = cm.adjust_span(sp); + let lines = cm.span_to_lines(sp); + new_line = lines.lines; + new_lo = lo.col.to_uint(); + } + None => { flag = false; } + } + + if flag { + if old_line == new_line && old_lo > new_lo { + highlight_lines(cmsp); + } + } +} + +fn print_macro_backtrace_internal(cm: @codemap::CodeMap, sp: span) { for sp.expn_info.each |ei| { let ss = ei.callee.span.map_default(@~"", |span| @cm.span_to_str(*span)); print_diagnostic(*ss, note, fmt!("in expansion of %s!", ei.callee.name)); let ss = cm.span_to_str(ei.call_site); print_diagnostic(ss, note, ~"expansion site"); - print_macro_backtrace(cm, ei.call_site); + print_macro_backtrace_internal(cm, ei.call_site); + } +} + +fn print_macro_backtrace(cmsp: Option<(@codemap::CodeMap, span)>) { + match cmsp { + Some((cm, sp)) => { + print_macro_backtrace_internal(cm, sp); + } + None => () } } From 5dda8ab12999d6f434a6d5f3746b48b757acb7b7 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Thu, 18 Apr 2013 12:25:03 +0300 Subject: [PATCH 243/403] sketch: Make rust sketch barf output prettier --- src/rt/rust_exchange_alloc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rt/rust_exchange_alloc.cpp b/src/rt/rust_exchange_alloc.cpp index a92bc4edd411a..5958c68f3e7d1 100644 --- a/src/rt/rust_exchange_alloc.cpp +++ b/src/rt/rust_exchange_alloc.cpp @@ -48,8 +48,8 @@ rust_get_exchange_count_ptr() { void rust_check_exchange_count_on_exit() { if (exchange_count != 0) { - printf("exchange heap not empty on on exit"); - printf("%d dangling allocations", (int)exchange_count); + printf("exchange heap not empty on exit\n"); + printf("%d dangling allocations\n", (int)exchange_count); abort(); } } From a35376e24ec28d79f4e29ec34061ba23353c3d57 Mon Sep 17 00:00:00 2001 From: Olivier Saut Date: Thu, 18 Apr 2013 11:51:12 +0200 Subject: [PATCH 244/403] Small typos, year date and URL of the fbuild system for reference. --- src/libstd/workcache.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index c4b450810aa86..d1aa069559e88 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -30,11 +30,12 @@ use core::to_bytes; /** * -* This is a loose clone of the fbuild build system, made a touch more -* generic (not wired to special cases on files) and much less metaprogram-y -* due to rust's comparative weakness there, relative to python. +* This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild), +* made a touch more generic (not wired to special cases on files) and much +* less metaprogram-y due to rust's comparative weakness there, relative to +* python. * -* It's based around _imperative bulids_ that happen to have some function +* It's based around _imperative builds_ that happen to have some function * calls cached. That is, it's _just_ a mechanism for describing cached * functions. This makes it much simpler and smaller than a "build system" * that produces an IR and evaluates it. The evaluation order is normal @@ -54,7 +55,7 @@ use core::to_bytes; * Works are conceptually single units, but we store them most of the time * in maps of the form (type,name) => value. These are WorkMaps. * -* A cached function divides the works it's interested up into inputs and +* A cached function divides the works it's interested in into inputs and * outputs, and subdivides those into declared (input) works and * discovered (input and output) works. * From 0ff568a3c1d4cc51109aacc88a598e6d3cfe5ea0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 18 Apr 2013 19:34:07 +1000 Subject: [PATCH 245/403] libcore: add an EnumerateIterator, like Python's `enumerate`. --- src/libcore/iterator.rs | 25 +++++++++++++++++++++++++ src/libcore/vec.rs | 10 ++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index fcb5102d4c07c..8a9f2d3e99425 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -22,6 +22,7 @@ pub trait IteratorUtil { // FIXME: #5898: should be called map fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; + fn enumerate(self) -> EnumerateIterator; fn advance(&mut self, f: &fn(A) -> bool); } @@ -42,6 +43,11 @@ impl> IteratorUtil for T { FilterIterator{iter: self, predicate: predicate} } + #[inline(always)] + fn enumerate(self) -> EnumerateIterator { + EnumerateIterator{iter: self, count: 0} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) { @@ -104,3 +110,22 @@ impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { } } } + +pub struct EnumerateIterator { + priv iter: T, + priv count: uint +} + +impl> Iterator<(uint, A)> for EnumerateIterator { + #[inline] + fn next(&mut self) -> Option<(uint, A)> { + match self.iter.next() { + Some(a) => { + let ret = Some((self.count, a)); + self.count += 1; + ret + } + _ => None + } + } +} diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 0403ae64f0205..eebe6a7a37f32 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -4474,6 +4474,16 @@ mod tests { i += 1; } } + + #[test] + fn test_iterator_enumerate() { + use iterator::*; + let xs = [0u,1,2,3,4,5]; + let mut it = xs.iter().enumerate(); + for it.advance |(i, &x): (uint, &uint)| { + assert_eq!(i, x); + } + } } // Local Variables: From f43fc5fff898d2c2d0b2a49ec35daf1005e76dd9 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 18 Apr 2013 20:46:23 +1000 Subject: [PATCH 246/403] libcore: make spawn_supervised documentation reflect its behaviour. --- src/libcore/task/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index a6c4b6c526862..2975f3d5e4660 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -466,8 +466,9 @@ pub fn spawn_unlinked(f: ~fn()) { pub fn spawn_supervised(f: ~fn()) { /*! - * Creates a child task unlinked from the current one. If either this - * task or the child task fails, the other will not be killed. + * Creates a child task supervised by the current one. If the child + * task fails, the parent will not be killed, but if the parent fails, + * the child will be killed. */ task().supervised().spawn(f) From d2a81b95c3e2ccfdba0324caae531ce3528ed4e2 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 18 Apr 2013 20:58:58 +1000 Subject: [PATCH 247/403] Implement bitwise operator traits for ints and uints --- src/libcore/num/int-template.rs | 34 +++++++++++++++++++++++++++++++ src/libcore/num/uint-template.rs | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index b495f9e7088fe..f901e59102743 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -199,6 +199,30 @@ impl ops::Modulo for T { impl ops::Neg for T { fn neg(&self) -> T { -*self } } +#[cfg(notest)] +impl ops::BitOr for T { + fn bitor(&self, other: &T) -> T { *self | *other } +} +#[cfg(notest)] +impl ops::BitAnd for T { + fn bitand(&self, other: &T) -> T { *self & *other } +} +#[cfg(notest)] +impl ops::BitXor for T { + fn bitxor(&self, other: &T) -> T { *self ^ *other } +} +#[cfg(notest)] +impl ops::Shl for T { + fn shl(&self, other: &T) -> T { *self << *other } +} +#[cfg(notest)] +impl ops::Shr for T { + fn shr(&self, other: &T) -> T { *self >> *other } +} +#[cfg(notest)] +impl ops::Not for T { + fn not(&self) -> T { !*self } +} // String conversion functions and impl str -> num @@ -283,6 +307,16 @@ mod tests { use super::inst::T; use prelude::*; + #[test] + fn test_bitwise_ops() { + assert!(0b1110 as T == (0b1100 as T).bitor(&(0b1010 as T))); + assert!(0b1000 as T == (0b1100 as T).bitand(&(0b1010 as T))); + assert!(0b0110 as T == (0b1100 as T).bitxor(&(0b1010 as T))); + assert!(0b1110 as T == (0b0111 as T).shl(&(1 as T))); + assert!(0b0111 as T == (0b1110 as T).shr(&(1 as T))); + assert!(-(0b11 as T) - (1 as T) == (0b11 as T).not()); + } + #[test] fn test_from_str() { assert!(from_str(~"0") == Some(0 as T)); diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index af6557e9881f2..34c11804af439 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -164,6 +164,30 @@ impl ops::Modulo for T { impl ops::Neg for T { fn neg(&self) -> T { -*self } } +#[cfg(notest)] +impl ops::BitOr for T { + fn bitor(&self, other: &T) -> T { *self | *other } +} +#[cfg(notest)] +impl ops::BitAnd for T { + fn bitand(&self, other: &T) -> T { *self & *other } +} +#[cfg(notest)] +impl ops::BitXor for T { + fn bitxor(&self, other: &T) -> T { *self ^ *other } +} +#[cfg(notest)] +impl ops::Shl for T { + fn shl(&self, other: &T) -> T { *self << *other } +} +#[cfg(notest)] +impl ops::Shr for T { + fn shr(&self, other: &T) -> T { *self >> *other } +} +#[cfg(notest)] +impl ops::Not for T { + fn not(&self) -> T { !*self } +} // String conversion functions and impl str -> num @@ -247,6 +271,17 @@ mod tests { use super::*; use super::inst::T; use prelude::*; + + #[test] + fn test_bitwise_ops() { + assert!(0b1110 as T == (0b1100 as T).bitor(&(0b1010 as T))); + assert!(0b1000 as T == (0b1100 as T).bitand(&(0b1010 as T))); + assert!(0b0110 as T == (0b1100 as T).bitxor(&(0b1010 as T))); + assert!(0b1110 as T == (0b0111 as T).shl(&(1 as T))); + assert!(0b0111 as T == (0b1110 as T).shr(&(1 as T))); + assert!(max_value - (0b1011 as T) == (0b1011 as T).not()); + } + #[test] pub fn test_to_str() { assert!(to_str_radix(0 as T, 10u) == ~"0"); From c967f2bb1e564cb4344ac3df87c9b52399f65d7d Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 18 Apr 2013 22:50:55 +1000 Subject: [PATCH 248/403] core: add a str iterator --- src/libcore/str.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index b0653db365e03..7cc3a694c5608 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -24,6 +24,7 @@ use clone::Clone; use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use libc; use option::{None, Option, Some}; +use iterator::Iterator; use ptr; use str; use u8; @@ -2358,6 +2359,10 @@ pub trait StrSlice<'self> { fn any(&self, it: &fn(char) -> bool) -> bool; fn contains<'a>(&self, needle: &'a str) -> bool; fn contains_char(&self, needle: char) -> bool; + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + fn char_iter(&self) -> StrCharIterator<'self>; fn each(&self, it: &fn(u8) -> bool); fn eachi(&self, it: &fn(uint, u8) -> bool); fn each_reverse(&self, it: &fn(u8) -> bool); @@ -2419,6 +2424,18 @@ impl<'self> StrSlice<'self> for &'self str { fn contains_char(&self, needle: char) -> bool { contains_char(*self, needle) } + + #[cfg(stage1)] + #[cfg(stage2)] + #[cfg(stage3)] + #[inline] + fn char_iter(&self) -> StrCharIterator<'self> { + StrCharIterator { + index: 0, + string: *self + } + } + /// Iterate over the bytes in a string #[inline] fn each(&self, it: &fn(u8) -> bool) { each(*self, it) } @@ -2609,6 +2626,30 @@ impl Clone for ~str { } } +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub struct StrCharIterator<'self> { + priv index: uint, + priv string: &'self str, +} + +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +impl<'self> Iterator for StrCharIterator<'self> { + #[inline] + fn next(&mut self) -> Option { + if self.index < self.string.len() { + let CharRange {ch, next} = char_range_at(self.string, self.index); + self.index = next; + Some(ch) + } else { + None + } + } +} + #[cfg(test)] mod tests { use char; @@ -3901,4 +3942,19 @@ mod tests { assert!(char_range_at_reverse("abc", 0).next == 0); } + #[test] + fn test_iterator() { + use iterator::*; + let s = ~"ศไทย中华Việt Nam"; + let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + + let mut pos = 0; + let mut it = s.char_iter(); + + for it.advance |c| { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); + } } From 939a97f5cb4c8f44bc60784bbf4aa5d44f1c5dca Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 18 Apr 2013 23:24:24 +1000 Subject: [PATCH 249/403] Add #[inline(always)] to each operator method --- src/libcore/num/f32.rs | 6 ++++++ src/libcore/num/f64.rs | 6 ++++++ src/libcore/num/float.rs | 12 ++++++++++++ src/libcore/num/int-template.rs | 13 +++++++++++++ src/libcore/num/uint-template.rs | 13 +++++++++++++ 5 files changed, 50 insertions(+) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 5e672ea0dfa86..404f1a82de5d0 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -288,26 +288,32 @@ impl num::One for f32 { #[cfg(notest)] impl ops::Add for f32 { + #[inline(always)] fn add(&self, other: &f32) -> f32 { *self + *other } } #[cfg(notest)] impl ops::Sub for f32 { + #[inline(always)] fn sub(&self, other: &f32) -> f32 { *self - *other } } #[cfg(notest)] impl ops::Mul for f32 { + #[inline(always)] fn mul(&self, other: &f32) -> f32 { *self * *other } } #[cfg(notest)] impl ops::Div for f32 { + #[inline(always)] fn div(&self, other: &f32) -> f32 { *self / *other } } #[cfg(notest)] impl ops::Modulo for f32 { + #[inline(always)] fn modulo(&self, other: &f32) -> f32 { *self % *other } } #[cfg(notest)] impl ops::Neg for f32 { + #[inline(always)] fn neg(&self) -> f32 { -*self } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 4c96da73d2130..b4eaa0e7fdc60 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -310,26 +310,32 @@ impl num::One for f64 { #[cfg(notest)] impl ops::Add for f64 { + #[inline(always)] fn add(&self, other: &f64) -> f64 { *self + *other } } #[cfg(notest)] impl ops::Sub for f64 { + #[inline(always)] fn sub(&self, other: &f64) -> f64 { *self - *other } } #[cfg(notest)] impl ops::Mul for f64 { + #[inline(always)] fn mul(&self, other: &f64) -> f64 { *self * *other } } #[cfg(notest)] impl ops::Div for f64 { + #[inline(always)] fn div(&self, other: &f64) -> f64 { *self / *other } } #[cfg(notest)] impl ops::Modulo for f64 { + #[inline(always)] fn modulo(&self, other: &f64) -> f64 { *self % *other } } #[cfg(notest)] impl ops::Neg for f64 { + #[inline(always)] fn neg(&self) -> f64 { -*self } } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 488756787b5cd..42f0f033ac243 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -387,15 +387,21 @@ pub fn tan(x: float) -> float { #[cfg(notest)] impl Eq for float { + #[inline(always)] fn eq(&self, other: &float) -> bool { (*self) == (*other) } + #[inline(always)] fn ne(&self, other: &float) -> bool { (*self) != (*other) } } #[cfg(notest)] impl Ord for float { + #[inline(always)] fn lt(&self, other: &float) -> bool { (*self) < (*other) } + #[inline(always)] fn le(&self, other: &float) -> bool { (*self) <= (*other) } + #[inline(always)] fn ge(&self, other: &float) -> bool { (*self) >= (*other) } + #[inline(always)] fn gt(&self, other: &float) -> bool { (*self) > (*other) } } @@ -444,26 +450,32 @@ impl num::Round for float { #[cfg(notest)] impl ops::Add for float { + #[inline(always)] fn add(&self, other: &float) -> float { *self + *other } } #[cfg(notest)] impl ops::Sub for float { + #[inline(always)] fn sub(&self, other: &float) -> float { *self - *other } } #[cfg(notest)] impl ops::Mul for float { + #[inline(always)] fn mul(&self, other: &float) -> float { *self * *other } } #[cfg(notest)] impl ops::Div for float { + #[inline(always)] fn div(&self, other: &float) -> float { *self / *other } } #[cfg(notest)] impl ops::Modulo for float { + #[inline(always)] fn modulo(&self, other: &float) -> float { *self % *other } } #[cfg(notest)] impl ops::Neg for float { + #[inline(always)] fn neg(&self) -> float { -*self } } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index f901e59102743..044c62e92c17d 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -177,50 +177,63 @@ impl num::One for T { #[cfg(notest)] impl ops::Add for T { + #[inline(always)] fn add(&self, other: &T) -> T { *self + *other } } #[cfg(notest)] impl ops::Sub for T { + #[inline(always)] fn sub(&self, other: &T) -> T { *self - *other } } #[cfg(notest)] impl ops::Mul for T { + #[inline(always)] fn mul(&self, other: &T) -> T { *self * *other } } #[cfg(notest)] impl ops::Div for T { + #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } #[cfg(notest)] impl ops::Modulo for T { + #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } #[cfg(notest)] impl ops::Neg for T { + #[inline(always)] fn neg(&self) -> T { -*self } } + #[cfg(notest)] impl ops::BitOr for T { + #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } #[cfg(notest)] impl ops::BitAnd for T { + #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } #[cfg(notest)] impl ops::BitXor for T { + #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } #[cfg(notest)] impl ops::Shl for T { + #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } #[cfg(notest)] impl ops::Shr for T { + #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } #[cfg(notest)] impl ops::Not for T { + #[inline(always)] fn not(&self) -> T { !*self } } diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 34c11804af439..b49ec65a95bbf 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -142,50 +142,63 @@ impl num::One for T { #[cfg(notest)] impl ops::Add for T { + #[inline(always)] fn add(&self, other: &T) -> T { *self + *other } } #[cfg(notest)] impl ops::Sub for T { + #[inline(always)] fn sub(&self, other: &T) -> T { *self - *other } } #[cfg(notest)] impl ops::Mul for T { + #[inline(always)] fn mul(&self, other: &T) -> T { *self * *other } } #[cfg(notest)] impl ops::Div for T { + #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } #[cfg(notest)] impl ops::Modulo for T { + #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } #[cfg(notest)] impl ops::Neg for T { + #[inline(always)] fn neg(&self) -> T { -*self } } + #[cfg(notest)] impl ops::BitOr for T { + #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } #[cfg(notest)] impl ops::BitAnd for T { + #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } #[cfg(notest)] impl ops::BitXor for T { + #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } #[cfg(notest)] impl ops::Shl for T { + #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } #[cfg(notest)] impl ops::Shr for T { + #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } #[cfg(notest)] impl ops::Not for T { + #[inline(always)] fn not(&self) -> T { !*self } } From 19cc352302838dd379c0d4a335a093fbfd0df64b Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 18 Apr 2013 23:36:38 +1000 Subject: [PATCH 250/403] core: io: the read_until function checks bytes not chars, so type should reflect that. --- src/libcore/io.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 3c5900f51a247..35ffd88c8f477 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -176,7 +176,7 @@ pub trait ReaderUtil { fn read_bytes(&self, len: uint) -> ~[u8]; /** - * Reads up until a specific character or EOF. + * Reads up until a specific byte is seen or EOF. * * The `include` parameter specifies if the character should be included * in the returned string. @@ -185,7 +185,7 @@ pub trait ReaderUtil { * * None right now. */ - fn read_until(&self, c: char, include: bool) -> ~str; + fn read_until(&self, c: u8, include: bool) -> ~str; /** * Reads up until the first '\n' or EOF. @@ -577,7 +577,7 @@ impl ReaderUtil for T { bytes } - fn read_until(&self, c: char, include: bool) -> ~str { + fn read_until(&self, c: u8, include: bool) -> ~str { let mut bytes = ~[]; loop { let ch = self.read_byte(); @@ -593,7 +593,7 @@ impl ReaderUtil for T { } fn read_line(&self) -> ~str { - self.read_until('\n', false) + self.read_until('\n' as u8, false) } fn read_chars(&self, n: uint) -> ~[char] { @@ -667,7 +667,7 @@ impl ReaderUtil for T { } fn read_c_str(&self) -> ~str { - self.read_until(0 as char, false) + self.read_until(0u8, false) } fn read_whole_stream(&self) -> ~[u8] { @@ -693,7 +693,7 @@ impl ReaderUtil for T { // include the \n, so that we can distinguish an entirely empty // line read after "...\n", and the trailing empty line in // "...\n\n". - let mut line = self.read_until('\n', true); + let mut line = self.read_until('\n' as u8, true); // blank line at the end of the reader is ignored if self.eof() && line.is_empty() { break; } From a7f6ec854223772bd5c445d6cd2a17a045009f72 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 19 Apr 2013 01:37:21 +1000 Subject: [PATCH 251/403] Use assert_eq! instead of assert! and remove extraneous parentheses --- src/libcore/num/float.rs | 192 +++++++++++++++---------------- src/libcore/num/int-template.rs | 131 ++++++++++----------- src/libcore/num/num.rs | 106 ++++++++--------- src/libcore/num/uint-template.rs | 98 ++++++++-------- 4 files changed, 260 insertions(+), 267 deletions(-) diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 42f0f033ac243..38111210c73c1 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -486,29 +486,29 @@ mod tests { #[test] pub fn test_to_str_exact_do_decimal() { let s = to_str_exact(5.0, 4u); - assert!(s == ~"5.0000"); + assert_eq!(s, ~"5.0000"); } #[test] pub fn test_from_str() { - assert!(from_str(~"3") == Some(3.)); - assert!(from_str(~"3.14") == Some(3.14)); - assert!(from_str(~"+3.14") == Some(3.14)); - assert!(from_str(~"-3.14") == Some(-3.14)); - assert!(from_str(~"2.5E10") == Some(25000000000.)); - assert!(from_str(~"2.5e10") == Some(25000000000.)); - assert!(from_str(~"25000000000.E-10") == Some(2.5)); - assert!(from_str(~".") == Some(0.)); - assert!(from_str(~".e1") == Some(0.)); - assert!(from_str(~".e-1") == Some(0.)); - assert!(from_str(~"5.") == Some(5.)); - assert!(from_str(~".5") == Some(0.5)); - assert!(from_str(~"0.5") == Some(0.5)); - assert!(from_str(~"-.5") == Some(-0.5)); - assert!(from_str(~"-5") == Some(-5.)); - assert!(from_str(~"inf") == Some(infinity)); - assert!(from_str(~"+inf") == Some(infinity)); - assert!(from_str(~"-inf") == Some(neg_infinity)); + assert_eq!(from_str(~"3"), Some(3.)); + assert_eq!(from_str(~"3.14"), Some(3.14)); + assert_eq!(from_str(~"+3.14"), Some(3.14)); + assert_eq!(from_str(~"-3.14"), Some(-3.14)); + assert_eq!(from_str(~"2.5E10"), Some(25000000000.)); + assert_eq!(from_str(~"2.5e10"), Some(25000000000.)); + assert_eq!(from_str(~"25000000000.E-10"), Some(2.5)); + assert_eq!(from_str(~"."), Some(0.)); + assert_eq!(from_str(~".e1"), Some(0.)); + assert_eq!(from_str(~".e-1"), Some(0.)); + assert_eq!(from_str(~"5."), Some(5.)); + assert_eq!(from_str(~".5"), Some(0.5)); + assert_eq!(from_str(~"0.5"), Some(0.5)); + assert_eq!(from_str(~"-.5"), Some(-0.5)); + assert_eq!(from_str(~"-5"), Some(-5.)); + assert_eq!(from_str(~"inf"), Some(infinity)); + assert_eq!(from_str(~"+inf"), Some(infinity)); + assert_eq!(from_str(~"-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test match from_str(~"NaN") { Some(f) => assert!(is_NaN(f)), @@ -538,24 +538,24 @@ mod tests { #[test] pub fn test_from_str_hex() { - assert!(from_str_hex(~"a4") == Some(164.)); - assert!(from_str_hex(~"a4.fe") == Some(164.9921875)); - assert!(from_str_hex(~"-a4.fe") == Some(-164.9921875)); - assert!(from_str_hex(~"+a4.fe") == Some(164.9921875)); - assert!(from_str_hex(~"ff0P4") == Some(0xff00 as float)); - assert!(from_str_hex(~"ff0p4") == Some(0xff00 as float)); - assert!(from_str_hex(~"ff0p-4") == Some(0xff as float)); - assert!(from_str_hex(~".") == Some(0.)); - assert!(from_str_hex(~".p1") == Some(0.)); - assert!(from_str_hex(~".p-1") == Some(0.)); - assert!(from_str_hex(~"f.") == Some(15.)); - assert!(from_str_hex(~".f") == Some(0.9375)); - assert!(from_str_hex(~"0.f") == Some(0.9375)); - assert!(from_str_hex(~"-.f") == Some(-0.9375)); - assert!(from_str_hex(~"-f") == Some(-15.)); - assert!(from_str_hex(~"inf") == Some(infinity)); - assert!(from_str_hex(~"+inf") == Some(infinity)); - assert!(from_str_hex(~"-inf") == Some(neg_infinity)); + assert_eq!(from_str_hex(~"a4"), Some(164.)); + assert_eq!(from_str_hex(~"a4.fe"), Some(164.9921875)); + assert_eq!(from_str_hex(~"-a4.fe"), Some(-164.9921875)); + assert_eq!(from_str_hex(~"+a4.fe"), Some(164.9921875)); + assert_eq!(from_str_hex(~"ff0P4"), Some(0xff00 as float)); + assert_eq!(from_str_hex(~"ff0p4"), Some(0xff00 as float)); + assert_eq!(from_str_hex(~"ff0p-4"), Some(0xff as float)); + assert_eq!(from_str_hex(~"."), Some(0.)); + assert_eq!(from_str_hex(~".p1"), Some(0.)); + assert_eq!(from_str_hex(~".p-1"), Some(0.)); + assert_eq!(from_str_hex(~"f."), Some(15.)); + assert_eq!(from_str_hex(~".f"), Some(0.9375)); + assert_eq!(from_str_hex(~"0.f"), Some(0.9375)); + assert_eq!(from_str_hex(~"-.f"), Some(-0.9375)); + assert_eq!(from_str_hex(~"-f"), Some(-15.)); + assert_eq!(from_str_hex(~"inf"), Some(infinity)); + assert_eq!(from_str_hex(~"+inf"), Some(infinity)); + assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test match from_str_hex(~"NaN") { Some(f) => assert!(is_NaN(f)), @@ -570,11 +570,11 @@ mod tests { Some(v) if is_zero(v) => assert!(is_positive(v)), _ => fail!() } - assert!(from_str_hex(~"e") == Some(14.)); - assert!(from_str_hex(~"E") == Some(14.)); - assert!(from_str_hex(~"E1") == Some(225.)); - assert!(from_str_hex(~"1e1e1") == Some(123361.)); - assert!(from_str_hex(~"1e1.1") == Some(481.0625)); + assert_eq!(from_str_hex(~"e"), Some(14.)); + assert_eq!(from_str_hex(~"E"), Some(14.)); + assert_eq!(from_str_hex(~"E1"), Some(225.)); + assert_eq!(from_str_hex(~"1e1e1"), Some(123361.)); + assert_eq!(from_str_hex(~"1e1.1"), Some(481.0625)); assert!(from_str_hex(~"").is_none()); assert!(from_str_hex(~"x").is_none()); @@ -590,92 +590,92 @@ mod tests { #[test] pub fn test_to_str_hex() { - assert!(to_str_hex(164.) == ~"a4"); - assert!(to_str_hex(164.9921875) == ~"a4.fe"); - assert!(to_str_hex(-164.9921875) == ~"-a4.fe"); - assert!(to_str_hex(0xff00 as float) == ~"ff00"); - assert!(to_str_hex(-(0xff00 as float)) == ~"-ff00"); - assert!(to_str_hex(0.) == ~"0"); - assert!(to_str_hex(15.) == ~"f"); - assert!(to_str_hex(-15.) == ~"-f"); - assert!(to_str_hex(0.9375) == ~"0.f"); - assert!(to_str_hex(-0.9375) == ~"-0.f"); - assert!(to_str_hex(infinity) == ~"inf"); - assert!(to_str_hex(neg_infinity) == ~"-inf"); - assert!(to_str_hex(NaN) == ~"NaN"); - assert!(to_str_hex(0.) == ~"0"); - assert!(to_str_hex(-0.) == ~"-0"); + assert_eq!(to_str_hex(164.), ~"a4"); + assert_eq!(to_str_hex(164.9921875), ~"a4.fe"); + assert_eq!(to_str_hex(-164.9921875), ~"-a4.fe"); + assert_eq!(to_str_hex(0xff00 as float), ~"ff00"); + assert_eq!(to_str_hex(-(0xff00 as float)), ~"-ff00"); + assert_eq!(to_str_hex(0.), ~"0"); + assert_eq!(to_str_hex(15.), ~"f"); + assert_eq!(to_str_hex(-15.), ~"-f"); + assert_eq!(to_str_hex(0.9375), ~"0.f"); + assert_eq!(to_str_hex(-0.9375), ~"-0.f"); + assert_eq!(to_str_hex(infinity), ~"inf"); + assert_eq!(to_str_hex(neg_infinity), ~"-inf"); + assert_eq!(to_str_hex(NaN), ~"NaN"); + assert_eq!(to_str_hex(0.), ~"0"); + assert_eq!(to_str_hex(-0.), ~"-0"); } #[test] pub fn test_to_str_radix() { - assert!(to_str_radix(36., 36u) == ~"10"); - assert!(to_str_radix(8.125, 2u) == ~"1000.001"); + assert_eq!(to_str_radix(36., 36u), ~"10"); + assert_eq!(to_str_radix(8.125, 2u), ~"1000.001"); } #[test] pub fn test_from_str_radix() { - assert!(from_str_radix(~"10", 36u) == Some(36.)); - assert!(from_str_radix(~"1000.001", 2u) == Some(8.125)); + assert_eq!(from_str_radix(~"10", 36u), Some(36.)); + assert_eq!(from_str_radix(~"1000.001", 2u), Some(8.125)); } #[test] pub fn test_positive() { - assert!((is_positive(infinity))); - assert!((is_positive(1.))); - assert!((is_positive(0.))); - assert!((!is_positive(-1.))); - assert!((!is_positive(neg_infinity))); - assert!((!is_positive(1./neg_infinity))); - assert!((!is_positive(NaN))); + assert!(is_positive(infinity)); + assert!(is_positive(1.)); + assert!(is_positive(0.)); + assert!(!is_positive(-1.)); + assert!(!is_positive(neg_infinity)); + assert!(!is_positive(1./neg_infinity)); + assert!(!is_positive(NaN)); } #[test] pub fn test_negative() { - assert!((!is_negative(infinity))); - assert!((!is_negative(1.))); - assert!((!is_negative(0.))); - assert!((is_negative(-1.))); - assert!((is_negative(neg_infinity))); - assert!((is_negative(1./neg_infinity))); - assert!((!is_negative(NaN))); + assert!(!is_negative(infinity)); + assert!(!is_negative(1.)); + assert!(!is_negative(0.)); + assert!(is_negative(-1.)); + assert!(is_negative(neg_infinity)); + assert!(is_negative(1./neg_infinity)); + assert!(!is_negative(NaN)); } #[test] pub fn test_nonpositive() { - assert!((!is_nonpositive(infinity))); - assert!((!is_nonpositive(1.))); - assert!((!is_nonpositive(0.))); - assert!((is_nonpositive(-1.))); - assert!((is_nonpositive(neg_infinity))); - assert!((is_nonpositive(1./neg_infinity))); - assert!((!is_nonpositive(NaN))); + assert!(!is_nonpositive(infinity)); + assert!(!is_nonpositive(1.)); + assert!(!is_nonpositive(0.)); + assert!(is_nonpositive(-1.)); + assert!(is_nonpositive(neg_infinity)); + assert!(is_nonpositive(1./neg_infinity)); + assert!(!is_nonpositive(NaN)); } #[test] pub fn test_nonnegative() { - assert!((is_nonnegative(infinity))); - assert!((is_nonnegative(1.))); - assert!((is_nonnegative(0.))); - assert!((!is_nonnegative(-1.))); - assert!((!is_nonnegative(neg_infinity))); - assert!((!is_nonnegative(1./neg_infinity))); - assert!((!is_nonnegative(NaN))); + assert!(is_nonnegative(infinity)); + assert!(is_nonnegative(1.)); + assert!(is_nonnegative(0.)); + assert!(!is_nonnegative(-1.)); + assert!(!is_nonnegative(neg_infinity)); + assert!(!is_nonnegative(1./neg_infinity)); + assert!(!is_nonnegative(NaN)); } #[test] pub fn test_to_str_inf() { - assert!(to_str_digits(infinity, 10u) == ~"inf"); - assert!(to_str_digits(-infinity, 10u) == ~"-inf"); + assert_eq!(to_str_digits(infinity, 10u), ~"inf"); + assert_eq!(to_str_digits(-infinity, 10u), ~"-inf"); } #[test] pub fn test_round() { - assert!(round(5.8) == 6.0); - assert!(round(5.2) == 5.0); - assert!(round(3.0) == 3.0); - assert!(round(2.5) == 3.0); - assert!(round(-3.5) == -4.0); + assert_eq!(round(5.8), 6.0); + assert_eq!(round(5.2), 5.0); + assert_eq!(round(3.0), 3.0); + assert_eq!(round(2.5), 3.0); + assert_eq!(round(-3.5), -4.0); } } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 044c62e92c17d..8fd61fb6187e4 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -322,27 +322,27 @@ mod tests { #[test] fn test_bitwise_ops() { - assert!(0b1110 as T == (0b1100 as T).bitor(&(0b1010 as T))); - assert!(0b1000 as T == (0b1100 as T).bitand(&(0b1010 as T))); - assert!(0b0110 as T == (0b1100 as T).bitxor(&(0b1010 as T))); - assert!(0b1110 as T == (0b0111 as T).shl(&(1 as T))); - assert!(0b0111 as T == (0b1110 as T).shr(&(1 as T))); - assert!(-(0b11 as T) - (1 as T) == (0b11 as T).not()); + assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); + assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T))); + assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T))); + assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T))); + assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T))); + assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not()); } #[test] fn test_from_str() { - assert!(from_str(~"0") == Some(0 as T)); - assert!(from_str(~"3") == Some(3 as T)); - assert!(from_str(~"10") == Some(10 as T)); - assert!(i32::from_str(~"123456789") == Some(123456789 as i32)); - assert!(from_str(~"00100") == Some(100 as T)); - - assert!(from_str(~"-1") == Some(-1 as T)); - assert!(from_str(~"-3") == Some(-3 as T)); - assert!(from_str(~"-10") == Some(-10 as T)); - assert!(i32::from_str(~"-123456789") == Some(-123456789 as i32)); - assert!(from_str(~"-00100") == Some(-100 as T)); + assert_eq!(from_str(~"0"), Some(0 as T)); + assert_eq!(from_str(~"3"), Some(3 as T)); + assert_eq!(from_str(~"10"), Some(10 as T)); + assert_eq!(i32::from_str(~"123456789"), Some(123456789 as i32)); + assert_eq!(from_str(~"00100"), Some(100 as T)); + + assert_eq!(from_str(~"-1"), Some(-1 as T)); + assert_eq!(from_str(~"-3"), Some(-3 as T)); + assert_eq!(from_str(~"-10"), Some(-10 as T)); + assert_eq!(i32::from_str(~"-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str(~"-00100"), Some(-100 as T)); assert!(from_str(~" ").is_none()); assert!(from_str(~"x").is_none()); @@ -351,28 +351,23 @@ mod tests { #[test] fn test_parse_bytes() { use str::to_bytes; - assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123 as T)); - assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9 as T)); - assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83 as T)); - assert!(i32::parse_bytes(to_bytes(~"123"), 16u) == Some(291 as i32)); - assert!(i32::parse_bytes(to_bytes(~"ffff"), 16u) == - Some(65535 as i32)); - assert!(i32::parse_bytes(to_bytes(~"FFFF"), 16u) == - Some(65535 as i32)); - assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35 as T)); - assert!(parse_bytes(to_bytes(~"Z"), 36u) == Some(35 as T)); - - assert!(parse_bytes(to_bytes(~"-123"), 10u) == Some(-123 as T)); - assert!(parse_bytes(to_bytes(~"-1001"), 2u) == Some(-9 as T)); - assert!(parse_bytes(to_bytes(~"-123"), 8u) == Some(-83 as T)); - assert!(i32::parse_bytes(to_bytes(~"-123"), 16u) == - Some(-291 as i32)); - assert!(i32::parse_bytes(to_bytes(~"-ffff"), 16u) == - Some(-65535 as i32)); - assert!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u) == - Some(-65535 as i32)); - assert!(parse_bytes(to_bytes(~"-z"), 36u) == Some(-35 as T)); - assert!(parse_bytes(to_bytes(~"-Z"), 36u) == Some(-35 as T)); + assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123 as T)); + assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9 as T)); + assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83 as T)); + assert_eq!(i32::parse_bytes(to_bytes(~"123"), 16u), Some(291 as i32)); + assert_eq!(i32::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535 as i32)); + assert_eq!(i32::parse_bytes(to_bytes(~"FFFF"), 16u), Some(65535 as i32)); + assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35 as T)); + assert_eq!(parse_bytes(to_bytes(~"Z"), 36u), Some(35 as T)); + + assert_eq!(parse_bytes(to_bytes(~"-123"), 10u), Some(-123 as T)); + assert_eq!(parse_bytes(to_bytes(~"-1001"), 2u), Some(-9 as T)); + assert_eq!(parse_bytes(to_bytes(~"-123"), 8u), Some(-83 as T)); + assert_eq!(i32::parse_bytes(to_bytes(~"-123"), 16u), Some(-291 as i32)); + assert_eq!(i32::parse_bytes(to_bytes(~"-ffff"), 16u), Some(-65535 as i32)); + assert_eq!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u), Some(-65535 as i32)); + assert_eq!(parse_bytes(to_bytes(~"-z"), 36u), Some(-35 as T)); + assert_eq!(parse_bytes(to_bytes(~"-Z"), 36u), Some(-35 as T)); assert!(parse_bytes(to_bytes(~"Z"), 35u).is_none()); assert!(parse_bytes(to_bytes(~"-9"), 2u).is_none()); @@ -380,74 +375,74 @@ mod tests { #[test] fn test_to_str() { - assert!((to_str_radix(0 as T, 10u) == ~"0")); - assert!((to_str_radix(1 as T, 10u) == ~"1")); - assert!((to_str_radix(-1 as T, 10u) == ~"-1")); - assert!((to_str_radix(127 as T, 16u) == ~"7f")); - assert!((to_str_radix(100 as T, 10u) == ~"100")); + assert_eq!(to_str_radix(0 as T, 10u), ~"0"); + assert_eq!(to_str_radix(1 as T, 10u), ~"1"); + assert_eq!(to_str_radix(-1 as T, 10u), ~"-1"); + assert_eq!(to_str_radix(127 as T, 16u), ~"7f"); + assert_eq!(to_str_radix(100 as T, 10u), ~"100"); } #[test] fn test_int_to_str_overflow() { let mut i8_val: i8 = 127_i8; - assert!((i8::to_str(i8_val) == ~"127")); + assert_eq!(i8::to_str(i8_val), ~"127"); i8_val += 1 as i8; - assert!((i8::to_str(i8_val) == ~"-128")); + assert_eq!(i8::to_str(i8_val), ~"-128"); let mut i16_val: i16 = 32_767_i16; - assert!((i16::to_str(i16_val) == ~"32767")); + assert_eq!(i16::to_str(i16_val), ~"32767"); i16_val += 1 as i16; - assert!((i16::to_str(i16_val) == ~"-32768")); + assert_eq!(i16::to_str(i16_val), ~"-32768"); let mut i32_val: i32 = 2_147_483_647_i32; - assert!((i32::to_str(i32_val) == ~"2147483647")); + assert_eq!(i32::to_str(i32_val), ~"2147483647"); i32_val += 1 as i32; - assert!((i32::to_str(i32_val) == ~"-2147483648")); + assert_eq!(i32::to_str(i32_val), ~"-2147483648"); let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert!((i64::to_str(i64_val) == ~"9223372036854775807")); + assert_eq!(i64::to_str(i64_val), ~"9223372036854775807"); i64_val += 1 as i64; - assert!((i64::to_str(i64_val) == ~"-9223372036854775808")); + assert_eq!(i64::to_str(i64_val), ~"-9223372036854775808"); } #[test] fn test_int_from_str_overflow() { let mut i8_val: i8 = 127_i8; - assert!((i8::from_str(~"127") == Some(i8_val))); - assert!((i8::from_str(~"128").is_none())); + assert_eq!(i8::from_str(~"127"), Some(i8_val)); + assert!(i8::from_str(~"128").is_none()); i8_val += 1 as i8; - assert!((i8::from_str(~"-128") == Some(i8_val))); - assert!((i8::from_str(~"-129").is_none())); + assert_eq!(i8::from_str(~"-128"), Some(i8_val)); + assert!(i8::from_str(~"-129").is_none()); let mut i16_val: i16 = 32_767_i16; - assert!((i16::from_str(~"32767") == Some(i16_val))); - assert!((i16::from_str(~"32768").is_none())); + assert_eq!(i16::from_str(~"32767"), Some(i16_val)); + assert!(i16::from_str(~"32768").is_none()); i16_val += 1 as i16; - assert!((i16::from_str(~"-32768") == Some(i16_val))); - assert!((i16::from_str(~"-32769").is_none())); + assert_eq!(i16::from_str(~"-32768"), Some(i16_val)); + assert!(i16::from_str(~"-32769").is_none()); let mut i32_val: i32 = 2_147_483_647_i32; - assert!((i32::from_str(~"2147483647") == Some(i32_val))); - assert!((i32::from_str(~"2147483648").is_none())); + assert_eq!(i32::from_str(~"2147483647"), Some(i32_val)); + assert!(i32::from_str(~"2147483648").is_none()); i32_val += 1 as i32; - assert!((i32::from_str(~"-2147483648") == Some(i32_val))); - assert!((i32::from_str(~"-2147483649").is_none())); + assert_eq!(i32::from_str(~"-2147483648"), Some(i32_val)); + assert!(i32::from_str(~"-2147483649").is_none()); let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert!((i64::from_str(~"9223372036854775807") == Some(i64_val))); - assert!((i64::from_str(~"9223372036854775808").is_none())); + assert_eq!(i64::from_str(~"9223372036854775807"), Some(i64_val)); + assert!(i64::from_str(~"9223372036854775808").is_none()); i64_val += 1 as i64; - assert!((i64::from_str(~"-9223372036854775808") == Some(i64_val))); - assert!((i64::from_str(~"-9223372036854775809").is_none())); + assert_eq!(i64::from_str(~"-9223372036854775808"), Some(i64_val)); + assert!(i64::from_str(~"-9223372036854775809").is_none()); } #[test] diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 19a1e276d3754..5834214475219 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -77,7 +77,7 @@ pub enum RoundMode { * * ~~~ * let twenty: f32 = num::cast(0x14); - * assert!(twenty == 20f32); + * assert_eq!(twenty, 20f32); * ~~~ */ #[inline(always)] @@ -196,17 +196,17 @@ pub fn pow_with_uint+Mul>( #[cfg(test)] fn test_num(ten: T, two: T) { - assert!(ten.add(&two) == cast(12)); - assert!(ten.sub(&two) == cast(8)); - assert!(ten.mul(&two) == cast(20)); - assert!(ten.div(&two) == cast(5)); - assert!(ten.modulo(&two) == cast(0)); - - assert!(ten.add(&two) == ten + two); - assert!(ten.sub(&two) == ten - two); - assert!(ten.mul(&two) == ten * two); - assert!(ten.div(&two) == ten / two); - assert!(ten.modulo(&two) == ten % two); + assert_eq!(ten.add(&two), cast(12)); + assert_eq!(ten.sub(&two), cast(8)); + assert_eq!(ten.mul(&two), cast(20)); + assert_eq!(ten.div(&two), cast(5)); + assert_eq!(ten.modulo(&two), cast(0)); + + assert_eq!(ten.add(&two), ten + two); + assert_eq!(ten.sub(&two), ten - two); + assert_eq!(ten.mul(&two), ten * two); + assert_eq!(ten.div(&two), ten / two); + assert_eq!(ten.modulo(&two), ten % two); } #[test] fn test_u8_num() { test_num(10u8, 2u8) } @@ -227,47 +227,47 @@ macro_rules! test_cast_20( ($_20:expr) => ({ let _20 = $_20; - assert!(20u == _20.to_uint()); - assert!(20u8 == _20.to_u8()); - assert!(20u16 == _20.to_u16()); - assert!(20u32 == _20.to_u32()); - assert!(20u64 == _20.to_u64()); - assert!(20i == _20.to_int()); - assert!(20i8 == _20.to_i8()); - assert!(20i16 == _20.to_i16()); - assert!(20i32 == _20.to_i32()); - assert!(20i64 == _20.to_i64()); - assert!(20f == _20.to_float()); - assert!(20f32 == _20.to_f32()); - assert!(20f64 == _20.to_f64()); - - assert!(_20 == NumCast::from(20u)); - assert!(_20 == NumCast::from(20u8)); - assert!(_20 == NumCast::from(20u16)); - assert!(_20 == NumCast::from(20u32)); - assert!(_20 == NumCast::from(20u64)); - assert!(_20 == NumCast::from(20i)); - assert!(_20 == NumCast::from(20i8)); - assert!(_20 == NumCast::from(20i16)); - assert!(_20 == NumCast::from(20i32)); - assert!(_20 == NumCast::from(20i64)); - assert!(_20 == NumCast::from(20f)); - assert!(_20 == NumCast::from(20f32)); - assert!(_20 == NumCast::from(20f64)); - - assert!(_20 == cast(20u)); - assert!(_20 == cast(20u8)); - assert!(_20 == cast(20u16)); - assert!(_20 == cast(20u32)); - assert!(_20 == cast(20u64)); - assert!(_20 == cast(20i)); - assert!(_20 == cast(20i8)); - assert!(_20 == cast(20i16)); - assert!(_20 == cast(20i32)); - assert!(_20 == cast(20i64)); - assert!(_20 == cast(20f)); - assert!(_20 == cast(20f32)); - assert!(_20 == cast(20f64)); + assert_eq!(20u, _20.to_uint()); + assert_eq!(20u8, _20.to_u8()); + assert_eq!(20u16, _20.to_u16()); + assert_eq!(20u32, _20.to_u32()); + assert_eq!(20u64, _20.to_u64()); + assert_eq!(20i, _20.to_int()); + assert_eq!(20i8, _20.to_i8()); + assert_eq!(20i16, _20.to_i16()); + assert_eq!(20i32, _20.to_i32()); + assert_eq!(20i64, _20.to_i64()); + assert_eq!(20f, _20.to_float()); + assert_eq!(20f32, _20.to_f32()); + assert_eq!(20f64, _20.to_f64()); + + assert_eq!(_20, NumCast::from(20u)); + assert_eq!(_20, NumCast::from(20u8)); + assert_eq!(_20, NumCast::from(20u16)); + assert_eq!(_20, NumCast::from(20u32)); + assert_eq!(_20, NumCast::from(20u64)); + assert_eq!(_20, NumCast::from(20i)); + assert_eq!(_20, NumCast::from(20i8)); + assert_eq!(_20, NumCast::from(20i16)); + assert_eq!(_20, NumCast::from(20i32)); + assert_eq!(_20, NumCast::from(20i64)); + assert_eq!(_20, NumCast::from(20f)); + assert_eq!(_20, NumCast::from(20f32)); + assert_eq!(_20, NumCast::from(20f64)); + + assert_eq!(_20, cast(20u)); + assert_eq!(_20, cast(20u8)); + assert_eq!(_20, cast(20u16)); + assert_eq!(_20, cast(20u32)); + assert_eq!(_20, cast(20u64)); + assert_eq!(_20, cast(20i)); + assert_eq!(_20, cast(20i8)); + assert_eq!(_20, cast(20i16)); + assert_eq!(_20, cast(20i32)); + assert_eq!(_20, cast(20i64)); + assert_eq!(_20, cast(20f)); + assert_eq!(_20, cast(20f32)); + assert_eq!(_20, cast(20f64)); }) ) diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index b49ec65a95bbf..0109c915c6014 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -287,32 +287,32 @@ mod tests { #[test] fn test_bitwise_ops() { - assert!(0b1110 as T == (0b1100 as T).bitor(&(0b1010 as T))); - assert!(0b1000 as T == (0b1100 as T).bitand(&(0b1010 as T))); - assert!(0b0110 as T == (0b1100 as T).bitxor(&(0b1010 as T))); - assert!(0b1110 as T == (0b0111 as T).shl(&(1 as T))); - assert!(0b0111 as T == (0b1110 as T).shr(&(1 as T))); - assert!(max_value - (0b1011 as T) == (0b1011 as T).not()); + assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); + assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T))); + assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T))); + assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T))); + assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T))); + assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not()); } #[test] pub fn test_to_str() { - assert!(to_str_radix(0 as T, 10u) == ~"0"); - assert!(to_str_radix(1 as T, 10u) == ~"1"); - assert!(to_str_radix(2 as T, 10u) == ~"2"); - assert!(to_str_radix(11 as T, 10u) == ~"11"); - assert!(to_str_radix(11 as T, 16u) == ~"b"); - assert!(to_str_radix(255 as T, 16u) == ~"ff"); - assert!(to_str_radix(0xff as T, 10u) == ~"255"); + assert_eq!(to_str_radix(0 as T, 10u), ~"0"); + assert_eq!(to_str_radix(1 as T, 10u), ~"1"); + assert_eq!(to_str_radix(2 as T, 10u), ~"2"); + assert_eq!(to_str_radix(11 as T, 10u), ~"11"); + assert_eq!(to_str_radix(11 as T, 16u), ~"b"); + assert_eq!(to_str_radix(255 as T, 16u), ~"ff"); + assert_eq!(to_str_radix(0xff as T, 10u), ~"255"); } #[test] pub fn test_from_str() { - assert!(from_str(~"0") == Some(0u as T)); - assert!(from_str(~"3") == Some(3u as T)); - assert!(from_str(~"10") == Some(10u as T)); - assert!(u32::from_str(~"123456789") == Some(123456789 as u32)); - assert!(from_str(~"00100") == Some(100u as T)); + assert_eq!(from_str(~"0"), Some(0u as T)); + assert_eq!(from_str(~"3"), Some(3u as T)); + assert_eq!(from_str(~"10"), Some(10u as T)); + assert_eq!(u32::from_str(~"123456789"), Some(123456789 as u32)); + assert_eq!(from_str(~"00100"), Some(100u as T)); assert!(from_str(~"").is_none()); assert!(from_str(~" ").is_none()); @@ -322,14 +322,12 @@ mod tests { #[test] pub fn test_parse_bytes() { use str::to_bytes; - assert!(parse_bytes(to_bytes(~"123"), 10u) == Some(123u as T)); - assert!(parse_bytes(to_bytes(~"1001"), 2u) == Some(9u as T)); - assert!(parse_bytes(to_bytes(~"123"), 8u) == Some(83u as T)); - assert!(u16::parse_bytes(to_bytes(~"123"), 16u) == - Some(291u as u16)); - assert!(u16::parse_bytes(to_bytes(~"ffff"), 16u) == - Some(65535u as u16)); - assert!(parse_bytes(to_bytes(~"z"), 36u) == Some(35u as T)); + assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123u as T)); + assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9u as T)); + assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83u as T)); + assert_eq!(u16::parse_bytes(to_bytes(~"123"), 16u), Some(291u as u16)); + assert_eq!(u16::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535u as u16)); + assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35u as T)); assert!(parse_bytes(to_bytes(~"Z"), 10u).is_none()); assert!(parse_bytes(to_bytes(~"_"), 2u).is_none()); @@ -338,63 +336,63 @@ mod tests { #[test] fn test_uint_to_str_overflow() { let mut u8_val: u8 = 255_u8; - assert!((u8::to_str(u8_val) == ~"255")); + assert_eq!(u8::to_str(u8_val), ~"255"); u8_val += 1 as u8; - assert!((u8::to_str(u8_val) == ~"0")); + assert_eq!(u8::to_str(u8_val), ~"0"); let mut u16_val: u16 = 65_535_u16; - assert!((u16::to_str(u16_val) == ~"65535")); + assert_eq!(u16::to_str(u16_val), ~"65535"); u16_val += 1 as u16; - assert!((u16::to_str(u16_val) == ~"0")); + assert_eq!(u16::to_str(u16_val), ~"0"); let mut u32_val: u32 = 4_294_967_295_u32; - assert!((u32::to_str(u32_val) == ~"4294967295")); + assert_eq!(u32::to_str(u32_val), ~"4294967295"); u32_val += 1 as u32; - assert!((u32::to_str(u32_val) == ~"0")); + assert_eq!(u32::to_str(u32_val), ~"0"); let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert!((u64::to_str(u64_val) == ~"18446744073709551615")); + assert_eq!(u64::to_str(u64_val), ~"18446744073709551615"); u64_val += 1 as u64; - assert!((u64::to_str(u64_val) == ~"0")); + assert_eq!(u64::to_str(u64_val), ~"0"); } #[test] fn test_uint_from_str_overflow() { let mut u8_val: u8 = 255_u8; - assert!((u8::from_str(~"255") == Some(u8_val))); - assert!((u8::from_str(~"256").is_none())); + assert_eq!(u8::from_str(~"255"), Some(u8_val)); + assert!(u8::from_str(~"256").is_none()); u8_val += 1 as u8; - assert!((u8::from_str(~"0") == Some(u8_val))); - assert!((u8::from_str(~"-1").is_none())); + assert_eq!(u8::from_str(~"0"), Some(u8_val)); + assert!(u8::from_str(~"-1").is_none()); let mut u16_val: u16 = 65_535_u16; - assert!((u16::from_str(~"65535") == Some(u16_val))); - assert!((u16::from_str(~"65536").is_none())); + assert_eq!(u16::from_str(~"65535"), Some(u16_val)); + assert!(u16::from_str(~"65536").is_none()); u16_val += 1 as u16; - assert!((u16::from_str(~"0") == Some(u16_val))); - assert!((u16::from_str(~"-1").is_none())); + assert_eq!(u16::from_str(~"0"), Some(u16_val)); + assert!(u16::from_str(~"-1").is_none()); let mut u32_val: u32 = 4_294_967_295_u32; - assert!((u32::from_str(~"4294967295") == Some(u32_val))); - assert!((u32::from_str(~"4294967296").is_none())); + assert_eq!(u32::from_str(~"4294967295"), Some(u32_val)); + assert!(u32::from_str(~"4294967296").is_none()); u32_val += 1 as u32; - assert!((u32::from_str(~"0") == Some(u32_val))); - assert!((u32::from_str(~"-1").is_none())); + assert_eq!(u32::from_str(~"0"), Some(u32_val)); + assert!(u32::from_str(~"-1").is_none()); let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert!((u64::from_str(~"18446744073709551615") == Some(u64_val))); - assert!((u64::from_str(~"18446744073709551616").is_none())); + assert_eq!(u64::from_str(~"18446744073709551615"), Some(u64_val)); + assert!(u64::from_str(~"18446744073709551616").is_none()); u64_val += 1 as u64; - assert!((u64::from_str(~"0") == Some(u64_val))); - assert!((u64::from_str(~"-1").is_none())); + assert_eq!(u64::from_str(~"0"), Some(u64_val)); + assert!(u64::from_str(~"-1").is_none()); } #[test] From a523abd75c619be64cb8c0613431150e0913c934 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 18 Apr 2013 08:15:40 -0400 Subject: [PATCH 252/403] add dropwhile and takewhile iterators --- src/libcore/iterator.rs | 70 +++++++++++++++++++++++++++++++++++++++++ src/libcore/vec.rs | 38 ++++++++++++++++------ 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 8a9f2d3e99425..8bd6c73fc7dbb 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -22,6 +22,8 @@ pub trait IteratorUtil { // FIXME: #5898: should be called map fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; + fn dropwhile<'r>(self, predicate: &'r fn(&A) -> bool) -> DropWhileIterator<'r, A, Self>; + fn takewhile<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; fn enumerate(self) -> EnumerateIterator; fn advance(&mut self, f: &fn(A) -> bool); } @@ -48,6 +50,16 @@ impl> IteratorUtil for T { EnumerateIterator{iter: self, count: 0} } + #[inline(always)] + fn dropwhile<'r>(self, predicate: &'r fn(&A) -> bool) -> DropWhileIterator<'r, A, T> { + DropWhileIterator{iter: self, flag: false, predicate: predicate} + } + + #[inline(always)] + fn takewhile<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { + TakeWhileIterator{iter: self, flag: false, predicate: predicate} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) { @@ -129,3 +141,61 @@ impl> Iterator<(uint, A)> for EnumerateIterator { } } } + +pub struct DropWhileIterator<'self, A, T> { + priv iter: T, + priv flag: bool, + priv predicate: &'self fn(&A) -> bool +} + +impl<'self, A, T: Iterator> Iterator for DropWhileIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.flag { + next + } else { + loop { + match next { + Some(x) => { + if (self.predicate)(&x) { + next = self.iter.next(); + loop + } else { + self.flag = true; + return Some(x) + } + } + None => return None + } + } + } + } +} + +pub struct TakeWhileIterator<'self, A, T> { + priv iter: T, + priv flag: bool, + priv predicate: &'self fn(&A) -> bool +} + +impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + None + } else { + match self.iter.next() { + Some(x) => { + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } + } + None => None + } + } + } +} diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index eebe6a7a37f32..45cc9618f59b0 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -4478,18 +4478,38 @@ mod tests { #[test] fn test_iterator_enumerate() { use iterator::*; - let xs = [0u,1,2,3,4,5]; + let xs = [0u, 1, 2, 3, 4, 5]; let mut it = xs.iter().enumerate(); for it.advance |(i, &x): (uint, &uint)| { assert_eq!(i, x); } } -} -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: + #[test] + fn test_iterator_takewhile() { + use iterator::*; + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5, 13]; + let mut it = xs.iter().takewhile(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_dropwhile() { + use iterator::*; + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let mut it = xs.iter().dropwhile(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } +} From 2686dcb98e7a48ea45fad3ea21e6406e26c97834 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 11:17:01 -0700 Subject: [PATCH 253/403] test: Add more comments about why extern-pass-TwoU64s is xfailed --- src/test/run-pass/extern-pass-TwoU64s.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index eb2e3b1158f1c..24dd3db8aca1c 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -11,7 +11,9 @@ // Test a foreign function that accepts and returns a struct // by value. -// xfail-fast This works standalone on windows but not with check-fast. don't know why +// xfail-fast This works standalone on windows but not with check-fast. +// possibly because there is another test that uses this extern fn but gives it +// a diferent signature #[deriving(Eq)] struct TwoU64s { From b18f12fb163af31f954c48a19a5375be3a1e675a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 11:17:34 -0700 Subject: [PATCH 254/403] test: xfail-macos some tests that don't work on mac i686 --- src/test/run-pass/extern-pass-TwoU32s.rs | 2 ++ src/test/run-pass/extern-return-TwoU16s.rs | 1 + src/test/run-pass/extern-return-TwoU32s.rs | 2 ++ src/test/run-pass/extern-return-TwoU8s.rs | 1 + 4 files changed, 6 insertions(+) diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index 16d14a96cfe4f..db040b8407a59 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -11,6 +11,8 @@ // Test a foreign function that accepts and returns a struct // by value. +// xfail-macos Broken on mac i686 + #[deriving(Eq)] struct TwoU32s { one: u32, two: u32 diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs index 0ea649a65b05f..f87b27e1f62d9 100644 --- a/src/test/run-pass/extern-return-TwoU16s.rs +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -9,6 +9,7 @@ // except according to those terms. // xfail-win32 #5745 +// xfail-macos Broken on mac i686 struct TwoU16s { one: u16, two: u16 diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs index 9e374687855b0..38e61ae6d49bd 100644 --- a/src/test/run-pass/extern-return-TwoU32s.rs +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-macos Broken on mac i686 + struct TwoU32s { one: u32, two: u32 } diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs index 9007d12a4514f..008e153769a64 100644 --- a/src/test/run-pass/extern-return-TwoU8s.rs +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -9,6 +9,7 @@ // except according to those terms. // xfail-win32 #5745 +// xfail-macos Broken on mac i686 struct TwoU8s { one: u8, two: u8 From ab08b4fbfde7e9cc9e0de07aed17b4d4e06ccc3e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 1 Apr 2013 18:17:16 -0700 Subject: [PATCH 255/403] core: Remove pipes::spawn_service, spawn_service_recv These are only used in test cases; pipes isn't the right place for them; they are unnecessary. Conflicts: src/libcore/rt/uv/mod.rs --- src/libcore/pipes.rs | 46 ------------------------- src/test/bench/pingpong.rs | 49 ++++++++++++++++++++++++++- src/test/run-pass/pipe-detect-term.rs | 10 +++--- src/test/run-pass/pipe-select.rs | 22 ++++++++++-- src/test/run-pass/pipe-sleep.rs | 30 ++++++++++++++-- 5 files changed, 102 insertions(+), 55 deletions(-) diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index fddb2af558709..fd50ecc5274a1 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -83,7 +83,6 @@ bounded and unbounded protocols allows for less code duplication. */ use cast::{forget, reinterpret_cast, transmute}; -use cell::Cell; use either::{Either, Left, Right}; use kinds::Owned; use libc; @@ -902,51 +901,6 @@ pub fn entangle() -> (SendPacket, RecvPacket) { (SendPacket(p), RecvPacket(p)) } -/** Spawn a task to provide a service. - -It takes an initialization function that produces a send and receive -endpoint. The send endpoint is returned to the caller and the receive -endpoint is passed to the new task. - -*/ -pub fn spawn_service( - init: extern fn() -> (SendPacketBuffered, - RecvPacketBuffered), - service: ~fn(v: RecvPacketBuffered)) - -> SendPacketBuffered { - let (client, server) = init(); - - // This is some nasty gymnastics required to safely move the pipe - // into a new task. - let server = Cell(server); - do task::spawn { - service(server.take()); - } - - client -} - -/** Like `spawn_service_recv`, but for protocols that start in the -receive state. - -*/ -pub fn spawn_service_recv( - init: extern fn() -> (RecvPacketBuffered, - SendPacketBuffered), - service: ~fn(v: SendPacketBuffered)) - -> RecvPacketBuffered { - let (client, server) = init(); - - // This is some nasty gymnastics required to safely move the pipe - // into a new task. - let server = Cell(server); - do task::spawn { - service(server.take()) - } - - client -} - pub mod rt { use option::{None, Option, Some}; diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index 731605e82bd1f..64fb9652ceae0 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -14,7 +14,8 @@ extern mod std; -use core::pipes::{spawn_service, recv}; +use core::cell::Cell; +use core::pipes::*; use std::time::precise_time_s; proto! pingpong ( @@ -70,6 +71,52 @@ macro_rules! follow ( ) ) + +/** Spawn a task to provide a service. + +It takes an initialization function that produces a send and receive +endpoint. The send endpoint is returned to the caller and the receive +endpoint is passed to the new task. + +*/ +pub fn spawn_service( + init: extern fn() -> (SendPacketBuffered, + RecvPacketBuffered), + service: ~fn(v: RecvPacketBuffered)) + -> SendPacketBuffered { + let (client, server) = init(); + + // This is some nasty gymnastics required to safely move the pipe + // into a new task. + let server = Cell(server); + do task::spawn { + service(server.take()); + } + + client +} + +/** Like `spawn_service_recv`, but for protocols that start in the +receive state. + +*/ +pub fn spawn_service_recv( + init: extern fn() -> (RecvPacketBuffered, + SendPacketBuffered), + service: ~fn(v: SendPacketBuffered)) + -> RecvPacketBuffered { + let (client, server) = init(); + + // This is some nasty gymnastics required to safely move the pipe + // into a new task. + let server = Cell(server); + do task::spawn { + service(server.take()) + } + + client +} + fn switch(+endp: core::pipes::RecvPacketBuffered, f: &fn(+v: Option) -> U) -> U { f(core::pipes::try_recv(endp)) diff --git a/src/test/run-pass/pipe-detect-term.rs b/src/test/run-pass/pipe-detect-term.rs index 6afa9e29349f3..bd0ffa6459067 100644 --- a/src/test/run-pass/pipe-detect-term.rs +++ b/src/test/run-pass/pipe-detect-term.rs @@ -18,7 +18,7 @@ extern mod std; use std::timer::sleep; use std::uv; -use core::pipes; +use core::cell::Cell; use core::pipes::{try_recv, recv}; proto! oneshot ( @@ -30,12 +30,14 @@ proto! oneshot ( pub fn main() { let iotask = &uv::global_loop::get(); - pipes::spawn_service(oneshot::init, |p| { - match try_recv(p) { + let (chan, port) = oneshot::init(); + let port = Cell(port); + do spawn { + match try_recv(port.take()) { Some(*) => { fail!() } None => { } } - }); + } sleep(iotask, 100); diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 221ecbfcf02e5..12d60c9d6ab01 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -17,8 +17,9 @@ extern mod std; use std::timer::sleep; use std::uv; +use core::cell::Cell; use core::pipes; -use core::pipes::{recv, select}; +use core::pipes::*; proto! oneshot ( waiting:send { @@ -32,13 +33,30 @@ proto! stream ( } ) +pub fn spawn_service( + init: extern fn() -> (SendPacketBuffered, + RecvPacketBuffered), + service: ~fn(v: RecvPacketBuffered)) + -> SendPacketBuffered { + let (client, server) = init(); + + // This is some nasty gymnastics required to safely move the pipe + // into a new task. + let server = Cell(server); + do task::spawn { + service(server.take()); + } + + client +} + pub fn main() { use oneshot::client::*; use stream::client::*; let iotask = &uv::global_loop::get(); - let c = pipes::spawn_service(stream::init, |p| { + let c = spawn_service(stream::init, |p| { error!("waiting for pipes"); let stream::send(x, p) = recv(p); error!("got pipes"); diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs index 57d72edd0a46a..86ffc96e89aec 100644 --- a/src/test/run-pass/pipe-sleep.rs +++ b/src/test/run-pass/pipe-sleep.rs @@ -13,8 +13,9 @@ extern mod std; use std::timer::sleep; use std::uv; +use core::cell::Cell; use core::pipes; -use core::pipes::recv; +use core::pipes::*; proto! oneshot ( waiting:send { @@ -22,10 +23,35 @@ proto! oneshot ( } ) + +/** Spawn a task to provide a service. + +It takes an initialization function that produces a send and receive +endpoint. The send endpoint is returned to the caller and the receive +endpoint is passed to the new task. + +*/ +pub fn spawn_service( + init: extern fn() -> (SendPacketBuffered, + RecvPacketBuffered), + service: ~fn(v: RecvPacketBuffered)) + -> SendPacketBuffered { + let (client, server) = init(); + + // This is some nasty gymnastics required to safely move the pipe + // into a new task. + let server = Cell(server); + do task::spawn { + service(server.take()); + } + + client +} + pub fn main() { use oneshot::client::*; - let c = pipes::spawn_service(oneshot::init, |p| { recv(p); }); + let c = spawn_service(oneshot::init, |p| { recv(p); }); let iotask = &uv::global_loop::get(); sleep(iotask, 500); From 8f2d21dc0d69de134e0ed70bcf1a15f4cac4973a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 1 Apr 2013 18:25:20 -0700 Subject: [PATCH 256/403] core: Just reordering some code --- src/libcore/pipes.rs | 162 +++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index fd50ecc5274a1..ba94c2ae66a23 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -669,87 +669,6 @@ pub fn wait_many(pkts: &[T]) -> uint { ready_packet } -/** Receives a message from one of two endpoints. - -The return value is `left` if the first endpoint received something, -or `right` if the second endpoint receives something. In each case, -the result includes the other endpoint as well so it can be used -again. Below is an example of using `select2`. - -~~~ -match select2(a, b) { - left((none, b)) { - // endpoint a was closed. - } - right((a, none)) { - // endpoint b was closed. - } - left((Some(_), b)) { - // endpoint a received a message - } - right(a, Some(_)) { - // endpoint b received a message. - } -} -~~~ - -Sometimes messages will be available on both endpoints at once. In -this case, `select2` may return either `left` or `right`. - -*/ -pub fn select2( - a: RecvPacketBuffered, - b: RecvPacketBuffered) - -> Either<(Option, RecvPacketBuffered), - (RecvPacketBuffered, Option)> -{ - let i = wait_many([a.header(), b.header()]); - - match i { - 0 => Left((try_recv(a), b)), - 1 => Right((a, try_recv(b))), - _ => fail!(~"select2 return an invalid packet") - } -} - -#[doc(hidden)] -pub trait Selectable { - fn header(&self) -> *PacketHeader; -} - -impl Selectable for *PacketHeader { - fn header(&self) -> *PacketHeader { *self } -} - -/// Returns the index of an endpoint that is ready to receive. -pub fn selecti(endpoints: &[T]) -> uint { - wait_many(endpoints) -} - -/// Returns 0 or 1 depending on which endpoint is ready to receive -pub fn select2i(a: &A, b: &B) -> - Either<(), ()> { - match wait_many([a.header(), b.header()]) { - 0 => Left(()), - 1 => Right(()), - _ => fail!(~"wait returned unexpected index") - } -} - -/** Waits on a set of endpoints. Returns a message, its index, and a - list of the remaining endpoints. - -*/ -pub fn select(endpoints: ~[RecvPacketBuffered]) - -> (uint, Option, ~[RecvPacketBuffered]) -{ - let ready = wait_many(endpoints.map(|p| p.header())); - let mut remaining = endpoints; - let port = remaining.swap_remove(ready); - let result = try_recv(port); - (ready, result, remaining) -} - /** The sending end of a pipe. It can be used to send exactly one message. @@ -901,6 +820,87 @@ pub fn entangle() -> (SendPacket, RecvPacket) { (SendPacket(p), RecvPacket(p)) } +/** Receives a message from one of two endpoints. + +The return value is `left` if the first endpoint received something, +or `right` if the second endpoint receives something. In each case, +the result includes the other endpoint as well so it can be used +again. Below is an example of using `select2`. + +~~~ +match select2(a, b) { + left((none, b)) { + // endpoint a was closed. + } + right((a, none)) { + // endpoint b was closed. + } + left((Some(_), b)) { + // endpoint a received a message + } + right(a, Some(_)) { + // endpoint b received a message. + } +} +~~~ + +Sometimes messages will be available on both endpoints at once. In +this case, `select2` may return either `left` or `right`. + +*/ +pub fn select2( + a: RecvPacketBuffered, + b: RecvPacketBuffered) + -> Either<(Option, RecvPacketBuffered), + (RecvPacketBuffered, Option)> +{ + let i = wait_many([a.header(), b.header()]); + + match i { + 0 => Left((try_recv(a), b)), + 1 => Right((a, try_recv(b))), + _ => fail!(~"select2 return an invalid packet") + } +} + +#[doc(hidden)] +pub trait Selectable { + fn header(&self) -> *PacketHeader; +} + +impl Selectable for *PacketHeader { + fn header(&self) -> *PacketHeader { *self } +} + +/// Returns the index of an endpoint that is ready to receive. +pub fn selecti(endpoints: &[T]) -> uint { + wait_many(endpoints) +} + +/// Returns 0 or 1 depending on which endpoint is ready to receive +pub fn select2i(a: &A, b: &B) -> + Either<(), ()> { + match wait_many([a.header(), b.header()]) { + 0 => Left(()), + 1 => Right(()), + _ => fail!(~"wait returned unexpected index") + } +} + +/** Waits on a set of endpoints. Returns a message, its index, and a + list of the remaining endpoints. + +*/ +pub fn select(endpoints: ~[RecvPacketBuffered]) + -> (uint, Option, ~[RecvPacketBuffered]) +{ + let ready = wait_many(endpoints.map(|p| p.header())); + let mut remaining = endpoints; + let port = remaining.swap_remove(ready); + let result = try_recv(port); + (ready, result, remaining) +} + pub mod rt { use option::{None, Option, Some}; From 3dce936753b90dcf80f25251034ccee7afd8ea71 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 1 Apr 2013 19:04:46 -0700 Subject: [PATCH 257/403] core: Remove #[doc(hidden)] attributes and atomic wrapper functions from pipes Neither are needed --- src/libcore/pipes.rs | 50 ++------------------------------------------ 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index ba94c2ae66a23..36cfdbf5617aa 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -92,14 +92,12 @@ use ptr; use task; use vec; -#[doc(hidden)] static SPIN_COUNT: uint = 0; macro_rules! move_it ( { $x:expr } => ( unsafe { let y = *ptr::addr_of(&($x)); y } ) ) -#[doc(hidden)] #[deriving(Eq)] enum State { Empty, @@ -124,7 +122,6 @@ pub fn BufferHeader() -> BufferHeader { } // This is for protocols to associate extra data to thread around. -#[doc(hidden)] pub struct Buffer { header: BufferHeader, data: T, @@ -185,13 +182,11 @@ pub impl PacketHeader { } } -#[doc(hidden)] pub struct Packet { header: PacketHeader, mut payload: Option, } -#[doc(hidden)] pub trait HasBuffer { fn set_buffer(&self, b: *libc::c_void); } @@ -202,14 +197,12 @@ impl HasBuffer for Packet { } } -#[doc(hidden)] pub fn mk_packet() -> Packet { Packet { header: PacketHeader(), payload: None, } } -#[doc(hidden)] fn unibuffer() -> ~Buffer> { let b = ~Buffer { header: BufferHeader(), @@ -225,7 +218,6 @@ fn unibuffer() -> ~Buffer> { b } -#[doc(hidden)] pub fn packet() -> *Packet { let b = unibuffer(); let p = ptr::addr_of(&(b.data)); @@ -234,7 +226,6 @@ pub fn packet() -> *Packet { p } -#[doc(hidden)] pub fn entangle_buffer( buffer: ~Buffer, init: &fn(*libc::c_void, x: &T) -> *Packet) @@ -245,30 +236,6 @@ pub fn entangle_buffer( (SendPacketBuffered(p), RecvPacketBuffered(p)) } -// If I call the rusti versions directly from a polymorphic function, -// I get link errors. This is a bug that needs investigated more. -#[doc(hidden)] -pub fn atomic_xchng_rel(dst: &mut int, src: int) -> int { - unsafe { - intrinsics::atomic_xchg_rel(dst, src) - } -} - -#[doc(hidden)] -pub fn atomic_add_acq(dst: &mut int, src: int) -> int { - unsafe { - intrinsics::atomic_xadd_acq(dst, src) - } -} - -#[doc(hidden)] -pub fn atomic_sub_rel(dst: &mut int, src: int) -> int { - unsafe { - intrinsics::atomic_xsub_rel(dst, src) - } -} - -#[doc(hidden)] pub fn swap_task(dst: &mut *rust_task, src: *rust_task) -> *rust_task { // It might be worth making both acquire and release versions of // this. @@ -277,11 +244,9 @@ pub fn swap_task(dst: &mut *rust_task, src: *rust_task) -> *rust_task { } } -#[doc(hidden)] #[allow(non_camel_case_types)] pub type rust_task = libc::c_void; -#[doc(hidden)] pub mod rustrt { use libc; use super::rust_task; @@ -303,7 +268,6 @@ pub mod rustrt { } } -#[doc(hidden)] fn wait_event(this: *rust_task) -> *libc::c_void { unsafe { let mut event = ptr::null(); @@ -316,21 +280,18 @@ fn wait_event(this: *rust_task) -> *libc::c_void { } } -#[doc(hidden)] fn swap_state_acq(dst: &mut State, src: State) -> State { unsafe { transmute(intrinsics::atomic_xchg_acq(transmute(dst), src as int)) } } -#[doc(hidden)] fn swap_state_rel(dst: &mut State, src: State) -> State { unsafe { transmute(intrinsics::atomic_xchg_rel(transmute(dst), src as int)) } } -#[doc(hidden)] pub unsafe fn get_buffer(p: *PacketHeader) -> ~Buffer { transmute((*p).buf_header()) } @@ -348,7 +309,7 @@ impl ::ops::Drop for BufferResource { let b = move_it!(self.buffer); //let p = ptr::addr_of(*b); //error!("drop %?", p); - let old_count = atomic_sub_rel(&mut b.header.ref_count, 1); + let old_count = intrinsics::atomic_xsub_rel(&mut b.header.ref_count, 1); //let old_count = atomic_xchng_rel(b.header.ref_count, 0); if old_count == 1 { // The new count is 0. @@ -365,7 +326,7 @@ impl ::ops::Drop for BufferResource { fn BufferResource(b: ~Buffer) -> BufferResource { //let p = ptr::addr_of(*b); //error!("take %?", p); - atomic_add_acq(&mut b.header.ref_count, 1); + unsafe { intrinsics::atomic_xadd_acq(&mut b.header.ref_count, 1) }; BufferResource { // tjc: ???? @@ -373,7 +334,6 @@ fn BufferResource(b: ~Buffer) -> BufferResource { } } -#[doc(hidden)] pub fn send(p: SendPacketBuffered, payload: T) -> bool { let header = p.header(); let p_ = p.unwrap(); @@ -550,7 +510,6 @@ pub fn peek(p: &RecvPacketBuffered) -> bool { } } -#[doc(hidden)] fn sender_terminate(p: *Packet) { let p = unsafe { &*p }; match swap_state_rel(&mut p.header.state, Terminated) { @@ -581,7 +540,6 @@ fn sender_terminate(p: *Packet) { } } -#[doc(hidden)] fn receiver_terminate(p: *Packet) { let p = unsafe { &*p }; match swap_state_rel(&mut p.header.state, Terminated) { @@ -675,7 +633,6 @@ message. */ pub type SendPacket = SendPacketBuffered>; -#[doc(hidden)] pub fn SendPacket(p: *Packet) -> SendPacket { SendPacketBuffered(p) } @@ -746,7 +703,6 @@ pub impl SendPacketBuffered { /// message. pub type RecvPacket = RecvPacketBuffered>; -#[doc(hidden)] pub fn RecvPacket(p: *Packet) -> RecvPacket { RecvPacketBuffered(p) } @@ -814,7 +770,6 @@ pub fn RecvPacketBuffered(p: *Packet) } } -#[doc(hidden)] pub fn entangle() -> (SendPacket, RecvPacket) { let p = packet(); (SendPacket(p), RecvPacket(p)) @@ -863,7 +818,6 @@ pub fn select2( } } -#[doc(hidden)] pub trait Selectable { fn header(&self) -> *PacketHeader; } From 056164ac1946898cb46ec075f1bd4c15dfbeff30 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 19:45:46 -0700 Subject: [PATCH 258/403] core: Inline the protocol definitions of sendp and oneshot I want to be able to see what is going on --- src/libcore/comm.rs | 132 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 4 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index f8b046e5b8c4f..b4d5a4f240d7f 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -73,11 +73,64 @@ pub fn select2i(a: &A, b: &B) -> // Streams - Make pipes a little easier in general. -proto! streamp ( +/*proto! streamp ( Open:send { data(T) -> Open } -) +)*/ + +#[allow(non_camel_case_types)] +pub mod streamp { + priv use core::kinds::Owned; + + pub fn init() -> (client::Open, server::Open) { + pub use core::pipes::HasBuffer; + ::core::pipes::entangle() + } + + #[allow(non_camel_case_types)] + pub enum Open { pub data(T, server::Open), } + + #[allow(non_camel_case_types)] + pub mod client { + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub fn try_data(pipe: Open, x_0: T) -> + ::core::option::Option> { + { + use super::data; + let (c, s) = ::core::pipes::entangle(); + let message = data(x_0, s); + if ::core::pipes::send(pipe, message) { + ::core::pipes::rt::make_some(c) + } else { ::core::pipes::rt::make_none() } + } + } + + #[allow(non_camel_case_types)] + pub fn data(pipe: Open, x_0: T) -> Open { + { + use super::data; + let (c, s) = ::core::pipes::entangle(); + let message = data(x_0, s); + ::core::pipes::send(pipe, message); + c + } + } + + #[allow(non_camel_case_types)] + pub type Open = ::core::pipes::SendPacket>; + } + + #[allow(non_camel_case_types)] + pub mod server { + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub type Open = ::core::pipes::RecvPacket>; + } +} #[doc(hidden)] struct Chan_ { @@ -364,11 +417,82 @@ impl { send(T) -> ! } -) +)*/ + +#[allow(non_camel_case_types)] +pub mod oneshot { + priv use core::kinds::Owned; + + pub fn init() -> (client::Oneshot, server::Oneshot) { + pub use core::pipes::HasBuffer; + + let buffer = + ~::core::pipes::Buffer{ + header: ::core::pipes::BufferHeader(), + data: __Buffer{ + Oneshot: ::core::pipes::mk_packet::>() + }, + }; + do ::core::pipes::entangle_buffer(buffer) |buffer, data| { + { + data.Oneshot.set_buffer(buffer); + ::ptr::addr_of(&(data.Oneshot)) + } + } + } + #[allow(non_camel_case_types)] + pub enum Oneshot { pub send(T), } + #[allow(non_camel_case_types)] + pub struct __Buffer { + Oneshot: ::core::pipes::Packet>, + } + + #[allow(non_camel_case_types)] + pub mod client { + + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub fn try_send(pipe: Oneshot, x_0: T) -> + ::core::option::Option<()> { + { + use super::send; + let message = send(x_0); + if ::core::pipes::send(pipe, message) { + ::core::pipes::rt::make_some(()) + } else { ::core::pipes::rt::make_none() } + } + } + + #[allow(non_camel_case_types)] + pub fn send(pipe: Oneshot, x_0: T) { + { + use super::send; + let message = send(x_0); + ::core::pipes::send(pipe, message); + } + } + + #[allow(non_camel_case_types)] + pub type Oneshot = + ::core::pipes::SendPacketBuffered, + super::__Buffer>; + } + + #[allow(non_camel_case_types)] + pub mod server { + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub type Oneshot = + ::core::pipes::RecvPacketBuffered, + super::__Buffer>; + } +} /// The send end of a oneshot pipe. pub type ChanOne = oneshot::client::Oneshot; From 4e22461cd8b3aaa1876f0579615b9afe037f7195 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 19:47:05 -0700 Subject: [PATCH 259/403] core: Remove a stray #[doc(hidden)] attribute --- src/libcore/comm.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index b4d5a4f240d7f..f5e87d314eae9 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -132,7 +132,6 @@ pub mod streamp { } } -#[doc(hidden)] struct Chan_ { mut endp: Option> } From 0617d580e6cfafb1fc662cfb9c9a3c23829fe2ae Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 19:50:20 -0700 Subject: [PATCH 260/403] core::comm: Remove functions in favor of methods `send`, etc. are never used. I've left the functions for oneshot pipes because by-value methods don't work. --- src/libcore/comm.rs | 256 +++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 159 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index f5e87d314eae9..fe6dbddc75e4d 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -132,25 +132,17 @@ pub mod streamp { } } -struct Chan_ { - mut endp: Option> -} - /// An endpoint that can send many messages. -pub enum Chan { - Chan_(Chan_) -} - -struct Port_ { - mut endp: Option>, +pub struct Chan { + mut endp: Option> } /// An endpoint that can receive many messages. -pub enum Port { - Port_(Port_) +pub struct Port { + mut endp: Option>, } -/** Creates a `(chan, port)` pair. +/** Creates a `(Port, Chan)` pair. These allow sending or receiving an unlimited number of messages. @@ -158,96 +150,70 @@ These allow sending or receiving an unlimited number of messages. pub fn stream() -> (Port, Chan) { let (c, s) = streamp::init(); - (Port_(Port_ { endp: Some(s) }), Chan_(Chan_{ endp: Some(c) })) -} - -// Add an inherent method so that imports of GenericChan are not -// required. -pub impl Chan { - fn send(&self, x: T) { chan_send(self, x) } - fn try_send(&self, x: T) -> bool { chan_try_send(self, x) } + (Port { endp: Some(s) }, Chan { endp: Some(c) }) } impl GenericChan for Chan { - fn send(&self, x: T) { chan_send(self, x) } -} - -#[inline(always)] -fn chan_send(self: &Chan, x: T) { - let mut endp = None; - endp <-> self.endp; - self.endp = Some( - streamp::client::data(endp.unwrap(), x)) + #[inline(always)] + fn send(&self, x: T) { + let mut endp = None; + endp <-> self.endp; + self.endp = Some( + streamp::client::data(endp.unwrap(), x)) + } } impl GenericSmartChan for Chan { + #[inline(always)] fn try_send(&self, x: T) -> bool { - chan_try_send(self, x) - } -} - -#[inline(always)] -fn chan_try_send(self: &Chan, x: T) -> bool { - let mut endp = None; - endp <-> self.endp; - match streamp::client::try_data(endp.unwrap(), x) { - Some(next) => { - self.endp = Some(next); - true + let mut endp = None; + endp <-> self.endp; + match streamp::client::try_data(endp.unwrap(), x) { + Some(next) => { + self.endp = Some(next); + true + } + None => false } - None => false } } -// Use an inherent impl so that imports are not required: -pub impl Port { - fn recv(&self) -> T { port_recv(self) } - fn try_recv(&self) -> Option { port_try_recv(self) } - fn peek(&self) -> bool { port_peek(self) } -} - impl GenericPort for Port { - // These two calls will prefer the inherent versions above: - fn recv(&self) -> T { port_recv(self) } - fn try_recv(&self) -> Option { port_try_recv(self) } -} - -#[inline(always)] -fn port_recv(self: &Port) -> T { - let mut endp = None; - endp <-> self.endp; - let streamp::data(x, endp) = recv(endp.unwrap()); - self.endp = Some(endp); - x -} - -#[inline(always)] -fn port_try_recv(self: &Port) -> Option { - let mut endp = None; - endp <-> self.endp; - match try_recv(endp.unwrap()) { - Some(streamp::data(x, endp)) => { - self.endp = Some(endp); - Some(x) + #[inline(always)] + fn recv(&self) -> T { + let mut endp = None; + endp <-> self.endp; + let streamp::data(x, endp) = recv(endp.unwrap()); + self.endp = Some(endp); + x + } + + #[inline(always)] + fn try_recv(&self) -> Option { + let mut endp = None; + endp <-> self.endp; + match try_recv(endp.unwrap()) { + Some(streamp::data(x, endp)) => { + self.endp = Some(endp); + Some(x) + } + None => None } - None => None } } impl Peekable for Port { - fn peek(&self) -> bool { port_peek(self) } -} - -#[inline(always)] -fn port_peek(self: &Port) -> bool { - let mut endp = None; - endp <-> self.endp; - let peek = match &endp { - &Some(ref endp) => peek(endp), - &None => fail!(~"peeking empty stream") - }; - self.endp <-> endp; - peek + #[inline(always)] + fn peek(&self) -> bool { + let mut endp = None; + endp <-> self.endp; + let peek = match &endp { + &Some(ref endp) => peek(endp), + &None => fail!(~"peeking empty stream") + }; + self.endp <-> endp; + peek + } } impl Selectable for Port { @@ -272,13 +238,6 @@ pub fn PortSet() -> PortSet{ } } -// Use an inherent impl so that imports are not required: -pub impl PortSet { - fn recv(&self) -> T { port_set_recv(self) } - fn try_recv(&self) -> Option { port_set_try_recv(self) } - fn peek(&self) -> bool { port_set_peek(self) } -} - pub impl PortSet { fn add(&self, port: Port) { self.ports.push(port) @@ -292,90 +251,69 @@ pub impl PortSet { } impl GenericPort for PortSet { - fn try_recv(&self) -> Option { port_set_try_recv(self) } - fn recv(&self) -> T { port_set_recv(self) } -} - -#[inline(always)] -fn port_set_recv(self: &PortSet) -> T { - port_set_try_recv(self).expect("port_set: endpoints closed") -} - -#[inline(always)] -fn port_set_try_recv(self: &PortSet) -> Option { - let mut result = None; - // we have to swap the ports array so we aren't borrowing - // aliasable mutable memory. - let mut ports = ~[]; - ports <-> self.ports; - while result.is_none() && ports.len() > 0 { - let i = wait_many(ports); - match ports[i].try_recv() { - Some(m) => { - result = Some(m); - } - None => { - // Remove this port. - let _ = ports.swap_remove(i); + fn try_recv(&self) -> Option { + let mut result = None; + // we have to swap the ports array so we aren't borrowing + // aliasable mutable memory. + let mut ports = ~[]; + ports <-> self.ports; + while result.is_none() && ports.len() > 0 { + let i = wait_many(ports); + match ports[i].try_recv() { + Some(m) => { + result = Some(m); + } + None => { + // Remove this port. + let _ = ports.swap_remove(i); + } } } + ports <-> self.ports; + result + } + fn recv(&self) -> T { + self.try_recv().expect("port_set: endpoints closed") } - ports <-> self.ports; - result } impl Peekable for PortSet { - fn peek(&self) -> bool { port_set_peek(self) } -} - -#[inline(always)] -fn port_set_peek(self: &PortSet) -> bool { - // It'd be nice to use self.port.each, but that version isn't - // pure. - for uint::range(0, vec::uniq_len(&const self.ports)) |i| { - // XXX: Botch pending demuting. - unsafe { - let port: &Port = cast::transmute(&mut self.ports[i]); - if port.peek() { return true } + fn peek(&self) -> bool { + // It'd be nice to use self.port.each, but that version isn't + // pure. + for uint::range(0, vec::uniq_len(&const self.ports)) |i| { + // XXX: Botch pending demuting. + unsafe { + let port: &Port = cast::transmute(&mut self.ports[i]); + if port.peek() { return true } + } } + false } - false } - /// A channel that can be shared between many senders. pub type SharedChan = unstable::Exclusive>; -pub impl SharedChan { - fn send(&self, x: T) { shared_chan_send(self, x) } - fn try_send(&self, x: T) -> bool { shared_chan_try_send(self, x) } -} - impl GenericChan for SharedChan { - fn send(&self, x: T) { shared_chan_send(self, x) } -} - -#[inline(always)] -fn shared_chan_send(self: &SharedChan, x: T) { - let mut xx = Some(x); - do self.with_imm |chan| { - let mut x = None; - x <-> xx; - chan.send(x.unwrap()) + fn send(&self, x: T) { + let mut xx = Some(x); + do self.with_imm |chan| { + let mut x = None; + x <-> xx; + chan.send(x.unwrap()) + } } } impl GenericSmartChan for SharedChan { - fn try_send(&self, x: T) -> bool { shared_chan_try_send(self, x) } -} - -#[inline(always)] -fn shared_chan_try_send(self: &SharedChan, x: T) -> bool { - let mut xx = Some(x); - do self.with_imm |chan| { - let mut x = None; - x <-> xx; - chan.try_send(x.unwrap()) + fn try_send(&self, x: T) -> bool { + let mut xx = Some(x); + do self.with_imm |chan| { + let mut x = None; + x <-> xx; + chan.try_send(x.unwrap()) + } } } From bc60d84507ba4d492889c9b702318346b5784e5c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 22:57:35 -0700 Subject: [PATCH 261/403] core::pipes: Just reordering declarations --- src/libcore/comm.rs | 95 +++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index fe6dbddc75e4d..60ec4fbfddb30 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -56,20 +56,6 @@ pub trait Peekable { fn peek(&self) -> bool; } -/// Returns the index of an endpoint that is ready to receive. -pub fn selecti(endpoints: &[T]) -> uint { - wait_many(endpoints) -} - -/// Returns 0 or 1 depending on which endpoint is ready to receive -pub fn select2i(a: &A, b: &B) -> - Either<(), ()> { - match wait_many([a.header(), b.header()]) { - 0 => Left(()), - 1 => Right(()), - _ => fail!(~"wait returned unexpected index") - } -} // Streams - Make pipes a little easier in general. @@ -322,38 +308,6 @@ pub fn SharedChan(c: Chan) -> SharedChan { unstable::exclusive(c) } -/// Receive a message from one of two endpoints. -pub trait Select2 { - /// Receive a message or return `None` if a connection closes. - fn try_select(&self) -> Either, Option>; - /// Receive a message or fail if a connection closes. - fn select(&self) -> Either; -} - -impl, - Right: Selectable + GenericPort> - Select2 for (Left, Right) { - - fn select(&self) -> Either { - match *self { - (ref lp, ref rp) => match select2i(lp, rp) { - Left(()) => Left (lp.recv()), - Right(()) => Right(rp.recv()) - } - } - } - - fn try_select(&self) -> Either, Option> { - match *self { - (ref lp, ref rp) => match select2i(lp, rp) { - Left(()) => Left (lp.try_recv()), - Right(()) => Right(rp.try_recv()) - } - } - } -} - /*proto! oneshot ( Oneshot:send { send(T) -> ! @@ -486,6 +440,55 @@ pub fn try_send_one(chan: ChanOne, data: T) oneshot::client::try_send(chan, data).is_some() } + + +/// Returns the index of an endpoint that is ready to receive. +pub fn selecti(endpoints: &[T]) -> uint { + wait_many(endpoints) +} + +/// Returns 0 or 1 depending on which endpoint is ready to receive +pub fn select2i(a: &A, b: &B) -> + Either<(), ()> { + match wait_many([a.header(), b.header()]) { + 0 => Left(()), + 1 => Right(()), + _ => fail!(~"wait returned unexpected index") + } +} + +/// Receive a message from one of two endpoints. +pub trait Select2 { + /// Receive a message or return `None` if a connection closes. + fn try_select(&self) -> Either, Option>; + /// Receive a message or fail if a connection closes. + fn select(&self) -> Either; +} + +impl, + Right: Selectable + GenericPort> + Select2 for (Left, Right) { + + fn select(&self) -> Either { + match *self { + (ref lp, ref rp) => match select2i(lp, rp) { + Left(()) => Left (lp.recv()), + Right(()) => Right(rp.recv()) + } + } + } + + fn try_select(&self) -> Either, Option> { + match *self { + (ref lp, ref rp) => match select2i(lp, rp) { + Left(()) => Left (lp.try_recv()), + Right(()) => Right(rp.try_recv()) + } + } + } +} + #[cfg(test)] mod test { use either::Right; From decd3901d5d63013a98ecc481c441f3f793b5207 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Apr 2013 23:45:29 -0700 Subject: [PATCH 262/403] core::comm: Modernize constructors to use `new` --- doc/tutorial-tasks.md | 2 +- src/compiletest/procsrv.rs | 2 +- src/libcore/comm.rs | 34 +++++++++++++++------- src/libcore/run.rs | 2 +- src/libcore/task/mod.rs | 4 +-- src/libcore/unstable/weak_task.rs | 2 +- src/librustc/rustc.rc | 2 +- src/librustdoc/astsrv.rs | 2 +- src/librustdoc/markdown_writer.rs | 2 +- src/librustdoc/page_pass.rs | 2 +- src/libstd/arc.rs | 2 +- src/libstd/net_ip.rs | 2 +- src/libstd/net_tcp.rs | 30 +++++++++---------- src/libstd/test.rs | 10 +++---- src/libstd/timer.rs | 4 +-- src/libstd/uv_global_loop.rs | 2 +- src/libstd/uv_iotask.rs | 6 ++-- src/libstd/uv_ll.rs | 6 ++-- src/test/bench/msgsend-pipes-shared.rs | 2 +- src/test/bench/msgsend-pipes.rs | 2 +- src/test/bench/shootout-chameneos-redux.rs | 4 +-- src/test/bench/shootout-mandelbrot.rs | 2 +- src/test/bench/shootout-pfib.rs | 2 +- src/test/bench/task-perf-linked-failure.rs | 2 +- src/test/run-pass/hashmap-memory.rs | 2 +- src/test/run-pass/task-comm-14.rs | 2 +- src/test/run-pass/task-comm-3.rs | 2 +- src/test/run-pass/task-comm-6.rs | 2 +- src/test/run-pass/task-comm-7.rs | 2 +- src/test/run-pass/task-comm-9.rs | 2 +- src/test/run-pass/unique-send-2.rs | 2 +- src/test/run-pass/unwind-resource.rs | 2 +- 32 files changed, 79 insertions(+), 67 deletions(-) diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 7831dc1d80fc0..bed696748306e 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -236,7 +236,7 @@ Instead we can use a `SharedChan`, a type that allows a single use core::comm::{stream, SharedChan}; let (port, chan) = stream(); -let chan = SharedChan(chan); +let chan = SharedChan::new(chan); for uint::range(0, 3) |init_val| { // Create a new channel handle to distribute to the child task diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index ca10aa0da7d45..7d78b84dc8005 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -73,7 +73,7 @@ pub fn run(lib_path: ~str, writeclose(pipe_in.out, input); - let p = comm::PortSet(); + let p = comm::PortSet::new(); let ch = p.chan(); do task::spawn_sched(task::SingleThreaded) || { let errput = readclose(pipe_err.in); diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index 60ec4fbfddb30..fc13463bd1c2a 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -19,6 +19,7 @@ use option::{Option, Some, None}; use uint; use unstable; use vec; +use unstable::Exclusive; use pipes::{recv, try_recv, wait_many, peek, PacketHeader}; @@ -218,13 +219,14 @@ pub struct PortSet { mut ports: ~[Port], } -pub fn PortSet() -> PortSet{ - PortSet { - ports: ~[] +pub impl PortSet { + + fn new() -> PortSet { + PortSet { + ports: ~[] + } } -} -pub impl PortSet { fn add(&self, port: Port) { self.ports.push(port) } @@ -279,12 +281,21 @@ impl Peekable for PortSet { } /// A channel that can be shared between many senders. -pub type SharedChan = unstable::Exclusive>; +pub struct SharedChan { + ch: Exclusive> +} + +impl SharedChan { + /// Converts a `chan` into a `shared_chan`. + pub fn new(c: Chan) -> SharedChan { + SharedChan { ch: unstable::exclusive(c) } + } +} impl GenericChan for SharedChan { fn send(&self, x: T) { let mut xx = Some(x); - do self.with_imm |chan| { + do self.ch.with_imm |chan| { let mut x = None; x <-> xx; chan.send(x.unwrap()) @@ -295,7 +306,7 @@ impl GenericChan for SharedChan { impl GenericSmartChan for SharedChan { fn try_send(&self, x: T) -> bool { let mut xx = Some(x); - do self.with_imm |chan| { + do self.ch.with_imm |chan| { let mut x = None; x <-> xx; chan.try_send(x.unwrap()) @@ -303,9 +314,10 @@ impl GenericSmartChan for SharedChan { } } -/// Converts a `chan` into a `shared_chan`. -pub fn SharedChan(c: Chan) -> SharedChan { - unstable::exclusive(c) +impl ::clone::Clone for SharedChan { + fn clone(&self) -> SharedChan { + SharedChan { ch: self.ch.clone() } + } } /*proto! oneshot ( diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 9e6524c25cb29..8b18cc3c6968c 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -405,7 +405,7 @@ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { // or the other. FIXME (#2625): Surely there's a much more // clever way to do this. let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); let ch_clone = ch.clone(); do task::spawn_sched(task::SingleThreaded) { let errput = readclose(pipe_err.in); diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 2975f3d5e4660..55546514e4fa5 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -657,7 +657,7 @@ fn test_cant_dup_task_builder() { #[test] #[ignore(cfg(windows))] fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port let (po, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); do spawn_unlinked { let ch = ch.clone(); do spawn_unlinked { @@ -881,7 +881,7 @@ fn test_spawn_sched_no_threads() { #[test] fn test_spawn_sched() { let (po, ch) = stream::<()>(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); fn f(i: int, ch: SharedChan<()>) { let parent_sched_id = unsafe { rt::rust_get_sched_id() }; diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs index 6eabb0629d1fc..4e2174fd5d24c 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -69,7 +69,7 @@ fn create_global_service() -> ~WeakTaskService { debug!("creating global weak task service"); let (port, chan) = stream::(); let port = Cell(port); - let chan = SharedChan(chan); + let chan = SharedChan::new(chan); let chan_clone = chan.clone(); do task().unlinked().spawn { diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 3fbe1b96ef7aa..0e242805e13ae 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -307,7 +307,7 @@ bug and need to present an error. pub fn monitor(+f: ~fn(diagnostic::Emitter)) { use core::comm::*; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); let ch_capture = ch.clone(); match do task::try || { let ch = ch_capture.clone(); diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index 3b905c612a5c6..c4c81b5ec2c70 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -69,7 +69,7 @@ fn run(owner: SrvOwner, source: ~str, parse: Parser) -> T { } let srv_ = Srv { - ch: SharedChan(ch) + ch: SharedChan::new(ch) }; let res = owner(srv_.clone()); diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index fcf7011cbc309..13f598ce70781 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -232,7 +232,7 @@ fn write_file(path: &Path, s: ~str) { pub fn future_writer_factory( ) -> (WriterFactory, Port<(doc::Page, ~str)>) { let (markdown_po, markdown_ch) = stream(); - let markdown_ch = SharedChan(markdown_ch); + let markdown_ch = SharedChan::new(markdown_ch); let writer_factory: WriterFactory = |page| { let (writer_po, writer_ch) = comm::stream(); let markdown_ch = markdown_ch.clone(); diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index c620e20530e66..93e7d8c808cda 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -50,7 +50,7 @@ pub fn run( let (result_port, result_chan) = stream(); let (page_port, page_chan) = stream(); - let page_chan = SharedChan(page_chan); + let page_chan = SharedChan::new(page_chan); do task::spawn { result_chan.send(make_doc_from_pages(&page_port)); }; diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index da1e4688939cc..8abe0262314b5 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -499,7 +499,7 @@ mod tests { let (p, c) = comm::stream(); do task::spawn() || { - let p = comm::PortSet(); + let p = comm::PortSet::new(); c.send(p.chan()); let arc_v = p.recv(); diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index e920ff20ac5dc..e58b17b83218f 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -113,7 +113,7 @@ enum IpGetAddrErr { pub fn get_addr(node: &str, iotask: &iotask) -> result::Result<~[IpAddr], IpGetAddrErr> { let (output_po, output_ch) = stream(); - let mut output_ch = Some(SharedChan(output_ch)); + let mut output_ch = Some(SharedChan::new(output_ch)); do str::as_buf(node) |node_ptr, len| { let output_ch = output_ch.swap_unwrap(); debug!("slice len %?", len); diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index b32df75063d97..6bf97843fa178 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -150,16 +150,16 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, -> result::Result { unsafe { let (result_po, result_ch) = stream::(); - let result_ch = SharedChan(result_ch); + let result_ch = SharedChan::new(result_ch); let (closed_signal_po, closed_signal_ch) = stream::<()>(); - let closed_signal_ch = SharedChan(closed_signal_ch); + let closed_signal_ch = SharedChan::new(closed_signal_ch); let conn_data = ConnectReqData { result_ch: result_ch, closed_signal_ch: closed_signal_ch }; let conn_data_ptr = ptr::addr_of(&conn_data); let (reader_po, reader_ch) = stream::>(); - let reader_ch = SharedChan(reader_ch); + let reader_ch = SharedChan::new(reader_ch); let stream_handle_ptr = malloc_uv_tcp_t(); *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t(); let socket_data = @TcpSocketData { @@ -517,7 +517,7 @@ pub fn accept(new_conn: TcpNewConnection) server_handle_ptr) as *TcpListenFcData; let (reader_po, reader_ch) = stream::< Result<~[u8], TcpErrData>>(); - let reader_ch = SharedChan(reader_ch); + let reader_ch = SharedChan::new(reader_ch); let iotask = &(*server_data_ptr).iotask; let stream_handle_ptr = malloc_uv_tcp_t(); *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = @@ -537,7 +537,7 @@ pub fn accept(new_conn: TcpNewConnection) (*client_socket_data_ptr).stream_handle_ptr; let (result_po, result_ch) = stream::>(); - let result_ch = SharedChan(result_ch); + let result_ch = SharedChan::new(result_ch); // UNSAFE LIBUV INTERACTION BEGIN // .. normally this happens within the context of @@ -646,9 +646,9 @@ fn listen_common(host_ip: ip::IpAddr, on_connect_cb: ~fn(*uv::ll::uv_tcp_t)) -> result::Result<(), TcpListenErrData> { let (stream_closed_po, stream_closed_ch) = stream::<()>(); - let stream_closed_ch = SharedChan(stream_closed_ch); + let stream_closed_ch = SharedChan::new(stream_closed_ch); let (kill_po, kill_ch) = stream::>(); - let kill_ch = SharedChan(kill_ch); + let kill_ch = SharedChan::new(kill_ch); let server_stream = uv::ll::tcp_t(); let server_stream_ptr = ptr::addr_of(&server_stream); let server_data: TcpListenFcData = TcpListenFcData { @@ -997,7 +997,7 @@ impl io::Writer for TcpSocketBuf { fn tear_down_socket_data(socket_data: @TcpSocketData) { unsafe { let (closed_po, closed_ch) = stream::<()>(); - let closed_ch = SharedChan(closed_ch); + let closed_ch = SharedChan::new(closed_ch); let close_data = TcpSocketCloseData { closed_ch: closed_ch }; @@ -1147,7 +1147,7 @@ fn write_common_impl(socket_data_ptr: *TcpSocketData, vec::len(raw_write_data)) ]; let write_buf_vec_ptr = ptr::addr_of(&write_buf_vec); let (result_po, result_ch) = stream::(); - let result_ch = SharedChan(result_ch); + let result_ch = SharedChan::new(result_ch); let write_data = WriteReqData { result_ch: result_ch }; @@ -1554,7 +1554,7 @@ mod test { let (server_result_po, server_result_ch) = stream::<~str>(); let (cont_po, cont_ch) = stream::<()>(); - let cont_ch = SharedChan(cont_ch); + let cont_ch = SharedChan::new(cont_ch); // server let hl_loop_clone = hl_loop.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -1592,7 +1592,7 @@ mod test { let expected_resp = ~"pong"; let (cont_po, cont_ch) = stream::<()>(); - let cont_ch = SharedChan(cont_ch); + let cont_ch = SharedChan::new(cont_ch); // server let hl_loop_clone = hl_loop.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -1652,7 +1652,7 @@ mod test { let expected_resp = ~"pong"; let (cont_po, cont_ch) = stream::<()>(); - let cont_ch = SharedChan(cont_ch); + let cont_ch = SharedChan::new(cont_ch); // server let hl_loop_clone = hl_loop.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -1717,7 +1717,7 @@ mod test { let (server_result_po, server_result_ch) = stream::<~str>(); let (cont_po, cont_ch) = stream::<()>(); - let cont_ch = SharedChan(cont_ch); + let cont_ch = SharedChan::new(cont_ch); // server let iotask_clone = iotask.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -1764,7 +1764,7 @@ mod test { let expected_resp = ~"A string\nwith multiple lines\n"; let (cont_po, cont_ch) = stream::<()>(); - let cont_ch = SharedChan(cont_ch); + let cont_ch = SharedChan::new(cont_ch); // server let hl_loop_clone = hl_loop.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -1813,7 +1813,7 @@ mod test { cont_ch: SharedChan<()>, iotask: &IoTask) -> ~str { let (server_po, server_ch) = stream::<~str>(); - let server_ch = SharedChan(server_ch); + let server_ch = SharedChan::new(server_ch); let server_ip_addr = ip::v4::parse_addr(server_ip); let listen_result = listen(server_ip_addr, server_port, 128, iotask, diff --git a/src/libstd/test.rs b/src/libstd/test.rs index ee83a0c9bd652..4ccbf207170e9 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -446,7 +446,7 @@ fn run_tests(opts: &TestOpts, let mut pending = 0; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); while pending > 0 || !remaining.is_empty() { while pending < concurrency && !remaining.is_empty() { @@ -797,7 +797,7 @@ mod tests { testfn: DynTestFn(|| f()), }; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); assert!(res != TrOk); @@ -815,7 +815,7 @@ mod tests { testfn: DynTestFn(|| f()), }; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); assert!(res == TrIgnored); @@ -834,7 +834,7 @@ mod tests { testfn: DynTestFn(|| f()), }; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); assert!(res == TrOk); @@ -852,7 +852,7 @@ mod tests { testfn: DynTestFn(|| f()), }; let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); assert!(res == TrFailed); diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index c229e72ae5d4a..e862fe6077cb6 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -43,7 +43,7 @@ pub fn delayed_send(iotask: &IoTask, ch: &Chan, val: T) { let (timer_done_po, timer_done_ch) = stream::<()>(); - let timer_done_ch = SharedChan(timer_done_ch); + let timer_done_ch = SharedChan::new(timer_done_ch); let timer = uv::ll::timer_t(); let timer_ptr = ptr::addr_of(&timer); do iotask::interact(iotask) |loop_ptr| { @@ -199,7 +199,7 @@ mod test { #[test] fn test_gl_timer_sleep_stress2() { let (po, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); let hl_loop = &uv::global_loop::get(); let repeat = 20u; diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs index 3130abdc7cd99..ac762d7d801fe 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libstd/uv_global_loop.rs @@ -211,7 +211,7 @@ mod test { #[ignore] fn test_stress_gl_uv_global_loop_high_level_global_timer() { let (exit_po, exit_ch) = stream::<()>(); - let exit_ch = SharedChan(exit_ch); + let exit_ch = SharedChan::new(exit_ch); let cycles = 5000u; for iter::repeat(cycles) { let exit_ch_clone = exit_ch.clone(); diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index 7a9d2438e6ada..c7a78f3891923 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -126,7 +126,7 @@ fn run_loop(iotask_ch: &Chan) { // while we dwell in the I/O loop let iotask = IoTask{ async_handle: async_handle, - op_chan: SharedChan(msg_ch) + op_chan: SharedChan::new(msg_ch) }; iotask_ch.send(iotask); @@ -230,7 +230,7 @@ fn impl_uv_iotask_async(iotask: &IoTask) { let (exit_po, exit_ch) = stream::<()>(); let ah_data = AhData { iotask: iotask.clone(), - exit_ch: SharedChan(exit_ch) + exit_ch: SharedChan::new(exit_ch) }; let ah_data_ptr: *AhData = unsafe { ptr::to_unsafe_ptr(&ah_data) @@ -293,7 +293,7 @@ fn test_uv_iotask_async() { // loop lives until, at least, all of the // impl_uv_hl_async() runs have been called, at least. let (work_exit_po, work_exit_ch) = stream::<()>(); - let work_exit_ch = SharedChan(work_exit_ch); + let work_exit_ch = SharedChan::new(work_exit_ch); for iter::repeat(7u) { let iotask_clone = iotask.clone(); let work_exit_ch_clone = work_exit_ch.clone(); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 740ecec001f83..ab3074e49dd68 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1717,12 +1717,12 @@ mod test { let kill_server_msg = ~"does a dog have buddha nature?"; let server_resp_msg = ~"mu!"; let (client_port, client_chan) = stream::<~str>(); - let client_chan = SharedChan(client_chan); + let client_chan = SharedChan::new(client_chan); let (server_port, server_chan) = stream::<~str>(); - let server_chan = SharedChan(server_chan); + let server_chan = SharedChan::new(server_chan); let (continue_port, continue_chan) = stream::(); - let continue_chan = SharedChan(continue_chan); + let continue_chan = SharedChan::new(continue_chan); let kill_server_msg_copy = copy kill_server_msg; let server_resp_msg_copy = copy server_resp_msg; diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index 50647e8c100dc..dbfd38ccf2624 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -58,7 +58,7 @@ fn run(args: &[~str]) { let (from_child, to_parent) = comm::stream(); let (from_parent, to_child) = comm::stream(); - let to_child = SharedChan(to_child); + let to_child = SharedChan::new(to_child); let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index 77e64818f7e6c..492b13f570869 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -53,7 +53,7 @@ fn server(requests: PortSet, responses: Chan) { fn run(args: &[~str]) { let (from_child, to_parent) = stream(); let (from_parent_, to_child) = stream(); - let from_parent = PortSet(); + let from_parent = PortSet::new(); from_parent.add(from_parent_); let size = uint::from_str(args[1]).get(); diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index a81f7fd76e77b..9dad24646ded2 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -137,9 +137,9 @@ fn rendezvous(nn: uint, set: ~[color]) { // these ports will allow us to hear from the creatures let (from_creatures, to_rendezvous) = stream::(); - let to_rendezvous = SharedChan(to_rendezvous); + let to_rendezvous = SharedChan::new(to_rendezvous); let (from_creatures_log, to_rendezvous_log) = stream::<~str>(); - let to_rendezvous_log = SharedChan(to_rendezvous_log); + let to_rendezvous_log = SharedChan::new(to_rendezvous_log); // these channels will be passed to the creatures so they can talk to us diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index f5d1661fa52bd..4909d05b35b16 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -173,7 +173,7 @@ fn main() { else { uint::from_str(args[1]).get() }; let (pport, pchan) = comm::stream(); - let pchan = comm::SharedChan(pchan); + let pchan = comm::SharedChan::new(pchan); for uint::range(0_u, size) |j| { let cchan = pchan.clone(); do task::spawn { cchan.send(chanmb(j, size, depth)) }; diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index a90afd418d881..f7bd779a8d89e 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -38,7 +38,7 @@ fn fib(n: int) -> int { } else if n <= 2 { c.send(1); } else { - let p = PortSet(); + let p = PortSet::new(); let ch = p.chan(); task::spawn(|| pfib(ch, n - 1) ); let ch = p.chan(); diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs index d7514320e36d5..90c9d6b33e4ad 100644 --- a/src/test/bench/task-perf-linked-failure.rs +++ b/src/test/bench/task-perf-linked-failure.rs @@ -26,7 +26,7 @@ use core::comm::*; fn grandchild_group(num_tasks: uint) { let (po, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); for num_tasks.times { let ch = ch.clone(); diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 910708b710602..bca4cbafc6cc4 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -60,7 +60,7 @@ mod map_reduce { pub fn map_reduce(inputs: ~[~str]) { let (ctrl_port, ctrl_chan) = stream(); - let ctrl_chan = SharedChan(ctrl_chan); + let ctrl_chan = SharedChan::new(ctrl_chan); // This task becomes the master control task. It spawns others // to do the rest. diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 4f0eb7c101f55..8b4855deaa563 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -11,7 +11,7 @@ // xfail-fast pub fn main() { - let po = comm::PortSet(); + let po = comm::PortSet::new(); // Spawn 10 tasks each sending us back one int. let mut i = 10; diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 9d5cb75804408..cf06deb1923a6 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -32,7 +32,7 @@ fn test00() { debug!("Creating tasks"); - let po = comm::PortSet(); + let po = comm::PortSet::new(); let mut i: int = 0; diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs index af004e0f34d44..67ef5fb190526 100644 --- a/src/test/run-pass/task-comm-6.rs +++ b/src/test/run-pass/task-comm-6.rs @@ -15,7 +15,7 @@ pub fn main() { test00(); } fn test00() { let mut r: int = 0; let mut sum: int = 0; - let p = comm::PortSet(); + let p = comm::PortSet::new(); let c0 = p.chan(); let c1 = p.chan(); let c2 = p.chan(); diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 980ded6aecc0d..81b4988852559 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -23,7 +23,7 @@ fn test00_start(c: comm::Chan, start: int, number_of_messages: int) { fn test00() { let mut r: int = 0; let mut sum: int = 0; - let p = comm::PortSet(); + let p = comm::PortSet::new(); let number_of_messages: int = 10; let c = p.chan(); diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 1661792c6ac36..a3c8dc554a663 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -22,7 +22,7 @@ fn test00_start(c: &comm::Chan, number_of_messages: int) { fn test00() { let r: int = 0; let mut sum: int = 0; - let p = comm::PortSet(); + let p = comm::PortSet::new(); let number_of_messages: int = 10; let ch = p.chan(); diff --git a/src/test/run-pass/unique-send-2.rs b/src/test/run-pass/unique-send-2.rs index b655f86bdbb11..df1c8708acd11 100644 --- a/src/test/run-pass/unique-send-2.rs +++ b/src/test/run-pass/unique-send-2.rs @@ -16,7 +16,7 @@ fn child(c: &SharedChan<~uint>, i: uint) { pub fn main() { let (p, ch) = stream(); - let ch = SharedChan(ch); + let ch = SharedChan::new(ch); let n = 100u; let mut expected = 0u; for uint::range(0u, n) |i| { diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index f76868b28bef4..4c7b2e6370242 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -39,7 +39,7 @@ fn f(c: SharedChan) { pub fn main() { let (p, c) = stream(); - let c = SharedChan(c); + let c = SharedChan::new(c); task::spawn_unlinked(|| f(c.clone()) ); error!("hiiiiiiiii"); assert!(p.recv()); From 8a6d6dd868371e2ffc035dc508fb255bb9cbc8a0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 14:10:13 -0700 Subject: [PATCH 263/403] rustc: Fix struct returns on x86 mac for 8-byte structs Mac appears to follow the same ABI as MSVC. This fixes one case but leaves others broken, like windows. --- src/librustc/middle/trans/cabi_x86.rs | 10 +++++----- src/test/run-pass/extern-pass-TwoU32s.rs | 2 -- src/test/run-pass/extern-return-TwoU32s.rs | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index a549f9121716f..08b8c3db3cabf 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use driver::session::os_win32; +use driver::session::{os_win32, os_macos}; use core::option::*; use lib::llvm::*; use lib::llvm::llvm::*; @@ -38,12 +38,12 @@ impl ABIInfo for X86_ABIInfo { // Rules for returning structs taken from // http://www.angelcode.com/dev/callconv/callconv.html + // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp let sret = { let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def }; - let big_struct = if self.ccx.sess.targ_cfg.os != os_win32 { - true - } else { - llsize_of_alloc(self.ccx, rty) > 8 + let big_struct = match self.ccx.sess.targ_cfg.os { + os_win32 | os_macos => llsize_of_alloc(self.ccx, rty) > 8, + _ => true }; returning_a_struct && big_struct }; diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index db040b8407a59..16d14a96cfe4f 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -11,8 +11,6 @@ // Test a foreign function that accepts and returns a struct // by value. -// xfail-macos Broken on mac i686 - #[deriving(Eq)] struct TwoU32s { one: u32, two: u32 diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs index 38e61ae6d49bd..9e374687855b0 100644 --- a/src/test/run-pass/extern-return-TwoU32s.rs +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-macos Broken on mac i686 - struct TwoU32s { one: u32, two: u32 } From 14b7277c4fe6fe7ef26a28931962d8557e2670a7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 4 Jan 2013 13:52:18 -0800 Subject: [PATCH 264/403] core: add vec::bsearch. --- src/libcore/vec.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index eebe6a7a37f32..01d1a57d78c3d 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1223,6 +1223,46 @@ pub fn rposition_between(v: &[T], start: uint, end: uint, None } + + +/** + * Binary search a sorted vector with a comparator function. + * + * The comparator should implement an order consistent with the sort + * order of the underlying vector, returning an order code that indicates + * whether its argument is `Less`, `Equal` or `Greater` the desired target. + * + * Returns the index where the comparator returned `Equal`, or `None` if + * not found. + */ +pub pure fn bsearch(v: &[T], f: &fn(&T) -> Ordering) -> Option { + let mut base : uint = 0; + let mut lim : uint = v.len(); + + while lim != 0 { + let ix = base + (lim >> 1); + match f(&v[ix]) { + Equal => return Some(ix), + Less => { + base = ix + 1; + lim -= 1; + } + Greater => () + } + lim >>= 1; + } + return None; +} + +/** + * Binary search a sorted vector for a given element. + * + * Returns the index of the element or None if not found. + */ +pub pure fn bsearch_elem(v: &[T], x: &T) -> Option { + bsearch(v, |p| p.cmp(x)) +} + // FIXME: if issue #586 gets implemented, could have a postcondition // saying the two result lists have the same length -- or, could // return a nominal record with a constraint saying that, instead of @@ -3710,6 +3750,51 @@ mod tests { assert!(rfind_between(v, 4u, 4u, f).is_none()); } + #[test] + fn test_bsearch_elem() { + fail_unless!(bsearch_elem([1,2,3,4,5], &5) == Some(4)); + fail_unless!(bsearch_elem([1,2,3,4,5], &4) == Some(3)); + fail_unless!(bsearch_elem([1,2,3,4,5], &3) == Some(2)); + fail_unless!(bsearch_elem([1,2,3,4,5], &2) == Some(1)); + fail_unless!(bsearch_elem([1,2,3,4,5], &1) == Some(0)); + + fail_unless!(bsearch_elem([2,4,6,8,10], &1) == None); + fail_unless!(bsearch_elem([2,4,6,8,10], &5) == None); + fail_unless!(bsearch_elem([2,4,6,8,10], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6,8,10], &10) == Some(4)); + + fail_unless!(bsearch_elem([2,4,6,8], &1) == None); + fail_unless!(bsearch_elem([2,4,6,8], &5) == None); + fail_unless!(bsearch_elem([2,4,6,8], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6,8], &8) == Some(3)); + + fail_unless!(bsearch_elem([2,4,6], &1) == None); + fail_unless!(bsearch_elem([2,4,6], &5) == None); + fail_unless!(bsearch_elem([2,4,6], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6], &6) == Some(2)); + + fail_unless!(bsearch_elem([2,4], &1) == None); + fail_unless!(bsearch_elem([2,4], &5) == None); + fail_unless!(bsearch_elem([2,4], &2) == Some(0)); + fail_unless!(bsearch_elem([2,4], &4) == Some(1)); + + fail_unless!(bsearch_elem([2], &1) == None); + fail_unless!(bsearch_elem([2], &5) == None); + fail_unless!(bsearch_elem([2], &2) == Some(0)); + + fail_unless!(bsearch_elem([], &1) == None); + fail_unless!(bsearch_elem([], &5) == None); + + fail_unless!(bsearch_elem([1,1,1,1,1], &1) != None); + fail_unless!(bsearch_elem([1,1,1,1,2], &1) != None); + fail_unless!(bsearch_elem([1,1,1,2,2], &1) != None); + fail_unless!(bsearch_elem([1,1,2,2,2], &1) != None); + fail_unless!(bsearch_elem([1,2,2,2,2], &1) == Some(0)); + + fail_unless!(bsearch_elem([1,2,3,4,5], &6) == None); + fail_unless!(bsearch_elem([1,2,3,4,5], &0) == None); + } + #[test] fn reverse_and_reversed() { let mut v: ~[int] = ~[10, 20]; From 5a3d26f271a39212de90544e7394c29373dc5bab Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Jan 2013 08:44:31 -0800 Subject: [PATCH 265/403] core: replace unicode match exprs with bsearch in const arrays, minor perf win. --- src/etc/unicode.py | 45 +- src/libcore/unicode.rs | 7113 ++++++++++++---------------------- src/libcore/vec.rs | 86 +- src/libsyntax/parse/lexer.rs | 4 +- 4 files changed, 2622 insertions(+), 4626 deletions(-) diff --git a/src/etc/unicode.py b/src/etc/unicode.py index 5dabf34953b01..864cf3daee07e 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -112,7 +112,49 @@ def escape_char(c): return "'\\u%4.4x'" % c return "'\\U%8.8x'" % c +def ch_prefix(ix): + if ix == 0: + return " " + if ix % 2 == 0: + return ",\n " + else: + return ", " + +def emit_bsearch_range_table(f): + f.write(""" + pure fn bsearch_range_table(c: char, r: &[(char,char)]) -> bool { + use cmp::{EQ, LT, GT}; + use vec::bsearch; + use option::None; + (do bsearch(r) |&(lo,hi)| { + if lo <= c && c <= hi { EQ } + else if hi < c { LT } + else { GT } + }) != None + }\n\n +"""); + def emit_property_module(f, mod, tbl): + f.write("pub mod %s {\n" % mod) + keys = tbl.keys() + keys.sort() + emit_bsearch_range_table(f); + for cat in keys: + f.write(" const %s_table : &[(char,char)] = &[\n" % cat) + ix = 0 + for pair in tbl[cat]: + f.write(ch_prefix(ix)) + f.write("(%s, %s)" % (escape_char(pair[0]), escape_char(pair[1]))) + ix += 1 + f.write("\n ];\n\n") + + f.write(" pub pure fn %s(c: char) -> bool {\n" % cat) + f.write(" bsearch_range_table(c, %s_table)\n" % cat) + f.write(" }\n\n") + f.write("}\n") + + +def emit_property_module_old(f, mod, tbl): f.write("mod %s {\n" % mod) keys = tbl.keys() keys.sort() @@ -193,8 +235,9 @@ def emit_decomp_module(f, canon, compat): rf = open(r, "w") (canon_decomp, compat_decomp, gencats) = load_unicode_data("UnicodeData.txt") -emit_decomp_module(rf, canon_decomp, compat_decomp) emit_property_module(rf, "general_category", gencats) +#emit_decomp_module(rf, canon_decomp, compat_decomp) + derived = load_derived_core_properties("DerivedCoreProperties.txt") emit_property_module(rf, "derived_property", derived) diff --git a/src/libcore/unicode.rs b/src/libcore/unicode.rs index 9f2ab66d5c207..a13d66c48ee0c 100644 --- a/src/libcore/unicode.rs +++ b/src/libcore/unicode.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -11,4680 +11,2633 @@ #[doc(hidden)]; // FIXME #3538 pub mod general_category { + + fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { + use cmp::{Equal, Less, Greater}; + use vec::bsearch; + use option::None; + (do bsearch(r) |&(lo,hi)| { + if lo <= c && c <= hi { Equal } + else if hi < c { Less } + else { Greater } + }) != None + } + + + static Cc_table : &'static [(char,char)] = &[ + ('\x00', '\x1f'), ('\x7f', '\x9f') + ]; + pub fn Cc(c: char) -> bool { - return match c { - '\x00' .. '\x1f' - | '\x7f' .. '\x9f' => true, - _ => false - }; + bsearch_range_table(c, Cc_table) } + static Cf_table : &'static [(char,char)] = &[ + ('\xad', '\xad'), ('\u0600', '\u0604'), + ('\u06dd', '\u06dd'), ('\u070f', '\u070f'), + ('\u200b', '\u200f'), ('\u202a', '\u202e'), + ('\u2060', '\u206f'), ('\ufeff', '\ufeff'), + ('\ufff9', '\ufffb'), ('\U000110bd', '\U000110bd'), + ('\U0001d173', '\U0001d17a'), ('\U000e0001', '\U000e007f') + ]; + pub fn Cf(c: char) -> bool { - return match c { - '\xad' - | '\u0600' .. '\u0603' - | '\u06dd' - | '\u070f' - | '\u17b4' .. '\u17b5' - | '\u200b' .. '\u200f' - | '\u202a' .. '\u202e' - | '\u2060' .. '\u206f' - | '\ufeff' - | '\ufff9' .. '\ufffb' - | '\U000110bd' - | '\U0001d173' .. '\U0001d17a' - | '\U000e0001' .. '\U000e007f' => true, - _ => false - }; + bsearch_range_table(c, Cf_table) } + static Co_table : &'static [(char,char)] = &[ + ('\ue000', '\uf8ff') + ]; + pub fn Co(c: char) -> bool { - return match c { - '\ue000' .. '\uf8ff' => true, - _ => false - }; + bsearch_range_table(c, Co_table) } + static Cs_table : &'static [(char,char)] = &[ + ('\ud800', '\udfff') + ]; + pub fn Cs(c: char) -> bool { - return match c { - '\ud800' .. '\udfff' => true, - _ => false - }; + bsearch_range_table(c, Cs_table) } + static Ll_table : &'static [(char,char)] = &[ + ('\x61', '\x7a'), ('\xb5', '\xb5'), + ('\xdf', '\xf6'), ('\xf8', '\xff'), + ('\u0101', '\u0101'), ('\u0103', '\u0103'), + ('\u0105', '\u0105'), ('\u0107', '\u0107'), + ('\u0109', '\u0109'), ('\u010b', '\u010b'), + ('\u010d', '\u010d'), ('\u010f', '\u010f'), + ('\u0111', '\u0111'), ('\u0113', '\u0113'), + ('\u0115', '\u0115'), ('\u0117', '\u0117'), + ('\u0119', '\u0119'), ('\u011b', '\u011b'), + ('\u011d', '\u011d'), ('\u011f', '\u011f'), + ('\u0121', '\u0121'), ('\u0123', '\u0123'), + ('\u0125', '\u0125'), ('\u0127', '\u0127'), + ('\u0129', '\u0129'), ('\u012b', '\u012b'), + ('\u012d', '\u012d'), ('\u012f', '\u012f'), + ('\u0131', '\u0131'), ('\u0133', '\u0133'), + ('\u0135', '\u0135'), ('\u0137', '\u0138'), + ('\u013a', '\u013a'), ('\u013c', '\u013c'), + ('\u013e', '\u013e'), ('\u0140', '\u0140'), + ('\u0142', '\u0142'), ('\u0144', '\u0144'), + ('\u0146', '\u0146'), ('\u0148', '\u0149'), + ('\u014b', '\u014b'), ('\u014d', '\u014d'), + ('\u014f', '\u014f'), ('\u0151', '\u0151'), + ('\u0153', '\u0153'), ('\u0155', '\u0155'), + ('\u0157', '\u0157'), ('\u0159', '\u0159'), + ('\u015b', '\u015b'), ('\u015d', '\u015d'), + ('\u015f', '\u015f'), ('\u0161', '\u0161'), + ('\u0163', '\u0163'), ('\u0165', '\u0165'), + ('\u0167', '\u0167'), ('\u0169', '\u0169'), + ('\u016b', '\u016b'), ('\u016d', '\u016d'), + ('\u016f', '\u016f'), ('\u0171', '\u0171'), + ('\u0173', '\u0173'), ('\u0175', '\u0175'), + ('\u0177', '\u0177'), ('\u017a', '\u017a'), + ('\u017c', '\u017c'), ('\u017e', '\u0180'), + ('\u0183', '\u0183'), ('\u0185', '\u0185'), + ('\u0188', '\u0188'), ('\u018c', '\u018d'), + ('\u0192', '\u0192'), ('\u0195', '\u0195'), + ('\u0199', '\u019b'), ('\u019e', '\u019e'), + ('\u01a1', '\u01a1'), ('\u01a3', '\u01a3'), + ('\u01a5', '\u01a5'), ('\u01a8', '\u01a8'), + ('\u01aa', '\u01ab'), ('\u01ad', '\u01ad'), + ('\u01b0', '\u01b0'), ('\u01b4', '\u01b4'), + ('\u01b6', '\u01b6'), ('\u01b9', '\u01ba'), + ('\u01bd', '\u01bf'), ('\u01c6', '\u01c6'), + ('\u01c9', '\u01c9'), ('\u01cc', '\u01cc'), + ('\u01ce', '\u01ce'), ('\u01d0', '\u01d0'), + ('\u01d2', '\u01d2'), ('\u01d4', '\u01d4'), + ('\u01d6', '\u01d6'), ('\u01d8', '\u01d8'), + ('\u01da', '\u01da'), ('\u01dc', '\u01dd'), + ('\u01df', '\u01df'), ('\u01e1', '\u01e1'), + ('\u01e3', '\u01e3'), ('\u01e5', '\u01e5'), + ('\u01e7', '\u01e7'), ('\u01e9', '\u01e9'), + ('\u01eb', '\u01eb'), ('\u01ed', '\u01ed'), + ('\u01ef', '\u01f0'), ('\u01f3', '\u01f3'), + ('\u01f5', '\u01f5'), ('\u01f9', '\u01f9'), + ('\u01fb', '\u01fb'), ('\u01fd', '\u01fd'), + ('\u01ff', '\u01ff'), ('\u0201', '\u0201'), + ('\u0203', '\u0203'), ('\u0205', '\u0205'), + ('\u0207', '\u0207'), ('\u0209', '\u0209'), + ('\u020b', '\u020b'), ('\u020d', '\u020d'), + ('\u020f', '\u020f'), ('\u0211', '\u0211'), + ('\u0213', '\u0213'), ('\u0215', '\u0215'), + ('\u0217', '\u0217'), ('\u0219', '\u0219'), + ('\u021b', '\u021b'), ('\u021d', '\u021d'), + ('\u021f', '\u021f'), ('\u0221', '\u0221'), + ('\u0223', '\u0223'), ('\u0225', '\u0225'), + ('\u0227', '\u0227'), ('\u0229', '\u0229'), + ('\u022b', '\u022b'), ('\u022d', '\u022d'), + ('\u022f', '\u022f'), ('\u0231', '\u0231'), + ('\u0233', '\u0239'), ('\u023c', '\u023c'), + ('\u023f', '\u0240'), ('\u0242', '\u0242'), + ('\u0247', '\u0247'), ('\u0249', '\u0249'), + ('\u024b', '\u024b'), ('\u024d', '\u024d'), + ('\u024f', '\u0293'), ('\u0295', '\u02af'), + ('\u0371', '\u0371'), ('\u0373', '\u0373'), + ('\u0377', '\u0377'), ('\u037b', '\u037d'), + ('\u0390', '\u0390'), ('\u03ac', '\u03ce'), + ('\u03d0', '\u03d1'), ('\u03d5', '\u03d7'), + ('\u03d9', '\u03d9'), ('\u03db', '\u03db'), + ('\u03dd', '\u03dd'), ('\u03df', '\u03df'), + ('\u03e1', '\u03e1'), ('\u03e3', '\u03e3'), + ('\u03e5', '\u03e5'), ('\u03e7', '\u03e7'), + ('\u03e9', '\u03e9'), ('\u03eb', '\u03eb'), + ('\u03ed', '\u03ed'), ('\u03ef', '\u03f3'), + ('\u03f5', '\u03f5'), ('\u03f8', '\u03f8'), + ('\u03fb', '\u03fc'), ('\u0430', '\u045f'), + ('\u0461', '\u0461'), ('\u0463', '\u0463'), + ('\u0465', '\u0465'), ('\u0467', '\u0467'), + ('\u0469', '\u0469'), ('\u046b', '\u046b'), + ('\u046d', '\u046d'), ('\u046f', '\u046f'), + ('\u0471', '\u0471'), ('\u0473', '\u0473'), + ('\u0475', '\u0475'), ('\u0477', '\u0477'), + ('\u0479', '\u0479'), ('\u047b', '\u047b'), + ('\u047d', '\u047d'), ('\u047f', '\u047f'), + ('\u0481', '\u0481'), ('\u048b', '\u048b'), + ('\u048d', '\u048d'), ('\u048f', '\u048f'), + ('\u0491', '\u0491'), ('\u0493', '\u0493'), + ('\u0495', '\u0495'), ('\u0497', '\u0497'), + ('\u0499', '\u0499'), ('\u049b', '\u049b'), + ('\u049d', '\u049d'), ('\u049f', '\u049f'), + ('\u04a1', '\u04a1'), ('\u04a3', '\u04a3'), + ('\u04a5', '\u04a5'), ('\u04a7', '\u04a7'), + ('\u04a9', '\u04a9'), ('\u04ab', '\u04ab'), + ('\u04ad', '\u04ad'), ('\u04af', '\u04af'), + ('\u04b1', '\u04b1'), ('\u04b3', '\u04b3'), + ('\u04b5', '\u04b5'), ('\u04b7', '\u04b7'), + ('\u04b9', '\u04b9'), ('\u04bb', '\u04bb'), + ('\u04bd', '\u04bd'), ('\u04bf', '\u04bf'), + ('\u04c2', '\u04c2'), ('\u04c4', '\u04c4'), + ('\u04c6', '\u04c6'), ('\u04c8', '\u04c8'), + ('\u04ca', '\u04ca'), ('\u04cc', '\u04cc'), + ('\u04ce', '\u04cf'), ('\u04d1', '\u04d1'), + ('\u04d3', '\u04d3'), ('\u04d5', '\u04d5'), + ('\u04d7', '\u04d7'), ('\u04d9', '\u04d9'), + ('\u04db', '\u04db'), ('\u04dd', '\u04dd'), + ('\u04df', '\u04df'), ('\u04e1', '\u04e1'), + ('\u04e3', '\u04e3'), ('\u04e5', '\u04e5'), + ('\u04e7', '\u04e7'), ('\u04e9', '\u04e9'), + ('\u04eb', '\u04eb'), ('\u04ed', '\u04ed'), + ('\u04ef', '\u04ef'), ('\u04f1', '\u04f1'), + ('\u04f3', '\u04f3'), ('\u04f5', '\u04f5'), + ('\u04f7', '\u04f7'), ('\u04f9', '\u04f9'), + ('\u04fb', '\u04fb'), ('\u04fd', '\u04fd'), + ('\u04ff', '\u04ff'), ('\u0501', '\u0501'), + ('\u0503', '\u0503'), ('\u0505', '\u0505'), + ('\u0507', '\u0507'), ('\u0509', '\u0509'), + ('\u050b', '\u050b'), ('\u050d', '\u050d'), + ('\u050f', '\u050f'), ('\u0511', '\u0511'), + ('\u0513', '\u0513'), ('\u0515', '\u0515'), + ('\u0517', '\u0517'), ('\u0519', '\u0519'), + ('\u051b', '\u051b'), ('\u051d', '\u051d'), + ('\u051f', '\u051f'), ('\u0521', '\u0521'), + ('\u0523', '\u0523'), ('\u0525', '\u0525'), + ('\u0527', '\u0527'), ('\u0561', '\u0587'), + ('\u1d00', '\u1d2b'), ('\u1d6b', '\u1d77'), + ('\u1d79', '\u1d9a'), ('\u1e01', '\u1e01'), + ('\u1e03', '\u1e03'), ('\u1e05', '\u1e05'), + ('\u1e07', '\u1e07'), ('\u1e09', '\u1e09'), + ('\u1e0b', '\u1e0b'), ('\u1e0d', '\u1e0d'), + ('\u1e0f', '\u1e0f'), ('\u1e11', '\u1e11'), + ('\u1e13', '\u1e13'), ('\u1e15', '\u1e15'), + ('\u1e17', '\u1e17'), ('\u1e19', '\u1e19'), + ('\u1e1b', '\u1e1b'), ('\u1e1d', '\u1e1d'), + ('\u1e1f', '\u1e1f'), ('\u1e21', '\u1e21'), + ('\u1e23', '\u1e23'), ('\u1e25', '\u1e25'), + ('\u1e27', '\u1e27'), ('\u1e29', '\u1e29'), + ('\u1e2b', '\u1e2b'), ('\u1e2d', '\u1e2d'), + ('\u1e2f', '\u1e2f'), ('\u1e31', '\u1e31'), + ('\u1e33', '\u1e33'), ('\u1e35', '\u1e35'), + ('\u1e37', '\u1e37'), ('\u1e39', '\u1e39'), + ('\u1e3b', '\u1e3b'), ('\u1e3d', '\u1e3d'), + ('\u1e3f', '\u1e3f'), ('\u1e41', '\u1e41'), + ('\u1e43', '\u1e43'), ('\u1e45', '\u1e45'), + ('\u1e47', '\u1e47'), ('\u1e49', '\u1e49'), + ('\u1e4b', '\u1e4b'), ('\u1e4d', '\u1e4d'), + ('\u1e4f', '\u1e4f'), ('\u1e51', '\u1e51'), + ('\u1e53', '\u1e53'), ('\u1e55', '\u1e55'), + ('\u1e57', '\u1e57'), ('\u1e59', '\u1e59'), + ('\u1e5b', '\u1e5b'), ('\u1e5d', '\u1e5d'), + ('\u1e5f', '\u1e5f'), ('\u1e61', '\u1e61'), + ('\u1e63', '\u1e63'), ('\u1e65', '\u1e65'), + ('\u1e67', '\u1e67'), ('\u1e69', '\u1e69'), + ('\u1e6b', '\u1e6b'), ('\u1e6d', '\u1e6d'), + ('\u1e6f', '\u1e6f'), ('\u1e71', '\u1e71'), + ('\u1e73', '\u1e73'), ('\u1e75', '\u1e75'), + ('\u1e77', '\u1e77'), ('\u1e79', '\u1e79'), + ('\u1e7b', '\u1e7b'), ('\u1e7d', '\u1e7d'), + ('\u1e7f', '\u1e7f'), ('\u1e81', '\u1e81'), + ('\u1e83', '\u1e83'), ('\u1e85', '\u1e85'), + ('\u1e87', '\u1e87'), ('\u1e89', '\u1e89'), + ('\u1e8b', '\u1e8b'), ('\u1e8d', '\u1e8d'), + ('\u1e8f', '\u1e8f'), ('\u1e91', '\u1e91'), + ('\u1e93', '\u1e93'), ('\u1e95', '\u1e9d'), + ('\u1e9f', '\u1e9f'), ('\u1ea1', '\u1ea1'), + ('\u1ea3', '\u1ea3'), ('\u1ea5', '\u1ea5'), + ('\u1ea7', '\u1ea7'), ('\u1ea9', '\u1ea9'), + ('\u1eab', '\u1eab'), ('\u1ead', '\u1ead'), + ('\u1eaf', '\u1eaf'), ('\u1eb1', '\u1eb1'), + ('\u1eb3', '\u1eb3'), ('\u1eb5', '\u1eb5'), + ('\u1eb7', '\u1eb7'), ('\u1eb9', '\u1eb9'), + ('\u1ebb', '\u1ebb'), ('\u1ebd', '\u1ebd'), + ('\u1ebf', '\u1ebf'), ('\u1ec1', '\u1ec1'), + ('\u1ec3', '\u1ec3'), ('\u1ec5', '\u1ec5'), + ('\u1ec7', '\u1ec7'), ('\u1ec9', '\u1ec9'), + ('\u1ecb', '\u1ecb'), ('\u1ecd', '\u1ecd'), + ('\u1ecf', '\u1ecf'), ('\u1ed1', '\u1ed1'), + ('\u1ed3', '\u1ed3'), ('\u1ed5', '\u1ed5'), + ('\u1ed7', '\u1ed7'), ('\u1ed9', '\u1ed9'), + ('\u1edb', '\u1edb'), ('\u1edd', '\u1edd'), + ('\u1edf', '\u1edf'), ('\u1ee1', '\u1ee1'), + ('\u1ee3', '\u1ee3'), ('\u1ee5', '\u1ee5'), + ('\u1ee7', '\u1ee7'), ('\u1ee9', '\u1ee9'), + ('\u1eeb', '\u1eeb'), ('\u1eed', '\u1eed'), + ('\u1eef', '\u1eef'), ('\u1ef1', '\u1ef1'), + ('\u1ef3', '\u1ef3'), ('\u1ef5', '\u1ef5'), + ('\u1ef7', '\u1ef7'), ('\u1ef9', '\u1ef9'), + ('\u1efb', '\u1efb'), ('\u1efd', '\u1efd'), + ('\u1eff', '\u1f07'), ('\u1f10', '\u1f15'), + ('\u1f20', '\u1f27'), ('\u1f30', '\u1f37'), + ('\u1f40', '\u1f45'), ('\u1f50', '\u1f57'), + ('\u1f60', '\u1f67'), ('\u1f70', '\u1f87'), + ('\u1f90', '\u1f97'), ('\u1fa0', '\u1fa7'), + ('\u1fb0', '\u1fb7'), ('\u1fbe', '\u1fbe'), + ('\u1fc2', '\u1fc7'), ('\u1fd0', '\u1fd7'), + ('\u1fe0', '\u1fe7'), ('\u1ff2', '\u1ff7'), + ('\u210a', '\u210a'), ('\u210e', '\u210f'), + ('\u2113', '\u2113'), ('\u212f', '\u212f'), + ('\u2134', '\u2134'), ('\u2139', '\u2139'), + ('\u213c', '\u213d'), ('\u2146', '\u2149'), + ('\u214e', '\u214e'), ('\u2184', '\u2184'), + ('\u2c30', '\u2c5e'), ('\u2c61', '\u2c61'), + ('\u2c65', '\u2c66'), ('\u2c68', '\u2c68'), + ('\u2c6a', '\u2c6a'), ('\u2c6c', '\u2c6c'), + ('\u2c71', '\u2c71'), ('\u2c73', '\u2c74'), + ('\u2c76', '\u2c7b'), ('\u2c81', '\u2c81'), + ('\u2c83', '\u2c83'), ('\u2c85', '\u2c85'), + ('\u2c87', '\u2c87'), ('\u2c89', '\u2c89'), + ('\u2c8b', '\u2c8b'), ('\u2c8d', '\u2c8d'), + ('\u2c8f', '\u2c8f'), ('\u2c91', '\u2c91'), + ('\u2c93', '\u2c93'), ('\u2c95', '\u2c95'), + ('\u2c97', '\u2c97'), ('\u2c99', '\u2c99'), + ('\u2c9b', '\u2c9b'), ('\u2c9d', '\u2c9d'), + ('\u2c9f', '\u2c9f'), ('\u2ca1', '\u2ca1'), + ('\u2ca3', '\u2ca3'), ('\u2ca5', '\u2ca5'), + ('\u2ca7', '\u2ca7'), ('\u2ca9', '\u2ca9'), + ('\u2cab', '\u2cab'), ('\u2cad', '\u2cad'), + ('\u2caf', '\u2caf'), ('\u2cb1', '\u2cb1'), + ('\u2cb3', '\u2cb3'), ('\u2cb5', '\u2cb5'), + ('\u2cb7', '\u2cb7'), ('\u2cb9', '\u2cb9'), + ('\u2cbb', '\u2cbb'), ('\u2cbd', '\u2cbd'), + ('\u2cbf', '\u2cbf'), ('\u2cc1', '\u2cc1'), + ('\u2cc3', '\u2cc3'), ('\u2cc5', '\u2cc5'), + ('\u2cc7', '\u2cc7'), ('\u2cc9', '\u2cc9'), + ('\u2ccb', '\u2ccb'), ('\u2ccd', '\u2ccd'), + ('\u2ccf', '\u2ccf'), ('\u2cd1', '\u2cd1'), + ('\u2cd3', '\u2cd3'), ('\u2cd5', '\u2cd5'), + ('\u2cd7', '\u2cd7'), ('\u2cd9', '\u2cd9'), + ('\u2cdb', '\u2cdb'), ('\u2cdd', '\u2cdd'), + ('\u2cdf', '\u2cdf'), ('\u2ce1', '\u2ce1'), + ('\u2ce3', '\u2ce4'), ('\u2cec', '\u2cec'), + ('\u2cee', '\u2cee'), ('\u2cf3', '\u2cf3'), + ('\u2d00', '\u2d2d'), ('\ua641', '\ua641'), + ('\ua643', '\ua643'), ('\ua645', '\ua645'), + ('\ua647', '\ua647'), ('\ua649', '\ua649'), + ('\ua64b', '\ua64b'), ('\ua64d', '\ua64d'), + ('\ua64f', '\ua64f'), ('\ua651', '\ua651'), + ('\ua653', '\ua653'), ('\ua655', '\ua655'), + ('\ua657', '\ua657'), ('\ua659', '\ua659'), + ('\ua65b', '\ua65b'), ('\ua65d', '\ua65d'), + ('\ua65f', '\ua65f'), ('\ua661', '\ua661'), + ('\ua663', '\ua663'), ('\ua665', '\ua665'), + ('\ua667', '\ua667'), ('\ua669', '\ua669'), + ('\ua66b', '\ua66b'), ('\ua66d', '\ua66d'), + ('\ua681', '\ua681'), ('\ua683', '\ua683'), + ('\ua685', '\ua685'), ('\ua687', '\ua687'), + ('\ua689', '\ua689'), ('\ua68b', '\ua68b'), + ('\ua68d', '\ua68d'), ('\ua68f', '\ua68f'), + ('\ua691', '\ua691'), ('\ua693', '\ua693'), + ('\ua695', '\ua695'), ('\ua697', '\ua697'), + ('\ua723', '\ua723'), ('\ua725', '\ua725'), + ('\ua727', '\ua727'), ('\ua729', '\ua729'), + ('\ua72b', '\ua72b'), ('\ua72d', '\ua72d'), + ('\ua72f', '\ua731'), ('\ua733', '\ua733'), + ('\ua735', '\ua735'), ('\ua737', '\ua737'), + ('\ua739', '\ua739'), ('\ua73b', '\ua73b'), + ('\ua73d', '\ua73d'), ('\ua73f', '\ua73f'), + ('\ua741', '\ua741'), ('\ua743', '\ua743'), + ('\ua745', '\ua745'), ('\ua747', '\ua747'), + ('\ua749', '\ua749'), ('\ua74b', '\ua74b'), + ('\ua74d', '\ua74d'), ('\ua74f', '\ua74f'), + ('\ua751', '\ua751'), ('\ua753', '\ua753'), + ('\ua755', '\ua755'), ('\ua757', '\ua757'), + ('\ua759', '\ua759'), ('\ua75b', '\ua75b'), + ('\ua75d', '\ua75d'), ('\ua75f', '\ua75f'), + ('\ua761', '\ua761'), ('\ua763', '\ua763'), + ('\ua765', '\ua765'), ('\ua767', '\ua767'), + ('\ua769', '\ua769'), ('\ua76b', '\ua76b'), + ('\ua76d', '\ua76d'), ('\ua76f', '\ua76f'), + ('\ua771', '\ua778'), ('\ua77a', '\ua77a'), + ('\ua77c', '\ua77c'), ('\ua77f', '\ua77f'), + ('\ua781', '\ua781'), ('\ua783', '\ua783'), + ('\ua785', '\ua785'), ('\ua787', '\ua787'), + ('\ua78c', '\ua78c'), ('\ua78e', '\ua78e'), + ('\ua791', '\ua791'), ('\ua793', '\ua793'), + ('\ua7a1', '\ua7a1'), ('\ua7a3', '\ua7a3'), + ('\ua7a5', '\ua7a5'), ('\ua7a7', '\ua7a7'), + ('\ua7a9', '\ua7a9'), ('\ua7fa', '\ua7fa'), + ('\ufb00', '\ufb17'), ('\uff41', '\uff5a'), + ('\U00010428', '\U0001044f'), ('\U0001d41a', '\U0001d433'), + ('\U0001d44e', '\U0001d467'), ('\U0001d482', '\U0001d49b'), + ('\U0001d4b6', '\U0001d4cf'), ('\U0001d4ea', '\U0001d503'), + ('\U0001d51e', '\U0001d537'), ('\U0001d552', '\U0001d56b'), + ('\U0001d586', '\U0001d59f'), ('\U0001d5ba', '\U0001d5d3'), + ('\U0001d5ee', '\U0001d607'), ('\U0001d622', '\U0001d63b'), + ('\U0001d656', '\U0001d66f'), ('\U0001d68a', '\U0001d6a5'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6e1'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d71b'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d755'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d78f'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7c9'), + ('\U0001d7cb', '\U0001d7cb') + ]; + pub fn Ll(c: char) -> bool { - return match c { - '\x61' .. '\x7a' - | '\xaa' - | '\xb5' - | '\xba' - | '\xdf' .. '\xf6' - | '\xf8' .. '\xff' - | '\u0101' - | '\u0103' - | '\u0105' - | '\u0107' - | '\u0109' - | '\u010b' - | '\u010d' - | '\u010f' - | '\u0111' - | '\u0113' - | '\u0115' - | '\u0117' - | '\u0119' - | '\u011b' - | '\u011d' - | '\u011f' - | '\u0121' - | '\u0123' - | '\u0125' - | '\u0127' - | '\u0129' - | '\u012b' - | '\u012d' - | '\u012f' - | '\u0131' - | '\u0133' - | '\u0135' - | '\u0137' .. '\u0138' - | '\u013a' - | '\u013c' - | '\u013e' - | '\u0140' - | '\u0142' - | '\u0144' - | '\u0146' - | '\u0148' .. '\u0149' - | '\u014b' - | '\u014d' - | '\u014f' - | '\u0151' - | '\u0153' - | '\u0155' - | '\u0157' - | '\u0159' - | '\u015b' - | '\u015d' - | '\u015f' - | '\u0161' - | '\u0163' - | '\u0165' - | '\u0167' - | '\u0169' - | '\u016b' - | '\u016d' - | '\u016f' - | '\u0171' - | '\u0173' - | '\u0175' - | '\u0177' - | '\u017a' - | '\u017c' - | '\u017e' .. '\u0180' - | '\u0183' - | '\u0185' - | '\u0188' - | '\u018c' .. '\u018d' - | '\u0192' - | '\u0195' - | '\u0199' .. '\u019b' - | '\u019e' - | '\u01a1' - | '\u01a3' - | '\u01a5' - | '\u01a8' - | '\u01aa' .. '\u01ab' - | '\u01ad' - | '\u01b0' - | '\u01b4' - | '\u01b6' - | '\u01b9' .. '\u01ba' - | '\u01bd' .. '\u01bf' - | '\u01c6' - | '\u01c9' - | '\u01cc' - | '\u01ce' - | '\u01d0' - | '\u01d2' - | '\u01d4' - | '\u01d6' - | '\u01d8' - | '\u01da' - | '\u01dc' .. '\u01dd' - | '\u01df' - | '\u01e1' - | '\u01e3' - | '\u01e5' - | '\u01e7' - | '\u01e9' - | '\u01eb' - | '\u01ed' - | '\u01ef' .. '\u01f0' - | '\u01f3' - | '\u01f5' - | '\u01f9' - | '\u01fb' - | '\u01fd' - | '\u01ff' - | '\u0201' - | '\u0203' - | '\u0205' - | '\u0207' - | '\u0209' - | '\u020b' - | '\u020d' - | '\u020f' - | '\u0211' - | '\u0213' - | '\u0215' - | '\u0217' - | '\u0219' - | '\u021b' - | '\u021d' - | '\u021f' - | '\u0221' - | '\u0223' - | '\u0225' - | '\u0227' - | '\u0229' - | '\u022b' - | '\u022d' - | '\u022f' - | '\u0231' - | '\u0233' .. '\u0239' - | '\u023c' - | '\u023f' .. '\u0240' - | '\u0242' - | '\u0247' - | '\u0249' - | '\u024b' - | '\u024d' - | '\u024f' .. '\u0293' - | '\u0295' .. '\u02af' - | '\u0371' - | '\u0373' - | '\u0377' - | '\u037b' .. '\u037d' - | '\u0390' - | '\u03ac' .. '\u03ce' - | '\u03d0' .. '\u03d1' - | '\u03d5' .. '\u03d7' - | '\u03d9' - | '\u03db' - | '\u03dd' - | '\u03df' - | '\u03e1' - | '\u03e3' - | '\u03e5' - | '\u03e7' - | '\u03e9' - | '\u03eb' - | '\u03ed' - | '\u03ef' .. '\u03f3' - | '\u03f5' - | '\u03f8' - | '\u03fb' .. '\u03fc' - | '\u0430' .. '\u045f' - | '\u0461' - | '\u0463' - | '\u0465' - | '\u0467' - | '\u0469' - | '\u046b' - | '\u046d' - | '\u046f' - | '\u0471' - | '\u0473' - | '\u0475' - | '\u0477' - | '\u0479' - | '\u047b' - | '\u047d' - | '\u047f' - | '\u0481' - | '\u048b' - | '\u048d' - | '\u048f' - | '\u0491' - | '\u0493' - | '\u0495' - | '\u0497' - | '\u0499' - | '\u049b' - | '\u049d' - | '\u049f' - | '\u04a1' - | '\u04a3' - | '\u04a5' - | '\u04a7' - | '\u04a9' - | '\u04ab' - | '\u04ad' - | '\u04af' - | '\u04b1' - | '\u04b3' - | '\u04b5' - | '\u04b7' - | '\u04b9' - | '\u04bb' - | '\u04bd' - | '\u04bf' - | '\u04c2' - | '\u04c4' - | '\u04c6' - | '\u04c8' - | '\u04ca' - | '\u04cc' - | '\u04ce' .. '\u04cf' - | '\u04d1' - | '\u04d3' - | '\u04d5' - | '\u04d7' - | '\u04d9' - | '\u04db' - | '\u04dd' - | '\u04df' - | '\u04e1' - | '\u04e3' - | '\u04e5' - | '\u04e7' - | '\u04e9' - | '\u04eb' - | '\u04ed' - | '\u04ef' - | '\u04f1' - | '\u04f3' - | '\u04f5' - | '\u04f7' - | '\u04f9' - | '\u04fb' - | '\u04fd' - | '\u04ff' - | '\u0501' - | '\u0503' - | '\u0505' - | '\u0507' - | '\u0509' - | '\u050b' - | '\u050d' - | '\u050f' - | '\u0511' - | '\u0513' - | '\u0515' - | '\u0517' - | '\u0519' - | '\u051b' - | '\u051d' - | '\u051f' - | '\u0521' - | '\u0523' - | '\u0525' - | '\u0527' - | '\u0561' .. '\u0587' - | '\u1d00' .. '\u1d2b' - | '\u1d62' .. '\u1d77' - | '\u1d79' .. '\u1d9a' - | '\u1e01' - | '\u1e03' - | '\u1e05' - | '\u1e07' - | '\u1e09' - | '\u1e0b' - | '\u1e0d' - | '\u1e0f' - | '\u1e11' - | '\u1e13' - | '\u1e15' - | '\u1e17' - | '\u1e19' - | '\u1e1b' - | '\u1e1d' - | '\u1e1f' - | '\u1e21' - | '\u1e23' - | '\u1e25' - | '\u1e27' - | '\u1e29' - | '\u1e2b' - | '\u1e2d' - | '\u1e2f' - | '\u1e31' - | '\u1e33' - | '\u1e35' - | '\u1e37' - | '\u1e39' - | '\u1e3b' - | '\u1e3d' - | '\u1e3f' - | '\u1e41' - | '\u1e43' - | '\u1e45' - | '\u1e47' - | '\u1e49' - | '\u1e4b' - | '\u1e4d' - | '\u1e4f' - | '\u1e51' - | '\u1e53' - | '\u1e55' - | '\u1e57' - | '\u1e59' - | '\u1e5b' - | '\u1e5d' - | '\u1e5f' - | '\u1e61' - | '\u1e63' - | '\u1e65' - | '\u1e67' - | '\u1e69' - | '\u1e6b' - | '\u1e6d' - | '\u1e6f' - | '\u1e71' - | '\u1e73' - | '\u1e75' - | '\u1e77' - | '\u1e79' - | '\u1e7b' - | '\u1e7d' - | '\u1e7f' - | '\u1e81' - | '\u1e83' - | '\u1e85' - | '\u1e87' - | '\u1e89' - | '\u1e8b' - | '\u1e8d' - | '\u1e8f' - | '\u1e91' - | '\u1e93' - | '\u1e95' .. '\u1e9d' - | '\u1e9f' - | '\u1ea1' - | '\u1ea3' - | '\u1ea5' - | '\u1ea7' - | '\u1ea9' - | '\u1eab' - | '\u1ead' - | '\u1eaf' - | '\u1eb1' - | '\u1eb3' - | '\u1eb5' - | '\u1eb7' - | '\u1eb9' - | '\u1ebb' - | '\u1ebd' - | '\u1ebf' - | '\u1ec1' - | '\u1ec3' - | '\u1ec5' - | '\u1ec7' - | '\u1ec9' - | '\u1ecb' - | '\u1ecd' - | '\u1ecf' - | '\u1ed1' - | '\u1ed3' - | '\u1ed5' - | '\u1ed7' - | '\u1ed9' - | '\u1edb' - | '\u1edd' - | '\u1edf' - | '\u1ee1' - | '\u1ee3' - | '\u1ee5' - | '\u1ee7' - | '\u1ee9' - | '\u1eeb' - | '\u1eed' - | '\u1eef' - | '\u1ef1' - | '\u1ef3' - | '\u1ef5' - | '\u1ef7' - | '\u1ef9' - | '\u1efb' - | '\u1efd' - | '\u1eff' .. '\u1f07' - | '\u1f10' .. '\u1f15' - | '\u1f20' .. '\u1f27' - | '\u1f30' .. '\u1f37' - | '\u1f40' .. '\u1f45' - | '\u1f50' .. '\u1f57' - | '\u1f60' .. '\u1f67' - | '\u1f70' .. '\u1f87' - | '\u1f90' .. '\u1f97' - | '\u1fa0' .. '\u1fa7' - | '\u1fb0' .. '\u1fb7' - | '\u1fbe' - | '\u1fc2' .. '\u1fc7' - | '\u1fd0' .. '\u1fd7' - | '\u1fe0' .. '\u1fe7' - | '\u1ff2' .. '\u1ff7' - | '\u210a' - | '\u210e' .. '\u210f' - | '\u2113' - | '\u212f' - | '\u2134' - | '\u2139' - | '\u213c' .. '\u213d' - | '\u2146' .. '\u2149' - | '\u214e' - | '\u2184' - | '\u2c30' .. '\u2c5e' - | '\u2c61' - | '\u2c65' .. '\u2c66' - | '\u2c68' - | '\u2c6a' - | '\u2c6c' - | '\u2c71' - | '\u2c73' .. '\u2c74' - | '\u2c76' .. '\u2c7c' - | '\u2c81' - | '\u2c83' - | '\u2c85' - | '\u2c87' - | '\u2c89' - | '\u2c8b' - | '\u2c8d' - | '\u2c8f' - | '\u2c91' - | '\u2c93' - | '\u2c95' - | '\u2c97' - | '\u2c99' - | '\u2c9b' - | '\u2c9d' - | '\u2c9f' - | '\u2ca1' - | '\u2ca3' - | '\u2ca5' - | '\u2ca7' - | '\u2ca9' - | '\u2cab' - | '\u2cad' - | '\u2caf' - | '\u2cb1' - | '\u2cb3' - | '\u2cb5' - | '\u2cb7' - | '\u2cb9' - | '\u2cbb' - | '\u2cbd' - | '\u2cbf' - | '\u2cc1' - | '\u2cc3' - | '\u2cc5' - | '\u2cc7' - | '\u2cc9' - | '\u2ccb' - | '\u2ccd' - | '\u2ccf' - | '\u2cd1' - | '\u2cd3' - | '\u2cd5' - | '\u2cd7' - | '\u2cd9' - | '\u2cdb' - | '\u2cdd' - | '\u2cdf' - | '\u2ce1' - | '\u2ce3' .. '\u2ce4' - | '\u2cec' - | '\u2cee' - | '\u2d00' .. '\u2d25' - | '\ua641' - | '\ua643' - | '\ua645' - | '\ua647' - | '\ua649' - | '\ua64b' - | '\ua64d' - | '\ua64f' - | '\ua651' - | '\ua653' - | '\ua655' - | '\ua657' - | '\ua659' - | '\ua65b' - | '\ua65d' - | '\ua65f' - | '\ua661' - | '\ua663' - | '\ua665' - | '\ua667' - | '\ua669' - | '\ua66b' - | '\ua66d' - | '\ua681' - | '\ua683' - | '\ua685' - | '\ua687' - | '\ua689' - | '\ua68b' - | '\ua68d' - | '\ua68f' - | '\ua691' - | '\ua693' - | '\ua695' - | '\ua697' - | '\ua723' - | '\ua725' - | '\ua727' - | '\ua729' - | '\ua72b' - | '\ua72d' - | '\ua72f' .. '\ua731' - | '\ua733' - | '\ua735' - | '\ua737' - | '\ua739' - | '\ua73b' - | '\ua73d' - | '\ua73f' - | '\ua741' - | '\ua743' - | '\ua745' - | '\ua747' - | '\ua749' - | '\ua74b' - | '\ua74d' - | '\ua74f' - | '\ua751' - | '\ua753' - | '\ua755' - | '\ua757' - | '\ua759' - | '\ua75b' - | '\ua75d' - | '\ua75f' - | '\ua761' - | '\ua763' - | '\ua765' - | '\ua767' - | '\ua769' - | '\ua76b' - | '\ua76d' - | '\ua76f' - | '\ua771' .. '\ua778' - | '\ua77a' - | '\ua77c' - | '\ua77f' - | '\ua781' - | '\ua783' - | '\ua785' - | '\ua787' - | '\ua78c' - | '\ua78e' - | '\ua791' - | '\ua7a1' - | '\ua7a3' - | '\ua7a5' - | '\ua7a7' - | '\ua7a9' .. '\ua7fa' - | '\ufb00' .. '\ufb17' - | '\uff41' .. '\uff5a' - | '\U00010428' .. '\U0001044f' - | '\U0001d41a' .. '\U0001d433' - | '\U0001d44e' .. '\U0001d467' - | '\U0001d482' .. '\U0001d49b' - | '\U0001d4b6' .. '\U0001d4cf' - | '\U0001d4ea' .. '\U0001d503' - | '\U0001d51e' .. '\U0001d537' - | '\U0001d552' .. '\U0001d56b' - | '\U0001d586' .. '\U0001d59f' - | '\U0001d5ba' .. '\U0001d5d3' - | '\U0001d5ee' .. '\U0001d607' - | '\U0001d622' .. '\U0001d63b' - | '\U0001d656' .. '\U0001d66f' - | '\U0001d68a' .. '\U0001d6a5' - | '\U0001d6c2' .. '\U0001d6da' - | '\U0001d6dc' .. '\U0001d6e1' - | '\U0001d6fc' .. '\U0001d714' - | '\U0001d716' .. '\U0001d71b' - | '\U0001d736' .. '\U0001d74e' - | '\U0001d750' .. '\U0001d755' - | '\U0001d770' .. '\U0001d788' - | '\U0001d78a' .. '\U0001d78f' - | '\U0001d7aa' .. '\U0001d7c2' - | '\U0001d7c4' .. '\U0001d7c9' - | '\U0001d7cb' - => true, - _ => false - }; + bsearch_range_table(c, Ll_table) } + static Lm_table : &'static [(char,char)] = &[ + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0374', '\u0374'), + ('\u037a', '\u037a'), ('\u0559', '\u0559'), + ('\u0640', '\u0640'), ('\u06e5', '\u06e6'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u081a', '\u081a'), ('\u0824', '\u0824'), + ('\u0828', '\u0828'), ('\u0971', '\u0971'), + ('\u0e46', '\u0e46'), ('\u0ec6', '\u0ec6'), + ('\u10fc', '\u10fc'), ('\u17d7', '\u17d7'), + ('\u1843', '\u1843'), ('\u1aa7', '\u1aa7'), + ('\u1c78', '\u1c7d'), ('\u1d2c', '\u1d6a'), + ('\u1d78', '\u1d78'), ('\u1d9b', '\u1dbf'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u2c7c', '\u2c7d'), + ('\u2d6f', '\u2d6f'), ('\u2e2f', '\u2e2f'), + ('\u3005', '\u3005'), ('\u3031', '\u3035'), + ('\u303b', '\u303b'), ('\u309d', '\u309e'), + ('\u30fc', '\u30fe'), ('\ua015', '\ua015'), + ('\ua4f8', '\ua4fd'), ('\ua60c', '\ua60c'), + ('\ua67f', '\ua67f'), ('\ua717', '\ua71f'), + ('\ua770', '\ua770'), ('\ua788', '\ua788'), + ('\ua7f8', '\ua7f9'), ('\ua9cf', '\ua9cf'), + ('\uaa70', '\uaa70'), ('\uaadd', '\uaadd'), + ('\uaaf3', '\uaaf4'), ('\uff70', '\uff70'), + ('\uff9e', '\uff9f'), ('\U00016f93', '\U00016f9f') + ]; + pub fn Lm(c: char) -> bool { - return match c { - '\u02b0' .. '\u02c1' - | '\u02c6' .. '\u02d1' - | '\u02e0' .. '\u02e4' - | '\u02ec' - | '\u02ee' - | '\u0374' - | '\u037a' - | '\u0559' - | '\u0640' - | '\u06e5' .. '\u06e6' - | '\u07f4' .. '\u07f5' - | '\u07fa' - | '\u081a' - | '\u0824' - | '\u0828' - | '\u0971' - | '\u0e46' - | '\u0ec6' - | '\u10fc' - | '\u17d7' - | '\u1843' - | '\u1aa7' - | '\u1c78' .. '\u1c7d' - | '\u1d2c' .. '\u1d61' - | '\u1d78' - | '\u1d9b' .. '\u1dbf' - | '\u2071' - | '\u207f' - | '\u2090' .. '\u209c' - | '\u2c7d' - | '\u2d6f' - | '\u2e2f' - | '\u3005' - | '\u3031' .. '\u3035' - | '\u303b' - | '\u309d' .. '\u309e' - | '\u30fc' .. '\u30fe' - | '\ua015' - | '\ua4f8' .. '\ua4fd' - | '\ua60c' - | '\ua67f' - | '\ua717' .. '\ua71f' - | '\ua770' - | '\ua788' - | '\ua9cf' - | '\uaa70' - | '\uaadd' - | '\uff70' - | '\uff9e' .. '\uff9f' - => true, - _ => false - }; + bsearch_range_table(c, Lm_table) } + static Lo_table : &'static [(char,char)] = &[ + ('\xaa', '\xaa'), ('\xba', '\xba'), + ('\u01bb', '\u01bb'), ('\u01c0', '\u01c3'), + ('\u0294', '\u0294'), ('\u05d0', '\u05f2'), + ('\u0620', '\u063f'), ('\u0641', '\u064a'), + ('\u066e', '\u066f'), ('\u0671', '\u06d3'), + ('\u06d5', '\u06d5'), ('\u06ee', '\u06ef'), + ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), + ('\u0710', '\u0710'), ('\u0712', '\u072f'), + ('\u074d', '\u07a5'), ('\u07b1', '\u07b1'), + ('\u07ca', '\u07ea'), ('\u0800', '\u0815'), + ('\u0840', '\u0858'), ('\u08a0', '\u08ac'), + ('\u0904', '\u0939'), ('\u093d', '\u093d'), + ('\u0950', '\u0950'), ('\u0958', '\u0961'), + ('\u0972', '\u097f'), ('\u0985', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), + ('\u09dc', '\u09e1'), ('\u09f0', '\u09f1'), + ('\u0a05', '\u0a39'), ('\u0a59', '\u0a5e'), + ('\u0a72', '\u0a74'), ('\u0a85', '\u0ab9'), + ('\u0abd', '\u0abd'), ('\u0ad0', '\u0ae1'), + ('\u0b05', '\u0b39'), ('\u0b3d', '\u0b3d'), + ('\u0b5c', '\u0b61'), ('\u0b71', '\u0b71'), + ('\u0b83', '\u0bb9'), ('\u0bd0', '\u0bd0'), + ('\u0c05', '\u0c3d'), ('\u0c58', '\u0c61'), + ('\u0c85', '\u0cb9'), ('\u0cbd', '\u0cbd'), + ('\u0cde', '\u0ce1'), ('\u0cf1', '\u0cf2'), + ('\u0d05', '\u0d3d'), ('\u0d4e', '\u0d4e'), + ('\u0d60', '\u0d61'), ('\u0d7a', '\u0d7f'), + ('\u0d85', '\u0dc6'), ('\u0e01', '\u0e30'), + ('\u0e32', '\u0e33'), ('\u0e40', '\u0e45'), + ('\u0e81', '\u0eb0'), ('\u0eb2', '\u0eb3'), + ('\u0ebd', '\u0ec4'), ('\u0edc', '\u0f00'), + ('\u0f40', '\u0f6c'), ('\u0f88', '\u0f8c'), + ('\u1000', '\u102a'), ('\u103f', '\u103f'), + ('\u1050', '\u1055'), ('\u105a', '\u105d'), + ('\u1061', '\u1061'), ('\u1065', '\u1066'), + ('\u106e', '\u1070'), ('\u1075', '\u1081'), + ('\u108e', '\u108e'), ('\u10d0', '\u10fa'), + ('\u10fd', '\u135a'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u1700', '\u1711'), + ('\u1720', '\u1731'), ('\u1740', '\u1751'), + ('\u1760', '\u1770'), ('\u1780', '\u17b3'), + ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), + ('\u1844', '\u18a8'), ('\u18aa', '\u191c'), + ('\u1950', '\u19ab'), ('\u19c1', '\u19c7'), + ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), + ('\u1b05', '\u1b33'), ('\u1b45', '\u1b4b'), + ('\u1b83', '\u1ba0'), ('\u1bae', '\u1baf'), + ('\u1bba', '\u1be5'), ('\u1c00', '\u1c23'), + ('\u1c4d', '\u1c4f'), ('\u1c5a', '\u1c77'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf5', '\u1cf6'), ('\u2135', '\u2138'), + ('\u2d30', '\u2d67'), ('\u2d80', '\u2dde'), + ('\u3006', '\u3006'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309f', '\u309f'), + ('\u30a1', '\u30fa'), ('\u30ff', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\ua014'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua500', '\ua60b'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua66e', '\ua66e'), + ('\ua6a0', '\ua6e5'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua840', '\ua873'), + ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), + ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), + ('\ua930', '\ua946'), ('\ua960', '\ua97c'), + ('\ua984', '\ua9b2'), ('\uaa00', '\uaa28'), + ('\uaa40', '\uaa42'), ('\uaa44', '\uaa4b'), + ('\uaa60', '\uaa6f'), ('\uaa71', '\uaa76'), + ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), + ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), + ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), + ('\uaac2', '\uaadc'), ('\uaae0', '\uaaea'), + ('\uaaf2', '\uaaf2'), ('\uab01', '\uabe2'), + ('\uac00', '\ud7fb'), ('\uf900', '\ufad9'), + ('\ufb1d', '\ufb1d'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufbb1'), ('\ufbd3', '\ufd3d'), + ('\ufd50', '\ufdfb'), ('\ufe70', '\ufefc'), + ('\uff66', '\uff6f'), ('\uff71', '\uff9d'), + ('\uffa0', '\uffdc'), ('\U00010000', '\U000100fa'), + ('\U00010280', '\U0001031e'), ('\U00010330', '\U00010340'), + ('\U00010342', '\U00010349'), ('\U00010380', '\U0001039d'), + ('\U000103a0', '\U000103cf'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010855'), ('\U00010900', '\U00010915'), + ('\U00010920', '\U00010939'), ('\U00010980', '\U00010a00'), + ('\U00010a10', '\U00010a33'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011003', '\U00011037'), ('\U00011083', '\U000110af'), + ('\U000110d0', '\U000110e8'), ('\U00011103', '\U00011126'), + ('\U00011183', '\U000111b2'), ('\U000111c1', '\U000111c4'), + ('\U00011680', '\U000116aa'), ('\U00012000', '\U0001236e'), + ('\U00013000', '\U00016f50'), ('\U0001b000', '\U0001b001'), + ('\U0001ee00', '\U0001eebb'), ('\U00020000', '\U0002fa1d') + ]; + pub fn Lo(c: char) -> bool { - return match c { - '\u01bb' - | '\u01c0' .. '\u01c3' - | '\u0294' - | '\u05d0' .. '\u05f2' - | '\u0620' .. '\u063f' - | '\u0641' .. '\u064a' - | '\u066e' .. '\u066f' - | '\u0671' .. '\u06d3' - | '\u06d5' - | '\u06ee' .. '\u06ef' - | '\u06fa' .. '\u06fc' - | '\u06ff' - | '\u0710' - | '\u0712' .. '\u072f' - | '\u074d' .. '\u07a5' - | '\u07b1' - | '\u07ca' .. '\u07ea' - | '\u0800' .. '\u0815' - | '\u0840' .. '\u0858' - | '\u0904' .. '\u0939' - | '\u093d' - | '\u0950' - | '\u0958' .. '\u0961' - | '\u0972' .. '\u097f' - | '\u0985' .. '\u09b9' - | '\u09bd' - | '\u09ce' - | '\u09dc' .. '\u09e1' - | '\u09f0' .. '\u09f1' - | '\u0a05' .. '\u0a39' - | '\u0a59' .. '\u0a5e' - | '\u0a72' .. '\u0a74' - | '\u0a85' .. '\u0ab9' - | '\u0abd' - | '\u0ad0' .. '\u0ae1' - | '\u0b05' .. '\u0b39' - | '\u0b3d' - | '\u0b5c' .. '\u0b61' - | '\u0b71' - | '\u0b83' .. '\u0bb9' - | '\u0bd0' - | '\u0c05' .. '\u0c3d' - | '\u0c58' .. '\u0c61' - | '\u0c85' .. '\u0cb9' - | '\u0cbd' - | '\u0cde' .. '\u0ce1' - | '\u0cf1' .. '\u0cf2' - | '\u0d05' .. '\u0d3d' - | '\u0d4e' - | '\u0d60' .. '\u0d61' - | '\u0d7a' .. '\u0d7f' - | '\u0d85' .. '\u0dc6' - | '\u0e01' .. '\u0e30' - | '\u0e32' .. '\u0e33' - | '\u0e40' .. '\u0e45' - | '\u0e81' .. '\u0eb0' - | '\u0eb2' .. '\u0eb3' - | '\u0ebd' .. '\u0ec4' - | '\u0edc' .. '\u0f00' - | '\u0f40' .. '\u0f6c' - | '\u0f88' .. '\u0f8c' - | '\u1000' .. '\u102a' - | '\u103f' - | '\u1050' .. '\u1055' - | '\u105a' .. '\u105d' - | '\u1061' - | '\u1065' .. '\u1066' - | '\u106e' .. '\u1070' - | '\u1075' .. '\u1081' - | '\u108e' - | '\u10d0' .. '\u10fa' - | '\u1100' .. '\u135a' - | '\u1380' .. '\u138f' - | '\u13a0' .. '\u13f4' - | '\u1401' .. '\u166c' - | '\u166f' .. '\u167f' - | '\u1681' .. '\u169a' - | '\u16a0' .. '\u16ea' - | '\u1700' .. '\u1711' - | '\u1720' .. '\u1731' - | '\u1740' .. '\u1751' - | '\u1760' .. '\u1770' - | '\u1780' .. '\u17b3' - | '\u17dc' - | '\u1820' .. '\u1842' - | '\u1844' .. '\u18a8' - | '\u18aa' .. '\u191c' - | '\u1950' .. '\u19ab' - | '\u19c1' .. '\u19c7' - | '\u1a00' .. '\u1a16' - | '\u1a20' .. '\u1a54' - | '\u1b05' .. '\u1b33' - | '\u1b45' .. '\u1b4b' - | '\u1b83' .. '\u1ba0' - | '\u1bae' .. '\u1baf' - | '\u1bc0' .. '\u1be5' - | '\u1c00' .. '\u1c23' - | '\u1c4d' .. '\u1c4f' - | '\u1c5a' .. '\u1c77' - | '\u1ce9' .. '\u1cec' - | '\u1cee' .. '\u1cf1' - | '\u2135' .. '\u2138' - | '\u2d30' .. '\u2d65' - | '\u2d80' .. '\u2dde' - | '\u3006' - | '\u303c' - | '\u3041' .. '\u3096' - | '\u309f' - | '\u30a1' .. '\u30fa' - | '\u30ff' .. '\u318e' - | '\u31a0' .. '\u31ba' - | '\u31f0' .. '\u31ff' - | '\u3400' .. '\u4db5' - | '\u4e00' .. '\ua014' - | '\ua016' .. '\ua48c' - | '\ua4d0' .. '\ua4f7' - | '\ua500' .. '\ua60b' - | '\ua610' .. '\ua61f' - | '\ua62a' .. '\ua62b' - | '\ua66e' - | '\ua6a0' .. '\ua6e5' - | '\ua7fb' .. '\ua801' - | '\ua803' .. '\ua805' - | '\ua807' .. '\ua80a' - | '\ua80c' .. '\ua822' - | '\ua840' .. '\ua873' - | '\ua882' .. '\ua8b3' - | '\ua8f2' .. '\ua8f7' - | '\ua8fb' - | '\ua90a' .. '\ua925' - | '\ua930' .. '\ua946' - | '\ua960' .. '\ua97c' - | '\ua984' .. '\ua9b2' - | '\uaa00' .. '\uaa28' - | '\uaa40' .. '\uaa42' - | '\uaa44' .. '\uaa4b' - | '\uaa60' .. '\uaa6f' - | '\uaa71' .. '\uaa76' - | '\uaa7a' - | '\uaa80' .. '\uaaaf' - | '\uaab1' - | '\uaab5' .. '\uaab6' - | '\uaab9' .. '\uaabd' - | '\uaac0' - | '\uaac2' .. '\uaadc' - | '\uab01' .. '\uabe2' - | '\uac00' .. '\ud7fb' - | '\uf900' .. '\ufad9' - | '\ufb1d' - | '\ufb1f' .. '\ufb28' - | '\ufb2a' .. '\ufbb1' - | '\ufbd3' .. '\ufd3d' - | '\ufd50' .. '\ufdfb' - | '\ufe70' .. '\ufefc' - | '\uff66' .. '\uff6f' - | '\uff71' .. '\uff9d' - | '\uffa0' .. '\uffdc' - | '\U00010000' .. '\U000100fa' - | '\U00010280' .. '\U0001031e' - | '\U00010330' .. '\U00010340' - | '\U00010342' .. '\U00010349' - | '\U00010380' .. '\U0001039d' - | '\U000103a0' .. '\U000103cf' - | '\U00010450' .. '\U0001049d' - | '\U00010800' .. '\U00010855' - | '\U00010900' .. '\U00010915' - | '\U00010920' .. '\U00010939' - | '\U00010a00' - | '\U00010a10' .. '\U00010a33' - | '\U00010a60' .. '\U00010a7c' - | '\U00010b00' .. '\U00010b35' - | '\U00010b40' .. '\U00010b55' - | '\U00010b60' .. '\U00010b72' - | '\U00010c00' .. '\U00010c48' - | '\U00011003' .. '\U00011037' - | '\U00011083' .. '\U000110af' - | '\U00012000' .. '\U0001236e' - | '\U00013000' .. '\U0001b001' - | '\U00020000' .. '\U0002fa1d' - => true, - _ => false - }; + bsearch_range_table(c, Lo_table) } + static Lt_table : &'static [(char,char)] = &[ + ('\u01c5', '\u01c5'), ('\u01c8', '\u01c8'), + ('\u01cb', '\u01cb'), ('\u01f2', '\u01f2'), + ('\u1f88', '\u1f8f'), ('\u1f98', '\u1f9f'), + ('\u1fa8', '\u1faf'), ('\u1fbc', '\u1fbc'), + ('\u1fcc', '\u1fcc'), ('\u1ffc', '\u1ffc') + ]; + pub fn Lt(c: char) -> bool { - return match c { - '\u01c5' - | '\u01c8' - | '\u01cb' - | '\u01f2' - | '\u1f88' .. '\u1f8f' - | '\u1f98' .. '\u1f9f' - | '\u1fa8' .. '\u1faf' - | '\u1fbc' - | '\u1fcc' - | '\u1ffc' - => true, - _ => false - }; + bsearch_range_table(c, Lt_table) } + static Lu_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\xc0', '\xd6'), + ('\xd8', '\xde'), ('\u0100', '\u0100'), + ('\u0102', '\u0102'), ('\u0104', '\u0104'), + ('\u0106', '\u0106'), ('\u0108', '\u0108'), + ('\u010a', '\u010a'), ('\u010c', '\u010c'), + ('\u010e', '\u010e'), ('\u0110', '\u0110'), + ('\u0112', '\u0112'), ('\u0114', '\u0114'), + ('\u0116', '\u0116'), ('\u0118', '\u0118'), + ('\u011a', '\u011a'), ('\u011c', '\u011c'), + ('\u011e', '\u011e'), ('\u0120', '\u0120'), + ('\u0122', '\u0122'), ('\u0124', '\u0124'), + ('\u0126', '\u0126'), ('\u0128', '\u0128'), + ('\u012a', '\u012a'), ('\u012c', '\u012c'), + ('\u012e', '\u012e'), ('\u0130', '\u0130'), + ('\u0132', '\u0132'), ('\u0134', '\u0134'), + ('\u0136', '\u0136'), ('\u0139', '\u0139'), + ('\u013b', '\u013b'), ('\u013d', '\u013d'), + ('\u013f', '\u013f'), ('\u0141', '\u0141'), + ('\u0143', '\u0143'), ('\u0145', '\u0145'), + ('\u0147', '\u0147'), ('\u014a', '\u014a'), + ('\u014c', '\u014c'), ('\u014e', '\u014e'), + ('\u0150', '\u0150'), ('\u0152', '\u0152'), + ('\u0154', '\u0154'), ('\u0156', '\u0156'), + ('\u0158', '\u0158'), ('\u015a', '\u015a'), + ('\u015c', '\u015c'), ('\u015e', '\u015e'), + ('\u0160', '\u0160'), ('\u0162', '\u0162'), + ('\u0164', '\u0164'), ('\u0166', '\u0166'), + ('\u0168', '\u0168'), ('\u016a', '\u016a'), + ('\u016c', '\u016c'), ('\u016e', '\u016e'), + ('\u0170', '\u0170'), ('\u0172', '\u0172'), + ('\u0174', '\u0174'), ('\u0176', '\u0176'), + ('\u0178', '\u0179'), ('\u017b', '\u017b'), + ('\u017d', '\u017d'), ('\u0181', '\u0182'), + ('\u0184', '\u0184'), ('\u0186', '\u0187'), + ('\u0189', '\u018b'), ('\u018e', '\u0191'), + ('\u0193', '\u0194'), ('\u0196', '\u0198'), + ('\u019c', '\u019d'), ('\u019f', '\u01a0'), + ('\u01a2', '\u01a2'), ('\u01a4', '\u01a4'), + ('\u01a6', '\u01a7'), ('\u01a9', '\u01a9'), + ('\u01ac', '\u01ac'), ('\u01ae', '\u01af'), + ('\u01b1', '\u01b3'), ('\u01b5', '\u01b5'), + ('\u01b7', '\u01b8'), ('\u01bc', '\u01bc'), + ('\u01c4', '\u01c4'), ('\u01c7', '\u01c7'), + ('\u01ca', '\u01ca'), ('\u01cd', '\u01cd'), + ('\u01cf', '\u01cf'), ('\u01d1', '\u01d1'), + ('\u01d3', '\u01d3'), ('\u01d5', '\u01d5'), + ('\u01d7', '\u01d7'), ('\u01d9', '\u01d9'), + ('\u01db', '\u01db'), ('\u01de', '\u01de'), + ('\u01e0', '\u01e0'), ('\u01e2', '\u01e2'), + ('\u01e4', '\u01e4'), ('\u01e6', '\u01e6'), + ('\u01e8', '\u01e8'), ('\u01ea', '\u01ea'), + ('\u01ec', '\u01ec'), ('\u01ee', '\u01ee'), + ('\u01f1', '\u01f1'), ('\u01f4', '\u01f4'), + ('\u01f6', '\u01f8'), ('\u01fa', '\u01fa'), + ('\u01fc', '\u01fc'), ('\u01fe', '\u01fe'), + ('\u0200', '\u0200'), ('\u0202', '\u0202'), + ('\u0204', '\u0204'), ('\u0206', '\u0206'), + ('\u0208', '\u0208'), ('\u020a', '\u020a'), + ('\u020c', '\u020c'), ('\u020e', '\u020e'), + ('\u0210', '\u0210'), ('\u0212', '\u0212'), + ('\u0214', '\u0214'), ('\u0216', '\u0216'), + ('\u0218', '\u0218'), ('\u021a', '\u021a'), + ('\u021c', '\u021c'), ('\u021e', '\u021e'), + ('\u0220', '\u0220'), ('\u0222', '\u0222'), + ('\u0224', '\u0224'), ('\u0226', '\u0226'), + ('\u0228', '\u0228'), ('\u022a', '\u022a'), + ('\u022c', '\u022c'), ('\u022e', '\u022e'), + ('\u0230', '\u0230'), ('\u0232', '\u0232'), + ('\u023a', '\u023b'), ('\u023d', '\u023e'), + ('\u0241', '\u0241'), ('\u0243', '\u0246'), + ('\u0248', '\u0248'), ('\u024a', '\u024a'), + ('\u024c', '\u024c'), ('\u024e', '\u024e'), + ('\u0370', '\u0370'), ('\u0372', '\u0372'), + ('\u0376', '\u0376'), ('\u0386', '\u0386'), + ('\u0388', '\u038f'), ('\u0391', '\u03ab'), + ('\u03cf', '\u03cf'), ('\u03d2', '\u03d4'), + ('\u03d8', '\u03d8'), ('\u03da', '\u03da'), + ('\u03dc', '\u03dc'), ('\u03de', '\u03de'), + ('\u03e0', '\u03e0'), ('\u03e2', '\u03e2'), + ('\u03e4', '\u03e4'), ('\u03e6', '\u03e6'), + ('\u03e8', '\u03e8'), ('\u03ea', '\u03ea'), + ('\u03ec', '\u03ec'), ('\u03ee', '\u03ee'), + ('\u03f4', '\u03f4'), ('\u03f7', '\u03f7'), + ('\u03f9', '\u03fa'), ('\u03fd', '\u042f'), + ('\u0460', '\u0460'), ('\u0462', '\u0462'), + ('\u0464', '\u0464'), ('\u0466', '\u0466'), + ('\u0468', '\u0468'), ('\u046a', '\u046a'), + ('\u046c', '\u046c'), ('\u046e', '\u046e'), + ('\u0470', '\u0470'), ('\u0472', '\u0472'), + ('\u0474', '\u0474'), ('\u0476', '\u0476'), + ('\u0478', '\u0478'), ('\u047a', '\u047a'), + ('\u047c', '\u047c'), ('\u047e', '\u047e'), + ('\u0480', '\u0480'), ('\u048a', '\u048a'), + ('\u048c', '\u048c'), ('\u048e', '\u048e'), + ('\u0490', '\u0490'), ('\u0492', '\u0492'), + ('\u0494', '\u0494'), ('\u0496', '\u0496'), + ('\u0498', '\u0498'), ('\u049a', '\u049a'), + ('\u049c', '\u049c'), ('\u049e', '\u049e'), + ('\u04a0', '\u04a0'), ('\u04a2', '\u04a2'), + ('\u04a4', '\u04a4'), ('\u04a6', '\u04a6'), + ('\u04a8', '\u04a8'), ('\u04aa', '\u04aa'), + ('\u04ac', '\u04ac'), ('\u04ae', '\u04ae'), + ('\u04b0', '\u04b0'), ('\u04b2', '\u04b2'), + ('\u04b4', '\u04b4'), ('\u04b6', '\u04b6'), + ('\u04b8', '\u04b8'), ('\u04ba', '\u04ba'), + ('\u04bc', '\u04bc'), ('\u04be', '\u04be'), + ('\u04c0', '\u04c1'), ('\u04c3', '\u04c3'), + ('\u04c5', '\u04c5'), ('\u04c7', '\u04c7'), + ('\u04c9', '\u04c9'), ('\u04cb', '\u04cb'), + ('\u04cd', '\u04cd'), ('\u04d0', '\u04d0'), + ('\u04d2', '\u04d2'), ('\u04d4', '\u04d4'), + ('\u04d6', '\u04d6'), ('\u04d8', '\u04d8'), + ('\u04da', '\u04da'), ('\u04dc', '\u04dc'), + ('\u04de', '\u04de'), ('\u04e0', '\u04e0'), + ('\u04e2', '\u04e2'), ('\u04e4', '\u04e4'), + ('\u04e6', '\u04e6'), ('\u04e8', '\u04e8'), + ('\u04ea', '\u04ea'), ('\u04ec', '\u04ec'), + ('\u04ee', '\u04ee'), ('\u04f0', '\u04f0'), + ('\u04f2', '\u04f2'), ('\u04f4', '\u04f4'), + ('\u04f6', '\u04f6'), ('\u04f8', '\u04f8'), + ('\u04fa', '\u04fa'), ('\u04fc', '\u04fc'), + ('\u04fe', '\u04fe'), ('\u0500', '\u0500'), + ('\u0502', '\u0502'), ('\u0504', '\u0504'), + ('\u0506', '\u0506'), ('\u0508', '\u0508'), + ('\u050a', '\u050a'), ('\u050c', '\u050c'), + ('\u050e', '\u050e'), ('\u0510', '\u0510'), + ('\u0512', '\u0512'), ('\u0514', '\u0514'), + ('\u0516', '\u0516'), ('\u0518', '\u0518'), + ('\u051a', '\u051a'), ('\u051c', '\u051c'), + ('\u051e', '\u051e'), ('\u0520', '\u0520'), + ('\u0522', '\u0522'), ('\u0524', '\u0524'), + ('\u0526', '\u0526'), ('\u0531', '\u0556'), + ('\u10a0', '\u10cd'), ('\u1e00', '\u1e00'), + ('\u1e02', '\u1e02'), ('\u1e04', '\u1e04'), + ('\u1e06', '\u1e06'), ('\u1e08', '\u1e08'), + ('\u1e0a', '\u1e0a'), ('\u1e0c', '\u1e0c'), + ('\u1e0e', '\u1e0e'), ('\u1e10', '\u1e10'), + ('\u1e12', '\u1e12'), ('\u1e14', '\u1e14'), + ('\u1e16', '\u1e16'), ('\u1e18', '\u1e18'), + ('\u1e1a', '\u1e1a'), ('\u1e1c', '\u1e1c'), + ('\u1e1e', '\u1e1e'), ('\u1e20', '\u1e20'), + ('\u1e22', '\u1e22'), ('\u1e24', '\u1e24'), + ('\u1e26', '\u1e26'), ('\u1e28', '\u1e28'), + ('\u1e2a', '\u1e2a'), ('\u1e2c', '\u1e2c'), + ('\u1e2e', '\u1e2e'), ('\u1e30', '\u1e30'), + ('\u1e32', '\u1e32'), ('\u1e34', '\u1e34'), + ('\u1e36', '\u1e36'), ('\u1e38', '\u1e38'), + ('\u1e3a', '\u1e3a'), ('\u1e3c', '\u1e3c'), + ('\u1e3e', '\u1e3e'), ('\u1e40', '\u1e40'), + ('\u1e42', '\u1e42'), ('\u1e44', '\u1e44'), + ('\u1e46', '\u1e46'), ('\u1e48', '\u1e48'), + ('\u1e4a', '\u1e4a'), ('\u1e4c', '\u1e4c'), + ('\u1e4e', '\u1e4e'), ('\u1e50', '\u1e50'), + ('\u1e52', '\u1e52'), ('\u1e54', '\u1e54'), + ('\u1e56', '\u1e56'), ('\u1e58', '\u1e58'), + ('\u1e5a', '\u1e5a'), ('\u1e5c', '\u1e5c'), + ('\u1e5e', '\u1e5e'), ('\u1e60', '\u1e60'), + ('\u1e62', '\u1e62'), ('\u1e64', '\u1e64'), + ('\u1e66', '\u1e66'), ('\u1e68', '\u1e68'), + ('\u1e6a', '\u1e6a'), ('\u1e6c', '\u1e6c'), + ('\u1e6e', '\u1e6e'), ('\u1e70', '\u1e70'), + ('\u1e72', '\u1e72'), ('\u1e74', '\u1e74'), + ('\u1e76', '\u1e76'), ('\u1e78', '\u1e78'), + ('\u1e7a', '\u1e7a'), ('\u1e7c', '\u1e7c'), + ('\u1e7e', '\u1e7e'), ('\u1e80', '\u1e80'), + ('\u1e82', '\u1e82'), ('\u1e84', '\u1e84'), + ('\u1e86', '\u1e86'), ('\u1e88', '\u1e88'), + ('\u1e8a', '\u1e8a'), ('\u1e8c', '\u1e8c'), + ('\u1e8e', '\u1e8e'), ('\u1e90', '\u1e90'), + ('\u1e92', '\u1e92'), ('\u1e94', '\u1e94'), + ('\u1e9e', '\u1e9e'), ('\u1ea0', '\u1ea0'), + ('\u1ea2', '\u1ea2'), ('\u1ea4', '\u1ea4'), + ('\u1ea6', '\u1ea6'), ('\u1ea8', '\u1ea8'), + ('\u1eaa', '\u1eaa'), ('\u1eac', '\u1eac'), + ('\u1eae', '\u1eae'), ('\u1eb0', '\u1eb0'), + ('\u1eb2', '\u1eb2'), ('\u1eb4', '\u1eb4'), + ('\u1eb6', '\u1eb6'), ('\u1eb8', '\u1eb8'), + ('\u1eba', '\u1eba'), ('\u1ebc', '\u1ebc'), + ('\u1ebe', '\u1ebe'), ('\u1ec0', '\u1ec0'), + ('\u1ec2', '\u1ec2'), ('\u1ec4', '\u1ec4'), + ('\u1ec6', '\u1ec6'), ('\u1ec8', '\u1ec8'), + ('\u1eca', '\u1eca'), ('\u1ecc', '\u1ecc'), + ('\u1ece', '\u1ece'), ('\u1ed0', '\u1ed0'), + ('\u1ed2', '\u1ed2'), ('\u1ed4', '\u1ed4'), + ('\u1ed6', '\u1ed6'), ('\u1ed8', '\u1ed8'), + ('\u1eda', '\u1eda'), ('\u1edc', '\u1edc'), + ('\u1ede', '\u1ede'), ('\u1ee0', '\u1ee0'), + ('\u1ee2', '\u1ee2'), ('\u1ee4', '\u1ee4'), + ('\u1ee6', '\u1ee6'), ('\u1ee8', '\u1ee8'), + ('\u1eea', '\u1eea'), ('\u1eec', '\u1eec'), + ('\u1eee', '\u1eee'), ('\u1ef0', '\u1ef0'), + ('\u1ef2', '\u1ef2'), ('\u1ef4', '\u1ef4'), + ('\u1ef6', '\u1ef6'), ('\u1ef8', '\u1ef8'), + ('\u1efa', '\u1efa'), ('\u1efc', '\u1efc'), + ('\u1efe', '\u1efe'), ('\u1f08', '\u1f0f'), + ('\u1f18', '\u1f1d'), ('\u1f28', '\u1f2f'), + ('\u1f38', '\u1f3f'), ('\u1f48', '\u1f4d'), + ('\u1f59', '\u1f5f'), ('\u1f68', '\u1f6f'), + ('\u1fb8', '\u1fbb'), ('\u1fc8', '\u1fcb'), + ('\u1fd8', '\u1fdb'), ('\u1fe8', '\u1fec'), + ('\u1ff8', '\u1ffb'), ('\u2102', '\u2102'), + ('\u2107', '\u2107'), ('\u210b', '\u210d'), + ('\u2110', '\u2112'), ('\u2115', '\u2115'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u2130', '\u2133'), + ('\u213e', '\u213f'), ('\u2145', '\u2145'), + ('\u2183', '\u2183'), ('\u2c00', '\u2c2e'), + ('\u2c60', '\u2c60'), ('\u2c62', '\u2c64'), + ('\u2c67', '\u2c67'), ('\u2c69', '\u2c69'), + ('\u2c6b', '\u2c6b'), ('\u2c6d', '\u2c70'), + ('\u2c72', '\u2c72'), ('\u2c75', '\u2c75'), + ('\u2c7e', '\u2c80'), ('\u2c82', '\u2c82'), + ('\u2c84', '\u2c84'), ('\u2c86', '\u2c86'), + ('\u2c88', '\u2c88'), ('\u2c8a', '\u2c8a'), + ('\u2c8c', '\u2c8c'), ('\u2c8e', '\u2c8e'), + ('\u2c90', '\u2c90'), ('\u2c92', '\u2c92'), + ('\u2c94', '\u2c94'), ('\u2c96', '\u2c96'), + ('\u2c98', '\u2c98'), ('\u2c9a', '\u2c9a'), + ('\u2c9c', '\u2c9c'), ('\u2c9e', '\u2c9e'), + ('\u2ca0', '\u2ca0'), ('\u2ca2', '\u2ca2'), + ('\u2ca4', '\u2ca4'), ('\u2ca6', '\u2ca6'), + ('\u2ca8', '\u2ca8'), ('\u2caa', '\u2caa'), + ('\u2cac', '\u2cac'), ('\u2cae', '\u2cae'), + ('\u2cb0', '\u2cb0'), ('\u2cb2', '\u2cb2'), + ('\u2cb4', '\u2cb4'), ('\u2cb6', '\u2cb6'), + ('\u2cb8', '\u2cb8'), ('\u2cba', '\u2cba'), + ('\u2cbc', '\u2cbc'), ('\u2cbe', '\u2cbe'), + ('\u2cc0', '\u2cc0'), ('\u2cc2', '\u2cc2'), + ('\u2cc4', '\u2cc4'), ('\u2cc6', '\u2cc6'), + ('\u2cc8', '\u2cc8'), ('\u2cca', '\u2cca'), + ('\u2ccc', '\u2ccc'), ('\u2cce', '\u2cce'), + ('\u2cd0', '\u2cd0'), ('\u2cd2', '\u2cd2'), + ('\u2cd4', '\u2cd4'), ('\u2cd6', '\u2cd6'), + ('\u2cd8', '\u2cd8'), ('\u2cda', '\u2cda'), + ('\u2cdc', '\u2cdc'), ('\u2cde', '\u2cde'), + ('\u2ce0', '\u2ce0'), ('\u2ce2', '\u2ce2'), + ('\u2ceb', '\u2ceb'), ('\u2ced', '\u2ced'), + ('\u2cf2', '\u2cf2'), ('\ua640', '\ua640'), + ('\ua642', '\ua642'), ('\ua644', '\ua644'), + ('\ua646', '\ua646'), ('\ua648', '\ua648'), + ('\ua64a', '\ua64a'), ('\ua64c', '\ua64c'), + ('\ua64e', '\ua64e'), ('\ua650', '\ua650'), + ('\ua652', '\ua652'), ('\ua654', '\ua654'), + ('\ua656', '\ua656'), ('\ua658', '\ua658'), + ('\ua65a', '\ua65a'), ('\ua65c', '\ua65c'), + ('\ua65e', '\ua65e'), ('\ua660', '\ua660'), + ('\ua662', '\ua662'), ('\ua664', '\ua664'), + ('\ua666', '\ua666'), ('\ua668', '\ua668'), + ('\ua66a', '\ua66a'), ('\ua66c', '\ua66c'), + ('\ua680', '\ua680'), ('\ua682', '\ua682'), + ('\ua684', '\ua684'), ('\ua686', '\ua686'), + ('\ua688', '\ua688'), ('\ua68a', '\ua68a'), + ('\ua68c', '\ua68c'), ('\ua68e', '\ua68e'), + ('\ua690', '\ua690'), ('\ua692', '\ua692'), + ('\ua694', '\ua694'), ('\ua696', '\ua696'), + ('\ua722', '\ua722'), ('\ua724', '\ua724'), + ('\ua726', '\ua726'), ('\ua728', '\ua728'), + ('\ua72a', '\ua72a'), ('\ua72c', '\ua72c'), + ('\ua72e', '\ua72e'), ('\ua732', '\ua732'), + ('\ua734', '\ua734'), ('\ua736', '\ua736'), + ('\ua738', '\ua738'), ('\ua73a', '\ua73a'), + ('\ua73c', '\ua73c'), ('\ua73e', '\ua73e'), + ('\ua740', '\ua740'), ('\ua742', '\ua742'), + ('\ua744', '\ua744'), ('\ua746', '\ua746'), + ('\ua748', '\ua748'), ('\ua74a', '\ua74a'), + ('\ua74c', '\ua74c'), ('\ua74e', '\ua74e'), + ('\ua750', '\ua750'), ('\ua752', '\ua752'), + ('\ua754', '\ua754'), ('\ua756', '\ua756'), + ('\ua758', '\ua758'), ('\ua75a', '\ua75a'), + ('\ua75c', '\ua75c'), ('\ua75e', '\ua75e'), + ('\ua760', '\ua760'), ('\ua762', '\ua762'), + ('\ua764', '\ua764'), ('\ua766', '\ua766'), + ('\ua768', '\ua768'), ('\ua76a', '\ua76a'), + ('\ua76c', '\ua76c'), ('\ua76e', '\ua76e'), + ('\ua779', '\ua779'), ('\ua77b', '\ua77b'), + ('\ua77d', '\ua77e'), ('\ua780', '\ua780'), + ('\ua782', '\ua782'), ('\ua784', '\ua784'), + ('\ua786', '\ua786'), ('\ua78b', '\ua78b'), + ('\ua78d', '\ua78d'), ('\ua790', '\ua790'), + ('\ua792', '\ua792'), ('\ua7a0', '\ua7a0'), + ('\ua7a2', '\ua7a2'), ('\ua7a4', '\ua7a4'), + ('\ua7a6', '\ua7a6'), ('\ua7a8', '\ua7a8'), + ('\ua7aa', '\ua7aa'), ('\uff21', '\uff3a'), + ('\U00010400', '\U00010427'), ('\U0001d400', '\U0001d419'), + ('\U0001d434', '\U0001d44d'), ('\U0001d468', '\U0001d481'), + ('\U0001d49c', '\U0001d4b5'), ('\U0001d4d0', '\U0001d4e9'), + ('\U0001d504', '\U0001d51c'), ('\U0001d538', '\U0001d550'), + ('\U0001d56c', '\U0001d585'), ('\U0001d5a0', '\U0001d5b9'), + ('\U0001d5d4', '\U0001d5ed'), ('\U0001d608', '\U0001d621'), + ('\U0001d63c', '\U0001d655'), ('\U0001d670', '\U0001d689'), + ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6e2', '\U0001d6fa'), + ('\U0001d71c', '\U0001d734'), ('\U0001d756', '\U0001d76e'), + ('\U0001d790', '\U0001d7a8'), ('\U0001d7ca', '\U0001d7ca') + ]; + pub fn Lu(c: char) -> bool { - return match c { - '\x41' .. '\x5a' - | '\xc0' .. '\xd6' - | '\xd8' .. '\xde' - | '\u0100' - | '\u0102' - | '\u0104' - | '\u0106' - | '\u0108' - | '\u010a' - | '\u010c' - | '\u010e' - | '\u0110' - | '\u0112' - | '\u0114' - | '\u0116' - | '\u0118' - | '\u011a' - | '\u011c' - | '\u011e' - | '\u0120' - | '\u0122' - | '\u0124' - | '\u0126' - | '\u0128' - | '\u012a' - | '\u012c' - | '\u012e' - | '\u0130' - | '\u0132' - | '\u0134' - | '\u0136' - | '\u0139' - | '\u013b' - | '\u013d' - | '\u013f' - | '\u0141' - | '\u0143' - | '\u0145' - | '\u0147' - | '\u014a' - | '\u014c' - | '\u014e' - | '\u0150' - | '\u0152' - | '\u0154' - | '\u0156' - | '\u0158' - | '\u015a' - | '\u015c' - | '\u015e' - | '\u0160' - | '\u0162' - | '\u0164' - | '\u0166' - | '\u0168' - | '\u016a' - | '\u016c' - | '\u016e' - | '\u0170' - | '\u0172' - | '\u0174' - | '\u0176' - | '\u0178' .. '\u0179' - | '\u017b' - | '\u017d' - | '\u0181' .. '\u0182' - | '\u0184' - | '\u0186' .. '\u0187' - | '\u0189' .. '\u018b' - | '\u018e' .. '\u0191' - | '\u0193' .. '\u0194' - | '\u0196' .. '\u0198' - | '\u019c' .. '\u019d' - | '\u019f' .. '\u01a0' - | '\u01a2' - | '\u01a4' - | '\u01a6' .. '\u01a7' - | '\u01a9' - | '\u01ac' - | '\u01ae' .. '\u01af' - | '\u01b1' .. '\u01b3' - | '\u01b5' - | '\u01b7' .. '\u01b8' - | '\u01bc' - | '\u01c4' - | '\u01c7' - | '\u01ca' - | '\u01cd' - | '\u01cf' - | '\u01d1' - | '\u01d3' - | '\u01d5' - | '\u01d7' - | '\u01d9' - | '\u01db' - | '\u01de' - | '\u01e0' - | '\u01e2' - | '\u01e4' - | '\u01e6' - | '\u01e8' - | '\u01ea' - | '\u01ec' - | '\u01ee' - | '\u01f1' - | '\u01f4' - | '\u01f6' .. '\u01f8' - | '\u01fa' - | '\u01fc' - | '\u01fe' - | '\u0200' - | '\u0202' - | '\u0204' - | '\u0206' - | '\u0208' - | '\u020a' - | '\u020c' - | '\u020e' - | '\u0210' - | '\u0212' - | '\u0214' - | '\u0216' - | '\u0218' - | '\u021a' - | '\u021c' - | '\u021e' - | '\u0220' - | '\u0222' - | '\u0224' - | '\u0226' - | '\u0228' - | '\u022a' - | '\u022c' - | '\u022e' - | '\u0230' - | '\u0232' - | '\u023a' .. '\u023b' - | '\u023d' .. '\u023e' - | '\u0241' - | '\u0243' .. '\u0246' - | '\u0248' - | '\u024a' - | '\u024c' - | '\u024e' - | '\u0370' - | '\u0372' - | '\u0376' - | '\u0386' - | '\u0388' .. '\u038f' - | '\u0391' .. '\u03ab' - | '\u03cf' - | '\u03d2' .. '\u03d4' - | '\u03d8' - | '\u03da' - | '\u03dc' - | '\u03de' - | '\u03e0' - | '\u03e2' - | '\u03e4' - | '\u03e6' - | '\u03e8' - | '\u03ea' - | '\u03ec' - | '\u03ee' - | '\u03f4' - | '\u03f7' - | '\u03f9' .. '\u03fa' - | '\u03fd' .. '\u042f' - | '\u0460' - | '\u0462' - | '\u0464' - | '\u0466' - | '\u0468' - | '\u046a' - | '\u046c' - | '\u046e' - | '\u0470' - | '\u0472' - | '\u0474' - | '\u0476' - | '\u0478' - | '\u047a' - | '\u047c' - | '\u047e' - | '\u0480' - | '\u048a' - | '\u048c' - | '\u048e' - | '\u0490' - | '\u0492' - | '\u0494' - | '\u0496' - | '\u0498' - | '\u049a' - | '\u049c' - | '\u049e' - | '\u04a0' - | '\u04a2' - | '\u04a4' - | '\u04a6' - | '\u04a8' - | '\u04aa' - | '\u04ac' - | '\u04ae' - | '\u04b0' - | '\u04b2' - | '\u04b4' - | '\u04b6' - | '\u04b8' - | '\u04ba' - | '\u04bc' - | '\u04be' - | '\u04c0' .. '\u04c1' - | '\u04c3' - | '\u04c5' - | '\u04c7' - | '\u04c9' - | '\u04cb' - | '\u04cd' - | '\u04d0' - | '\u04d2' - | '\u04d4' - | '\u04d6' - | '\u04d8' - | '\u04da' - | '\u04dc' - | '\u04de' - | '\u04e0' - | '\u04e2' - | '\u04e4' - | '\u04e6' - | '\u04e8' - | '\u04ea' - | '\u04ec' - | '\u04ee' - | '\u04f0' - | '\u04f2' - | '\u04f4' - | '\u04f6' - | '\u04f8' - | '\u04fa' - | '\u04fc' - | '\u04fe' - | '\u0500' - | '\u0502' - | '\u0504' - | '\u0506' - | '\u0508' - | '\u050a' - | '\u050c' - | '\u050e' - | '\u0510' - | '\u0512' - | '\u0514' - | '\u0516' - | '\u0518' - | '\u051a' - | '\u051c' - | '\u051e' - | '\u0520' - | '\u0522' - | '\u0524' - | '\u0526' - | '\u0531' .. '\u0556' - | '\u10a0' .. '\u10c5' - | '\u1e00' - | '\u1e02' - | '\u1e04' - | '\u1e06' - | '\u1e08' - | '\u1e0a' - | '\u1e0c' - | '\u1e0e' - | '\u1e10' - | '\u1e12' - | '\u1e14' - | '\u1e16' - | '\u1e18' - | '\u1e1a' - | '\u1e1c' - | '\u1e1e' - | '\u1e20' - | '\u1e22' - | '\u1e24' - | '\u1e26' - | '\u1e28' - | '\u1e2a' - | '\u1e2c' - | '\u1e2e' - | '\u1e30' - | '\u1e32' - | '\u1e34' - | '\u1e36' - | '\u1e38' - | '\u1e3a' - | '\u1e3c' - | '\u1e3e' - | '\u1e40' - | '\u1e42' - | '\u1e44' - | '\u1e46' - | '\u1e48' - | '\u1e4a' - | '\u1e4c' - | '\u1e4e' - | '\u1e50' - | '\u1e52' - | '\u1e54' - | '\u1e56' - | '\u1e58' - | '\u1e5a' - | '\u1e5c' - | '\u1e5e' - | '\u1e60' - | '\u1e62' - | '\u1e64' - | '\u1e66' - | '\u1e68' - | '\u1e6a' - | '\u1e6c' - | '\u1e6e' - | '\u1e70' - | '\u1e72' - | '\u1e74' - | '\u1e76' - | '\u1e78' - | '\u1e7a' - | '\u1e7c' - | '\u1e7e' - | '\u1e80' - | '\u1e82' - | '\u1e84' - | '\u1e86' - | '\u1e88' - | '\u1e8a' - | '\u1e8c' - | '\u1e8e' - | '\u1e90' - | '\u1e92' - | '\u1e94' - | '\u1e9e' - | '\u1ea0' - | '\u1ea2' - | '\u1ea4' - | '\u1ea6' - | '\u1ea8' - | '\u1eaa' - | '\u1eac' - | '\u1eae' - | '\u1eb0' - | '\u1eb2' - | '\u1eb4' - | '\u1eb6' - | '\u1eb8' - | '\u1eba' - | '\u1ebc' - | '\u1ebe' - | '\u1ec0' - | '\u1ec2' - | '\u1ec4' - | '\u1ec6' - | '\u1ec8' - | '\u1eca' - | '\u1ecc' - | '\u1ece' - | '\u1ed0' - | '\u1ed2' - | '\u1ed4' - | '\u1ed6' - | '\u1ed8' - | '\u1eda' - | '\u1edc' - | '\u1ede' - | '\u1ee0' - | '\u1ee2' - | '\u1ee4' - | '\u1ee6' - | '\u1ee8' - | '\u1eea' - | '\u1eec' - | '\u1eee' - | '\u1ef0' - | '\u1ef2' - | '\u1ef4' - | '\u1ef6' - | '\u1ef8' - | '\u1efa' - | '\u1efc' - | '\u1efe' - | '\u1f08' .. '\u1f0f' - | '\u1f18' .. '\u1f1d' - | '\u1f28' .. '\u1f2f' - | '\u1f38' .. '\u1f3f' - | '\u1f48' .. '\u1f4d' - | '\u1f59' .. '\u1f5f' - | '\u1f68' .. '\u1f6f' - | '\u1fb8' .. '\u1fbb' - | '\u1fc8' .. '\u1fcb' - | '\u1fd8' .. '\u1fdb' - | '\u1fe8' .. '\u1fec' - | '\u1ff8' .. '\u1ffb' - | '\u2102' - | '\u2107' - | '\u210b' .. '\u210d' - | '\u2110' .. '\u2112' - | '\u2115' - | '\u2119' .. '\u211d' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212a' .. '\u212d' - | '\u2130' .. '\u2133' - | '\u213e' .. '\u213f' - | '\u2145' - | '\u2183' - | '\u2c00' .. '\u2c2e' - | '\u2c60' - | '\u2c62' .. '\u2c64' - | '\u2c67' - | '\u2c69' - | '\u2c6b' - | '\u2c6d' .. '\u2c70' - | '\u2c72' - | '\u2c75' - | '\u2c7e' .. '\u2c80' - | '\u2c82' - | '\u2c84' - | '\u2c86' - | '\u2c88' - | '\u2c8a' - | '\u2c8c' - | '\u2c8e' - | '\u2c90' - | '\u2c92' - | '\u2c94' - | '\u2c96' - | '\u2c98' - | '\u2c9a' - | '\u2c9c' - | '\u2c9e' - | '\u2ca0' - | '\u2ca2' - | '\u2ca4' - | '\u2ca6' - | '\u2ca8' - | '\u2caa' - | '\u2cac' - | '\u2cae' - | '\u2cb0' - | '\u2cb2' - | '\u2cb4' - | '\u2cb6' - | '\u2cb8' - | '\u2cba' - | '\u2cbc' - | '\u2cbe' - | '\u2cc0' - | '\u2cc2' - | '\u2cc4' - | '\u2cc6' - | '\u2cc8' - | '\u2cca' - | '\u2ccc' - | '\u2cce' - | '\u2cd0' - | '\u2cd2' - | '\u2cd4' - | '\u2cd6' - | '\u2cd8' - | '\u2cda' - | '\u2cdc' - | '\u2cde' - | '\u2ce0' - | '\u2ce2' - | '\u2ceb' - | '\u2ced' - | '\ua640' - | '\ua642' - | '\ua644' - | '\ua646' - | '\ua648' - | '\ua64a' - | '\ua64c' - | '\ua64e' - | '\ua650' - | '\ua652' - | '\ua654' - | '\ua656' - | '\ua658' - | '\ua65a' - | '\ua65c' - | '\ua65e' - | '\ua660' - | '\ua662' - | '\ua664' - | '\ua666' - | '\ua668' - | '\ua66a' - | '\ua66c' - | '\ua680' - | '\ua682' - | '\ua684' - | '\ua686' - | '\ua688' - | '\ua68a' - | '\ua68c' - | '\ua68e' - | '\ua690' - | '\ua692' - | '\ua694' - | '\ua696' - | '\ua722' - | '\ua724' - | '\ua726' - | '\ua728' - | '\ua72a' - | '\ua72c' - | '\ua72e' - | '\ua732' - | '\ua734' - | '\ua736' - | '\ua738' - | '\ua73a' - | '\ua73c' - | '\ua73e' - | '\ua740' - | '\ua742' - | '\ua744' - | '\ua746' - | '\ua748' - | '\ua74a' - | '\ua74c' - | '\ua74e' - | '\ua750' - | '\ua752' - | '\ua754' - | '\ua756' - | '\ua758' - | '\ua75a' - | '\ua75c' - | '\ua75e' - | '\ua760' - | '\ua762' - | '\ua764' - | '\ua766' - | '\ua768' - | '\ua76a' - | '\ua76c' - | '\ua76e' - | '\ua779' - | '\ua77b' - | '\ua77d' .. '\ua77e' - | '\ua780' - | '\ua782' - | '\ua784' - | '\ua786' - | '\ua78b' - | '\ua78d' - | '\ua790' - | '\ua7a0' - | '\ua7a2' - | '\ua7a4' - | '\ua7a6' - | '\ua7a8' - | '\uff21' .. '\uff3a' - | '\U00010400' .. '\U00010427' - | '\U0001d400' .. '\U0001d419' - | '\U0001d434' .. '\U0001d44d' - | '\U0001d468' .. '\U0001d481' - | '\U0001d49c' .. '\U0001d4b5' - | '\U0001d4d0' .. '\U0001d4e9' - | '\U0001d504' .. '\U0001d51c' - | '\U0001d538' .. '\U0001d550' - | '\U0001d56c' .. '\U0001d585' - | '\U0001d5a0' .. '\U0001d5b9' - | '\U0001d5d4' .. '\U0001d5ed' - | '\U0001d608' .. '\U0001d621' - | '\U0001d63c' .. '\U0001d655' - | '\U0001d670' .. '\U0001d689' - | '\U0001d6a8' .. '\U0001d6c0' - | '\U0001d6e2' .. '\U0001d6fa' - | '\U0001d71c' .. '\U0001d734' - | '\U0001d756' .. '\U0001d76e' - | '\U0001d790' .. '\U0001d7a8' - | '\U0001d7ca' - => true, - _ => false - }; + bsearch_range_table(c, Lu_table) } + static Mc_table : &'static [(char,char)] = &[ + ('\u0903', '\u0903'), ('\u093b', '\u093b'), + ('\u093e', '\u0940'), ('\u0949', '\u094c'), + ('\u094e', '\u094f'), ('\u0982', '\u0983'), + ('\u09be', '\u09c0'), ('\u09c7', '\u09cc'), + ('\u09d7', '\u09d7'), ('\u0a03', '\u0a03'), + ('\u0a3e', '\u0a40'), ('\u0a83', '\u0a83'), + ('\u0abe', '\u0ac0'), ('\u0ac9', '\u0acc'), + ('\u0b02', '\u0b03'), ('\u0b3e', '\u0b3e'), + ('\u0b40', '\u0b40'), ('\u0b47', '\u0b4c'), + ('\u0b57', '\u0b57'), ('\u0bbe', '\u0bbf'), + ('\u0bc1', '\u0bcc'), ('\u0bd7', '\u0bd7'), + ('\u0c01', '\u0c03'), ('\u0c41', '\u0c44'), + ('\u0c82', '\u0c83'), ('\u0cbe', '\u0cbe'), + ('\u0cc0', '\u0cc4'), ('\u0cc7', '\u0ccb'), + ('\u0cd5', '\u0cd6'), ('\u0d02', '\u0d03'), + ('\u0d3e', '\u0d40'), ('\u0d46', '\u0d4c'), + ('\u0d57', '\u0d57'), ('\u0d82', '\u0d83'), + ('\u0dcf', '\u0dd1'), ('\u0dd8', '\u0df3'), + ('\u0f3e', '\u0f3f'), ('\u0f7f', '\u0f7f'), + ('\u102b', '\u102c'), ('\u1031', '\u1031'), + ('\u1038', '\u1038'), ('\u103b', '\u103c'), + ('\u1056', '\u1057'), ('\u1062', '\u1064'), + ('\u1067', '\u106d'), ('\u1083', '\u1084'), + ('\u1087', '\u108c'), ('\u108f', '\u108f'), + ('\u109a', '\u109c'), ('\u17b6', '\u17b6'), + ('\u17be', '\u17c5'), ('\u17c7', '\u17c8'), + ('\u1923', '\u1926'), ('\u1929', '\u1931'), + ('\u1933', '\u1938'), ('\u19b0', '\u19c0'), + ('\u19c8', '\u19c9'), ('\u1a19', '\u1a1b'), + ('\u1a55', '\u1a55'), ('\u1a57', '\u1a57'), + ('\u1a61', '\u1a61'), ('\u1a63', '\u1a64'), + ('\u1a6d', '\u1a72'), ('\u1b04', '\u1b04'), + ('\u1b35', '\u1b35'), ('\u1b3b', '\u1b3b'), + ('\u1b3d', '\u1b41'), ('\u1b43', '\u1b44'), + ('\u1b82', '\u1b82'), ('\u1ba1', '\u1ba1'), + ('\u1ba6', '\u1ba7'), ('\u1baa', '\u1baa'), + ('\u1bac', '\u1bad'), ('\u1be7', '\u1be7'), + ('\u1bea', '\u1bec'), ('\u1bee', '\u1bee'), + ('\u1bf2', '\u1bf3'), ('\u1c24', '\u1c2b'), + ('\u1c34', '\u1c35'), ('\u1ce1', '\u1ce1'), + ('\u1cf2', '\u1cf3'), ('\u302e', '\u302f'), + ('\ua823', '\ua824'), ('\ua827', '\ua827'), + ('\ua880', '\ua881'), ('\ua8b4', '\ua8c3'), + ('\ua952', '\ua953'), ('\ua983', '\ua983'), + ('\ua9b4', '\ua9b5'), ('\ua9ba', '\ua9bb'), + ('\ua9bd', '\ua9c0'), ('\uaa2f', '\uaa30'), + ('\uaa33', '\uaa34'), ('\uaa4d', '\uaa4d'), + ('\uaa7b', '\uaa7b'), ('\uaaeb', '\uaaeb'), + ('\uaaee', '\uaaef'), ('\uaaf5', '\uaaf5'), + ('\uabe3', '\uabe4'), ('\uabe6', '\uabe7'), + ('\uabe9', '\uabea'), ('\uabec', '\uabec'), + ('\U00011000', '\U00011000'), ('\U00011002', '\U00011002'), + ('\U00011082', '\U00011082'), ('\U000110b0', '\U000110b2'), + ('\U000110b7', '\U000110b8'), ('\U0001112c', '\U0001112c'), + ('\U00011182', '\U00011182'), ('\U000111b3', '\U000111b5'), + ('\U000111bf', '\U000111c0'), ('\U000116ac', '\U000116ac'), + ('\U000116ae', '\U000116af'), ('\U000116b6', '\U000116b6'), + ('\U00016f51', '\U00016f7e'), ('\U0001d165', '\U0001d166'), + ('\U0001d16d', '\U0001d172') + ]; + pub fn Mc(c: char) -> bool { - return match c { - '\u0903' - | '\u093b' - | '\u093e' .. '\u0940' - | '\u0949' .. '\u094c' - | '\u094e' .. '\u094f' - | '\u0982' .. '\u0983' - | '\u09be' .. '\u09c0' - | '\u09c7' .. '\u09cc' - | '\u09d7' - | '\u0a03' - | '\u0a3e' .. '\u0a40' - | '\u0a83' - | '\u0abe' .. '\u0ac0' - | '\u0ac9' .. '\u0acc' - | '\u0b02' .. '\u0b03' - | '\u0b3e' - | '\u0b40' - | '\u0b47' .. '\u0b4c' - | '\u0b57' - | '\u0bbe' .. '\u0bbf' - | '\u0bc1' .. '\u0bcc' - | '\u0bd7' - | '\u0c01' .. '\u0c03' - | '\u0c41' .. '\u0c44' - | '\u0c82' .. '\u0c83' - | '\u0cbe' - | '\u0cc0' .. '\u0cc4' - | '\u0cc7' .. '\u0ccb' - | '\u0cd5' .. '\u0cd6' - | '\u0d02' .. '\u0d03' - | '\u0d3e' .. '\u0d40' - | '\u0d46' .. '\u0d4c' - | '\u0d57' - | '\u0d82' .. '\u0d83' - | '\u0dcf' .. '\u0dd1' - | '\u0dd8' .. '\u0df3' - | '\u0f3e' .. '\u0f3f' - | '\u0f7f' - | '\u102b' .. '\u102c' - | '\u1031' - | '\u1038' - | '\u103b' .. '\u103c' - | '\u1056' .. '\u1057' - | '\u1062' .. '\u1064' - | '\u1067' .. '\u106d' - | '\u1083' .. '\u1084' - | '\u1087' .. '\u108c' - | '\u108f' - | '\u109a' .. '\u109c' - | '\u17b6' - | '\u17be' .. '\u17c5' - | '\u17c7' .. '\u17c8' - | '\u1923' .. '\u1926' - | '\u1929' .. '\u1931' - | '\u1933' .. '\u1938' - | '\u19b0' .. '\u19c0' - | '\u19c8' .. '\u19c9' - | '\u1a19' .. '\u1a1b' - | '\u1a55' - | '\u1a57' - | '\u1a61' - | '\u1a63' .. '\u1a64' - | '\u1a6d' .. '\u1a72' - | '\u1b04' - | '\u1b35' - | '\u1b3b' - | '\u1b3d' .. '\u1b41' - | '\u1b43' .. '\u1b44' - | '\u1b82' - | '\u1ba1' - | '\u1ba6' .. '\u1ba7' - | '\u1baa' - | '\u1be7' - | '\u1bea' .. '\u1bec' - | '\u1bee' - | '\u1bf2' .. '\u1bf3' - | '\u1c24' .. '\u1c2b' - | '\u1c34' .. '\u1c35' - | '\u1ce1' - | '\u1cf2' - | '\ua823' .. '\ua824' - | '\ua827' - | '\ua880' .. '\ua881' - | '\ua8b4' .. '\ua8c3' - | '\ua952' .. '\ua953' - | '\ua983' - | '\ua9b4' .. '\ua9b5' - | '\ua9ba' .. '\ua9bb' - | '\ua9bd' .. '\ua9c0' - | '\uaa2f' .. '\uaa30' - | '\uaa33' .. '\uaa34' - | '\uaa4d' - | '\uaa7b' - | '\uabe3' .. '\uabe4' - | '\uabe6' .. '\uabe7' - | '\uabe9' .. '\uabea' - | '\uabec' - | '\U00011000' - | '\U00011002' - | '\U00011082' - | '\U000110b0' .. '\U000110b2' - | '\U000110b7' .. '\U000110b8' - | '\U0001d165' .. '\U0001d166' - | '\U0001d16d' .. '\U0001d172' - => true, - _ => false - }; + bsearch_range_table(c, Mc_table) } + static Me_table : &'static [(char,char)] = &[ + ('\u0488', '\u0489'), ('\u20dd', '\u20e0'), + ('\u20e2', '\u20e4'), ('\ua670', '\ua672') + ]; + pub fn Me(c: char) -> bool { - return match c { - '\u0488' .. '\u0489' - | '\u20dd' .. '\u20e0' - | '\u20e2' .. '\u20e4' - | '\ua670' .. '\ua672' - => true, - _ => false - }; + bsearch_range_table(c, Me_table) } + static Mn_table : &'static [(char,char)] = &[ + ('\u0300', '\u036f'), ('\u0483', '\u0487'), + ('\u0591', '\u05bd'), ('\u05bf', '\u05bf'), + ('\u05c1', '\u05c2'), ('\u05c4', '\u05c5'), + ('\u05c7', '\u05c7'), ('\u0610', '\u061a'), + ('\u064b', '\u065f'), ('\u0670', '\u0670'), + ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), + ('\u06e7', '\u06e8'), ('\u06ea', '\u06ed'), + ('\u0711', '\u0711'), ('\u0730', '\u074a'), + ('\u07a6', '\u07b0'), ('\u07eb', '\u07f3'), + ('\u0816', '\u0819'), ('\u081b', '\u0823'), + ('\u0825', '\u0827'), ('\u0829', '\u082d'), + ('\u0859', '\u085b'), ('\u08e4', '\u0902'), + ('\u093a', '\u093a'), ('\u093c', '\u093c'), + ('\u0941', '\u0948'), ('\u094d', '\u094d'), + ('\u0951', '\u0957'), ('\u0962', '\u0963'), + ('\u0981', '\u0981'), ('\u09bc', '\u09bc'), + ('\u09c1', '\u09c4'), ('\u09cd', '\u09cd'), + ('\u09e2', '\u09e3'), ('\u0a01', '\u0a02'), + ('\u0a3c', '\u0a3c'), ('\u0a41', '\u0a51'), + ('\u0a70', '\u0a71'), ('\u0a75', '\u0a82'), + ('\u0abc', '\u0abc'), ('\u0ac1', '\u0ac8'), + ('\u0acd', '\u0acd'), ('\u0ae2', '\u0ae3'), + ('\u0b01', '\u0b01'), ('\u0b3c', '\u0b3c'), + ('\u0b3f', '\u0b3f'), ('\u0b41', '\u0b44'), + ('\u0b4d', '\u0b56'), ('\u0b62', '\u0b63'), + ('\u0b82', '\u0b82'), ('\u0bc0', '\u0bc0'), + ('\u0bcd', '\u0bcd'), ('\u0c3e', '\u0c40'), + ('\u0c46', '\u0c56'), ('\u0c62', '\u0c63'), + ('\u0cbc', '\u0cbc'), ('\u0cbf', '\u0cbf'), + ('\u0cc6', '\u0cc6'), ('\u0ccc', '\u0ccd'), + ('\u0ce2', '\u0ce3'), ('\u0d41', '\u0d44'), + ('\u0d4d', '\u0d4d'), ('\u0d62', '\u0d63'), + ('\u0dca', '\u0dca'), ('\u0dd2', '\u0dd6'), + ('\u0e31', '\u0e31'), ('\u0e34', '\u0e3a'), + ('\u0e47', '\u0e4e'), ('\u0eb1', '\u0eb1'), + ('\u0eb4', '\u0ebc'), ('\u0ec8', '\u0ecd'), + ('\u0f18', '\u0f19'), ('\u0f35', '\u0f35'), + ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), + ('\u0f71', '\u0f7e'), ('\u0f80', '\u0f84'), + ('\u0f86', '\u0f87'), ('\u0f8d', '\u0fbc'), + ('\u0fc6', '\u0fc6'), ('\u102d', '\u1030'), + ('\u1032', '\u1037'), ('\u1039', '\u103a'), + ('\u103d', '\u103e'), ('\u1058', '\u1059'), + ('\u105e', '\u1060'), ('\u1071', '\u1074'), + ('\u1082', '\u1082'), ('\u1085', '\u1086'), + ('\u108d', '\u108d'), ('\u109d', '\u109d'), + ('\u135d', '\u135f'), ('\u1712', '\u1714'), + ('\u1732', '\u1734'), ('\u1752', '\u1753'), + ('\u1772', '\u1773'), ('\u17b4', '\u17b5'), + ('\u17b7', '\u17bd'), ('\u17c6', '\u17c6'), + ('\u17c9', '\u17d3'), ('\u17dd', '\u17dd'), + ('\u180b', '\u180d'), ('\u18a9', '\u18a9'), + ('\u1920', '\u1922'), ('\u1927', '\u1928'), + ('\u1932', '\u1932'), ('\u1939', '\u193b'), + ('\u1a17', '\u1a18'), ('\u1a56', '\u1a56'), + ('\u1a58', '\u1a60'), ('\u1a62', '\u1a62'), + ('\u1a65', '\u1a6c'), ('\u1a73', '\u1a7f'), + ('\u1b00', '\u1b03'), ('\u1b34', '\u1b34'), + ('\u1b36', '\u1b3a'), ('\u1b3c', '\u1b3c'), + ('\u1b42', '\u1b42'), ('\u1b6b', '\u1b73'), + ('\u1b80', '\u1b81'), ('\u1ba2', '\u1ba5'), + ('\u1ba8', '\u1ba9'), ('\u1bab', '\u1bab'), + ('\u1be6', '\u1be6'), ('\u1be8', '\u1be9'), + ('\u1bed', '\u1bed'), ('\u1bef', '\u1bf1'), + ('\u1c2c', '\u1c33'), ('\u1c36', '\u1c37'), + ('\u1cd0', '\u1cd2'), ('\u1cd4', '\u1ce0'), + ('\u1ce2', '\u1ce8'), ('\u1ced', '\u1ced'), + ('\u1cf4', '\u1cf4'), ('\u1dc0', '\u1dff'), + ('\u20d0', '\u20dc'), ('\u20e1', '\u20e1'), + ('\u20e5', '\u20f0'), ('\u2cef', '\u2cf1'), + ('\u2d7f', '\u2d7f'), ('\u2de0', '\u2dff'), + ('\u302a', '\u302d'), ('\u3099', '\u309a'), + ('\ua66f', '\ua66f'), ('\ua674', '\ua67d'), + ('\ua69f', '\ua69f'), ('\ua6f0', '\ua6f1'), + ('\ua802', '\ua802'), ('\ua806', '\ua806'), + ('\ua80b', '\ua80b'), ('\ua825', '\ua826'), + ('\ua8c4', '\ua8c4'), ('\ua8e0', '\ua8f1'), + ('\ua926', '\ua92d'), ('\ua947', '\ua951'), + ('\ua980', '\ua982'), ('\ua9b3', '\ua9b3'), + ('\ua9b6', '\ua9b9'), ('\ua9bc', '\ua9bc'), + ('\uaa29', '\uaa2e'), ('\uaa31', '\uaa32'), + ('\uaa35', '\uaa36'), ('\uaa43', '\uaa43'), + ('\uaa4c', '\uaa4c'), ('\uaab0', '\uaab0'), + ('\uaab2', '\uaab4'), ('\uaab7', '\uaab8'), + ('\uaabe', '\uaabf'), ('\uaac1', '\uaac1'), + ('\uaaec', '\uaaed'), ('\uaaf6', '\uaaf6'), + ('\uabe5', '\uabe5'), ('\uabe8', '\uabe8'), + ('\uabed', '\uabed'), ('\ufb1e', '\ufb1e'), + ('\ufe00', '\ufe0f'), ('\ufe20', '\ufe26'), + ('\U000101fd', '\U000101fd'), ('\U00010a01', '\U00010a0f'), + ('\U00010a38', '\U00010a3f'), ('\U00011001', '\U00011001'), + ('\U00011038', '\U00011046'), ('\U00011080', '\U00011081'), + ('\U000110b3', '\U000110b6'), ('\U000110b9', '\U000110ba'), + ('\U00011100', '\U00011102'), ('\U00011127', '\U0001112b'), + ('\U0001112d', '\U00011134'), ('\U00011180', '\U00011181'), + ('\U000111b6', '\U000111be'), ('\U000116ab', '\U000116ab'), + ('\U000116ad', '\U000116ad'), ('\U000116b0', '\U000116b5'), + ('\U000116b7', '\U000116b7'), ('\U00016f8f', '\U00016f92'), + ('\U0001d167', '\U0001d169'), ('\U0001d17b', '\U0001d182'), + ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), + ('\U0001d242', '\U0001d244'), ('\U000e0100', '\U000e01ef') + ]; + pub fn Mn(c: char) -> bool { - return match c { - '\u0300' .. '\u036f' - | '\u0483' .. '\u0487' - | '\u0591' .. '\u05bd' - | '\u05bf' - | '\u05c1' .. '\u05c2' - | '\u05c4' .. '\u05c5' - | '\u05c7' - | '\u0610' .. '\u061a' - | '\u064b' .. '\u065f' - | '\u0670' - | '\u06d6' .. '\u06dc' - | '\u06df' .. '\u06e4' - | '\u06e7' .. '\u06e8' - | '\u06ea' .. '\u06ed' - | '\u0711' - | '\u0730' .. '\u074a' - | '\u07a6' .. '\u07b0' - | '\u07eb' .. '\u07f3' - | '\u0816' .. '\u0819' - | '\u081b' .. '\u0823' - | '\u0825' .. '\u0827' - | '\u0829' .. '\u082d' - | '\u0859' .. '\u085b' - | '\u0900' .. '\u0902' - | '\u093a' - | '\u093c' - | '\u0941' .. '\u0948' - | '\u094d' - | '\u0951' .. '\u0957' - | '\u0962' .. '\u0963' - | '\u0981' - | '\u09bc' - | '\u09c1' .. '\u09c4' - | '\u09cd' - | '\u09e2' .. '\u09e3' - | '\u0a01' .. '\u0a02' - | '\u0a3c' - | '\u0a41' .. '\u0a51' - | '\u0a70' .. '\u0a71' - | '\u0a75' .. '\u0a82' - | '\u0abc' - | '\u0ac1' .. '\u0ac8' - | '\u0acd' - | '\u0ae2' .. '\u0ae3' - | '\u0b01' - | '\u0b3c' - | '\u0b3f' - | '\u0b41' .. '\u0b44' - | '\u0b4d' .. '\u0b56' - | '\u0b62' .. '\u0b63' - | '\u0b82' - | '\u0bc0' - | '\u0bcd' - | '\u0c3e' .. '\u0c40' - | '\u0c46' .. '\u0c56' - | '\u0c62' .. '\u0c63' - | '\u0cbc' - | '\u0cbf' - | '\u0cc6' - | '\u0ccc' .. '\u0ccd' - | '\u0ce2' .. '\u0ce3' - | '\u0d41' .. '\u0d44' - | '\u0d4d' - | '\u0d62' .. '\u0d63' - | '\u0dca' - | '\u0dd2' .. '\u0dd6' - | '\u0e31' - | '\u0e34' .. '\u0e3a' - | '\u0e47' .. '\u0e4e' - | '\u0eb1' - | '\u0eb4' .. '\u0ebc' - | '\u0ec8' .. '\u0ecd' - | '\u0f18' .. '\u0f19' - | '\u0f35' - | '\u0f37' - | '\u0f39' - | '\u0f71' .. '\u0f7e' - | '\u0f80' .. '\u0f84' - | '\u0f86' .. '\u0f87' - | '\u0f8d' .. '\u0fbc' - | '\u0fc6' - | '\u102d' .. '\u1030' - | '\u1032' .. '\u1037' - | '\u1039' .. '\u103a' - | '\u103d' .. '\u103e' - | '\u1058' .. '\u1059' - | '\u105e' .. '\u1060' - | '\u1071' .. '\u1074' - | '\u1082' - | '\u1085' .. '\u1086' - | '\u108d' - | '\u109d' - | '\u135d' .. '\u135f' - | '\u1712' .. '\u1714' - | '\u1732' .. '\u1734' - | '\u1752' .. '\u1753' - | '\u1772' .. '\u1773' - | '\u17b7' .. '\u17bd' - | '\u17c6' - | '\u17c9' .. '\u17d3' - | '\u17dd' - | '\u180b' .. '\u180d' - | '\u18a9' - | '\u1920' .. '\u1922' - | '\u1927' .. '\u1928' - | '\u1932' - | '\u1939' .. '\u193b' - | '\u1a17' .. '\u1a18' - | '\u1a56' - | '\u1a58' .. '\u1a60' - | '\u1a62' - | '\u1a65' .. '\u1a6c' - | '\u1a73' .. '\u1a7f' - | '\u1b00' .. '\u1b03' - | '\u1b34' - | '\u1b36' .. '\u1b3a' - | '\u1b3c' - | '\u1b42' - | '\u1b6b' .. '\u1b73' - | '\u1b80' .. '\u1b81' - | '\u1ba2' .. '\u1ba5' - | '\u1ba8' .. '\u1ba9' - | '\u1be6' - | '\u1be8' .. '\u1be9' - | '\u1bed' - | '\u1bef' .. '\u1bf1' - | '\u1c2c' .. '\u1c33' - | '\u1c36' .. '\u1c37' - | '\u1cd0' .. '\u1cd2' - | '\u1cd4' .. '\u1ce0' - | '\u1ce2' .. '\u1ce8' - | '\u1ced' - | '\u1dc0' .. '\u1dff' - | '\u20d0' .. '\u20dc' - | '\u20e1' - | '\u20e5' .. '\u20f0' - | '\u2cef' .. '\u2cf1' - | '\u2d7f' - | '\u2de0' .. '\u2dff' - | '\u302a' .. '\u302f' - | '\u3099' .. '\u309a' - | '\ua66f' - | '\ua67c' .. '\ua67d' - | '\ua6f0' .. '\ua6f1' - | '\ua802' - | '\ua806' - | '\ua80b' - | '\ua825' .. '\ua826' - | '\ua8c4' - | '\ua8e0' .. '\ua8f1' - | '\ua926' .. '\ua92d' - | '\ua947' .. '\ua951' - | '\ua980' .. '\ua982' - | '\ua9b3' - | '\ua9b6' .. '\ua9b9' - | '\ua9bc' - | '\uaa29' .. '\uaa2e' - | '\uaa31' .. '\uaa32' - | '\uaa35' .. '\uaa36' - | '\uaa43' - | '\uaa4c' - | '\uaab0' - | '\uaab2' .. '\uaab4' - | '\uaab7' .. '\uaab8' - | '\uaabe' .. '\uaabf' - | '\uaac1' - | '\uabe5' - | '\uabe8' - | '\uabed' - | '\ufb1e' - | '\ufe00' .. '\ufe0f' - | '\ufe20' .. '\ufe26' - | '\U000101fd' - | '\U00010a01' .. '\U00010a0f' - | '\U00010a38' .. '\U00010a3f' - | '\U00011001' - | '\U00011038' .. '\U00011046' - | '\U00011080' .. '\U00011081' - | '\U000110b3' .. '\U000110b6' - | '\U000110b9' .. '\U000110ba' - | '\U0001d167' .. '\U0001d169' - | '\U0001d17b' .. '\U0001d182' - | '\U0001d185' .. '\U0001d18b' - | '\U0001d1aa' .. '\U0001d1ad' - | '\U0001d242' .. '\U0001d244' - | '\U000e0100' .. '\U000e01ef' - => true, - _ => false - }; + bsearch_range_table(c, Mn_table) } + static Nd_table : &'static [(char,char)] = &[ + ('\x30', '\x39'), ('\u0660', '\u0669'), + ('\u06f0', '\u06f9'), ('\u07c0', '\u07c9'), + ('\u0966', '\u096f'), ('\u09e6', '\u09ef'), + ('\u0a66', '\u0a6f'), ('\u0ae6', '\u0aef'), + ('\u0b66', '\u0b6f'), ('\u0be6', '\u0bef'), + ('\u0c66', '\u0c6f'), ('\u0ce6', '\u0cef'), + ('\u0d66', '\u0d6f'), ('\u0e50', '\u0e59'), + ('\u0ed0', '\u0ed9'), ('\u0f20', '\u0f29'), + ('\u1040', '\u1049'), ('\u1090', '\u1099'), + ('\u17e0', '\u17e9'), ('\u1810', '\u1819'), + ('\u1946', '\u194f'), ('\u19d0', '\u19d9'), + ('\u1a80', '\u1a99'), ('\u1b50', '\u1b59'), + ('\u1bb0', '\u1bb9'), ('\u1c40', '\u1c49'), + ('\u1c50', '\u1c59'), ('\ua620', '\ua629'), + ('\ua8d0', '\ua8d9'), ('\ua900', '\ua909'), + ('\ua9d0', '\ua9d9'), ('\uaa50', '\uaa59'), + ('\uabf0', '\uabf9'), ('\uff10', '\uff19'), + ('\U000104a0', '\U000104a9'), ('\U00011066', '\U0001106f'), + ('\U000110f0', '\U000110f9'), ('\U00011136', '\U0001113f'), + ('\U000111d0', '\U000111d9'), ('\U000116c0', '\U000116c9'), + ('\U0001d7ce', '\U0001d7ff') + ]; + pub fn Nd(c: char) -> bool { - return match c { - '\x30' .. '\x39' - | '\u0660' .. '\u0669' - | '\u06f0' .. '\u06f9' - | '\u07c0' .. '\u07c9' - | '\u0966' .. '\u096f' - | '\u09e6' .. '\u09ef' - | '\u0a66' .. '\u0a6f' - | '\u0ae6' .. '\u0aef' - | '\u0b66' .. '\u0b6f' - | '\u0be6' .. '\u0bef' - | '\u0c66' .. '\u0c6f' - | '\u0ce6' .. '\u0cef' - | '\u0d66' .. '\u0d6f' - | '\u0e50' .. '\u0e59' - | '\u0ed0' .. '\u0ed9' - | '\u0f20' .. '\u0f29' - | '\u1040' .. '\u1049' - | '\u1090' .. '\u1099' - | '\u17e0' .. '\u17e9' - | '\u1810' .. '\u1819' - | '\u1946' .. '\u194f' - | '\u19d0' .. '\u19d9' - | '\u1a80' .. '\u1a99' - | '\u1b50' .. '\u1b59' - | '\u1bb0' .. '\u1bb9' - | '\u1c40' .. '\u1c49' - | '\u1c50' .. '\u1c59' - | '\ua620' .. '\ua629' - | '\ua8d0' .. '\ua8d9' - | '\ua900' .. '\ua909' - | '\ua9d0' .. '\ua9d9' - | '\uaa50' .. '\uaa59' - | '\uabf0' .. '\uabf9' - | '\uff10' .. '\uff19' - | '\U000104a0' .. '\U000104a9' - | '\U00011066' .. '\U0001106f' - | '\U0001d7ce' .. '\U0001d7ff' - => true, - _ => false - }; + bsearch_range_table(c, Nd_table) } + static Nl_table : &'static [(char,char)] = &[ + ('\u16ee', '\u16f0'), ('\u2160', '\u2182'), + ('\u2185', '\u2188'), ('\u3007', '\u3007'), + ('\u3021', '\u3029'), ('\u3038', '\u303a'), + ('\ua6e6', '\ua6ef'), ('\U00010140', '\U00010174'), + ('\U00010341', '\U00010341'), ('\U0001034a', '\U0001034a'), + ('\U000103d1', '\U000103d5'), ('\U00012400', '\U00012462') + ]; + pub fn Nl(c: char) -> bool { - return match c { - '\u16ee' .. '\u16f0' - | '\u2160' .. '\u2182' - | '\u2185' .. '\u2188' - | '\u3007' - | '\u3021' .. '\u3029' - | '\u3038' .. '\u303a' - | '\ua6e6' .. '\ua6ef' - | '\U00010140' .. '\U00010174' - | '\U00010341' - | '\U0001034a' - | '\U000103d1' .. '\U000103d5' - | '\U00012400' .. '\U00012462' - => true, - _ => false - }; + bsearch_range_table(c, Nl_table) } + static No_table : &'static [(char,char)] = &[ + ('\xb2', '\xb3'), ('\xb9', '\xb9'), + ('\xbc', '\xbe'), ('\u09f4', '\u09f9'), + ('\u0b72', '\u0b77'), ('\u0bf0', '\u0bf2'), + ('\u0c78', '\u0c7e'), ('\u0d70', '\u0d75'), + ('\u0f2a', '\u0f33'), ('\u1369', '\u137c'), + ('\u17f0', '\u17f9'), ('\u19da', '\u19da'), + ('\u2070', '\u2070'), ('\u2074', '\u2079'), + ('\u2080', '\u2089'), ('\u2150', '\u215f'), + ('\u2189', '\u2189'), ('\u2460', '\u249b'), + ('\u24ea', '\u24ff'), ('\u2776', '\u2793'), + ('\u2cfd', '\u2cfd'), ('\u3192', '\u3195'), + ('\u3220', '\u3229'), ('\u3248', '\u324f'), + ('\u3251', '\u325f'), ('\u3280', '\u3289'), + ('\u32b1', '\u32bf'), ('\ua830', '\ua835'), + ('\U00010107', '\U00010133'), ('\U00010175', '\U00010178'), + ('\U0001018a', '\U0001018a'), ('\U00010320', '\U00010323'), + ('\U00010858', '\U0001085f'), ('\U00010916', '\U0001091b'), + ('\U00010a40', '\U00010a47'), ('\U00010a7d', '\U00010a7e'), + ('\U00010b58', '\U00010b5f'), ('\U00010b78', '\U00010b7f'), + ('\U00010e60', '\U00010e7e'), ('\U00011052', '\U00011065'), + ('\U0001d360', '\U0001d371'), ('\U0001f100', '\U0001f10a') + ]; + pub fn No(c: char) -> bool { - return match c { - '\xb2' .. '\xb3' - | '\xb9' - | '\xbc' .. '\xbe' - | '\u09f4' .. '\u09f9' - | '\u0b72' .. '\u0b77' - | '\u0bf0' .. '\u0bf2' - | '\u0c78' .. '\u0c7e' - | '\u0d70' .. '\u0d75' - | '\u0f2a' .. '\u0f33' - | '\u1369' .. '\u137c' - | '\u17f0' .. '\u17f9' - | '\u19da' - | '\u2070' - | '\u2074' .. '\u2079' - | '\u2080' .. '\u2089' - | '\u2150' .. '\u215f' - | '\u2189' - | '\u2460' .. '\u249b' - | '\u24ea' .. '\u24ff' - | '\u2776' .. '\u2793' - | '\u2cfd' - | '\u3192' .. '\u3195' - | '\u3220' .. '\u3229' - | '\u3251' .. '\u325f' - | '\u3280' .. '\u3289' - | '\u32b1' .. '\u32bf' - | '\ua830' .. '\ua835' - | '\U00010107' .. '\U00010133' - | '\U00010175' .. '\U00010178' - | '\U0001018a' - | '\U00010320' .. '\U00010323' - | '\U00010858' .. '\U0001085f' - | '\U00010916' .. '\U0001091b' - | '\U00010a40' .. '\U00010a47' - | '\U00010a7d' .. '\U00010a7e' - | '\U00010b58' .. '\U00010b5f' - | '\U00010b78' .. '\U00010b7f' - | '\U00010e60' .. '\U00010e7e' - | '\U00011052' .. '\U00011065' - | '\U0001d360' .. '\U0001d371' - | '\U0001f100' .. '\U0001f10a' - => true, - _ => false - }; + bsearch_range_table(c, No_table) } + static Pc_table : &'static [(char,char)] = &[ + ('\x5f', '\x5f'), ('\u203f', '\u2040'), + ('\u2054', '\u2054'), ('\ufe33', '\ufe34'), + ('\ufe4d', '\ufe4f'), ('\uff3f', '\uff3f') + ]; + pub fn Pc(c: char) -> bool { - return match c { - '\x5f' - | '\u203f' .. '\u2040' - | '\u2054' - | '\ufe33' .. '\ufe34' - | '\ufe4d' .. '\ufe4f' - | '\uff3f' - => true, - _ => false - }; + bsearch_range_table(c, Pc_table) } + static Pd_table : &'static [(char,char)] = &[ + ('\x2d', '\x2d'), ('\u058a', '\u058a'), + ('\u05be', '\u05be'), ('\u1400', '\u1400'), + ('\u1806', '\u1806'), ('\u2010', '\u2015'), + ('\u2e17', '\u2e17'), ('\u2e1a', '\u2e1a'), + ('\u2e3a', '\u2e3b'), ('\u301c', '\u301c'), + ('\u3030', '\u3030'), ('\u30a0', '\u30a0'), + ('\ufe31', '\ufe32'), ('\ufe58', '\ufe58'), + ('\ufe63', '\ufe63'), ('\uff0d', '\uff0d') + ]; + pub fn Pd(c: char) -> bool { - return match c { - '\x2d' - | '\u058a' - | '\u05be' - | '\u1400' - | '\u1806' - | '\u2010' .. '\u2015' - | '\u2e17' - | '\u2e1a' - | '\u301c' - | '\u3030' - | '\u30a0' - | '\ufe31' .. '\ufe32' - | '\ufe58' - | '\ufe63' - | '\uff0d' - => true, - _ => false - }; + bsearch_range_table(c, Pd_table) } + static Pe_table : &'static [(char,char)] = &[ + ('\x29', '\x29'), ('\x5d', '\x5d'), + ('\x7d', '\x7d'), ('\u0f3b', '\u0f3b'), + ('\u0f3d', '\u0f3d'), ('\u169c', '\u169c'), + ('\u2046', '\u2046'), ('\u207e', '\u207e'), + ('\u208e', '\u208e'), ('\u232a', '\u232a'), + ('\u2769', '\u2769'), ('\u276b', '\u276b'), + ('\u276d', '\u276d'), ('\u276f', '\u276f'), + ('\u2771', '\u2771'), ('\u2773', '\u2773'), + ('\u2775', '\u2775'), ('\u27c6', '\u27c6'), + ('\u27e7', '\u27e7'), ('\u27e9', '\u27e9'), + ('\u27eb', '\u27eb'), ('\u27ed', '\u27ed'), + ('\u27ef', '\u27ef'), ('\u2984', '\u2984'), + ('\u2986', '\u2986'), ('\u2988', '\u2988'), + ('\u298a', '\u298a'), ('\u298c', '\u298c'), + ('\u298e', '\u298e'), ('\u2990', '\u2990'), + ('\u2992', '\u2992'), ('\u2994', '\u2994'), + ('\u2996', '\u2996'), ('\u2998', '\u2998'), + ('\u29d9', '\u29d9'), ('\u29db', '\u29db'), + ('\u29fd', '\u29fd'), ('\u2e23', '\u2e23'), + ('\u2e25', '\u2e25'), ('\u2e27', '\u2e27'), + ('\u2e29', '\u2e29'), ('\u3009', '\u3009'), + ('\u300b', '\u300b'), ('\u300d', '\u300d'), + ('\u300f', '\u300f'), ('\u3011', '\u3011'), + ('\u3015', '\u3015'), ('\u3017', '\u3017'), + ('\u3019', '\u3019'), ('\u301b', '\u301b'), + ('\u301e', '\u301f'), ('\ufd3f', '\ufd3f'), + ('\ufe18', '\ufe18'), ('\ufe36', '\ufe36'), + ('\ufe38', '\ufe38'), ('\ufe3a', '\ufe3a'), + ('\ufe3c', '\ufe3c'), ('\ufe3e', '\ufe3e'), + ('\ufe40', '\ufe40'), ('\ufe42', '\ufe42'), + ('\ufe44', '\ufe44'), ('\ufe48', '\ufe48'), + ('\ufe5a', '\ufe5a'), ('\ufe5c', '\ufe5c'), + ('\ufe5e', '\ufe5e'), ('\uff09', '\uff09'), + ('\uff3d', '\uff3d'), ('\uff5d', '\uff5d'), + ('\uff60', '\uff60'), ('\uff63', '\uff63') + ]; + pub fn Pe(c: char) -> bool { - return match c { - '\x29' - | '\x5d' - | '\x7d' - | '\u0f3b' - | '\u0f3d' - | '\u169c' - | '\u2046' - | '\u207e' - | '\u208e' - | '\u232a' - | '\u2769' - | '\u276b' - | '\u276d' - | '\u276f' - | '\u2771' - | '\u2773' - | '\u2775' - | '\u27c6' - | '\u27e7' - | '\u27e9' - | '\u27eb' - | '\u27ed' - | '\u27ef' - | '\u2984' - | '\u2986' - | '\u2988' - | '\u298a' - | '\u298c' - | '\u298e' - | '\u2990' - | '\u2992' - | '\u2994' - | '\u2996' - | '\u2998' - | '\u29d9' - | '\u29db' - | '\u29fd' - | '\u2e23' - | '\u2e25' - | '\u2e27' - | '\u2e29' - | '\u3009' - | '\u300b' - | '\u300d' - | '\u300f' - | '\u3011' - | '\u3015' - | '\u3017' - | '\u3019' - | '\u301b' - | '\u301e' .. '\u301f' - | '\ufd3f' - | '\ufe18' - | '\ufe36' - | '\ufe38' - | '\ufe3a' - | '\ufe3c' - | '\ufe3e' - | '\ufe40' - | '\ufe42' - | '\ufe44' - | '\ufe48' - | '\ufe5a' - | '\ufe5c' - | '\ufe5e' - | '\uff09' - | '\uff3d' - | '\uff5d' - | '\uff60' - | '\uff63' - => true, - _ => false - }; + bsearch_range_table(c, Pe_table) } + static Pf_table : &'static [(char,char)] = &[ + ('\xbb', '\xbb'), ('\u2019', '\u2019'), + ('\u201d', '\u201d'), ('\u203a', '\u203a'), + ('\u2e03', '\u2e03'), ('\u2e05', '\u2e05'), + ('\u2e0a', '\u2e0a'), ('\u2e0d', '\u2e0d'), + ('\u2e1d', '\u2e1d'), ('\u2e21', '\u2e21') + ]; + pub fn Pf(c: char) -> bool { - return match c { - '\xbb' - | '\u2019' - | '\u201d' - | '\u203a' - | '\u2e03' - | '\u2e05' - | '\u2e0a' - | '\u2e0d' - | '\u2e1d' - | '\u2e21' - => true, - _ => false - }; + bsearch_range_table(c, Pf_table) } + static Pi_table : &'static [(char,char)] = &[ + ('\xab', '\xab'), ('\u2018', '\u2018'), + ('\u201b', '\u201c'), ('\u201f', '\u201f'), + ('\u2039', '\u2039'), ('\u2e02', '\u2e02'), + ('\u2e04', '\u2e04'), ('\u2e09', '\u2e09'), + ('\u2e0c', '\u2e0c'), ('\u2e1c', '\u2e1c'), + ('\u2e20', '\u2e20') + ]; + pub fn Pi(c: char) -> bool { - return match c { - '\xab' - | '\u2018' - | '\u201b' .. '\u201c' - | '\u201f' - | '\u2039' - | '\u2e02' - | '\u2e04' - | '\u2e09' - | '\u2e0c' - | '\u2e1c' - | '\u2e20' - => true, - _ => false - }; + bsearch_range_table(c, Pi_table) } + static Po_table : &'static [(char,char)] = &[ + ('\x21', '\x23'), ('\x25', '\x27'), + ('\x2a', '\x2a'), ('\x2c', '\x2c'), + ('\x2e', '\x2f'), ('\x3a', '\x3b'), + ('\x3f', '\x40'), ('\x5c', '\x5c'), + ('\xa1', '\xa1'), ('\xa7', '\xa7'), + ('\xb6', '\xb7'), ('\xbf', '\xbf'), + ('\u037e', '\u037e'), ('\u0387', '\u0387'), + ('\u055a', '\u055f'), ('\u0589', '\u0589'), + ('\u05c0', '\u05c0'), ('\u05c3', '\u05c3'), + ('\u05c6', '\u05c6'), ('\u05f3', '\u05f4'), + ('\u0609', '\u060a'), ('\u060c', '\u060d'), + ('\u061b', '\u061f'), ('\u066a', '\u066d'), + ('\u06d4', '\u06d4'), ('\u0700', '\u070d'), + ('\u07f7', '\u07f9'), ('\u0830', '\u083e'), + ('\u085e', '\u085e'), ('\u0964', '\u0965'), + ('\u0970', '\u0970'), ('\u0af0', '\u0af0'), + ('\u0df4', '\u0df4'), ('\u0e4f', '\u0e4f'), + ('\u0e5a', '\u0e5b'), ('\u0f04', '\u0f12'), + ('\u0f14', '\u0f14'), ('\u0f85', '\u0f85'), + ('\u0fd0', '\u0fd4'), ('\u0fd9', '\u0fda'), + ('\u104a', '\u104f'), ('\u10fb', '\u10fb'), + ('\u1360', '\u1368'), ('\u166d', '\u166e'), + ('\u16eb', '\u16ed'), ('\u1735', '\u1736'), + ('\u17d4', '\u17d6'), ('\u17d8', '\u17da'), + ('\u1800', '\u1805'), ('\u1807', '\u180a'), + ('\u1944', '\u1945'), ('\u1a1e', '\u1a1f'), + ('\u1aa0', '\u1aa6'), ('\u1aa8', '\u1aad'), + ('\u1b5a', '\u1b60'), ('\u1bfc', '\u1bff'), + ('\u1c3b', '\u1c3f'), ('\u1c7e', '\u1cc7'), + ('\u1cd3', '\u1cd3'), ('\u2016', '\u2017'), + ('\u2020', '\u2027'), ('\u2030', '\u2038'), + ('\u203b', '\u203e'), ('\u2041', '\u2043'), + ('\u2047', '\u2051'), ('\u2053', '\u2053'), + ('\u2055', '\u205e'), ('\u2cf9', '\u2cfc'), + ('\u2cfe', '\u2cff'), ('\u2d70', '\u2d70'), + ('\u2e00', '\u2e01'), ('\u2e06', '\u2e08'), + ('\u2e0b', '\u2e0b'), ('\u2e0e', '\u2e16'), + ('\u2e18', '\u2e19'), ('\u2e1b', '\u2e1b'), + ('\u2e1e', '\u2e1f'), ('\u2e2a', '\u2e2e'), + ('\u2e30', '\u2e39'), ('\u3001', '\u3003'), + ('\u303d', '\u303d'), ('\u30fb', '\u30fb'), + ('\ua4fe', '\ua4ff'), ('\ua60d', '\ua60f'), + ('\ua673', '\ua673'), ('\ua67e', '\ua67e'), + ('\ua6f2', '\ua6f7'), ('\ua874', '\ua877'), + ('\ua8ce', '\ua8cf'), ('\ua8f8', '\ua8fa'), + ('\ua92e', '\ua92f'), ('\ua95f', '\ua95f'), + ('\ua9c1', '\ua9cd'), ('\ua9de', '\ua9df'), + ('\uaa5c', '\uaa5f'), ('\uaade', '\uaadf'), + ('\uaaf0', '\uaaf1'), ('\uabeb', '\uabeb'), + ('\ufe10', '\ufe16'), ('\ufe19', '\ufe19'), + ('\ufe30', '\ufe30'), ('\ufe45', '\ufe46'), + ('\ufe49', '\ufe4c'), ('\ufe50', '\ufe57'), + ('\ufe5f', '\ufe61'), ('\ufe68', '\ufe68'), + ('\ufe6a', '\ufe6b'), ('\uff01', '\uff03'), + ('\uff05', '\uff07'), ('\uff0a', '\uff0a'), + ('\uff0c', '\uff0c'), ('\uff0e', '\uff0f'), + ('\uff1a', '\uff1b'), ('\uff1f', '\uff20'), + ('\uff3c', '\uff3c'), ('\uff61', '\uff61'), + ('\uff64', '\uff65'), ('\U00010100', '\U00010102'), + ('\U0001039f', '\U0001039f'), ('\U000103d0', '\U000103d0'), + ('\U00010857', '\U00010857'), ('\U0001091f', '\U0001091f'), + ('\U0001093f', '\U0001093f'), ('\U00010a50', '\U00010a58'), + ('\U00010a7f', '\U00010a7f'), ('\U00010b39', '\U00010b3f'), + ('\U00011047', '\U0001104d'), ('\U000110bb', '\U000110bc'), + ('\U000110be', '\U000110c1'), ('\U00011140', '\U00011143'), + ('\U000111c5', '\U000111c8'), ('\U00012470', '\U00012473') + ]; + pub fn Po(c: char) -> bool { - return match c { - '\x21' .. '\x23' - | '\x25' .. '\x27' - | '\x2a' - | '\x2c' - | '\x2e' .. '\x2f' - | '\x3a' .. '\x3b' - | '\x3f' .. '\x40' - | '\x5c' - | '\xa1' - | '\xb7' - | '\xbf' - | '\u037e' - | '\u0387' - | '\u055a' .. '\u055f' - | '\u0589' - | '\u05c0' - | '\u05c3' - | '\u05c6' - | '\u05f3' .. '\u05f4' - | '\u0609' .. '\u060a' - | '\u060c' .. '\u060d' - | '\u061b' .. '\u061f' - | '\u066a' .. '\u066d' - | '\u06d4' - | '\u0700' .. '\u070d' - | '\u07f7' .. '\u07f9' - | '\u0830' .. '\u083e' - | '\u085e' - | '\u0964' .. '\u0965' - | '\u0970' - | '\u0df4' - | '\u0e4f' - | '\u0e5a' .. '\u0e5b' - | '\u0f04' .. '\u0f12' - | '\u0f85' - | '\u0fd0' .. '\u0fd4' - | '\u0fd9' .. '\u0fda' - | '\u104a' .. '\u104f' - | '\u10fb' - | '\u1361' .. '\u1368' - | '\u166d' .. '\u166e' - | '\u16eb' .. '\u16ed' - | '\u1735' .. '\u1736' - | '\u17d4' .. '\u17d6' - | '\u17d8' .. '\u17da' - | '\u1800' .. '\u1805' - | '\u1807' .. '\u180a' - | '\u1944' .. '\u1945' - | '\u1a1e' .. '\u1a1f' - | '\u1aa0' .. '\u1aa6' - | '\u1aa8' .. '\u1aad' - | '\u1b5a' .. '\u1b60' - | '\u1bfc' .. '\u1bff' - | '\u1c3b' .. '\u1c3f' - | '\u1c7e' .. '\u1c7f' - | '\u1cd3' - | '\u2016' .. '\u2017' - | '\u2020' .. '\u2027' - | '\u2030' .. '\u2038' - | '\u203b' .. '\u203e' - | '\u2041' .. '\u2043' - | '\u2047' .. '\u2051' - | '\u2053' - | '\u2055' .. '\u205e' - | '\u2cf9' .. '\u2cfc' - | '\u2cfe' .. '\u2cff' - | '\u2d70' - | '\u2e00' .. '\u2e01' - | '\u2e06' .. '\u2e08' - | '\u2e0b' - | '\u2e0e' .. '\u2e16' - | '\u2e18' .. '\u2e19' - | '\u2e1b' - | '\u2e1e' .. '\u2e1f' - | '\u2e2a' .. '\u2e2e' - | '\u2e30' .. '\u2e31' - | '\u3001' .. '\u3003' - | '\u303d' - | '\u30fb' - | '\ua4fe' .. '\ua4ff' - | '\ua60d' .. '\ua60f' - | '\ua673' - | '\ua67e' - | '\ua6f2' .. '\ua6f7' - | '\ua874' .. '\ua877' - | '\ua8ce' .. '\ua8cf' - | '\ua8f8' .. '\ua8fa' - | '\ua92e' .. '\ua92f' - | '\ua95f' - | '\ua9c1' .. '\ua9cd' - | '\ua9de' .. '\ua9df' - | '\uaa5c' .. '\uaa5f' - | '\uaade' .. '\uaadf' - | '\uabeb' - | '\ufe10' .. '\ufe16' - | '\ufe19' - | '\ufe30' - | '\ufe45' .. '\ufe46' - | '\ufe49' .. '\ufe4c' - | '\ufe50' .. '\ufe57' - | '\ufe5f' .. '\ufe61' - | '\ufe68' - | '\ufe6a' .. '\ufe6b' - | '\uff01' .. '\uff03' - | '\uff05' .. '\uff07' - | '\uff0a' - | '\uff0c' - | '\uff0e' .. '\uff0f' - | '\uff1a' .. '\uff1b' - | '\uff1f' .. '\uff20' - | '\uff3c' - | '\uff61' - | '\uff64' .. '\uff65' - | '\U00010100' .. '\U00010101' - | '\U0001039f' - | '\U000103d0' - | '\U00010857' - | '\U0001091f' - | '\U0001093f' - | '\U00010a50' .. '\U00010a58' - | '\U00010a7f' - | '\U00010b39' .. '\U00010b3f' - | '\U00011047' .. '\U0001104d' - | '\U000110bb' .. '\U000110bc' - | '\U000110be' .. '\U000110c1' - | '\U00012470' .. '\U00012473' - => true, - _ => false - }; + bsearch_range_table(c, Po_table) } + static Ps_table : &'static [(char,char)] = &[ + ('\x28', '\x28'), ('\x5b', '\x5b'), + ('\x7b', '\x7b'), ('\u0f3a', '\u0f3a'), + ('\u0f3c', '\u0f3c'), ('\u169b', '\u169b'), + ('\u201a', '\u201a'), ('\u201e', '\u201e'), + ('\u2045', '\u2045'), ('\u207d', '\u207d'), + ('\u208d', '\u208d'), ('\u2329', '\u2329'), + ('\u2768', '\u2768'), ('\u276a', '\u276a'), + ('\u276c', '\u276c'), ('\u276e', '\u276e'), + ('\u2770', '\u2770'), ('\u2772', '\u2772'), + ('\u2774', '\u2774'), ('\u27c5', '\u27c5'), + ('\u27e6', '\u27e6'), ('\u27e8', '\u27e8'), + ('\u27ea', '\u27ea'), ('\u27ec', '\u27ec'), + ('\u27ee', '\u27ee'), ('\u2983', '\u2983'), + ('\u2985', '\u2985'), ('\u2987', '\u2987'), + ('\u2989', '\u2989'), ('\u298b', '\u298b'), + ('\u298d', '\u298d'), ('\u298f', '\u298f'), + ('\u2991', '\u2991'), ('\u2993', '\u2993'), + ('\u2995', '\u2995'), ('\u2997', '\u2997'), + ('\u29d8', '\u29d8'), ('\u29da', '\u29da'), + ('\u29fc', '\u29fc'), ('\u2e22', '\u2e22'), + ('\u2e24', '\u2e24'), ('\u2e26', '\u2e26'), + ('\u2e28', '\u2e28'), ('\u3008', '\u3008'), + ('\u300a', '\u300a'), ('\u300c', '\u300c'), + ('\u300e', '\u300e'), ('\u3010', '\u3010'), + ('\u3014', '\u3014'), ('\u3016', '\u3016'), + ('\u3018', '\u3018'), ('\u301a', '\u301a'), + ('\u301d', '\u301d'), ('\ufd3e', '\ufd3e'), + ('\ufe17', '\ufe17'), ('\ufe35', '\ufe35'), + ('\ufe37', '\ufe37'), ('\ufe39', '\ufe39'), + ('\ufe3b', '\ufe3b'), ('\ufe3d', '\ufe3d'), + ('\ufe3f', '\ufe3f'), ('\ufe41', '\ufe41'), + ('\ufe43', '\ufe43'), ('\ufe47', '\ufe47'), + ('\ufe59', '\ufe59'), ('\ufe5b', '\ufe5b'), + ('\ufe5d', '\ufe5d'), ('\uff08', '\uff08'), + ('\uff3b', '\uff3b'), ('\uff5b', '\uff5b'), + ('\uff5f', '\uff5f'), ('\uff62', '\uff62') + ]; + pub fn Ps(c: char) -> bool { - return match c { - '\x28' - | '\x5b' - | '\x7b' - | '\u0f3a' - | '\u0f3c' - | '\u169b' - | '\u201a' - | '\u201e' - | '\u2045' - | '\u207d' - | '\u208d' - | '\u2329' - | '\u2768' - | '\u276a' - | '\u276c' - | '\u276e' - | '\u2770' - | '\u2772' - | '\u2774' - | '\u27c5' - | '\u27e6' - | '\u27e8' - | '\u27ea' - | '\u27ec' - | '\u27ee' - | '\u2983' - | '\u2985' - | '\u2987' - | '\u2989' - | '\u298b' - | '\u298d' - | '\u298f' - | '\u2991' - | '\u2993' - | '\u2995' - | '\u2997' - | '\u29d8' - | '\u29da' - | '\u29fc' - | '\u2e22' - | '\u2e24' - | '\u2e26' - | '\u2e28' - | '\u3008' - | '\u300a' - | '\u300c' - | '\u300e' - | '\u3010' - | '\u3014' - | '\u3016' - | '\u3018' - | '\u301a' - | '\u301d' - | '\ufd3e' - | '\ufe17' - | '\ufe35' - | '\ufe37' - | '\ufe39' - | '\ufe3b' - | '\ufe3d' - | '\ufe3f' - | '\ufe41' - | '\ufe43' - | '\ufe47' - | '\ufe59' - | '\ufe5b' - | '\ufe5d' - | '\uff08' - | '\uff3b' - | '\uff5b' - | '\uff5f' - | '\uff62' - => true, - _ => false - }; + bsearch_range_table(c, Ps_table) } + static Sc_table : &'static [(char,char)] = &[ + ('\x24', '\x24'), ('\xa2', '\xa5'), + ('\u058f', '\u058f'), ('\u060b', '\u060b'), + ('\u09f2', '\u09f3'), ('\u09fb', '\u09fb'), + ('\u0af1', '\u0af1'), ('\u0bf9', '\u0bf9'), + ('\u0e3f', '\u0e3f'), ('\u17db', '\u17db'), + ('\u20a0', '\u20ba'), ('\ua838', '\ua838'), + ('\ufdfc', '\ufdfc'), ('\ufe69', '\ufe69'), + ('\uff04', '\uff04'), ('\uffe0', '\uffe1'), + ('\uffe5', '\uffe6') + ]; + pub fn Sc(c: char) -> bool { - return match c { - '\x24' - | '\xa2' .. '\xa5' - | '\u060b' - | '\u09f2' .. '\u09f3' - | '\u09fb' - | '\u0af1' - | '\u0bf9' - | '\u0e3f' - | '\u17db' - | '\u20a0' .. '\u20b9' - | '\ua838' - | '\ufdfc' - | '\ufe69' - | '\uff04' - | '\uffe0' .. '\uffe1' - | '\uffe5' .. '\uffe6' - => true, - _ => false - }; + bsearch_range_table(c, Sc_table) } + static Sk_table : &'static [(char,char)] = &[ + ('\x5e', '\x5e'), ('\x60', '\x60'), + ('\xa8', '\xa8'), ('\xaf', '\xaf'), + ('\xb4', '\xb4'), ('\xb8', '\xb8'), + ('\u02c2', '\u02c5'), ('\u02d2', '\u02df'), + ('\u02e5', '\u02eb'), ('\u02ed', '\u02ed'), + ('\u02ef', '\u02ff'), ('\u0375', '\u0375'), + ('\u0384', '\u0385'), ('\u1fbd', '\u1fbd'), + ('\u1fbf', '\u1fc1'), ('\u1fcd', '\u1fcf'), + ('\u1fdd', '\u1fdf'), ('\u1fed', '\u1fef'), + ('\u1ffd', '\u1ffe'), ('\u309b', '\u309c'), + ('\ua700', '\ua716'), ('\ua720', '\ua721'), + ('\ua789', '\ua78a'), ('\ufbb2', '\ufbc1'), + ('\uff3e', '\uff3e'), ('\uff40', '\uff40'), + ('\uffe3', '\uffe3') + ]; + pub fn Sk(c: char) -> bool { - return match c { - '\x5e' - | '\x60' - | '\xa8' - | '\xaf' - | '\xb4' - | '\xb8' - | '\u02c2' .. '\u02c5' - | '\u02d2' .. '\u02df' - | '\u02e5' .. '\u02eb' - | '\u02ed' - | '\u02ef' .. '\u02ff' - | '\u0375' - | '\u0384' .. '\u0385' - | '\u1fbd' - | '\u1fbf' .. '\u1fc1' - | '\u1fcd' .. '\u1fcf' - | '\u1fdd' .. '\u1fdf' - | '\u1fed' .. '\u1fef' - | '\u1ffd' .. '\u1ffe' - | '\u309b' .. '\u309c' - | '\ua700' .. '\ua716' - | '\ua720' .. '\ua721' - | '\ua789' .. '\ua78a' - | '\ufbb2' .. '\ufbc1' - | '\uff3e' - | '\uff40' - | '\uffe3' - => true, - _ => false - }; + bsearch_range_table(c, Sk_table) } + static Sm_table : &'static [(char,char)] = &[ + ('\x2b', '\x2b'), ('\x3c', '\x3e'), + ('\x7c', '\x7c'), ('\x7e', '\x7e'), + ('\xac', '\xac'), ('\xb1', '\xb1'), + ('\xd7', '\xd7'), ('\xf7', '\xf7'), + ('\u03f6', '\u03f6'), ('\u0606', '\u0608'), + ('\u2044', '\u2044'), ('\u2052', '\u2052'), + ('\u207a', '\u207c'), ('\u208a', '\u208c'), + ('\u2118', '\u2118'), ('\u2140', '\u2144'), + ('\u214b', '\u214b'), ('\u2190', '\u2194'), + ('\u219a', '\u219b'), ('\u21a0', '\u21a0'), + ('\u21a3', '\u21a3'), ('\u21a6', '\u21a6'), + ('\u21ae', '\u21ae'), ('\u21ce', '\u21cf'), + ('\u21d2', '\u21d2'), ('\u21d4', '\u21d4'), + ('\u21f4', '\u22ff'), ('\u2308', '\u230b'), + ('\u2320', '\u2321'), ('\u237c', '\u237c'), + ('\u239b', '\u23b3'), ('\u23dc', '\u23e1'), + ('\u25b7', '\u25b7'), ('\u25c1', '\u25c1'), + ('\u25f8', '\u25ff'), ('\u266f', '\u266f'), + ('\u27c0', '\u27c4'), ('\u27c7', '\u27e5'), + ('\u27f0', '\u27ff'), ('\u2900', '\u2982'), + ('\u2999', '\u29d7'), ('\u29dc', '\u29fb'), + ('\u29fe', '\u2aff'), ('\u2b30', '\u2b44'), + ('\u2b47', '\u2b4c'), ('\ufb29', '\ufb29'), + ('\ufe62', '\ufe62'), ('\ufe64', '\ufe66'), + ('\uff0b', '\uff0b'), ('\uff1c', '\uff1e'), + ('\uff5c', '\uff5c'), ('\uff5e', '\uff5e'), + ('\uffe2', '\uffe2'), ('\uffe9', '\uffec'), + ('\U0001d6c1', '\U0001d6c1'), ('\U0001d6db', '\U0001d6db'), + ('\U0001d6fb', '\U0001d6fb'), ('\U0001d715', '\U0001d715'), + ('\U0001d735', '\U0001d735'), ('\U0001d74f', '\U0001d74f'), + ('\U0001d76f', '\U0001d76f'), ('\U0001d789', '\U0001d789'), + ('\U0001d7a9', '\U0001d7a9'), ('\U0001d7c3', '\U0001d7c3'), + ('\U0001eef0', '\U0001eef1') + ]; + pub fn Sm(c: char) -> bool { - return match c { - '\x2b' - | '\x3c' .. '\x3e' - | '\x7c' - | '\x7e' - | '\xac' - | '\xb1' - | '\xd7' - | '\xf7' - | '\u03f6' - | '\u0606' .. '\u0608' - | '\u2044' - | '\u2052' - | '\u207a' .. '\u207c' - | '\u208a' .. '\u208c' - | '\u2118' - | '\u2140' .. '\u2144' - | '\u214b' - | '\u2190' .. '\u2194' - | '\u219a' .. '\u219b' - | '\u21a0' - | '\u21a3' - | '\u21a6' - | '\u21ae' - | '\u21ce' .. '\u21cf' - | '\u21d2' - | '\u21d4' - | '\u21f4' .. '\u22ff' - | '\u2308' .. '\u230b' - | '\u2320' .. '\u2321' - | '\u237c' - | '\u239b' .. '\u23b3' - | '\u23dc' .. '\u23e1' - | '\u25b7' - | '\u25c1' - | '\u25f8' .. '\u25ff' - | '\u266f' - | '\u27c0' .. '\u27c4' - | '\u27c7' .. '\u27e5' - | '\u27f0' .. '\u27ff' - | '\u2900' .. '\u2982' - | '\u2999' .. '\u29d7' - | '\u29dc' .. '\u29fb' - | '\u29fe' .. '\u2aff' - | '\u2b30' .. '\u2b44' - | '\u2b47' .. '\u2b4c' - | '\ufb29' - | '\ufe62' - | '\ufe64' .. '\ufe66' - | '\uff0b' - | '\uff1c' .. '\uff1e' - | '\uff5c' - | '\uff5e' - | '\uffe2' - | '\uffe9' .. '\uffec' - | '\U0001d6c1' - | '\U0001d6db' - | '\U0001d6fb' - | '\U0001d715' - | '\U0001d735' - | '\U0001d74f' - | '\U0001d76f' - | '\U0001d789' - | '\U0001d7a9' - | '\U0001d7c3' - => true, - _ => false - }; + bsearch_range_table(c, Sm_table) } + static So_table : &'static [(char,char)] = &[ + ('\xa6', '\xa6'), ('\xa9', '\xa9'), + ('\xae', '\xae'), ('\xb0', '\xb0'), + ('\u0482', '\u0482'), ('\u060e', '\u060f'), + ('\u06de', '\u06de'), ('\u06e9', '\u06e9'), + ('\u06fd', '\u06fe'), ('\u07f6', '\u07f6'), + ('\u09fa', '\u09fa'), ('\u0b70', '\u0b70'), + ('\u0bf3', '\u0bf8'), ('\u0bfa', '\u0bfa'), + ('\u0c7f', '\u0c7f'), ('\u0d79', '\u0d79'), + ('\u0f01', '\u0f03'), ('\u0f13', '\u0f13'), + ('\u0f15', '\u0f17'), ('\u0f1a', '\u0f1f'), + ('\u0f34', '\u0f34'), ('\u0f36', '\u0f36'), + ('\u0f38', '\u0f38'), ('\u0fbe', '\u0fc5'), + ('\u0fc7', '\u0fcf'), ('\u0fd5', '\u0fd8'), + ('\u109e', '\u109f'), ('\u1390', '\u1399'), + ('\u1940', '\u1940'), ('\u19de', '\u19ff'), + ('\u1b61', '\u1b6a'), ('\u1b74', '\u1b7c'), + ('\u2100', '\u2101'), ('\u2103', '\u2106'), + ('\u2108', '\u2109'), ('\u2114', '\u2114'), + ('\u2116', '\u2117'), ('\u211e', '\u2123'), + ('\u2125', '\u2125'), ('\u2127', '\u2127'), + ('\u2129', '\u2129'), ('\u212e', '\u212e'), + ('\u213a', '\u213b'), ('\u214a', '\u214a'), + ('\u214c', '\u214d'), ('\u214f', '\u214f'), + ('\u2195', '\u2199'), ('\u219c', '\u219f'), + ('\u21a1', '\u21a2'), ('\u21a4', '\u21a5'), + ('\u21a7', '\u21ad'), ('\u21af', '\u21cd'), + ('\u21d0', '\u21d1'), ('\u21d3', '\u21d3'), + ('\u21d5', '\u21f3'), ('\u2300', '\u2307'), + ('\u230c', '\u231f'), ('\u2322', '\u2328'), + ('\u232b', '\u237b'), ('\u237d', '\u239a'), + ('\u23b4', '\u23db'), ('\u23e2', '\u244a'), + ('\u249c', '\u24e9'), ('\u2500', '\u25b6'), + ('\u25b8', '\u25c0'), ('\u25c2', '\u25f7'), + ('\u2600', '\u266e'), ('\u2670', '\u2767'), + ('\u2794', '\u27bf'), ('\u2800', '\u28ff'), + ('\u2b00', '\u2b2f'), ('\u2b45', '\u2b46'), + ('\u2b50', '\u2b59'), ('\u2ce5', '\u2cea'), + ('\u2e80', '\u2ffb'), ('\u3004', '\u3004'), + ('\u3012', '\u3013'), ('\u3020', '\u3020'), + ('\u3036', '\u3037'), ('\u303e', '\u303f'), + ('\u3190', '\u3191'), ('\u3196', '\u319f'), + ('\u31c0', '\u31e3'), ('\u3200', '\u321e'), + ('\u322a', '\u3247'), ('\u3250', '\u3250'), + ('\u3260', '\u327f'), ('\u328a', '\u32b0'), + ('\u32c0', '\u33ff'), ('\u4dc0', '\u4dff'), + ('\ua490', '\ua4c6'), ('\ua828', '\ua82b'), + ('\ua836', '\ua837'), ('\ua839', '\ua839'), + ('\uaa77', '\uaa79'), ('\ufdfd', '\ufdfd'), + ('\uffe4', '\uffe4'), ('\uffe8', '\uffe8'), + ('\uffed', '\uffee'), ('\ufffc', '\ufffd'), + ('\U00010137', '\U0001013f'), ('\U00010179', '\U00010189'), + ('\U00010190', '\U000101fc'), ('\U0001d000', '\U0001d164'), + ('\U0001d16a', '\U0001d16c'), ('\U0001d183', '\U0001d184'), + ('\U0001d18c', '\U0001d1a9'), ('\U0001d1ae', '\U0001d241'), + ('\U0001d245', '\U0001d356'), ('\U0001f000', '\U0001f0df'), + ('\U0001f110', '\U0001f773') + ]; + pub fn So(c: char) -> bool { - return match c { - '\xa6' .. '\xa7' - | '\xa9' - | '\xae' - | '\xb0' - | '\xb6' - | '\u0482' - | '\u060e' .. '\u060f' - | '\u06de' - | '\u06e9' - | '\u06fd' .. '\u06fe' - | '\u07f6' - | '\u09fa' - | '\u0b70' - | '\u0bf3' .. '\u0bf8' - | '\u0bfa' - | '\u0c7f' - | '\u0d79' - | '\u0f01' .. '\u0f03' - | '\u0f13' .. '\u0f17' - | '\u0f1a' .. '\u0f1f' - | '\u0f34' - | '\u0f36' - | '\u0f38' - | '\u0fbe' .. '\u0fc5' - | '\u0fc7' .. '\u0fcf' - | '\u0fd5' .. '\u0fd8' - | '\u109e' .. '\u109f' - | '\u1360' - | '\u1390' .. '\u1399' - | '\u1940' - | '\u19de' .. '\u19ff' - | '\u1b61' .. '\u1b6a' - | '\u1b74' .. '\u1b7c' - | '\u2100' .. '\u2101' - | '\u2103' .. '\u2106' - | '\u2108' .. '\u2109' - | '\u2114' - | '\u2116' .. '\u2117' - | '\u211e' .. '\u2123' - | '\u2125' - | '\u2127' - | '\u2129' - | '\u212e' - | '\u213a' .. '\u213b' - | '\u214a' - | '\u214c' .. '\u214d' - | '\u214f' - | '\u2195' .. '\u2199' - | '\u219c' .. '\u219f' - | '\u21a1' .. '\u21a2' - | '\u21a4' .. '\u21a5' - | '\u21a7' .. '\u21ad' - | '\u21af' .. '\u21cd' - | '\u21d0' .. '\u21d1' - | '\u21d3' - | '\u21d5' .. '\u21f3' - | '\u2300' .. '\u2307' - | '\u230c' .. '\u231f' - | '\u2322' .. '\u2328' - | '\u232b' .. '\u237b' - | '\u237d' .. '\u239a' - | '\u23b4' .. '\u23db' - | '\u23e2' .. '\u244a' - | '\u249c' .. '\u24e9' - | '\u2500' .. '\u25b6' - | '\u25b8' .. '\u25c0' - | '\u25c2' .. '\u25f7' - | '\u2600' .. '\u266e' - | '\u2670' .. '\u2767' - | '\u2794' .. '\u27bf' - | '\u2800' .. '\u28ff' - | '\u2b00' .. '\u2b2f' - | '\u2b45' .. '\u2b46' - | '\u2b50' .. '\u2b59' - | '\u2ce5' .. '\u2cea' - | '\u2e80' .. '\u2ffb' - | '\u3004' - | '\u3012' .. '\u3013' - | '\u3020' - | '\u3036' .. '\u3037' - | '\u303e' .. '\u303f' - | '\u3190' .. '\u3191' - | '\u3196' .. '\u319f' - | '\u31c0' .. '\u31e3' - | '\u3200' .. '\u321e' - | '\u322a' .. '\u3250' - | '\u3260' .. '\u327f' - | '\u328a' .. '\u32b0' - | '\u32c0' .. '\u33ff' - | '\u4dc0' .. '\u4dff' - | '\ua490' .. '\ua4c6' - | '\ua828' .. '\ua82b' - | '\ua836' .. '\ua837' - | '\ua839' - | '\uaa77' .. '\uaa79' - | '\ufdfd' - | '\uffe4' - | '\uffe8' - | '\uffed' .. '\uffee' - | '\ufffc' .. '\ufffd' - | '\U00010102' - | '\U00010137' .. '\U0001013f' - | '\U00010179' .. '\U00010189' - | '\U00010190' .. '\U000101fc' - | '\U0001d000' .. '\U0001d164' - | '\U0001d16a' .. '\U0001d16c' - | '\U0001d183' .. '\U0001d184' - | '\U0001d18c' .. '\U0001d1a9' - | '\U0001d1ae' .. '\U0001d241' - | '\U0001d245' .. '\U0001d356' - | '\U0001f000' .. '\U0001f0df' - | '\U0001f110' .. '\U0001f773' - => true, - _ => false - }; + bsearch_range_table(c, So_table) } + static Zl_table : &'static [(char,char)] = &[ + ('\u2028', '\u2028') + ]; + pub fn Zl(c: char) -> bool { - return match c { - '\u2028' => true, - _ => false - }; + bsearch_range_table(c, Zl_table) } + static Zp_table : &'static [(char,char)] = &[ + ('\u2029', '\u2029') + ]; + pub fn Zp(c: char) -> bool { - return match c { - '\u2029' => true, - _ => false - }; + bsearch_range_table(c, Zp_table) } + static Zs_table : &'static [(char,char)] = &[ + ('\x20', '\x20'), ('\xa0', '\xa0'), + ('\u1680', '\u1680'), ('\u180e', '\u180e'), + ('\u2000', '\u200a'), ('\u202f', '\u202f'), + ('\u205f', '\u205f'), ('\u3000', '\u3000') + ]; + pub fn Zs(c: char) -> bool { - return match c { - '\x20' - | '\xa0' - | '\u1680' - | '\u180e' - | '\u2000' .. '\u200a' - | '\u202f' - | '\u205f' - | '\u3000' - => true, - _ => false - }; + bsearch_range_table(c, Zs_table) } } -mod derived_property { - /// Check if a character has the alphabetic unicode property + +pub mod derived_property { + + + fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { + use cmp::{Equal, Less, Greater}; + use vec::bsearch; + use option::None; + (do bsearch(r) |&(lo,hi)| { + if lo <= c && c <= hi { Equal } + else if hi < c { Less } + else { Greater } + }) != None + } + + + static Alphabetic_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xba', '\xba'), ('\xc0', '\xd6'), + ('\xd8', '\xf6'), ('\xf8', '\u01ba'), + ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), + ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), + ('\u0294', '\u0294'), ('\u0295', '\u02af'), + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0345', '\u0345'), + ('\u0370', '\u0373'), ('\u0374', '\u0374'), + ('\u0376', '\u0377'), ('\u037a', '\u037a'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0388', '\u038a'), ('\u038c', '\u038c'), + ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), + ('\u03f7', '\u0481'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u05b0', '\u05bd'), + ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), + ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), + ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), + ('\u0610', '\u061a'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u064b', '\u0657'), ('\u0659', '\u065f'), + ('\u066e', '\u066f'), ('\u0670', '\u0670'), + ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), + ('\u06d6', '\u06dc'), ('\u06e1', '\u06e4'), + ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), + ('\u06ed', '\u06ed'), ('\u06ee', '\u06ef'), + ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), + ('\u0710', '\u0710'), ('\u0711', '\u0711'), + ('\u0712', '\u072f'), ('\u0730', '\u073f'), + ('\u074d', '\u07a5'), ('\u07a6', '\u07b0'), + ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u0800', '\u0815'), ('\u0816', '\u0817'), + ('\u081a', '\u081a'), ('\u081b', '\u0823'), + ('\u0824', '\u0824'), ('\u0825', '\u0827'), + ('\u0828', '\u0828'), ('\u0829', '\u082c'), + ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u08e4', '\u08e9'), + ('\u08f0', '\u08fe'), ('\u0900', '\u0902'), + ('\u0903', '\u0903'), ('\u0904', '\u0939'), + ('\u093a', '\u093a'), ('\u093b', '\u093b'), + ('\u093d', '\u093d'), ('\u093e', '\u0940'), + ('\u0941', '\u0948'), ('\u0949', '\u094c'), + ('\u094e', '\u094f'), ('\u0950', '\u0950'), + ('\u0955', '\u0957'), ('\u0958', '\u0961'), + ('\u0962', '\u0963'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0981', '\u0981'), ('\u0982', '\u0983'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09be', '\u09c0'), + ('\u09c1', '\u09c4'), ('\u09c7', '\u09c8'), + ('\u09cb', '\u09cc'), ('\u09ce', '\u09ce'), + ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), + ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), + ('\u09f0', '\u09f1'), ('\u0a01', '\u0a02'), + ('\u0a03', '\u0a03'), ('\u0a05', '\u0a0a'), + ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), + ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), + ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), + ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), + ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4c'), + ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), + ('\u0a5e', '\u0a5e'), ('\u0a70', '\u0a71'), + ('\u0a72', '\u0a74'), ('\u0a75', '\u0a75'), + ('\u0a81', '\u0a82'), ('\u0a83', '\u0a83'), + ('\u0a85', '\u0a8d'), ('\u0a8f', '\u0a91'), + ('\u0a93', '\u0aa8'), ('\u0aaa', '\u0ab0'), + ('\u0ab2', '\u0ab3'), ('\u0ab5', '\u0ab9'), + ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), + ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), + ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), + ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), + ('\u0ae2', '\u0ae3'), ('\u0b01', '\u0b01'), + ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), + ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), + ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), + ('\u0b35', '\u0b39'), ('\u0b3d', '\u0b3d'), + ('\u0b3e', '\u0b3e'), ('\u0b3f', '\u0b3f'), + ('\u0b40', '\u0b40'), ('\u0b41', '\u0b44'), + ('\u0b47', '\u0b48'), ('\u0b4b', '\u0b4c'), + ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), + ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), + ('\u0b62', '\u0b63'), ('\u0b71', '\u0b71'), + ('\u0b82', '\u0b82'), ('\u0b83', '\u0b83'), + ('\u0b85', '\u0b8a'), ('\u0b8e', '\u0b90'), + ('\u0b92', '\u0b95'), ('\u0b99', '\u0b9a'), + ('\u0b9c', '\u0b9c'), ('\u0b9e', '\u0b9f'), + ('\u0ba3', '\u0ba4'), ('\u0ba8', '\u0baa'), + ('\u0bae', '\u0bb9'), ('\u0bbe', '\u0bbf'), + ('\u0bc0', '\u0bc0'), ('\u0bc1', '\u0bc2'), + ('\u0bc6', '\u0bc8'), ('\u0bca', '\u0bcc'), + ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), + ('\u0c01', '\u0c03'), ('\u0c05', '\u0c0c'), + ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), + ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), + ('\u0c3d', '\u0c3d'), ('\u0c3e', '\u0c40'), + ('\u0c41', '\u0c44'), ('\u0c46', '\u0c48'), + ('\u0c4a', '\u0c4c'), ('\u0c55', '\u0c56'), + ('\u0c58', '\u0c59'), ('\u0c60', '\u0c61'), + ('\u0c62', '\u0c63'), ('\u0c82', '\u0c83'), + ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), + ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), + ('\u0cb5', '\u0cb9'), ('\u0cbd', '\u0cbd'), + ('\u0cbe', '\u0cbe'), ('\u0cbf', '\u0cbf'), + ('\u0cc0', '\u0cc4'), ('\u0cc6', '\u0cc6'), + ('\u0cc7', '\u0cc8'), ('\u0cca', '\u0ccb'), + ('\u0ccc', '\u0ccc'), ('\u0cd5', '\u0cd6'), + ('\u0cde', '\u0cde'), ('\u0ce0', '\u0ce1'), + ('\u0ce2', '\u0ce3'), ('\u0cf1', '\u0cf2'), + ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), + ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), + ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), + ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), + ('\u0d4a', '\u0d4c'), ('\u0d4e', '\u0d4e'), + ('\u0d57', '\u0d57'), ('\u0d60', '\u0d61'), + ('\u0d62', '\u0d63'), ('\u0d7a', '\u0d7f'), + ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0dcf', '\u0dd1'), ('\u0dd2', '\u0dd4'), + ('\u0dd6', '\u0dd6'), ('\u0dd8', '\u0ddf'), + ('\u0df2', '\u0df3'), ('\u0e01', '\u0e30'), + ('\u0e31', '\u0e31'), ('\u0e32', '\u0e33'), + ('\u0e34', '\u0e3a'), ('\u0e40', '\u0e45'), + ('\u0e46', '\u0e46'), ('\u0e4d', '\u0e4d'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), + ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), + ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), + ('\u0ec6', '\u0ec6'), ('\u0ecd', '\u0ecd'), + ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), + ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), + ('\u0f71', '\u0f7e'), ('\u0f7f', '\u0f7f'), + ('\u0f80', '\u0f81'), ('\u0f88', '\u0f8c'), + ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), + ('\u1000', '\u102a'), ('\u102b', '\u102c'), + ('\u102d', '\u1030'), ('\u1031', '\u1031'), + ('\u1032', '\u1036'), ('\u1038', '\u1038'), + ('\u103b', '\u103c'), ('\u103d', '\u103e'), + ('\u103f', '\u103f'), ('\u1050', '\u1055'), + ('\u1056', '\u1057'), ('\u1058', '\u1059'), + ('\u105a', '\u105d'), ('\u105e', '\u1060'), + ('\u1061', '\u1061'), ('\u1062', '\u1062'), + ('\u1065', '\u1066'), ('\u1067', '\u1068'), + ('\u106e', '\u1070'), ('\u1071', '\u1074'), + ('\u1075', '\u1081'), ('\u1082', '\u1082'), + ('\u1083', '\u1084'), ('\u1085', '\u1086'), + ('\u108e', '\u108e'), ('\u109c', '\u109c'), + ('\u109d', '\u109d'), ('\u10a0', '\u10c5'), + ('\u10c7', '\u10c7'), ('\u10cd', '\u10cd'), + ('\u10d0', '\u10fa'), ('\u10fc', '\u10fc'), + ('\u10fd', '\u1248'), ('\u124a', '\u124d'), + ('\u1250', '\u1256'), ('\u1258', '\u1258'), + ('\u125a', '\u125d'), ('\u1260', '\u1288'), + ('\u128a', '\u128d'), ('\u1290', '\u12b0'), + ('\u12b2', '\u12b5'), ('\u12b8', '\u12be'), + ('\u12c0', '\u12c0'), ('\u12c2', '\u12c5'), + ('\u12c8', '\u12d6'), ('\u12d8', '\u1310'), + ('\u1312', '\u1315'), ('\u1318', '\u135a'), + ('\u135f', '\u135f'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1712', '\u1713'), ('\u1720', '\u1731'), + ('\u1732', '\u1733'), ('\u1740', '\u1751'), + ('\u1752', '\u1753'), ('\u1760', '\u176c'), + ('\u176e', '\u1770'), ('\u1772', '\u1773'), + ('\u1780', '\u17b3'), ('\u17b6', '\u17b6'), + ('\u17b7', '\u17bd'), ('\u17be', '\u17c5'), + ('\u17c6', '\u17c6'), ('\u17c7', '\u17c8'), + ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), + ('\u1820', '\u1842'), ('\u1843', '\u1843'), + ('\u1844', '\u1877'), ('\u1880', '\u18a8'), + ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1920', '\u1922'), ('\u1923', '\u1926'), + ('\u1927', '\u1928'), ('\u1929', '\u192b'), + ('\u1930', '\u1931'), ('\u1932', '\u1932'), + ('\u1933', '\u1938'), ('\u1950', '\u196d'), + ('\u1970', '\u1974'), ('\u1980', '\u19ab'), + ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), + ('\u19c8', '\u19c9'), ('\u1a00', '\u1a16'), + ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), + ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), + ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), + ('\u1a58', '\u1a5e'), ('\u1a61', '\u1a61'), + ('\u1a62', '\u1a62'), ('\u1a63', '\u1a64'), + ('\u1a65', '\u1a6c'), ('\u1a6d', '\u1a72'), + ('\u1a73', '\u1a74'), ('\u1aa7', '\u1aa7'), + ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), + ('\u1b05', '\u1b33'), ('\u1b35', '\u1b35'), + ('\u1b36', '\u1b3a'), ('\u1b3b', '\u1b3b'), + ('\u1b3c', '\u1b3c'), ('\u1b3d', '\u1b41'), + ('\u1b42', '\u1b42'), ('\u1b43', '\u1b43'), + ('\u1b45', '\u1b4b'), ('\u1b80', '\u1b81'), + ('\u1b82', '\u1b82'), ('\u1b83', '\u1ba0'), + ('\u1ba1', '\u1ba1'), ('\u1ba2', '\u1ba5'), + ('\u1ba6', '\u1ba7'), ('\u1ba8', '\u1ba9'), + ('\u1bac', '\u1bad'), ('\u1bae', '\u1baf'), + ('\u1bba', '\u1be5'), ('\u1be7', '\u1be7'), + ('\u1be8', '\u1be9'), ('\u1bea', '\u1bec'), + ('\u1bed', '\u1bed'), ('\u1bee', '\u1bee'), + ('\u1bef', '\u1bf1'), ('\u1c00', '\u1c23'), + ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), + ('\u1c34', '\u1c35'), ('\u1c4d', '\u1c4f'), + ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf2', '\u1cf3'), ('\u1cf5', '\u1cf6'), + ('\u1d00', '\u1d2b'), ('\u1d2c', '\u1d6a'), + ('\u1d6b', '\u1d77'), ('\u1d78', '\u1d78'), + ('\u1d79', '\u1d9a'), ('\u1d9b', '\u1dbf'), + ('\u1e00', '\u1f15'), ('\u1f18', '\u1f1d'), + ('\u1f20', '\u1f45'), ('\u1f48', '\u1f4d'), + ('\u1f50', '\u1f57'), ('\u1f59', '\u1f59'), + ('\u1f5b', '\u1f5b'), ('\u1f5d', '\u1f5d'), + ('\u1f5f', '\u1f7d'), ('\u1f80', '\u1fb4'), + ('\u1fb6', '\u1fbc'), ('\u1fbe', '\u1fbe'), + ('\u1fc2', '\u1fc4'), ('\u1fc6', '\u1fcc'), + ('\u1fd0', '\u1fd3'), ('\u1fd6', '\u1fdb'), + ('\u1fe0', '\u1fec'), ('\u1ff2', '\u1ff4'), + ('\u1ff6', '\u1ffc'), ('\u2071', '\u2071'), + ('\u207f', '\u207f'), ('\u2090', '\u209c'), + ('\u2102', '\u2102'), ('\u2107', '\u2107'), + ('\u210a', '\u2113'), ('\u2115', '\u2115'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u212f', '\u2134'), + ('\u2135', '\u2138'), ('\u2139', '\u2139'), + ('\u213c', '\u213f'), ('\u2145', '\u2149'), + ('\u214e', '\u214e'), ('\u2160', '\u2182'), + ('\u2183', '\u2184'), ('\u2185', '\u2188'), + ('\u24b6', '\u24e9'), ('\u2c00', '\u2c2e'), + ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), + ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), + ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), + ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), + ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), + ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), + ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), + ('\u2de0', '\u2dff'), ('\u2e2f', '\u2e2f'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309d', '\u309e'), + ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), + ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), + ('\u3105', '\u312d'), ('\u3131', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), + ('\ua000', '\ua014'), ('\ua015', '\ua015'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), + ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua674', '\ua67b'), + ('\ua67f', '\ua67f'), ('\ua680', '\ua697'), + ('\ua69f', '\ua69f'), ('\ua6a0', '\ua6e5'), + ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua823', '\ua824'), + ('\ua825', '\ua826'), ('\ua827', '\ua827'), + ('\ua840', '\ua873'), ('\ua880', '\ua881'), + ('\ua882', '\ua8b3'), ('\ua8b4', '\ua8c3'), + ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), + ('\ua90a', '\ua925'), ('\ua926', '\ua92a'), + ('\ua930', '\ua946'), ('\ua947', '\ua951'), + ('\ua952', '\ua952'), ('\ua960', '\ua97c'), + ('\ua980', '\ua982'), ('\ua983', '\ua983'), + ('\ua984', '\ua9b2'), ('\ua9b4', '\ua9b5'), + ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), + ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9bf'), + ('\ua9cf', '\ua9cf'), ('\uaa00', '\uaa28'), + ('\uaa29', '\uaa2e'), ('\uaa2f', '\uaa30'), + ('\uaa31', '\uaa32'), ('\uaa33', '\uaa34'), + ('\uaa35', '\uaa36'), ('\uaa40', '\uaa42'), + ('\uaa43', '\uaa43'), ('\uaa44', '\uaa4b'), + ('\uaa4c', '\uaa4c'), ('\uaa4d', '\uaa4d'), + ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), + ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), + ('\uaa80', '\uaaaf'), ('\uaab0', '\uaab0'), + ('\uaab1', '\uaab1'), ('\uaab2', '\uaab4'), + ('\uaab5', '\uaab6'), ('\uaab7', '\uaab8'), + ('\uaab9', '\uaabd'), ('\uaabe', '\uaabe'), + ('\uaac0', '\uaac0'), ('\uaac2', '\uaac2'), + ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), + ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), + ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uaaf5', '\uaaf5'), ('\uab01', '\uab06'), + ('\uab09', '\uab0e'), ('\uab11', '\uab16'), + ('\uab20', '\uab26'), ('\uab28', '\uab2e'), + ('\uabc0', '\uabe2'), ('\uabe3', '\uabe4'), + ('\uabe5', '\uabe5'), ('\uabe6', '\uabe7'), + ('\uabe8', '\uabe8'), ('\uabe9', '\uabea'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), + ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), + ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), + ('\ufbd3', '\ufd3d'), ('\ufd50', '\ufd8f'), + ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdfb'), + ('\ufe70', '\ufe74'), ('\ufe76', '\ufefc'), + ('\uff21', '\uff3a'), ('\uff41', '\uff5a'), + ('\uff66', '\uff6f'), ('\uff70', '\uff70'), + ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), + ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), + ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), + ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), + ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), + ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), + ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), + ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), + ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), + ('\U00010a19', '\U00010a33'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), + ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), + ('\U00011038', '\U00011045'), ('\U00011082', '\U00011082'), + ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), + ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), + ('\U000110d0', '\U000110e8'), ('\U00011100', '\U00011102'), + ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), + ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011132'), + ('\U00011180', '\U00011181'), ('\U00011182', '\U00011182'), + ('\U00011183', '\U000111b2'), ('\U000111b3', '\U000111b5'), + ('\U000111b6', '\U000111be'), ('\U000111bf', '\U000111bf'), + ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), + ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), + ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), + ('\U000116b0', '\U000116b5'), ('\U00012000', '\U0001236e'), + ('\U00012400', '\U00012462'), ('\U00013000', '\U0001342e'), + ('\U00016800', '\U00016a38'), ('\U00016f00', '\U00016f44'), + ('\U00016f50', '\U00016f50'), ('\U00016f51', '\U00016f7e'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), + ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), + ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), + ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), + ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), + ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), + ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), + ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), + ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), + ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d') + ]; + pub fn Alphabetic(c: char) -> bool { - return match c { - '\x41' .. '\x5a' - | '\x61' .. '\x7a' - | '\xaa' - | '\xb5' - | '\xba' - | '\xc0' .. '\xd6' - | '\xd8' .. '\xf6' - | '\xf8' .. '\u01ba' - | '\u01bb' - | '\u01bc' .. '\u01bf' - | '\u01c0' .. '\u01c3' - | '\u01c4' .. '\u0293' - | '\u0294' - | '\u0295' .. '\u02af' - | '\u02b0' .. '\u02c1' - | '\u02c6' .. '\u02d1' - | '\u02e0' .. '\u02e4' - | '\u02ec' - | '\u02ee' - | '\u0345' - | '\u0370' .. '\u0373' - | '\u0374' - | '\u0376' .. '\u0377' - | '\u037a' - | '\u037b' .. '\u037d' - | '\u0386' - | '\u0388' .. '\u038a' - | '\u038c' - | '\u038e' .. '\u03a1' - | '\u03a3' .. '\u03f5' - | '\u03f7' .. '\u0481' - | '\u048a' .. '\u0527' - | '\u0531' .. '\u0556' - | '\u0559' - | '\u0561' .. '\u0587' - | '\u05b0' .. '\u05bd' - | '\u05bf' - | '\u05c1' .. '\u05c2' - | '\u05c4' .. '\u05c5' - | '\u05c7' - | '\u05d0' .. '\u05ea' - | '\u05f0' .. '\u05f2' - | '\u0610' .. '\u061a' - | '\u0620' .. '\u063f' - | '\u0640' - | '\u0641' .. '\u064a' - | '\u064b' .. '\u0657' - | '\u0659' .. '\u065f' - | '\u066e' .. '\u066f' - | '\u0670' - | '\u0671' .. '\u06d3' - | '\u06d5' - | '\u06d6' .. '\u06dc' - | '\u06e1' .. '\u06e4' - | '\u06e5' .. '\u06e6' - | '\u06e7' .. '\u06e8' - | '\u06ed' - | '\u06ee' .. '\u06ef' - | '\u06fa' .. '\u06fc' - | '\u06ff' - | '\u0710' - | '\u0711' - | '\u0712' .. '\u072f' - | '\u0730' .. '\u073f' - | '\u074d' .. '\u07a5' - | '\u07a6' .. '\u07b0' - | '\u07b1' - | '\u07ca' .. '\u07ea' - | '\u07f4' .. '\u07f5' - | '\u07fa' - | '\u0800' .. '\u0815' - | '\u0816' .. '\u0817' - | '\u081a' - | '\u081b' .. '\u0823' - | '\u0824' - | '\u0825' .. '\u0827' - | '\u0828' - | '\u0829' .. '\u082c' - | '\u0840' .. '\u0858' - | '\u0900' .. '\u0902' - | '\u0903' - | '\u0904' .. '\u0939' - | '\u093a' - | '\u093b' - | '\u093d' - | '\u093e' .. '\u0940' - | '\u0941' .. '\u0948' - | '\u0949' .. '\u094c' - | '\u094e' .. '\u094f' - | '\u0950' - | '\u0955' .. '\u0957' - | '\u0958' .. '\u0961' - | '\u0962' .. '\u0963' - | '\u0971' - | '\u0972' .. '\u0977' - | '\u0979' .. '\u097f' - | '\u0981' - | '\u0982' .. '\u0983' - | '\u0985' .. '\u098c' - | '\u098f' .. '\u0990' - | '\u0993' .. '\u09a8' - | '\u09aa' .. '\u09b0' - | '\u09b2' - | '\u09b6' .. '\u09b9' - | '\u09bd' - | '\u09be' .. '\u09c0' - | '\u09c1' .. '\u09c4' - | '\u09c7' .. '\u09c8' - | '\u09cb' .. '\u09cc' - | '\u09ce' - | '\u09d7' - | '\u09dc' .. '\u09dd' - | '\u09df' .. '\u09e1' - | '\u09e2' .. '\u09e3' - | '\u09f0' .. '\u09f1' - | '\u0a01' .. '\u0a02' - | '\u0a03' - | '\u0a05' .. '\u0a0a' - | '\u0a0f' .. '\u0a10' - | '\u0a13' .. '\u0a28' - | '\u0a2a' .. '\u0a30' - | '\u0a32' .. '\u0a33' - | '\u0a35' .. '\u0a36' - | '\u0a38' .. '\u0a39' - | '\u0a3e' .. '\u0a40' - | '\u0a41' .. '\u0a42' - | '\u0a47' .. '\u0a48' - | '\u0a4b' .. '\u0a4c' - | '\u0a51' - | '\u0a59' .. '\u0a5c' - | '\u0a5e' - | '\u0a70' .. '\u0a71' - | '\u0a72' .. '\u0a74' - | '\u0a75' - | '\u0a81' .. '\u0a82' - | '\u0a83' - | '\u0a85' .. '\u0a8d' - | '\u0a8f' .. '\u0a91' - | '\u0a93' .. '\u0aa8' - | '\u0aaa' .. '\u0ab0' - | '\u0ab2' .. '\u0ab3' - | '\u0ab5' .. '\u0ab9' - | '\u0abd' - | '\u0abe' .. '\u0ac0' - | '\u0ac1' .. '\u0ac5' - | '\u0ac7' .. '\u0ac8' - | '\u0ac9' - | '\u0acb' .. '\u0acc' - | '\u0ad0' - | '\u0ae0' .. '\u0ae1' - | '\u0ae2' .. '\u0ae3' - | '\u0b01' - | '\u0b02' .. '\u0b03' - | '\u0b05' .. '\u0b0c' - | '\u0b0f' .. '\u0b10' - | '\u0b13' .. '\u0b28' - | '\u0b2a' .. '\u0b30' - | '\u0b32' .. '\u0b33' - | '\u0b35' .. '\u0b39' - | '\u0b3d' - | '\u0b3e' - | '\u0b3f' - | '\u0b40' - | '\u0b41' .. '\u0b44' - | '\u0b47' .. '\u0b48' - | '\u0b4b' .. '\u0b4c' - | '\u0b56' - | '\u0b57' - | '\u0b5c' .. '\u0b5d' - | '\u0b5f' .. '\u0b61' - | '\u0b62' .. '\u0b63' - | '\u0b71' - | '\u0b82' - | '\u0b83' - | '\u0b85' .. '\u0b8a' - | '\u0b8e' .. '\u0b90' - | '\u0b92' .. '\u0b95' - | '\u0b99' .. '\u0b9a' - | '\u0b9c' - | '\u0b9e' .. '\u0b9f' - | '\u0ba3' .. '\u0ba4' - | '\u0ba8' .. '\u0baa' - | '\u0bae' .. '\u0bb9' - | '\u0bbe' .. '\u0bbf' - | '\u0bc0' - | '\u0bc1' .. '\u0bc2' - | '\u0bc6' .. '\u0bc8' - | '\u0bca' .. '\u0bcc' - | '\u0bd0' - | '\u0bd7' - | '\u0c01' .. '\u0c03' - | '\u0c05' .. '\u0c0c' - | '\u0c0e' .. '\u0c10' - | '\u0c12' .. '\u0c28' - | '\u0c2a' .. '\u0c33' - | '\u0c35' .. '\u0c39' - | '\u0c3d' - | '\u0c3e' .. '\u0c40' - | '\u0c41' .. '\u0c44' - | '\u0c46' .. '\u0c48' - | '\u0c4a' .. '\u0c4c' - | '\u0c55' .. '\u0c56' - | '\u0c58' .. '\u0c59' - | '\u0c60' .. '\u0c61' - | '\u0c62' .. '\u0c63' - | '\u0c82' .. '\u0c83' - | '\u0c85' .. '\u0c8c' - | '\u0c8e' .. '\u0c90' - | '\u0c92' .. '\u0ca8' - | '\u0caa' .. '\u0cb3' - | '\u0cb5' .. '\u0cb9' - | '\u0cbd' - | '\u0cbe' - | '\u0cbf' - | '\u0cc0' .. '\u0cc4' - | '\u0cc6' - | '\u0cc7' .. '\u0cc8' - | '\u0cca' .. '\u0ccb' - | '\u0ccc' - | '\u0cd5' .. '\u0cd6' - | '\u0cde' - | '\u0ce0' .. '\u0ce1' - | '\u0ce2' .. '\u0ce3' - | '\u0cf1' .. '\u0cf2' - | '\u0d02' .. '\u0d03' - | '\u0d05' .. '\u0d0c' - | '\u0d0e' .. '\u0d10' - | '\u0d12' .. '\u0d3a' - | '\u0d3d' - | '\u0d3e' .. '\u0d40' - | '\u0d41' .. '\u0d44' - | '\u0d46' .. '\u0d48' - | '\u0d4a' .. '\u0d4c' - | '\u0d4e' - | '\u0d57' - | '\u0d60' .. '\u0d61' - | '\u0d62' .. '\u0d63' - | '\u0d7a' .. '\u0d7f' - | '\u0d82' .. '\u0d83' - | '\u0d85' .. '\u0d96' - | '\u0d9a' .. '\u0db1' - | '\u0db3' .. '\u0dbb' - | '\u0dbd' - | '\u0dc0' .. '\u0dc6' - | '\u0dcf' .. '\u0dd1' - | '\u0dd2' .. '\u0dd4' - | '\u0dd6' - | '\u0dd8' .. '\u0ddf' - | '\u0df2' .. '\u0df3' - | '\u0e01' .. '\u0e30' - | '\u0e31' - | '\u0e32' .. '\u0e33' - | '\u0e34' .. '\u0e3a' - | '\u0e40' .. '\u0e45' - | '\u0e46' - | '\u0e4d' - | '\u0e81' .. '\u0e82' - | '\u0e84' - | '\u0e87' .. '\u0e88' - | '\u0e8a' - | '\u0e8d' - | '\u0e94' .. '\u0e97' - | '\u0e99' .. '\u0e9f' - | '\u0ea1' .. '\u0ea3' - | '\u0ea5' - | '\u0ea7' - | '\u0eaa' .. '\u0eab' - | '\u0ead' .. '\u0eb0' - | '\u0eb1' - | '\u0eb2' .. '\u0eb3' - | '\u0eb4' .. '\u0eb9' - | '\u0ebb' .. '\u0ebc' - | '\u0ebd' - | '\u0ec0' .. '\u0ec4' - | '\u0ec6' - | '\u0ecd' - | '\u0edc' .. '\u0edd' - | '\u0f00' - | '\u0f40' .. '\u0f47' - | '\u0f49' .. '\u0f6c' - | '\u0f71' .. '\u0f7e' - | '\u0f7f' - | '\u0f80' .. '\u0f81' - | '\u0f88' .. '\u0f8c' - | '\u0f8d' .. '\u0f97' - | '\u0f99' .. '\u0fbc' - | '\u1000' .. '\u102a' - | '\u102b' .. '\u102c' - | '\u102d' .. '\u1030' - | '\u1031' - | '\u1032' .. '\u1036' - | '\u1038' - | '\u103b' .. '\u103c' - | '\u103d' .. '\u103e' - | '\u103f' - | '\u1050' .. '\u1055' - | '\u1056' .. '\u1057' - | '\u1058' .. '\u1059' - | '\u105a' .. '\u105d' - | '\u105e' .. '\u1060' - | '\u1061' - | '\u1062' - | '\u1065' .. '\u1066' - | '\u1067' .. '\u1068' - | '\u106e' .. '\u1070' - | '\u1071' .. '\u1074' - | '\u1075' .. '\u1081' - | '\u1082' - | '\u1083' .. '\u1084' - | '\u1085' .. '\u1086' - | '\u108e' - | '\u109c' - | '\u109d' - | '\u10a0' .. '\u10c5' - | '\u10d0' .. '\u10fa' - | '\u10fc' - | '\u1100' .. '\u1248' - | '\u124a' .. '\u124d' - | '\u1250' .. '\u1256' - | '\u1258' - | '\u125a' .. '\u125d' - | '\u1260' .. '\u1288' - | '\u128a' .. '\u128d' - | '\u1290' .. '\u12b0' - | '\u12b2' .. '\u12b5' - | '\u12b8' .. '\u12be' - | '\u12c0' - | '\u12c2' .. '\u12c5' - | '\u12c8' .. '\u12d6' - | '\u12d8' .. '\u1310' - | '\u1312' .. '\u1315' - | '\u1318' .. '\u135a' - | '\u135f' - | '\u1380' .. '\u138f' - | '\u13a0' .. '\u13f4' - | '\u1401' .. '\u166c' - | '\u166f' .. '\u167f' - | '\u1681' .. '\u169a' - | '\u16a0' .. '\u16ea' - | '\u16ee' .. '\u16f0' - | '\u1700' .. '\u170c' - | '\u170e' .. '\u1711' - | '\u1712' .. '\u1713' - | '\u1720' .. '\u1731' - | '\u1732' .. '\u1733' - | '\u1740' .. '\u1751' - | '\u1752' .. '\u1753' - | '\u1760' .. '\u176c' - | '\u176e' .. '\u1770' - | '\u1772' .. '\u1773' - | '\u1780' .. '\u17b3' - | '\u17b6' - | '\u17b7' .. '\u17bd' - | '\u17be' .. '\u17c5' - | '\u17c6' - | '\u17c7' .. '\u17c8' - | '\u17d7' - | '\u17dc' - | '\u1820' .. '\u1842' - | '\u1843' - | '\u1844' .. '\u1877' - | '\u1880' .. '\u18a8' - | '\u18a9' - | '\u18aa' - | '\u18b0' .. '\u18f5' - | '\u1900' .. '\u191c' - | '\u1920' .. '\u1922' - | '\u1923' .. '\u1926' - | '\u1927' .. '\u1928' - | '\u1929' .. '\u192b' - | '\u1930' .. '\u1931' - | '\u1932' - | '\u1933' .. '\u1938' - | '\u1950' .. '\u196d' - | '\u1970' .. '\u1974' - | '\u1980' .. '\u19ab' - | '\u19b0' .. '\u19c0' - | '\u19c1' .. '\u19c7' - | '\u19c8' .. '\u19c9' - | '\u1a00' .. '\u1a16' - | '\u1a17' .. '\u1a18' - | '\u1a19' .. '\u1a1b' - | '\u1a20' .. '\u1a54' - | '\u1a55' - | '\u1a56' - | '\u1a57' - | '\u1a58' .. '\u1a5e' - | '\u1a61' - | '\u1a62' - | '\u1a63' .. '\u1a64' - | '\u1a65' .. '\u1a6c' - | '\u1a6d' .. '\u1a72' - | '\u1a73' .. '\u1a74' - | '\u1aa7' - | '\u1b00' .. '\u1b03' - | '\u1b04' - | '\u1b05' .. '\u1b33' - | '\u1b35' - | '\u1b36' .. '\u1b3a' - | '\u1b3b' - | '\u1b3c' - | '\u1b3d' .. '\u1b41' - | '\u1b42' - | '\u1b43' - | '\u1b45' .. '\u1b4b' - | '\u1b80' .. '\u1b81' - | '\u1b82' - | '\u1b83' .. '\u1ba0' - | '\u1ba1' - | '\u1ba2' .. '\u1ba5' - | '\u1ba6' .. '\u1ba7' - | '\u1ba8' .. '\u1ba9' - | '\u1bae' .. '\u1baf' - | '\u1bc0' .. '\u1be5' - | '\u1be7' - | '\u1be8' .. '\u1be9' - | '\u1bea' .. '\u1bec' - | '\u1bed' - | '\u1bee' - | '\u1bef' .. '\u1bf1' - | '\u1c00' .. '\u1c23' - | '\u1c24' .. '\u1c2b' - | '\u1c2c' .. '\u1c33' - | '\u1c34' .. '\u1c35' - | '\u1c4d' .. '\u1c4f' - | '\u1c5a' .. '\u1c77' - | '\u1c78' .. '\u1c7d' - | '\u1ce9' .. '\u1cec' - | '\u1cee' .. '\u1cf1' - | '\u1cf2' - | '\u1d00' .. '\u1d2b' - | '\u1d2c' .. '\u1d61' - | '\u1d62' .. '\u1d77' - | '\u1d78' - | '\u1d79' .. '\u1d9a' - | '\u1d9b' .. '\u1dbf' - | '\u1e00' .. '\u1f15' - | '\u1f18' .. '\u1f1d' - | '\u1f20' .. '\u1f45' - | '\u1f48' .. '\u1f4d' - | '\u1f50' .. '\u1f57' - | '\u1f59' - | '\u1f5b' - | '\u1f5d' - | '\u1f5f' .. '\u1f7d' - | '\u1f80' .. '\u1fb4' - | '\u1fb6' .. '\u1fbc' - | '\u1fbe' - | '\u1fc2' .. '\u1fc4' - | '\u1fc6' .. '\u1fcc' - | '\u1fd0' .. '\u1fd3' - | '\u1fd6' .. '\u1fdb' - | '\u1fe0' .. '\u1fec' - | '\u1ff2' .. '\u1ff4' - | '\u1ff6' .. '\u1ffc' - | '\u2071' - | '\u207f' - | '\u2090' .. '\u209c' - | '\u2102' - | '\u2107' - | '\u210a' .. '\u2113' - | '\u2115' - | '\u2119' .. '\u211d' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212a' .. '\u212d' - | '\u212f' .. '\u2134' - | '\u2135' .. '\u2138' - | '\u2139' - | '\u213c' .. '\u213f' - | '\u2145' .. '\u2149' - | '\u214e' - | '\u2160' .. '\u2182' - | '\u2183' .. '\u2184' - | '\u2185' .. '\u2188' - | '\u24b6' .. '\u24e9' - | '\u2c00' .. '\u2c2e' - | '\u2c30' .. '\u2c5e' - | '\u2c60' .. '\u2c7c' - | '\u2c7d' - | '\u2c7e' .. '\u2ce4' - | '\u2ceb' .. '\u2cee' - | '\u2d00' .. '\u2d25' - | '\u2d30' .. '\u2d65' - | '\u2d6f' - | '\u2d80' .. '\u2d96' - | '\u2da0' .. '\u2da6' - | '\u2da8' .. '\u2dae' - | '\u2db0' .. '\u2db6' - | '\u2db8' .. '\u2dbe' - | '\u2dc0' .. '\u2dc6' - | '\u2dc8' .. '\u2dce' - | '\u2dd0' .. '\u2dd6' - | '\u2dd8' .. '\u2dde' - | '\u2de0' .. '\u2dff' - | '\u2e2f' - | '\u3005' - | '\u3006' - | '\u3007' - | '\u3021' .. '\u3029' - | '\u3031' .. '\u3035' - | '\u3038' .. '\u303a' - | '\u303b' - | '\u303c' - | '\u3041' .. '\u3096' - | '\u309d' .. '\u309e' - | '\u309f' - | '\u30a1' .. '\u30fa' - | '\u30fc' .. '\u30fe' - | '\u30ff' - | '\u3105' .. '\u312d' - | '\u3131' .. '\u318e' - | '\u31a0' .. '\u31ba' - | '\u31f0' .. '\u31ff' - | '\u3400' .. '\u4db5' - | '\u4e00' .. '\u9fcb' - | '\ua000' .. '\ua014' - | '\ua015' - | '\ua016' .. '\ua48c' - | '\ua4d0' .. '\ua4f7' - | '\ua4f8' .. '\ua4fd' - | '\ua500' .. '\ua60b' - | '\ua60c' - | '\ua610' .. '\ua61f' - | '\ua62a' .. '\ua62b' - | '\ua640' .. '\ua66d' - | '\ua66e' - | '\ua67f' - | '\ua680' .. '\ua697' - | '\ua6a0' .. '\ua6e5' - | '\ua6e6' .. '\ua6ef' - | '\ua717' .. '\ua71f' - | '\ua722' .. '\ua76f' - | '\ua770' - | '\ua771' .. '\ua787' - | '\ua788' - | '\ua78b' .. '\ua78e' - | '\ua790' .. '\ua791' - | '\ua7a0' .. '\ua7a9' - | '\ua7fa' - | '\ua7fb' .. '\ua801' - | '\ua803' .. '\ua805' - | '\ua807' .. '\ua80a' - | '\ua80c' .. '\ua822' - | '\ua823' .. '\ua824' - | '\ua825' .. '\ua826' - | '\ua827' - | '\ua840' .. '\ua873' - | '\ua880' .. '\ua881' - | '\ua882' .. '\ua8b3' - | '\ua8b4' .. '\ua8c3' - | '\ua8f2' .. '\ua8f7' - | '\ua8fb' - | '\ua90a' .. '\ua925' - | '\ua926' .. '\ua92a' - | '\ua930' .. '\ua946' - | '\ua947' .. '\ua951' - | '\ua952' - | '\ua960' .. '\ua97c' - | '\ua980' .. '\ua982' - | '\ua983' - | '\ua984' .. '\ua9b2' - | '\ua9b4' .. '\ua9b5' - | '\ua9b6' .. '\ua9b9' - | '\ua9ba' .. '\ua9bb' - | '\ua9bc' - | '\ua9bd' .. '\ua9bf' - | '\ua9cf' - | '\uaa00' .. '\uaa28' - | '\uaa29' .. '\uaa2e' - | '\uaa2f' .. '\uaa30' - | '\uaa31' .. '\uaa32' - | '\uaa33' .. '\uaa34' - | '\uaa35' .. '\uaa36' - | '\uaa40' .. '\uaa42' - | '\uaa43' - | '\uaa44' .. '\uaa4b' - | '\uaa4c' - | '\uaa4d' - | '\uaa60' .. '\uaa6f' - | '\uaa70' - | '\uaa71' .. '\uaa76' - | '\uaa7a' - | '\uaa80' .. '\uaaaf' - | '\uaab0' - | '\uaab1' - | '\uaab2' .. '\uaab4' - | '\uaab5' .. '\uaab6' - | '\uaab7' .. '\uaab8' - | '\uaab9' .. '\uaabd' - | '\uaabe' - | '\uaac0' - | '\uaac2' - | '\uaadb' .. '\uaadc' - | '\uaadd' - | '\uab01' .. '\uab06' - | '\uab09' .. '\uab0e' - | '\uab11' .. '\uab16' - | '\uab20' .. '\uab26' - | '\uab28' .. '\uab2e' - | '\uabc0' .. '\uabe2' - | '\uabe3' .. '\uabe4' - | '\uabe5' - | '\uabe6' .. '\uabe7' - | '\uabe8' - | '\uabe9' .. '\uabea' - | '\uac00' .. '\ud7a3' - | '\ud7b0' .. '\ud7c6' - | '\ud7cb' .. '\ud7fb' - | '\uf900' .. '\ufa2d' - | '\ufa30' .. '\ufa6d' - | '\ufa70' .. '\ufad9' - | '\ufb00' .. '\ufb06' - | '\ufb13' .. '\ufb17' - | '\ufb1d' - | '\ufb1e' - | '\ufb1f' .. '\ufb28' - | '\ufb2a' .. '\ufb36' - | '\ufb38' .. '\ufb3c' - | '\ufb3e' - | '\ufb40' .. '\ufb41' - | '\ufb43' .. '\ufb44' - | '\ufb46' .. '\ufbb1' - | '\ufbd3' .. '\ufd3d' - | '\ufd50' .. '\ufd8f' - | '\ufd92' .. '\ufdc7' - | '\ufdf0' .. '\ufdfb' - | '\ufe70' .. '\ufe74' - | '\ufe76' .. '\ufefc' - | '\uff21' .. '\uff3a' - | '\uff41' .. '\uff5a' - | '\uff66' .. '\uff6f' - | '\uff70' - | '\uff71' .. '\uff9d' - | '\uff9e' .. '\uff9f' - | '\uffa0' .. '\uffbe' - | '\uffc2' .. '\uffc7' - | '\uffca' .. '\uffcf' - | '\uffd2' .. '\uffd7' - | '\uffda' .. '\uffdc' - | '\U00010000' .. '\U0001000b' - | '\U0001000d' .. '\U00010026' - | '\U00010028' .. '\U0001003a' - | '\U0001003c' .. '\U0001003d' - | '\U0001003f' .. '\U0001004d' - | '\U00010050' .. '\U0001005d' - | '\U00010080' .. '\U000100fa' - | '\U00010140' .. '\U00010174' - | '\U00010280' .. '\U0001029c' - | '\U000102a0' .. '\U000102d0' - | '\U00010300' .. '\U0001031e' - | '\U00010330' .. '\U00010340' - | '\U00010341' - | '\U00010342' .. '\U00010349' - | '\U0001034a' - | '\U00010380' .. '\U0001039d' - | '\U000103a0' .. '\U000103c3' - | '\U000103c8' .. '\U000103cf' - | '\U000103d1' .. '\U000103d5' - | '\U00010400' .. '\U0001044f' - | '\U00010450' .. '\U0001049d' - | '\U00010800' .. '\U00010805' - | '\U00010808' - | '\U0001080a' .. '\U00010835' - | '\U00010837' .. '\U00010838' - | '\U0001083c' - | '\U0001083f' .. '\U00010855' - | '\U00010900' .. '\U00010915' - | '\U00010920' .. '\U00010939' - | '\U00010a00' - | '\U00010a01' .. '\U00010a03' - | '\U00010a05' .. '\U00010a06' - | '\U00010a0c' .. '\U00010a0f' - | '\U00010a10' .. '\U00010a13' - | '\U00010a15' .. '\U00010a17' - | '\U00010a19' .. '\U00010a33' - | '\U00010a60' .. '\U00010a7c' - | '\U00010b00' .. '\U00010b35' - | '\U00010b40' .. '\U00010b55' - | '\U00010b60' .. '\U00010b72' - | '\U00010c00' .. '\U00010c48' - | '\U00011000' - | '\U00011001' - | '\U00011002' - | '\U00011003' .. '\U00011037' - | '\U00011038' .. '\U00011045' - | '\U00011082' - | '\U00011083' .. '\U000110af' - | '\U000110b0' .. '\U000110b2' - | '\U000110b3' .. '\U000110b6' - | '\U000110b7' .. '\U000110b8' - | '\U00012000' .. '\U0001236e' - | '\U00012400' .. '\U00012462' - | '\U00013000' .. '\U0001342e' - | '\U00016800' .. '\U00016a38' - | '\U0001b000' .. '\U0001b001' - | '\U0001d400' .. '\U0001d454' - | '\U0001d456' .. '\U0001d49c' - | '\U0001d49e' .. '\U0001d49f' - | '\U0001d4a2' - | '\U0001d4a5' .. '\U0001d4a6' - | '\U0001d4a9' .. '\U0001d4ac' - | '\U0001d4ae' .. '\U0001d4b9' - | '\U0001d4bb' - | '\U0001d4bd' .. '\U0001d4c3' - | '\U0001d4c5' .. '\U0001d505' - | '\U0001d507' .. '\U0001d50a' - | '\U0001d50d' .. '\U0001d514' - | '\U0001d516' .. '\U0001d51c' - | '\U0001d51e' .. '\U0001d539' - | '\U0001d53b' .. '\U0001d53e' - | '\U0001d540' .. '\U0001d544' - | '\U0001d546' - | '\U0001d54a' .. '\U0001d550' - | '\U0001d552' .. '\U0001d6a5' - | '\U0001d6a8' .. '\U0001d6c0' - | '\U0001d6c2' .. '\U0001d6da' - | '\U0001d6dc' .. '\U0001d6fa' - | '\U0001d6fc' .. '\U0001d714' - | '\U0001d716' .. '\U0001d734' - | '\U0001d736' .. '\U0001d74e' - | '\U0001d750' .. '\U0001d76e' - | '\U0001d770' .. '\U0001d788' - | '\U0001d78a' .. '\U0001d7a8' - | '\U0001d7aa' .. '\U0001d7c2' - | '\U0001d7c4' .. '\U0001d7cb' - | '\U00020000' .. '\U0002a6d6' - | '\U0002a700' .. '\U0002b734' - | '\U0002b740' .. '\U0002b81d' - | '\U0002f800' .. '\U0002fa1d' - => true, - _ => false - }; + bsearch_range_table(c, Alphabetic_table) } + static XID_Continue_table : &'static [(char,char)] = &[ + ('\x30', '\x39'), ('\x41', '\x5a'), + ('\x5f', '\x5f'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xb7', '\xb7'), ('\xba', '\xba'), + ('\xc0', '\xd6'), ('\xd8', '\xf6'), + ('\xf8', '\u01ba'), ('\u01bb', '\u01bb'), + ('\u01bc', '\u01bf'), ('\u01c0', '\u01c3'), + ('\u01c4', '\u0293'), ('\u0294', '\u0294'), + ('\u0295', '\u02af'), ('\u02b0', '\u02c1'), + ('\u02c6', '\u02d1'), ('\u02e0', '\u02e4'), + ('\u02ec', '\u02ec'), ('\u02ee', '\u02ee'), + ('\u0300', '\u036f'), ('\u0370', '\u0373'), + ('\u0374', '\u0374'), ('\u0376', '\u0377'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0387', '\u0387'), ('\u0388', '\u038a'), + ('\u038c', '\u038c'), ('\u038e', '\u03a1'), + ('\u03a3', '\u03f5'), ('\u03f7', '\u0481'), + ('\u0483', '\u0487'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u0591', '\u05bd'), + ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), + ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), + ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), + ('\u0610', '\u061a'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u064b', '\u065f'), ('\u0660', '\u0669'), + ('\u066e', '\u066f'), ('\u0670', '\u0670'), + ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), + ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), + ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), + ('\u06ea', '\u06ed'), ('\u06ee', '\u06ef'), + ('\u06f0', '\u06f9'), ('\u06fa', '\u06fc'), + ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), + ('\u0711', '\u0711'), ('\u0712', '\u072f'), + ('\u0730', '\u074a'), ('\u074d', '\u07a5'), + ('\u07a6', '\u07b0'), ('\u07b1', '\u07b1'), + ('\u07c0', '\u07c9'), ('\u07ca', '\u07ea'), + ('\u07eb', '\u07f3'), ('\u07f4', '\u07f5'), + ('\u07fa', '\u07fa'), ('\u0800', '\u0815'), + ('\u0816', '\u0819'), ('\u081a', '\u081a'), + ('\u081b', '\u0823'), ('\u0824', '\u0824'), + ('\u0825', '\u0827'), ('\u0828', '\u0828'), + ('\u0829', '\u082d'), ('\u0840', '\u0858'), + ('\u0859', '\u085b'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u08e4', '\u08fe'), + ('\u0900', '\u0902'), ('\u0903', '\u0903'), + ('\u0904', '\u0939'), ('\u093a', '\u093a'), + ('\u093b', '\u093b'), ('\u093c', '\u093c'), + ('\u093d', '\u093d'), ('\u093e', '\u0940'), + ('\u0941', '\u0948'), ('\u0949', '\u094c'), + ('\u094d', '\u094d'), ('\u094e', '\u094f'), + ('\u0950', '\u0950'), ('\u0951', '\u0957'), + ('\u0958', '\u0961'), ('\u0962', '\u0963'), + ('\u0966', '\u096f'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0981', '\u0981'), ('\u0982', '\u0983'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bc', '\u09bc'), ('\u09bd', '\u09bd'), + ('\u09be', '\u09c0'), ('\u09c1', '\u09c4'), + ('\u09c7', '\u09c8'), ('\u09cb', '\u09cc'), + ('\u09cd', '\u09cd'), ('\u09ce', '\u09ce'), + ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), + ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), + ('\u09e6', '\u09ef'), ('\u09f0', '\u09f1'), + ('\u0a01', '\u0a02'), ('\u0a03', '\u0a03'), + ('\u0a05', '\u0a0a'), ('\u0a0f', '\u0a10'), + ('\u0a13', '\u0a28'), ('\u0a2a', '\u0a30'), + ('\u0a32', '\u0a33'), ('\u0a35', '\u0a36'), + ('\u0a38', '\u0a39'), ('\u0a3c', '\u0a3c'), + ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), + ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4d'), + ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), + ('\u0a5e', '\u0a5e'), ('\u0a66', '\u0a6f'), + ('\u0a70', '\u0a71'), ('\u0a72', '\u0a74'), + ('\u0a75', '\u0a75'), ('\u0a81', '\u0a82'), + ('\u0a83', '\u0a83'), ('\u0a85', '\u0a8d'), + ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), + ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), + ('\u0ab5', '\u0ab9'), ('\u0abc', '\u0abc'), + ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), + ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), + ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), + ('\u0acd', '\u0acd'), ('\u0ad0', '\u0ad0'), + ('\u0ae0', '\u0ae1'), ('\u0ae2', '\u0ae3'), + ('\u0ae6', '\u0aef'), ('\u0b01', '\u0b01'), + ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), + ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), + ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), + ('\u0b35', '\u0b39'), ('\u0b3c', '\u0b3c'), + ('\u0b3d', '\u0b3d'), ('\u0b3e', '\u0b3e'), + ('\u0b3f', '\u0b3f'), ('\u0b40', '\u0b40'), + ('\u0b41', '\u0b44'), ('\u0b47', '\u0b48'), + ('\u0b4b', '\u0b4c'), ('\u0b4d', '\u0b4d'), + ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), + ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), + ('\u0b62', '\u0b63'), ('\u0b66', '\u0b6f'), + ('\u0b71', '\u0b71'), ('\u0b82', '\u0b82'), + ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), + ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), + ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), + ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), + ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), + ('\u0bbe', '\u0bbf'), ('\u0bc0', '\u0bc0'), + ('\u0bc1', '\u0bc2'), ('\u0bc6', '\u0bc8'), + ('\u0bca', '\u0bcc'), ('\u0bcd', '\u0bcd'), + ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), + ('\u0be6', '\u0bef'), ('\u0c01', '\u0c03'), + ('\u0c05', '\u0c0c'), ('\u0c0e', '\u0c10'), + ('\u0c12', '\u0c28'), ('\u0c2a', '\u0c33'), + ('\u0c35', '\u0c39'), ('\u0c3d', '\u0c3d'), + ('\u0c3e', '\u0c40'), ('\u0c41', '\u0c44'), + ('\u0c46', '\u0c48'), ('\u0c4a', '\u0c4d'), + ('\u0c55', '\u0c56'), ('\u0c58', '\u0c59'), + ('\u0c60', '\u0c61'), ('\u0c62', '\u0c63'), + ('\u0c66', '\u0c6f'), ('\u0c82', '\u0c83'), + ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), + ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), + ('\u0cb5', '\u0cb9'), ('\u0cbc', '\u0cbc'), + ('\u0cbd', '\u0cbd'), ('\u0cbe', '\u0cbe'), + ('\u0cbf', '\u0cbf'), ('\u0cc0', '\u0cc4'), + ('\u0cc6', '\u0cc6'), ('\u0cc7', '\u0cc8'), + ('\u0cca', '\u0ccb'), ('\u0ccc', '\u0ccd'), + ('\u0cd5', '\u0cd6'), ('\u0cde', '\u0cde'), + ('\u0ce0', '\u0ce1'), ('\u0ce2', '\u0ce3'), + ('\u0ce6', '\u0cef'), ('\u0cf1', '\u0cf2'), + ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), + ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), + ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), + ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), + ('\u0d4a', '\u0d4c'), ('\u0d4d', '\u0d4d'), + ('\u0d4e', '\u0d4e'), ('\u0d57', '\u0d57'), + ('\u0d60', '\u0d61'), ('\u0d62', '\u0d63'), + ('\u0d66', '\u0d6f'), ('\u0d7a', '\u0d7f'), + ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0dca', '\u0dca'), ('\u0dcf', '\u0dd1'), + ('\u0dd2', '\u0dd4'), ('\u0dd6', '\u0dd6'), + ('\u0dd8', '\u0ddf'), ('\u0df2', '\u0df3'), + ('\u0e01', '\u0e30'), ('\u0e31', '\u0e31'), + ('\u0e32', '\u0e33'), ('\u0e34', '\u0e3a'), + ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), + ('\u0e47', '\u0e4e'), ('\u0e50', '\u0e59'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), + ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), + ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), + ('\u0ec6', '\u0ec6'), ('\u0ec8', '\u0ecd'), + ('\u0ed0', '\u0ed9'), ('\u0edc', '\u0edf'), + ('\u0f00', '\u0f00'), ('\u0f18', '\u0f19'), + ('\u0f20', '\u0f29'), ('\u0f35', '\u0f35'), + ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), + ('\u0f3e', '\u0f3f'), ('\u0f40', '\u0f47'), + ('\u0f49', '\u0f6c'), ('\u0f71', '\u0f7e'), + ('\u0f7f', '\u0f7f'), ('\u0f80', '\u0f84'), + ('\u0f86', '\u0f87'), ('\u0f88', '\u0f8c'), + ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), + ('\u0fc6', '\u0fc6'), ('\u1000', '\u102a'), + ('\u102b', '\u102c'), ('\u102d', '\u1030'), + ('\u1031', '\u1031'), ('\u1032', '\u1037'), + ('\u1038', '\u1038'), ('\u1039', '\u103a'), + ('\u103b', '\u103c'), ('\u103d', '\u103e'), + ('\u103f', '\u103f'), ('\u1040', '\u1049'), + ('\u1050', '\u1055'), ('\u1056', '\u1057'), + ('\u1058', '\u1059'), ('\u105a', '\u105d'), + ('\u105e', '\u1060'), ('\u1061', '\u1061'), + ('\u1062', '\u1064'), ('\u1065', '\u1066'), + ('\u1067', '\u106d'), ('\u106e', '\u1070'), + ('\u1071', '\u1074'), ('\u1075', '\u1081'), + ('\u1082', '\u1082'), ('\u1083', '\u1084'), + ('\u1085', '\u1086'), ('\u1087', '\u108c'), + ('\u108d', '\u108d'), ('\u108e', '\u108e'), + ('\u108f', '\u108f'), ('\u1090', '\u1099'), + ('\u109a', '\u109c'), ('\u109d', '\u109d'), + ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), + ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), + ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), + ('\u124a', '\u124d'), ('\u1250', '\u1256'), + ('\u1258', '\u1258'), ('\u125a', '\u125d'), + ('\u1260', '\u1288'), ('\u128a', '\u128d'), + ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), + ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), + ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), + ('\u12d8', '\u1310'), ('\u1312', '\u1315'), + ('\u1318', '\u135a'), ('\u135d', '\u135f'), + ('\u1369', '\u1371'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1712', '\u1714'), ('\u1720', '\u1731'), + ('\u1732', '\u1734'), ('\u1740', '\u1751'), + ('\u1752', '\u1753'), ('\u1760', '\u176c'), + ('\u176e', '\u1770'), ('\u1772', '\u1773'), + ('\u1780', '\u17b3'), ('\u17b4', '\u17b5'), + ('\u17b6', '\u17b6'), ('\u17b7', '\u17bd'), + ('\u17be', '\u17c5'), ('\u17c6', '\u17c6'), + ('\u17c7', '\u17c8'), ('\u17c9', '\u17d3'), + ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), + ('\u17dd', '\u17dd'), ('\u17e0', '\u17e9'), + ('\u180b', '\u180d'), ('\u1810', '\u1819'), + ('\u1820', '\u1842'), ('\u1843', '\u1843'), + ('\u1844', '\u1877'), ('\u1880', '\u18a8'), + ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1920', '\u1922'), ('\u1923', '\u1926'), + ('\u1927', '\u1928'), ('\u1929', '\u192b'), + ('\u1930', '\u1931'), ('\u1932', '\u1932'), + ('\u1933', '\u1938'), ('\u1939', '\u193b'), + ('\u1946', '\u194f'), ('\u1950', '\u196d'), + ('\u1970', '\u1974'), ('\u1980', '\u19ab'), + ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), + ('\u19c8', '\u19c9'), ('\u19d0', '\u19d9'), + ('\u19da', '\u19da'), ('\u1a00', '\u1a16'), + ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), + ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), + ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), + ('\u1a58', '\u1a5e'), ('\u1a60', '\u1a60'), + ('\u1a61', '\u1a61'), ('\u1a62', '\u1a62'), + ('\u1a63', '\u1a64'), ('\u1a65', '\u1a6c'), + ('\u1a6d', '\u1a72'), ('\u1a73', '\u1a7c'), + ('\u1a7f', '\u1a7f'), ('\u1a80', '\u1a89'), + ('\u1a90', '\u1a99'), ('\u1aa7', '\u1aa7'), + ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), + ('\u1b05', '\u1b33'), ('\u1b34', '\u1b34'), + ('\u1b35', '\u1b35'), ('\u1b36', '\u1b3a'), + ('\u1b3b', '\u1b3b'), ('\u1b3c', '\u1b3c'), + ('\u1b3d', '\u1b41'), ('\u1b42', '\u1b42'), + ('\u1b43', '\u1b44'), ('\u1b45', '\u1b4b'), + ('\u1b50', '\u1b59'), ('\u1b6b', '\u1b73'), + ('\u1b80', '\u1b81'), ('\u1b82', '\u1b82'), + ('\u1b83', '\u1ba0'), ('\u1ba1', '\u1ba1'), + ('\u1ba2', '\u1ba5'), ('\u1ba6', '\u1ba7'), + ('\u1ba8', '\u1ba9'), ('\u1baa', '\u1baa'), + ('\u1bab', '\u1bab'), ('\u1bac', '\u1bad'), + ('\u1bae', '\u1baf'), ('\u1bb0', '\u1bb9'), + ('\u1bba', '\u1be5'), ('\u1be6', '\u1be6'), + ('\u1be7', '\u1be7'), ('\u1be8', '\u1be9'), + ('\u1bea', '\u1bec'), ('\u1bed', '\u1bed'), + ('\u1bee', '\u1bee'), ('\u1bef', '\u1bf1'), + ('\u1bf2', '\u1bf3'), ('\u1c00', '\u1c23'), + ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), + ('\u1c34', '\u1c35'), ('\u1c36', '\u1c37'), + ('\u1c40', '\u1c49'), ('\u1c4d', '\u1c4f'), + ('\u1c50', '\u1c59'), ('\u1c5a', '\u1c77'), + ('\u1c78', '\u1c7d'), ('\u1cd0', '\u1cd2'), + ('\u1cd4', '\u1ce0'), ('\u1ce1', '\u1ce1'), + ('\u1ce2', '\u1ce8'), ('\u1ce9', '\u1cec'), + ('\u1ced', '\u1ced'), ('\u1cee', '\u1cf1'), + ('\u1cf2', '\u1cf3'), ('\u1cf4', '\u1cf4'), + ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), + ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), + ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), + ('\u1d9b', '\u1dbf'), ('\u1dc0', '\u1de6'), + ('\u1dfc', '\u1dff'), ('\u1e00', '\u1f15'), + ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), + ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), + ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), + ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), + ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), + ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), + ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), + ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), + ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), + ('\u203f', '\u2040'), ('\u2054', '\u2054'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u20d0', '\u20dc'), + ('\u20e1', '\u20e1'), ('\u20e5', '\u20f0'), + ('\u2102', '\u2102'), ('\u2107', '\u2107'), + ('\u210a', '\u2113'), ('\u2115', '\u2115'), + ('\u2118', '\u2118'), ('\u2119', '\u211d'), + ('\u2124', '\u2124'), ('\u2126', '\u2126'), + ('\u2128', '\u2128'), ('\u212a', '\u212d'), + ('\u212e', '\u212e'), ('\u212f', '\u2134'), + ('\u2135', '\u2138'), ('\u2139', '\u2139'), + ('\u213c', '\u213f'), ('\u2145', '\u2149'), + ('\u214e', '\u214e'), ('\u2160', '\u2182'), + ('\u2183', '\u2184'), ('\u2185', '\u2188'), + ('\u2c00', '\u2c2e'), ('\u2c30', '\u2c5e'), + ('\u2c60', '\u2c7b'), ('\u2c7c', '\u2c7d'), + ('\u2c7e', '\u2ce4'), ('\u2ceb', '\u2cee'), + ('\u2cef', '\u2cf1'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d7f', '\u2d7f'), + ('\u2d80', '\u2d96'), ('\u2da0', '\u2da6'), + ('\u2da8', '\u2dae'), ('\u2db0', '\u2db6'), + ('\u2db8', '\u2dbe'), ('\u2dc0', '\u2dc6'), + ('\u2dc8', '\u2dce'), ('\u2dd0', '\u2dd6'), + ('\u2dd8', '\u2dde'), ('\u2de0', '\u2dff'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u302a', '\u302d'), ('\u302e', '\u302f'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u3099', '\u309a'), + ('\u309d', '\u309e'), ('\u309f', '\u309f'), + ('\u30a1', '\u30fa'), ('\u30fc', '\u30fe'), + ('\u30ff', '\u30ff'), ('\u3105', '\u312d'), + ('\u3131', '\u318e'), ('\u31a0', '\u31ba'), + ('\u31f0', '\u31ff'), ('\u3400', '\u4db5'), + ('\u4e00', '\u9fcc'), ('\ua000', '\ua014'), + ('\ua015', '\ua015'), ('\ua016', '\ua48c'), + ('\ua4d0', '\ua4f7'), ('\ua4f8', '\ua4fd'), + ('\ua500', '\ua60b'), ('\ua60c', '\ua60c'), + ('\ua610', '\ua61f'), ('\ua620', '\ua629'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua66f', '\ua66f'), + ('\ua674', '\ua67d'), ('\ua67f', '\ua67f'), + ('\ua680', '\ua697'), ('\ua69f', '\ua69f'), + ('\ua6a0', '\ua6e5'), ('\ua6e6', '\ua6ef'), + ('\ua6f0', '\ua6f1'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua802', '\ua802'), ('\ua803', '\ua805'), + ('\ua806', '\ua806'), ('\ua807', '\ua80a'), + ('\ua80b', '\ua80b'), ('\ua80c', '\ua822'), + ('\ua823', '\ua824'), ('\ua825', '\ua826'), + ('\ua827', '\ua827'), ('\ua840', '\ua873'), + ('\ua880', '\ua881'), ('\ua882', '\ua8b3'), + ('\ua8b4', '\ua8c3'), ('\ua8c4', '\ua8c4'), + ('\ua8d0', '\ua8d9'), ('\ua8e0', '\ua8f1'), + ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), + ('\ua900', '\ua909'), ('\ua90a', '\ua925'), + ('\ua926', '\ua92d'), ('\ua930', '\ua946'), + ('\ua947', '\ua951'), ('\ua952', '\ua953'), + ('\ua960', '\ua97c'), ('\ua980', '\ua982'), + ('\ua983', '\ua983'), ('\ua984', '\ua9b2'), + ('\ua9b3', '\ua9b3'), ('\ua9b4', '\ua9b5'), + ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), + ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9c0'), + ('\ua9cf', '\ua9cf'), ('\ua9d0', '\ua9d9'), + ('\uaa00', '\uaa28'), ('\uaa29', '\uaa2e'), + ('\uaa2f', '\uaa30'), ('\uaa31', '\uaa32'), + ('\uaa33', '\uaa34'), ('\uaa35', '\uaa36'), + ('\uaa40', '\uaa42'), ('\uaa43', '\uaa43'), + ('\uaa44', '\uaa4b'), ('\uaa4c', '\uaa4c'), + ('\uaa4d', '\uaa4d'), ('\uaa50', '\uaa59'), + ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), + ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), + ('\uaa7b', '\uaa7b'), ('\uaa80', '\uaaaf'), + ('\uaab0', '\uaab0'), ('\uaab1', '\uaab1'), + ('\uaab2', '\uaab4'), ('\uaab5', '\uaab6'), + ('\uaab7', '\uaab8'), ('\uaab9', '\uaabd'), + ('\uaabe', '\uaabf'), ('\uaac0', '\uaac0'), + ('\uaac1', '\uaac1'), ('\uaac2', '\uaac2'), + ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), + ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), + ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uaaf5', '\uaaf5'), ('\uaaf6', '\uaaf6'), + ('\uab01', '\uab06'), ('\uab09', '\uab0e'), + ('\uab11', '\uab16'), ('\uab20', '\uab26'), + ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), + ('\uabe3', '\uabe4'), ('\uabe5', '\uabe5'), + ('\uabe6', '\uabe7'), ('\uabe8', '\uabe8'), + ('\uabe9', '\uabea'), ('\uabec', '\uabec'), + ('\uabed', '\uabed'), ('\uabf0', '\uabf9'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), + ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), + ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), + ('\ufbd3', '\ufc5d'), ('\ufc64', '\ufd3d'), + ('\ufd50', '\ufd8f'), ('\ufd92', '\ufdc7'), + ('\ufdf0', '\ufdf9'), ('\ufe00', '\ufe0f'), + ('\ufe20', '\ufe26'), ('\ufe33', '\ufe34'), + ('\ufe4d', '\ufe4f'), ('\ufe71', '\ufe71'), + ('\ufe73', '\ufe73'), ('\ufe77', '\ufe77'), + ('\ufe79', '\ufe79'), ('\ufe7b', '\ufe7b'), + ('\ufe7d', '\ufe7d'), ('\ufe7f', '\ufefc'), + ('\uff10', '\uff19'), ('\uff21', '\uff3a'), + ('\uff3f', '\uff3f'), ('\uff41', '\uff5a'), + ('\uff66', '\uff6f'), ('\uff70', '\uff70'), + ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U000101fd', '\U000101fd'), + ('\U00010280', '\U0001029c'), ('\U000102a0', '\U000102d0'), + ('\U00010300', '\U0001031e'), ('\U00010330', '\U00010340'), + ('\U00010341', '\U00010341'), ('\U00010342', '\U00010349'), + ('\U0001034a', '\U0001034a'), ('\U00010380', '\U0001039d'), + ('\U000103a0', '\U000103c3'), ('\U000103c8', '\U000103cf'), + ('\U000103d1', '\U000103d5'), ('\U00010400', '\U0001044f'), + ('\U00010450', '\U0001049d'), ('\U000104a0', '\U000104a9'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), + ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), + ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), + ('\U00010a19', '\U00010a33'), ('\U00010a38', '\U00010a3a'), + ('\U00010a3f', '\U00010a3f'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), + ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), + ('\U00011038', '\U00011046'), ('\U00011066', '\U0001106f'), + ('\U00011080', '\U00011081'), ('\U00011082', '\U00011082'), + ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), + ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), + ('\U000110b9', '\U000110ba'), ('\U000110d0', '\U000110e8'), + ('\U000110f0', '\U000110f9'), ('\U00011100', '\U00011102'), + ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), + ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011134'), + ('\U00011136', '\U0001113f'), ('\U00011180', '\U00011181'), + ('\U00011182', '\U00011182'), ('\U00011183', '\U000111b2'), + ('\U000111b3', '\U000111b5'), ('\U000111b6', '\U000111be'), + ('\U000111bf', '\U000111c0'), ('\U000111c1', '\U000111c4'), + ('\U000111d0', '\U000111d9'), ('\U00011680', '\U000116aa'), + ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), + ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), + ('\U000116b0', '\U000116b5'), ('\U000116b6', '\U000116b6'), + ('\U000116b7', '\U000116b7'), ('\U000116c0', '\U000116c9'), + ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), + ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), + ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), + ('\U00016f51', '\U00016f7e'), ('\U00016f8f', '\U00016f92'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d165', '\U0001d166'), ('\U0001d167', '\U0001d169'), + ('\U0001d16d', '\U0001d172'), ('\U0001d17b', '\U0001d182'), + ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), + ('\U0001d242', '\U0001d244'), ('\U0001d400', '\U0001d454'), + ('\U0001d456', '\U0001d49c'), ('\U0001d49e', '\U0001d49f'), + ('\U0001d4a2', '\U0001d4a2'), ('\U0001d4a5', '\U0001d4a6'), + ('\U0001d4a9', '\U0001d4ac'), ('\U0001d4ae', '\U0001d4b9'), + ('\U0001d4bb', '\U0001d4bb'), ('\U0001d4bd', '\U0001d4c3'), + ('\U0001d4c5', '\U0001d505'), ('\U0001d507', '\U0001d50a'), + ('\U0001d50d', '\U0001d514'), ('\U0001d516', '\U0001d51c'), + ('\U0001d51e', '\U0001d539'), ('\U0001d53b', '\U0001d53e'), + ('\U0001d540', '\U0001d544'), ('\U0001d546', '\U0001d546'), + ('\U0001d54a', '\U0001d550'), ('\U0001d552', '\U0001d6a5'), + ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6c2', '\U0001d6da'), + ('\U0001d6dc', '\U0001d6fa'), ('\U0001d6fc', '\U0001d714'), + ('\U0001d716', '\U0001d734'), ('\U0001d736', '\U0001d74e'), + ('\U0001d750', '\U0001d76e'), ('\U0001d770', '\U0001d788'), + ('\U0001d78a', '\U0001d7a8'), ('\U0001d7aa', '\U0001d7c2'), + ('\U0001d7c4', '\U0001d7cb'), ('\U0001d7ce', '\U0001d7ff'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d'), ('\U000e0100', '\U000e01ef') + ]; + pub fn XID_Continue(c: char) -> bool { - return match c { - '\x30' .. '\x39' - | '\x41' .. '\x5a' - | '\x5f' - | '\x61' .. '\x7a' - | '\xaa' - | '\xb5' - | '\xb7' - | '\xba' - | '\xc0' .. '\xd6' - | '\xd8' .. '\xf6' - | '\xf8' .. '\u01ba' - | '\u01bb' - | '\u01bc' .. '\u01bf' - | '\u01c0' .. '\u01c3' - | '\u01c4' .. '\u0293' - | '\u0294' - | '\u0295' .. '\u02af' - | '\u02b0' .. '\u02c1' - | '\u02c6' .. '\u02d1' - | '\u02e0' .. '\u02e4' - | '\u02ec' - | '\u02ee' - | '\u0300' .. '\u036f' - | '\u0370' .. '\u0373' - | '\u0374' - | '\u0376' .. '\u0377' - | '\u037b' .. '\u037d' - | '\u0386' - | '\u0387' - | '\u0388' .. '\u038a' - | '\u038c' - | '\u038e' .. '\u03a1' - | '\u03a3' .. '\u03f5' - | '\u03f7' .. '\u0481' - | '\u0483' .. '\u0487' - | '\u048a' .. '\u0527' - | '\u0531' .. '\u0556' - | '\u0559' - | '\u0561' .. '\u0587' - | '\u0591' .. '\u05bd' - | '\u05bf' - | '\u05c1' .. '\u05c2' - | '\u05c4' .. '\u05c5' - | '\u05c7' - | '\u05d0' .. '\u05ea' - | '\u05f0' .. '\u05f2' - | '\u0610' .. '\u061a' - | '\u0620' .. '\u063f' - | '\u0640' - | '\u0641' .. '\u064a' - | '\u064b' .. '\u065f' - | '\u0660' .. '\u0669' - | '\u066e' .. '\u066f' - | '\u0670' - | '\u0671' .. '\u06d3' - | '\u06d5' - | '\u06d6' .. '\u06dc' - | '\u06df' .. '\u06e4' - | '\u06e5' .. '\u06e6' - | '\u06e7' .. '\u06e8' - | '\u06ea' .. '\u06ed' - | '\u06ee' .. '\u06ef' - | '\u06f0' .. '\u06f9' - | '\u06fa' .. '\u06fc' - | '\u06ff' - | '\u0710' - | '\u0711' - | '\u0712' .. '\u072f' - | '\u0730' .. '\u074a' - | '\u074d' .. '\u07a5' - | '\u07a6' .. '\u07b0' - | '\u07b1' - | '\u07c0' .. '\u07c9' - | '\u07ca' .. '\u07ea' - | '\u07eb' .. '\u07f3' - | '\u07f4' .. '\u07f5' - | '\u07fa' - | '\u0800' .. '\u0815' - | '\u0816' .. '\u0819' - | '\u081a' - | '\u081b' .. '\u0823' - | '\u0824' - | '\u0825' .. '\u0827' - | '\u0828' - | '\u0829' .. '\u082d' - | '\u0840' .. '\u0858' - | '\u0859' .. '\u085b' - | '\u0900' .. '\u0902' - | '\u0903' - | '\u0904' .. '\u0939' - | '\u093a' - | '\u093b' - | '\u093c' - | '\u093d' - | '\u093e' .. '\u0940' - | '\u0941' .. '\u0948' - | '\u0949' .. '\u094c' - | '\u094d' - | '\u094e' .. '\u094f' - | '\u0950' - | '\u0951' .. '\u0957' - | '\u0958' .. '\u0961' - | '\u0962' .. '\u0963' - | '\u0966' .. '\u096f' - | '\u0971' - | '\u0972' .. '\u0977' - | '\u0979' .. '\u097f' - | '\u0981' - | '\u0982' .. '\u0983' - | '\u0985' .. '\u098c' - | '\u098f' .. '\u0990' - | '\u0993' .. '\u09a8' - | '\u09aa' .. '\u09b0' - | '\u09b2' - | '\u09b6' .. '\u09b9' - | '\u09bc' - | '\u09bd' - | '\u09be' .. '\u09c0' - | '\u09c1' .. '\u09c4' - | '\u09c7' .. '\u09c8' - | '\u09cb' .. '\u09cc' - | '\u09cd' - | '\u09ce' - | '\u09d7' - | '\u09dc' .. '\u09dd' - | '\u09df' .. '\u09e1' - | '\u09e2' .. '\u09e3' - | '\u09e6' .. '\u09ef' - | '\u09f0' .. '\u09f1' - | '\u0a01' .. '\u0a02' - | '\u0a03' - | '\u0a05' .. '\u0a0a' - | '\u0a0f' .. '\u0a10' - | '\u0a13' .. '\u0a28' - | '\u0a2a' .. '\u0a30' - | '\u0a32' .. '\u0a33' - | '\u0a35' .. '\u0a36' - | '\u0a38' .. '\u0a39' - | '\u0a3c' - | '\u0a3e' .. '\u0a40' - | '\u0a41' .. '\u0a42' - | '\u0a47' .. '\u0a48' - | '\u0a4b' .. '\u0a4d' - | '\u0a51' - | '\u0a59' .. '\u0a5c' - | '\u0a5e' - | '\u0a66' .. '\u0a6f' - | '\u0a70' .. '\u0a71' - | '\u0a72' .. '\u0a74' - | '\u0a75' - | '\u0a81' .. '\u0a82' - | '\u0a83' - | '\u0a85' .. '\u0a8d' - | '\u0a8f' .. '\u0a91' - | '\u0a93' .. '\u0aa8' - | '\u0aaa' .. '\u0ab0' - | '\u0ab2' .. '\u0ab3' - | '\u0ab5' .. '\u0ab9' - | '\u0abc' - | '\u0abd' - | '\u0abe' .. '\u0ac0' - | '\u0ac1' .. '\u0ac5' - | '\u0ac7' .. '\u0ac8' - | '\u0ac9' - | '\u0acb' .. '\u0acc' - | '\u0acd' - | '\u0ad0' - | '\u0ae0' .. '\u0ae1' - | '\u0ae2' .. '\u0ae3' - | '\u0ae6' .. '\u0aef' - | '\u0b01' - | '\u0b02' .. '\u0b03' - | '\u0b05' .. '\u0b0c' - | '\u0b0f' .. '\u0b10' - | '\u0b13' .. '\u0b28' - | '\u0b2a' .. '\u0b30' - | '\u0b32' .. '\u0b33' - | '\u0b35' .. '\u0b39' - | '\u0b3c' - | '\u0b3d' - | '\u0b3e' - | '\u0b3f' - | '\u0b40' - | '\u0b41' .. '\u0b44' - | '\u0b47' .. '\u0b48' - | '\u0b4b' .. '\u0b4c' - | '\u0b4d' - | '\u0b56' - | '\u0b57' - | '\u0b5c' .. '\u0b5d' - | '\u0b5f' .. '\u0b61' - | '\u0b62' .. '\u0b63' - | '\u0b66' .. '\u0b6f' - | '\u0b71' - | '\u0b82' - | '\u0b83' - | '\u0b85' .. '\u0b8a' - | '\u0b8e' .. '\u0b90' - | '\u0b92' .. '\u0b95' - | '\u0b99' .. '\u0b9a' - | '\u0b9c' - | '\u0b9e' .. '\u0b9f' - | '\u0ba3' .. '\u0ba4' - | '\u0ba8' .. '\u0baa' - | '\u0bae' .. '\u0bb9' - | '\u0bbe' .. '\u0bbf' - | '\u0bc0' - | '\u0bc1' .. '\u0bc2' - | '\u0bc6' .. '\u0bc8' - | '\u0bca' .. '\u0bcc' - | '\u0bcd' - | '\u0bd0' - | '\u0bd7' - | '\u0be6' .. '\u0bef' - | '\u0c01' .. '\u0c03' - | '\u0c05' .. '\u0c0c' - | '\u0c0e' .. '\u0c10' - | '\u0c12' .. '\u0c28' - | '\u0c2a' .. '\u0c33' - | '\u0c35' .. '\u0c39' - | '\u0c3d' - | '\u0c3e' .. '\u0c40' - | '\u0c41' .. '\u0c44' - | '\u0c46' .. '\u0c48' - | '\u0c4a' .. '\u0c4d' - | '\u0c55' .. '\u0c56' - | '\u0c58' .. '\u0c59' - | '\u0c60' .. '\u0c61' - | '\u0c62' .. '\u0c63' - | '\u0c66' .. '\u0c6f' - | '\u0c82' .. '\u0c83' - | '\u0c85' .. '\u0c8c' - | '\u0c8e' .. '\u0c90' - | '\u0c92' .. '\u0ca8' - | '\u0caa' .. '\u0cb3' - | '\u0cb5' .. '\u0cb9' - | '\u0cbc' - | '\u0cbd' - | '\u0cbe' - | '\u0cbf' - | '\u0cc0' .. '\u0cc4' - | '\u0cc6' - | '\u0cc7' .. '\u0cc8' - | '\u0cca' .. '\u0ccb' - | '\u0ccc' .. '\u0ccd' - | '\u0cd5' .. '\u0cd6' - | '\u0cde' - | '\u0ce0' .. '\u0ce1' - | '\u0ce2' .. '\u0ce3' - | '\u0ce6' .. '\u0cef' - | '\u0cf1' .. '\u0cf2' - | '\u0d02' .. '\u0d03' - | '\u0d05' .. '\u0d0c' - | '\u0d0e' .. '\u0d10' - | '\u0d12' .. '\u0d3a' - | '\u0d3d' - | '\u0d3e' .. '\u0d40' - | '\u0d41' .. '\u0d44' - | '\u0d46' .. '\u0d48' - | '\u0d4a' .. '\u0d4c' - | '\u0d4d' - | '\u0d4e' - | '\u0d57' - | '\u0d60' .. '\u0d61' - | '\u0d62' .. '\u0d63' - | '\u0d66' .. '\u0d6f' - | '\u0d7a' .. '\u0d7f' - | '\u0d82' .. '\u0d83' - | '\u0d85' .. '\u0d96' - | '\u0d9a' .. '\u0db1' - | '\u0db3' .. '\u0dbb' - | '\u0dbd' - | '\u0dc0' .. '\u0dc6' - | '\u0dca' - | '\u0dcf' .. '\u0dd1' - | '\u0dd2' .. '\u0dd4' - | '\u0dd6' - | '\u0dd8' .. '\u0ddf' - | '\u0df2' .. '\u0df3' - | '\u0e01' .. '\u0e30' - | '\u0e31' - | '\u0e32' .. '\u0e33' - | '\u0e34' .. '\u0e3a' - | '\u0e40' .. '\u0e45' - | '\u0e46' - | '\u0e47' .. '\u0e4e' - | '\u0e50' .. '\u0e59' - | '\u0e81' .. '\u0e82' - | '\u0e84' - | '\u0e87' .. '\u0e88' - | '\u0e8a' - | '\u0e8d' - | '\u0e94' .. '\u0e97' - | '\u0e99' .. '\u0e9f' - | '\u0ea1' .. '\u0ea3' - | '\u0ea5' - | '\u0ea7' - | '\u0eaa' .. '\u0eab' - | '\u0ead' .. '\u0eb0' - | '\u0eb1' - | '\u0eb2' .. '\u0eb3' - | '\u0eb4' .. '\u0eb9' - | '\u0ebb' .. '\u0ebc' - | '\u0ebd' - | '\u0ec0' .. '\u0ec4' - | '\u0ec6' - | '\u0ec8' .. '\u0ecd' - | '\u0ed0' .. '\u0ed9' - | '\u0edc' .. '\u0edd' - | '\u0f00' - | '\u0f18' .. '\u0f19' - | '\u0f20' .. '\u0f29' - | '\u0f35' - | '\u0f37' - | '\u0f39' - | '\u0f3e' .. '\u0f3f' - | '\u0f40' .. '\u0f47' - | '\u0f49' .. '\u0f6c' - | '\u0f71' .. '\u0f7e' - | '\u0f7f' - | '\u0f80' .. '\u0f84' - | '\u0f86' .. '\u0f87' - | '\u0f88' .. '\u0f8c' - | '\u0f8d' .. '\u0f97' - | '\u0f99' .. '\u0fbc' - | '\u0fc6' - | '\u1000' .. '\u102a' - | '\u102b' .. '\u102c' - | '\u102d' .. '\u1030' - | '\u1031' - | '\u1032' .. '\u1037' - | '\u1038' - | '\u1039' .. '\u103a' - | '\u103b' .. '\u103c' - | '\u103d' .. '\u103e' - | '\u103f' - | '\u1040' .. '\u1049' - | '\u1050' .. '\u1055' - | '\u1056' .. '\u1057' - | '\u1058' .. '\u1059' - | '\u105a' .. '\u105d' - | '\u105e' .. '\u1060' - | '\u1061' - | '\u1062' .. '\u1064' - | '\u1065' .. '\u1066' - | '\u1067' .. '\u106d' - | '\u106e' .. '\u1070' - | '\u1071' .. '\u1074' - | '\u1075' .. '\u1081' - | '\u1082' - | '\u1083' .. '\u1084' - | '\u1085' .. '\u1086' - | '\u1087' .. '\u108c' - | '\u108d' - | '\u108e' - | '\u108f' - | '\u1090' .. '\u1099' - | '\u109a' .. '\u109c' - | '\u109d' - | '\u10a0' .. '\u10c5' - | '\u10d0' .. '\u10fa' - | '\u10fc' - | '\u1100' .. '\u1248' - | '\u124a' .. '\u124d' - | '\u1250' .. '\u1256' - | '\u1258' - | '\u125a' .. '\u125d' - | '\u1260' .. '\u1288' - | '\u128a' .. '\u128d' - | '\u1290' .. '\u12b0' - | '\u12b2' .. '\u12b5' - | '\u12b8' .. '\u12be' - | '\u12c0' - | '\u12c2' .. '\u12c5' - | '\u12c8' .. '\u12d6' - | '\u12d8' .. '\u1310' - | '\u1312' .. '\u1315' - | '\u1318' .. '\u135a' - | '\u135d' .. '\u135f' - | '\u1369' .. '\u1371' - | '\u1380' .. '\u138f' - | '\u13a0' .. '\u13f4' - | '\u1401' .. '\u166c' - | '\u166f' .. '\u167f' - | '\u1681' .. '\u169a' - | '\u16a0' .. '\u16ea' - | '\u16ee' .. '\u16f0' - | '\u1700' .. '\u170c' - | '\u170e' .. '\u1711' - | '\u1712' .. '\u1714' - | '\u1720' .. '\u1731' - | '\u1732' .. '\u1734' - | '\u1740' .. '\u1751' - | '\u1752' .. '\u1753' - | '\u1760' .. '\u176c' - | '\u176e' .. '\u1770' - | '\u1772' .. '\u1773' - | '\u1780' .. '\u17b3' - | '\u17b6' - | '\u17b7' .. '\u17bd' - | '\u17be' .. '\u17c5' - | '\u17c6' - | '\u17c7' .. '\u17c8' - | '\u17c9' .. '\u17d3' - | '\u17d7' - | '\u17dc' - | '\u17dd' - | '\u17e0' .. '\u17e9' - | '\u180b' .. '\u180d' - | '\u1810' .. '\u1819' - | '\u1820' .. '\u1842' - | '\u1843' - | '\u1844' .. '\u1877' - | '\u1880' .. '\u18a8' - | '\u18a9' - | '\u18aa' - | '\u18b0' .. '\u18f5' - | '\u1900' .. '\u191c' - | '\u1920' .. '\u1922' - | '\u1923' .. '\u1926' - | '\u1927' .. '\u1928' - | '\u1929' .. '\u192b' - | '\u1930' .. '\u1931' - | '\u1932' - | '\u1933' .. '\u1938' - | '\u1939' .. '\u193b' - | '\u1946' .. '\u194f' - | '\u1950' .. '\u196d' - | '\u1970' .. '\u1974' - | '\u1980' .. '\u19ab' - | '\u19b0' .. '\u19c0' - | '\u19c1' .. '\u19c7' - | '\u19c8' .. '\u19c9' - | '\u19d0' .. '\u19d9' - | '\u19da' - | '\u1a00' .. '\u1a16' - | '\u1a17' .. '\u1a18' - | '\u1a19' .. '\u1a1b' - | '\u1a20' .. '\u1a54' - | '\u1a55' - | '\u1a56' - | '\u1a57' - | '\u1a58' .. '\u1a5e' - | '\u1a60' - | '\u1a61' - | '\u1a62' - | '\u1a63' .. '\u1a64' - | '\u1a65' .. '\u1a6c' - | '\u1a6d' .. '\u1a72' - | '\u1a73' .. '\u1a7c' - | '\u1a7f' - | '\u1a80' .. '\u1a89' - | '\u1a90' .. '\u1a99' - | '\u1aa7' - | '\u1b00' .. '\u1b03' - | '\u1b04' - | '\u1b05' .. '\u1b33' - | '\u1b34' - | '\u1b35' - | '\u1b36' .. '\u1b3a' - | '\u1b3b' - | '\u1b3c' - | '\u1b3d' .. '\u1b41' - | '\u1b42' - | '\u1b43' .. '\u1b44' - | '\u1b45' .. '\u1b4b' - | '\u1b50' .. '\u1b59' - | '\u1b6b' .. '\u1b73' - | '\u1b80' .. '\u1b81' - | '\u1b82' - | '\u1b83' .. '\u1ba0' - | '\u1ba1' - | '\u1ba2' .. '\u1ba5' - | '\u1ba6' .. '\u1ba7' - | '\u1ba8' .. '\u1ba9' - | '\u1baa' - | '\u1bae' .. '\u1baf' - | '\u1bb0' .. '\u1bb9' - | '\u1bc0' .. '\u1be5' - | '\u1be6' - | '\u1be7' - | '\u1be8' .. '\u1be9' - | '\u1bea' .. '\u1bec' - | '\u1bed' - | '\u1bee' - | '\u1bef' .. '\u1bf1' - | '\u1bf2' .. '\u1bf3' - | '\u1c00' .. '\u1c23' - | '\u1c24' .. '\u1c2b' - | '\u1c2c' .. '\u1c33' - | '\u1c34' .. '\u1c35' - | '\u1c36' .. '\u1c37' - | '\u1c40' .. '\u1c49' - | '\u1c4d' .. '\u1c4f' - | '\u1c50' .. '\u1c59' - | '\u1c5a' .. '\u1c77' - | '\u1c78' .. '\u1c7d' - | '\u1cd0' .. '\u1cd2' - | '\u1cd4' .. '\u1ce0' - | '\u1ce1' - | '\u1ce2' .. '\u1ce8' - | '\u1ce9' .. '\u1cec' - | '\u1ced' - | '\u1cee' .. '\u1cf1' - | '\u1cf2' - | '\u1d00' .. '\u1d2b' - | '\u1d2c' .. '\u1d61' - | '\u1d62' .. '\u1d77' - | '\u1d78' - | '\u1d79' .. '\u1d9a' - | '\u1d9b' .. '\u1dbf' - | '\u1dc0' .. '\u1de6' - | '\u1dfc' .. '\u1dff' - | '\u1e00' .. '\u1f15' - | '\u1f18' .. '\u1f1d' - | '\u1f20' .. '\u1f45' - | '\u1f48' .. '\u1f4d' - | '\u1f50' .. '\u1f57' - | '\u1f59' - | '\u1f5b' - | '\u1f5d' - | '\u1f5f' .. '\u1f7d' - | '\u1f80' .. '\u1fb4' - | '\u1fb6' .. '\u1fbc' - | '\u1fbe' - | '\u1fc2' .. '\u1fc4' - | '\u1fc6' .. '\u1fcc' - | '\u1fd0' .. '\u1fd3' - | '\u1fd6' .. '\u1fdb' - | '\u1fe0' .. '\u1fec' - | '\u1ff2' .. '\u1ff4' - | '\u1ff6' .. '\u1ffc' - | '\u203f' .. '\u2040' - | '\u2054' - | '\u2071' - | '\u207f' - | '\u2090' .. '\u209c' - | '\u20d0' .. '\u20dc' - | '\u20e1' - | '\u20e5' .. '\u20f0' - | '\u2102' - | '\u2107' - | '\u210a' .. '\u2113' - | '\u2115' - | '\u2118' - | '\u2119' .. '\u211d' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212a' .. '\u212d' - | '\u212e' - | '\u212f' .. '\u2134' - | '\u2135' .. '\u2138' - | '\u2139' - | '\u213c' .. '\u213f' - | '\u2145' .. '\u2149' - | '\u214e' - | '\u2160' .. '\u2182' - | '\u2183' .. '\u2184' - | '\u2185' .. '\u2188' - | '\u2c00' .. '\u2c2e' - | '\u2c30' .. '\u2c5e' - | '\u2c60' .. '\u2c7c' - | '\u2c7d' - | '\u2c7e' .. '\u2ce4' - | '\u2ceb' .. '\u2cee' - | '\u2cef' .. '\u2cf1' - | '\u2d00' .. '\u2d25' - | '\u2d30' .. '\u2d65' - | '\u2d6f' - | '\u2d7f' - | '\u2d80' .. '\u2d96' - | '\u2da0' .. '\u2da6' - | '\u2da8' .. '\u2dae' - | '\u2db0' .. '\u2db6' - | '\u2db8' .. '\u2dbe' - | '\u2dc0' .. '\u2dc6' - | '\u2dc8' .. '\u2dce' - | '\u2dd0' .. '\u2dd6' - | '\u2dd8' .. '\u2dde' - | '\u2de0' .. '\u2dff' - | '\u3005' - | '\u3006' - | '\u3007' - | '\u3021' .. '\u3029' - | '\u302a' .. '\u302f' - | '\u3031' .. '\u3035' - | '\u3038' .. '\u303a' - | '\u303b' - | '\u303c' - | '\u3041' .. '\u3096' - | '\u3099' .. '\u309a' - | '\u309d' .. '\u309e' - | '\u309f' - | '\u30a1' .. '\u30fa' - | '\u30fc' .. '\u30fe' - | '\u30ff' - | '\u3105' .. '\u312d' - | '\u3131' .. '\u318e' - | '\u31a0' .. '\u31ba' - | '\u31f0' .. '\u31ff' - | '\u3400' .. '\u4db5' - | '\u4e00' .. '\u9fcb' - | '\ua000' .. '\ua014' - | '\ua015' - | '\ua016' .. '\ua48c' - | '\ua4d0' .. '\ua4f7' - | '\ua4f8' .. '\ua4fd' - | '\ua500' .. '\ua60b' - | '\ua60c' - | '\ua610' .. '\ua61f' - | '\ua620' .. '\ua629' - | '\ua62a' .. '\ua62b' - | '\ua640' .. '\ua66d' - | '\ua66e' - | '\ua66f' - | '\ua67c' .. '\ua67d' - | '\ua67f' - | '\ua680' .. '\ua697' - | '\ua6a0' .. '\ua6e5' - | '\ua6e6' .. '\ua6ef' - | '\ua6f0' .. '\ua6f1' - | '\ua717' .. '\ua71f' - | '\ua722' .. '\ua76f' - | '\ua770' - | '\ua771' .. '\ua787' - | '\ua788' - | '\ua78b' .. '\ua78e' - | '\ua790' .. '\ua791' - | '\ua7a0' .. '\ua7a9' - | '\ua7fa' - | '\ua7fb' .. '\ua801' - | '\ua802' - | '\ua803' .. '\ua805' - | '\ua806' - | '\ua807' .. '\ua80a' - | '\ua80b' - | '\ua80c' .. '\ua822' - | '\ua823' .. '\ua824' - | '\ua825' .. '\ua826' - | '\ua827' - | '\ua840' .. '\ua873' - | '\ua880' .. '\ua881' - | '\ua882' .. '\ua8b3' - | '\ua8b4' .. '\ua8c3' - | '\ua8c4' - | '\ua8d0' .. '\ua8d9' - | '\ua8e0' .. '\ua8f1' - | '\ua8f2' .. '\ua8f7' - | '\ua8fb' - | '\ua900' .. '\ua909' - | '\ua90a' .. '\ua925' - | '\ua926' .. '\ua92d' - | '\ua930' .. '\ua946' - | '\ua947' .. '\ua951' - | '\ua952' .. '\ua953' - | '\ua960' .. '\ua97c' - | '\ua980' .. '\ua982' - | '\ua983' - | '\ua984' .. '\ua9b2' - | '\ua9b3' - | '\ua9b4' .. '\ua9b5' - | '\ua9b6' .. '\ua9b9' - | '\ua9ba' .. '\ua9bb' - | '\ua9bc' - | '\ua9bd' .. '\ua9c0' - | '\ua9cf' - | '\ua9d0' .. '\ua9d9' - | '\uaa00' .. '\uaa28' - | '\uaa29' .. '\uaa2e' - | '\uaa2f' .. '\uaa30' - | '\uaa31' .. '\uaa32' - | '\uaa33' .. '\uaa34' - | '\uaa35' .. '\uaa36' - | '\uaa40' .. '\uaa42' - | '\uaa43' - | '\uaa44' .. '\uaa4b' - | '\uaa4c' - | '\uaa4d' - | '\uaa50' .. '\uaa59' - | '\uaa60' .. '\uaa6f' - | '\uaa70' - | '\uaa71' .. '\uaa76' - | '\uaa7a' - | '\uaa7b' - | '\uaa80' .. '\uaaaf' - | '\uaab0' - | '\uaab1' - | '\uaab2' .. '\uaab4' - | '\uaab5' .. '\uaab6' - | '\uaab7' .. '\uaab8' - | '\uaab9' .. '\uaabd' - | '\uaabe' .. '\uaabf' - | '\uaac0' - | '\uaac1' - | '\uaac2' - | '\uaadb' .. '\uaadc' - | '\uaadd' - | '\uab01' .. '\uab06' - | '\uab09' .. '\uab0e' - | '\uab11' .. '\uab16' - | '\uab20' .. '\uab26' - | '\uab28' .. '\uab2e' - | '\uabc0' .. '\uabe2' - | '\uabe3' .. '\uabe4' - | '\uabe5' - | '\uabe6' .. '\uabe7' - | '\uabe8' - | '\uabe9' .. '\uabea' - | '\uabec' - | '\uabed' - | '\uabf0' .. '\uabf9' - | '\uac00' .. '\ud7a3' - | '\ud7b0' .. '\ud7c6' - | '\ud7cb' .. '\ud7fb' - | '\uf900' .. '\ufa2d' - | '\ufa30' .. '\ufa6d' - | '\ufa70' .. '\ufad9' - | '\ufb00' .. '\ufb06' - | '\ufb13' .. '\ufb17' - | '\ufb1d' - | '\ufb1e' - | '\ufb1f' .. '\ufb28' - | '\ufb2a' .. '\ufb36' - | '\ufb38' .. '\ufb3c' - | '\ufb3e' - | '\ufb40' .. '\ufb41' - | '\ufb43' .. '\ufb44' - | '\ufb46' .. '\ufbb1' - | '\ufbd3' .. '\ufc5d' - | '\ufc64' .. '\ufd3d' - | '\ufd50' .. '\ufd8f' - | '\ufd92' .. '\ufdc7' - | '\ufdf0' .. '\ufdf9' - | '\ufe00' .. '\ufe0f' - | '\ufe20' .. '\ufe26' - | '\ufe33' .. '\ufe34' - | '\ufe4d' .. '\ufe4f' - | '\ufe71' - | '\ufe73' - | '\ufe77' - | '\ufe79' - | '\ufe7b' - | '\ufe7d' - | '\ufe7f' .. '\ufefc' - | '\uff10' .. '\uff19' - | '\uff21' .. '\uff3a' - | '\uff3f' - | '\uff41' .. '\uff5a' - | '\uff66' .. '\uff6f' - | '\uff70' - | '\uff71' .. '\uff9d' - | '\uff9e' .. '\uff9f' - | '\uffa0' .. '\uffbe' - | '\uffc2' .. '\uffc7' - | '\uffca' .. '\uffcf' - | '\uffd2' .. '\uffd7' - | '\uffda' .. '\uffdc' - | '\U00010000' .. '\U0001000b' - | '\U0001000d' .. '\U00010026' - | '\U00010028' .. '\U0001003a' - | '\U0001003c' .. '\U0001003d' - | '\U0001003f' .. '\U0001004d' - | '\U00010050' .. '\U0001005d' - | '\U00010080' .. '\U000100fa' - | '\U00010140' .. '\U00010174' - | '\U000101fd' - | '\U00010280' .. '\U0001029c' - | '\U000102a0' .. '\U000102d0' - | '\U00010300' .. '\U0001031e' - | '\U00010330' .. '\U00010340' - | '\U00010341' - | '\U00010342' .. '\U00010349' - | '\U0001034a' - | '\U00010380' .. '\U0001039d' - | '\U000103a0' .. '\U000103c3' - | '\U000103c8' .. '\U000103cf' - | '\U000103d1' .. '\U000103d5' - | '\U00010400' .. '\U0001044f' - | '\U00010450' .. '\U0001049d' - | '\U000104a0' .. '\U000104a9' - | '\U00010800' .. '\U00010805' - | '\U00010808' - | '\U0001080a' .. '\U00010835' - | '\U00010837' .. '\U00010838' - | '\U0001083c' - | '\U0001083f' .. '\U00010855' - | '\U00010900' .. '\U00010915' - | '\U00010920' .. '\U00010939' - | '\U00010a00' - | '\U00010a01' .. '\U00010a03' - | '\U00010a05' .. '\U00010a06' - | '\U00010a0c' .. '\U00010a0f' - | '\U00010a10' .. '\U00010a13' - | '\U00010a15' .. '\U00010a17' - | '\U00010a19' .. '\U00010a33' - | '\U00010a38' .. '\U00010a3a' - | '\U00010a3f' - | '\U00010a60' .. '\U00010a7c' - | '\U00010b00' .. '\U00010b35' - | '\U00010b40' .. '\U00010b55' - | '\U00010b60' .. '\U00010b72' - | '\U00010c00' .. '\U00010c48' - | '\U00011000' - | '\U00011001' - | '\U00011002' - | '\U00011003' .. '\U00011037' - | '\U00011038' .. '\U00011046' - | '\U00011066' .. '\U0001106f' - | '\U00011080' .. '\U00011081' - | '\U00011082' - | '\U00011083' .. '\U000110af' - | '\U000110b0' .. '\U000110b2' - | '\U000110b3' .. '\U000110b6' - | '\U000110b7' .. '\U000110b8' - | '\U000110b9' .. '\U000110ba' - | '\U00012000' .. '\U0001236e' - | '\U00012400' .. '\U00012462' - | '\U00013000' .. '\U0001342e' - | '\U00016800' .. '\U00016a38' - | '\U0001b000' .. '\U0001b001' - | '\U0001d165' .. '\U0001d166' - | '\U0001d167' .. '\U0001d169' - | '\U0001d16d' .. '\U0001d172' - | '\U0001d17b' .. '\U0001d182' - | '\U0001d185' .. '\U0001d18b' - | '\U0001d1aa' .. '\U0001d1ad' - | '\U0001d242' .. '\U0001d244' - | '\U0001d400' .. '\U0001d454' - | '\U0001d456' .. '\U0001d49c' - | '\U0001d49e' .. '\U0001d49f' - | '\U0001d4a2' - | '\U0001d4a5' .. '\U0001d4a6' - | '\U0001d4a9' .. '\U0001d4ac' - | '\U0001d4ae' .. '\U0001d4b9' - | '\U0001d4bb' - | '\U0001d4bd' .. '\U0001d4c3' - | '\U0001d4c5' .. '\U0001d505' - | '\U0001d507' .. '\U0001d50a' - | '\U0001d50d' .. '\U0001d514' - | '\U0001d516' .. '\U0001d51c' - | '\U0001d51e' .. '\U0001d539' - | '\U0001d53b' .. '\U0001d53e' - | '\U0001d540' .. '\U0001d544' - | '\U0001d546' - | '\U0001d54a' .. '\U0001d550' - | '\U0001d552' .. '\U0001d6a5' - | '\U0001d6a8' .. '\U0001d6c0' - | '\U0001d6c2' .. '\U0001d6da' - | '\U0001d6dc' .. '\U0001d6fa' - | '\U0001d6fc' .. '\U0001d714' - | '\U0001d716' .. '\U0001d734' - | '\U0001d736' .. '\U0001d74e' - | '\U0001d750' .. '\U0001d76e' - | '\U0001d770' .. '\U0001d788' - | '\U0001d78a' .. '\U0001d7a8' - | '\U0001d7aa' .. '\U0001d7c2' - | '\U0001d7c4' .. '\U0001d7cb' - | '\U0001d7ce' .. '\U0001d7ff' - | '\U00020000' .. '\U0002a6d6' - | '\U0002a700' .. '\U0002b734' - | '\U0002b740' .. '\U0002b81d' - | '\U0002f800' .. '\U0002fa1d' - | '\U000e0100' .. '\U000e01ef' - => true, - _ => false - }; + bsearch_range_table(c, XID_Continue_table) } + static XID_Start_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xba', '\xba'), ('\xc0', '\xd6'), + ('\xd8', '\xf6'), ('\xf8', '\u01ba'), + ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), + ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), + ('\u0294', '\u0294'), ('\u0295', '\u02af'), + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0370', '\u0373'), + ('\u0374', '\u0374'), ('\u0376', '\u0377'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0388', '\u038a'), ('\u038c', '\u038c'), + ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), + ('\u03f7', '\u0481'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u05d0', '\u05ea'), + ('\u05f0', '\u05f2'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u066e', '\u066f'), ('\u0671', '\u06d3'), + ('\u06d5', '\u06d5'), ('\u06e5', '\u06e6'), + ('\u06ee', '\u06ef'), ('\u06fa', '\u06fc'), + ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), + ('\u0712', '\u072f'), ('\u074d', '\u07a5'), + ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u0800', '\u0815'), ('\u081a', '\u081a'), + ('\u0824', '\u0824'), ('\u0828', '\u0828'), + ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u0904', '\u0939'), + ('\u093d', '\u093d'), ('\u0950', '\u0950'), + ('\u0958', '\u0961'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), + ('\u09dc', '\u09dd'), ('\u09df', '\u09e1'), + ('\u09f0', '\u09f1'), ('\u0a05', '\u0a0a'), + ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), + ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), + ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), + ('\u0a59', '\u0a5c'), ('\u0a5e', '\u0a5e'), + ('\u0a72', '\u0a74'), ('\u0a85', '\u0a8d'), + ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), + ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), + ('\u0ab5', '\u0ab9'), ('\u0abd', '\u0abd'), + ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), + ('\u0b05', '\u0b0c'), ('\u0b0f', '\u0b10'), + ('\u0b13', '\u0b28'), ('\u0b2a', '\u0b30'), + ('\u0b32', '\u0b33'), ('\u0b35', '\u0b39'), + ('\u0b3d', '\u0b3d'), ('\u0b5c', '\u0b5d'), + ('\u0b5f', '\u0b61'), ('\u0b71', '\u0b71'), + ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), + ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), + ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), + ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), + ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), + ('\u0bd0', '\u0bd0'), ('\u0c05', '\u0c0c'), + ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), + ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), + ('\u0c3d', '\u0c3d'), ('\u0c58', '\u0c59'), + ('\u0c60', '\u0c61'), ('\u0c85', '\u0c8c'), + ('\u0c8e', '\u0c90'), ('\u0c92', '\u0ca8'), + ('\u0caa', '\u0cb3'), ('\u0cb5', '\u0cb9'), + ('\u0cbd', '\u0cbd'), ('\u0cde', '\u0cde'), + ('\u0ce0', '\u0ce1'), ('\u0cf1', '\u0cf2'), + ('\u0d05', '\u0d0c'), ('\u0d0e', '\u0d10'), + ('\u0d12', '\u0d3a'), ('\u0d3d', '\u0d3d'), + ('\u0d4e', '\u0d4e'), ('\u0d60', '\u0d61'), + ('\u0d7a', '\u0d7f'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0e01', '\u0e30'), ('\u0e32', '\u0e32'), + ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb2', '\u0eb2'), ('\u0ebd', '\u0ebd'), + ('\u0ec0', '\u0ec4'), ('\u0ec6', '\u0ec6'), + ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), + ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), + ('\u0f88', '\u0f8c'), ('\u1000', '\u102a'), + ('\u103f', '\u103f'), ('\u1050', '\u1055'), + ('\u105a', '\u105d'), ('\u1061', '\u1061'), + ('\u1065', '\u1066'), ('\u106e', '\u1070'), + ('\u1075', '\u1081'), ('\u108e', '\u108e'), + ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), + ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), + ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), + ('\u124a', '\u124d'), ('\u1250', '\u1256'), + ('\u1258', '\u1258'), ('\u125a', '\u125d'), + ('\u1260', '\u1288'), ('\u128a', '\u128d'), + ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), + ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), + ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), + ('\u12d8', '\u1310'), ('\u1312', '\u1315'), + ('\u1318', '\u135a'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1720', '\u1731'), ('\u1740', '\u1751'), + ('\u1760', '\u176c'), ('\u176e', '\u1770'), + ('\u1780', '\u17b3'), ('\u17d7', '\u17d7'), + ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), + ('\u1843', '\u1843'), ('\u1844', '\u1877'), + ('\u1880', '\u18a8'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1950', '\u196d'), ('\u1970', '\u1974'), + ('\u1980', '\u19ab'), ('\u19c1', '\u19c7'), + ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), + ('\u1aa7', '\u1aa7'), ('\u1b05', '\u1b33'), + ('\u1b45', '\u1b4b'), ('\u1b83', '\u1ba0'), + ('\u1bae', '\u1baf'), ('\u1bba', '\u1be5'), + ('\u1c00', '\u1c23'), ('\u1c4d', '\u1c4f'), + ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), + ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), + ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), + ('\u1d9b', '\u1dbf'), ('\u1e00', '\u1f15'), + ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), + ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), + ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), + ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), + ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), + ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), + ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), + ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), + ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u2102', '\u2102'), + ('\u2107', '\u2107'), ('\u210a', '\u2113'), + ('\u2115', '\u2115'), ('\u2118', '\u2118'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u212e', '\u212e'), + ('\u212f', '\u2134'), ('\u2135', '\u2138'), + ('\u2139', '\u2139'), ('\u213c', '\u213f'), + ('\u2145', '\u2149'), ('\u214e', '\u214e'), + ('\u2160', '\u2182'), ('\u2183', '\u2184'), + ('\u2185', '\u2188'), ('\u2c00', '\u2c2e'), + ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), + ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), + ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), + ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), + ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), + ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), + ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309d', '\u309e'), + ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), + ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), + ('\u3105', '\u312d'), ('\u3131', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), + ('\ua000', '\ua014'), ('\ua015', '\ua015'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), + ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua67f', '\ua67f'), + ('\ua680', '\ua697'), ('\ua6a0', '\ua6e5'), + ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua840', '\ua873'), + ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), + ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), + ('\ua930', '\ua946'), ('\ua960', '\ua97c'), + ('\ua984', '\ua9b2'), ('\ua9cf', '\ua9cf'), + ('\uaa00', '\uaa28'), ('\uaa40', '\uaa42'), + ('\uaa44', '\uaa4b'), ('\uaa60', '\uaa6f'), + ('\uaa70', '\uaa70'), ('\uaa71', '\uaa76'), + ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), + ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), + ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), + ('\uaac2', '\uaac2'), ('\uaadb', '\uaadc'), + ('\uaadd', '\uaadd'), ('\uaae0', '\uaaea'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uab01', '\uab06'), ('\uab09', '\uab0e'), + ('\uab11', '\uab16'), ('\uab20', '\uab26'), + ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1f', '\ufb28'), ('\ufb2a', '\ufb36'), + ('\ufb38', '\ufb3c'), ('\ufb3e', '\ufb3e'), + ('\ufb40', '\ufb41'), ('\ufb43', '\ufb44'), + ('\ufb46', '\ufbb1'), ('\ufbd3', '\ufc5d'), + ('\ufc64', '\ufd3d'), ('\ufd50', '\ufd8f'), + ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdf9'), + ('\ufe71', '\ufe71'), ('\ufe73', '\ufe73'), + ('\ufe77', '\ufe77'), ('\ufe79', '\ufe79'), + ('\ufe7b', '\ufe7b'), ('\ufe7d', '\ufe7d'), + ('\ufe7f', '\ufefc'), ('\uff21', '\uff3a'), + ('\uff41', '\uff5a'), ('\uff66', '\uff6f'), + ('\uff70', '\uff70'), ('\uff71', '\uff9d'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), + ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), + ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), + ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), + ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), + ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), + ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a10', '\U00010a13'), + ('\U00010a15', '\U00010a17'), ('\U00010a19', '\U00010a33'), + ('\U00010a60', '\U00010a7c'), ('\U00010b00', '\U00010b35'), + ('\U00010b40', '\U00010b55'), ('\U00010b60', '\U00010b72'), + ('\U00010c00', '\U00010c48'), ('\U00011003', '\U00011037'), + ('\U00011083', '\U000110af'), ('\U000110d0', '\U000110e8'), + ('\U00011103', '\U00011126'), ('\U00011183', '\U000111b2'), + ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), + ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), + ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), + ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), + ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), + ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), + ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), + ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), + ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), + ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), + ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), + ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), + ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d') + ]; + pub fn XID_Start(c: char) -> bool { - return match c { - '\x41' .. '\x5a' - | '\x61' .. '\x7a' - | '\xaa' - | '\xb5' - | '\xba' - | '\xc0' .. '\xd6' - | '\xd8' .. '\xf6' - | '\xf8' .. '\u01ba' - | '\u01bb' - | '\u01bc' .. '\u01bf' - | '\u01c0' .. '\u01c3' - | '\u01c4' .. '\u0293' - | '\u0294' - | '\u0295' .. '\u02af' - | '\u02b0' .. '\u02c1' - | '\u02c6' .. '\u02d1' - | '\u02e0' .. '\u02e4' - | '\u02ec' - | '\u02ee' - | '\u0370' .. '\u0373' - | '\u0374' - | '\u0376' .. '\u0377' - | '\u037b' .. '\u037d' - | '\u0386' - | '\u0388' .. '\u038a' - | '\u038c' - | '\u038e' .. '\u03a1' - | '\u03a3' .. '\u03f5' - | '\u03f7' .. '\u0481' - | '\u048a' .. '\u0527' - | '\u0531' .. '\u0556' - | '\u0559' - | '\u0561' .. '\u0587' - | '\u05d0' .. '\u05ea' - | '\u05f0' .. '\u05f2' - | '\u0620' .. '\u063f' - | '\u0640' - | '\u0641' .. '\u064a' - | '\u066e' .. '\u066f' - | '\u0671' .. '\u06d3' - | '\u06d5' - | '\u06e5' .. '\u06e6' - | '\u06ee' .. '\u06ef' - | '\u06fa' .. '\u06fc' - | '\u06ff' - | '\u0710' - | '\u0712' .. '\u072f' - | '\u074d' .. '\u07a5' - | '\u07b1' - | '\u07ca' .. '\u07ea' - | '\u07f4' .. '\u07f5' - | '\u07fa' - | '\u0800' .. '\u0815' - | '\u081a' - | '\u0824' - | '\u0828' - | '\u0840' .. '\u0858' - | '\u0904' .. '\u0939' - | '\u093d' - | '\u0950' - | '\u0958' .. '\u0961' - | '\u0971' - | '\u0972' .. '\u0977' - | '\u0979' .. '\u097f' - | '\u0985' .. '\u098c' - | '\u098f' .. '\u0990' - | '\u0993' .. '\u09a8' - | '\u09aa' .. '\u09b0' - | '\u09b2' - | '\u09b6' .. '\u09b9' - | '\u09bd' - | '\u09ce' - | '\u09dc' .. '\u09dd' - | '\u09df' .. '\u09e1' - | '\u09f0' .. '\u09f1' - | '\u0a05' .. '\u0a0a' - | '\u0a0f' .. '\u0a10' - | '\u0a13' .. '\u0a28' - | '\u0a2a' .. '\u0a30' - | '\u0a32' .. '\u0a33' - | '\u0a35' .. '\u0a36' - | '\u0a38' .. '\u0a39' - | '\u0a59' .. '\u0a5c' - | '\u0a5e' - | '\u0a72' .. '\u0a74' - | '\u0a85' .. '\u0a8d' - | '\u0a8f' .. '\u0a91' - | '\u0a93' .. '\u0aa8' - | '\u0aaa' .. '\u0ab0' - | '\u0ab2' .. '\u0ab3' - | '\u0ab5' .. '\u0ab9' - | '\u0abd' - | '\u0ad0' - | '\u0ae0' .. '\u0ae1' - | '\u0b05' .. '\u0b0c' - | '\u0b0f' .. '\u0b10' - | '\u0b13' .. '\u0b28' - | '\u0b2a' .. '\u0b30' - | '\u0b32' .. '\u0b33' - | '\u0b35' .. '\u0b39' - | '\u0b3d' - | '\u0b5c' .. '\u0b5d' - | '\u0b5f' .. '\u0b61' - | '\u0b71' - | '\u0b83' - | '\u0b85' .. '\u0b8a' - | '\u0b8e' .. '\u0b90' - | '\u0b92' .. '\u0b95' - | '\u0b99' .. '\u0b9a' - | '\u0b9c' - | '\u0b9e' .. '\u0b9f' - | '\u0ba3' .. '\u0ba4' - | '\u0ba8' .. '\u0baa' - | '\u0bae' .. '\u0bb9' - | '\u0bd0' - | '\u0c05' .. '\u0c0c' - | '\u0c0e' .. '\u0c10' - | '\u0c12' .. '\u0c28' - | '\u0c2a' .. '\u0c33' - | '\u0c35' .. '\u0c39' - | '\u0c3d' - | '\u0c58' .. '\u0c59' - | '\u0c60' .. '\u0c61' - | '\u0c85' .. '\u0c8c' - | '\u0c8e' .. '\u0c90' - | '\u0c92' .. '\u0ca8' - | '\u0caa' .. '\u0cb3' - | '\u0cb5' .. '\u0cb9' - | '\u0cbd' - | '\u0cde' - | '\u0ce0' .. '\u0ce1' - | '\u0cf1' .. '\u0cf2' - | '\u0d05' .. '\u0d0c' - | '\u0d0e' .. '\u0d10' - | '\u0d12' .. '\u0d3a' - | '\u0d3d' - | '\u0d4e' - | '\u0d60' .. '\u0d61' - | '\u0d7a' .. '\u0d7f' - | '\u0d85' .. '\u0d96' - | '\u0d9a' .. '\u0db1' - | '\u0db3' .. '\u0dbb' - | '\u0dbd' - | '\u0dc0' .. '\u0dc6' - | '\u0e01' .. '\u0e30' - | '\u0e32' - | '\u0e40' .. '\u0e45' - | '\u0e46' - | '\u0e81' .. '\u0e82' - | '\u0e84' - | '\u0e87' .. '\u0e88' - | '\u0e8a' - | '\u0e8d' - | '\u0e94' .. '\u0e97' - | '\u0e99' .. '\u0e9f' - | '\u0ea1' .. '\u0ea3' - | '\u0ea5' - | '\u0ea7' - | '\u0eaa' .. '\u0eab' - | '\u0ead' .. '\u0eb0' - | '\u0eb2' - | '\u0ebd' - | '\u0ec0' .. '\u0ec4' - | '\u0ec6' - | '\u0edc' .. '\u0edd' - | '\u0f00' - | '\u0f40' .. '\u0f47' - | '\u0f49' .. '\u0f6c' - | '\u0f88' .. '\u0f8c' - | '\u1000' .. '\u102a' - | '\u103f' - | '\u1050' .. '\u1055' - | '\u105a' .. '\u105d' - | '\u1061' - | '\u1065' .. '\u1066' - | '\u106e' .. '\u1070' - | '\u1075' .. '\u1081' - | '\u108e' - | '\u10a0' .. '\u10c5' - | '\u10d0' .. '\u10fa' - | '\u10fc' - | '\u1100' .. '\u1248' - | '\u124a' .. '\u124d' - | '\u1250' .. '\u1256' - | '\u1258' - | '\u125a' .. '\u125d' - | '\u1260' .. '\u1288' - | '\u128a' .. '\u128d' - | '\u1290' .. '\u12b0' - | '\u12b2' .. '\u12b5' - | '\u12b8' .. '\u12be' - | '\u12c0' - | '\u12c2' .. '\u12c5' - | '\u12c8' .. '\u12d6' - | '\u12d8' .. '\u1310' - | '\u1312' .. '\u1315' - | '\u1318' .. '\u135a' - | '\u1380' .. '\u138f' - | '\u13a0' .. '\u13f4' - | '\u1401' .. '\u166c' - | '\u166f' .. '\u167f' - | '\u1681' .. '\u169a' - | '\u16a0' .. '\u16ea' - | '\u16ee' .. '\u16f0' - | '\u1700' .. '\u170c' - | '\u170e' .. '\u1711' - | '\u1720' .. '\u1731' - | '\u1740' .. '\u1751' - | '\u1760' .. '\u176c' - | '\u176e' .. '\u1770' - | '\u1780' .. '\u17b3' - | '\u17d7' - | '\u17dc' - | '\u1820' .. '\u1842' - | '\u1843' - | '\u1844' .. '\u1877' - | '\u1880' .. '\u18a8' - | '\u18aa' - | '\u18b0' .. '\u18f5' - | '\u1900' .. '\u191c' - | '\u1950' .. '\u196d' - | '\u1970' .. '\u1974' - | '\u1980' .. '\u19ab' - | '\u19c1' .. '\u19c7' - | '\u1a00' .. '\u1a16' - | '\u1a20' .. '\u1a54' - | '\u1aa7' - | '\u1b05' .. '\u1b33' - | '\u1b45' .. '\u1b4b' - | '\u1b83' .. '\u1ba0' - | '\u1bae' .. '\u1baf' - | '\u1bc0' .. '\u1be5' - | '\u1c00' .. '\u1c23' - | '\u1c4d' .. '\u1c4f' - | '\u1c5a' .. '\u1c77' - | '\u1c78' .. '\u1c7d' - | '\u1ce9' .. '\u1cec' - | '\u1cee' .. '\u1cf1' - | '\u1d00' .. '\u1d2b' - | '\u1d2c' .. '\u1d61' - | '\u1d62' .. '\u1d77' - | '\u1d78' - | '\u1d79' .. '\u1d9a' - | '\u1d9b' .. '\u1dbf' - | '\u1e00' .. '\u1f15' - | '\u1f18' .. '\u1f1d' - | '\u1f20' .. '\u1f45' - | '\u1f48' .. '\u1f4d' - | '\u1f50' .. '\u1f57' - | '\u1f59' - | '\u1f5b' - | '\u1f5d' - | '\u1f5f' .. '\u1f7d' - | '\u1f80' .. '\u1fb4' - | '\u1fb6' .. '\u1fbc' - | '\u1fbe' - | '\u1fc2' .. '\u1fc4' - | '\u1fc6' .. '\u1fcc' - | '\u1fd0' .. '\u1fd3' - | '\u1fd6' .. '\u1fdb' - | '\u1fe0' .. '\u1fec' - | '\u1ff2' .. '\u1ff4' - | '\u1ff6' .. '\u1ffc' - | '\u2071' - | '\u207f' - | '\u2090' .. '\u209c' - | '\u2102' - | '\u2107' - | '\u210a' .. '\u2113' - | '\u2115' - | '\u2118' - | '\u2119' .. '\u211d' - | '\u2124' - | '\u2126' - | '\u2128' - | '\u212a' .. '\u212d' - | '\u212e' - | '\u212f' .. '\u2134' - | '\u2135' .. '\u2138' - | '\u2139' - | '\u213c' .. '\u213f' - | '\u2145' .. '\u2149' - | '\u214e' - | '\u2160' .. '\u2182' - | '\u2183' .. '\u2184' - | '\u2185' .. '\u2188' - | '\u2c00' .. '\u2c2e' - | '\u2c30' .. '\u2c5e' - | '\u2c60' .. '\u2c7c' - | '\u2c7d' - | '\u2c7e' .. '\u2ce4' - | '\u2ceb' .. '\u2cee' - | '\u2d00' .. '\u2d25' - | '\u2d30' .. '\u2d65' - | '\u2d6f' - | '\u2d80' .. '\u2d96' - | '\u2da0' .. '\u2da6' - | '\u2da8' .. '\u2dae' - | '\u2db0' .. '\u2db6' - | '\u2db8' .. '\u2dbe' - | '\u2dc0' .. '\u2dc6' - | '\u2dc8' .. '\u2dce' - | '\u2dd0' .. '\u2dd6' - | '\u2dd8' .. '\u2dde' - | '\u3005' - | '\u3006' - | '\u3007' - | '\u3021' .. '\u3029' - | '\u3031' .. '\u3035' - | '\u3038' .. '\u303a' - | '\u303b' - | '\u303c' - | '\u3041' .. '\u3096' - | '\u309d' .. '\u309e' - | '\u309f' - | '\u30a1' .. '\u30fa' - | '\u30fc' .. '\u30fe' - | '\u30ff' - | '\u3105' .. '\u312d' - | '\u3131' .. '\u318e' - | '\u31a0' .. '\u31ba' - | '\u31f0' .. '\u31ff' - | '\u3400' .. '\u4db5' - | '\u4e00' .. '\u9fcb' - | '\ua000' .. '\ua014' - | '\ua015' - | '\ua016' .. '\ua48c' - | '\ua4d0' .. '\ua4f7' - | '\ua4f8' .. '\ua4fd' - | '\ua500' .. '\ua60b' - | '\ua60c' - | '\ua610' .. '\ua61f' - | '\ua62a' .. '\ua62b' - | '\ua640' .. '\ua66d' - | '\ua66e' - | '\ua67f' - | '\ua680' .. '\ua697' - | '\ua6a0' .. '\ua6e5' - | '\ua6e6' .. '\ua6ef' - | '\ua717' .. '\ua71f' - | '\ua722' .. '\ua76f' - | '\ua770' - | '\ua771' .. '\ua787' - | '\ua788' - | '\ua78b' .. '\ua78e' - | '\ua790' .. '\ua791' - | '\ua7a0' .. '\ua7a9' - | '\ua7fa' - | '\ua7fb' .. '\ua801' - | '\ua803' .. '\ua805' - | '\ua807' .. '\ua80a' - | '\ua80c' .. '\ua822' - | '\ua840' .. '\ua873' - | '\ua882' .. '\ua8b3' - | '\ua8f2' .. '\ua8f7' - | '\ua8fb' - | '\ua90a' .. '\ua925' - | '\ua930' .. '\ua946' - | '\ua960' .. '\ua97c' - | '\ua984' .. '\ua9b2' - | '\ua9cf' - | '\uaa00' .. '\uaa28' - | '\uaa40' .. '\uaa42' - | '\uaa44' .. '\uaa4b' - | '\uaa60' .. '\uaa6f' - | '\uaa70' - | '\uaa71' .. '\uaa76' - | '\uaa7a' - | '\uaa80' .. '\uaaaf' - | '\uaab1' - | '\uaab5' .. '\uaab6' - | '\uaab9' .. '\uaabd' - | '\uaac0' - | '\uaac2' - | '\uaadb' .. '\uaadc' - | '\uaadd' - | '\uab01' .. '\uab06' - | '\uab09' .. '\uab0e' - | '\uab11' .. '\uab16' - | '\uab20' .. '\uab26' - | '\uab28' .. '\uab2e' - | '\uabc0' .. '\uabe2' - | '\uac00' .. '\ud7a3' - | '\ud7b0' .. '\ud7c6' - | '\ud7cb' .. '\ud7fb' - | '\uf900' .. '\ufa2d' - | '\ufa30' .. '\ufa6d' - | '\ufa70' .. '\ufad9' - | '\ufb00' .. '\ufb06' - | '\ufb13' .. '\ufb17' - | '\ufb1d' - | '\ufb1f' .. '\ufb28' - | '\ufb2a' .. '\ufb36' - | '\ufb38' .. '\ufb3c' - | '\ufb3e' - | '\ufb40' .. '\ufb41' - | '\ufb43' .. '\ufb44' - | '\ufb46' .. '\ufbb1' - | '\ufbd3' .. '\ufc5d' - | '\ufc64' .. '\ufd3d' - | '\ufd50' .. '\ufd8f' - | '\ufd92' .. '\ufdc7' - | '\ufdf0' .. '\ufdf9' - | '\ufe71' - | '\ufe73' - | '\ufe77' - | '\ufe79' - | '\ufe7b' - | '\ufe7d' - | '\ufe7f' .. '\ufefc' - | '\uff21' .. '\uff3a' - | '\uff41' .. '\uff5a' - | '\uff66' .. '\uff6f' - | '\uff70' - | '\uff71' .. '\uff9d' - | '\uffa0' .. '\uffbe' - | '\uffc2' .. '\uffc7' - | '\uffca' .. '\uffcf' - | '\uffd2' .. '\uffd7' - | '\uffda' .. '\uffdc' - | '\U00010000' .. '\U0001000b' - | '\U0001000d' .. '\U00010026' - | '\U00010028' .. '\U0001003a' - | '\U0001003c' .. '\U0001003d' - | '\U0001003f' .. '\U0001004d' - | '\U00010050' .. '\U0001005d' - | '\U00010080' .. '\U000100fa' - | '\U00010140' .. '\U00010174' - | '\U00010280' .. '\U0001029c' - | '\U000102a0' .. '\U000102d0' - | '\U00010300' .. '\U0001031e' - | '\U00010330' .. '\U00010340' - | '\U00010341' - | '\U00010342' .. '\U00010349' - | '\U0001034a' - | '\U00010380' .. '\U0001039d' - | '\U000103a0' .. '\U000103c3' - | '\U000103c8' .. '\U000103cf' - | '\U000103d1' .. '\U000103d5' - | '\U00010400' .. '\U0001044f' - | '\U00010450' .. '\U0001049d' - | '\U00010800' .. '\U00010805' - | '\U00010808' - | '\U0001080a' .. '\U00010835' - | '\U00010837' .. '\U00010838' - | '\U0001083c' - | '\U0001083f' .. '\U00010855' - | '\U00010900' .. '\U00010915' - | '\U00010920' .. '\U00010939' - | '\U00010a00' - | '\U00010a10' .. '\U00010a13' - | '\U00010a15' .. '\U00010a17' - | '\U00010a19' .. '\U00010a33' - | '\U00010a60' .. '\U00010a7c' - | '\U00010b00' .. '\U00010b35' - | '\U00010b40' .. '\U00010b55' - | '\U00010b60' .. '\U00010b72' - | '\U00010c00' .. '\U00010c48' - | '\U00011003' .. '\U00011037' - | '\U00011083' .. '\U000110af' - | '\U00012000' .. '\U0001236e' - | '\U00012400' .. '\U00012462' - | '\U00013000' .. '\U0001342e' - | '\U00016800' .. '\U00016a38' - | '\U0001b000' .. '\U0001b001' - | '\U0001d400' .. '\U0001d454' - | '\U0001d456' .. '\U0001d49c' - | '\U0001d49e' .. '\U0001d49f' - | '\U0001d4a2' - | '\U0001d4a5' .. '\U0001d4a6' - | '\U0001d4a9' .. '\U0001d4ac' - | '\U0001d4ae' .. '\U0001d4b9' - | '\U0001d4bb' - | '\U0001d4bd' .. '\U0001d4c3' - | '\U0001d4c5' .. '\U0001d505' - | '\U0001d507' .. '\U0001d50a' - | '\U0001d50d' .. '\U0001d514' - | '\U0001d516' .. '\U0001d51c' - | '\U0001d51e' .. '\U0001d539' - | '\U0001d53b' .. '\U0001d53e' - | '\U0001d540' .. '\U0001d544' - | '\U0001d546' - | '\U0001d54a' .. '\U0001d550' - | '\U0001d552' .. '\U0001d6a5' - | '\U0001d6a8' .. '\U0001d6c0' - | '\U0001d6c2' .. '\U0001d6da' - | '\U0001d6dc' .. '\U0001d6fa' - | '\U0001d6fc' .. '\U0001d714' - | '\U0001d716' .. '\U0001d734' - | '\U0001d736' .. '\U0001d74e' - | '\U0001d750' .. '\U0001d76e' - | '\U0001d770' .. '\U0001d788' - | '\U0001d78a' .. '\U0001d7a8' - | '\U0001d7aa' .. '\U0001d7c2' - | '\U0001d7c4' .. '\U0001d7cb' - | '\U00020000' .. '\U0002a6d6' - | '\U0002a700' .. '\U0002b734' - | '\U0002b740' .. '\U0002b81d' - | '\U0002f800' .. '\U0002fa1d' - => true, - _ => false - }; + bsearch_range_table(c, XID_Start_table) } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 01d1a57d78c3d..2a199dddbf45a 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1235,7 +1235,7 @@ pub fn rposition_between(v: &[T], start: uint, end: uint, * Returns the index where the comparator returned `Equal`, or `None` if * not found. */ -pub pure fn bsearch(v: &[T], f: &fn(&T) -> Ordering) -> Option { +pub fn bsearch(v: &[T], f: &fn(&T) -> Ordering) -> Option { let mut base : uint = 0; let mut lim : uint = v.len(); @@ -1259,7 +1259,7 @@ pub pure fn bsearch(v: &[T], f: &fn(&T) -> Ordering) -> Option { * * Returns the index of the element or None if not found. */ -pub pure fn bsearch_elem(v: &[T], x: &T) -> Option { +pub fn bsearch_elem(v: &[T], x: &T) -> Option { bsearch(v, |p| p.cmp(x)) } @@ -3752,47 +3752,47 @@ mod tests { #[test] fn test_bsearch_elem() { - fail_unless!(bsearch_elem([1,2,3,4,5], &5) == Some(4)); - fail_unless!(bsearch_elem([1,2,3,4,5], &4) == Some(3)); - fail_unless!(bsearch_elem([1,2,3,4,5], &3) == Some(2)); - fail_unless!(bsearch_elem([1,2,3,4,5], &2) == Some(1)); - fail_unless!(bsearch_elem([1,2,3,4,5], &1) == Some(0)); - - fail_unless!(bsearch_elem([2,4,6,8,10], &1) == None); - fail_unless!(bsearch_elem([2,4,6,8,10], &5) == None); - fail_unless!(bsearch_elem([2,4,6,8,10], &4) == Some(1)); - fail_unless!(bsearch_elem([2,4,6,8,10], &10) == Some(4)); - - fail_unless!(bsearch_elem([2,4,6,8], &1) == None); - fail_unless!(bsearch_elem([2,4,6,8], &5) == None); - fail_unless!(bsearch_elem([2,4,6,8], &4) == Some(1)); - fail_unless!(bsearch_elem([2,4,6,8], &8) == Some(3)); - - fail_unless!(bsearch_elem([2,4,6], &1) == None); - fail_unless!(bsearch_elem([2,4,6], &5) == None); - fail_unless!(bsearch_elem([2,4,6], &4) == Some(1)); - fail_unless!(bsearch_elem([2,4,6], &6) == Some(2)); - - fail_unless!(bsearch_elem([2,4], &1) == None); - fail_unless!(bsearch_elem([2,4], &5) == None); - fail_unless!(bsearch_elem([2,4], &2) == Some(0)); - fail_unless!(bsearch_elem([2,4], &4) == Some(1)); - - fail_unless!(bsearch_elem([2], &1) == None); - fail_unless!(bsearch_elem([2], &5) == None); - fail_unless!(bsearch_elem([2], &2) == Some(0)); - - fail_unless!(bsearch_elem([], &1) == None); - fail_unless!(bsearch_elem([], &5) == None); - - fail_unless!(bsearch_elem([1,1,1,1,1], &1) != None); - fail_unless!(bsearch_elem([1,1,1,1,2], &1) != None); - fail_unless!(bsearch_elem([1,1,1,2,2], &1) != None); - fail_unless!(bsearch_elem([1,1,2,2,2], &1) != None); - fail_unless!(bsearch_elem([1,2,2,2,2], &1) == Some(0)); - - fail_unless!(bsearch_elem([1,2,3,4,5], &6) == None); - fail_unless!(bsearch_elem([1,2,3,4,5], &0) == None); + assert!(bsearch_elem([1,2,3,4,5], &5) == Some(4)); + assert!(bsearch_elem([1,2,3,4,5], &4) == Some(3)); + assert!(bsearch_elem([1,2,3,4,5], &3) == Some(2)); + assert!(bsearch_elem([1,2,3,4,5], &2) == Some(1)); + assert!(bsearch_elem([1,2,3,4,5], &1) == Some(0)); + + assert!(bsearch_elem([2,4,6,8,10], &1) == None); + assert!(bsearch_elem([2,4,6,8,10], &5) == None); + assert!(bsearch_elem([2,4,6,8,10], &4) == Some(1)); + assert!(bsearch_elem([2,4,6,8,10], &10) == Some(4)); + + assert!(bsearch_elem([2,4,6,8], &1) == None); + assert!(bsearch_elem([2,4,6,8], &5) == None); + assert!(bsearch_elem([2,4,6,8], &4) == Some(1)); + assert!(bsearch_elem([2,4,6,8], &8) == Some(3)); + + assert!(bsearch_elem([2,4,6], &1) == None); + assert!(bsearch_elem([2,4,6], &5) == None); + assert!(bsearch_elem([2,4,6], &4) == Some(1)); + assert!(bsearch_elem([2,4,6], &6) == Some(2)); + + assert!(bsearch_elem([2,4], &1) == None); + assert!(bsearch_elem([2,4], &5) == None); + assert!(bsearch_elem([2,4], &2) == Some(0)); + assert!(bsearch_elem([2,4], &4) == Some(1)); + + assert!(bsearch_elem([2], &1) == None); + assert!(bsearch_elem([2], &5) == None); + assert!(bsearch_elem([2], &2) == Some(0)); + + assert!(bsearch_elem([], &1) == None); + assert!(bsearch_elem([], &5) == None); + + assert!(bsearch_elem([1,1,1,1,1], &1) != None); + assert!(bsearch_elem([1,1,1,1,2], &1) != None); + assert!(bsearch_elem([1,1,1,2,2], &1) != None); + assert!(bsearch_elem([1,1,2,2,2], &1) != None); + assert!(bsearch_elem([1,2,2,2,2], &1) == Some(0)); + + assert!(bsearch_elem([1,2,3,4,5], &6) == None); + assert!(bsearch_elem([1,2,3,4,5], &0) == None); } #[test] diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index bc930515a5d89..a9edf12f7fa82 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -535,7 +535,7 @@ fn ident_start(c: char) -> bool { (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' - || (c > 'z' && char::is_XID_start(c)) + || (c > '\x7f' && char::is_XID_start(c)) } fn ident_continue(c: char) -> bool { @@ -543,7 +543,7 @@ fn ident_continue(c: char) -> bool { || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' - || (c > 'z' && char::is_XID_continue(c)) + || (c > '\x7f' && char::is_XID_continue(c)) } // return the next token from the string From 18db9a2954450cdc5ace4c91a147804824aa153b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 16 Apr 2013 16:10:21 -0700 Subject: [PATCH 266/403] rustc: One less copy --- src/librustc/back/link.rs | 4 ++-- src/librustc/driver/driver.rs | 8 ++++---- src/librustc/driver/session.rs | 4 ++-- src/librustc/rustc.rc | 11 +++++------ 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 1c99566280815..8794dae117811 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -153,9 +153,9 @@ pub mod jit { code: entry, env: ptr::null() }; - let func: &fn(++argv: ~[~str]) = cast::transmute(closure); + let func: &fn(++argv: ~[@~str]) = cast::transmute(closure); - func(~[/*bad*/copy sess.opts.binary]); + func(~[sess.opts.binary]); } } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index a804469ac6511..44c092d869779 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -62,7 +62,7 @@ pub fn source_name(input: input) -> ~str { } } -pub fn default_configuration(sess: Session, +argv0: ~str, input: input) -> +pub fn default_configuration(sess: Session, argv0: @~str, input: input) -> ast::crate_cfg { let libc = match sess.targ_cfg.os { session::os_win32 => ~"msvcrt.dll", @@ -101,7 +101,7 @@ pub fn default_configuration(sess: Session, +argv0: ~str, input: input) -> mk(@~"target_word_size", @wordsz), mk(@~"target_libc", @libc), // Build bindings. - mk(@~"build_compiler", @argv0), + mk(@~"build_compiler", argv0), mk(@~"build_input", @source_name(input))]; } @@ -114,7 +114,7 @@ pub fn append_configuration(+cfg: ast::crate_cfg, +name: ~str) } } -pub fn build_configuration(sess: Session, +argv0: ~str, input: input) -> +pub fn build_configuration(sess: Session, argv0: @~str, input: input) -> ast::crate_cfg { // Combine the configuration requested by the session (command line) with // some default and generated configuration items @@ -523,7 +523,7 @@ pub fn host_triple() -> ~str { }; } -pub fn build_session_options(+binary: ~str, +pub fn build_session_options(binary: @~str, matches: &getopts::Matches, demitter: diagnostic::Emitter) -> @session::options { diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index aee5e01e09108..6171ebd8610e4 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -131,7 +131,7 @@ pub struct options { // will be added to the crate AST node. This should not be used for // anything except building the full crate config prior to parsing. cfg: ast::crate_cfg, - binary: ~str, + binary: @~str, test: bool, parse_only: bool, no_trans: bool, @@ -303,7 +303,7 @@ pub fn basic_options() -> @options { maybe_sysroot: None, target_triple: host_triple(), cfg: ~[], - binary: ~"rustc", + binary: @~"rustc", test: false, parse_only: false, no_trans: false, diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 3fbe1b96ef7aa..67f71682d32f4 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -206,9 +206,9 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { ::core::logging::console_off(); let mut args = /*bad*/copy *args; - let binary = args.shift(); + let binary = @args.shift(); - if args.is_empty() { usage(binary); return; } + if args.is_empty() { usage(*binary); return; } let matches = &match getopts::groups::getopts(args, optgroups()) { @@ -219,7 +219,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { }; if opt_present(matches, ~"h") || opt_present(matches, ~"help") { - usage(binary); + usage(*binary); return; } @@ -236,7 +236,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { } if opt_present(matches, ~"v") || opt_present(matches, ~"version") { - version(binary); + version(*binary); return; } let input = match vec::len(matches.free) { @@ -253,8 +253,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { _ => early_error(demitter, ~"multiple input filenames provided") }; - // XXX: Bad copy. - let sopts = build_session_options(copy binary, matches, demitter); + let sopts = build_session_options(binary, matches, demitter); let sess = build_session(sopts, demitter); let odir = getopts::opt_maybe_str(matches, ~"out-dir"); let odir = odir.map(|o| Path(*o)); From d2718e6324270831b36e14638d8522b702a3534a Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Thu, 18 Apr 2013 18:05:33 -0400 Subject: [PATCH 267/403] xfail box and vec debug info tests --- src/test/debug-info/box.rs | 2 ++ src/test/debug-info/vec.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs index f77ec3f947a05..54aa0c12578b9 100644 --- a/src/test/debug-info/box.rs +++ b/src/test/debug-info/box.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break 29 diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs index 861af3bdbc21d..3876f1c46d487 100644 --- a/src/test/debug-info/vec.rs +++ b/src/test/debug-info/vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + // compile-flags:-Z extra-debug-info // debugger:set print pretty off // debugger:break 29 From 62847b0f24a1a550778f0b150a09dcf4c90f3b41 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 17 Apr 2013 19:36:59 -0700 Subject: [PATCH 268/403] rustc: Make some typechecker errors non-fatal --- src/librustc/middle/typeck/check/_match.rs | 43 ++++++++++++++----- .../compile-fail/pattern-error-continue.rs | 36 ++++++++++++++++ 2 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 src/test/compile-fail/pattern-error-continue.rs diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index e2dd0d1ed9ed2..e0c3e71a5a1ad 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -195,7 +195,9 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::Path, Some(ref subpats) => subpats_len = subpats.len() } - if arg_len > 0u { + let mut error_happened = false; + + if arg_len > 0 { // N-ary variant. if arg_len != subpats_len { let s = fmt!("this pattern has %u field%s, but the corresponding \ @@ -205,23 +207,36 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::Path, kind_name, arg_len, if arg_len == 1u { ~"" } else { ~"s" }); - // XXX: This should not be fatal. - tcx.sess.span_fatal(pat.span, s); + tcx.sess.span_err(pat.span, s); + error_happened = true; } - for subpats.each |pats| { - for vec::each2(*pats, arg_types) |subpat, arg_ty| { - check_pat(pcx, *subpat, *arg_ty); + if !error_happened { + for subpats.each |pats| { + for vec::each2(*pats, arg_types) |subpat, arg_ty| { + check_pat(pcx, *subpat, *arg_ty); + } } } - } else if subpats_len > 0u { - tcx.sess.span_fatal + } else if subpats_len > 0 { + tcx.sess.span_err (pat.span, fmt!("this pattern has %u field%s, but the \ corresponding %s has no fields", subpats_len, if subpats_len == 1u { ~"" } else { ~"s" }, kind_name)); + error_happened = true; + } + + if error_happened { + let tcx = pcx.fcx.ccx.tcx; + + for subpats.each |pats| { + for pats.each |pat| { + check_pat(pcx, *pat, ty::mk_err(tcx)); + } + } } } @@ -446,6 +461,7 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { ast::pat_struct(path, ref fields, etc) => { // Grab the class data that we care about. let structure = structure_of(fcx, pat.span, expected); + let mut error_happened = false; match structure { ty::ty_struct(cid, ref substs) => { check_struct_pat(pcx, pat.id, pat.span, expected, path, @@ -457,16 +473,21 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { substs); } _ => { - // XXX: This should not be fatal. - tcx.sess.span_fatal(pat.span, + tcx.sess.span_err(pat.span, fmt!("mismatched types: expected `%s` \ but found struct", fcx.infcx().ty_to_str(expected))); + error_happened = true; } } // Finally, write in the type. - fcx.write_ty(pat.id, expected); + if error_happened { + fcx.write_error(pat.id); + } + else { + fcx.write_ty(pat.id, expected); + } } ast::pat_tup(ref elts) => { let s = structure_of(fcx, pat.span, expected); diff --git a/src/test/compile-fail/pattern-error-continue.rs b/src/test/compile-fail/pattern-error-continue.rs new file mode 100644 index 0000000000000..14d8b04ade4eb --- /dev/null +++ b/src/test/compile-fail/pattern-error-continue.rs @@ -0,0 +1,36 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that certain pattern-match type errors are non-fatal + +enum A { + B(int, int), + C(int, int, int), + D +} + +struct S { + a: int +} + +fn f(_c: char) {} + +fn main() { + match B(1, 2) { + B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but + D(_) => (), //~ ERROR this pattern has 1 field, but + _ => () + } + match 'c' { + S { _ } => (), //~ ERROR mismatched types: expected `char` but found struct + _ => () + } + f(true); //~ ERROR mismatched types: expected `char` but found `bool` +} \ No newline at end of file From 1aebf30f72c16628ce3b5404329e65a0d4ad4e05 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 18 Apr 2013 15:24:25 -0700 Subject: [PATCH 269/403] Tidy --- src/librustpkg/rustpkg.rc | 2 +- src/librustpkg/testsuite/pass/fancy-lib/bar.rs | 10 ++++++++++ src/librustpkg/testsuite/pass/fancy-lib/foo.rs | 10 ++++++++++ src/librustpkg/testsuite/pass/install-paths/bench.rs | 10 ++++++++++ src/librustpkg/testsuite/pass/simple-lib/bar.rs | 10 ++++++++++ src/librustpkg/testsuite/pass/simple-lib/foo.rs | 10 ++++++++++ src/librustpkg/util.rs | 3 ++- 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index ca8161067c2b6..206404ae2040c 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -752,7 +752,7 @@ impl PkgSrc { `test.rs`, or `bench.rs`."); fail!(~"Failed to infer crates to build"); } - + debug!("found %u libs, %u mains, %u tests, %u benchs", self.libs.len(), self.mains.len(), diff --git a/src/librustpkg/testsuite/pass/fancy-lib/bar.rs b/src/librustpkg/testsuite/pass/fancy-lib/bar.rs index e300c2a3295a3..ffbc6e2a7f9b2 100644 --- a/src/librustpkg/testsuite/pass/fancy-lib/bar.rs +++ b/src/librustpkg/testsuite/pass/fancy-lib/bar.rs @@ -1,3 +1,13 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub fn assert_true() { assert!(true); } diff --git a/src/librustpkg/testsuite/pass/fancy-lib/foo.rs b/src/librustpkg/testsuite/pass/fancy-lib/foo.rs index 4b3f3923d058f..542a6af402d05 100644 --- a/src/librustpkg/testsuite/pass/fancy-lib/foo.rs +++ b/src/librustpkg/testsuite/pass/fancy-lib/foo.rs @@ -1,2 +1,12 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub fn do_nothing() { } \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/install-paths/bench.rs b/src/librustpkg/testsuite/pass/install-paths/bench.rs index 5aa6d2455cf3b..e1641ccf07493 100644 --- a/src/librustpkg/testsuite/pass/install-paths/bench.rs +++ b/src/librustpkg/testsuite/pass/install-paths/bench.rs @@ -1,3 +1,13 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #[bench] fn g() { let mut x = 0; diff --git a/src/librustpkg/testsuite/pass/simple-lib/bar.rs b/src/librustpkg/testsuite/pass/simple-lib/bar.rs index e300c2a3295a3..ffbc6e2a7f9b2 100644 --- a/src/librustpkg/testsuite/pass/simple-lib/bar.rs +++ b/src/librustpkg/testsuite/pass/simple-lib/bar.rs @@ -1,3 +1,13 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub fn assert_true() { assert!(true); } diff --git a/src/librustpkg/testsuite/pass/simple-lib/foo.rs b/src/librustpkg/testsuite/pass/simple-lib/foo.rs index 4b3f3923d058f..542a6af402d05 100644 --- a/src/librustpkg/testsuite/pass/simple-lib/foo.rs +++ b/src/librustpkg/testsuite/pass/simple-lib/foo.rs @@ -1,2 +1,12 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub fn do_nothing() { } \ No newline at end of file diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 1709a8d06ad15..bb162974e035d 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -528,7 +528,8 @@ pub fn compile_crate_from_input(input: driver::input, } None => { debug!("Calling compile_upto, outputs = %?", outputs); - let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, Some(outputs)); + let (crate, _) = driver::compile_upto(sess, cfg, input, + driver::cu_parse, Some(outputs)); // Inject the inferred link_meta info if it's not already there // (assumes that name and vers are the only linkage metas) From 3d43af15d8ddb497e5aa76cb1ae0530198c63f96 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 16 Apr 2013 17:30:31 -0700 Subject: [PATCH 270/403] rustc: Anti-copy police In this case, some copies are still necessary to convert from a mutable to an immutable @-box. It's still an improvement, I hope. --- src/librustc/driver/driver.rs | 8 +++---- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/trans/monomorphize.rs | 10 ++++----- src/librustc/middle/trans/type_use.rs | 27 ++++++++++++----------- src/librustdoc/parse.rs | 2 +- src/librusti/rusti.rc | 8 +++---- src/librustpkg/rustpkg.rc | 4 ++-- src/librustpkg/util.rs | 4 ++-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 44c092d869779..355bc13766648 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -898,9 +898,9 @@ mod test { getopts::fail_str(f)) }; let sessopts = build_session_options( - ~"rustc", matches, diagnostic::emit); + @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); - let cfg = build_configuration(sess, ~"whatever", str_input(~"")); + let cfg = build_configuration(sess, @~"whatever", str_input(~"")); assert!((attr::contains_name(cfg, ~"test"))); } @@ -917,9 +917,9 @@ mod test { } }; let sessopts = build_session_options( - ~"rustc", matches, diagnostic::emit); + @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); - let cfg = build_configuration(sess, ~"whatever", str_input(~"")); + let cfg = build_configuration(sess, @~"whatever", str_input(~"")); let test_items = attr::find_meta_items_by_name(cfg, ~"test"); assert!((vec::len(test_items) == 1u)); } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index f14096443b2b7..cec9a95671e43 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -184,7 +184,7 @@ pub struct CrateContext { monomorphized: @mut HashMap, monomorphizing: @mut HashMap, // Cache computed type parameter uses (see type_use.rs) - type_use_cache: @mut HashMap, + type_use_cache: @mut HashMap, // Cache generated vtables vtables: @mut HashMap, // Cache of constant strings, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 7aab6367d405a..c6ade350e0bba 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -342,7 +342,7 @@ pub fn make_mono_id(ccx: @CrateContext, substs: &[ty::t], vtables: Option, impl_did_opt: Option, - +param_uses: Option<~[type_use::type_uses]>) -> mono_id { + param_uses: Option<@~[type_use::type_uses]>) -> mono_id { let precise_param_ids = match vtables { Some(vts) => { let item_ty = ty::lookup_item_type(ccx.tcx, item); @@ -353,12 +353,12 @@ pub fn make_mono_id(ccx: @CrateContext, match *bound { ty::bound_trait(_) => { v.push(meth::vtable_id(ccx, /*bad*/copy vts[i])); - i += 1u; + i += 1; } _ => () } } - (*subst, if v.len() > 0u { Some(v) } else { None }) + (*subst, if !v.is_empty() { Some(v) } else { None }) }) } None => { @@ -367,7 +367,7 @@ pub fn make_mono_id(ccx: @CrateContext, }; let param_ids = match param_uses { Some(ref uses) => { - vec::map2(precise_param_ids, *uses, |id, uses| { + vec::map2(precise_param_ids, **uses, |id, uses| { if ccx.sess.no_monomorphic_collapse() { match copy *id { (a, b) => mono_precise(a, b) @@ -377,7 +377,7 @@ pub fn make_mono_id(ccx: @CrateContext, // XXX: Bad copy. (a, copy b@Some(_)) => mono_precise(a, b), (subst, None) => { - if *uses == 0u { + if *uses == 0 { mono_any } else if *uses == type_use::use_repr && !ty::type_needs_drop(ccx.tcx, subst) diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 25e3ed0f400a8..4094c597bbbef 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -47,9 +47,9 @@ use syntax::ast_util; use syntax::visit; pub type type_uses = uint; // Bitmask -pub static use_repr: uint = 1u; /* Dependency on size/alignment/mode and +pub static use_repr: uint = 1; /* Dependency on size/alignment/mode and take/drop glue */ -pub static use_tydesc: uint = 2u; /* Takes the tydesc, or compares */ +pub static use_tydesc: uint = 2; /* Takes the tydesc, or compares */ pub struct Context { ccx: @CrateContext, @@ -57,9 +57,9 @@ pub struct Context { } pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) - -> ~[type_uses] { + -> @~[type_uses] { match ccx.type_use_cache.find(&fn_id) { - Some(uses) => return /*bad*/ copy *uses, + Some(uses) => return *uses, None => () } @@ -70,11 +70,11 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) }; // Conservatively assume full use for recursive loops - ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u)); + ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, 3u)); let cx = Context { ccx: ccx, - uses: @mut vec::from_elem(n_tps, 0u) + uses: @mut vec::from_elem(n_tps, 0) }; match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty { ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) | @@ -92,8 +92,9 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) } if fn_id_loc.crate != local_crate { - let uses = copy *cx.uses; - ccx.type_use_cache.insert(fn_id, copy uses); + let Context { uses: @uses, _ } = cx; + let uses = @uses; // mutability + ccx.type_use_cache.insert(fn_id, uses); return uses; } let map_node = match ccx.tcx.items.find(&fn_id_loc.node) { @@ -179,9 +180,9 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) ccx.tcx.sess.parse_sess.interner))); } } - // XXX: Bad copies, use @vec instead? - let uses = copy *cx.uses; - ccx.type_use_cache.insert(fn_id, copy uses); + let Context { uses: @uses, _ } = cx; + let uses = @uses; // mutability + ccx.type_use_cache.insert(fn_id, uses); uses } @@ -253,7 +254,7 @@ pub fn mark_for_method_call(cx: Context, e_id: node_id, callee_id: node_id) { // before stage2 let ts = /*bad*/ copy **ts; let type_uses = type_uses_for(cx.ccx, did, ts.len()); - for vec::each2(type_uses, ts) |uses, subst| { + for vec::each2(*type_uses, ts) |uses, subst| { type_needs(cx, *uses, *subst) } } @@ -302,7 +303,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) { let ts = copy **ts; let id = ast_util::def_id_of_def(*cx.ccx.tcx.def_map.get(&e.id)); let uses_for_ts = type_uses_for(cx.ccx, id, ts.len()); - for vec::each2(uses_for_ts, ts) |uses, subst| { + for vec::each2(*uses_for_ts, ts) |uses, subst| { type_needs(cx, *uses, *subst) } } diff --git a/src/librustdoc/parse.rs b/src/librustdoc/parse.rs index d09182e87f315..6c759e935b931 100644 --- a/src/librustdoc/parse.rs +++ b/src/librustdoc/parse.rs @@ -39,5 +39,5 @@ pub fn from_str_sess(sess: session::Session, source: ~str) -> @ast::crate { } fn cfg(sess: session::Session, input: driver::input) -> ast::crate_cfg { - driver::build_configuration(sess, ~"rustdoc", input) + driver::build_configuration(sess, @~"rustdoc", input) } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 8e4a58c766e53..e14a6e0e7409e 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -127,7 +127,7 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl { fn run(repl: Repl, input: ~str) -> Repl { let options = @session::options { crate_type: session::unknown_crate, - binary: repl.binary, + binary: @repl.binary, addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)), jit: true, .. *session::basic_options() @@ -146,7 +146,7 @@ fn run(repl: Repl, input: ~str) -> Repl { debug!("building driver configuration"); let cfg = driver::build_configuration(sess, - repl.binary, + @repl.binary, wrapped); let outputs = driver::build_output_filenames(wrapped, &None, &None, sess); @@ -191,14 +191,14 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { match do task::try { let src_path = Path(src_filename); let options = @session::options { - binary: binary, + binary: @binary, addl_lib_search_paths: ~[os::getcwd()], .. *session::basic_options() }; let input = driver::file_input(src_path); let sess = driver::build_session(options, diagnostic::emit); *sess.building_library = true; - let cfg = driver::build_configuration(sess, binary, input); + let cfg = driver::build_configuration(sess, @binary, input); let outputs = driver::build_output_filenames( input, &None, &None, sess); // If the library already exists and is newer than the source diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index f8805142769c1..c28e790338db7 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -76,13 +76,13 @@ impl PkgScript { // Build the rustc session data structures to pass // to the compiler let options = @session::options { - binary: binary, + binary: @binary, crate_type: session::bin_crate, .. *session::basic_options() }; let input = driver::file_input(script); let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, binary, input); + let cfg = driver::build_configuration(sess, @binary, input); let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, None); let work_dir = dest_dir(id); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 19938e8c5f178..c61a0025ff6de 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -467,7 +467,7 @@ pub fn compile_input(sysroot: Option, test: test, maybe_sysroot: sysroot, addl_lib_search_paths: ~[copy *out_dir], - .. *driver::build_session_options(binary, &matches, diagnostic::emit) + .. *driver::build_session_options(@binary, &matches, diagnostic::emit) }; let mut crate_cfg = options.cfg; @@ -499,7 +499,7 @@ pub fn compile_crate_from_input(input: driver::input, build_dir_opt: Option { debug!("Calling compile_rest, outputs = %?", outputs); From 0f85cf180a430c066d5b86db0998d124f8dff03b Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 06:06:33 -0400 Subject: [PATCH 271/403] iterator: add skip and take --- src/libcore/iterator.rs | 61 +++++++++++++++++++++++++++++++++++++++++ src/libcore/vec.rs | 28 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 8bd6c73fc7dbb..996951e82192a 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -24,6 +24,8 @@ pub trait IteratorUtil { fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; fn dropwhile<'r>(self, predicate: &'r fn(&A) -> bool) -> DropWhileIterator<'r, A, Self>; fn takewhile<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; + fn skip(self, n: uint) -> SkipIterator; + fn take(self, n: uint) -> TakeIterator; fn enumerate(self) -> EnumerateIterator; fn advance(&mut self, f: &fn(A) -> bool); } @@ -60,6 +62,16 @@ impl> IteratorUtil for T { TakeWhileIterator{iter: self, flag: false, predicate: predicate} } + #[inline(always)] + fn skip(self, n: uint) -> SkipIterator { + SkipIterator{iter: self, n: n} + } + + #[inline(always)] + fn take(self, n: uint) -> TakeIterator { + TakeIterator{iter: self, n: n} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) { @@ -199,3 +211,52 @@ impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { } } } + +pub struct SkipIterator { + priv iter: T, + priv n: uint +} + +impl> Iterator for SkipIterator { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.n == 0 { + next + } else { + let n = self.n; + for n.times { + match next { + Some(_) => { + next = self.iter.next(); + loop + } + None => { + self.n = 0; + return None + } + } + } + self.n = 0; + next + } + } +} + +pub struct TakeIterator { + priv iter: T, + priv n: uint +} + +impl> Iterator for TakeIterator { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + if self.n != 0 { + self.n -= 1; + next + } else { + None + } + } +} diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 45cc9618f59b0..9ebc72c6f409c 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -4512,4 +4512,32 @@ mod tests { } assert_eq!(i, ys.len()); } + + #[test] + fn test_iterator_skip() { + use iterator::*; + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let mut it = xs.iter().skip(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_take() { + use iterator::*; + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5]; + let mut it = xs.iter().take(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } } From 962a753890f801c378b3cb244b7d7ca3cae164a5 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 07:28:51 -0400 Subject: [PATCH 272/403] takewhile -> take_while, dropwhile -> skip_while --- src/libcore/iterator.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 996951e82192a..1887e0cec80ba 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -22,8 +22,8 @@ pub trait IteratorUtil { // FIXME: #5898: should be called map fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; - fn dropwhile<'r>(self, predicate: &'r fn(&A) -> bool) -> DropWhileIterator<'r, A, Self>; - fn takewhile<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; + fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>; + fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; fn skip(self, n: uint) -> SkipIterator; fn take(self, n: uint) -> TakeIterator; fn enumerate(self) -> EnumerateIterator; @@ -53,12 +53,12 @@ impl> IteratorUtil for T { } #[inline(always)] - fn dropwhile<'r>(self, predicate: &'r fn(&A) -> bool) -> DropWhileIterator<'r, A, T> { - DropWhileIterator{iter: self, flag: false, predicate: predicate} + fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> { + SkipWhileIterator{iter: self, flag: false, predicate: predicate} } #[inline(always)] - fn takewhile<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { + fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { TakeWhileIterator{iter: self, flag: false, predicate: predicate} } @@ -154,13 +154,13 @@ impl> Iterator<(uint, A)> for EnumerateIterator { } } -pub struct DropWhileIterator<'self, A, T> { +pub struct SkipWhileIterator<'self, A, T> { priv iter: T, priv flag: bool, priv predicate: &'self fn(&A) -> bool } -impl<'self, A, T: Iterator> Iterator for DropWhileIterator<'self, A, T> { +impl<'self, A, T: Iterator> Iterator for SkipWhileIterator<'self, A, T> { #[inline] fn next(&mut self) -> Option { let mut next = self.iter.next(); From 8ae6b33ed0cf2b1793773f31b8f5249347ef0983 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 19 Apr 2013 22:30:49 +1000 Subject: [PATCH 273/403] libcore: clarify documentation for char_at(_reverse) --- src/libcore/str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 7cc3a694c5608..cb362b2e6c09c 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1863,7 +1863,7 @@ pub fn char_range_at(s: &str, i: uint) -> CharRange { return CharRange {ch: val as char, next: i}; } -/// Plucks the `n`th character from the beginning of a string +/// Plucks the character starting at the `i`th byte of a string pub fn char_at(s: &str, i: uint) -> char { return char_range_at(s, i).ch; } @@ -1874,11 +1874,11 @@ pub struct CharRange { } /** - * Given a byte position and a str, return the previous char and its position + * Given a byte position and a str, return the previous char and its position. * * This function can be used to iterate over a unicode string in reverse. * - * returns 0 for next index if called on start index 0 + * Returns 0 for next index if called on start index 0. */ pub fn char_range_at_reverse(ss: &str, start: uint) -> CharRange { let mut prev = start; @@ -1900,7 +1900,7 @@ pub fn char_range_at_reverse(ss: &str, start: uint) -> CharRange { return CharRange {ch:ch, next:prev}; } -/// Plucks the `n`th character from the end of a string +/// Plucks the character ending at the `i`th byte of a string pub fn char_at_reverse(s: &str, i: uint) -> char { char_range_at_reverse(s, i).ch } From ae1c9ebf3c3a0a7e176314f742f533a788ea0dd2 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 07:30:22 -0400 Subject: [PATCH 274/403] move iterator adaptor tests to iterator module --- src/libcore/iterator.rs | 67 +++++++++++++++++++++++++++++++++++++++++ src/libcore/vec.rs | 66 ---------------------------------------- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 1887e0cec80ba..5e0b8df8c339e 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -260,3 +260,70 @@ impl> Iterator for TakeIterator { } } } + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + #[test] + fn test_iterator_enumerate() { + let xs = [0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + for it.advance |(i, &x): (uint, &uint)| { + assert_eq!(i, x); + } + } + + #[test] + fn test_iterator_take_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5, 13]; + let mut it = xs.iter().take_while(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let mut it = xs.iter().skip_while(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let mut it = xs.iter().skip(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_take() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5]; + let mut it = xs.iter().take(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } +} diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 9ebc72c6f409c..139fcedad2779 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -4474,70 +4474,4 @@ mod tests { i += 1; } } - - #[test] - fn test_iterator_enumerate() { - use iterator::*; - let xs = [0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().enumerate(); - for it.advance |(i, &x): (uint, &uint)| { - assert_eq!(i, x); - } - } - - #[test] - fn test_iterator_takewhile() { - use iterator::*; - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5, 13]; - let mut it = xs.iter().takewhile(|&x| *x < 15u); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_dropwhile() { - use iterator::*; - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [15, 16, 17, 19]; - let mut it = xs.iter().dropwhile(|&x| *x < 15u); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip() { - use iterator::*; - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; - let ys = [13, 15, 16, 17, 19, 20, 30]; - let mut it = xs.iter().skip(5); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_take() { - use iterator::*; - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5]; - let mut it = xs.iter().take(5); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } } From d7a2ae6c42f1d9755178485fd93f234c2df8a8fe Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 09:18:22 -0400 Subject: [PATCH 275/403] re-organize the iterator module a bit --- src/libcore/iterator.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 5e0b8df8c339e..50939ba7faf64 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -22,11 +22,11 @@ pub trait IteratorUtil { // FIXME: #5898: should be called map fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; + fn enumerate(self) -> EnumerateIterator; fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>; fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; fn skip(self, n: uint) -> SkipIterator; fn take(self, n: uint) -> TakeIterator; - fn enumerate(self) -> EnumerateIterator; fn advance(&mut self, f: &fn(A) -> bool); } @@ -101,6 +101,21 @@ impl, U: Iterator> Iterator<(A, B)> for ZipIterator { + priv iter: T, + priv f: &'self fn(A) -> B +} + +impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(a) => Some((self.f)(a)), + _ => None + } + } +} + pub struct FilterIterator<'self, A, T> { priv iter: T, priv predicate: &'self fn(&A) -> bool @@ -120,21 +135,6 @@ impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { } } -pub struct MapIterator<'self, A, B, T> { - priv iter: T, - priv f: &'self fn(A) -> B -} - -impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { - #[inline] - fn next(&mut self) -> Option { - match self.iter.next() { - Some(a) => Some((self.f)(a)), - _ => None - } - } -} - pub struct EnumerateIterator { priv iter: T, priv count: uint From 90313b789c1d057dcc4aeed0374359f4927214c5 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 20 Apr 2013 00:07:07 +1000 Subject: [PATCH 276/403] libcore: add an UnfoldrIterator like Haskell's `unfoldr` --- src/libcore/iterator.rs | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 50939ba7faf64..7ca40ae3a300a 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -261,6 +261,28 @@ impl> Iterator for TakeIterator { } } +pub struct UnfoldrIterator<'self, A, St> { + priv f: &'self fn(&mut St) -> Option, + priv state: St +} + +pub impl<'self, A, St> UnfoldrIterator<'self, A, St> { + #[inline] + fn new(f: &'self fn(&mut St) -> Option, initial_state: St) -> UnfoldrIterator<'self, A, St> { + UnfoldrIterator { + f: f, + state: initial_state + } + } +} + +impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } +} + #[cfg(test)] mod tests { use super::*; @@ -326,4 +348,25 @@ mod tests { } assert_eq!(i, ys.len()); } + + #[test] + fn test_unfoldr() { + fn count(st: &mut uint) -> Option { + if *st < 10 { + let ret = Some(*st); + *st += 1; + ret + } else { + None + } + } + + let mut it = UnfoldrIterator::new(count, 0); + let mut i = 0; + for it.advance |counted| { + assert_eq!(counted, i); + i += 1; + } + assert_eq!(i, 10); + } } From 1d81b7b286d2be46474022935c5ac111dafd5c4d Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 11:29:38 -0400 Subject: [PATCH 277/403] iterator: add a chain adaptor --- src/libcore/iterator.rs | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 7ca40ae3a300a..e233eb7feed67 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -18,6 +18,7 @@ pub trait Iterator { } pub trait IteratorUtil { + fn chain(self, other: Self) -> ChainIterator; fn zip>(self, other: U) -> ZipIterator; // FIXME: #5898: should be called map fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; @@ -31,6 +32,11 @@ pub trait IteratorUtil { } impl> IteratorUtil for T { + #[inline(always)] + fn chain(self, other: T) -> ChainIterator { + ChainIterator{a: self, b: other, flag: false} + } + #[inline(always)] fn zip>(self, other: U) -> ZipIterator { ZipIterator{a: self, b: other} @@ -86,6 +92,28 @@ impl> IteratorUtil for T { } } +pub struct ChainIterator { + priv a: T, + priv b: T, + priv flag: bool +} + +impl> Iterator for ChainIterator { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + self.b.next() + } else { + match self.a.next() { + Some(x) => return Some(x), + _ => () + } + self.flag = true; + self.b.next() + } + } +} + pub struct ZipIterator { priv a: T, priv b: U @@ -288,6 +316,20 @@ mod tests { use super::*; use prelude::*; + #[test] + fn test_iterator_chain() { + let xs = [0u, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + let mut it = xs.iter().chain(ys.iter()); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + } + #[test] fn test_iterator_enumerate() { let xs = [0u, 1, 2, 3, 4, 5]; From a2e535028471b715b5a3aaf7cbeb3e6d77a07af6 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 19 Apr 2013 12:17:24 -0400 Subject: [PATCH 278/403] iterator: add a bit of documentation --- src/libcore/iterator.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index e233eb7feed67..4929b1b8dba37 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -8,7 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Composable iterator objects +/*! Composable external iterators + +The `Iterator` trait defines an interface for objects which implement iteration as a state machine. + +Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects +implementing the `Iterator` trait. + +*/ use prelude::*; @@ -17,6 +24,10 @@ pub trait Iterator { fn next(&mut self) -> Option; } +/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also +/// implementations of the `Iterator` trait. +/// +/// In the future these will be default methods instead of a utility trait. pub trait IteratorUtil { fn chain(self, other: Self) -> ChainIterator; fn zip>(self, other: U) -> ZipIterator; @@ -31,6 +42,10 @@ pub trait IteratorUtil { fn advance(&mut self, f: &fn(A) -> bool); } +/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also +/// implementations of the `Iterator` trait. +/// +/// In the future these will be default methods instead of a utility trait. impl> IteratorUtil for T { #[inline(always)] fn chain(self, other: T) -> ChainIterator { From 1a36b0f17ef0b59411981fdd25ac9ce4ba7e20e0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 28 Mar 2013 18:39:09 -0700 Subject: [PATCH 279/403] librustc: Remove `fail_unless!` --- src/librustc/middle/astencode.rs | 12 +++++++++++- src/test/run-pass/auto-encode.rs | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index a67be995171ff..f9a3c0fab724a 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1336,7 +1336,17 @@ fn roundtrip(in_item: Option<@ast::item>) { let ebml_doc = reader::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); - assert_eq!(in_item, out_item); + let exp_str = do io::with_str_writer |w| { + in_item.encode(&prettyprint::Serializer(w)) + }; + let out_str = do io::with_str_writer |w| { + out_item.encode(&prettyprint::Serializer(w)) + }; + + debug!("expected string: %s", exp_str); + debug!("actual string : %s", out_str); + + assert!(exp_str == out_str); } #[test] diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index bfc15acaa763c..372f8ab4bc8f7 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -25,6 +25,20 @@ use std::ebml; use std::serialize::{Decodable, Encodable}; use std::time; +<<<<<<< HEAD +======= +fn test_prettyprint>( + a: &A, + expected: &~str +) { + let s = do io::with_str_writer |w| { + a.encode(&prettyprint::Serializer(w)) + }; + debug!("s == %?", s); + assert!(s == *expected); +} + +>>>>>>> librustc: Remove `fail_unless!` fn test_ebml + From f903ae9e72ec02539373da22fd4d025422af7554 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 29 Mar 2013 16:55:04 -0700 Subject: [PATCH 280/403] librustc: Implement fast-ffi and use it in various places --- src/libcore/libc.rs | 10 + src/libcore/unstable/lang.rs | 12 +- src/libcore/vec.rs | 2 + src/librustc/driver/driver.rs | 9 +- src/librustc/lib/llvm.rs | 440 +++++++++++++++++++++- src/librustc/middle/astencode.rs | 12 +- src/librustc/middle/trans/base.rs | 85 +++-- src/librustc/middle/trans/closure.rs | 13 +- src/librustc/middle/trans/foreign.rs | 50 ++- src/librustc/middle/trans/inline.rs | 3 +- src/librustc/middle/trans/meth.rs | 3 +- src/librustc/middle/trans/monomorphize.rs | 11 +- src/rt/rust_task.cpp | 5 +- src/rt/rust_upcall.cpp | 15 + src/rt/rustrt.def.in | 2 + src/rustllvm/RustWrapper.cpp | 1 + src/test/run-pass/auto-encode.rs | 14 - 17 files changed, 618 insertions(+), 69 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index e5c5b2f9f2c26..9d100d1d352dd 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1109,8 +1109,10 @@ pub mod funcs { // Omitted: putc, putchar (might be macros). unsafe fn puts(s: *c_char) -> c_int; unsafe fn ungetc(c: c_int, stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *FILE) -> size_t; + #[fast_ffi] unsafe fn fwrite(ptr: *c_void, size: size_t, nobj: size_t, stream: *FILE) -> size_t; unsafe fn fseek(stream: *FILE, offset: c_long, @@ -1144,9 +1146,13 @@ pub mod funcs { -> c_long; unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int) -> c_ulong; + #[fast_ffi] unsafe fn calloc(nobj: size_t, size: size_t) -> *c_void; + #[fast_ffi] unsafe fn malloc(size: size_t) -> *c_void; + #[fast_ffi] unsafe fn realloc(p: *c_void, size: size_t) -> *c_void; + #[fast_ffi] unsafe fn free(p: *c_void); unsafe fn abort() -> !; unsafe fn exit(status: c_int) -> !; @@ -1340,6 +1346,7 @@ pub mod funcs { textmode: c_int) -> c_int; #[link_name = "_read"] + #[fast_ffi] unsafe fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int; @@ -1350,6 +1357,7 @@ pub mod funcs { unsafe fn unlink(c: *c_char) -> c_int; #[link_name = "_write"] + #[fast_ffi] unsafe fn write(fd: c_int, buf: *c_void, count: c_uint) -> c_int; } @@ -1502,6 +1510,7 @@ pub mod funcs { unsafe fn pathconf(path: *c_char, name: c_int) -> c_long; unsafe fn pause() -> c_int; unsafe fn pipe(fds: *mut c_int) -> c_int; + #[fast_ffi] unsafe fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; unsafe fn rmdir(path: *c_char) -> c_int; @@ -1514,6 +1523,7 @@ pub mod funcs { unsafe fn tcgetpgrp(fd: c_int) -> pid_t; unsafe fn ttyname(fd: c_int) -> *c_char; unsafe fn unlink(c: *c_char) -> c_int; + #[fast_ffi] unsafe fn write(fd: c_int, buf: *c_void, count: size_t) -> ssize_t; } diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index be776a39742f0..611862a79e7e0 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -35,6 +35,14 @@ pub mod rustrt { #[rust_stack] unsafe fn rust_upcall_free(ptr: *c_char); + + #[fast_ffi] + unsafe fn rust_upcall_malloc_noswitch(td: *c_char, + size: uintptr_t) + -> *c_char; + + #[fast_ffi] + unsafe fn rust_upcall_free_noswitch(ptr: *c_char); } } @@ -81,7 +89,7 @@ pub unsafe fn exchange_free(ptr: *c_char) { #[lang="malloc"] #[inline(always)] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { - return rustrt::rust_upcall_malloc(td, size); + return rustrt::rust_upcall_malloc_noswitch(td, size); } // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from @@ -90,7 +98,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[lang="free"] #[inline(always)] pub unsafe fn local_free(ptr: *c_char) { - rustrt::rust_upcall_free(ptr); + rustrt::rust_upcall_free_noswitch(ptr); } #[lang="borrow_as_imm"] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 139fcedad2779..f6492ede9f9ca 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -43,9 +43,11 @@ pub mod rustrt { pub extern { // These names are terrible. reserve_shared applies // to ~[] and reserve_shared_actual applies to @[]. + #[fast_ffi] unsafe fn vec_reserve_shared(++t: *sys::TypeDesc, ++v: **raw::VecRepr, ++n: libc::size_t); + #[fast_ffi] unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc, ++v: **raw::VecRepr, ++n: libc::size_t); diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 355bc13766648..7ea1fe8015825 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -172,10 +172,13 @@ pub enum compile_upto { // For continuing compilation after a parsed crate has been // modified -pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, - upto: compile_upto, outputs: Option<@OutputFilenames>, +#[fixed_stack_segment] +pub fn compile_rest(sess: Session, + cfg: ast::crate_cfg, + upto: compile_upto, + outputs: Option<@OutputFilenames>, curr: Option<@ast::crate>) - -> (@ast::crate, Option) { + -> (@ast::crate, Option) { let time_passes = sess.time_passes(); let mut crate = curr.get(); diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 06f7261040c5d..0ab883d330d9d 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -234,438 +234,624 @@ pub mod llvm { #[abi = "cdecl"] pub extern { /* Create and destroy contexts. */ + #[fast_ffi] pub unsafe fn LLVMContextCreate() -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMGetGlobalContext() -> ContextRef; + #[fast_ffi] pub unsafe fn LLVMContextDispose(C: ContextRef); + #[fast_ffi] pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *c_char, SLen: c_uint) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint; /* Create and destroy modules. */ + #[fast_ffi] pub unsafe fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char, C: ContextRef) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMDisposeModule(M: ModuleRef); /** Data layout. See Module::getDataLayout. */ + #[fast_ffi] pub unsafe fn LLVMGetDataLayout(M: ModuleRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetDataLayout(M: ModuleRef, Triple: *c_char); /** Target triple. See Module::getTargetTriple. */ + #[fast_ffi] pub unsafe fn LLVMGetTarget(M: ModuleRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetTarget(M: ModuleRef, Triple: *c_char); /** See Module::dump. */ + #[fast_ffi] pub unsafe fn LLVMDumpModule(M: ModuleRef); /** See Module::setModuleInlineAsm. */ + #[fast_ffi] pub unsafe fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *c_char); /** See llvm::LLVMTypeKind::getTypeID. */ pub unsafe fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind; /** See llvm::LLVMType::getContext. */ + #[fast_ffi] pub unsafe fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef; /* Operations on integer types */ + #[fast_ffi] pub unsafe fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt1Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt8Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt16Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt32Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMInt64Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; /* Operations on real types */ + #[fast_ffi] pub unsafe fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFloatType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMDoubleType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMX86FP80Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMFP128Type() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPPCFP128Type() -> TypeRef; /* Operations on function types */ + #[fast_ffi] pub unsafe fn LLVMFunctionType(ReturnType: TypeRef, ParamTypes: *TypeRef, ParamCount: c_uint, IsVarArg: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *TypeRef); /* Operations on struct types */ + #[fast_ffi] pub unsafe fn LLVMStructTypeInContext(C: ContextRef, ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMStructType(ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetStructElementTypes(StructTy: TypeRef, Dest: *mut TypeRef); + #[fast_ffi] pub unsafe fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool; /* Operations on array, pointer, and vector types (sequence types) */ + #[fast_ffi] pub unsafe fn LLVMArrayType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetElementType(Ty: TypeRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; /* Operations on other types */ + #[fast_ffi] pub unsafe fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMVoidType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMLabelType() -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMMetadataType() -> TypeRef; /* Operations on all values */ + #[fast_ffi] pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMGetValueName(Val: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetValueName(Val: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMDumpValue(Val: ValueRef); + #[fast_ffi] pub unsafe fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); + #[fast_ffi] pub unsafe fn LLVMHasMetadata(Val: ValueRef) -> c_int; + #[fast_ffi] pub unsafe fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef); /* Operations on Uses */ + #[fast_ffi] pub unsafe fn LLVMGetFirstUse(Val: ValueRef) -> UseRef; + #[fast_ffi] pub unsafe fn LLVMGetNextUse(U: UseRef) -> UseRef; + #[fast_ffi] pub unsafe fn LLVMGetUser(U: UseRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetUsedValue(U: UseRef) -> ValueRef; /* Operations on Users */ + #[fast_ffi] pub unsafe fn LLVMGetNumOperands(Val: ValueRef) -> c_int; + #[fast_ffi] pub unsafe fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef); /* Operations on constants of any type */ + #[fast_ffi] pub unsafe fn LLVMConstNull(Ty: TypeRef) -> ValueRef; /* all zeroes */ + #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; /* only for int/vector */ + #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMIsConstant(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMIsNull(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMIsUndef(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef; /* Operations on metadata */ + #[fast_ffi] pub unsafe fn LLVMMDStringInContext(C: ContextRef, Str: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char, Val: ValueRef); /* Operations on scalar constants */ + #[fast_ffi] pub unsafe fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntOfString(IntTy: TypeRef, Text: *c_char, Radix: u8) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntOfStringAndSize(IntTy: TypeRef, Text: *c_char, SLen: c_uint, Radix: u8) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstRealOfString(RealTy: TypeRef, Text: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstRealOfStringAndSize(RealTy: TypeRef, Text: *c_char, SLen: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong; + #[fast_ffi] pub unsafe fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; /* Operations on composite constants */ + #[fast_ffi] pub unsafe fn LLVMConstStringInContext(C: ContextRef, Str: *c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstStructInContext(C: ContextRef, ConstantVals: *ValueRef, Count: c_uint, Packed: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstString(Str: *c_char, Length: c_uint, DontNullTerminate: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef, Length: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef, Count: c_uint, Packed: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef, Size: c_uint) -> ValueRef; /* Constant expressions */ + #[fast_ffi] pub unsafe fn LLVMAlignOf(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSizeOf(Ty: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExactSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstGEP(ConstantVal: ValueRef, ConstantIndices: *ValueRef, NumIndices: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: *ValueRef, NumIndices: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstSelect(ConstantCondition: ValueRef, ConstantIfTrue: ValueRef, ConstantIfFalse: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExtractElement(VectorConstant: ValueRef, IndexConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInsertElement(VectorConstant: ValueRef, ElementValueConstant: ValueRef, IndexConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstShuffleVector(VectorAConstant: ValueRef, VectorBConstant: ValueRef, MaskConstant: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *c_uint, NumIdx: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInsertValue(AggConstant: ValueRef, ElementValueConstant: ValueRef, IdxList: *c_uint, NumIdx: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: *c_char, Constraints: *c_char, HasSideEffects: Bool, IsAlignStack: Bool) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef; /* Operations on global variables, functions, and aliases (globals) */ + #[fast_ffi] pub unsafe fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMIsDeclaration(Global: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMGetLinkage(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetLinkage(Global: ValueRef, Link: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetSection(Global: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetSection(Global: ValueRef, Section: *c_char); + #[fast_ffi] pub unsafe fn LLVMGetVisibility(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetAlignment(Global: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint); /* Operations on global variables */ + #[fast_ffi] pub unsafe fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddGlobalInAddressSpace(M: ModuleRef, Ty: TypeRef, Name: *c_char, AddressSpace: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNamedGlobal(M: ModuleRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMDeleteGlobal(GlobalVar: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef); + #[fast_ffi] pub unsafe fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool); + #[fast_ffi] pub unsafe fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); /* Operations on aliases */ + #[fast_ffi] pub unsafe fn LLVMAddAlias(M: ModuleRef, Ty: TypeRef, Aliasee: ValueRef, @@ -673,161 +859,242 @@ pub mod llvm { -> ValueRef; /* Operations on functions */ + #[fast_ffi] pub unsafe fn LLVMAddFunction(M: ModuleRef, Name: *c_char, FunctionTy: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNamedFunction(M: ModuleRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMDeleteFunction(Fn: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetOrInsertFunction(M: ModuleRef, Name: *c_char, FunctionTy: TypeRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetGC(Fn: ValueRef) -> *c_char; + #[fast_ffi] pub unsafe fn LLVMSetGC(Fn: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMAddFunctionAttr(Fn: ValueRef, - PA: c_ulonglong, - HighPA: c_ulonglong); + PA: c_uint, + HighPA: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong; + #[fast_ffi] pub unsafe fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA: c_ulonglong); /* Operations on parameters */ + #[fast_ffi] pub unsafe fn LLVMCountParams(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint); + #[fast_ffi] pub unsafe fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetAttribute(Arg: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint); /* Operations on basic blocks */ + #[fast_ffi] pub unsafe fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMInsertBasicBlockInContext(C: ContextRef, BB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMAppendBasicBlock(Fn: ValueRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, Name: *c_char) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef); /* Operations on instructions */ + #[fast_ffi] pub unsafe fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef; /* Operations on call sites */ + #[fast_ffi] pub unsafe fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint); + #[fast_ffi] pub unsafe fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); + #[fast_ffi] pub unsafe fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); + #[fast_ffi] pub unsafe fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint, align: c_uint); /* Operations on call instructions (only) */ + #[fast_ffi] pub unsafe fn LLVMIsTailCall(CallInst: ValueRef) -> Bool; + #[fast_ffi] pub unsafe fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); /* Operations on phi nodes */ + #[fast_ffi] pub unsafe fn LLVMAddIncoming(PhiNode: ValueRef, IncomingValues: *ValueRef, IncomingBlocks: *BasicBlockRef, Count: c_uint); + #[fast_ffi] pub unsafe fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint; + #[fast_ffi] pub unsafe fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMGetIncomingBlock(PhiNode: ValueRef, Index: c_uint) -> BasicBlockRef; /* Instruction builders */ + #[fast_ffi] pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; + #[fast_ffi] pub unsafe fn LLVMCreateBuilder() -> BuilderRef; + #[fast_ffi] pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef); + #[fast_ffi] pub unsafe fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef; + #[fast_ffi] pub unsafe fn LLVMClearInsertionPosition(Builder: BuilderRef); + #[fast_ffi] pub unsafe fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef); + #[fast_ffi] pub unsafe fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef, Instr: ValueRef, Name: *c_char); + #[fast_ffi] pub unsafe fn LLVMDisposeBuilder(Builder: BuilderRef); /* Metadata */ + #[fast_ffi] pub unsafe fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef); + #[fast_ffi] pub unsafe fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef); /* Terminators */ + #[fast_ffi] pub unsafe fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *ValueRef, N: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCondBr(B: BuilderRef, If: ValueRef, Then: BasicBlockRef, Else: BasicBlockRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSwitch(B: BuilderRef, V: ValueRef, Else: BasicBlockRef, NumCases: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, Args: *ValueRef, @@ -835,367 +1102,447 @@ pub mod llvm { Then: BasicBlockRef, Catch: BasicBlockRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLandingPad(B: BuilderRef, Ty: TypeRef, PersFn: ValueRef, NumClauses: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; /* Add a case to the switch instruction */ + #[fast_ffi] pub unsafe fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); /* Add a destination to the indirectbr instruction */ + #[fast_ffi] pub unsafe fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef); /* Add a clause to the landing pad instruction */ + #[fast_ffi] pub unsafe fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef); /* Set the cleanup on a landing pad instruction */ + #[fast_ffi] pub unsafe fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool); /* Arithmetic */ + #[fast_ffi] pub unsafe fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExactSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildURem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildShl(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAnd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildOr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildXor(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBinOp(B: BuilderRef, Op: Opcode, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef; /* Memory */ + #[fast_ffi] pub unsafe fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildArrayMalloc(B: BuilderRef, Ty: TypeRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildArrayAlloca(B: BuilderRef, Ty: TypeRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGEP(B: BuilderRef, Pointer: ValueRef, Indices: *ValueRef, NumIndices: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInBoundsGEP(B: BuilderRef, Pointer: ValueRef, Indices: *ValueRef, NumIndices: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildStructGEP(B: BuilderRef, Pointer: ValueRef, Idx: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGlobalString(B: BuilderRef, Str: *c_char, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildGlobalStringPtr(B: BuilderRef, Str: *c_char, Name: *c_char) -> ValueRef; /* Casts */ + #[fast_ffi] pub unsafe fn LLVMBuildTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildZExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPToUI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPToSI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildUIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPtrToInt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIntToPtr(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildZExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildTruncOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCast(B: BuilderRef, Op: Opcode, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPointerCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIntCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFPCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef, Name: *c_char) -> ValueRef; /* Comparisons */ + #[fast_ffi] pub unsafe fn LLVMBuildICmp(B: BuilderRef, Op: c_uint, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildFCmp(B: BuilderRef, Op: c_uint, LHS: ValueRef, RHS: ValueRef, Name: *c_char) -> ValueRef; /* Miscellaneous instructions */ + #[fast_ffi] pub unsafe fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: *ValueRef, NumArgs: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildSelect(B: BuilderRef, If: ValueRef, Then: ValueRef, Else: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildVAArg(B: BuilderRef, list: ValueRef, Ty: TypeRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExtractElement(B: BuilderRef, VecVal: ValueRef, Index: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInsertElement(B: BuilderRef, VecVal: ValueRef, EltVal: ValueRef, Index: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildShuffleVector(B: BuilderRef, V1: ValueRef, V2: ValueRef, Mask: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildExtractValue(B: BuilderRef, AggVal: ValueRef, Index: c_uint, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildInsertValue(B: BuilderRef, AggVal: ValueRef, EltVal: ValueRef, @@ -1203,14 +1550,17 @@ pub mod llvm { Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *c_char) -> ValueRef; + #[fast_ffi] pub unsafe fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, @@ -1225,155 +1575,227 @@ pub mod llvm { ++Order: AtomicOrdering) -> ValueRef; /* Selected entries from the downcasts. */ + #[fast_ffi] pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef; /** Writes a module to the specified path. Returns 0 on success. */ + #[fast_ffi] pub unsafe fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *c_char) -> c_int; /** Creates target data from a target layout string. */ + #[fast_ffi] pub unsafe fn LLVMCreateTargetData(StringRep: *c_char) -> TargetDataRef; /** Adds the target data to the given pass manager. The pass manager references the target data only weakly. */ + #[fast_ffi] pub unsafe fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef); /** Number of bytes clobbered when doing a Store to *T. */ + #[fast_ffi] pub unsafe fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong; /** Number of bytes clobbered when doing a Store to *T. */ + #[fast_ffi] pub unsafe fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong; /** Distance between successive elements in an array of T. Includes ABI padding. */ + #[fast_ffi] pub unsafe fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Returns the preferred alignment of a type. */ + #[fast_ffi] pub unsafe fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Returns the minimum alignment of a type. */ + #[fast_ffi] pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** * Returns the minimum alignment of a type when part of a call frame. */ + #[fast_ffi] pub unsafe fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint; /** Disposes target data. */ + #[fast_ffi] pub unsafe fn LLVMDisposeTargetData(TD: TargetDataRef); /** Creates a pass manager. */ + #[fast_ffi] pub unsafe fn LLVMCreatePassManager() -> PassManagerRef; /** Disposes a pass manager. */ + #[fast_ffi] pub unsafe fn LLVMDisposePassManager(PM: PassManagerRef); /** Runs a pass manager on a module. */ + #[fast_ffi] pub unsafe fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; /** Adds a verification pass. */ + #[fast_ffi] pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddIPSCCPPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddInstructionCombiningPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddCFGSimplificationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddFunctionInliningPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddFunctionAttrsPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddJumpThreadingPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddConstantPropagationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddReassociatePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopRotatePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLICMPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopUnswitchPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopDeletionPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopUnrollPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGVNPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddMemCpyOptPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddSCCPPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddConstantMergePass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddArgumentPromotionPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddTailCallEliminationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddAggressiveDCEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddGlobalDCEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddPruneEHPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddLoopIdiomPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddEarlyCSEPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef; + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetOptLevel( PMB: PassManagerBuilderRef, OptimizationLevel: c_uint); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetSizeLevel( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableUnitAtATime( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableUnrollLoops( PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls (PMB: PassManagerBuilderRef, Value: Bool); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderUseInlinerWithThreshold (PMB: PassManagerBuilderRef, threshold: c_uint); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderPopulateModulePassManager (PMB: PassManagerBuilderRef, PM: PassManagerRef); + #[fast_ffi] pub unsafe fn LLVMPassManagerBuilderPopulateFunctionPassManager (PMB: PassManagerBuilderRef, PM: PassManagerRef); /** Destroys a memory buffer. */ + #[fast_ffi] pub unsafe fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef); /* Stuff that's in rustllvm/ because it's not upstream yet. */ /** Opens an object file. */ + #[fast_ffi] pub unsafe fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef; /** Closes an object file. */ + #[fast_ffi] pub unsafe fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef); /** Enumerates the sections in an object file. */ + #[fast_ffi] pub unsafe fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef; /** Destroys a section iterator. */ + #[fast_ffi] pub unsafe fn LLVMDisposeSectionIterator(SI: SectionIteratorRef); /** Returns true if the section iterator is at the end of the section list: */ + #[fast_ffi] pub unsafe fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool; /** Moves the section iterator to point to the next section. */ + #[fast_ffi] pub unsafe fn LLVMMoveToNextSection(SI: SectionIteratorRef); /** Returns the current section name. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char; /** Returns the current section size. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; /** Returns the current section contents as a string buffer. */ + #[fast_ffi] pub unsafe fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *c_char; /** Reads the given file and returns it as a memory buffer. Use LLVMDisposeMemoryBuffer() to get rid of it. */ + #[fast_ffi] pub unsafe fn LLVMRustCreateMemoryBufferWithContentsOfFile( Path: *c_char) -> MemoryBufferRef; + #[fast_ffi] pub unsafe fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef, Triple: *c_char, @@ -1387,17 +1809,21 @@ pub mod llvm { /** Returns a string describing the last error caused by an LLVMRust* call. */ + #[fast_ffi] pub unsafe fn LLVMRustGetLastError() -> *c_char; /** Prepare the JIT. Returns a memory manager that can load crates. */ + #[fast_ffi] pub unsafe fn LLVMRustPrepareJIT(__morestack: *()) -> *(); /** Load a crate into the memory manager. */ + #[fast_ffi] pub unsafe fn LLVMRustLoadCrate(MM: *(), Filename: *c_char) -> bool; /** Execute the JIT engine. */ + #[fast_ffi] pub unsafe fn LLVMRustExecuteJIT(MM: *(), PM: PassManagerRef, M: ModuleRef, @@ -1405,40 +1831,50 @@ pub mod llvm { EnableSegmentedStacks: bool) -> *(); /** Parses the bitcode in the given memory buffer. */ + #[fast_ffi] pub unsafe fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef; /** Parses LLVM asm in the given file */ + #[fast_ffi] pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char) -> ModuleRef; + #[fast_ffi] pub unsafe fn LLVMRustAddPrintModulePass(PM: PassManagerRef, M: ModuleRef, Output: *c_char); /** Turn on LLVM pass-timing. */ + #[fast_ffi] pub unsafe fn LLVMRustEnableTimePasses(); /// Print the pass timings since static dtors aren't picking them up. + #[fast_ffi] pub unsafe fn LLVMRustPrintPassTimings(); + #[fast_ffi] pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef; + #[fast_ffi] pub unsafe fn LLVMStructSetBody(StructTy: TypeRef, ElementTypes: *TypeRef, ElementCount: c_uint, Packed: Bool); + #[fast_ffi] pub unsafe fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef, Count: c_uint) -> ValueRef; /** Enables LLVM debug output. */ + #[fast_ffi] pub unsafe fn LLVMSetDebug(Enabled: c_int); /** Prepares inline assembly. */ + #[fast_ffi] pub unsafe fn LLVMInlineAsm(Ty: TypeRef, AsmString: *c_char, Constraints: *c_char, SideEffects: Bool, AlignStack: Bool, Dialect: c_uint) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index f9a3c0fab724a..a67be995171ff 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1336,17 +1336,7 @@ fn roundtrip(in_item: Option<@ast::item>) { let ebml_doc = reader::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); - let exp_str = do io::with_str_writer |w| { - in_item.encode(&prettyprint::Serializer(w)) - }; - let out_str = do io::with_str_writer |w| { - out_item.encode(&prettyprint::Serializer(w)) - }; - - debug!("expected string: %s", exp_str); - debug!("actual string : %s", out_str); - - assert!(exp_str == out_str); + assert_eq!(in_item, out_item); } #[test] diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index cd6b23aadadd5..46813974af166 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -399,24 +399,24 @@ pub fn set_optimize_for_size(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, lib::llvm::OptimizeForSizeAttribute - as c_ulonglong, - 0u as c_ulonglong); + as c_uint, + 0); } } pub fn set_no_inline(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::NoInlineAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::NoInlineAttribute as c_uint, + 0); } } pub fn set_no_unwind(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::NoUnwindAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::NoUnwindAttribute as c_uint, + 0); } } @@ -425,15 +425,16 @@ pub fn set_no_unwind(f: ValueRef) { pub fn set_uwtable(f: ValueRef) { unsafe { llvm::LLVMAddFunctionAttr(f, - lib::llvm::UWTableAttribute as c_ulonglong, - 0u as c_ulonglong); + lib::llvm::UWTableAttribute as c_uint, + 0); } } pub fn set_inline_hint(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute - as c_ulonglong, 0u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, + lib::llvm::InlineHintAttribute as c_uint, + 0); } } @@ -449,14 +450,15 @@ pub fn set_inline_hint_if_appr(attrs: &[ast::attribute], pub fn set_always_inline(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute - as c_ulonglong, 0u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, + lib::llvm::AlwaysInlineAttribute as c_uint, + 0); } } -pub fn set_custom_stack_growth_fn(f: ValueRef) { +pub fn set_fixed_stack_segment(f: ValueRef) { unsafe { - llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong); + llvm::LLVMAddFunctionAttr(f, 0, 1 << (39 - 32)); } } @@ -1774,6 +1776,7 @@ pub fn trans_closure(ccx: @CrateContext, param_substs: Option<@param_substs>, id: ast::node_id, impl_id: Option, + attributes: &[ast::attribute], maybe_load_env: &fn(fn_ctxt), finish: &fn(block)) { ccx.stats.n_closures += 1; @@ -1784,10 +1787,20 @@ pub fn trans_closure(ccx: @CrateContext, param_substs.repr(ccx.tcx)); // Set up arguments to the function. - let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs, - Some(body.span)); - let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, - decl.inputs); + let fcx = new_fn_ctxt_w_id(ccx, + path, + llfndecl, + id, + impl_id, + param_substs, + Some(body.span)); + let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs); + + // Set the fixed stack segment flag if necessary. + if attr::attrs_contains_name(attributes, "fixed_stack_segment") { + set_no_inline(fcx.llfn); + set_fixed_stack_segment(fcx.llfn); + } // Set GC for function. if ccx.sess.opts.gc { @@ -1840,7 +1853,8 @@ pub fn trans_fn(ccx: @CrateContext, ty_self: self_arg, param_substs: Option<@param_substs>, id: ast::node_id, - impl_id: Option) { + impl_id: Option, + attrs: &[ast::attribute]) { let do_time = ccx.sess.trans_stats(); let start = if do_time { time::get_time() } else { time::Timespec::new(0, 0) }; @@ -1850,8 +1864,16 @@ pub fn trans_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; let the_path_str = path_str(ccx.sess, path); - trans_closure(ccx, path, decl, body, llfndecl, ty_self, - param_substs, id, impl_id, + trans_closure(ccx, + path, + decl, + body, + llfndecl, + ty_self, + param_substs, + id, + impl_id, + attrs, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -2023,8 +2045,16 @@ pub fn trans_struct_dtor(ccx: @CrateContext, } /* Translate the dtor body */ let decl = ast_util::dtor_dec(); - trans_fn(ccx, path, &decl, body, lldecl, - impl_self(class_ty), psubsts, dtor_id, None); + trans_fn(ccx, + path, + &decl, + body, + lldecl, + impl_self(class_ty), + psubsts, + dtor_id, + None, + []); lldecl } @@ -2073,7 +2103,14 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), - decl, body, llfndecl, no_self, None, item.id, None); + decl, + body, + llfndecl, + no_self, + None, + item.id, + None, + item.attrs); } else { for body.node.stmts.each |stmt| { match stmt.node { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 0ef9d4af60487..380a512d17b23 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -416,9 +416,16 @@ pub fn trans_expr_fn(bcx: block, None => None}; let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil, ret_handle); - trans_closure(ccx, sub_path, decl, - body, llfn, no_self, - /*bad*/ copy bcx.fcx.param_substs, user_id, None, + trans_closure(ccx, + sub_path, + decl, + body, + llfn, + no_self, + /*bad*/ copy bcx.fcx.param_substs, + user_id, + None, + [], |fcx| load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), sigil), |bcx| { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 1037a4c071041..8c308bfa8894b 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -316,11 +316,11 @@ pub fn trans_foreign_mod(ccx: @CrateContext, { let llwrapfn = get_item_val(ccx, id); let tys = shim_types(ccx, id); - if attr::attrs_contains_name( - foreign_item.attrs, "rust_stack") - { + if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") { build_direct_fn(ccx, llwrapfn, foreign_item, &tys, cc); + } else if attr::attrs_contains_name(foreign_item.attrs, "fast_ffi") { + build_fast_ffi_fn(ccx, llwrapfn, foreign_item, &tys, cc); } else { let llshimfn = build_shim_fn(ccx, foreign_item, &tys, cc); @@ -380,16 +380,47 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_direct_fn(ccx: @CrateContext, decl: ValueRef, item: @ast::foreign_item, tys: &ShimTypes, cc: lib::llvm::CallConv) { + debug!("build_direct_fn(%s)", *link_name(ccx, item)); + + let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); + let ty = ty::lookup_item_type(ccx.tcx, + ast_util::local_def(item.id)).ty; + let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { + get_param(decl, i + first_real_arg) + }); + let retval = Call(bcx, llbasefn, args); + let ret_ty = ty::ty_fn_ret(ty); + if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { + Store(bcx, retval, fcx.llretptr); + } + build_return(bcx); + finish_fn(fcx, lltop); + } + + // FIXME (#2535): this is very shaky and probably gets ABIs wrong all + // over the place + fn build_fast_ffi_fn(ccx: @CrateContext, + decl: ValueRef, + item: @ast::foreign_item, + tys: &ShimTypes, + cc: lib::llvm::CallConv) { + debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); + let fcx = new_fn_ctxt(ccx, ~[], decl, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); + set_no_inline(fcx.llfn); + set_fixed_stack_segment(fcx.llfn); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { get_param(decl, i + first_real_arg) }); let retval = Call(bcx, llbasefn, args); - if !ty::type_is_nil(ty::ty_fn_ret(ty)) { + let ret_ty = ty::ty_fn_ret(ty); + if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr); } build_return(bcx); @@ -1006,7 +1037,16 @@ pub fn trans_foreign_fn(ccx: @CrateContext, ))); let llty = type_of_fn_from_ty(ccx, t); let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty); - trans_fn(ccx, path, decl, body, llfndecl, no_self, None, id, None); + trans_fn(ccx, + path, + decl, + body, + llfndecl, + no_self, + None, + id, + None, + []); return llfndecl; } diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 15c2e8e3d9350..3f2fb95513a39 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -116,7 +116,8 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, self_kind, None, mth.id, - Some(impl_did)); + Some(impl_did), + []); } local_def(mth.id) } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index c518605faf13a..d3a15cbbfe150 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -137,7 +137,8 @@ pub fn trans_method(ccx: @CrateContext, self_arg, param_substs, method.id, - Some(impl_id)); + Some(impl_id), + []); } pub fn trans_self_arg(bcx: block, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index c6ade350e0bba..a6930b339ae72 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -195,7 +195,16 @@ pub fn monomorphic_fn(ccx: @CrateContext, }, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(/*bad*/copy i.attrs, d); - trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); + trans_fn(ccx, + pt, + decl, + body, + d, + no_self, + psubsts, + fn_id.node, + None, + []); d } ast_map::node_item(*) => { diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 63dc1c9833e21..021811ffa7624 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -457,8 +457,9 @@ rust_task::get_next_stack_size(size_t min, size_t current, size_t requested) { "min: %" PRIdPTR " current: %" PRIdPTR " requested: %" PRIdPTR, min, current, requested); - // Allocate at least enough to accomodate the next frame - size_t sz = std::max(min, requested); + // Allocate at least enough to accomodate the next frame, plus a little + // slack to avoid thrashing + size_t sz = std::max(min, requested + (requested / 2)); // And double the stack size each allocation const size_t max = 1024 * 1024; diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 9f39e1433fc63..e524e6de859c8 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -191,6 +191,14 @@ rust_upcall_malloc(type_desc *td, uintptr_t size) { return upcall_malloc(td, size); } +extern "C" CDECL uintptr_t +rust_upcall_malloc_noswitch(type_desc *td, uintptr_t size) { + rust_task *task = rust_get_current_task(); + s_malloc_args args = {task, 0, td, size}; + upcall_s_malloc(&args); + return args.retval; +} + /********************************************************************** * Called whenever an object in the task-local heap is freed. */ @@ -231,6 +239,13 @@ rust_upcall_free(void* ptr) { upcall_free(ptr); } +extern "C" CDECL void +rust_upcall_free_noswitch(void* ptr) { + rust_task *task = rust_get_current_task(); + s_free_args args = {task,ptr}; + upcall_s_free(&args); +} + /**********************************************************************/ extern "C" _Unwind_Reason_Code diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index f63e3f53a7caf..4a79b2e4ae643 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -66,7 +66,9 @@ upcall_del_stack upcall_reset_stack_limit rust_upcall_fail rust_upcall_free +rust_upcall_free_noswitch rust_upcall_malloc +rust_upcall_malloc_noswitch rust_uv_loop_new rust_uv_loop_delete rust_uv_walk diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 5d422b2d2edc3..1612fec402974 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -451,6 +451,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, TargetOptions Options; Options.NoFramePointerElim = true; Options.EnableSegmentedStacks = EnableSegmentedStacks; + Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big. PassManager *PM = unwrap(PMR); diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 372f8ab4bc8f7..bfc15acaa763c 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -25,20 +25,6 @@ use std::ebml; use std::serialize::{Decodable, Encodable}; use std::time; -<<<<<<< HEAD -======= -fn test_prettyprint>( - a: &A, - expected: &~str -) { - let s = do io::with_str_writer |w| { - a.encode(&prettyprint::Serializer(w)) - }; - debug!("s == %?", s); - assert!(s == *expected); -} - ->>>>>>> librustc: Remove `fail_unless!` fn test_ebml + From af42d37547c15732a7c9d358c0a14967aef75e96 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 1 Apr 2013 13:55:49 -0700 Subject: [PATCH 281/403] rustllvm: Fix RustWrapper.cpp --- src/rustllvm/RustWrapper.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 1612fec402974..7c22cc6cc2538 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -15,6 +15,8 @@ // //===----------------------------------------------------------------------=== +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Linker.h" #include "llvm/PassManager.h" #include "llvm/IR/InlineAsm.h" @@ -152,7 +154,9 @@ class RustMCJITMemoryManager : public JITMemoryManager { unsigned SectionID); virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, bool isReadOnly); + + virtual bool applyPermissions(std::string *Str); virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); @@ -240,8 +244,9 @@ bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { } uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { + unsigned Alignment, + unsigned SectionID, + bool isReadOnly) { if (!Alignment) Alignment = 16; uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment); @@ -249,9 +254,14 @@ uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size, return Addr; } +bool RustMCJITMemoryManager::applyPermissions(std::string *Str) { + // Empty. + return true; +} + uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID) { + unsigned Alignment, + unsigned SectionID) { if (!Alignment) Alignment = 16; unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1); @@ -485,13 +495,12 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, } extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) { - SMDiagnostic d; Module *m = ParseAssemblyFile(Filename, d, getGlobalContext()); if (m) { return wrap(m); } else { - LLVMRustError = d.getMessage().data(); + LLVMRustError = d.getMessage().str().c_str(); return NULL; } } From 3ffaaab9e9e3a2437fd9ed5b04cf3ba3695cc2d2 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 1 Apr 2013 15:33:21 -0700 Subject: [PATCH 282/403] librustc: Switch the `@`s in types with `~` --- src/librustc/middle/ty.rs | 18 ++++++++++++------ src/test/bench/core-map.rs | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 4212b03c41653..ef0b2070a0e09 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -232,7 +232,7 @@ pub type ctxt = @ctxt_; struct ctxt_ { diag: @syntax::diagnostic::span_handler, - interner: @mut HashMap, + interner: @mut HashMap, next_id: @mut uint, vecs_implicitly_copyable: bool, legacy_modes: bool, @@ -320,7 +320,7 @@ enum tbox_flag { needs_subst = 1 | 2 | 8 } -type t_box = @t_box_; +type t_box = &'static t_box_; struct t_box_ { sty: sty, @@ -903,7 +903,7 @@ fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) } fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id }; match cx.interner.find(&key) { - Some(&t) => unsafe { return cast::reinterpret_cast(&t); }, + Some(t) => unsafe { return cast::transmute(&t.sty); }, _ => () } @@ -973,21 +973,27 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { } } - let t = @t_box_ { + let t = ~t_box_ { sty: st, id: *cx.next_id, flags: flags, o_def_id: o_def_id }; + + let sty_ptr = to_unsafe_ptr(&t.sty); + let key = intern_key { - sty: to_unsafe_ptr(&t.sty), + sty: sty_ptr, o_def_id: o_def_id }; cx.interner.insert(key, t); *cx.next_id += 1; - unsafe { cast::reinterpret_cast(&t) } + + unsafe { + cast::transmute::<*sty, t>(sty_ptr) + } } pub fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) } diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 8a8962fb9d637..b75aa3c909b96 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -88,6 +88,7 @@ fn vector>(map: &mut M, n_keys: uint, dist: &[uint]) { } } +#[fixed_stack_segment] fn main() { let args = os::args(); let n_keys = { From 04df19c5ca78d94e01dacbfb99471509128c6f8a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 2 Apr 2013 11:47:23 -0700 Subject: [PATCH 283/403] librustc: Take primitive types out of the type hash table. --- src/librustc/middle/ty.rs | 158 ++++++++++++++++++++++++++++++++------ 1 file changed, 133 insertions(+), 25 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ef0b2070a0e09..72c2cfedd986e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -307,7 +307,7 @@ struct ctxt_ { used_unsafe: @mut HashSet, } -enum tbox_flag { +pub enum tbox_flag { has_params = 1, has_self = 2, needs_infer = 4, @@ -320,9 +320,9 @@ enum tbox_flag { needs_subst = 1 | 2 | 8 } -type t_box = &'static t_box_; +pub type t_box = &'static t_box_; -struct t_box_ { +pub struct t_box_ { sty: sty, id: uint, flags: uint, @@ -513,6 +513,57 @@ pub struct substs { tps: ~[t] } +mod primitives { + use super::{sty, t_box_}; + + use core::option::None; + use syntax::ast; + + macro_rules! def_prim_ty( + ($name:ident, $sty:expr, $id:expr) => ( + pub static $name: t_box_ = t_box_ { + sty: $sty, + id: $id, + flags: 0, + o_def_id: None, + }; + ) + ) + + def_prim_ty!(TY_NIL, super::ty_nil, 0) + def_prim_ty!(TY_BOOL, super::ty_bool, 1) + def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2) + def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3) + def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4) + def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5) + def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6) + def_prim_ty!(TY_I64, super::ty_int(ast::ty_i64), 7) + def_prim_ty!(TY_UINT, super::ty_uint(ast::ty_u), 8) + def_prim_ty!(TY_U8, super::ty_uint(ast::ty_u8), 9) + def_prim_ty!(TY_U16, super::ty_uint(ast::ty_u16), 10) + def_prim_ty!(TY_U32, super::ty_uint(ast::ty_u32), 11) + def_prim_ty!(TY_U64, super::ty_uint(ast::ty_u64), 12) + def_prim_ty!(TY_FLOAT, super::ty_float(ast::ty_f), 13) + def_prim_ty!(TY_F32, super::ty_float(ast::ty_f32), 14) + def_prim_ty!(TY_F64, super::ty_float(ast::ty_f64), 15) + + pub static TY_BOT: t_box_ = t_box_ { + sty: super::ty_bot, + id: 16, + flags: super::has_ty_bot as uint, + o_def_id: None, + }; + + pub static TY_ERR: t_box_ = t_box_ { + sty: super::ty_err, + id: 17, + flags: super::has_ty_err as uint, + o_def_id: None, + }; + + pub static LAST_PRIMITIVE_ID: uint = 18; +} + // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. #[deriving(Eq)] @@ -852,7 +903,7 @@ pub fn mk_ctxt(s: session::Session, @ctxt_ { diag: s.diagnostic(), interner: @mut HashMap::new(), - next_id: @mut 0, + next_id: @mut primitives::LAST_PRIMITIVE_ID, vecs_implicitly_copyable: vecs_implicitly_copyable, legacy_modes: legacy_modes, cstore: s.cstore, @@ -901,6 +952,17 @@ fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) } // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for t above). fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { + // Check for primitive types. + match st { + ty_nil => return mk_nil(cx), + ty_err => return mk_err(cx), + ty_bool => return mk_bool(cx), + ty_int(i) => return mk_mach_int(cx, i), + ty_uint(u) => return mk_mach_uint(cx, u), + ty_float(f) => return mk_mach_float(cx, f), + _ => {} + }; + let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id }; match cx.interner.find(&key) { Some(t) => unsafe { return cast::transmute(&t.sty); }, @@ -996,49 +1058,95 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { } } -pub fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) } +#[inline(always)] +pub fn mk_prim_t(cx: ctxt, primitive: &'static t_box_) -> t { + unsafe { + cast::transmute::<&'static t_box_, t>(primitive) + } +} + +#[inline(always)] +pub fn mk_nil(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_NIL) } -pub fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) } +#[inline(always)] +pub fn mk_err(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_ERR) } -pub fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) } +#[inline(always)] +pub fn mk_bot(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOT) } -pub fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) } +#[inline(always)] +pub fn mk_bool(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOOL) } -pub fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) } +#[inline(always)] +pub fn mk_int(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_INT) } -pub fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) } +#[inline(always)] +pub fn mk_i8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I8) } -pub fn mk_i16(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i16)) } +#[inline(always)] +pub fn mk_i16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I16) } -pub fn mk_i32(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i32)) } +#[inline(always)] +pub fn mk_i32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I32) } -pub fn mk_i64(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i64)) } +#[inline(always)] +pub fn mk_i64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I64) } -pub fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) } +#[inline(always)] +pub fn mk_float(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_FLOAT) } -pub fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) } +#[inline(always)] +pub fn mk_f32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F32) } -pub fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) } +#[inline(always)] +pub fn mk_f64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F64) } -pub fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) } +#[inline(always)] +pub fn mk_uint(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_UINT) } -pub fn mk_u32(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u32)) } +#[inline(always)] +pub fn mk_u8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U8) } -pub fn mk_u64(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u64)) } +#[inline(always)] +pub fn mk_u16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U16) } -pub fn mk_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) } +#[inline(always)] +pub fn mk_u32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U32) } -pub fn mk_f64(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f64)) } +#[inline(always)] +pub fn mk_u64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U64) } -pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) } +pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { + match tm { + ast::ty_i => mk_int(cx), + ast::ty_char => mk_char(cx), + ast::ty_i8 => mk_i8(cx), + ast::ty_i16 => mk_i16(cx), + ast::ty_i32 => mk_i32(cx), + ast::ty_i64 => mk_i64(cx), + } +} -pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) } +pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { + match tm { + ast::ty_u => mk_uint(cx), + ast::ty_u8 => mk_u8(cx), + ast::ty_u16 => mk_u16(cx), + ast::ty_u32 => mk_u32(cx), + ast::ty_u64 => mk_u64(cx), + } +} pub fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t { - mk_t(cx, ty_float(tm)) + match tm { + ast::ty_f => mk_float(cx), + ast::ty_f32 => mk_f32(cx), + ast::ty_f64 => mk_f64(cx), + } } -pub fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) } +#[inline(always)] +pub fn mk_char(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_CHAR) } pub fn mk_estr(cx: ctxt, t: vstore) -> t { mk_t(cx, ty_estr(t)) From 53f54dda60a769fa6b3d325f5787134bc9d90c6b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 2 Apr 2013 13:41:18 -0700 Subject: [PATCH 284/403] librustc: Remove def_ids from types. --- src/librustc/metadata/decoder.rs | 7 +------ src/librustc/metadata/tydecode.rs | 4 ++-- src/librustc/metadata/tyencode.rs | 13 ------------- src/librustc/middle/ty.rs | 23 ++++------------------- src/librustc/middle/typeck/collect.rs | 11 +---------- 5 files changed, 8 insertions(+), 50 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 472b455b73531..5b19834b31c0b 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -249,12 +249,7 @@ fn doc_transformed_self_ty(doc: ebml::Doc, pub fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { - let t = doc_type(item, tcx, cdata); - if family_names_type(item_family(item)) { - ty::mk_with_id(tcx, t, item_id) - } else { - t - } + doc_type(item, tcx, cdata) } fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 41ebf14a9a8bc..709f1d4fc35d7 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -381,9 +381,9 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } } '"' => { - let def = parse_def(st, TypeWithId, conv); + let _ = parse_def(st, TypeWithId, conv); let inner = parse_ty(st, conv); - ty::mk_with_id(st.tcx, inner, def) + inner } 'B' => ty::mk_opaque_box(st.tcx), 'a' => { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index a9a07d1b41d9d..f6338f83ca611 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -78,19 +78,6 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) { Some(a) => { w.write_str(*a.s); return; } None => { let pos = w.tell(); - match ty::type_def_id(t) { - Some(def_id) => { - // Do not emit node ids that map to unexported names. Those - // are not helpful. - if def_id.crate != local_crate || - (cx.reachable)(def_id.node) { - w.write_char('"'); - w.write_str((cx.ds)(def_id)); - w.write_char('|'); - } - } - _ => {} - } enc_sty(w, cx, /*bad*/copy ty::get(t).sty); let end = w.tell(); let len = end - pos; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 72c2cfedd986e..ff41f6f5ae125 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -133,7 +133,6 @@ impl to_bytes::IterBytes for creader_cache_key { struct intern_key { sty: *sty, - o_def_id: Option } // NB: Do not replace this with #[deriving(Eq)]. The automatically-derived @@ -142,7 +141,7 @@ struct intern_key { impl cmp::Eq for intern_key { fn eq(&self, other: &intern_key) -> bool { unsafe { - *self.sty == *other.sty && self.o_def_id == other.o_def_id + *self.sty == *other.sty } } fn ne(&self, other: &intern_key) -> bool { @@ -153,7 +152,7 @@ impl cmp::Eq for intern_key { impl to_bytes::IterBytes for intern_key { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { unsafe { - to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f); + (*self.sty).iter_bytes(lsb0, f); } } } @@ -326,7 +325,6 @@ pub struct t_box_ { sty: sty, id: uint, flags: uint, - o_def_id: Option } // To reduce refcounting cost, we're representing types as unsafe pointers @@ -359,7 +357,6 @@ pub fn type_needs_infer(t: t) -> bool { pub fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) } -pub fn type_def_id(t: t) -> Option { get(t).o_def_id } pub fn type_id(t: t) -> uint { get(t).id } #[deriving(Eq)] @@ -516,7 +513,6 @@ pub struct substs { mod primitives { use super::{sty, t_box_}; - use core::option::None; use syntax::ast; macro_rules! def_prim_ty( @@ -525,7 +521,6 @@ mod primitives { sty: $sty, id: $id, flags: 0, - o_def_id: None, }; ) ) @@ -551,14 +546,12 @@ mod primitives { sty: super::ty_bot, id: 16, flags: super::has_ty_bot as uint, - o_def_id: None, }; pub static TY_ERR: t_box_ = t_box_ { sty: super::ty_err, id: 17, flags: super::has_ty_err as uint, - o_def_id: None, }; pub static LAST_PRIMITIVE_ID: uint = 18; @@ -945,13 +938,11 @@ pub fn mk_ctxt(s: session::Session, } } - // Type constructors -fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) } // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for t above). -fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { +fn mk_t(cx: ctxt, +st: sty) -> t { // Check for primitive types. match st { ty_nil => return mk_nil(cx), @@ -963,7 +954,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { _ => {} }; - let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id }; + let key = intern_key { sty: to_unsafe_ptr(&st) }; match cx.interner.find(&key) { Some(t) => unsafe { return cast::transmute(&t.sty); }, _ => () @@ -1039,14 +1030,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { sty: st, id: *cx.next_id, flags: flags, - o_def_id: o_def_id }; let sty_ptr = to_unsafe_ptr(&t.sty); let key = intern_key { sty: sty_ptr, - o_def_id: o_def_id }; cx.interner.insert(key, t); @@ -1263,10 +1252,6 @@ pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t { pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } -pub fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t { - mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id)) -} - // Converts s to its machine type equivalent pub fn mach_sty(cfg: @session::config, t: t) -> sty { match get(t).sty { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 59ea8ea039e1f..36b4626731626 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1085,16 +1085,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) let region_parameterization = RegionParameterization::from_variance_and_generics(rp, generics); let tpt = { - let ty = { - let t0 = ccx.to_ty(&type_rscope(region_parameterization), t); - // Do not associate a def id with a named, parameterized type - // like "foo". This is because otherwise ty_to_str will - // print the name as merely "foo", as it has no way to - // reconstruct the value of X. - if generics.is_parameterized() { t0 } else { - ty::mk_with_id(tcx, t0, def_id) - } - }; + let ty = ccx.to_ty(&type_rscope(region_parameterization), t); ty_param_bounds_and_ty { generics: ty_generics(ccx, rp, generics, 0), ty: ty From 4c29b4cb93ee090a22d27faf4e700bfc2364ebc5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 2 Apr 2013 16:20:02 -0700 Subject: [PATCH 285/403] librustc: Optimize metadata::decoder::item_name. --- src/libcore/str.rs | 9 +++++++++ src/librustc/metadata/decoder.rs | 10 ++++++++-- src/libsyntax/parse/token.rs | 22 ++++++++++++++++++++++ src/libsyntax/util/interner.rs | 9 +++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index cb362b2e6c09c..6bde7d33849e6 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -67,6 +67,15 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str { return unsafe { raw::from_bytes_with_null(vv) }; } +pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { + unsafe { + assert!(is_utf8(vector)); + let (ptr, len): (*u8, uint) = ::cast::transmute(vector); + let string: &'a str = ::cast::transmute((ptr, len + 1)); + string + } +} + /// Copy a slice into a new unique str pub fn from_slice(s: &str) -> ~str { unsafe { raw::slice_bytes_owned(s, 0, len(s)) } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 5b19834b31c0b..248d847f89dae 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -37,7 +37,7 @@ use std::serialize::Decodable; use syntax::ast_map; use syntax::attr; use syntax::diagnostic::span_handler; -use syntax::parse::token::{ident_interner, special_idents}; +use syntax::parse::token::{StringRef, ident_interner, special_idents}; use syntax::print::pprust; use syntax::{ast, ast_util}; use syntax::codemap; @@ -322,7 +322,13 @@ fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { let name = reader::get_doc(item, tag_paths_data_name); - intr.intern(@str::from_bytes(reader::doc_data(name))) + do reader::with_doc_data(name) |data| { + let string = str::from_bytes_slice(data); + match intr.find_equiv(&StringRef(string)) { + None => intr.intern(@(string.to_owned())), + Some(val) => val, + } + } } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index cf05a4375a8a5..b94b53076ec55 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,9 +18,11 @@ use util::interner; use core::cast; use core::char; +use core::cmp::Equiv; use core::hashmap::HashSet; use core::str; use core::task; +use core::to_bytes; #[auto_encode] #[auto_decode] @@ -355,6 +357,19 @@ pub mod special_idents { pub static type_self: ident = ident { repr: 36u, ctxt: 0}; // `Self` } +pub struct StringRef<'self>(&'self str); + +impl<'self> Equiv<@~str> for StringRef<'self> { + #[inline(always)] + fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) } +} + +impl<'self> to_bytes::IterBytes for StringRef<'self> { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { + (**self).iter_bytes(lsb0, f); + } +} + pub struct ident_interner { priv interner: Interner<@~str>, } @@ -372,6 +387,13 @@ pub impl ident_interner { fn len(&self) -> uint { self.interner.len() } + fn find_equiv>(&self, val: &Q) + -> Option { + match self.interner.find_equiv(val) { + Some(v) => Some(ast::ident { repr: v }), + None => None, + } + } } pub fn mk_ident_interner() -> @ident_interner { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 75bcac1b16306..cda1c6c0df385 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -16,6 +16,7 @@ #[macro_escape]; use core::prelude::*; +use core::cmp::Equiv; use core::hashmap::HashMap; pub struct Interner { @@ -67,6 +68,14 @@ pub impl Interner { fn get(&self, idx: uint) -> T { self.vect[idx] } fn len(&self) -> uint { let vect = &*self.vect; vect.len() } + + fn find_equiv>(&self, val: &Q) + -> Option { + match self.map.find_equiv(val) { + Some(v) => Some(*v), + None => None, + } + } } /* Key for thread-local data for sneaking interner information to the From 2dbe20a5610c3244feab0db5ab20ff062dc91085 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 3 Apr 2013 11:50:43 -0700 Subject: [PATCH 286/403] libstd: Micro-optimize vuint_at --- src/libstd/ebml.rs | 57 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 4a3447700bc8f..7b479bc7578bd 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -59,10 +59,13 @@ pub mod reader { use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc}; use serialize; + use core::cast::transmute; use core::int; use core::io; use core::prelude::*; + use core::ptr::offset; use core::str; + use core::unstable::intrinsics::bswap32; use core::vec; // ebml reading @@ -78,7 +81,8 @@ pub mod reader { next: uint } - fn vuint_at(data: &[u8], start: uint) -> Res { + #[inline(never)] + fn vuint_at_slow(data: &[u8], start: uint) -> Res { let a = data[start]; if a & 0x80u8 != 0u8 { return Res {val: (a & 0x7fu8) as uint, next: start + 1u}; @@ -87,18 +91,63 @@ pub mod reader { return Res {val: ((a & 0x3fu8) as uint) << 8u | (data[start + 1u] as uint), next: start + 2u}; - } else if a & 0x20u8 != 0u8 { + } + if a & 0x20u8 != 0u8 { return Res {val: ((a & 0x1fu8) as uint) << 16u | (data[start + 1u] as uint) << 8u | (data[start + 2u] as uint), next: start + 3u}; - } else if a & 0x10u8 != 0u8 { + } + if a & 0x10u8 != 0u8 { return Res {val: ((a & 0x0fu8) as uint) << 24u | (data[start + 1u] as uint) << 16u | (data[start + 2u] as uint) << 8u | (data[start + 3u] as uint), next: start + 4u}; - } else { error!("vint too big"); fail!(); } + } + fail!(~"vint too big"); + } + + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "x86_64")] + pub fn vuint_at(data: &[u8], start: uint) -> Res { + if data.len() - start < 4 { + return vuint_at_slow(data, start); + } + + unsafe { + let (ptr, _): (*u8, uint) = transmute(data); + let ptr = offset(ptr, start); + let ptr: *i32 = transmute(ptr); + let val = bswap32(*ptr); + let val: u32 = transmute(val); + if (val & 0x80000000) != 0 { + Res { + val: ((val >> 24) & 0x7f) as uint, + next: start + 1 + } + } else if (val & 0x40000000) != 0 { + Res { + val: ((val >> 16) & 0x3fff) as uint, + next: start + 2 + } + } else if (val & 0x20000000) != 0 { + Res { + val: ((val >> 8) & 0x1fffff) as uint, + next: start + 3 + } + } else { + Res { + val: (val & 0x0fffffff) as uint, + next: start + 4 + } + } + } + } + + #[cfg(target_arch = "arm")] + pub fn vuint_at(data: &[u8], start: uint) -> Res { + vuint_at_slow(data, start) } pub fn Doc(data: @~[u8]) -> Doc { From ca8e99fd78ab9b56c5bdc61027b032ad52c2ec8b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 5 Apr 2013 11:55:43 -0700 Subject: [PATCH 287/403] rt: Fix scalability problem with big stacks on 32 bit --- src/rt/rust_sched_loop.cpp | 18 +++++++++++ src/rt/rust_sched_loop.h | 32 +++++++++++++++++++ src/rt/rust_stack.cpp | 4 +++ src/rt/rust_stack.h | 4 +-- src/rt/rust_task.cpp | 65 ++++++++++++++++++++++++++++++++++++-- src/rt/rust_task.h | 14 ++++++++ 6 files changed, 131 insertions(+), 6 deletions(-) diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index 90393acdd59d6..dbcbd7b83cf23 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -29,6 +29,8 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) : should_exit(false), cached_c_stack(NULL), extra_c_stack(NULL), + cached_big_stack(NULL), + extra_big_stack(NULL), dead_task(NULL), killed(killed), pump_signal(NULL), @@ -263,6 +265,11 @@ rust_sched_loop::run_single_turn() { destroy_exchange_stack(kernel->region(), cached_c_stack); cached_c_stack = NULL; } + assert(!extra_big_stack); + if (cached_big_stack) { + destroy_exchange_stack(kernel->region(), cached_big_stack); + cached_big_stack = NULL; + } sched->release_task_thread(); return sched_loop_state_exit; @@ -392,6 +399,13 @@ rust_sched_loop::prepare_c_stack(rust_task *task) { cached_c_stack = create_exchange_stack(kernel->region(), C_STACK_SIZE); } + assert(!extra_big_stack); + if (!cached_big_stack) { + cached_big_stack = create_exchange_stack(kernel->region(), + C_STACK_SIZE + + (C_STACK_SIZE * 2)); + cached_big_stack->is_big = 1; + } } void @@ -400,6 +414,10 @@ rust_sched_loop::unprepare_c_stack() { destroy_exchange_stack(kernel->region(), extra_c_stack); extra_c_stack = NULL; } + if (extra_big_stack) { + destroy_exchange_stack(kernel->region(), extra_big_stack); + extra_big_stack = NULL; + } } // diff --git a/src/rt/rust_sched_loop.h b/src/rt/rust_sched_loop.h index 736c09ee920ca..a099c5e0c7495 100644 --- a/src/rt/rust_sched_loop.h +++ b/src/rt/rust_sched_loop.h @@ -67,6 +67,8 @@ struct rust_sched_loop stk_seg *cached_c_stack; stk_seg *extra_c_stack; + stk_seg *cached_big_stack; + stk_seg *extra_big_stack; rust_task_list running_tasks; rust_task_list blocked_tasks; @@ -147,6 +149,10 @@ struct rust_sched_loop stk_seg *borrow_c_stack(); void return_c_stack(stk_seg *stack); + // Called by tasks when they need a big stack + stk_seg *borrow_big_stack(); + void return_big_stack(stk_seg *stack); + int get_id() { return this->id; } }; @@ -202,6 +208,32 @@ rust_sched_loop::return_c_stack(stk_seg *stack) { } } +// NB: Runs on the Rust stack. Might return NULL! +inline stk_seg * +rust_sched_loop::borrow_big_stack() { + assert(cached_big_stack); + stk_seg *your_stack; + if (extra_big_stack) { + your_stack = extra_big_stack; + extra_big_stack = NULL; + } else { + your_stack = cached_big_stack; + cached_big_stack = NULL; + } + return your_stack; +} + +// NB: Runs on the Rust stack +inline void +rust_sched_loop::return_big_stack(stk_seg *stack) { + assert(!extra_big_stack); + assert(stack); + if (!cached_big_stack) + cached_big_stack = stack; + else + extra_big_stack = stack; +} + // this is needed to appease the circular dependency gods #include "rust_task.h" diff --git a/src/rt/rust_stack.cpp b/src/rt/rust_stack.cpp index 64ca256ff4611..f07690a955ea2 100644 --- a/src/rt/rust_stack.cpp +++ b/src/rt/rust_stack.cpp @@ -13,6 +13,8 @@ #include "vg/valgrind.h" #include "vg/memcheck.h" +#include + #ifdef _LP64 const uintptr_t canary_value = 0xABCDABCDABCDABCD; #else @@ -61,6 +63,7 @@ create_stack(memory_region *region, size_t sz) { stk_seg *stk = (stk_seg *)region->malloc(total_sz, "stack"); memset(stk, 0, sizeof(stk_seg)); stk->end = (uintptr_t) &stk->data[sz]; + stk->is_big = 0; add_stack_canary(stk); register_valgrind_stack(stk); return stk; @@ -78,6 +81,7 @@ create_exchange_stack(rust_exchange_alloc *exchange, size_t sz) { stk_seg *stk = (stk_seg *)exchange->malloc(total_sz); memset(stk, 0, sizeof(stk_seg)); stk->end = (uintptr_t) &stk->data[sz]; + stk->is_big = 0; add_stack_canary(stk); register_valgrind_stack(stk); return stk; diff --git a/src/rt/rust_stack.h b/src/rt/rust_stack.h index 51b884e47b1e7..3b34b91e309cf 100644 --- a/src/rt/rust_stack.h +++ b/src/rt/rust_stack.h @@ -22,9 +22,7 @@ struct stk_seg { stk_seg *next; uintptr_t end; unsigned int valgrind_id; -#ifndef _LP64 - uint32_t pad; -#endif + uint8_t is_big; rust_task *task; uintptr_t canary; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 021811ffa7624..6db138b418e51 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -53,7 +53,8 @@ rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state, disallow_yield(0), c_stack(NULL), next_c_sp(0), - next_rust_sp(0) + next_rust_sp(0), + big_stack(NULL) { LOGPTR(sched_loop, "new task", (uintptr_t)this); DLOG(sched_loop, task, "sizeof(task) = %d (0x%x)", @@ -556,13 +557,64 @@ rust_task::cleanup_after_turn() { // Delete any spare stack segments that were left // behind by calls to prev_stack assert(stk); + while (stk->next) { stk_seg *new_next = stk->next->next; - free_stack(stk->next); + + if (stk->next->is_big) { + assert (big_stack == stk->next); + sched_loop->return_big_stack(big_stack); + big_stack = NULL; + } else { + free_stack(stk->next); + } + stk->next = new_next; } } +// NB: Runs on the Rust stack. Returns true if we successfully allocated the big +// stack and false otherwise. +bool +rust_task::new_big_stack() { + // If we have a cached big stack segment, use it. + if (big_stack) { + // Check to see if we're already on the big stack. + stk_seg *ss = stk; + while (ss != NULL) { + if (ss == big_stack) + return false; + ss = ss->prev; + } + + // Unlink the big stack. + if (big_stack->next) + big_stack->next->prev = big_stack->prev; + if (big_stack->prev) + big_stack->prev->next = big_stack->next; + } else { + stk_seg *borrowed_big_stack = sched_loop->borrow_big_stack(); + if (!borrowed_big_stack) { + dump_stacks(); + abort(); + } else { + big_stack = borrowed_big_stack; + } + } + + big_stack->task = this; + big_stack->next = stk->next; + if (big_stack->next) + big_stack->next->prev = big_stack; + big_stack->prev = stk; + if (stk) + stk->next = big_stack; + + stk = big_stack; + + return true; +} + static bool sp_in_stk_seg(uintptr_t sp, stk_seg *stk) { // Not positive these bounds for sp are correct. I think that the first @@ -602,9 +654,16 @@ rust_task::delete_all_stacks() { assert(stk->next == NULL); while (stk != NULL) { stk_seg *prev = stk->prev; - free_stack(stk); + + if (stk->is_big) + sched_loop->return_big_stack(stk); + else + free_stack(stk); + stk = prev; } + + big_stack = NULL; } /* diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 00d20fefc0ee5..e8b3ef44ac09e 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -133,6 +133,9 @@ #define RZ_BSD_32 (1024*20) #define RZ_BSD_64 (1024*20) +// The threshold beyond which we switch to the C stack. +#define STACK_THRESHOLD (1024 * 1024) + #ifdef __linux__ #ifdef __i386__ #define RED_ZONE_SIZE RZ_LINUX_32 @@ -263,9 +266,13 @@ rust_task : public kernel_owned uintptr_t next_c_sp; uintptr_t next_rust_sp; + // The big stack. + stk_seg *big_stack; + // Called when the atomic refcount reaches zero void delete_this(); + bool new_big_stack(); void new_stack_fast(size_t requested_sz); void new_stack(size_t requested_sz); void free_stack(stk_seg *stk); @@ -284,6 +291,8 @@ rust_task : public kernel_owned char const *file, size_t line); + void dump_stacks(); + friend void task_start_wrapper(spawn_args *a); friend void cleanup_task(cleanup_args *a); friend void reset_stack_limit_on_c_stack(reset_args *a); @@ -568,6 +577,11 @@ rust_task::new_stack_fast(size_t requested_sz) { // The minimum stack size, in bytes, of a Rust stack, excluding red zone size_t min_sz = sched_loop->min_stack_size; + if (requested_sz > STACK_THRESHOLD) { + if (new_big_stack()) + return; + } + // Try to reuse an existing stack segment if (stk != NULL && stk->next != NULL) { size_t next_sz = user_stack_size(stk->next); From 0b0ca597bf25d13e4493c72843389cc9e47425b6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sun, 7 Apr 2013 16:09:12 -0700 Subject: [PATCH 288/403] librustc: Improve inlining behavior. --- src/librustc/middle/trans/closure.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 380a512d17b23..252a10f8a8bbc 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -409,6 +409,15 @@ pub fn trans_expr_fn(bcx: block, ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); + // Always mark inline if this is a loop body. This is important for + // performance on many programs with tight loops. + if is_loop_body.is_some() { + set_always_inline(llfn); + } else { + // Can't hurt. + set_inline_hint(llfn); + } + let Result {bcx: bcx, val: closure} = match sigil { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = *ccx.maps.capture_map.get(&user_id); From 90b65c88397b72deacb07d2b3963e959effe83ac Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 12 Apr 2013 12:06:47 -0700 Subject: [PATCH 289/403] llvm: Fixes for RustWrapper. --- src/rustllvm/RustWrapper.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 7c22cc6cc2538..141276e86f098 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -222,12 +222,6 @@ class RustMCJITMemoryManager : public JITMemoryManager { virtual void deallocateExceptionTable(void *ET) { llvm_unreachable("Unimplemented call"); } - virtual uint8_t* allocateDataSection(uintptr_t, unsigned int, unsigned int, bool) { - llvm_unreachable("Unimplemented call"); - } - virtual bool applyPermissions(std::string*) { - llvm_unreachable("Unimplemented call"); - } }; bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) { From 9738c2a45c03034f937a0b2ce7a690f64e7662eb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 16 Apr 2013 16:11:16 -0700 Subject: [PATCH 290/403] test: Rewrite nbody and spectralnorm shootout benchmarks --- src/libcore/core.rc | 1 + src/libcore/iter.rs | 4 + src/libcore/prelude.rs | 2 +- src/libcore/vec.rs | 41 ++- src/test/bench/shootout-nbody.rs | 362 +++++++++--------------- src/test/bench/shootout-spectralnorm.rs | 102 +++---- 6 files changed, 206 insertions(+), 306 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index e7a5cfbaf4b25..4080c70c8ae48 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -98,6 +98,7 @@ pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; pub use vec::{OwnedVector, OwnedCopyableVector}; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; +pub use iter::{ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use ptr::Ptr; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index a220cd520c32a..3dcca0e06c228 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -45,6 +45,10 @@ pub trait ExtendedIter { fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) -> ~[B]; } +pub trait ExtendedMutableIter { + fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool); +} + pub trait EqIter { fn contains(&self, x: &A) -> bool; fn count(&self, x: &A) -> uint; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index e148493ca4512..95481d032a446 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -33,7 +33,7 @@ pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; -pub use iter::Times; +pub use iter::{Times, ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use path::GenericPath; pub use path::Path; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index f6492ede9f9ca..3e0ba38a6e816 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1388,13 +1388,19 @@ pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) { /// to mutate the contents as you iterate. #[inline(always)] pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) { - let mut i = 0; - let n = v.len(); - while i < n { - if !f(&mut v[i]) { - return; + do vec::as_mut_buf(v) |p, n| { + let mut n = n; + let mut p = p; + while n > 0 { + unsafe { + let q: &'r mut T = cast::transmute_mut_region(&mut *p); + if !f(q) { + break; + } + p = p.offset(1); + } + n -= 1; } - i += 1; } } @@ -1426,6 +1432,22 @@ pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) { } } +/** + * Iterates over a mutable vector's elements and indices + * + * Return true to continue, false to break. + */ +#[inline(always)] +pub fn eachi_mut<'r,T>(v: &'r mut [T], f: &fn(uint, v: &'r mut T) -> bool) { + let mut i = 0; + for each_mut(v) |p| { + if !f(i, p) { + return; + } + i += 1; + } +} + /** * Iterates over a vector's elements in reverse * @@ -2654,6 +2676,13 @@ impl<'self,A> iter::ExtendedIter for &'self [A] { } } +impl<'self,A> iter::ExtendedMutableIter for &'self mut [A] { + #[inline(always)] + pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) { + eachi_mut(*self, blk) + } +} + // FIXME(#4148): This should be redundant impl iter::ExtendedIter for ~[A] { pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 97907025bd1a0..e633f307bc227 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -1,254 +1,150 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// based on: -// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java - -extern mod std; - -use core::os; - -// Using sqrt from the standard library is way slower than using libc -// directly even though std just calls libc, I guess it must be -// because the the indirection through another dynamic linker -// stub. Kind of shocking. Might be able to make it faster still with -// an llvm intrinsic. -mod libc { - #[nolink] - pub extern { - pub fn sqrt(n: float) -> float; - } -} - -fn main() { - let args = os::args(); - let args = if os::getenv(~"RUST_BENCH").is_some() { - ~[~"", ~"4000000"] - } else if args.len() <= 1u { - ~[~"", ~"100000"] - } else { - args - }; - let n = int::from_str(args[1]).get(); - let mut bodies: ~[Body::Props] = NBodySystem::make(); - io::println(fmt!("%f", NBodySystem::energy(bodies))); - let mut i = 0; - while i < n { - NBodySystem::advance(bodies, 0.01); - i += 1; - } - io::println(fmt!("%f", NBodySystem::energy(bodies))); +use core::from_str::FromStr; +use core::uint::range; +use core::unstable::intrinsics::sqrtf64; + +static PI: f64 = 3.141592653589793; +static SOLAR_MASS: f64 = 4.0 * PI * PI; +static YEAR: f64 = 365.24; +static N_BODIES: uint = 5; + +static BODIES: [Planet, ..N_BODIES] = [ + // Sun + Planet { + x: [ 0.0, 0.0, 0.0 ], + v: [ 0.0, 0.0, 0.0 ], + mass: SOLAR_MASS, + }, + // Jupiter + Planet { + x: [ + 4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01, + ], + v: [ + 1.66007664274403694e-03 * YEAR, + 7.69901118419740425e-03 * YEAR, + -6.90460016972063023e-05 * YEAR, + ], + mass: 9.54791938424326609e-04 * SOLAR_MASS, + }, + // Saturn + Planet { + x: [ + 8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01, + ], + v: [ + -2.76742510726862411e-03 * YEAR, + 4.99852801234917238e-03 * YEAR, + 2.30417297573763929e-05 * YEAR, + ], + mass: 2.85885980666130812e-04 * SOLAR_MASS, + }, + // Uranus + Planet { + x: [ + 1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01, + ], + v: [ + 2.96460137564761618e-03 * YEAR, + 2.37847173959480950e-03 * YEAR, + -2.96589568540237556e-05 * YEAR, + ], + mass: 4.36624404335156298e-05 * SOLAR_MASS, + }, + // Neptune + Planet { + x: [ + 1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01, + ], + v: [ + 2.68067772490389322e-03 * YEAR, + 1.62824170038242295e-03 * YEAR, + -9.51592254519715870e-05 * YEAR, + ], + mass: 5.15138902046611451e-05 * SOLAR_MASS, + }, +]; + +struct Planet { + x: [f64, ..3], + v: [f64, ..3], + mass: f64, } -pub mod NBodySystem { - use Body; - - pub fn make() -> ~[Body::Props] { - let mut bodies: ~[Body::Props] = - ~[Body::sun(), - Body::jupiter(), - Body::saturn(), - Body::uranus(), - Body::neptune()]; - - let mut px = 0.0; - let mut py = 0.0; - let mut pz = 0.0; - - let mut i = 0; - while i < 5 { - px += bodies[i].vx * bodies[i].mass; - py += bodies[i].vy * bodies[i].mass; - pz += bodies[i].vz * bodies[i].mass; - - i += 1; - } - - // side-effecting - Body::offset_momentum(&mut bodies[0], px, py, pz); - - return bodies; - } - - pub fn advance(bodies: &mut [Body::Props], dt: float) { - let mut i = 0; - while i < 5 { - let mut j = i + 1; - while j < 5 { - advance_one(&mut bodies[i], - &mut bodies[j], dt); - j += 1; +fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) { + let mut d = [ 0.0, ..3 ]; + for (steps as uint).times { + for range(0, N_BODIES) |i| { + for range(i + 1, N_BODIES) |j| { + d[0] = bodies[i].x[0] - bodies[j].x[0]; + d[1] = bodies[i].x[1] - bodies[j].x[1]; + d[2] = bodies[i].x[2] - bodies[j].x[2]; + + let d2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; + let mag = dt / (d2 * sqrtf64(d2)); + + let a_mass = bodies[i].mass, b_mass = bodies[j].mass; + bodies[i].v[0] -= d[0] * b_mass * mag; + bodies[i].v[1] -= d[1] * b_mass * mag; + bodies[i].v[2] -= d[2] * b_mass * mag; + + bodies[j].v[0] += d[0] * a_mass * mag; + bodies[j].v[1] += d[1] * a_mass * mag; + bodies[j].v[2] += d[2] * a_mass * mag; } - - i += 1; } - i = 0; - while i < 5 { - move_(&mut bodies[i], dt); - i += 1; + for vec::each_mut(*bodies) |a| { + a.x[0] += dt * a.v[0]; + a.x[1] += dt * a.v[1]; + a.x[2] += dt * a.v[2]; } } +} - pub fn advance_one(bi: &mut Body::Props, - bj: &mut Body::Props, - dt: float) { - unsafe { - let dx = bi.x - bj.x; - let dy = bi.y - bj.y; - let dz = bi.z - bj.z; - - let dSquared = dx * dx + dy * dy + dz * dz; - - let distance = ::libc::sqrt(dSquared); - let mag = dt / (dSquared * distance); - - bi.vx -= dx * bj.mass * mag; - bi.vy -= dy * bj.mass * mag; - bi.vz -= dz * bj.mass * mag; - - bj.vx += dx * bi.mass * mag; - bj.vy += dy * bi.mass * mag; - bj.vz += dz * bi.mass * mag; +fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 { + let mut e = 0.0; + let mut d = [ 0.0, ..3 ]; + for range(0, N_BODIES) |i| { + for range(0, 3) |k| { + e += bodies[i].mass * bodies[i].v[k] * bodies[i].v[k] / 2.0; } - } - - pub fn move_(b: &mut Body::Props, dt: float) { - b.x += dt * b.vx; - b.y += dt * b.vy; - b.z += dt * b.vz; - } - pub fn energy(bodies: &[Body::Props]) -> float { - unsafe { - let mut dx; - let mut dy; - let mut dz; - let mut distance; - let mut e = 0.0; - - let mut i = 0; - while i < 5 { - e += - 0.5 * bodies[i].mass * - (bodies[i].vx * bodies[i].vx - + bodies[i].vy * bodies[i].vy - + bodies[i].vz * bodies[i].vz); - - let mut j = i + 1; - while j < 5 { - dx = bodies[i].x - bodies[j].x; - dy = bodies[i].y - bodies[j].y; - dz = bodies[i].z - bodies[j].z; - - distance = ::libc::sqrt(dx * dx - + dy * dy - + dz * dz); - e -= bodies[i].mass - * bodies[j].mass / distance; - - j += 1; - } - - i += 1; + for range(i + 1, N_BODIES) |j| { + for range(0, 3) |k| { + d[k] = bodies[i].x[k] - bodies[j].x[k]; } - return e; + let dist = sqrtf64(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); + e -= bodies[i].mass * bodies[j].mass / dist; } } + e } -pub mod Body { - use Body; - - pub static PI: float = 3.141592653589793; - pub static SOLAR_MASS: float = 39.478417604357432; - // was 4 * PI * PI originally - pub static DAYS_PER_YEAR: float = 365.24; - - pub struct Props { - x: float, - y: float, - z: float, - vx: float, - vy: float, - vz: float, - mass: float - } - - pub fn jupiter() -> Body::Props { - return Props { - x: 4.84143144246472090e+00, - y: -1.16032004402742839e+00, - z: -1.03622044471123109e-01, - vx: 1.66007664274403694e-03 * DAYS_PER_YEAR, - vy: 7.69901118419740425e-03 * DAYS_PER_YEAR, - vz: -6.90460016972063023e-05 * DAYS_PER_YEAR, - mass: 9.54791938424326609e-04 * SOLAR_MASS - }; - } - - pub fn saturn() -> Body::Props { - return Props { - x: 8.34336671824457987e+00, - y: 4.12479856412430479e+00, - z: -4.03523417114321381e-01, - vx: -2.76742510726862411e-03 * DAYS_PER_YEAR, - vy: 4.99852801234917238e-03 * DAYS_PER_YEAR, - vz: 2.30417297573763929e-05 * DAYS_PER_YEAR, - mass: 2.85885980666130812e-04 * SOLAR_MASS - }; - } - - pub fn uranus() -> Body::Props { - return Props { - x: 1.28943695621391310e+01, - y: -1.51111514016986312e+01, - z: -2.23307578892655734e-01, - vx: 2.96460137564761618e-03 * DAYS_PER_YEAR, - vy: 2.37847173959480950e-03 * DAYS_PER_YEAR, - vz: -2.96589568540237556e-05 * DAYS_PER_YEAR, - mass: 4.36624404335156298e-05 * SOLAR_MASS - }; +fn offset_momentum(bodies: &mut [Planet, ..N_BODIES]) { + for range(0, N_BODIES) |i| { + for range(0, 3) |k| { + bodies[0].v[k] -= bodies[i].v[k] * bodies[i].mass / SOLAR_MASS; + } } +} - pub fn neptune() -> Body::Props { - return Props { - x: 1.53796971148509165e+01, - y: -2.59193146099879641e+01, - z: 1.79258772950371181e-01, - vx: 2.68067772490389322e-03 * DAYS_PER_YEAR, - vy: 1.62824170038242295e-03 * DAYS_PER_YEAR, - vz: -9.51592254519715870e-05 * DAYS_PER_YEAR, - mass: 5.15138902046611451e-05 * SOLAR_MASS - }; - } +fn main() { + let n: i32 = FromStr::from_str(os::args()[1]).get(); + let mut bodies = BODIES; - pub fn sun() -> Body::Props { - return Props { - x: 0.0, - y: 0.0, - z: 0.0, - vx: 0.0, - vy: 0.0, - vz: 0.0, - mass: SOLAR_MASS - }; - } + offset_momentum(&mut bodies); + println(fmt!("%.9f", energy(&bodies) as float)); - pub fn offset_momentum(props: &mut Body::Props, - px: float, - py: float, - pz: float) { - props.vx = -px / SOLAR_MASS; - props.vy = -py / SOLAR_MASS; - props.vz = -pz / SOLAR_MASS; - } + advance(&mut bodies, 0.01, n); + println(fmt!("%.9f", energy(&bodies) as float)); } + diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index 6e39b755b22af..00e255d890b9d 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -1,84 +1,54 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +use core::from_str::FromStr; +use core::iter::ExtendedMutableIter; +use core::unstable::intrinsics::sqrtf64; -// Based on spectalnorm.gcc by Sebastien Loisel - -extern mod std; +#[inline] +fn A(i: i32, j: i32) -> i32 { + (i+j) * (i+j+1) / 2 + i + 1 +} -fn eval_A(i: uint, j: uint) -> float { - 1.0/(((i+j)*(i+j+1u)/2u+i+1u) as float) +fn dot(v: &[f64], u: &[f64]) -> f64 { + let mut sum = 0.0; + for v.eachi |i, &v_i| { + sum += v_i * u[i]; + } + sum } -fn eval_A_times_u(u: &const [float], Au: &mut [float]) { - let N = vec::len(u); - let mut i = 0u; - while i < N { - Au[i] = 0.0; - let mut j = 0u; - while j < N { - Au[i] += eval_A(i, j) * u[j]; - j += 1u; +fn mult_Av(v: &mut [f64], out: &mut [f64]) { + for vec::eachi_mut(out) |i, out_i| { + let mut sum = 0.0; + for vec::eachi_mut(v) |j, &v_j| { + sum += v_j / (A(i as i32, j as i32) as f64); } - i += 1u; + *out_i = sum; } } -fn eval_At_times_u(u: &const [float], Au: &mut [float]) { - let N = vec::len(u); - let mut i = 0u; - while i < N { - Au[i] = 0.0; - let mut j = 0u; - while j < N { - Au[i] += eval_A(j, i) * u[j]; - j += 1u; +fn mult_Atv(v: &mut [f64], out: &mut [f64]) { + for vec::eachi_mut(out) |i, out_i| { + let mut sum = 0.0; + for vec::eachi_mut(v) |j, &v_j| { + sum += v_j / (A(j as i32, i as i32) as f64); } - i += 1u; + *out_i = sum; } } -fn eval_AtA_times_u(u: &const [float], AtAu: &mut [float]) { - let mut v = vec::from_elem(vec::len(u), 0.0); - eval_A_times_u(u, v); - eval_At_times_u(v, AtAu); +fn mult_AtAv(v: &mut [f64], out: &mut [f64], tmp: &mut [f64]) { + mult_Av(v, tmp); + mult_Atv(tmp, out); } +#[fixed_stack_segment] fn main() { - let args = os::args(); - let args = if os::getenv(~"RUST_BENCH").is_some() { - ~[~"", ~"2000"] - } else if args.len() <= 1u { - ~[~"", ~"1000"] - } else { - args - }; - - let N = uint::from_str(args[1]).get(); - - let mut u = vec::from_elem(N, 1.0); - let mut v = vec::from_elem(N, 0.0); - let mut i = 0u; - while i < 10u { - eval_AtA_times_u(u, v); - eval_AtA_times_u(v, u); - i += 1u; - } - - let mut vBv = 0.0; - let mut vv = 0.0; - let mut i = 0u; - while i < N { - vBv += u[i] * v[i]; - vv += v[i] * v[i]; - i += 1u; + let n: uint = FromStr::from_str(os::args()[1]).get(); + let mut u = vec::from_elem(n, 1f64), v = u.clone(), tmp = u.clone(); + for 8.times { + mult_AtAv(u, v, tmp); + mult_AtAv(v, u, tmp); } - io::println(fmt!("%0.9f\n", float::sqrt(vBv / vv))); + println(fmt!("%.9f", sqrtf64(dot(u,v) / dot(v,v)) as float)); } + From 10aa1c3c05b67c974d47cf1e21b3c2b3549fb0d6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 17 Apr 2013 14:19:25 -0700 Subject: [PATCH 291/403] test: Add fannkuch-redux and fasta-redux shootout benchmarks --- src/libcore/vec.rs | 24 ++- src/test/bench/shootout-fannkuch-redux.rs | 95 ++++++++++ src/test/bench/shootout-fannkuchredux.rs | 81 --------- src/test/bench/shootout-fasta-redux.rs | 204 ++++++++++++++++++++++ 4 files changed, 322 insertions(+), 82 deletions(-) create mode 100644 src/test/bench/shootout-fannkuch-redux.rs delete mode 100644 src/test/bench/shootout-fannkuchredux.rs create mode 100644 src/test/bench/shootout-fasta-redux.rs diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 3e0ba38a6e816..8934b6cab67c8 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -12,8 +12,9 @@ #[warn(non_camel_case_types)]; -use container::{Container, Mutable}; +use cast::transmute; use cast; +use container::{Container, Mutable}; use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use iter::BaseIter; @@ -2137,6 +2138,7 @@ pub trait ImmutableCopyableVector { fn filtered(&self, f: &fn(&T) -> bool) -> ~[T]; fn rfind(&self, f: &fn(t: &T) -> bool) -> Option; fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]); + unsafe fn unsafe_get(&self, elem: uint) -> T; } /// Extension methods for vectors @@ -2173,6 +2175,13 @@ impl<'self,T:Copy> ImmutableCopyableVector for &'self [T] { fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]) { partitioned(*self, f) } + + /// Returns the element at the given index, without doing bounds checking. + #[inline(always)] + unsafe fn unsafe_get(&self, elem: uint) -> T { + let (ptr, _): (*T, uint) = transmute(*self); + *ptr.offset(elem) + } } pub trait OwnedVector { @@ -2313,6 +2322,19 @@ impl OwnedEqVector for ~[T] { } } +pub trait MutableVector { + unsafe fn unsafe_set(&self, elem: uint, val: T); +} + +impl<'self,T> MutableVector for &'self mut [T] { + #[inline(always)] + unsafe fn unsafe_set(&self, elem: uint, val: T) { + let pair_ptr: &(*mut T, uint) = transmute(self); + let (ptr, _) = *pair_ptr; + *ptr.offset(elem) = val; + } +} + /** * Constructs a vector from an unsafe pointer to a buffer * diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs new file mode 100644 index 0000000000000..21f38245ca359 --- /dev/null +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -0,0 +1,95 @@ +use core::from_str::FromStr; +use core::i32::range; +use core::vec::MutableVector; + +fn max(a: i32, b: i32) -> i32 { + if a > b { + a + } else { + b + } +} + +#[inline(never)] +fn fannkuch_redux(n: i32) -> i32 { + let mut perm = vec::from_elem(n as uint, 0i32); + let mut perm1 = vec::from_fn(n as uint, |i| i as i32); + let mut count = vec::from_elem(n as uint, 0i32); + let mut max_flips_count = 0i32, perm_count = 0i32, checksum = 0i32; + + let mut r = n; + loop { + unsafe { + while r != 1 { + count.unsafe_set((r-1) as uint, r); + r -= 1; + } + + // XXX: Need each2_mut. + for vec::eachi_mut(perm) |i, perm_i| { + *perm_i = perm1.unsafe_get(i); + } + + let mut flips_count: i32 = 0; + let mut k: i32; + loop { + k = perm.unsafe_get(0); + if k == 0 { + break; + } + + let k2 = (k+1) >> 1; + for range(0, k2) |i| { + let (perm_i, perm_k_i) = { + (perm.unsafe_get(i as uint), + perm.unsafe_get((k-i) as uint)) + }; + perm.unsafe_set(i as uint, perm_k_i); + perm.unsafe_set((k-i) as uint, perm_i); + } + flips_count += 1; + } + + max_flips_count = max(max_flips_count, flips_count); + checksum += if perm_count % 2 == 0 { + flips_count + } else { + -flips_count + }; + + // Use incremental change to generate another permutation. + loop { + if r == n { + println(checksum.to_str()); + return max_flips_count; + } + + let perm0 = perm1[0]; + let mut i: i32 = 0; + while i < r { + let j = i + 1; + let perm1_j = { perm1.unsafe_get(j as uint) }; + perm1.unsafe_set(i as uint, perm1_j); + i = j; + } + perm1.unsafe_set(r as uint, perm0); + + let count_r = { count.unsafe_get(r as uint) }; + count.unsafe_set(r as uint, count_r - 1); + if count.unsafe_get(r as uint) > 0 { + break; + } + r += 1; + } + + perm_count += 1; + } + } +} + +#[fixed_stack_segment] +fn main() { + let n: i32 = FromStr::from_str(os::args()[1]).get(); + println(fmt!("Pfannkuchen(%d) = %d", n as int, fannkuch_redux(n) as int)); +} + diff --git a/src/test/bench/shootout-fannkuchredux.rs b/src/test/bench/shootout-fannkuchredux.rs deleted file mode 100644 index 675151cf6c9da..0000000000000 --- a/src/test/bench/shootout-fannkuchredux.rs +++ /dev/null @@ -1,81 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Based on Isaac Gouy's fannkuchredux.csharp -extern mod std; - -fn fannkuch(n: int) -> int { - fn perm1init(i: uint) -> int { return i as int; } - - let mut perm = vec::from_elem(n as uint, 0); - let mut perm1 = vec::from_fn(n as uint, |i| perm1init(i)); - let mut count = vec::from_elem(n as uint, 0); - let mut f = 0; - let mut i = 0; - let mut k = 0; - let mut r = 0; - let mut flips = 0; - let mut nperm = 0; - let mut checksum = 0; - r = n; - while r > 0 { - i = 0; - while r != 1 { count[r - 1] = r; r -= 1; } - while i < n { perm[i] = perm1[i]; i += 1; } - // Count flips and update max and checksum - - f = 0; - k = perm[0]; - while k != 0 { - i = 0; - while 2 * i < k { - let t = perm[i]; - perm[i] = perm[k - i]; - perm[k - i] = t; - i += 1; - } - k = perm[0]; - f += 1; - } - if f > flips { flips = f; } - if nperm & 0x1 == 0 { checksum += f; } else { checksum -= f; } - // Use incremental change to generate another permutation - - let mut go = true; - while go { - if r == n { - io::println(fmt!("%d", checksum)); - return flips; - } - let p0 = perm1[0]; - i = 0; - while i < r { let j = i + 1; perm1[i] = perm1[j]; i = j; } - perm1[r] = p0; - count[r] -= 1; - if count[r] > 0 { go = false; } else { r += 1; } - } - nperm += 1; - } - return flips; -} - -fn main() { - let args = os::args(); - let args = if os::getenv(~"RUST_BENCH").is_some() { - ~[~"", ~"10"] - } else if args.len() <= 1u { - ~[~"", ~"8"] - } else { - args - }; - - let n = int::from_str(args[1]).get(); - io::println(fmt!("Pfannkuchen(%d) = %d", n, fannkuch(n))); -} diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs new file mode 100644 index 0000000000000..5cb04fcd27a8f --- /dev/null +++ b/src/test/bench/shootout-fasta-redux.rs @@ -0,0 +1,204 @@ +use core::cast::transmute; +use core::from_str::FromStr; +use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite}; +use core::uint::{min, range}; +use core::vec::bytes::copy_memory; + +static LINE_LEN: uint = 60; +static LOOKUP_SIZE: uint = 4 * 1024; +static LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32; + +// Random number generator constants +static IM: u32 = 139968; +static IA: u32 = 3877; +static IC: u32 = 29573; + +static ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\ + GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\ + GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\ + AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\ + CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\ + CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\ + CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +static NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 }; + +static MESSAGE_1: &'static str = ">ONE Homo sapiens alu\n"; +static MESSAGE_2: &'static str = ">TWO IUB ambiguity codes\n"; +static MESSAGE_3: &'static str = ">THREE Homo sapiens frequency\n"; + +static IUB: [AminoAcid, ..15] = [ + AminoAcid { c: 'a' as u8, p: 0.27 }, + AminoAcid { c: 'c' as u8, p: 0.12 }, + AminoAcid { c: 'g' as u8, p: 0.12 }, + AminoAcid { c: 't' as u8, p: 0.27 }, + AminoAcid { c: 'B' as u8, p: 0.02 }, + AminoAcid { c: 'D' as u8, p: 0.02 }, + AminoAcid { c: 'H' as u8, p: 0.02 }, + AminoAcid { c: 'K' as u8, p: 0.02 }, + AminoAcid { c: 'M' as u8, p: 0.02 }, + AminoAcid { c: 'N' as u8, p: 0.02 }, + AminoAcid { c: 'R' as u8, p: 0.02 }, + AminoAcid { c: 'S' as u8, p: 0.02 }, + AminoAcid { c: 'V' as u8, p: 0.02 }, + AminoAcid { c: 'W' as u8, p: 0.02 }, + AminoAcid { c: 'Y' as u8, p: 0.02 }, +]; + +static HOMO_SAPIENS: [AminoAcid, ..4] = [ + AminoAcid { c: 'a' as u8, p: 0.3029549426680 }, + AminoAcid { c: 'c' as u8, p: 0.1979883004921 }, + AminoAcid { c: 'g' as u8, p: 0.1975473066391 }, + AminoAcid { c: 't' as u8, p: 0.3015094502008 }, +]; + +// XXX: Use map(). +fn sum_and_scale(a: &'static [AminoAcid]) -> ~[AminoAcid] { + let mut result = ~[]; + let mut p = 0f32; + for a.each |a_i| { + let mut a_i = *a_i; + p += a_i.p; + a_i.p = p * LOOKUP_SCALE; + result.push(a_i); + } + result[result.len() - 1].p = LOOKUP_SCALE; + result +} + +struct AminoAcid { + c: u8, + p: f32, +} + +struct RepeatFasta { + alu: &'static str, + stdout: *FILE, +} + +impl RepeatFasta { + fn new(stdout: *FILE, alu: &'static str) -> RepeatFasta { + RepeatFasta { + alu: alu, + stdout: stdout, + } + } + + fn make(&mut self, n: uint) { + unsafe { + let stdout = self.stdout; + let alu_len = self.alu.len(); + let mut buf = vec::from_elem(alu_len + LINE_LEN, 0u8); + let alu: &[u8] = str::byte_slice_no_callback(self.alu); + + copy_memory(buf, alu, alu_len); + copy_memory(vec::mut_slice(buf, alu_len, buf.len()), + alu, + LINE_LEN); + + let mut pos = 0, bytes, n = n; + while n > 0 { + bytes = min(LINE_LEN, n); + fwrite(transmute(&buf[pos]), bytes as u64, 1, stdout); + fputc('\n' as c_int, stdout); + pos += bytes; + if pos > alu_len { + pos -= alu_len; + } + n -= bytes; + } + } + } +} + +struct RandomFasta { + seed: u32, + stdout: *FILE, + lookup: [AminoAcid, ..LOOKUP_SIZE], +} + +impl RandomFasta { + fn new(stdout: *FILE, a: &[AminoAcid]) -> RandomFasta { + RandomFasta { + seed: 42, + stdout: stdout, + lookup: RandomFasta::make_lookup(a), + } + } + + fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] { + let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ]; + let mut j = 0; + for vec::eachi_mut(lookup) |i, slot| { + while a[j].p < (i as f32) { + j += 1; + } + *slot = a[j]; + } + lookup + } + + fn rng(&mut self, max: f32) -> f32 { + self.seed = (self.seed * IA + IC) % IM; + max * (self.seed as f32) / (IM as f32) + } + + fn nextc(&mut self) -> u8 { + let r = self.rng(1.0); + for self.lookup.each |a| { + if a.p >= r { + return a.c; + } + } + 0 + } + + fn make(&mut self, n: uint) { + unsafe { + let lines = n / LINE_LEN, chars_left = n % LINE_LEN; + let mut buf = [0, ..LINE_LEN + 1]; + + for lines.times { + for range(0, LINE_LEN) |i| { + buf[i] = self.nextc(); + } + buf[LINE_LEN] = '\n' as u8; + fwrite(transmute(&buf[0]), + LINE_LEN as u64 + 1, + 1, + self.stdout); + } + for range(0, chars_left) |i| { + buf[i] = self.nextc(); + } + fwrite(transmute(&buf[0]), chars_left as u64, 1, self.stdout); + } + } +} + +#[fixed_stack_segment] +fn main() { + let n: uint = FromStr::from_str(os::args()[1]).get(); + + unsafe { + let mode = "w"; + let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0])); + + fputs(transmute(&MESSAGE_1[0]), stdout); + let mut repeat = RepeatFasta::new(stdout, ALU); + repeat.make(n * 2); + + fputs(transmute(&MESSAGE_2[0]), stdout); + let iub = sum_and_scale(IUB); + let mut random = RandomFasta::new(stdout, iub); + random.make(n * 3); + + fputs(transmute(&MESSAGE_3[0]), stdout); + let homo_sapiens = sum_and_scale(HOMO_SAPIENS); + random.lookup = RandomFasta::make_lookup(homo_sapiens); + random.make(n * 5); + + fputc('\n' as c_int, stdout); + } +} + From 1d3231362cbee20a1df032fd871f8afd8980a98e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 17 Apr 2013 18:59:54 -0700 Subject: [PATCH 292/403] test: Add k-nucleotide --- src/test/run-pass/shootout-k-nucleotide.rs | 314 +++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 src/test/run-pass/shootout-k-nucleotide.rs diff --git a/src/test/run-pass/shootout-k-nucleotide.rs b/src/test/run-pass/shootout-k-nucleotide.rs new file mode 100644 index 0000000000000..1330e8c892f34 --- /dev/null +++ b/src/test/run-pass/shootout-k-nucleotide.rs @@ -0,0 +1,314 @@ +extern mod std; + +use core::cast::transmute; +use core::i32::range; +use core::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat}; +use core::libc::{stat, strlen}; +use core::ptr::null; +use core::unstable::intrinsics::init; +use core::vec::{reverse, slice}; +use std::sort::quick_sort3; + +static LINE_LEN: uint = 80; +static TABLE: [u8, ..4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ]; +static TABLE_SIZE: uint = 2 << 16; + +static OCCURRENCES: [&'static str, ..5] = [ + "GGT", + "GGTA", + "GGTATT", + "GGTATTTTAATT", + "GGTATTTTAATTTATAGT", +]; + +// Code implementation + +#[deriving(Eq, Ord)] +struct Code(u64); + +impl Code { + fn hash(&self) -> u64 { + **self + } + + #[inline(always)] + fn push_char(&self, c: u8) -> Code { + Code((**self << 2) + (pack_symbol(c) as u64)) + } + + fn rotate(&self, c: u8, frame: i32) -> Code { + Code(*self.push_char(c) & ((1u64 << (2 * (frame as u64))) - 1)) + } + + fn pack(string: &str) -> Code { + let mut code = Code(0u64); + for uint::range(0, string.len()) |i| { + code = code.push_char(string[i]); + } + code + } + + // XXX: Inefficient. + fn unpack(&self, frame: i32) -> ~str { + let mut key = **self; + let mut result = ~[]; + for (frame as uint).times { + result.push(unpack_symbol((key as u8) & 3)); + key >>= 2; + } + + reverse(result); + str::from_bytes(result) + } +} + +// Hash table implementation + +trait TableCallback { + fn f(&self, entry: &mut Entry); +} + +struct BumpCallback; + +impl TableCallback for BumpCallback { + fn f(&self, entry: &mut Entry) { + entry.count += 1; + } +} + +struct PrintCallback(&'static str); + +impl TableCallback for PrintCallback { + fn f(&self, entry: &mut Entry) { + println(fmt!("%d\t%s", entry.count as int, **self)); + } +} + +struct Entry { + code: Code, + count: i32, + next: Option<~Entry>, +} + +struct Table { + count: i32, + items: [Option<~Entry>, ..TABLE_SIZE] +} + +impl Table { + fn new() -> Table { + Table { + count: 0, + items: [ None, ..TABLE_SIZE ], + } + } + + fn search_remainder(item: &mut Entry, key: Code, c: C) { + match item.next { + None => { + let mut entry = ~Entry { + code: key, + count: 0, + next: None, + }; + c.f(entry); + item.next = Some(entry); + } + Some(ref mut entry) => { + if entry.code == key { + c.f(*entry); + return; + } + + Table::search_remainder(*entry, key, c) + } + } + } + + fn lookup(&mut self, key: Code, c: C) { + let index = *key % (TABLE_SIZE as u64); + + { + if self.items[index].is_none() { + let mut entry = ~Entry { + code: key, + count: 0, + next: None, + }; + c.f(entry); + self.items[index] = Some(entry); + return; + } + } + + { + let mut entry = &mut *self.items[index].get_mut_ref(); + if entry.code == key { + c.f(*entry); + return; + } + + Table::search_remainder(*entry, key, c) + } + } + + fn each(&self, f: &fn(entry: &Entry) -> bool) { + for self.items.each |item| { + match *item { + None => {} + Some(ref item) => { + let mut item: &Entry = *item; + loop { + if !f(item) { + return; + } + + match item.next { + None => break, + Some(ref next_item) => item = &**next_item, + } + } + } + }; + } + } +} + +// Main program + +fn pack_symbol(c: u8) -> u8 { + match c { + 'a' as u8 | 'A' as u8 => 0, + 'c' as u8 | 'C' as u8 => 1, + 'g' as u8 | 'G' as u8 => 2, + 't' as u8 | 'T' as u8 => 3, + _ => fail!(c.to_str()) + } +} + +fn unpack_symbol(c: u8) -> u8 { + TABLE[c] +} + +fn next_char<'a>(mut buf: &'a [u8]) -> &'a [u8] { + loop { + buf = slice(buf, 1, buf.len()); + if buf.len() == 0 { + break; + } + if buf[0] != (' ' as u8) && buf[0] != ('\t' as u8) && + buf[0] != ('\n' as u8) && buf[0] != 0 { + break; + } + } + buf +} + +#[inline(never)] +fn read_stdin() -> ~[u8] { + unsafe { + let mode = "r"; + //let stdin = fdopen(STDIN_FILENO as c_int, transmute(&mode[0])); + let path = "knucleotide-input.txt"; + let stdin = fopen(transmute(&path[0]), transmute(&mode[0])); + + let mut st: stat = init(); + fstat(fileno(stdin), &mut st); + let mut buf = vec::from_elem(st.st_size as uint, 0); + + let header = str::byte_slice_no_callback(">THREE"); + let header = vec::slice(header, 0, 6); + + { + let mut window: &mut [u8] = buf; + loop { + fgets(transmute(&mut window[0]), LINE_LEN as c_int, stdin); + + { + if vec::slice(window, 0, 6) == header { + break; + } + } + } + + while fgets(transmute(&mut window[0]), + LINE_LEN as c_int, + stdin) != null() { + window = vec::mut_slice(window, + strlen(transmute(&window[0])) as uint, + window.len()); + } + } + + buf + } +} + +#[inline(never)] +#[fixed_stack_segment] +fn generate_frequencies(frequencies: &mut Table, + mut input: &[u8], + frame: i32) { + let mut code = Code(0); + + // Pull first frame. + for (frame as uint).times { + code = code.push_char(input[0]); + input = next_char(input); + } + frequencies.lookup(code, BumpCallback); + + while input.len() != 0 && input[0] != ('>' as u8) { + code = code.rotate(input[0], frame); + frequencies.lookup(code, BumpCallback); + input = next_char(input); + } +} + +#[inline(never)] +#[fixed_stack_segment] +fn print_frequencies(frequencies: &Table, frame: i32) { + let mut vector = ~[]; + for frequencies.each |entry| { + vector.push((entry.code, entry.count)); + } + quick_sort3(vector); + + let mut total_count = 0; + for vector.each |&(_, count)| { + total_count += count; + } + + for vector.each |&(key, count)| { + println(fmt!("%s %.3f", + key.unpack(frame), + (count as float * 100.0) / (total_count as float))); + } +} + +fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) { + frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence)) +} + +#[fixed_stack_segment] +fn main() { + let input = read_stdin(); + + let mut frequencies = ~Table::new(); + generate_frequencies(frequencies, input, 1); + print_frequencies(frequencies, 1); + + *frequencies = Table::new(); + generate_frequencies(frequencies, input, 2); + print_frequencies(frequencies, 2); + + for range(0, 5) |i| { + let occurrence = OCCURRENCES[i]; + *frequencies = Table::new(); + generate_frequencies(frequencies, + input, + occurrence.len() as i32); + print_occurrences(frequencies, occurrence); + } +} + From bc0dd7f1083681375aa7fdfeacf8ad3e3942ce2a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 17 Apr 2013 19:05:30 -0700 Subject: [PATCH 293/403] Move shootout-k-nucleotide to bench --- src/test/{run-pass => bench}/shootout-k-nucleotide.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/{run-pass => bench}/shootout-k-nucleotide.rs (100%) diff --git a/src/test/run-pass/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs similarity index 100% rename from src/test/run-pass/shootout-k-nucleotide.rs rename to src/test/bench/shootout-k-nucleotide.rs From 7720c15ae11141e2b1a2a3a560b1cdacb6ddada4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Apr 2013 15:53:09 -0700 Subject: [PATCH 294/403] test: Implement pidigits and reverse-complement --- src/test/bench/shootout-pidigits.rs | 176 ++++++++++++++++++ src/test/bench/shootout-reverse-complement.rs | 152 +++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 src/test/bench/shootout-pidigits.rs create mode 100644 src/test/bench/shootout-reverse-complement.rs diff --git a/src/test/bench/shootout-pidigits.rs b/src/test/bench/shootout-pidigits.rs new file mode 100644 index 0000000000000..722d72ece8164 --- /dev/null +++ b/src/test/bench/shootout-pidigits.rs @@ -0,0 +1,176 @@ +use core::cast::transmute; +use core::from_str::FromStr; +use core::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc}; +use core::libc::{fputs}; +use core::ptr::null; + +struct mpz_t { + _mp_alloc: c_int, + _mp_size: c_int, + _mp_limb_t: *c_void, +} + +impl mpz_t { + fn new() -> mpz_t { + mpz_t { + _mp_alloc: 0, + _mp_size: 0, + _mp_limb_t: null(), + } + } +} + +#[link_args="-lgmp"] +extern { + #[fast_ffi] + #[link_name="__gmpz_add"] + fn mpz_add(x: *mpz_t, y: *mpz_t, z: *mpz_t); + #[fast_ffi] + #[link_name="__gmpz_cmp"] + fn mpz_cmp(x: *mpz_t, y: *mpz_t) -> c_int; + #[fast_ffi] + #[link_name="__gmpz_fdiv_qr"] + fn mpz_fdiv_qr(a: *mpz_t, b: *mpz_t, c: *mpz_t, d: *mpz_t); + #[fast_ffi] + #[link_name="__gmpz_get_ui"] + fn mpz_get_ui(x: *mpz_t) -> c_uint; + #[fast_ffi] + #[link_name="__gmpz_init"] + fn mpz_init(x: *mpz_t); + #[fast_ffi] + #[link_name="__gmpz_init_set_ui"] + fn mpz_init_set_ui(x: *mpz_t, y: c_uint); + #[fast_ffi] + #[link_name="__gmpz_mul_2exp"] + fn mpz_mul_2exp(x: *mpz_t, y: *mpz_t, z: c_uint); + #[fast_ffi] + #[link_name="__gmpz_mul_ui"] + fn mpz_mul_ui(x: *mpz_t, y: *mpz_t, z: c_uint); + #[fast_ffi] + #[link_name="__gmpz_submul_ui"] + fn mpz_submul_ui(x: *mpz_t, y: *mpz_t, z: c_uint); +} + +struct Context { + numer: mpz_t, + accum: mpz_t, + denom: mpz_t, + tmp1: mpz_t, + tmp2: mpz_t, +} + +impl Context { + fn new() -> Context { + unsafe { + let mut result = Context { + numer: mpz_t::new(), + accum: mpz_t::new(), + denom: mpz_t::new(), + tmp1: mpz_t::new(), + tmp2: mpz_t::new(), + }; + mpz_init(&result.tmp1); + mpz_init(&result.tmp2); + mpz_init_set_ui(&result.numer, 1); + mpz_init_set_ui(&result.accum, 0); + mpz_init_set_ui(&result.denom, 1); + result + } + } + + fn extract_digit(&mut self) -> i32 { + unsafe { + if mpz_cmp(&self.numer, &self.accum) > 0 { + return -1; + } + + // Compute (numer * 3 + accum) / denom + mpz_mul_2exp(&self.tmp1, &self.numer, 1); + mpz_add(&self.tmp1, &self.tmp1, &self.numer); + mpz_add(&self.tmp1, &self.tmp1, &self.accum); + mpz_fdiv_qr(&self.tmp1, &self.tmp2, &self.tmp1, &self.denom); + + // Now, if (numer * 4 + accum) % denom... + mpz_add(&self.tmp2, &self.tmp2, &self.numer); + + // ... is normalized, then the two divisions have the same result. + if mpz_cmp(&self.tmp2, &self.denom) >= 0 { + return -1; + } + + mpz_get_ui(&self.tmp1) as i32 + } + } + + fn next_term(&mut self, k: u32) { + unsafe { + let y2 = k*2 + 1; + + mpz_mul_2exp(&self.tmp1, &self.numer, 1); + mpz_add(&self.accum, &self.accum, &self.tmp1); + mpz_mul_ui(&self.accum, &self.accum, y2); + mpz_mul_ui(&self.numer, &self.numer, k); + mpz_mul_ui(&self.denom, &self.denom, y2); + } + } + + fn eliminate_digit(&mut self, d: u32) { + unsafe { + mpz_submul_ui(&self.accum, &self.denom, d); + mpz_mul_ui(&self.accum, &self.accum, 10); + mpz_mul_ui(&self.numer, &self.numer, 10); + } + } +} + +fn pidigits(n: u32) { + unsafe { + let mode = "w"; + let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0])); + + let mut d: i32; + let mut i: u32 = 0, k: u32 = 0, m: u32; + + let mut context = Context::new(); + loop { + loop { + k += 1; + context.next_term(k); + d = context.extract_digit(); + if d != -1 { + break; + } + } + + fputc((d as c_int) + ('0' as c_int), stdout); + + i += 1; + m = i % 10; + if m == 0 { + let res = fmt!("\t:%d\n", i as int); + fputs(transmute(&res[0]), stdout); + } + if i >= n { + break; + } + context.eliminate_digit(d as u32); + } + + if m != 0 { + m = 10 - m; + while m != 0 { + m -= 1; + fputc(' ' as c_int, stdout); + } + let res = fmt!("\t:%d\n", i as int); + fputs(transmute(&res[0]), stdout); + } + } +} + +#[fixed_stack_segment] +fn main() { + let n: u32 = FromStr::from_str(os::args()[1]).get(); + pidigits(n); +} + diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs new file mode 100644 index 0000000000000..21b1f8f3c82be --- /dev/null +++ b/src/test/bench/shootout-reverse-complement.rs @@ -0,0 +1,152 @@ +use core::cast::transmute; +use core::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite}; +use core::libc::{size_t}; +use core::ptr::null; +use core::vec::{capacity, reserve, reserve_at_least}; +use core::vec::raw::set_len; + +static LINE_LEN: u32 = 80; + +static COMPLEMENTS: [u8, ..256] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, + 'T' as u8, + 'V' as u8, + 'G' as u8, + 'H' as u8, + 0, + 0, + 'C' as u8, + 'D' as u8, + 0, + 0, + 'M' as u8, + 0, + 'K' as u8, + 'N' as u8, + 0, + 0, + 0, + 'Y' as u8, + 'S' as u8, + 'A' as u8, + 'A' as u8, + 'B' as u8, + 'W' as u8, + 0, + 'R' as u8, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, + 'T' as u8, + 'V' as u8, + 'G' as u8, + 'H' as u8, + 0, + 0, + 'C' as u8, + 'D' as u8, + 0, + 0, + 'M' as u8, + 0, + 'K' as u8, + 'N' as u8, + 0, + 0, + 0, + 'Y' as u8, + 'S' as u8, + 'A' as u8, + 'A' as u8, + 'B' as u8, + 'W' as u8, + 0, + 'R' as u8, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +#[fixed_stack_segment] +fn main() { + unsafe { + let mode = "r"; + //let stdin = fdopen(STDIN_FILENO as c_int, transmute(&mode[0])); + let path = "reversecomplement-input.txt"; + let stdin = fopen(transmute(&path[0]), transmute(&mode[0])); + let mode = "w"; + let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0])); + + let mut out: ~[u8] = ~[]; + reserve(&mut out, 12777888); + let mut pos = 0; + + loop { + let needed = pos + (LINE_LEN as uint) + 1; + if capacity(&out) < needed { + reserve_at_least(&mut out, needed); + } + + let mut ptr = out.unsafe_mut_ref(pos); + if fgets(transmute(ptr), LINE_LEN as c_int, stdin) == null() { + break; + } + + // Don't change lines that begin with '>' or ';'. + let first = *ptr; + if first == ('>' as u8) { + while *ptr != 0 { + ptr = ptr.offset(1); + } + *ptr = '\n' as u8; + + pos = (ptr as uint) - (out.unsafe_ref(0) as uint); + fwrite(transmute(out.unsafe_ref(0)), + 1, + pos as size_t, + stdout); + + pos = 0; + loop; + } + + // Complement other lines. + loop { + let ch = *ptr; + if ch == 0 { + break; + } + *ptr = COMPLEMENTS.unsafe_get(ch as uint); + ptr = ptr.offset(1); + } + *ptr = '\n' as u8; + + pos = (ptr as uint) - (out.unsafe_ref(0) as uint); + } + + fwrite(transmute(out.unsafe_ref(0)), 1, pos as size_t, stdout); + } +} + From c995a62d44ce8534d4f8bf36284419661b87e167 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Apr 2013 15:53:29 -0700 Subject: [PATCH 295/403] librustc: WIP patch for using the return value. --- src/libcore/core.rc | 2 +- src/libcore/hashmap.rs | 40 +- src/libcore/libc.rs | 4 + src/libcore/num/int-template.rs | 2 +- src/libcore/num/uint-template.rs | 2 +- src/libcore/prelude.rs | 2 +- src/libcore/str.rs | 9 + src/libcore/vec.rs | 27 +- src/librustc/back/link.rs | 6 +- src/librustc/middle/trans/base.rs | 307 +++++++++++----- src/librustc/middle/trans/build.rs | 22 +- src/librustc/middle/trans/cabi.rs | 40 +- src/librustc/middle/trans/callee.rs | 77 ++-- src/librustc/middle/trans/closure.rs | 18 +- src/librustc/middle/trans/common.rs | 16 +- src/librustc/middle/trans/controlflow.rs | 6 +- src/librustc/middle/trans/datum.rs | 2 +- src/librustc/middle/trans/expr.rs | 62 +++- src/librustc/middle/trans/foreign.rs | 445 ++++++++++++++--------- src/librustc/middle/trans/glue.rs | 22 +- src/librustc/middle/trans/type_of.rs | 32 +- src/libstd/net_tcp.rs | 29 +- src/libstd/uv_ll.rs | 3 +- src/rt/rust_uv.cpp | 3 +- src/test/run-pass/const-bound.rs | 4 +- src/test/run-pass/extern-call.rs | 2 +- 26 files changed, 778 insertions(+), 406 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 4080c70c8ae48..81190ea8fc62e 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -95,7 +95,7 @@ pub use str::{StrSlice}; pub use container::{Container, Mutable}; pub use vec::{CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; -pub use vec::{OwnedVector, OwnedCopyableVector}; +pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector}; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use iter::{ExtendedMutableIter}; diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 3efe21fc42cdb..1d7cc8515a656 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -16,7 +16,6 @@ use container::{Container, Mutable, Map, Set}; use cmp::{Eq, Equiv}; use hash::Hash; -use to_bytes::IterBytes; use iter::BaseIter; use hash::Hash; use iter; @@ -72,7 +71,7 @@ fn linear_map_with_capacity_and_keys( } } -priv impl HashMap { +priv impl HashMap { #[inline(always)] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the @@ -111,9 +110,8 @@ priv impl HashMap { } #[inline(always)] - fn bucket_for_key_equiv>(&self, - k: &Q) - -> SearchResult { + fn bucket_for_key_equiv>(&self, k: &Q) + -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash_equiv(hash, k) } @@ -303,7 +301,7 @@ priv impl HashMap { } } -impl Container for HashMap { +impl Container for HashMap { /// Return the number of elements in the map fn len(&const self) -> uint { self.size } @@ -311,7 +309,7 @@ impl Container for HashMap { fn is_empty(&const self) -> bool { self.len() == 0 } } -impl Mutable for HashMap { +impl Mutable for HashMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { for uint::range(0, self.buckets.len()) |idx| { @@ -321,7 +319,7 @@ impl Mutable for HashMap { } } -impl Map for HashMap { +impl Map for HashMap { /// Return true if the map contains a value for the specified key fn contains_key(&self, k: &K) -> bool { match self.bucket_for_key(k) { @@ -458,7 +456,7 @@ impl Map for HashMap { } } -pub impl HashMap { +pub impl HashMap { /// Create an empty HashMap fn new() -> HashMap { HashMap::with_capacity(INITIAL_CAPACITY) @@ -669,8 +667,7 @@ pub impl HashMap { /// Return true if the map contains a value for the specified key, /// using equivalence - fn contains_key_equiv>(&self, key: &Q) - -> bool { + fn contains_key_equiv>(&self, key: &Q) -> bool { match self.bucket_for_key_equiv(key) { FoundEntry(_) => {true} TableFull | FoundHole(_) => {false} @@ -680,8 +677,7 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, using /// equivalence #[cfg(stage0)] - fn find_equiv>(&self, k: &Q) - -> Option<&'self V> { + fn find_equiv>(&self, k: &Q) -> Option<&'self V> { match self.bucket_for_key_equiv(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), TableFull | FoundHole(_) => None, @@ -693,9 +689,7 @@ pub impl HashMap { #[cfg(stage1)] #[cfg(stage2)] #[cfg(stage3)] - fn find_equiv<'a, Q:Hash + IterBytes + Equiv>( - &'a self, k: &Q) -> Option<&'a V> - { + fn find_equiv<'a, Q:Hash + Equiv>(&'a self, k: &Q) -> Option<&'a V> { match self.bucket_for_key_equiv(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), TableFull | FoundHole(_) => None, @@ -703,7 +697,7 @@ pub impl HashMap { } } -impl Eq for HashMap { +impl Eq for HashMap { fn eq(&self, other: &HashMap) -> bool { if self.len() != other.len() { return false; } @@ -724,18 +718,18 @@ pub struct HashSet { priv map: HashMap } -impl BaseIter for HashSet { +impl BaseIter for HashSet { /// Visit all values in order fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } fn size_hint(&self) -> Option { Some(self.len()) } } -impl Eq for HashSet { +impl Eq for HashSet { fn eq(&self, other: &HashSet) -> bool { self.map == other.map } fn ne(&self, other: &HashSet) -> bool { self.map != other.map } } -impl Container for HashSet { +impl Container for HashSet { /// Return the number of elements in the set fn len(&const self) -> uint { self.map.len() } @@ -743,12 +737,12 @@ impl Container for HashSet { fn is_empty(&const self) -> bool { self.map.is_empty() } } -impl Mutable for HashSet { +impl Mutable for HashSet { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } } -impl Set for HashSet { +impl Set for HashSet { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } @@ -816,7 +810,7 @@ impl Set for HashSet { } } -pub impl HashSet { +pub impl HashSet { /// Create an empty HashSet fn new() -> HashSet { HashSet::with_capacity(INITIAL_CAPACITY) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 9d100d1d352dd..945d08323b4e5 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1097,9 +1097,12 @@ pub mod funcs { unsafe fn setbuf(stream: *FILE, buf: *c_char); // Omitted: printf and scanf variants. unsafe fn fgetc(stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fgets(buf: *mut c_char, n: c_int, stream: *FILE) -> *c_char; + #[fast_ffi] unsafe fn fputc(c: c_int, stream: *FILE) -> c_int; + #[fast_ffi] unsafe fn fputs(s: *c_char, stream: *FILE) -> *c_char; // Omitted: getc, getchar (might be macros). @@ -1263,6 +1266,7 @@ pub mod funcs { unsafe fn pclose(stream: *FILE) -> c_int; #[link_name = "_fdopen"] + #[fast_ffi] unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE; #[link_name = "_fileno"] diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 8fd61fb6187e4..e170d85cc716e 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -503,4 +503,4 @@ mod tests { fn test_range_step_zero_step() { for range_step(0,10,0) |_i| {} } -} \ No newline at end of file +} diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 0109c915c6014..0fb6ea614d861 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -474,4 +474,4 @@ mod tests { fn test_range_step_zero_step_down() { for range_step(0,-10,0) |_i| {} } -} \ No newline at end of file +} diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 95481d032a446..822fb2e476beb 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -46,7 +46,7 @@ pub use to_str::ToStr; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use vec::{CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; -pub use vec::{OwnedVector, OwnedCopyableVector}; +pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector}; pub use io::{Reader, ReaderUtil, Writer, WriterUtil}; /* Reexported runtime types */ diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 6bde7d33849e6..837f9c1a9adea 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -430,6 +430,15 @@ pub fn byte_slice(s: &str, f: &fn(v: &[u8]) -> T) -> T { } } +/// Work with the string as a byte slice, not including trailing null, without +/// a callback. +#[inline(always)] +pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] { + unsafe { + cast::transmute(s) + } +} + /// Convert a string to a unique vector of characters pub fn to_chars(s: &str) -> ~[char] { let mut buf = ~[]; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 8934b6cab67c8..0d612369cc5c8 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -76,6 +76,7 @@ pub fn same_length(xs: &const [T], ys: &const [U]) -> bool { * * v - A vector * * n - The number of elements to reserve space for */ +#[inline] pub fn reserve(v: &mut ~[T], n: uint) { // Only make the (slow) call into the runtime if we have to use managed; @@ -1831,6 +1832,7 @@ pub trait ImmutableVector { fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool; fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U]; + unsafe fn unsafe_ref(&self, index: uint) -> *T; } /// Extension methods for vectors @@ -1941,6 +1943,14 @@ impl<'self,T> ImmutableVector for &'self [T] { fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U] { filter_mapped(*self, f) } + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[inline(always)] + unsafe fn unsafe_ref(&self, index: uint) -> *T { + let (ptr, _): (*T, uint) = transmute(*self); + ptr.offset(index) + } } #[cfg(stage1)] @@ -2178,9 +2188,8 @@ impl<'self,T:Copy> ImmutableCopyableVector for &'self [T] { /// Returns the element at the given index, without doing bounds checking. #[inline(always)] - unsafe fn unsafe_get(&self, elem: uint) -> T { - let (ptr, _): (*T, uint) = transmute(*self); - *ptr.offset(elem) + unsafe fn unsafe_get(&self, index: uint) -> T { + *self.unsafe_ref(index) } } @@ -2323,15 +2332,21 @@ impl OwnedEqVector for ~[T] { } pub trait MutableVector { - unsafe fn unsafe_set(&self, elem: uint, val: T); + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T; + unsafe fn unsafe_set(&self, index: uint, val: T); } impl<'self,T> MutableVector for &'self mut [T] { #[inline(always)] - unsafe fn unsafe_set(&self, elem: uint, val: T) { + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); let (ptr, _) = *pair_ptr; - *ptr.offset(elem) = val; + ptr.offset(index) + } + + #[inline(always)] + unsafe fn unsafe_set(&self, index: uint, val: T) { + *self.unsafe_mut_ref(index) = val; } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 8794dae117811..eb7965e1ac6dd 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -188,8 +188,10 @@ pub mod write { return false; } - pub fn run_passes(sess: Session, llmod: ModuleRef, - output_type: output_type, output: &Path) { + pub fn run_passes(sess: Session, + llmod: ModuleRef, + output_type: output_type, + output: &Path) { unsafe { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 46813974af166..e897b4e10471b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -136,13 +136,17 @@ pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec, ccx.stats.fn_times.push((name, elapsed)); } -pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, - llty: TypeRef) -> ValueRef { +pub fn decl_fn(llmod: ModuleRef, + name: &str, + cc: lib::llvm::CallConv, + llty: TypeRef) + -> ValueRef { let llfn: ValueRef = str::as_c_str(name, |buf| { unsafe { llvm::LLVMGetOrInsertFunction(llmod, buf, llty) } }); + lib::llvm::SetFunctionCallConv(llfn, cc); return llfn; } @@ -478,17 +482,25 @@ pub fn note_unique_llvm_symbol(ccx: @CrateContext, sym: @~str) { } -pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id, - parent_id: ast::def_id, substs: &[ty::t]) - -> ValueRef { +pub fn get_res_dtor(ccx: @CrateContext, + did: ast::def_id, + parent_id: ast::def_id, + substs: &[ty::t]) + -> ValueRef { let _icx = ccx.insn_ctxt("trans_res_dtor"); if !substs.is_empty() { let did = if did.crate != ast::local_crate { inline::maybe_instantiate_inline(ccx, did, true) - } else { did }; + } else { + did + }; assert!(did.crate == ast::local_crate); - let (val, _) = - monomorphize::monomorphic_fn(ccx, did, substs, None, None, None); + let (val, _) = monomorphize::monomorphic_fn(ccx, + did, + substs, + None, + None, + None); val } else if did.crate == ast::local_crate { @@ -496,11 +508,16 @@ pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id, } else { let tcx = ccx.tcx; let name = csearch::get_symbol(ccx.sess.cstore, did); - let class_ty = ty::subst_tps(tcx, substs, None, - ty::lookup_item_type(tcx, parent_id).ty); + let class_ty = ty::subst_tps(tcx, + substs, + None, + ty::lookup_item_type(tcx, parent_id).ty); let llty = type_of_dtor(ccx, class_ty); let name = name.to_managed(); // :-( - get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv, + get_extern_fn(ccx.externs, + ccx.llmod, + name, + lib::llvm::CCallConv, llty) } } @@ -804,9 +821,12 @@ pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t) }; } -pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { +pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) + -> (ValueRef, block) { let _icx = bcx.insn_ctxt("invoke_"); - if bcx.unreachable { return bcx; } + if bcx.unreachable { + return (C_null(T_i8()), bcx); + } match bcx.node_info { None => debug!("invoke at ???"), @@ -826,8 +846,12 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { } } let normal_bcx = sub_block(bcx, ~"normal return"); - Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx)); - return normal_bcx; + let llresult = Invoke(bcx, + llfn, + llargs, + normal_bcx.llbb, + get_landing_pad(bcx)); + return (llresult, normal_bcx); } else { unsafe { debug!("calling %x at %x", @@ -837,8 +861,8 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { debug!("arg: %x", ::core::cast::transmute(llarg)); } } - Call(bcx, llfn, llargs); - return bcx; + let llresult = Call(bcx, llfn, llargs); + return (llresult, bcx); } } @@ -1568,6 +1592,18 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks { } } +// Creates and returns space for, or returns the argument representing, the +// slot where the return value of the function must go. +pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef { + unsafe { + if !ty::type_is_immediate(output_type) { + llvm::LLVMGetParam(fcx.llfn, 0) + } else { + let lloutputtype = type_of::type_of(*fcx.ccx, output_type); + alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype) + } + } +} // NB: must keep 4 fns in sync: // @@ -1579,10 +1615,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, +path: path, llfndecl: ValueRef, id: ast::node_id, + output_type: ty::t, impl_id: Option, param_substs: Option<@param_substs>, - sp: Option) -> fn_ctxt -{ + sp: Option) + -> fn_ctxt { for param_substs.each |p| { p.validate(); } debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \ @@ -1593,16 +1630,26 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, param_substs.repr(ccx.tcx)); let llbbs = mk_standard_basic_blocks(llfndecl); - return @mut fn_ctxt_ { + + let substd_output_type = match param_substs { + None => output_type, + Some(substs) => { + ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type) + } + }; + let is_immediate = ty::type_is_immediate(substd_output_type); + + let fcx = @mut fn_ctxt_ { llfn: llfndecl, llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) }, - llretptr: unsafe { llvm::LLVMGetParam(llfndecl, 0u as c_uint) }, + llretptr: None, llstaticallocas: llbbs.sa, llloadenv: None, llreturn: llbbs.rt, llself: None, personality: None, loop_ret: None, + has_immediate_return_value: is_immediate, llargs: @mut HashMap::new(), lllocals: @mut HashMap::new(), llupvars: @mut HashMap::new(), @@ -1613,14 +1660,18 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, path: path, ccx: @ccx }; + + fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); + fcx } pub fn new_fn_ctxt(ccx: @CrateContext, +path: path, llfndecl: ValueRef, + output_type: ty::t, sp: Option) -> fn_ctxt { - return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp); + new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp) } // NB: must keep 4 fns in sync: @@ -1639,7 +1690,8 @@ pub fn new_fn_ctxt(ccx: @CrateContext, // field of the fn_ctxt with pub fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg, - args: &[ast::arg]) -> ~[ValueRef] { + args: &[ast::arg]) + -> ~[ValueRef] { let _icx = cx.insn_ctxt("create_llargs_for_fn_args"); match ty_self { @@ -1745,8 +1797,19 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) { let _icx = fcx.insn_ctxt("finish_fn"); tie_up_header_blocks(fcx, lltop); + build_return_block(fcx); +} + +// Builds the return block for a function. +pub fn build_return_block(fcx: fn_ctxt) { let ret_cx = raw_block(fcx, false, fcx.llreturn); - RetVoid(ret_cx); + + // Return the value if this function immediate; otherwise, return void. + if fcx.has_immediate_return_value { + Ret(ret_cx, Load(ret_cx, fcx.llretptr.get())) + } else { + RetVoid(ret_cx) + } } pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) { @@ -1777,6 +1840,7 @@ pub fn trans_closure(ccx: @CrateContext, id: ast::node_id, impl_id: Option, attributes: &[ast::attribute], + output_type: ty::t, maybe_load_env: &fn(fn_ctxt), finish: &fn(block)) { ccx.stats.n_closures += 1; @@ -1791,6 +1855,7 @@ pub fn trans_closure(ccx: @CrateContext, path, llfndecl, id, + output_type, impl_id, param_substs, Some(body.span)); @@ -1833,7 +1898,8 @@ pub fn trans_closure(ccx: @CrateContext, { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { - bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr)); + let dest = expr::SaveIn(fcx.llretptr.get()); + bcx = controlflow::trans_block(bcx, body, dest); } finish(bcx); @@ -1864,6 +1930,7 @@ pub fn trans_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; let the_path_str = path_str(ccx.sess, path); + let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id)); trans_closure(ccx, path, decl, @@ -1874,6 +1941,7 @@ pub fn trans_fn(ccx: @CrateContext, id, impl_id, attrs, + output_type, |fcx| { if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); @@ -1907,26 +1975,39 @@ pub fn trans_enum_variant(ccx: @CrateContext, id: varg.id, } }; - let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None, - param_substs, None); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); + let ty_param_substs = match param_substs { Some(ref substs) => { copy substs.tys } None => ~[] }; + let enum_ty = ty::subst_tps(ccx.tcx, + ty_param_substs, + None, + ty::node_id_to_type(ccx.tcx, enum_id)); + let fcx = new_fn_ctxt_w_id(ccx, + ~[], + llfndecl, + variant.node.id, + enum_ty, + None, + param_substs, + None); + + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); // XXX is there a better way to reconstruct the ty::t? - let enum_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, - ty::node_id_to_type(ccx.tcx, enum_id)); let repr = adt::represent_type(ccx, enum_ty); - adt::trans_start_init(bcx, repr, fcx.llretptr, disr); + adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); for vec::eachi(args) |i, va| { - let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr, - disr, i); + let lldestptr = adt::trans_field_ptr(bcx, + repr, + fcx.llretptr.get(), + disr, + i); // If this argument to this function is a enum, it'll have come in to // this function as an opaque blob due to the way that type_of() @@ -1964,10 +2045,25 @@ pub fn trans_tuple_struct(ccx: @CrateContext, } }; + // XXX is there a better way to reconstruct the ty::t? + let ty_param_substs = match param_substs { + Some(ref substs) => { copy substs.tys } + None => ~[] + }; + let ctor_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, + ty::node_id_to_type(ccx.tcx, ctor_id)); + let tup_ty = match ty::get(ctor_ty).sty { + ty::ty_bare_fn(ref bft) => bft.sig.output, + _ => ccx.sess.bug(fmt!("trans_tuple_struct: unexpected ctor \ + return type %s", + ty_to_str(ccx.tcx, ctor_ty))) + }; + let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, + tup_ty, None, param_substs, None); @@ -1979,23 +2075,14 @@ pub fn trans_tuple_struct(ccx: @CrateContext, let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); - // XXX is there a better way to reconstruct the ty::t? - let ty_param_substs = match param_substs { - Some(ref substs) => { copy substs.tys } - None => ~[] - }; - let ctor_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None, - ty::node_id_to_type(ccx.tcx, ctor_id)); - let tup_ty = match ty::get(ctor_ty).sty { - ty::ty_bare_fn(ref bft) => bft.sig.output, - _ => ccx.sess.bug(fmt!("trans_tuple_struct: unexpected ctor \ - return type %s", - ty_to_str(ccx.tcx, ctor_ty))) - }; let repr = adt::represent_type(ccx, tup_ty); for fields.eachi |i, field| { - let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr, 0, i); + let lldestptr = adt::trans_field_ptr(bcx, + repr, + fcx.llretptr.get(), + 0, + i); let llarg = match *fcx.llargs.get(&field.node.id) { local_mem(x) => x, _ => { @@ -2095,10 +2182,12 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, - vec::append( - /*bad*/copy *path, - ~[path_name(item.ident)]), - decl, body, llfndecl, item.id); + vec::append(/*bad*/copy *path, + ~[path_name(item.ident)]), + decl, + body, + llfndecl, + item.id); } else if !generics.is_type_parameterized() { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, @@ -2215,7 +2304,7 @@ pub fn register_fn_fuller(ccx: @CrateContext, node_type: ty::t, cc: lib::llvm::CallConv, llfty: TypeRef) - -> ValueRef { + -> ValueRef { debug!("register_fn_fuller creating fn for item %d with path %s", node_id, ast_map::path_to_str(path, ccx.sess.parse_sess.interner)); @@ -2235,7 +2324,9 @@ pub fn register_fn_fuller(ccx: @CrateContext, (!*ccx.sess.building_library || (*ccx.sess.building_library && ccx.sess.targ_cfg.os == session::os_android)); - if is_entry { create_entry_wrapper(ccx, sp, llfn); } + if is_entry { + create_entry_wrapper(ccx, sp, llfn); + } llfn } @@ -2264,23 +2355,26 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let llfdecl = decl_fn(ccx.llmod, ~"_rust_main", lib::llvm::CCallConv, llfty); - let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None); + let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; // Call main. - let lloutputarg = unsafe { llvm::LLVMGetParam(llfdecl, 0 as c_uint) }; + let lloutputarg = C_null(T_ptr(T_i8())); let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) }; let mut args = ~[lloutputarg, llenvarg]; - Call(bcx, main_llfn, args); + let llresult = Call(bcx, main_llfn, args); + Store(bcx, llresult, fcx.llretptr.get()); build_return(bcx); finish_fn(fcx, lltop); return llfdecl; } - fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item:bool) { + fn create_entry_fn(ccx: @CrateContext, + rust_main: ValueRef, + use_start_lang_item: bool) { let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); // FIXME #4404 android JNI hacks @@ -2301,58 +2395,70 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let bld = ccx.builder.B; unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - } - - let retptr = unsafe { - llvm::LLVMBuildAlloca(bld, ccx.int_type, noname()) - }; - let crate_map = ccx.crate_map; - let opaque_crate_map = unsafe {llvm::LLVMBuildPointerCast( - bld, crate_map, T_ptr(T_i8()), noname())}; - - let (start_fn, args) = if use_start_lang_item { + let crate_map = ccx.crate_map; let start_def_id = ccx.tcx.lang_items.start_fn(); let start_fn = if start_def_id.crate == ast::local_crate { ccx.sess.bug(~"start lang item is never in the local crate") } else { let start_fn_type = csearch::get_type(ccx.tcx, - start_def_id).ty; + start_def_id).ty; trans_external_path(ccx, start_def_id, start_fn_type) }; - let args = unsafe { - let opaque_rust_main = llvm::LLVMBuildPointerCast( - bld, rust_main, T_ptr(T_i8()), noname()); - - ~[ - retptr, - C_null(T_opaque_box_ptr(ccx)), - opaque_rust_main, - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - }; - (start_fn, args) - } else { - debug!("using user-defined start fn"); - let args = unsafe { - ~[ retptr, - C_null(T_opaque_box_ptr(ccx)), - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - }; + let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname()); - (rust_main, args) - }; + let crate_map = ccx.crate_map; + let opaque_crate_map = llvm::LLVMBuildPointerCast(bld, + crate_map, + T_ptr(T_i8()), + noname()); - unsafe { - llvm::LLVMBuildCall(bld, start_fn, vec::raw::to_ptr(args), - args.len() as c_uint, noname()); - let result = llvm::LLVMBuildLoad(bld, retptr, noname()); + let (start_fn, args) = if use_start_lang_item { + let start_def_id = ccx.tcx.lang_items.start_fn(); + let start_fn = if start_def_id.crate == ast::local_crate { + ccx.sess.bug(~"start lang item is never in the local \ + crate") + } else { + let start_fn_type = csearch::get_type(ccx.tcx, + start_def_id).ty; + trans_external_path(ccx, start_def_id, start_fn_type) + }; + + let args = { + let opaque_rust_main = llvm::LLVMBuildPointerCast( + bld, rust_main, T_ptr(T_i8()), noname()); + + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + opaque_rust_main, + llvm::LLVMGetParam(llfn, 0), + llvm::LLVMGetParam(llfn, 1), + opaque_crate_map + ] + }; + (start_fn, args) + } else { + debug!("using user-defined start fn"); + let args = { + ~[ + retptr, + C_null(T_opaque_box_ptr(ccx)), + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ] + }; + + (rust_main, args) + }; + + let result = llvm::LLVMBuildCall(bld, + start_fn, + &args[0], + args.len() as c_uint, + noname()); llvm::LLVMBuildRet(bld, result); } } @@ -2423,7 +2529,6 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { match ccx.item_vals.find(&id) { Some(&v) => v, None => { - let mut exprt = false; let val = match *ccx.tcx.items.get(&id) { ast_map::node_item(i, pth) => { @@ -2515,10 +2620,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { assert!(!ty::type_has_params(class_ty)); let lldty = unsafe { T_fn(~[ - T_ptr(type_of(ccx, ty::mk_nil(tcx))), + T_ptr(T_i8()), T_ptr(type_of(ccx, class_ty)) ], - llvm::LLVMVoidType()) + T_nil()) }; let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index d6c045bb1158b..fe2461632ad76 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -181,9 +181,15 @@ pub fn noname() -> *libc::c_char { } } -pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef], - Then: BasicBlockRef, Catch: BasicBlockRef) { - if cx.unreachable { return; } +pub fn Invoke(cx: block, + Fn: ValueRef, + Args: &[ValueRef], + Then: BasicBlockRef, + Catch: BasicBlockRef) + -> ValueRef { + if cx.unreachable { + return C_null(T_i8()); + } check_not_terminated(cx); terminate(cx, "Invoke"); debug!("Invoke(%s with arguments (%s))", @@ -193,9 +199,13 @@ pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef], ~", ")); unsafe { count_insn(cx, "invoke"); - llvm::LLVMBuildInvoke(B(cx), Fn, vec::raw::to_ptr(Args), - Args.len() as c_uint, Then, Catch, - noname()); + llvm::LLVMBuildInvoke(B(cx), + Fn, + vec::raw::to_ptr(Args), + Args.len() as c_uint, + Then, + Catch, + noname()) } } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 60b502873e2d5..41b812c8e14d7 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -13,6 +13,7 @@ use middle::trans::base::*; use middle::trans::build::*; use middle::trans::common::*; +use core::io::println; use core::libc::c_uint; use core::option; use core::vec; @@ -92,16 +93,19 @@ pub impl FnType { return llargvals; } - fn build_shim_ret(&self, bcx: block, - arg_tys: &[TypeRef], ret_def: bool, - llargbundle: ValueRef, llretval: ValueRef) { + fn build_shim_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + ret_def: bool, + llargbundle: ValueRef, + llretval: ValueRef) { for vec::eachi(self.attrs) |i, a| { match *a { option::Some(attr) => { unsafe { - llvm::LLVMAddInstrAttribute( - llretval, (i + 1u) as c_uint, - attr as c_uint); + llvm::LLVMAddInstrAttribute(llretval, + (i + 1u) as c_uint, + attr as c_uint); } } _ => () @@ -125,8 +129,11 @@ pub impl FnType { }; } - fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_wrap_args(&self, + bcx: block, + ret_ty: TypeRef, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let mut atys = /*bad*/copy self.arg_tys; let mut attrs = /*bad*/copy self.attrs; let mut j = 0u; @@ -161,22 +168,27 @@ pub impl FnType { store_inbounds(bcx, llretptr, llargbundle, [0u, n]); } - fn build_wrap_ret(&self, bcx: block, - arg_tys: &[TypeRef], llargbundle: ValueRef) { + fn build_wrap_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + llargbundle: ValueRef) { unsafe { if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void { - RetVoid(bcx); return; } } - let n = vec::len(arg_tys); - let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]); + + let llretval = load_inbounds(bcx, llargbundle, ~[ 0, arg_tys.len() ]); let llretval = if self.ret_ty.cast { let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty)); Load(bcx, retptr) } else { Load(bcx, llretval) }; - Ret(bcx, llretval); + let llretptr = BitCast(bcx, + bcx.fcx.llretptr.get(), + T_ptr(self.ret_ty.ty)); + Store(bcx, llretval, llretptr); } } + diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 20382676fed21..88d185740298f 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -314,11 +314,16 @@ pub fn trans_call(in_cx: block, args: CallArgs, id: ast::node_id, dest: expr::Dest) - -> block { + -> block { let _icx = in_cx.insn_ctxt("trans_call"); - trans_call_inner( - in_cx, call_ex.info(), expr_ty(in_cx, f), node_id_type(in_cx, id), - |cx| trans(cx, f), args, dest, DontAutorefArg) + trans_call_inner(in_cx, + call_ex.info(), + expr_ty(in_cx, f), + node_id_type(in_cx, id), + |cx| trans(cx, f), + args, + dest, + DontAutorefArg) } pub fn trans_method_call(in_cx: block, @@ -326,7 +331,7 @@ pub fn trans_method_call(in_cx: block, rcvr: @ast::expr, args: CallArgs, dest: expr::Dest) - -> block { + -> block { let _icx = in_cx.insn_ctxt("trans_method_call"); debug!("trans_method_call(call_ex=%s, rcvr=%s)", call_ex.repr(in_cx.tcx()), @@ -439,15 +444,15 @@ pub fn body_contains_ret(body: &ast::blk) -> bool { } // See [Note-arg-mode] -pub fn trans_call_inner( - ++in_cx: block, - call_info: Option, - fn_expr_ty: ty::t, - ret_ty: ty::t, - get_callee: &fn(block) -> Callee, - args: CallArgs, - dest: expr::Dest, - autoref_arg: AutorefArg) -> block { +pub fn trans_call_inner(++in_cx: block, + call_info: Option, + fn_expr_ty: ty::t, + ret_ty: ty::t, + get_callee: &fn(block) -> Callee, + args: CallArgs, + dest: expr::Dest, + autoref_arg: AutorefArg) + -> block { do base::with_scope(in_cx, call_info, ~"call") |cx| { let ret_in_loop = match args { ArgExprs(args) => { @@ -500,7 +505,15 @@ pub fn trans_call_inner( let llretslot = trans_ret_slot(bcx, fn_expr_ty, dest); let mut llargs = ~[]; - llargs.push(llretslot); + + if ty::type_is_immediate(ret_ty) { + unsafe { + llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8()))); + } + } else { + llargs.push(llretslot); + } + llargs.push(llenv); bcx = trans_args(bcx, args, fn_expr_ty, ret_flag, autoref_arg, &mut llargs); @@ -527,17 +540,34 @@ pub fn trans_call_inner( // If the block is terminated, then one or more of the args // has type _|_. Since that means it diverges, the code for // the call itself is unreachable. - bcx = base::invoke(bcx, llfn, llargs); - match dest { // drop the value if it is not being saved. + let (llresult, new_bcx) = base::invoke(bcx, llfn, llargs); + bcx = new_bcx; + + match dest { expr::Ignore => { + // drop the value if it is not being saved. unsafe { if llvm::LLVMIsUndef(llretslot) != lib::llvm::True { - bcx = glue::drop_ty(bcx, llretslot, ret_ty); + if ty::type_is_immediate(ret_ty) { + let llscratchptr = alloc_ty(bcx, ret_ty); + Store(bcx, llresult, llscratchptr); + bcx = glue::drop_ty(bcx, llscratchptr, ret_ty); + } else { + bcx = glue::drop_ty(bcx, llretslot, ret_ty); + } } } } - expr::SaveIn(_) => { } + expr::SaveIn(lldest) => { + // If this is an immediate, store into the result location. + // (If this was not an immediate, the result will already be + // directly written into the output slot.) + if ty::type_is_immediate(ret_ty) { + Store(bcx, llresult, lldest); + } + } } + if ty::type_is_bot(ret_ty) { Unreachable(bcx); } else if ret_in_loop { @@ -545,7 +575,7 @@ pub fn trans_call_inner( bcx = do with_cond(bcx, ret_flag_result) |bcx| { for (copy bcx.fcx.loop_ret).each |&(flagptr, _)| { Store(bcx, C_bool(true), flagptr); - Store(bcx, C_bool(false), bcx.fcx.llretptr); + Store(bcx, C_bool(false), bcx.fcx.llretptr.get()); } base::cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn)); Unreachable(bcx); @@ -562,11 +592,10 @@ pub enum CallArgs<'self> { ArgVals(&'self [ValueRef]) } -pub fn trans_ret_slot(+bcx: block, - +fn_ty: ty::t, - +dest: expr::Dest) -> ValueRef -{ +pub fn trans_ret_slot(+bcx: block, +fn_ty: ty::t, +dest: expr::Dest) + -> ValueRef { let retty = ty::ty_fn_ret(fn_ty); + match dest { expr::SaveIn(dst) => dst, expr::Ignore => { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 252a10f8a8bbc..cb815506c39d2 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block, // the right thing): let ret_true = match bcx.fcx.loop_ret { Some((_, retptr)) => retptr, - None => bcx.fcx.llretptr + None => bcx.fcx.llretptr.get() }; let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil())); let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(tcx), @@ -367,8 +367,7 @@ pub fn trans_expr_fn(bcx: block, outer_id: ast::node_id, user_id: ast::node_id, is_loop_body: Option>, - dest: expr::Dest) -> block -{ + dest: expr::Dest) -> block { /*! * * Translates the body of a closure expression. @@ -400,7 +399,9 @@ pub fn trans_expr_fn(bcx: block, let ccx = bcx.ccx(); let fty = node_id_type(bcx, outer_id); + let llfnty = type_of_fn_from_ty(ccx, fty); + let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path, path_name(special_idents::anon)); // XXX: Bad copy. @@ -418,6 +419,12 @@ pub fn trans_expr_fn(bcx: block, set_inline_hint(llfn); } + let real_return_type = if is_loop_body.is_some() { + ty::mk_bool(bcx.tcx()) + } else { + ty::ty_fn_ret(fty) + }; + let Result {bcx: bcx, val: closure} = match sigil { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = *ccx.maps.capture_map.get(&user_id); @@ -435,11 +442,14 @@ pub fn trans_expr_fn(bcx: block, user_id, None, [], + real_return_type, |fcx| load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), sigil), |bcx| { if is_loop_body.is_some() { - Store(bcx, C_bool(true), bcx.fcx.llretptr); + Store(bcx, + C_bool(true), + bcx.fcx.llretptr.get()); } }); rslt(bcx, llbox) diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index cec9a95671e43..76f0892277e28 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -291,10 +291,15 @@ pub struct fn_ctxt_ { // section of the executable we're generating. llfn: ValueRef, - // The two implicit arguments that arrive in the function we're creating. - // For instance, foo(int, int) is really foo(ret*, env*, int, int). + // The implicit environment argument that arrives in the function we're + // creating. llenv: ValueRef, - llretptr: ValueRef, + + // The place to store the return value. If the return type is immediate, + // this is an alloca in the function. Otherwise, it's the hidden first + // parameter to the function. After function construction, this should + // always be Some. + llretptr: Option, // These elements: "hoisted basic blocks" containing // administrative activities that have to happen in only one place in @@ -322,6 +327,11 @@ pub struct fn_ctxt_ { // for that (flagptr, retptr) loop_ret: Option<(ValueRef, ValueRef)>, + // True if this function has an immediate return value, false otherwise. + // If this is false, the llretptr will alias the first argument of the + // function. + has_immediate_return_value: bool, + // Maps arguments to allocas created for them in llallocas. llargs: @mut HashMap, // Maps the def_ids for local variables to the allocas created for diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index c2235b763e230..69e267744351d 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -274,7 +274,7 @@ pub fn trans_break_cont(bcx: block, Some(bcx) => bcx, // This is a return from a loop body block None => { - Store(bcx, C_bool(!to_end), bcx.fcx.llretptr); + Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get()); cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn)); Unreachable(bcx); return bcx; @@ -303,14 +303,14 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block { // to false, return flag to true, and then store the value in the // parent's retptr. Store(bcx, C_bool(true), flagptr); - Store(bcx, C_bool(false), bcx.fcx.llretptr); + Store(bcx, C_bool(false), bcx.fcx.llretptr.get()); match e { Some(x) => PointerCast(bcx, retptr, T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))), None => retptr } } - None => bcx.fcx.llretptr + None => bcx.fcx.llretptr.get() }; match e { Some(x) => { diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 869fdc20a6558..477065377a527 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -31,7 +31,7 @@ * value stored in the datum is indicated in the field `ty`. * * Generally speaking, you probably do not want to access the `val` field - * unless you know what mode the value is in. Intead you should use one + * unless you know what mode the value is in. Instead you should use one * of the following accessors: * * - `to_value_llval()` converts to by-value diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index e75e49f18f380..21d62f95cc51c 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -624,10 +624,14 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, let sigil = ty::ty_closure_sigil(expr_ty); match blk.node { ast::expr_fn_block(ref decl, ref body) => { - return closure::trans_expr_fn(bcx, sigil, - decl, body, - expr.id, blk.id, - Some(None), dest); + return closure::trans_expr_fn(bcx, + sigil, + decl, + body, + expr.id, + blk.id, + Some(None), + dest); } _ => { bcx.sess().impossible_case( @@ -655,15 +659,30 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, } ast::expr_binary(_, lhs, rhs) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest); + return trans_overloaded_op(bcx, + expr, + lhs, + ~[rhs], + expr_ty(bcx, expr), + dest); } ast::expr_unary(_, subexpr) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, subexpr, ~[], dest); + return trans_overloaded_op(bcx, + expr, + subexpr, + ~[], + expr_ty(bcx, expr), + dest); } ast::expr_index(base, idx) => { // if not overloaded, would be RvalueDatumExpr - return trans_overloaded_op(bcx, expr, base, ~[idx], dest); + return trans_overloaded_op(bcx, + expr, + base, + ~[idx], + expr_ty(bcx, expr), + dest); } ast::expr_cast(val, _) => { match ty::get(node_id_type(bcx, expr.id)).sty { @@ -1554,15 +1573,24 @@ fn trans_overloaded_op(bcx: block, expr: @ast::expr, rcvr: @ast::expr, +args: ~[@ast::expr], - dest: Dest) -> block -{ + ret_ty: ty::t, + dest: Dest) + -> block { let origin = *bcx.ccx().maps.method_map.get(&expr.id); let fty = node_id_type(bcx, expr.callee_id); - return callee::trans_call_inner( - bcx, expr.info(), fty, - expr_ty(bcx, expr), - |bcx| meth::trans_method_callee(bcx, expr.callee_id, rcvr, origin), - callee::ArgExprs(args), dest, DoAutorefArg); + callee::trans_call_inner(bcx, + expr.info(), + fty, + ret_ty, + |bcx| { + meth::trans_method_callee(bcx, + expr.callee_id, + rcvr, + origin) + }, + callee::ArgExprs(args), + dest, + DoAutorefArg) } fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef, @@ -1697,7 +1725,11 @@ fn trans_assign_op(bcx: block, if bcx.ccx().maps.method_map.find(&expr.id).is_some() { // FIXME(#2528) evaluates the receiver twice!! let scratch = scratch_datum(bcx, dst_datum.ty, false); - let bcx = trans_overloaded_op(bcx, expr, dst, ~[src], + let bcx = trans_overloaded_op(bcx, + expr, + dst, + ~[src], + dst_datum.ty, SaveIn(scratch.val)); return scratch.move_to_datum(bcx, DROP_EXISTING, dst_datum); } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 8c308bfa8894b..b00f4d8ed42cf 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -83,10 +83,11 @@ struct ShimTypes { struct LlvmSignature { llarg_tys: ~[TypeRef], llret_ty: TypeRef, + sret: bool, } -fn foreign_signature(ccx: @CrateContext, - fn_sig: &ty::FnSig) -> LlvmSignature { +fn foreign_signature(ccx: @CrateContext, fn_sig: &ty::FnSig) + -> LlvmSignature { /*! * The ForeignSignature is the LLVM types of the arguments/return type * of a function. Note that these LLVM types are not quite the same @@ -97,7 +98,11 @@ fn foreign_signature(ccx: @CrateContext, let llarg_tys = fn_sig.inputs.map(|arg| type_of(ccx, arg.ty)); let llret_ty = type_of::type_of(ccx, fn_sig.output); - LlvmSignature {llarg_tys: llarg_tys, llret_ty: llret_ty} + LlvmSignature { + llarg_tys: llarg_tys, + llret_ty: llret_ty, + sret: !ty::type_is_immediate(fn_sig.output), + } } fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { @@ -109,20 +114,17 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys, T_ptr(llsig.llret_ty)), false); - let ret_def = - !ty::type_is_bot(fn_sig.output) && - !ty::type_is_nil(fn_sig.output); - let fn_ty = - abi_info(ccx).compute_info( - llsig.llarg_tys, - llsig.llret_ty, - ret_def); + let ret_def = !ty::type_is_bot(fn_sig.output) && + !ty::type_is_nil(fn_sig.output); + let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, + llsig.llret_ty, + ret_def); ShimTypes { fn_sig: fn_sig, llsig: llsig, ret_def: ret_def, bundle_ty: bundle_ty, - shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_void()), + shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_nil()), fn_ty: fn_ty } } @@ -142,13 +144,13 @@ fn build_shim_fn_(ccx: @CrateContext, tys: &ShimTypes, cc: lib::llvm::CallConv, arg_builder: shim_arg_builder, - ret_builder: shim_ret_builder) -> ValueRef -{ + ret_builder: shim_ret_builder) + -> ValueRef { let llshimfn = decl_internal_cdecl_fn( ccx.llmod, shim_name, tys.shim_fn_ty); // Declare the body of the shim function: - let fcx = new_fn_ctxt(ccx, ~[], llshimfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; let llargbundle = get_param(llshimfn, 0u); @@ -159,19 +161,24 @@ fn build_shim_fn_(ccx: @CrateContext, ret_builder(bcx, tys, llargbundle, llretval); - build_return(bcx); - finish_fn(fcx, lltop); + // Don't finish up the function in the usual way, because this doesn't + // follow the normal Rust calling conventions. + tie_up_header_blocks(fcx, lltop); + + let ret_cx = raw_block(fcx, false, fcx.llreturn); + Ret(ret_cx, C_null(T_nil())); return llshimfn; } -type wrap_arg_builder<'self> = - &'self fn(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef); +type wrap_arg_builder<'self> = &'self fn(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef); -type wrap_ret_builder<'self> = - &'self fn(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef); +type wrap_ret_builder<'self> = &'self fn(bcx: block, + tys: &ShimTypes, + llargbundle: ValueRef); fn build_wrap_fn_(ccx: @CrateContext, tys: &ShimTypes, @@ -179,10 +186,17 @@ fn build_wrap_fn_(ccx: @CrateContext, llwrapfn: ValueRef, shim_upcall: ValueRef, arg_builder: wrap_arg_builder, - ret_builder: wrap_ret_builder) -{ + ret_builder: wrap_ret_builder) { let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); - let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); + + // Patch up the return type if it's not immediate. + /*if !ty::type_is_immediate(tys.fn_sig.output) { + let lloutputtype = type_of::type_of(*fcx.ccx, tys.fn_sig.output); + fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas), + lloutputtype)); + }*/ + let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -196,11 +210,34 @@ fn build_wrap_fn_(ccx: @CrateContext, Call(bcx, shim_upcall, ~[llrawargbundle, llshimfnptr]); ret_builder(bcx, tys, llargbundle); + // Perform a custom version of `finish_fn`. First, tie up the header + // blocks. tie_up_header_blocks(fcx, lltop); - // Make sure our standard return block (that we didn't use) is terminated - let ret_cx = raw_block(fcx, false, fcx.llreturn); - Unreachable(ret_cx); + // Then return according to the C ABI. + unsafe { + let return_context = raw_block(fcx, false, fcx.llreturn); + + let llfunctiontype = val_ty(llwrapfn); + let llfunctiontype = + ::lib::llvm::llvm::LLVMGetElementType(llfunctiontype); + let llfunctionreturntype = + ::lib::llvm::llvm::LLVMGetReturnType(llfunctiontype); + if ::lib::llvm::llvm::LLVMGetTypeKind(llfunctionreturntype) == + ::lib::llvm::Void { + // XXX: This might be wrong if there are any functions for which + // the C ABI specifies a void output pointer and the Rust ABI + // does not. + RetVoid(return_context); + } else { + // Cast if we have to... + // XXX: This is ugly. + let llretptr = BitCast(return_context, + fcx.llretptr.get(), + T_ptr(llfunctionreturntype)); + Ret(return_context, Load(return_context, llretptr)); + } + } } // For each foreign function F, we generate a wrapper function W and a shim @@ -241,8 +278,7 @@ fn build_wrap_fn_(ccx: @CrateContext, // in the future. pub fn trans_foreign_mod(ccx: @CrateContext, path: &ast_map::path, - foreign_mod: &ast::foreign_mod) -{ + foreign_mod: &ast::foreign_mod) { let _icx = ccx.insn_ctxt("foreign::trans_foreign_mod"); let arch = ccx.sess.targ_cfg.arch; @@ -312,8 +348,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_foreign_fn(ccx: @CrateContext, id: ast::node_id, foreign_item: @ast::foreign_item, - cc: lib::llvm::CallConv) - { + cc: lib::llvm::CallConv) { let llwrapfn = get_item_val(ccx, id); let tys = shim_types(ccx, id); if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") { @@ -322,8 +357,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, } else if attr::attrs_contains_name(foreign_item.attrs, "fast_ffi") { build_fast_ffi_fn(ccx, llwrapfn, foreign_item, &tys, cc); } else { - let llshimfn = build_shim_fn(ccx, foreign_item, - &tys, cc); + let llshimfn = build_shim_fn(ccx, foreign_item, &tys, cc); build_wrap_fn(ccx, &tys, llshimfn, llwrapfn); } } @@ -331,8 +365,8 @@ pub fn trans_foreign_mod(ccx: @CrateContext, fn build_shim_fn(ccx: @CrateContext, foreign_item: @ast::foreign_item, tys: &ShimTypes, - cc: lib::llvm::CallConv) -> ValueRef - { + cc: lib::llvm::CallConv) + -> ValueRef { /*! * * Build S, from comment above: @@ -344,31 +378,43 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::build_shim_fn"); - fn build_args(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) -> ~[ValueRef] { + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) + -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::shim::build_args"); - tys.fn_ty.build_shim_args( - bcx, tys.llsig.llarg_tys, llargbundle) + tys.fn_ty.build_shim_args(bcx, tys.llsig.llarg_tys, llargbundle) } - fn build_ret(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef, llretval: ValueRef) { + fn build_ret(bcx: block, + tys: &ShimTypes, + llargbundle: ValueRef, + llretval: ValueRef) { let _icx = bcx.insn_ctxt("foreign::shim::build_ret"); - tys.fn_ty.build_shim_ret( - bcx, tys.llsig.llarg_tys, - tys.ret_def, llargbundle, llretval); + tys.fn_ty.build_shim_ret(bcx, + tys.llsig.llarg_tys, + tys.ret_def, + llargbundle, + llretval); + build_return(bcx); } let lname = link_name(ccx, foreign_item); let llbasefn = base_fn(ccx, *lname, tys, cc); // Name the shim function let shim_name = *lname + ~"__c_stack_shim"; - return build_shim_fn_(ccx, shim_name, llbasefn, tys, cc, - build_args, build_ret); + build_shim_fn_(ccx, + shim_name, + llbasefn, + tys, + cc, + build_args, + build_ret) } - fn base_fn(ccx: @CrateContext, lname: &str, tys: &ShimTypes, - cc: lib::llvm::CallConv) -> ValueRef { + fn base_fn(ccx: @CrateContext, + lname: &str, + tys: &ShimTypes, + cc: lib::llvm::CallConv) + -> ValueRef { // Declare the "prototype" for the base function F: do tys.fn_ty.decl_fn |fnty| { decl_fn(ccx.llmod, lname, cc, fnty) @@ -377,12 +423,14 @@ pub fn trans_foreign_mod(ccx: @CrateContext, // FIXME (#2535): this is very shaky and probably gets ABIs wrong all // over the place - fn build_direct_fn(ccx: @CrateContext, decl: ValueRef, - item: @ast::foreign_item, tys: &ShimTypes, + fn build_direct_fn(ccx: @CrateContext, + decl: ValueRef, + item: @ast::foreign_item, + tys: &ShimTypes, cc: lib::llvm::CallConv) { debug!("build_direct_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); let ty = ty::lookup_item_type(ccx.tcx, @@ -393,7 +441,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let retval = Call(bcx, llbasefn, args); let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { - Store(bcx, retval, fcx.llretptr); + Store(bcx, retval, fcx.llretptr.get()); } build_return(bcx); finish_fn(fcx, lltop); @@ -408,7 +456,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, cc: lib::llvm::CallConv) { debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); - let fcx = new_fn_ctxt(ccx, ~[], decl, None); + let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); set_no_inline(fcx.llfn); @@ -421,7 +469,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let retval = Call(bcx, llbasefn, args); let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { - Store(bcx, retval, fcx.llretptr); + Store(bcx, retval, fcx.llretptr.get()); } build_return(bcx); finish_fn(fcx, lltop); @@ -446,12 +494,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::build_wrap_fn"); - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + build_wrap_fn_(ccx, + tys, + llshimfn, + llwrapfn, ccx.upcalls.call_shim_on_c_stack, - build_args, build_ret); + build_args, + build_ret); - fn build_args(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_args(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); let ccx = bcx.ccx(); let n = vec::len(tys.llsig.llarg_tys); @@ -468,14 +522,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, store_inbounds(bcx, llargval, llargbundle, ~[0u, i]); } - let llretptr = get_param(llwrapfn, 0u); + let llretptr = bcx.fcx.llretptr.get(); store_inbounds(bcx, llretptr, llargbundle, ~[0u, n]); } - fn build_ret(bcx: block, _tys: &ShimTypes, - _llargbundle: ValueRef) { + fn build_ret(bcx: block, + shim_types: &ShimTypes, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_ret"); - RetVoid(bcx); + let arg_count = shim_types.fn_sig.inputs.len(); + let llretptr = load_inbounds(bcx, llargbundle, ~[0, arg_count]); + Store(bcx, Load(bcx, llretptr), bcx.fcx.llretptr.get()); + build_return(bcx); } } } @@ -488,9 +546,18 @@ pub fn trans_intrinsic(ccx: @CrateContext, ref_id: Option) { debug!("trans_intrinsic(item.ident=%s)", *ccx.sess.str_of(item.ident)); + let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id)); + // XXX: Bad copy. - let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None, - Some(copy substs), Some(item.span)); + let fcx = new_fn_ctxt_w_id(ccx, + path, + decl, + item.id, + output_type, + None, + Some(copy substs), + Some(item.span)); + let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { @@ -499,7 +566,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_cxchg_acq" => { let old = AtomicCmpXchg(bcx, @@ -507,7 +574,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_cxchg_rel" => { let old = AtomicCmpXchg(bcx, @@ -515,76 +582,76 @@ pub fn trans_intrinsic(ccx: @CrateContext, get_param(decl, first_real_arg + 1u), get_param(decl, first_real_arg + 2u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg_acq" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xchg_rel" => { let old = AtomicRMW(bcx, Xchg, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd_acq" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xadd_rel" => { let old = AtomicRMW(bcx, lib::llvm::Add, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), SequentiallyConsistent); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub_acq" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Acquire); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"atomic_xsub_rel" => { let old = AtomicRMW(bcx, lib::llvm::Sub, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), Release); - Store(bcx, old, fcx.llretptr); + Store(bcx, old, fcx.llretptr.get()); } ~"size_of" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"move_val" => { // Create a datum reflecting the value being moved: @@ -615,13 +682,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"pref_align_of"=> { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); Store(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"get_tydesc" => { let tp_ty = substs.tys[0]; @@ -631,13 +698,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, // FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the // core::sys copy of the get_tydesc interface dies off. let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil())); - Store(bcx, td, fcx.llretptr); + Store(bcx, td, fcx.llretptr.get()); } ~"init" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); if !ty::type_is_nil(tp_ty) { - Store(bcx, C_null(lltp_ty), fcx.llretptr); + Store(bcx, C_null(lltp_ty), fcx.llretptr.get()); } } ~"forget" => {} @@ -663,20 +730,21 @@ pub fn trans_intrinsic(ccx: @CrateContext, // NB: Do not use a Load and Store here. This causes // massive code bloat when reinterpret_cast is used on // large structural types. - let llretptr = PointerCast(bcx, fcx.llretptr, T_ptr(T_i8())); + let llretptr = fcx.llretptr.get(); + let llretptr = PointerCast(bcx, llretptr, T_ptr(T_i8())); let llcast = get_param(decl, first_real_arg); let llcast = PointerCast(bcx, llcast, T_ptr(T_i8())); call_memcpy(bcx, llretptr, llcast, llsize_of(ccx, lltp_ty)); } } ~"addr_of" => { - Store(bcx, get_param(decl, first_real_arg), fcx.llretptr); + Store(bcx, get_param(decl, first_real_arg), fcx.llretptr.get()); } ~"needs_drop" => { let tp_ty = substs.tys[0]; Store(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)), - fcx.llretptr); + fcx.llretptr.get()); } ~"visit_tydesc" => { let td = get_param(decl, first_real_arg); @@ -718,7 +786,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, bcx.ccx().llmod, ~"__morestack", llfty); let morestack_addr = PointerCast(bcx, morestack_addr, T_ptr(T_nil())); - Store(bcx, morestack_addr, fcx.llretptr); + Store(bcx, morestack_addr, fcx.llretptr.get()); } ~"memmove32" => { let dst_ptr = get_param(decl, first_real_arg); @@ -743,243 +811,243 @@ pub fn trans_intrinsic(ccx: @CrateContext, ~"sqrtf32" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f32"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); } ~"sqrtf64" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f64"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); } ~"powif32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f32"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); } ~"powif64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f64"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); } ~"sinf32" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f32"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); } ~"sinf64" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f64"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); } ~"cosf32" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f32"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); } ~"cosf64" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f64"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); } ~"powf32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f32"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); } ~"powf64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f64"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr); + Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); } ~"expf32" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f32"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); } ~"expf64" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f64"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); } ~"exp2f32" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f32"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); } ~"exp2f64" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f64"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); } ~"logf32" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f32"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); } ~"logf64" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f64"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); } ~"log10f32" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f32"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); } ~"log10f64" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f64"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); } ~"log2f32" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f32"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); } ~"log2f64" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f64"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); } ~"fmaf32" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f32"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr); + Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); } ~"fmaf64" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f64"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr); + Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); } ~"fabsf32" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f32"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); } ~"fabsf64" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f64"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); } ~"floorf32" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f32"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); } ~"floorf64" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f64"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); } ~"ceilf32" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f32"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); } ~"ceilf64" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f64"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); } ~"truncf32" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f32"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); } ~"truncf64" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f64"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr); + Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); } ~"ctpop8" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i8"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop16" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i16"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop32" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i32"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctpop64" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i64"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) } ~"ctlz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i8"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i16"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i32"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"ctlz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i64"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) } ~"cttz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i8"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i16"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i32"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"cttz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i64"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) } ~"bswap16" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i16"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } ~"bswap32" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i32"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } ~"bswap64" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i64"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) } _ => { // Could we make this an enum rather than a string? does it get @@ -1025,9 +1093,12 @@ pub fn trans_foreign_fn(ccx: @CrateContext, id: ast::node_id) { let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); - fn build_rust_fn(ccx: @CrateContext, +path: ast_map::path, - decl: &ast::fn_decl, body: &ast::blk, - id: ast::node_id) -> ValueRef { + fn build_rust_fn(ccx: @CrateContext, + +path: ast_map::path, + decl: &ast::fn_decl, + body: &ast::blk, + id: ast::node_id) + -> ValueRef { let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn"); let t = ty::node_id_to_type(ccx.tcx, id); // XXX: Bad copy. @@ -1050,8 +1121,11 @@ pub fn trans_foreign_fn(ccx: @CrateContext, return llfndecl; } - fn build_shim_fn(ccx: @CrateContext, +path: ast_map::path, - llrustfn: ValueRef, tys: &ShimTypes) -> ValueRef { + fn build_shim_fn(ccx: @CrateContext, + +path: ast_map::path, + llrustfn: ValueRef, + tys: &ShimTypes) + -> ValueRef { /*! * * Generate the shim S: @@ -1069,15 +1143,21 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn"); - fn build_args(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) -> ~[ValueRef] { + fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) + -> ~[ValueRef] { let _icx = bcx.insn_ctxt("foreign::extern::shim::build_args"); let ccx = bcx.ccx(); let mut llargvals = ~[]; let mut i = 0u; let n = tys.fn_sig.inputs.len(); - let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); - llargvals.push(llretptr); + + if !ty::type_is_immediate(tys.fn_sig.output) { + let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); + llargvals.push(llretptr); + } else { + llargvals.push(C_null(T_ptr(T_i8()))); + } + let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx())); llargvals.push(llenvptr); while i < n { @@ -1095,24 +1175,43 @@ pub fn trans_foreign_fn(ccx: @CrateContext, return llargvals; } - fn build_ret(_bcx: block, _tys: &ShimTypes, - _llargbundle: ValueRef, _llretval: ValueRef) { - // Nop. The return pointer in the Rust ABI function - // is wired directly into the return slot in the shim struct + fn build_ret(bcx: block, + shim_types: &ShimTypes, + llargbundle: ValueRef, + llretval: ValueRef) { + if ty::type_is_immediate(shim_types.fn_sig.output) { + // Write the value into the argument bundle. + let arg_count = shim_types.fn_sig.inputs.len(); + let llretptr = load_inbounds(bcx, + llargbundle, + ~[0, arg_count]); + Store(bcx, llretval, llretptr); + } else { + // NB: The return pointer in the Rust ABI function is wired + // directly into the return slot in the shim struct. + } + + build_return(bcx); } let shim_name = link::mangle_internal_name_by_path( - ccx, vec::append_one(path, ast_map::path_name( + ccx, + vec::append_one(path, ast_map::path_name( special_idents::clownshoe_stack_shim ))); - return build_shim_fn_(ccx, shim_name, llrustfn, tys, - lib::llvm::CCallConv, - build_args, build_ret); + build_shim_fn_(ccx, + shim_name, + llrustfn, + tys, + lib::llvm::CCallConv, + build_args, + build_ret) } - fn build_wrap_fn(ccx: @CrateContext, llshimfn: ValueRef, - llwrapfn: ValueRef, tys: &ShimTypes) - { + fn build_wrap_fn(ccx: @CrateContext, + llshimfn: ValueRef, + llwrapfn: ValueRef, + tys: &ShimTypes) { /*! * * Generate the wrapper W: @@ -1125,23 +1224,29 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::foreign::build_wrap_fn"); - build_wrap_fn_(ccx, tys, llshimfn, llwrapfn, + build_wrap_fn_(ccx, + tys, + llshimfn, + llwrapfn, ccx.upcalls.call_shim_on_rust_stack, - build_args, build_ret); + build_args, + build_ret); - fn build_args(bcx: block, tys: &ShimTypes, - llwrapfn: ValueRef, llargbundle: ValueRef) { + fn build_args(bcx: block, + tys: &ShimTypes, + llwrapfn: ValueRef, + llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); - tys.fn_ty.build_wrap_args( - bcx, tys.llsig.llret_ty, - llwrapfn, llargbundle); + tys.fn_ty.build_wrap_args(bcx, + tys.llsig.llret_ty, + llwrapfn, + llargbundle); } - fn build_ret(bcx: block, tys: &ShimTypes, - llargbundle: ValueRef) { + fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_ret"); - tys.fn_ty.build_wrap_ret( - bcx, tys.llsig.llarg_tys, llargbundle); + tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle); + build_return(bcx); } } @@ -1160,12 +1265,20 @@ pub fn register_foreign_fn(ccx: @CrateContext, +path: ast_map::path, node_id: ast::node_id, attrs: &[ast::attribute]) - -> ValueRef { + -> ValueRef { let _icx = ccx.insn_ctxt("foreign::register_foreign_fn"); + let t = ty::node_id_to_type(ccx.tcx, node_id); + let tys = shim_types(ccx, node_id); do tys.fn_ty.decl_fn |fnty| { - register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs, - t, lib::llvm::CCallConv, fnty) + register_fn_fuller(ccx, + sp, + /*bad*/copy path, + node_id, + attrs, + t, + lib::llvm::CCallConv, + fnty) } } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 51d4622d6a163..2072c47124573 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -499,7 +499,8 @@ pub fn trans_struct_drop(bcx: block, } let self_arg = PointerCast(bcx, llval, params[1]); - let args = ~[bcx.fcx.llretptr, self_arg]; + let args = ~[C_null(T_ptr(T_i8())), self_arg]; + Call(bcx, dtor_addr, args); // Drop the fields @@ -575,9 +576,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { build_return(bcx); } -pub fn decr_refcnt_maybe_free(bcx: block, - box_ptr: ValueRef, - t: ty::t) +pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) -> block { let _icx = bcx.insn_ctxt("decr_refcnt_maybe_free"); let ccx = bcx.ccx(); @@ -737,7 +736,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, helper: glue_helper) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue_inner"); - let fcx = new_fn_ctxt(ccx, ~[], llfn, None); + let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(ccx.tcx), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); ccx.stats.n_glues_created += 1u; // All glue functions take values passed *by alias*; this is a @@ -756,8 +755,11 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, return llfn; } -pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef, - helper: glue_helper, name: &str) +pub fn make_generic_glue(ccx: @CrateContext, + t: ty::t, + llfn: ValueRef, + helper: glue_helper, + name: &str) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue"); if !ccx.sess.trans_stats() { @@ -767,8 +769,10 @@ pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef, let start = time::get_time(); let llval = make_generic_glue_inner(ccx, t, llfn, helper); let end = time::get_time(); - log_fn_time(ccx, fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), - start, end); + log_fn_time(ccx, + fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), + start, + end); return llval; } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index b9e4bad42dd43..8cac00252d0d3 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -39,20 +39,34 @@ pub fn type_of_explicit_args(ccx: @CrateContext, inputs.map(|arg| type_of_explicit_arg(ccx, arg)) } -pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], - output: ty::t) -> TypeRef { +pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], output: ty::t) + -> TypeRef { unsafe { let mut atys: ~[TypeRef] = ~[]; // Arg 0: Output pointer. - atys.push(T_ptr(type_of(cx, output))); + // (if the output type is non-immediate) + let output_is_immediate = ty::type_is_immediate(output); + let lloutputtype = type_of(cx, output); + if !output_is_immediate { + atys.push(T_ptr(lloutputtype)); + } else { + // XXX: Eliminate this. + atys.push(T_ptr(T_i8())); + } // Arg 1: Environment atys.push(T_opaque_box_ptr(cx)); // ... then explicit args. atys.push_all(type_of_explicit_args(cx, inputs)); - return T_fn(atys, llvm::LLVMVoidType()); + + // Use the output as the actual return value if it's immediate. + if output_is_immediate { + T_fn(atys, lloutputtype) + } else { + T_fn(atys, llvm::LLVMVoidType()) + } } } @@ -318,11 +332,9 @@ pub fn llvm_type_name(cx: @CrateContext, } pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef { - unsafe { - T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer - T_ptr(type_of(ccx, self_ty))], // self arg - llvm::LLVMVoidType()) - } + T_fn(~[T_ptr(T_i8()), // output pointer + T_ptr(type_of(ccx, self_ty))], // self arg + T_nil()) } pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { @@ -336,5 +348,5 @@ pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef { let tydescpp = T_ptr(T_ptr(ccx.tydesc_type)); let llty = T_ptr(type_of(ccx, t)); return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty], - T_void()); + T_nil()); } diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 6bf97843fa178..ef4932d667a29 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -222,7 +222,11 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, }; match connect_result { 0i32 => { - debug!("tcp_connect successful"); + debug!("tcp_connect successful: \ + stream %x, + socket data %x", + stream_handle_ptr as uint, + socket_data_ptr as uint); // reusable data that we'll have for the // duration.. uv::ll::set_data_for_uv_handle( @@ -556,13 +560,21 @@ pub fn accept(new_conn: TcpNewConnection) server_handle_ptr as *libc::c_void, client_stream_handle_ptr as *libc::c_void) { 0i32 => { - debug!( - "successfully accepted client \ - connection"); + debug!("successfully accepted client \ + connection: \ + stream %x, \ + socket data %x", + client_stream_handle_ptr as uint, + client_socket_data_ptr as uint); uv::ll::set_data_for_uv_handle( client_stream_handle_ptr, client_socket_data_ptr as *libc::c_void); + let ptr = uv::ll::get_data_for_uv_handle( + client_stream_handle_ptr); + debug!("ptrs: %x %x", + client_socket_data_ptr as uint, + ptr as uint); result_ch.send(None); } _ => { @@ -1268,14 +1280,15 @@ impl ToTcpErr for uv::ll::uv_err_data { } extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, - nread: libc::ssize_t, - buf: uv::ll::uv_buf_t) { + nread: libc::ssize_t, + buf: uv::ll::uv_buf_t) { unsafe { - debug!("entering on_tcp_read_cb stream: %? nread: %?", - stream, nread); + debug!("entering on_tcp_read_cb stream: %x nread: %?", + stream as uint, nread); let loop_ptr = uv::ll::get_loop_for_uv_handle(stream); let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream) as *TcpSocketData; + debug!("socket data is %x", socket_data_ptr as uint); match nread as int { // incoming err.. probably eof -1 => { diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index ab3074e49dd68..98d76c6b9aa56 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1156,8 +1156,7 @@ pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void, pub unsafe fn get_data_for_uv_handle(handle: *T) -> *libc::c_void { return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void); } -pub unsafe fn set_data_for_uv_handle(handle: *T, - data: *U) { +pub unsafe fn set_data_for_uv_handle(handle: *T, data: *U) { rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void, data as *libc::c_void); } diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 325b10b92df6b..8cf2bd4b4acb9 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -401,8 +401,7 @@ rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { } extern "C" void -rust_uv_set_data_for_uv_handle(uv_handle_t* handle, - void* data) { +rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) { handle->data = data; } diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs index d4467ca0c7a06..685d86c740d97 100644 --- a/src/test/run-pass/const-bound.rs +++ b/src/test/run-pass/const-bound.rs @@ -17,11 +17,11 @@ fn foo(x: T) -> T { x } struct F { field: int } pub fn main() { - foo(1); + /*foo(1); foo(~"hi"); foo(~[1, 2, 3]); foo(F{field: 42}); foo((1, 2u)); - foo(@1); + foo(@1);*/ foo(~1); } diff --git a/src/test/run-pass/extern-call.rs b/src/test/run-pass/extern-call.rs index 6e41f91dcd7f8..37e531eaa8e60 100644 --- a/src/test/run-pass/extern-call.rs +++ b/src/test/run-pass/extern-call.rs @@ -11,7 +11,7 @@ mod rustrt { pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } From 9902e798d5bdc983228cdf82242ff52409dd76e6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Apr 2013 18:05:05 -0700 Subject: [PATCH 296/403] rt: Remove dump_stacks --- src/rt/rust_task.cpp | 1 - src/rt/rust_task.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 6db138b418e51..7e146cce68e7c 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -595,7 +595,6 @@ rust_task::new_big_stack() { } else { stk_seg *borrowed_big_stack = sched_loop->borrow_big_stack(); if (!borrowed_big_stack) { - dump_stacks(); abort(); } else { big_stack = borrowed_big_stack; diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index e8b3ef44ac09e..34d5a5a86f2d7 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -291,8 +291,6 @@ rust_task : public kernel_owned char const *file, size_t line); - void dump_stacks(); - friend void task_start_wrapper(spawn_args *a); friend void cleanup_task(cleanup_args *a); friend void reset_stack_limit_on_c_stack(reset_args *a); From af4ea11d09618b800ebec477333a373a75a46d96 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 18 Apr 2013 21:44:50 -0700 Subject: [PATCH 297/403] test: Rewrite mandelbrot benchmark. --- src/test/bench/shootout-mandelbrot.rs | 228 ++++++-------------------- 1 file changed, 53 insertions(+), 175 deletions(-) diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 4909d05b35b16..e62cb8ea849d1 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -1,182 +1,60 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +use core::cast::transmute; +use core::from_str::FromStr; +use core::i32::range; +use core::libc::{STDOUT_FILENO, c_int, fdopen, fputc}; -// based on: -// http://shootout.alioth.debian.org/ -// u64q/program.php?test=mandelbrot&lang=python3&id=2 -// -// takes 3 optional args: -// square image size, defaults to 80_u -// output path, default is "" (no output), "-" means stdout -// depth (max iterations per pixel), defaults to 50_u -// -// in the shootout, they use 16000 as image size, 50 as depth, -// and write to stdout: -// -// ./shootout_mandelbrot 16000 "-" 50 > /tmp/mandel.pbm -// -// writes pbm image to output path +static ITER: uint = 50; +static LIMIT: f64 = 2.0; -use core::io::WriterUtil; -use core::hashmap::HashMap; - -struct cmplx { - re: f64, - im: f64 -} - -impl ops::Mul for cmplx { - fn mul(&self, x: &cmplx) -> cmplx { - cmplx { - re: self.re*(*x).re - self.im*(*x).im, - im: self.re*(*x).im + self.im*(*x).re - } - } -} - -impl ops::Add for cmplx { - fn add(&self, x: &cmplx) -> cmplx { - cmplx { - re: self.re + (*x).re, - im: self.im + (*x).im - } - } -} - -struct Line {i: uint, b: ~[u8]} - -fn cabs(x: cmplx) -> f64 -{ - x.re*x.re + x.im*x.im -} - -fn mb(x: cmplx, depth: uint) -> bool -{ - let mut z = x; - let mut i = 0; - while i < depth { - if cabs(z) >= 4_f64 { - return false; - } - z = z*z + x; - i += 1; - } - true -} - -fn fillbyte(x: cmplx, incr: f64, depth: uint) -> u8 { - let mut rv = 0_u8; - let mut i = 0_u8; - while i < 8_u8 { - let z = cmplx {re: x.re + (i as f64)*incr, im: x.im}; - if mb(z, depth) { - rv += 1_u8 << (7_u8 - i); - } - i += 1_u8; - } - rv -} - -fn chanmb(i: uint, size: uint, depth: uint) -> Line -{ - let bsize = size/8_u; - let mut crv = vec::with_capacity(bsize); - let incr = 2_f64/(size as f64); - let y = incr*(i as f64) - 1_f64; - let xincr = 8_f64*incr; - for uint::range(0_u, bsize) |j| { - let x = cmplx {re: xincr*(j as f64) - 1.5_f64, im: y}; - crv.push(fillbyte(x, incr, depth)); - }; - Line {i:i, b:crv} -} - -struct Devnull(); - -impl io::Writer for Devnull { - fn write(&self, _b: &const [u8]) {} - fn seek(&self, _i: int, _s: io::SeekStyle) {} - fn tell(&self) -> uint {0_u} - fn flush(&self) -> int {0} - fn get_type(&self) -> io::WriterType { io::File } -} - -fn writer(path: ~str, pport: comm::Port, size: uint) -{ - let cout: @io::Writer = match path { - ~"" => { - @Devnull as @io::Writer - } - ~"-" => { - io::stdout() - } - _ => { - result::get( - &io::file_writer(&Path(path), - ~[io::Create, io::Truncate])) - } - }; - cout.write_line("P4"); - cout.write_line(fmt!("%u %u", size, size)); - let mut lines: HashMap = HashMap::new(); - let mut done = 0_u; - let mut i = 0_u; - while i < size { - let aline = pport.recv(); - if aline.i == done { - debug!("W %u", done); - cout.write(aline.b); - done += 1_u; - let mut prev = done; - while prev <= i { - match lines.pop(&prev) { - Some(pl) => { - debug!("WS %u", prev); - cout.write(pl.b); - done += 1_u; - prev += 1_u; +#[fixed_stack_segment] +fn main() { + unsafe { + let w: i32 = FromStr::from_str(os::args()[1]).get(), h = w; + let mut byte_acc: i8 = 0; + let mut bit_num: i32 = 0; + + println(fmt!("P4\n%d %d", w as int, h as int)); + + let mode = "w"; + let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0])); + + for range(0, h) |y| { + let y = y as f64; + for range(0, w) |x| { + let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64); + let Cr = 2.0 * (x as f64) / (w as f64) - 1.5; + let Ci = 2.0 * (y as f64) / (h as f64) - 1.0; + + for ITER.times { + if Tr + Ti > LIMIT * LIMIT { + break; } - None => break - }; - }; + + Zi = 2.0*Zr*Zi + Ci; + Zr = Tr - Ti + Cr; + Tr = Zr * Zr; + Ti = Zi * Zi; + } + + byte_acc <<= 1; + if Tr + Ti <= LIMIT * LIMIT { + byte_acc |= 1; + } + + bit_num += 1; + + if bit_num == 8 { + fputc(byte_acc as c_int, stdout); + byte_acc = 0; + bit_num = 0; + } else if x == w - 1 { + byte_acc <<= 8 - w%8; + fputc(byte_acc as c_int, stdout); + byte_acc = 0; + bit_num = 0; + } + } } - else { - debug!("S %u", aline.i); - lines.insert(aline.i, aline); - }; - i += 1_u; } } -fn main() { - let args = os::args(); - let args = if os::getenv(~"RUST_BENCH").is_some() { - ~[~"", ~"4000", ~"50"] - } else { - args - }; - - let depth = if vec::len(args) < 4_u { 50_u } - else { uint::from_str(args[3]).get() }; - - let path = if vec::len(args) < 3_u { ~"" } - else { copy args[2] }; // FIXME: bad for perf - - let size = if vec::len(args) < 2_u { 80_u } - else { uint::from_str(args[1]).get() }; - - let (pport, pchan) = comm::stream(); - let pchan = comm::SharedChan::new(pchan); - for uint::range(0_u, size) |j| { - let cchan = pchan.clone(); - do task::spawn { cchan.send(chanmb(j, size, depth)) }; - }; - writer(path, pport, size); -} From f93b3cd5c3783eabd527607adda891d8a84dab4f Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 19 Apr 2013 11:50:03 -0700 Subject: [PATCH 298/403] librustc: Remove debug code; xfail-pretty reverse-complement. --- src/librustc/middle/trans/cabi.rs | 1 - src/librustc/middle/trans/foreign.rs | 10 +++++++--- src/test/bench/shootout-reverse-complement.rs | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 41b812c8e14d7..ed028d14bd65f 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -13,7 +13,6 @@ use middle::trans::base::*; use middle::trans::build::*; use middle::trans::common::*; -use core::io::println; use core::libc::c_uint; use core::option; use core::vec; diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index b00f4d8ed42cf..86ce556be7235 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -185,17 +185,19 @@ fn build_wrap_fn_(ccx: @CrateContext, llshimfn: ValueRef, llwrapfn: ValueRef, shim_upcall: ValueRef, + needs_c_return: bool, arg_builder: wrap_arg_builder, ret_builder: wrap_ret_builder) { let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_"); let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None); - // Patch up the return type if it's not immediate. - /*if !ty::type_is_immediate(tys.fn_sig.output) { + // Patch up the return type if it's not immediate and we're returning via + // the C ABI. + if needs_c_return && !ty::type_is_immediate(tys.fn_sig.output) { let lloutputtype = type_of::type_of(*fcx.ccx, tys.fn_sig.output); fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype)); - }*/ + } let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -499,6 +501,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, llshimfn, llwrapfn, ccx.upcalls.call_shim_on_c_stack, + false, build_args, build_ret); @@ -1229,6 +1232,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext, llshimfn, llwrapfn, ccx.upcalls.call_shim_on_rust_stack, + true, build_args, build_ret); diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 21b1f8f3c82be..e3774be053cd9 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -1,3 +1,5 @@ +// xfail-pretty + use core::cast::transmute; use core::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite}; use core::libc::{size_t}; From c44d7a64865c5aa9507351be881e4c18ef38e4b0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 17 Apr 2013 17:55:21 -0700 Subject: [PATCH 299/403] core::rt: Declare large parts of the I/O API --- src/libcore/rt/io/blocking/file.rs | 82 +++++ src/libcore/rt/io/comm_adapters.rs | 59 ++++ src/libcore/rt/io/file.rs | 64 +++- src/libcore/rt/io/flate.rs | 121 ++++++++ src/libcore/rt/io/mem.rs | 166 ++++++++++ src/libcore/rt/io/misc.rs | 42 +++ src/libcore/rt/io/mod.rs | 269 ++++++++++++++++- src/libcore/rt/io/net/http.rs | 29 ++ src/libcore/rt/io/net/ip.rs | 15 + src/libcore/rt/io/net/mod.rs | 31 ++ src/libcore/rt/io/net/tcp.rs | 50 +++ src/libcore/rt/io/net/udp.rs | 51 ++++ src/libcore/rt/io/net/unix.rs | 51 ++++ src/libcore/rt/io/stdio.rs | 60 ++++ src/libcore/rt/io/util.rs | 469 +++++++++++++++++++++++++++++ src/libcore/rt/rtio.rs | 7 +- src/libcore/rt/uv/net.rs | 2 +- src/libcore/rt/uvio.rs | 1 + 18 files changed, 1539 insertions(+), 30 deletions(-) create mode 100644 src/libcore/rt/io/blocking/file.rs create mode 100644 src/libcore/rt/io/comm_adapters.rs create mode 100644 src/libcore/rt/io/flate.rs create mode 100644 src/libcore/rt/io/mem.rs create mode 100644 src/libcore/rt/io/misc.rs create mode 100644 src/libcore/rt/io/net/http.rs create mode 100644 src/libcore/rt/io/net/ip.rs create mode 100644 src/libcore/rt/io/net/mod.rs create mode 100644 src/libcore/rt/io/net/tcp.rs create mode 100644 src/libcore/rt/io/net/udp.rs create mode 100644 src/libcore/rt/io/net/unix.rs create mode 100644 src/libcore/rt/io/stdio.rs create mode 100644 src/libcore/rt/io/util.rs diff --git a/src/libcore/rt/io/blocking/file.rs b/src/libcore/rt/io/blocking/file.rs new file mode 100644 index 0000000000000..8daf8adf38784 --- /dev/null +++ b/src/libcore/rt/io/blocking/file.rs @@ -0,0 +1,82 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Blocking posix-based file I/O + +use prelude::*; +use super::super::*; +use libc::{c_int, FILE}; + +#[allow(non_camel_case_types)] +pub type fd_t = c_int; + +// Make this a newtype so we can't do I/O on arbitrary integers +pub struct FileDesc(fd_t); + +impl FileDesc { + /// Create a `FileDesc` from an open C file descriptor. + /// + /// The `FileDesc` takes ownership of the file descriptor + /// and will close it upon destruction. + pub fn new(_fd: fd_t) -> FileDesc { fail!() } +} + +impl Reader for FileDesc { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for FileDesc { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for FileDesc { + fn close(&mut self) { fail!() } +} + +impl Seekable for FileDesc { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +pub struct CFile(*FILE); + +impl CFile { + /// Create a `CFile` from an open `FILE` pointer. + /// + /// The `CFile` takes ownership of the file descriptor + /// and will close it upon destruction. + pub fn new(_file: *FILE) -> CFile { fail!() } +} + +impl Reader for CFile { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for CFile { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for CFile { + fn close(&mut self) { fail!() } +} + +impl Seekable for CFile { + fn tell(&self) -> u64 { fail!() } + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} diff --git a/src/libcore/rt/io/comm_adapters.rs b/src/libcore/rt/io/comm_adapters.rs new file mode 100644 index 0000000000000..1d6893b3ca616 --- /dev/null +++ b/src/libcore/rt/io/comm_adapters.rs @@ -0,0 +1,59 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::{Reader, Writer}; + +struct PortReader

; + +impl> PortReader

{ + pub fn new(_port: P) -> PortReader

{ fail!() } +} + +impl> Reader for PortReader

{ + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +struct ChanWriter; + +impl> ChanWriter { + pub fn new(_chan: C) -> ChanWriter { fail!() } +} + +impl> Writer for ChanWriter { + pub fn write(&mut self, _buf: &[u8]) { fail!() } + + pub fn flush(&mut self) { fail!() } +} + +struct ReaderPort; + +impl ReaderPort { + pub fn new(_reader: R) -> ReaderPort { fail!() } +} + +impl GenericPort<~[u8]> for ReaderPort { + fn recv(&self) -> ~[u8] { fail!() } + + fn try_recv(&self) -> Option<~[u8]> { fail!() } +} + +struct WriterChan; + +impl WriterChan { + pub fn new(_writer: W) -> WriterChan { fail!() } +} + +impl GenericChan<~[u8]> for WriterChan { + fn send(&self, _x: ~[u8]) { fail!() } +} + diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs index b7f3ed280a845..0fa357f0ac999 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libcore/rt/io/file.rs @@ -9,35 +9,79 @@ // except according to those terms. use prelude::*; -use super::Stream; +use super::misc::PathLike; +use super::{Reader, Writer, Seekable, Closeable}; +use super::{IoError, SeekStyle}; + +/// Open a file with the default FileMode and FileAccess +/// # TODO are there sane defaults here? +pub fn open_file(_path: &P) -> FileStream { fail!() } + +/// # TODO +/// * Ugh, this is ridiculous. What is the best way to represent these options? +enum FileMode { + /// Opens an existing file. IoError if file does not exist. + Open, + /// Creates a file. IoError if file exists. + Create, + /// Opens an existing file or creates a new one. + OpenOrCreate, + /// Opens an existing file or creates a new one, positioned at EOF. + Append, + /// Opens an existing file, truncating it to 0 bytes. + Truncate, + /// Opens an existing file or creates a new one, truncating it to 0 bytes. + CreateOrTruncate, +} + +enum FileAccess { + Read, + Write, + ReadWrite +} pub struct FileStream; -pub impl FileStream { - fn new(_path: Path) -> FileStream { +impl FileStream { + pub fn open(_path: &P, + _mode: FileMode, + _access: FileAccess + ) -> Result { fail!() } } -impl Stream for FileStream { - fn read(&mut self, _buf: &mut [u8]) -> uint { +impl Reader for FileStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } fn eof(&mut self) -> bool { fail!() } +} - fn write(&mut self, _v: &const [u8]) { - fail!() - } +impl Writer for FileStream { + fn write(&mut self, _v: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Seekable for FileStream { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Closeable for FileStream { + fn close(&mut self) { fail!() } } #[test] #[ignore] fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() { let message = "it's alright. have a good time"; - let filename = Path("test.txt"); - let mut outstream = FileStream::new(filename); + let filename = &Path("test.txt"); + let mut outstream = FileStream::open(filename, Create, Read).unwrap(); outstream.write(message.to_bytes()); } diff --git a/src/libcore/rt/io/flate.rs b/src/libcore/rt/io/flate.rs new file mode 100644 index 0000000000000..24537bef329ab --- /dev/null +++ b/src/libcore/rt/io/flate.rs @@ -0,0 +1,121 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Some various other I/O types + +// NOTE: These ultimately belong somewhere else + +use prelude::*; +use super::*; + +/// A Writer decorator that compresses using the 'deflate' scheme +pub struct DeflateWriter { + inner_writer: W +} + +impl DeflateWriter { + pub fn new(inner_writer: W) -> DeflateWriter { + DeflateWriter { + inner_writer: inner_writer + } + } +} + +impl Writer for DeflateWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Decorator for DeflateWriter { + fn inner(self) -> W { + match self { + DeflateWriter { inner_writer: w } => w + } + } + + fn inner_ref<'a>(&'a self) -> &'a W { + match *self { + DeflateWriter { inner_writer: ref w } => w + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { + match *self { + DeflateWriter { inner_writer: ref mut w } => w + } + } +} + +/// A Reader decorator that decompresses using the 'deflate' scheme +pub struct InflateReader { + inner_reader: R +} + +impl InflateReader { + pub fn new(inner_reader: R) -> InflateReader { + InflateReader { + inner_reader: inner_reader + } + } +} + +impl Reader for InflateReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Decorator for InflateReader { + fn inner(self) -> R { + match self { + InflateReader { inner_reader: r } => r + } + } + + fn inner_ref<'a>(&'a self) -> &'a R { + match *self { + InflateReader { inner_reader: ref r } => r + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { + match *self { + InflateReader { inner_reader: ref mut r } => r + } + } +} + +#[cfg(test)] +mod test { + use prelude::*; + use super::*; + use super::super::mem::*; + use super::super::Decorator; + + #[test] + #[ignore] + fn smoke_test() { + let mem_writer = MemWriter::new(); + let mut deflate_writer = DeflateWriter::new(mem_writer); + let in_msg = "test"; + let in_bytes = in_msg.to_bytes(); + deflate_writer.write(in_bytes); + deflate_writer.flush(); + let buf = deflate_writer.inner().inner(); + let mem_reader = MemReader::new(buf); + let mut inflate_reader = InflateReader::new(mem_reader); + let mut out_bytes = [0, .. 100]; + let bytes_read = inflate_reader.read(out_bytes).get(); + assert!(bytes_read == in_bytes.len()); + let out_msg = str::from_bytes(out_bytes); + assert!(in_msg == out_msg); + } +} \ No newline at end of file diff --git a/src/libcore/rt/io/mem.rs b/src/libcore/rt/io/mem.rs new file mode 100644 index 0000000000000..04790c579137f --- /dev/null +++ b/src/libcore/rt/io/mem.rs @@ -0,0 +1,166 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Readers and Writers for in-memory buffers +//! +//! # TODO +//! +//! * Should probably have something like this for strings. +//! * Should they implement Closable? Would take extra state. + +use prelude::*; +use super::*; + + +/// Writes to an owned, growable byte vector +pub struct MemWriter { + buf: ~[u8] +} + +impl MemWriter { + pub fn new() -> MemWriter { MemWriter { buf: ~[] } } +} + +impl Writer for MemWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { /* no-op */ } +} + +impl Seekable for MemWriter { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Decorator<~[u8]> for MemWriter { + + fn inner(self) -> ~[u8] { + match self { + MemWriter { buf: buf } => buf + } + } + + fn inner_ref<'a>(&'a self) -> &'a ~[u8] { + match *self { + MemWriter { buf: ref buf } => buf + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { + match *self { + MemWriter { buf: ref mut buf } => buf + } + } +} + +/// Reads from an owned byte vector +pub struct MemReader { + buf: ~[u8], + pos: uint +} + +impl MemReader { + pub fn new(buf: ~[u8]) -> MemReader { + MemReader { + buf: buf, + pos: 0 + } + } +} + +impl Reader for MemReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Seekable for MemReader { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Decorator<~[u8]> for MemReader { + + fn inner(self) -> ~[u8] { + match self { + MemReader { buf: buf, _ } => buf + } + } + + fn inner_ref<'a>(&'a self) -> &'a ~[u8] { + match *self { + MemReader { buf: ref buf, _ } => buf + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { + match *self { + MemReader { buf: ref mut buf, _ } => buf + } + } +} + + +/// Writes to a fixed-size byte slice +struct BufWriter<'self> { + buf: &'self mut [u8], + pos: uint +} + +impl<'self> BufWriter<'self> { + pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> { + BufWriter { + buf: buf, + pos: 0 + } + } +} + +impl<'self> Writer for BufWriter<'self> { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl<'self> Seekable for BufWriter<'self> { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + + +/// Reads from a fixed-size byte slice +struct BufReader<'self> { + buf: &'self [u8], + pos: uint +} + +impl<'self> BufReader<'self> { + pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> { + BufReader { + buf: buf, + pos: 0 + } + } +} + +impl<'self> Reader for BufReader<'self> { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl<'self> Seekable for BufReader<'self> { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} \ No newline at end of file diff --git a/src/libcore/rt/io/misc.rs b/src/libcore/rt/io/misc.rs new file mode 100644 index 0000000000000..7bace5d6df2cc --- /dev/null +++ b/src/libcore/rt/io/misc.rs @@ -0,0 +1,42 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path::*; + +pub trait PathLike { + fn path_as_str(&self, f: &fn(&str) -> T) -> T; +} + +impl<'self> PathLike for &'self str { + fn path_as_str(&self, f: &fn(&str) -> T) -> T { + f(*self) + } +} + +impl PathLike for Path { + fn path_as_str(&self, f: &fn(&str) -> T) -> T { + let s = self.to_str(); + f(s) + } +} + +#[cfg(test)] +mod test { + use path::*; + use super::PathLike; + + #[test] + fn path_like_smoke_test() { + let expected = "/home"; + let path = Path(expected); + path.path_as_str(|p| assert!(p == expected)); + path.path_as_str(|p| assert!(p == expected)); + } +} diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs index 1634e7443b479..e711c2ff66e3c 100644 --- a/src/libcore/rt/io/mod.rs +++ b/src/libcore/rt/io/mod.rs @@ -8,35 +8,276 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! Synchronous I/O + +This module defines the Rust interface for synchronous I/O. +It supports file access, + +This will likely live in core::io, not core::rt::io. + +# Examples + +Some examples of obvious things you might want to do + +* Read lines from stdin + + for stdin().each_line |line| { + println(line) + } + +* Read a complete file to a string, (converting newlines?) + + let contents = open("message.txt").read_to_str(); // read_to_str?? + +* Write a line to a file + + let file = FileStream::open("message.txt", Create, Write); + file.write_line("hello, file!"); + +* Iterate over the lines of a file + +* Pull the lines of a file into a vector of strings + +* Connect based on URL? Requires thinking about where the URL type lives + and how to make protocol handlers extensible, e.g. the "tcp" protocol + yields a `TcpStream`. + + connect("tcp://localhost:8080").write_line("HTTP 1.0 GET /"); + +# Terms + +* reader +* writer +* stream +* Blocking vs. non-blocking +* synchrony and asynchrony + +I tend to call this implementation non-blocking, because performing I/O +doesn't block the progress of other tasks. Is that how we want to present +it, 'synchronous but non-blocking'? + +# Error Handling + +# Resource management + +* `close` vs. RAII + +# Paths and URLs + +# std + +Some I/O things don't belong in core + + - url + - net - `fn connect` + - http + - flate + +# TODO + +* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose. + Overloading would be nice. +* Add overloading for Path and &str and Url &str +* stdin/err/out +* print, println, etc. +* fsync +* relationship with filesystem querying, Directory, File types etc. +* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic? +* Trait for things that are both readers and writers, Stream? +* How to handle newline conversion +* String conversion +* File vs. FileStream? File is shorter but could also be used for getting file info + - maybe File is for general file querying and *also* has a static `open` method +* open vs. connect for generic stream opening +* Do we need `close` at all? dtors might be good enough +* How does I/O relate to the Iterator trait? +* std::base64 filters + +*/ + +use prelude::*; + +// Reexports +pub use self::stdio::stdin; +pub use self::stdio::stdout; +pub use self::stdio::stderr; +pub use self::stdio::print; +pub use self::stdio::println; + +pub use self::file::open_file; +pub use self::file::FileStream; +pub use self::net::Listener; +pub use self::net::ip::IpAddr; +pub use self::net::tcp::TcpListener; +pub use self::net::tcp::TcpStream; +pub use self::net::udp::UdpStream; + +// Some extension traits that all Readers and Writers get. +pub use self::util::ReaderUtil; +pub use self::util::ReaderByteConversions; +pub use self::util::WriterByteConversions; + +/// Synchronous, non-blocking file I/O. pub mod file; -// FIXME #5370 Strongly want this to be StreamError(&mut Stream) -pub struct StreamError; +/// Synchronous, non-blocking network I/O. +#[path = "net/mod.rs"] +pub mod net; + +/// Readers and Writers for memory buffers and strings. +#[cfg(not(stage0))] // XXX Using unsnapshotted features +pub mod mem; + +/// Non-blocking access to stdin, stdout, stderr +pub mod stdio; + +/// Basic stream compression. XXX: Belongs with other flate code +#[cfg(not(stage0))] // XXX Using unsnapshotted features +pub mod flate; + +/// Interop between byte streams and pipes. Not sure where it belongs +#[cfg(not(stage0))] // XXX " +pub mod comm_adapters; + +/// Extension traits +mod util; + +/// Non-I/O things needed by the I/O module +mod misc; + +/// Thread-blocking implementations +pub mod blocking { + /// Posix file I/O + pub mod file; + /// # TODO - implement this + pub mod stdio { } + /// Sockets + /// # TODO - implement this + pub mod net { + pub mod tcp { } + pub mod udp { } + #[cfg(unix)] + pub mod unix { } + } +} + + +/// The type passed to I/O condition handlers to indicate error +/// +/// # TODO +/// +/// Is something like this sufficient? It's kind of archaic +pub struct IoError { + kind: IoErrorKind, + desc: &'static str, + detail: Option<~str> +} + +pub enum IoErrorKind { + FileNotFound, + FilePermission, + ConnectionFailed, + Closed, + OtherIoError +} // XXX: Can't put doc comments on macros -// Raised by `Stream` instances on error. Returning `true` from the handler -// indicates that the `Stream` should continue, `false` that it should fail. +// Raised by `I/O` operations on error. condition! { - stream_error: super::StreamError -> bool; + io_error: super::IoError -> (); } -pub trait Stream { - /// Read bytes, up to the length of `buf` and place them in `buf`, - /// returning the number of bytes read or an `IoError`. Reads - /// 0 bytes on EOF. +pub trait Reader { + /// Read bytes, up to the length of `buf` and place them in `buf`. + /// Returns the number of bytes read, or `None` on EOF. /// /// # Failure /// - /// Raises the `reader_error` condition on error - fn read(&mut self, buf: &mut [u8]) -> uint; + /// Raises the `io_error` condition on error, then returns `None`. + /// + /// # TODO + /// + /// This doesn't take a `len` argument like the old `read`. + /// Will people often need to slice their vectors to call this + /// and will that be annoying? + fn read(&mut self, buf: &mut [u8]) -> Option; - /// Return whether the Reader has reached the end of the stream + /// Return whether the Reader has reached the end of the stream. + /// + /// # Example + /// + /// let reader = FileStream::new() + /// while !reader.eof() { + /// println(reader.read_line()); + /// } + /// + /// # TODO + /// + /// What does this return if the Reader is in an error state? fn eof(&mut self) -> bool; +} +pub trait Writer { /// Write the given buffer /// /// # Failure /// - /// Raises the `writer_error` condition on error - fn write(&mut self, v: &const [u8]); + /// Raises the `io_error` condition on error + fn write(&mut self, buf: &[u8]); + + /// Flush output + fn flush(&mut self); +} + +/// I/O types that may be closed +/// +/// Any further operations performed on a closed resource will raise +/// on `io_error` +pub trait Closeable { + /// Close the I/O resource + fn close(&mut self); +} + +pub trait Stream: Reader + Writer + Closeable { } + +pub enum SeekStyle { + /// Seek from the beginning of the stream + SeekSet, + /// Seek from the end of the stream + SeekEnd, + /// Seek from the current position + SeekCur, +} + +/// # TODO +/// * Are `u64` and `i64` the right choices? +pub trait Seekable { + fn tell(&self) -> u64; + fn seek(&mut self, pos: i64, style: SeekStyle); +} + +/// Common trait for decorator types. +/// +/// Provides accessors to get the inner, 'decorated' values. The I/O library +/// uses decorators to add functionality like compression and encryption to I/O +/// streams. +/// +/// # TODO +/// +/// Is this worth having a trait for? May be overkill +pub trait Decorator { + /// Destroy the decorator and extract the decorated value + /// + /// # TODO + /// + /// Because this takes `self' one could never 'undecorate' a Reader/Writer + /// that has been boxed. Is that ok? This feature is mostly useful for + /// extracting the buffer from MemWriter + fn inner(self) -> T; + + /// Take an immutable reference to the decorated value + fn inner_ref<'a>(&'a self) -> &'a T; + + /// Take a mutable reference to the decorated value + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T; } diff --git a/src/libcore/rt/io/net/http.rs b/src/libcore/rt/io/net/http.rs new file mode 100644 index 0000000000000..40f0b315e05b5 --- /dev/null +++ b/src/libcore/rt/io/net/http.rs @@ -0,0 +1,29 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Simple HTTP client and server + +// XXX This should not be in core + +struct HttpServer; + +#[cfg(test)] +mod test { + use unstable::run_in_bare_thread; + + #[test] #[ignore] + fn smoke_test() { + do run_in_bare_thread { + } + + do run_in_bare_thread { + } + } +} diff --git a/src/libcore/rt/io/net/ip.rs b/src/libcore/rt/io/net/ip.rs new file mode 100644 index 0000000000000..d9b7f4e6e4011 --- /dev/null +++ b/src/libcore/rt/io/net/ip.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub enum IpAddr { + Ipv4(u8, u8, u8, u8, u16), + Ipv6 +} + diff --git a/src/libcore/rt/io/net/mod.rs b/src/libcore/rt/io/net/mod.rs new file mode 100644 index 0000000000000..130ff6b38fa82 --- /dev/null +++ b/src/libcore/rt/io/net/mod.rs @@ -0,0 +1,31 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; + +pub mod tcp; +pub mod udp; +pub mod ip; +#[cfg(unix)] +pub mod unix; +pub mod http; + +/// A listener is a value that listens for connections +pub trait Listener { + /// Wait for and accept an incoming connection + /// + /// Returns `None` on timeout. + /// + /// # Failure + /// + /// Raises `io_error` condition. If the condition is handled, + /// then `accept` returns `None`. + fn accept(&mut self) -> Option; +} diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs new file mode 100644 index 0000000000000..ddd75cd8415f3 --- /dev/null +++ b/src/libcore/rt/io/net/tcp.rs @@ -0,0 +1,50 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::ip::IpAddr; + +pub struct TcpStream; + +impl TcpStream { + pub fn connect(_addr: IpAddr) -> Result { + fail!() + } +} + +impl Reader for TcpStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for TcpStream { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for TcpStream { + fn close(&mut self) { fail!() } +} + +pub struct TcpListener; + +impl TcpListener { + pub fn new(_addr: IpAddr) -> TcpListener { + fail!() + } +} + +impl Listener for TcpListener { + fn accept(&mut self) -> Option { fail!() } +} diff --git a/src/libcore/rt/io/net/udp.rs b/src/libcore/rt/io/net/udp.rs new file mode 100644 index 0000000000000..a0f7aa819899e --- /dev/null +++ b/src/libcore/rt/io/net/udp.rs @@ -0,0 +1,51 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::ip::IpAddr; + +pub struct UdpStream; + +impl UdpStream { + pub fn connect(_addr: IpAddr) -> Result { + fail!() + } +} + +impl Reader for UdpStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for UdpStream { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for UdpStream { + fn close(&mut self) { fail!() } +} + +pub struct UdpListener; + +impl UdpListener { + pub fn new(_addr: IpAddr) -> UdpListener { + fail!() + } +} + +impl Listener for UdpListener { + fn accept(&mut self) -> Option { fail!() } +} + diff --git a/src/libcore/rt/io/net/unix.rs b/src/libcore/rt/io/net/unix.rs new file mode 100644 index 0000000000000..fde87deef33f5 --- /dev/null +++ b/src/libcore/rt/io/net/unix.rs @@ -0,0 +1,51 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::super::misc::PathLike; + +pub struct UnixStream; + +impl UnixStream { + pub fn connect(_path: &P) -> Result { + fail!() + } +} + +impl Reader for UnixStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for UnixStream { + fn write(&mut self, _v: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for UnixStream { + fn close(&mut self) { fail!() } +} + +pub struct UnixListener; + +impl UnixListener { + pub fn new(_path: &P) -> UnixListener { + fail!() + } +} + +impl Listener for UnixListener { + fn accept(&mut self) -> Option { fail!() } +} + diff --git a/src/libcore/rt/io/stdio.rs b/src/libcore/rt/io/stdio.rs new file mode 100644 index 0000000000000..3a742266f81a4 --- /dev/null +++ b/src/libcore/rt/io/stdio.rs @@ -0,0 +1,60 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::{Reader, Writer, Closeable}; + +pub fn stdin() -> StdReader { fail!() } + +pub fn stdout() -> StdWriter { fail!() } + +pub fn stderr() -> StdReader { fail!() } + +pub fn print(s: &str) { fail!() } + +pub fn println(s: &str) { fail!() } + +pub enum StdStream { + StdIn, + StdOut, + StdErr +} + +pub struct StdReader; + +impl StdReader { + pub fn new(_stream: StdStream) -> StdReader { fail!() } +} + +impl Reader for StdReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Closeable for StdReader { + fn close(&mut self) { fail!() } +} + +pub struct StdWriter; + +impl StdWriter { + pub fn new(_stream: StdStream) -> StdWriter { fail!() } +} + +impl Writer for StdWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for StdWriter { + fn close(&mut self) { fail!() } +} diff --git a/src/libcore/rt/io/util.rs b/src/libcore/rt/io/util.rs new file mode 100644 index 0000000000000..d695815adcebc --- /dev/null +++ b/src/libcore/rt/io/util.rs @@ -0,0 +1,469 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utility mixins that apply to all Readers and Writers + +// TODO: Not sure how this should be structured +// TODO: Iteration should probably be considered seperately + +pub trait ReaderUtil { + + /// Reads `len` bytes and gives you back a new vector + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns an empty + /// vector if the condition is handled. + fn read_bytes(&mut self, len: uint) -> ~[u8]; + + /// Reads all remaining bytes from the stream. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns an empty + /// vector if the condition is handled. + fn read_to_end(&mut self) -> ~[u8]; + +} + +pub trait ReaderByteConversions { + /// Reads `n` little-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` little-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads `n` big-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` big-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads a little-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_uint(&mut self) -> uint; + + /// Reads a little-endian integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_int(&mut self) -> int; + + /// Reads a big-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_uint(&mut self) -> uint; + + /// Reads a big-endian integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_int(&mut self) -> int; + + /// Reads a big-endian `u64`. + /// + /// `u64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u64(&mut self) -> u64; + + /// Reads a big-endian `u32`. + /// + /// `u32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u32(&mut self) -> u32; + + /// Reads a big-endian `u16`. + /// + /// `u16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u16(&mut self) -> u16; + + /// Reads a big-endian `i64`. + /// + /// `i64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i64(&mut self) -> i64; + + /// Reads a big-endian `i32`. + /// + /// `i32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i32(&mut self) -> i32; + + /// Reads a big-endian `i16`. + /// + /// `i16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i16(&mut self) -> i16; + + /// Reads a big-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_f64(&mut self) -> f64; + + /// Reads a big-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_f32(&mut self) -> f32; + + /// Reads a little-endian `u64`. + /// + /// `u64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u64(&mut self) -> u64; + + /// Reads a little-endian `u32`. + /// + /// `u32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u32(&mut self) -> u32; + + /// Reads a little-endian `u16`. + /// + /// `u16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u16(&mut self) -> u16; + + /// Reads a little-endian `i64`. + /// + /// `i64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i64(&mut self) -> i64; + + /// Reads a little-endian `i32`. + /// + /// `i32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i32(&mut self) -> i32; + + /// Reads a little-endian `i16`. + /// + /// `i16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i16(&mut self) -> i16; + + /// Reads a little-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_f64(&mut self) -> f64; + + /// Reads a little-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_f32(&mut self) -> f32; + + /// Read a u8. + /// + /// `u8`s are 1 byte. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_u8(&mut self) -> u8; + + /// Read an i8. + /// + /// `i8`s are 1 byte. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_i8(&mut self) -> i8; + +} + +pub trait WriterByteConversions { + /// Write the result of passing n through `int::to_str_bytes`. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_int(&mut self, n: int); + + /// Write the result of passing n through `uint::to_str_bytes`. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_uint(&mut self, n: uint); + + /// Write a little-endian uint (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_uint(&mut self, n: uint); + + /// Write a little-endian int (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_int(&mut self, n: int); + + /// Write a big-endian uint (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_uint(&mut self, n: uint); + + /// Write a big-endian int (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_int(&mut self, n: int); + + /// Write a big-endian u64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u64(&mut self, n: u64); + + /// Write a big-endian u32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u32(&mut self, n: u32); + + /// Write a big-endian u16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u16(&mut self, n: u16); + + /// Write a big-endian i64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i64(&mut self, n: i64); + + /// Write a big-endian i32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i32(&mut self, n: i32); + + /// Write a big-endian i16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i16(&mut self, n: i16); + + /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_f64(&mut self, f: f64); + + /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_f32(&mut self, f: f32); + + /// Write a little-endian u64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u64(&mut self, n: u64); + + /// Write a little-endian u32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u32(&mut self, n: u32); + + /// Write a little-endian u16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u16(&mut self, n: u16); + + /// Write a little-endian i64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i64(&mut self, n: i64); + + /// Write a little-endian i32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i32(&mut self, n: i32); + + /// Write a little-endian i16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i16(&mut self, n: i16); + + /// Write a little-endian IEEE754 double-precision floating-point + /// (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_f64(&mut self, f: f64); + + /// Write a litten-endian IEEE754 single-precision floating-point + /// (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_f32(&mut self, f: f32); + + /// Write a u8 (1 byte). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_u8(&mut self, n: u8); + + /// Write a i8 (1 byte). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_i8(&mut self, n: i8); +} diff --git a/src/libcore/rt/rtio.rs b/src/libcore/rt/rtio.rs index 6a7c3970c0091..66eb79ba6ae4e 100644 --- a/src/libcore/rt/rtio.rs +++ b/src/libcore/rt/rtio.rs @@ -11,6 +11,8 @@ use option::*; use result::*; +use super::io::net::ip::IpAddr; + // XXX: ~object doesn't work currently so these are some placeholder // types to use instead pub type EventLoopObject = super::uvio::UvEventLoop; @@ -43,8 +45,3 @@ pub trait Stream { fn read(&mut self, buf: &mut [u8]) -> Result; fn write(&mut self, buf: &[u8]) -> Result<(), ()>; } - -pub enum IpAddr { - Ipv4(u8, u8, u8, u8, u16), - Ipv6 -} diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index 4b9ff4504ddac..0dc1a4d86cbc9 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -17,7 +17,7 @@ use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCa loop_from_watcher, status_to_maybe_uv_error, install_watcher_data, get_watcher_data, drop_watcher_data, vec_to_uv_buf, vec_from_uv_buf}; -use super::super::rtio::{IpAddr, Ipv4, Ipv6}; +use super::super::io::net::ip::{IpAddr, Ipv4, Ipv6}; #[cfg(test)] use unstable::run_in_bare_thread; diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index fe7b0a71dbfe6..b069c67a5f7f0 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -11,6 +11,7 @@ use option::*; use result::*; +use super::io::net::ip::{IpAddr, Ipv4}; use super::uv::*; use super::rtio::*; use ops::Drop; From b96765179ec16bc306bf0f1cc76c7ff67ea36670 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 27 Mar 2013 15:24:50 -0700 Subject: [PATCH 300/403] core: Add rt::context for figuring out what runtime services are available Conflicts: src/libcore/rt/sched/mod.rs --- src/libcore/rt/mod.rs | 72 +++++++++++++++++++++++++++++++++++ src/libcore/rt/sched/local.rs | 34 ++++++++++++++++- src/libcore/rt/sched/mod.rs | 5 +++ src/rt/rust_builtin.cpp | 5 +++ src/rt/rustrt.def.in | 1 + 5 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index b1227af5f4c33..ba61b49d14a4e 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -88,3 +88,75 @@ pub fn start(main: *u8, _argc: int, _argv: **c_char, _crate_map: *u8) -> int { fn rust_call_nullary_fn(f: *u8); } } + +/// Possible contexts in which Rust code may be executing. +/// Different runtime services are available depending on context. +#[deriving(Eq)] +pub enum RuntimeContext { + // Only default services, e.g. exchange heap + GlobalContext, + // The scheduler may be accessed + SchedulerContext, + // Full task services, e.g. local heap, unwinding + TaskContext, + // Running in an old-style task + OldTaskContext +} + +pub fn context() -> RuntimeContext { + + use task::rt::rust_task; + use self::sched::Scheduler; + + // XXX: Hitting TLS twice to check if the scheduler exists + // then to check for the task is not good for perf + if unsafe { rust_try_get_task().is_not_null() } { + return OldTaskContext; + } else { + if Scheduler::have_local() { + let context = ::cell::empty_cell(); + do Scheduler::borrow_local |sched| { + if sched.in_task_context() { + context.put_back(TaskContext); + } else { + context.put_back(SchedulerContext); + } + } + return context.take(); + } else { + return GlobalContext; + } + } + + pub extern { + #[rust_stack] + fn rust_try_get_task() -> *rust_task; + } +} + +#[test] +fn test_context() { + use unstable::run_in_bare_thread; + use self::sched::{Scheduler, Task}; + use self::uvio::UvEventLoop; + use cell::Cell; + + assert!(context() == OldTaskContext); + do run_in_bare_thread { + assert!(context() == GlobalContext); + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~do Task::new(&mut sched.stack_pool) { + assert!(context() == TaskContext); + let sched = Scheduler::take_local(); + do sched.deschedule_running_task_and_then() |task| { + assert!(context() == SchedulerContext); + let task = Cell(task); + do Scheduler::borrow_local |sched| { + sched.task_queue.push_back(task.take()); + } + } + }; + sched.task_queue.push_back(task); + sched.run(); + } +} diff --git a/src/libcore/rt/sched/local.rs b/src/libcore/rt/sched/local.rs index d800101111464..0eb97ee67ec8a 100644 --- a/src/libcore/rt/sched/local.rs +++ b/src/libcore/rt/sched/local.rs @@ -10,6 +10,7 @@ //! Access to the thread-local Scheduler +use prelude::*; use ptr::mut_null; use libc::c_void; use cast::transmute; @@ -39,6 +40,16 @@ pub fn take() -> ~Scheduler { } } +/// Check whether there is a thread-local Scheduler attached to the running thread +pub fn exists() -> bool { + unsafe { + match maybe_tls_key() { + Some(key) => tls::get(key).is_not_null(), + None => false + } + } +} + /// Borrow a mutable reference to the thread-local Scheduler /// # Safety Note /// Because this leaves the Scheduler in thread-local storage it is possible @@ -60,10 +71,31 @@ pub unsafe fn borrow() -> &mut Scheduler { } fn tls_key() -> tls::Key { + maybe_tls_key().get() +} + +fn maybe_tls_key() -> Option { unsafe { let key: *mut c_void = rust_get_sched_tls_key(); let key: &mut tls::Key = transmute(key); - return *key; + let key = *key; + // Check that the key has been initialized. + + // NB: This is a little racy because, while the key is + // initalized under a mutex and it's assumed to be initalized + // in the Scheduler ctor by any thread that needs to use it, + // we are not accessing the key under a mutex. Threads that + // are not using the new Scheduler but still *want to check* + // whether they are running under a new Scheduler may see a 0 + // value here that is in the process of being initialized in + // another thread. I think this is fine since the only action + // they could take if it was initialized would be to check the + // thread-local value and see that it's not set. + if key != 0 { + return Some(key); + } else { + return None; + } } } diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index f157e6a80e0c4..1141ea480c959 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -133,6 +133,11 @@ pub impl Scheduler { local::take() } + /// Just check whether there is a local scheduler + fn have_local() -> bool { + local::exists() + } + // * Scheduler-context operations fn resume_task_from_queue(~self) -> bool { diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 475c030e8f250..a0db6f64f69fc 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -539,6 +539,11 @@ rust_get_task() { return rust_get_current_task(); } +extern "C" rust_task * +rust_try_get_task() { + return rust_try_get_current_task(); +} + extern "C" CDECL stk_seg * rust_get_stack_segment() { return rust_get_current_task()->stk; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index f63e3f53a7caf..5a556ed2107df 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -47,6 +47,7 @@ rust_env_pairs rust_task_yield rust_task_is_unwinding rust_get_task +rust_try_get_task rust_get_stack_segment rust_log_str start_task From 6773b63671081c722761d3980393642452c08157 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 18:22:04 -0700 Subject: [PATCH 301/403] core: Don't use managed boxes in TaskBuilder --- src/libcore/task/mod.rs | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 55546514e4fa5..9a0063b746a98 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -175,7 +175,7 @@ pub struct TaskOpts { // FIXME (#3724): Replace the 'consumed' bit with move mode on self pub struct TaskBuilder { opts: TaskOpts, - gen_body: @fn(v: ~fn()) -> ~fn(), + mut gen_body: Option<~fn(v: ~fn()) -> ~fn()>, can_not_copy: Option, mut consumed: bool, } @@ -188,7 +188,7 @@ pub struct TaskBuilder { pub fn task() -> TaskBuilder { TaskBuilder { opts: default_task_opts(), - gen_body: |body| body, // Identity function + gen_body: None, can_not_copy: None, mut consumed: false, } @@ -201,6 +201,7 @@ priv impl TaskBuilder { fail!(~"Cannot copy a task_builder"); // Fake move mode on self } self.consumed = true; + let gen_body = replace(&mut self.gen_body, None); let notify_chan = replace(&mut self.opts.notify_chan, None); TaskBuilder { opts: TaskOpts { @@ -209,7 +210,7 @@ priv impl TaskBuilder { notify_chan: notify_chan, sched: self.opts.sched }, - gen_body: self.gen_body, + gen_body: gen_body, can_not_copy: None, consumed: false } @@ -341,8 +342,23 @@ pub impl TaskBuilder { * generator by applying the task body which results from the * existing body generator to the new body generator. */ - fn add_wrapper(&self, wrapper: @fn(v: ~fn()) -> ~fn()) -> TaskBuilder { - let prev_gen_body = self.gen_body; + fn add_wrapper(&self, wrapper: ~fn(v: ~fn()) -> ~fn()) -> TaskBuilder { + let prev_gen_body = replace(&mut self.gen_body, None); + let prev_gen_body = match prev_gen_body { + Some(gen) => gen, + None => { + let f: ~fn(~fn()) -> ~fn() = |body| body; + f + } + }; + let prev_gen_body = Cell(prev_gen_body); + let next_gen_body = { + let f: ~fn(~fn()) -> ~fn() = |body| { + let prev_gen_body = prev_gen_body.take(); + wrapper(prev_gen_body(body)) + }; + f + }; let notify_chan = replace(&mut self.opts.notify_chan, None); TaskBuilder { opts: TaskOpts { @@ -351,7 +367,7 @@ pub impl TaskBuilder { notify_chan: notify_chan, sched: self.opts.sched }, - gen_body: |body| { wrapper(prev_gen_body(body)) }, + gen_body: Some(next_gen_body), can_not_copy: None, .. self.consume() } @@ -370,6 +386,7 @@ pub impl TaskBuilder { * must be greater than zero. */ fn spawn(&self, f: ~fn()) { + let gen_body = replace(&mut self.gen_body, None); let notify_chan = replace(&mut self.opts.notify_chan, None); let x = self.consume(); let opts = TaskOpts { @@ -378,7 +395,15 @@ pub impl TaskBuilder { notify_chan: notify_chan, sched: x.opts.sched }; - spawn::spawn_raw(opts, (x.gen_body)(f)); + let f = match gen_body { + Some(gen) => { + gen(f) + } + None => { + f + } + }; + spawn::spawn_raw(opts, f); } /// Runs a task, while transfering ownership of one argument to the child. fn spawn_with(&self, arg: A, f: ~fn(v: A)) { From 15ece0c23ef9b2e696ea4e81bf088e37fedc5d01 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 18:38:12 -0700 Subject: [PATCH 302/403] core: Wire up `spawn` to the new scheduler It will check which scheduler it is running under and create the correct type of task as appropriate. Most options aren't supported but basic spawning works. --- src/libcore/rt/mod.rs | 21 +++++++++++++++++++++ src/libcore/task/mod.rs | 9 +++++++++ src/libcore/task/spawn.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index ba61b49d14a4e..2b9f147bf627d 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -160,3 +160,24 @@ fn test_context() { sched.run(); } } + +// For setting up tests of the new scheduler +#[cfg(test)] +pub fn run_in_newsched_task(f: ~fn()) { + use cell::Cell; + use unstable::run_in_bare_thread; + use self::sched::{Scheduler, Task}; + use self::uvio::UvEventLoop; + + let f = Cell(Cell(f)); + + do run_in_bare_thread { + let mut sched = ~UvEventLoop::new_scheduler(); + let f = f.take(); + let task = ~do Task::new(&mut sched.stack_pool) { + (f.take())(); + }; + sched.task_queue.push_back(task); + sched.run(); + } +} diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 9a0063b746a98..a6c03638713ed 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -1226,3 +1226,12 @@ fn test_spawn_thread_on_demand() { port.recv(); } + +#[test] +fn test_simple_newsched_spawn() { + use rt::run_in_newsched_task; + + do run_in_newsched_task { + spawn(||()) + } +} diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index c71f7d26d40f1..47e386029955b 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -531,6 +531,35 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) } pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { + use rt::*; + + match context() { + OldTaskContext => { + spawn_raw_oldsched(opts, f) + } + TaskContext => { + spawn_raw_newsched(opts, f) + } + SchedulerContext => { + fail!(~"can't spawn from scheduler context") + } + GlobalContext => { + fail!(~"can't spawn from global context") + } + } +} + +fn spawn_raw_newsched(opts: TaskOpts, f: ~fn()) { + use rt::sched::*; + + // XXX: How to schedule a new task is a policy decision that shouldn't be made here + let mut sched = Scheduler::take_local(); + let task = ~Task::new(&mut sched.stack_pool, f); + sched.resume_task_from_running_task_direct(task); +} + +fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) { + let (child_tg, ancestors, is_main) = gen_child_taskgroup(opts.linked, opts.supervised); From d261bb32d95732ef8aa74b010bb8c98f058785b2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 19:32:32 -0700 Subject: [PATCH 303/403] core: More tweaks to the thread-local scheduler interface --- src/libcore/rt/mod.rs | 14 +- .../rt/sched/{local.rs => local_sched.rs} | 22 ++- src/libcore/rt/sched/mod.rs | 142 ++++++++---------- src/libcore/rt/uvio.rs | 68 +++++---- src/libcore/task/spawn.rs | 2 +- 5 files changed, 125 insertions(+), 123 deletions(-) rename src/libcore/rt/sched/{local.rs => local_sched.rs} (87%) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 2b9f147bf627d..e93e0c6fc6cc9 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -106,16 +106,16 @@ pub enum RuntimeContext { pub fn context() -> RuntimeContext { use task::rt::rust_task; - use self::sched::Scheduler; + use self::sched::local_sched; // XXX: Hitting TLS twice to check if the scheduler exists // then to check for the task is not good for perf if unsafe { rust_try_get_task().is_not_null() } { return OldTaskContext; } else { - if Scheduler::have_local() { + if local_sched::exists() { let context = ::cell::empty_cell(); - do Scheduler::borrow_local |sched| { + do local_sched::borrow |sched| { if sched.in_task_context() { context.put_back(TaskContext); } else { @@ -137,7 +137,7 @@ pub fn context() -> RuntimeContext { #[test] fn test_context() { use unstable::run_in_bare_thread; - use self::sched::{Scheduler, Task}; + use self::sched::{local_sched, Task}; use self::uvio::UvEventLoop; use cell::Cell; @@ -147,11 +147,11 @@ fn test_context() { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { assert!(context() == TaskContext); - let sched = Scheduler::take_local(); + let sched = local_sched::take(); do sched.deschedule_running_task_and_then() |task| { assert!(context() == SchedulerContext); let task = Cell(task); - do Scheduler::borrow_local |sched| { + do local_sched::borrow |sched| { sched.task_queue.push_back(task.take()); } } @@ -166,7 +166,7 @@ fn test_context() { pub fn run_in_newsched_task(f: ~fn()) { use cell::Cell; use unstable::run_in_bare_thread; - use self::sched::{Scheduler, Task}; + use self::sched::Task; use self::uvio::UvEventLoop; let f = Cell(Cell(f)); diff --git a/src/libcore/rt/sched/local.rs b/src/libcore/rt/sched/local_sched.rs similarity index 87% rename from src/libcore/rt/sched/local.rs rename to src/libcore/rt/sched/local_sched.rs index 0eb97ee67ec8a..2ab50252ac69e 100644 --- a/src/libcore/rt/sched/local.rs +++ b/src/libcore/rt/sched/local_sched.rs @@ -16,6 +16,7 @@ use libc::c_void; use cast::transmute; use super::Scheduler; +use super::super::rtio::IoFactoryObject; use tls = super::super::thread_local_storage; #[cfg(test)] use super::super::uvio::UvEventLoop; @@ -50,11 +51,21 @@ pub fn exists() -> bool { } } +/// Borrow the thread-local scheduler from thread-local storage. +/// While the scheduler is borrowed it is not available in TLS. +pub fn borrow(f: &fn(&mut Scheduler)) { + let mut sched = take(); + f(sched); + put(sched); +} + /// Borrow a mutable reference to the thread-local Scheduler +/// /// # Safety Note +/// /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased -pub unsafe fn borrow() -> &mut Scheduler { +pub unsafe fn unsafe_borrow() -> &mut Scheduler { unsafe { let key = tls_key(); let mut void_sched: *mut c_void = tls::get(key); @@ -70,6 +81,13 @@ pub unsafe fn borrow() -> &mut Scheduler { } } +pub unsafe fn unsafe_borrow_io() -> &mut IoFactoryObject { + unsafe { + let sched = unsafe_borrow(); + return sched.event_loop.io().unwrap(); + } +} + fn tls_key() -> tls::Key { maybe_tls_key().get() } @@ -125,7 +143,7 @@ fn borrow_smoke_test() { let scheduler = ~UvEventLoop::new_scheduler(); put(scheduler); unsafe { - let _scheduler = borrow(); + let _scheduler = unsafe_borrow(); } let _scheduler = take(); } diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 1141ea480c959..fe443437e3671 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -14,7 +14,7 @@ use cast::transmute; use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; -use super::rtio::{EventLoop, EventLoopObject, IoFactoryObject}; +use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; #[cfg(test)] use super::uvio::UvEventLoop; @@ -22,7 +22,8 @@ use super::context::Context; #[cfg(test)] use int; #[cfg(test)] use cell::Cell; -mod local; +// A more convenient name for external callers, e.g. `local_sched::take()` +pub mod local_sched; /// The Scheduler is responsible for coordinating execution of Tasks /// on a single thread. When the scheduler is running it is owned by @@ -90,52 +91,25 @@ pub impl Scheduler { assert!(!self.in_task_context()); // Give ownership of the scheduler (self) to the thread - local::put(self); - - let scheduler = unsafe { local::borrow() }; - fn run_scheduler_once() { - let scheduler = Scheduler::take_local(); - if scheduler.resume_task_from_queue() { - // Ok, a task ran. Nice! We'll do it again later - do Scheduler::borrow_local |scheduler| { - scheduler.event_loop.callback(run_scheduler_once); + local_sched::put(self); + + unsafe { + let scheduler = local_sched::unsafe_borrow(); + fn run_scheduler_once() { + let scheduler = local_sched::take(); + if scheduler.resume_task_from_queue() { + // Ok, a task ran. Nice! We'll do it again later + do local_sched::borrow |scheduler| { + scheduler.event_loop.callback(run_scheduler_once); + } } } - } - - scheduler.event_loop.callback(run_scheduler_once); - scheduler.event_loop.run(); - - return local::take(); - } - /// Get a mutable pointer to the thread-local I/O - /// # Safety Note - /// This allows other mutable aliases to the scheduler, both in the current - /// execution context and other execution contexts. - unsafe fn borrow_local_io() -> &mut IoFactoryObject { - unsafe { - let io = local::borrow().event_loop.io().unwrap(); - transmute::<&mut IoFactoryObject, &mut IoFactoryObject>(io) + scheduler.event_loop.callback(run_scheduler_once); + scheduler.event_loop.run(); } - } - - /// Borrow the thread-local scheduler from thread-local storage. - /// While the scheduler is borrowed it is not available in TLS. - fn borrow_local(f: &fn(&mut Scheduler)) { - let mut sched = local::take(); - f(sched); - local::put(sched); - } - - /// Take ownership of the scheduler from thread local storage - fn take_local() -> ~Scheduler { - local::take() - } - /// Just check whether there is a local scheduler - fn have_local() -> bool { - local::exists() + return local_sched::take(); } // * Scheduler-context operations @@ -151,7 +125,7 @@ pub impl Scheduler { } None => { rtdebug!("no tasks in queue"); - local::put(self); + local_sched::put(self); return false; } } @@ -167,22 +141,24 @@ pub impl Scheduler { self.current_task = Some(task); self.enqueue_cleanup_job(DoNothing); - local::put(self); + local_sched::put(self); // Take pointers to both the task and scheduler's saved registers. - let sched = unsafe { local::borrow() }; - let (sched_context, _, next_task_context) = sched.get_contexts(); - let next_task_context = next_task_context.unwrap(); - // Context switch to the task, restoring it's registers - // and saving the scheduler's - Context::swap(sched_context, next_task_context); - - let sched = unsafe { local::borrow() }; - // The running task should have passed ownership elsewhere - assert!(sched.current_task.is_none()); - - // Running tasks may have asked us to do some cleanup - sched.run_cleanup_job(); + unsafe { + let sched = local_sched::unsafe_borrow(); + let (sched_context, _, next_task_context) = sched.get_contexts(); + let next_task_context = next_task_context.unwrap(); + // Context switch to the task, restoring it's registers + // and saving the scheduler's + Context::swap(sched_context, next_task_context); + + let sched = local_sched::unsafe_borrow(); + // The running task should have passed ownership elsewhere + assert!(sched.current_task.is_none()); + + // Running tasks may have asked us to do some cleanup + sched.run_cleanup_job(); + } } @@ -199,9 +175,9 @@ pub impl Scheduler { let dead_task = self.current_task.swap_unwrap(); self.enqueue_cleanup_job(RecycleTask(dead_task)); - local::put(self); + local_sched::put(self); - let sched = unsafe { local::borrow() }; + let sched = unsafe { local_sched::unsafe_borrow() }; let (sched_context, last_task_context, _) = sched.get_contexts(); let last_task_context = last_task_context.unwrap(); Context::swap(last_task_context, sched_context); @@ -228,15 +204,15 @@ pub impl Scheduler { let f_opaque = ClosureConverter::from_fn(f_fake_region); self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); - local::put(self); + local_sched::put(self); - let sched = unsafe { local::borrow() }; + let sched = unsafe { local_sched::unsafe_borrow() }; let (sched_context, last_task_context, _) = sched.get_contexts(); let last_task_context = last_task_context.unwrap(); Context::swap(last_task_context, sched_context); // We could be executing in a different thread now - let sched = unsafe { local::borrow() }; + let sched = unsafe { local_sched::unsafe_borrow() }; sched.run_cleanup_job(); } @@ -253,17 +229,19 @@ pub impl Scheduler { self.enqueue_cleanup_job(RescheduleTask(old_running_task)); self.current_task = Some(next_task); - local::put(self); + local_sched::put(self); - let sched = unsafe { local::borrow() }; - let (_, last_task_context, next_task_context) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - let next_task_context = next_task_context.unwrap(); - Context::swap(last_task_context, next_task_context); - - // We could be executing in a different thread now - let sched = unsafe { local::borrow() }; - sched.run_cleanup_job(); + unsafe { + let sched = local_sched::unsafe_borrow(); + let (_, last_task_context, next_task_context) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + let next_task_context = next_task_context.unwrap(); + Context::swap(last_task_context, next_task_context); + + // We could be executing in a different thread now + let sched = local_sched::unsafe_borrow(); + sched.run_cleanup_job(); + } } // * Other stuff @@ -363,12 +341,14 @@ pub impl Task { // This is the first code to execute after the initial // context switch to the task. The previous context may // have asked us to do some cleanup. - let sched = unsafe { local::borrow() }; - sched.run_cleanup_job(); + unsafe { + let sched = local_sched::unsafe_borrow(); + sched.run_cleanup_job(); + } start(); - let sched = Scheduler::take_local(); + let sched = local_sched::take(); sched.terminate_current_task(); }; return wrapper; @@ -428,7 +408,7 @@ fn test_swap_tasks() { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - let mut sched = Scheduler::take_local(); + let mut sched = local_sched::take(); let task2 = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } }; @@ -460,7 +440,7 @@ fn test_run_a_lot_of_tasks_queued() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - do Scheduler::borrow_local |sched| { + do local_sched::borrow |sched| { let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -493,7 +473,7 @@ fn test_run_a_lot_of_tasks_direct() { assert!(count == MAX); fn run_task(count_ptr: *mut int) { - let mut sched = Scheduler::take_local(); + let mut sched = local_sched::take(); let task = ~do Task::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -513,11 +493,11 @@ fn test_block_task() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - let sched = Scheduler::take_local(); + let sched = local_sched::take(); assert!(sched.in_task_context()); do sched.deschedule_running_task_and_then() |task| { let task = Cell(task); - do Scheduler::borrow_local |sched| { + do local_sched::borrow |sched| { assert!(!sched.in_task_context()); sched.task_queue.push_back(task.take()); } diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index b069c67a5f7f0..ff5397398354a 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -17,7 +17,7 @@ use super::rtio::*; use ops::Drop; use cell::{Cell, empty_cell}; use cast::transmute; -use super::sched::Scheduler; +use super::sched::{Scheduler, local_sched}; #[cfg(test)] use super::sched::Task; #[cfg(test)] use unstable::run_in_bare_thread; @@ -121,14 +121,14 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context do scheduler.deschedule_running_task_and_then |task| { rtdebug!("connect: entered scheduler context"); - do Scheduler::borrow_local |scheduler| { + do local_sched::borrow |scheduler| { assert!(!scheduler.in_task_context()); } let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); @@ -150,7 +150,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(maybe_stream); } // Context switch - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -195,7 +195,7 @@ impl TcpListener for UvTcpListener { let server_tcp_watcher = self.watcher(); - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); assert!(scheduler.in_task_context()); do scheduler.deschedule_running_task_and_then |task| { @@ -218,7 +218,7 @@ impl TcpListener for UvTcpListener { rtdebug!("resuming task from listen"); // Context switch - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -258,13 +258,13 @@ impl Stream for UvStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; do scheduler.deschedule_running_task_and_then |task| { rtdebug!("read: entered scheduler context"); - do Scheduler::borrow_local |scheduler| { + do local_sched::borrow |scheduler| { assert!(!scheduler.in_task_context()); } let mut watcher = watcher; @@ -292,7 +292,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -304,7 +304,7 @@ impl Stream for UvStream { fn write(&mut self, buf: &[u8]) -> Result<(), ()> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; @@ -323,7 +323,7 @@ impl Stream for UvStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -339,7 +339,7 @@ fn test_simple_io_no_connect() { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; + let io = unsafe { local_sched::unsafe_borrow_io() }; let addr = Ipv4(127, 0, 0, 1, 2926); let maybe_chan = io.connect(addr); assert!(maybe_chan.is_none()); @@ -357,25 +357,29 @@ fn test_simple_tcp_server_and_client() { let addr = Ipv4(127, 0, 0, 1, 2929); let client_task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; - let mut stream = io.connect(addr).unwrap(); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.close(); + unsafe { + let io = local_sched::unsafe_borrow_io(); + let mut stream = io.connect(addr).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.close(); + } }; let server_task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; - let mut listener = io.bind(addr).unwrap(); - let mut stream = listener.listen().unwrap(); - let mut buf = [0, .. 2048]; - let nread = stream.read(buf).unwrap(); - assert!(nread == 8); - for uint::range(0, nread) |i| { - rtdebug!("%u", buf[i] as uint); - assert!(buf[i] == i as u8); + unsafe { + let io = local_sched::unsafe_borrow_io(); + let mut listener = io.bind(addr).unwrap(); + let mut stream = listener.listen().unwrap(); + let mut buf = [0, .. 2048]; + let nread = stream.read(buf).unwrap(); + assert!(nread == 8); + for uint::range(0, nread) |i| { + rtdebug!("%u", buf[i] as uint); + assert!(buf[i] == i as u8); + } + stream.close(); + listener.close(); } - stream.close(); - listener.close(); }; // Start the server first so it listens before the client connects @@ -392,7 +396,7 @@ fn test_read_and_block() { let addr = Ipv4(127, 0, 0, 1, 2930); let client_task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; + let io = unsafe { local_sched::unsafe_borrow_io() }; let mut stream = io.connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -402,7 +406,7 @@ fn test_read_and_block() { }; let server_task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; + let io = unsafe { local_sched::unsafe_borrow_io() }; let mut listener = io.bind(addr).unwrap(); let mut stream = listener.listen().unwrap(); let mut buf = [0, .. 2048]; @@ -420,13 +424,13 @@ fn test_read_and_block() { } reads += 1; - let scheduler = Scheduler::take_local(); + let scheduler = local_sched::take(); // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it do scheduler.deschedule_running_task_and_then |task| { let task = Cell(task); - do Scheduler::borrow_local |scheduler| { + do local_sched::borrow |scheduler| { scheduler.task_queue.push_back(task.take()); } } @@ -453,7 +457,7 @@ fn test_read_read_read() { let addr = Ipv4(127, 0, 0, 1, 2931); let client_task = ~do Task::new(&mut sched.stack_pool) { - let io = unsafe { Scheduler::borrow_local_io() }; + let io = unsafe { local_sched::unsafe_borrow_io() }; let mut stream = io.connect(addr).unwrap(); let mut buf = [0, .. 2048]; let mut total_bytes_read = 0; diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 47e386029955b..5b45f498319fa 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -553,7 +553,7 @@ fn spawn_raw_newsched(opts: TaskOpts, f: ~fn()) { use rt::sched::*; // XXX: How to schedule a new task is a policy decision that shouldn't be made here - let mut sched = Scheduler::take_local(); + let mut sched = local_sched::take(); let task = ~Task::new(&mut sched.stack_pool, f); sched.resume_task_from_running_task_direct(task); } From eddd817bf05723c02722a7b4ab16b7c74baa9533 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 20:16:33 -0700 Subject: [PATCH 304/403] core::rt: Add another context switching operation to the scheduler `switch_running_tasks_and_then` does a context switch to another task then immediatly runs a closure. --- src/libcore/rt/sched/mod.rs | 117 +++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index fe443437e3671..e0f2397b64b92 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -65,6 +65,8 @@ enum CleanupJob { pub impl Scheduler { + fn in_task_context(&self) -> bool { self.current_task.is_some() } + fn new(event_loop: ~EventLoopObject) -> Scheduler { // Lazily initialize the global state, currently the scheduler TLS key @@ -131,6 +133,59 @@ pub impl Scheduler { } } + // * Task-context operations + + /// Called by a running task to end execution, after which it will + /// be recycled by the scheduler for reuse in a new task. + fn terminate_current_task(~self) { + let mut self = self; + assert!(self.in_task_context()); + + rtdebug!("ending running task"); + + let dead_task = self.current_task.swap_unwrap(); + self.enqueue_cleanup_job(RecycleTask(dead_task)); + + local_sched::put(self); + + let sched = unsafe { local_sched::unsafe_borrow() }; + let (sched_context, last_task_context, _) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); + + // Control never reaches here + } + + /// Switch directly to another task, without going through the scheduler. + /// You would want to think hard about doing this, e.g. if there are + /// pending I/O events it would be a bad idea. + fn resume_task_from_running_task_direct(~self, next_task: ~Task) { + let mut self = self; + assert!(self.in_task_context()); + + rtdebug!("switching tasks"); + + let old_running_task = self.current_task.swap_unwrap(); + self.enqueue_cleanup_job(RescheduleTask(old_running_task)); + self.current_task = Some(next_task); + + local_sched::put(self); + + unsafe { + let sched = local_sched::unsafe_borrow(); + let (_, last_task_context, next_task_context) = sched.get_contexts(); + let last_task_context = last_task_context.unwrap(); + let next_task_context = next_task_context.unwrap(); + Context::swap(last_task_context, next_task_context); + + // We could be executing in a different thread now + let sched = local_sched::unsafe_borrow(); + sched.run_cleanup_job(); + } + } + + // Core scheduling ops + fn resume_task_immediately(~self, task: ~Task) { let mut self = self; assert!(!self.in_task_context()); @@ -161,30 +216,6 @@ pub impl Scheduler { } } - - // * Task-context operations - - /// Called by a running task to end execution, after which it will - /// be recycled by the scheduler for reuse in a new task. - fn terminate_current_task(~self) { - let mut self = self; - assert!(self.in_task_context()); - - rtdebug!("ending running task"); - - let dead_task = self.current_task.swap_unwrap(); - self.enqueue_cleanup_job(RecycleTask(dead_task)); - - local_sched::put(self); - - let sched = unsafe { local_sched::unsafe_borrow() }; - let (sched_context, last_task_context, _) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - Context::swap(last_task_context, sched_context); - - // Control never reaches here - } - /// Block a running task, context switch to the scheduler, then pass the /// blocked task to a closure. /// @@ -219,14 +250,16 @@ pub impl Scheduler { /// Switch directly to another task, without going through the scheduler. /// You would want to think hard about doing this, e.g. if there are /// pending I/O events it would be a bad idea. - fn resume_task_from_running_task_direct(~self, next_task: ~Task) { + fn switch_running_tasks_and_then(~self, next_task: ~Task, f: &fn(~Task)) { let mut self = self; assert!(self.in_task_context()); rtdebug!("switching tasks"); let old_running_task = self.current_task.swap_unwrap(); - self.enqueue_cleanup_job(RescheduleTask(old_running_task)); + let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) }; + let f_opaque = ClosureConverter::from_fn(f_fake_region); + self.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque)); self.current_task = Some(next_task); local_sched::put(self); @@ -244,9 +277,9 @@ pub impl Scheduler { } } - // * Other stuff - fn in_task_context(&self) -> bool { self.current_task.is_some() } + + // * Other stuff fn enqueue_cleanup_job(&mut self, job: CleanupJob) { assert!(self.cleanup_job.is_none()); @@ -422,6 +455,34 @@ fn test_swap_tasks() { } } +#[test] +fn test_swap_tasks_then() { + do run_in_bare_thread { + let mut count = 0; + let count_ptr: *mut int = &mut count; + + let mut sched = ~UvEventLoop::new_scheduler(); + let task1 = ~do Task::new(&mut sched.stack_pool) { + unsafe { *count_ptr = *count_ptr + 1; } + let mut sched = local_sched::take(); + let task2 = ~do Task::new(&mut sched.stack_pool) { + unsafe { *count_ptr = *count_ptr + 1; } + }; + // Context switch directly to the new task + do sched.switch_running_tasks_and_then(task2) |task1| { + let task1 = Cell(task1); + do local_sched::borrow |sched| { + sched.task_queue.push_front(task1.take()); + } + } + unsafe { *count_ptr = *count_ptr + 1; } + }; + sched.task_queue.push_back(task1); + sched.run(); + assert!(count == 3); + } +} + #[bench] #[test] #[ignore(reason = "long test")] fn test_run_a_lot_of_tasks_queued() { do run_in_bare_thread { From b57611d10c31a7bfdc3703fa938277caaa87f3a7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Apr 2013 23:54:55 -0700 Subject: [PATCH 305/403] core::rt: Simplify some scheduler operations --- src/libcore/rt/sched/mod.rs | 110 +++++------------------------------- src/libcore/task/spawn.rs | 3 +- 2 files changed, 14 insertions(+), 99 deletions(-) diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index e0f2397b64b92..28946281628b1 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -16,11 +16,11 @@ use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; +use cell::Cell; #[cfg(test)] use super::uvio::UvEventLoop; #[cfg(test)] use unstable::run_in_bare_thread; #[cfg(test)] use int; -#[cfg(test)] use cell::Cell; // A more convenient name for external callers, e.g. `local_sched::take()` pub mod local_sched; @@ -58,8 +58,6 @@ impl ClosureConverter for UnsafeTaskReceiver { enum CleanupJob { DoNothing, - RescheduleTask(~Task), - RecycleTask(~Task), GiveTask(~Task, UnsafeTaskReceiver) } @@ -143,44 +141,25 @@ pub impl Scheduler { rtdebug!("ending running task"); - let dead_task = self.current_task.swap_unwrap(); - self.enqueue_cleanup_job(RecycleTask(dead_task)); - - local_sched::put(self); - - let sched = unsafe { local_sched::unsafe_borrow() }; - let (sched_context, last_task_context, _) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - Context::swap(last_task_context, sched_context); + do self.deschedule_running_task_and_then |dead_task| { + let dead_task = Cell(dead_task); + do local_sched::borrow |sched| { + dead_task.take().recycle(&mut sched.stack_pool); + } + } // Control never reaches here } - /// Switch directly to another task, without going through the scheduler. - /// You would want to think hard about doing this, e.g. if there are - /// pending I/O events it would be a bad idea. - fn resume_task_from_running_task_direct(~self, next_task: ~Task) { + fn schedule_new_task(~self, task: ~Task) { let mut self = self; assert!(self.in_task_context()); - rtdebug!("switching tasks"); - - let old_running_task = self.current_task.swap_unwrap(); - self.enqueue_cleanup_job(RescheduleTask(old_running_task)); - self.current_task = Some(next_task); - - local_sched::put(self); - - unsafe { - let sched = local_sched::unsafe_borrow(); - let (_, last_task_context, next_task_context) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - let next_task_context = next_task_context.unwrap(); - Context::swap(last_task_context, next_task_context); - - // We could be executing in a different thread now - let sched = local_sched::unsafe_borrow(); - sched.run_cleanup_job(); + do self.switch_running_tasks_and_then(task) |last_task| { + let last_task = Cell(last_task); + do local_sched::borrow |sched| { + sched.task_queue.push_front(last_task.take()); + } } } @@ -294,11 +273,6 @@ pub impl Scheduler { let cleanup_job = self.cleanup_job.swap_unwrap(); match cleanup_job { DoNothing => { } - RescheduleTask(task) => { - // NB: Pushing to the *front* of the queue - self.task_queue.push_front(task); - } - RecycleTask(task) => task.recycle(&mut self.stack_pool), GiveTask(task, f) => (f.to_fn())(task) } } @@ -316,8 +290,6 @@ pub impl Scheduler { Option<&'a mut Context>, Option<&'a mut Context>) { let last_task = match self.cleanup_job { - Some(RescheduleTask(~ref task)) | - Some(RecycleTask(~ref task)) | Some(GiveTask(~ref task, _)) => { Some(task) } @@ -432,29 +404,6 @@ fn test_several_tasks() { } } -#[test] -fn test_swap_tasks() { - do run_in_bare_thread { - let mut count = 0; - let count_ptr: *mut int = &mut count; - - let mut sched = ~UvEventLoop::new_scheduler(); - let task1 = ~do Task::new(&mut sched.stack_pool) { - unsafe { *count_ptr = *count_ptr + 1; } - let mut sched = local_sched::take(); - let task2 = ~do Task::new(&mut sched.stack_pool) { - unsafe { *count_ptr = *count_ptr + 1; } - }; - // Context switch directly to the new task - sched.resume_task_from_running_task_direct(task2); - unsafe { *count_ptr = *count_ptr + 1; } - }; - sched.task_queue.push_back(task1); - sched.run(); - assert!(count == 3); - } -} - #[test] fn test_swap_tasks_then() { do run_in_bare_thread { @@ -516,39 +465,6 @@ fn test_run_a_lot_of_tasks_queued() { } } -#[bench] #[test] #[ignore(reason = "too much stack allocation")] -fn test_run_a_lot_of_tasks_direct() { - do run_in_bare_thread { - static MAX: int = 100000; - let mut count = 0; - let count_ptr: *mut int = &mut count; - - let mut sched = ~UvEventLoop::new_scheduler(); - - let start_task = ~do Task::new(&mut sched.stack_pool) { - run_task(count_ptr); - }; - sched.task_queue.push_back(start_task); - sched.run(); - - assert!(count == MAX); - - fn run_task(count_ptr: *mut int) { - let mut sched = local_sched::take(); - let task = ~do Task::new(&mut sched.stack_pool) { - unsafe { - *count_ptr = *count_ptr + 1; - if *count_ptr != MAX { - run_task(count_ptr); - } - } - }; - // Context switch directly to the new task - sched.resume_task_from_running_task_direct(task); - }; - } -} - #[test] fn test_block_task() { do run_in_bare_thread { diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 5b45f498319fa..118c4cc23125b 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -552,10 +552,9 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { fn spawn_raw_newsched(opts: TaskOpts, f: ~fn()) { use rt::sched::*; - // XXX: How to schedule a new task is a policy decision that shouldn't be made here let mut sched = local_sched::take(); let task = ~Task::new(&mut sched.stack_pool, f); - sched.resume_task_from_running_task_direct(task); + sched.schedule_new_task(task); } fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) { From e782e1f37183b7ad7731cf0fbb474b55d199a9d5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 19 Apr 2013 12:04:19 -0700 Subject: [PATCH 306/403] Tidy --- src/libcore/rt/io/file.rs | 6 +++--- src/libcore/rt/io/mem.rs | 10 +++++----- src/libcore/rt/io/mod.rs | 20 ++++++++++---------- src/libcore/rt/io/net/http.rs | 2 +- src/libcore/rt/io/util.rs | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs index 0fa357f0ac999..06d2aaaca352f 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libcore/rt/io/file.rs @@ -14,10 +14,10 @@ use super::{Reader, Writer, Seekable, Closeable}; use super::{IoError, SeekStyle}; /// Open a file with the default FileMode and FileAccess -/// # TODO are there sane defaults here? +/// # XXX are there sane defaults here? pub fn open_file(_path: &P) -> FileStream { fail!() } -/// # TODO +/// # XXX /// * Ugh, this is ridiculous. What is the best way to represent these options? enum FileMode { /// Opens an existing file. IoError if file does not exist. @@ -33,7 +33,7 @@ enum FileMode { /// Opens an existing file or creates a new one, truncating it to 0 bytes. CreateOrTruncate, } - + enum FileAccess { Read, Write, diff --git a/src/libcore/rt/io/mem.rs b/src/libcore/rt/io/mem.rs index 04790c579137f..fcba4b1d502f9 100644 --- a/src/libcore/rt/io/mem.rs +++ b/src/libcore/rt/io/mem.rs @@ -10,7 +10,7 @@ //! Readers and Writers for in-memory buffers //! -//! # TODO +//! # XXX //! //! * Should probably have something like this for strings. //! * Should they implement Closable? Would take extra state. @@ -61,7 +61,7 @@ impl Decorator<~[u8]> for MemWriter { } } -/// Reads from an owned byte vector +/// Reads from an owned byte vector pub struct MemReader { buf: ~[u8], pos: uint @@ -109,13 +109,13 @@ impl Decorator<~[u8]> for MemReader { } } - + /// Writes to a fixed-size byte slice struct BufWriter<'self> { buf: &'self mut [u8], pos: uint } - + impl<'self> BufWriter<'self> { pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> { BufWriter { @@ -138,7 +138,7 @@ impl<'self> Seekable for BufWriter<'self> { } -/// Reads from a fixed-size byte slice +/// Reads from a fixed-size byte slice struct BufReader<'self> { buf: &'self [u8], pos: uint diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs index e711c2ff66e3c..aed48ee7353a6 100644 --- a/src/libcore/rt/io/mod.rs +++ b/src/libcore/rt/io/mod.rs @@ -11,7 +11,7 @@ /*! Synchronous I/O This module defines the Rust interface for synchronous I/O. -It supports file access, +It supports file access, This will likely live in core::io, not core::rt::io. @@ -73,7 +73,7 @@ Some I/O things don't belong in core - http - flate -# TODO +# XXX * Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose. Overloading would be nice. @@ -149,10 +149,10 @@ mod misc; pub mod blocking { /// Posix file I/O pub mod file; - /// # TODO - implement this + /// # XXX - implement this pub mod stdio { } /// Sockets - /// # TODO - implement this + /// # XXX - implement this pub mod net { pub mod tcp { } pub mod udp { } @@ -164,7 +164,7 @@ pub mod blocking { /// The type passed to I/O condition handlers to indicate error /// -/// # TODO +/// # XXX /// /// Is something like this sufficient? It's kind of archaic pub struct IoError { @@ -195,7 +195,7 @@ pub trait Reader { /// /// Raises the `io_error` condition on error, then returns `None`. /// - /// # TODO + /// # XXX /// /// This doesn't take a `len` argument like the old `read`. /// Will people often need to slice their vectors to call this @@ -211,7 +211,7 @@ pub trait Reader { /// println(reader.read_line()); /// } /// - /// # TODO + /// # XXX /// /// What does this return if the Reader is in an error state? fn eof(&mut self) -> bool; @@ -249,7 +249,7 @@ pub enum SeekStyle { SeekCur, } -/// # TODO +/// # XXX /// * Are `u64` and `i64` the right choices? pub trait Seekable { fn tell(&self) -> u64; @@ -262,13 +262,13 @@ pub trait Seekable { /// uses decorators to add functionality like compression and encryption to I/O /// streams. /// -/// # TODO +/// # XXX /// /// Is this worth having a trait for? May be overkill pub trait Decorator { /// Destroy the decorator and extract the decorated value /// - /// # TODO + /// # XXX /// /// Because this takes `self' one could never 'undecorate' a Reader/Writer /// that has been boxed. Is that ok? This feature is mostly useful for diff --git a/src/libcore/rt/io/net/http.rs b/src/libcore/rt/io/net/http.rs index 40f0b315e05b5..c693cfaab678b 100644 --- a/src/libcore/rt/io/net/http.rs +++ b/src/libcore/rt/io/net/http.rs @@ -17,7 +17,7 @@ struct HttpServer; #[cfg(test)] mod test { use unstable::run_in_bare_thread; - + #[test] #[ignore] fn smoke_test() { do run_in_bare_thread { diff --git a/src/libcore/rt/io/util.rs b/src/libcore/rt/io/util.rs index d695815adcebc..cff224a80bee2 100644 --- a/src/libcore/rt/io/util.rs +++ b/src/libcore/rt/io/util.rs @@ -10,8 +10,8 @@ //! Utility mixins that apply to all Readers and Writers -// TODO: Not sure how this should be structured -// TODO: Iteration should probably be considered seperately +// XXX: Not sure how this should be structured +// XXX: Iteration should probably be considered seperately pub trait ReaderUtil { From 69eb218ffccfba72258b091bb18f4cadf83343b9 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 19 Apr 2013 14:14:07 -0700 Subject: [PATCH 307/403] Try to suppress valgrind errors I can't reproduce the one on the bots, but this might fix it --- src/etc/x86.supp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/x86.supp b/src/etc/x86.supp index 028bde2e73ff8..1253b5ffc06c9 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -583,7 +583,7 @@ { llvm-optimization-reads-uninitialized-memory-3 Memcheck:Cond - fun:_ZN4test9run_tests4anon13expr_fn_* + fun:_ZN4test9run_tests* ... } From 7270fadfccb8f7b767bf45bda106a55b6a874c03 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 19 Apr 2013 14:58:21 -0700 Subject: [PATCH 308/403] core::rt: Rename Closeable to Close, Seekable to Seek, blocking to native --- src/libcore/rt/io/file.rs | 6 +++--- src/libcore/rt/io/mem.rs | 8 ++++---- src/libcore/rt/io/mod.rs | 8 ++++---- src/libcore/rt/io/{blocking => native}/file.rs | 8 ++++---- src/libcore/rt/io/net/tcp.rs | 2 +- src/libcore/rt/io/net/udp.rs | 2 +- src/libcore/rt/io/net/unix.rs | 2 +- src/libcore/rt/io/stdio.rs | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) rename src/libcore/rt/io/{blocking => native}/file.rs (94%) diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs index 06d2aaaca352f..e041183b58452 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libcore/rt/io/file.rs @@ -10,7 +10,7 @@ use prelude::*; use super::misc::PathLike; -use super::{Reader, Writer, Seekable, Closeable}; +use super::{Reader, Writer, Seek, Close}; use super::{IoError, SeekStyle}; /// Open a file with the default FileMode and FileAccess @@ -67,13 +67,13 @@ impl Writer for FileStream { fn flush(&mut self) { fail!() } } -impl Seekable for FileStream { +impl Seek for FileStream { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } } -impl Closeable for FileStream { +impl Close for FileStream { fn close(&mut self) { fail!() } } diff --git a/src/libcore/rt/io/mem.rs b/src/libcore/rt/io/mem.rs index fcba4b1d502f9..600968a3c7105 100644 --- a/src/libcore/rt/io/mem.rs +++ b/src/libcore/rt/io/mem.rs @@ -34,7 +34,7 @@ impl Writer for MemWriter { fn flush(&mut self) { /* no-op */ } } -impl Seekable for MemWriter { +impl Seek for MemWriter { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } @@ -82,7 +82,7 @@ impl Reader for MemReader { fn eof(&mut self) -> bool { fail!() } } -impl Seekable for MemReader { +impl Seek for MemReader { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } @@ -131,7 +131,7 @@ impl<'self> Writer for BufWriter<'self> { fn flush(&mut self) { fail!() } } -impl<'self> Seekable for BufWriter<'self> { +impl<'self> Seek for BufWriter<'self> { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } @@ -159,7 +159,7 @@ impl<'self> Reader for BufReader<'self> { fn eof(&mut self) -> bool { fail!() } } -impl<'self> Seekable for BufReader<'self> { +impl<'self> Seek for BufReader<'self> { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs index aed48ee7353a6..b035532144c44 100644 --- a/src/libcore/rt/io/mod.rs +++ b/src/libcore/rt/io/mod.rs @@ -146,7 +146,7 @@ mod util; mod misc; /// Thread-blocking implementations -pub mod blocking { +pub mod native { /// Posix file I/O pub mod file; /// # XXX - implement this @@ -233,12 +233,12 @@ pub trait Writer { /// /// Any further operations performed on a closed resource will raise /// on `io_error` -pub trait Closeable { +pub trait Close { /// Close the I/O resource fn close(&mut self); } -pub trait Stream: Reader + Writer + Closeable { } +pub trait Stream: Reader + Writer + Close { } pub enum SeekStyle { /// Seek from the beginning of the stream @@ -251,7 +251,7 @@ pub enum SeekStyle { /// # XXX /// * Are `u64` and `i64` the right choices? -pub trait Seekable { +pub trait Seek { fn tell(&self) -> u64; fn seek(&mut self, pos: i64, style: SeekStyle); } diff --git a/src/libcore/rt/io/blocking/file.rs b/src/libcore/rt/io/native/file.rs similarity index 94% rename from src/libcore/rt/io/blocking/file.rs rename to src/libcore/rt/io/native/file.rs index 8daf8adf38784..e203df815f2f4 100644 --- a/src/libcore/rt/io/blocking/file.rs +++ b/src/libcore/rt/io/native/file.rs @@ -40,11 +40,11 @@ impl Writer for FileDesc { fn flush(&mut self) { fail!() } } -impl Closeable for FileDesc { +impl Close for FileDesc { fn close(&mut self) { fail!() } } -impl Seekable for FileDesc { +impl Seek for FileDesc { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } @@ -72,11 +72,11 @@ impl Writer for CFile { fn flush(&mut self) { fail!() } } -impl Closeable for CFile { +impl Close for CFile { fn close(&mut self) { fail!() } } -impl Seekable for CFile { +impl Seek for CFile { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } } diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs index ddd75cd8415f3..e3f71dca8c827 100644 --- a/src/libcore/rt/io/net/tcp.rs +++ b/src/libcore/rt/io/net/tcp.rs @@ -33,7 +33,7 @@ impl Writer for TcpStream { fn flush(&mut self) { fail!() } } -impl Closeable for TcpStream { +impl Close for TcpStream { fn close(&mut self) { fail!() } } diff --git a/src/libcore/rt/io/net/udp.rs b/src/libcore/rt/io/net/udp.rs index a0f7aa819899e..f76bb58a45eb9 100644 --- a/src/libcore/rt/io/net/udp.rs +++ b/src/libcore/rt/io/net/udp.rs @@ -33,7 +33,7 @@ impl Writer for UdpStream { fn flush(&mut self) { fail!() } } -impl Closeable for UdpStream { +impl Close for UdpStream { fn close(&mut self) { fail!() } } diff --git a/src/libcore/rt/io/net/unix.rs b/src/libcore/rt/io/net/unix.rs index fde87deef33f5..35eabe21b2a6b 100644 --- a/src/libcore/rt/io/net/unix.rs +++ b/src/libcore/rt/io/net/unix.rs @@ -33,7 +33,7 @@ impl Writer for UnixStream { fn flush(&mut self) { fail!() } } -impl Closeable for UnixStream { +impl Close for UnixStream { fn close(&mut self) { fail!() } } diff --git a/src/libcore/rt/io/stdio.rs b/src/libcore/rt/io/stdio.rs index 3a742266f81a4..21989f5e873d0 100644 --- a/src/libcore/rt/io/stdio.rs +++ b/src/libcore/rt/io/stdio.rs @@ -9,7 +9,7 @@ // except according to those terms. use prelude::*; -use super::{Reader, Writer, Closeable}; +use super::{Reader, Writer, Close}; pub fn stdin() -> StdReader { fail!() } @@ -39,7 +39,7 @@ impl Reader for StdReader { fn eof(&mut self) -> bool { fail!() } } -impl Closeable for StdReader { +impl Close for StdReader { fn close(&mut self) { fail!() } } @@ -55,6 +55,6 @@ impl Writer for StdWriter { fn flush(&mut self) { fail!() } } -impl Closeable for StdWriter { +impl Close for StdWriter { fn close(&mut self) { fail!() } } From dcea71720852cf6b7d682d6caa054a2d6fb96068 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 19 Apr 2013 15:57:31 -0700 Subject: [PATCH 309/403] librustc: Fix botched merge. rs=merge --- src/libcore/vec.rs | 9 +++++++++ src/librustc/middle/trans/reflect.rs | 8 ++++++-- src/libsyntax/parse/token.rs | 8 ++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 0d612369cc5c8..efb11271af6d5 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1976,6 +1976,7 @@ pub trait ImmutableVector<'self, T> { fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool; fn flat_map(&self, f: &fn(t: &T) -> ~[U]) -> ~[U]; fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U]; + unsafe fn unsafe_ref(&self, index: uint) -> *T; } /// Extension methods for vectors @@ -2097,6 +2098,14 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { fn filter_mapped(&self, f: &fn(t: &T) -> Option) -> ~[U] { filter_mapped(*self, f) } + + /// Returns a pointer to the element at the given index, without doing + /// bounds checking. + #[inline(always)] + unsafe fn unsafe_ref(&self, index: uint) -> *T { + let (ptr, _): (*T, uint) = transmute(*self); + ptr.offset(index) + } } pub trait ImmutableEqVector { diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index e62e19f636a4e..30c14ab679f31 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -288,11 +288,15 @@ pub impl Reflector { let arg = unsafe { llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) }; - let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None); + let fcx = new_fn_ctxt(ccx, + ~[], + llfdecl, + ty::mk_uint(ccx.tcx), + None); let bcx = top_scope_block(fcx, None); let arg = BitCast(bcx, arg, llptrty); let ret = adt::trans_get_discr(bcx, repr, arg); - Store(bcx, ret, fcx.llretptr); + Store(bcx, ret, fcx.llretptr.get()); cleanup_and_Br(bcx, bcx, fcx.llreturn); finish_fn(fcx, bcx.llbb); llfdecl diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b94b53076ec55..2483cacd1a69f 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -376,10 +376,10 @@ pub struct ident_interner { pub impl ident_interner { fn intern(&self, val: @~str) -> ast::ident { - ast::ident { repr: self.interner.intern(val), ctxt: 0} + ast::ident { repr: self.interner.intern(val), ctxt: 0 } } fn gensym(&self, val: @~str) -> ast::ident { - ast::ident { repr: self.interner.gensym(val), ctxt: 0} + ast::ident { repr: self.interner.gensym(val), ctxt: 0 } } fn get(&self, idx: ast::ident) -> @~str { self.interner.get(idx.repr) @@ -388,9 +388,9 @@ pub impl ident_interner { self.interner.len() } fn find_equiv>(&self, val: &Q) - -> Option { + -> Option { match self.interner.find_equiv(val) { - Some(v) => Some(ast::ident { repr: v }), + Some(v) => Some(ast::ident { repr: v, ctxt: 0 }), None => None, } } From 69f6ac5d31fbd2a4bcf104a818e79d6e4e34c8f7 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Fri, 19 Apr 2013 19:17:34 -0400 Subject: [PATCH 310/403] Fix debug! usage in tutorial --- doc/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 01dd76647f5fd..56629b93b1a49 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1670,7 +1670,7 @@ do spawn { ~~~~ If you want to see the output of `debug!` statements, you will need to turn on `debug!` logging. -To enable `debug!` logging, set the RUST_LOG environment variable to `debug` (e.g., with bash, `export RUST_LOG=debug`) +To enable `debug!` logging, set the RUST_LOG environment variable to the name of your crate, which, for a file named `foo.rs`, will be `foo` (e.g., with bash, `export RUST_LOG=foo`). ## For loops From a1a9326c6d71cb7f3b678f4047a1e958318dd337 Mon Sep 17 00:00:00 2001 From: gifnksm Date: Sat, 20 Apr 2013 10:44:32 +0900 Subject: [PATCH 311/403] libcore: Fix assertion failure in vec::windowe. vec::windowed fails if given window size is greater than vector length + 1. --- src/libcore/vec.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 139fcedad2779..4f2453c4d79ac 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1516,6 +1516,7 @@ pub fn each_permutation(v: &[T], put: &fn(ts: &[T]) -> bool) { #[cfg(stage0)] // XXX: lifetimes! pub fn windowed(n: uint, v: &[T], it: &fn(&[T]) -> bool) { assert!(1u <= n); + if n > v.len() { return; } for uint::range(0, v.len() - n + 1) |i| { if !it(v.slice(i, i+n)) { return } } @@ -1525,6 +1526,7 @@ pub fn windowed(n: uint, v: &[T], it: &fn(&[T]) -> bool) { #[cfg(stage3)] pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) { assert!(1u <= n); + if n > v.len() { return; } for uint::range(0, v.len() - n + 1) |i| { if !it(v.slice(i, i + n)) { return } } @@ -3833,6 +3835,7 @@ mod tests { t(3, &[&[1,2,3],&[2,3,4],&[3,4,5],&[4,5,6]]); t(4, &[&[1,2,3,4],&[2,3,4,5],&[3,4,5,6]]); t(7, &[]); + t(8, &[]); } #[test] From d2b644842a75af44d042f4026a585e4a9cf5979a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 19 Apr 2013 19:21:53 -0700 Subject: [PATCH 312/403] test: xfail some benchmarks that require external libraries or inputs --- src/test/bench/shootout-k-nucleotide.rs | 2 ++ src/test/bench/shootout-pidigits.rs | 2 ++ src/test/bench/shootout-reverse-complement.rs | 1 + 3 files changed, 5 insertions(+) diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 1330e8c892f34..224885a3f79b1 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -1,3 +1,5 @@ +// xfail-test + extern mod std; use core::cast::transmute; diff --git a/src/test/bench/shootout-pidigits.rs b/src/test/bench/shootout-pidigits.rs index 722d72ece8164..38e87358ee214 100644 --- a/src/test/bench/shootout-pidigits.rs +++ b/src/test/bench/shootout-pidigits.rs @@ -1,3 +1,5 @@ +// xfail-test + use core::cast::transmute; use core::from_str::FromStr; use core::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc}; diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index e3774be053cd9..72c01c8d55cfb 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -1,4 +1,5 @@ // xfail-pretty +// xfail-test use core::cast::transmute; use core::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite}; From 93e13e0eee1c14ea8287e448210404f407c84d19 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 19 Apr 2013 18:13:35 -0400 Subject: [PATCH 313/403] Fix an ICE when dereferencing types which cannot be dereferenced --- src/librustc/middle/typeck/check/regionck.rs | 9 +++------ src/test/compile-fail/deref-non-pointer.rs | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index dff794c548bd5..56a8aaecae281 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -413,12 +413,9 @@ fn constrain_derefs(rcx: @mut Rcx, match ty::deref(tcx, derefd_ty, true) { Some(mt) => derefd_ty = mt.ty, - None => { - tcx.sess.span_bug( - deref_expr.span, - fmt!("%?'th deref is of a non-deref'able type `%s`", - i, rcx.fcx.infcx().ty_to_str(derefd_ty))); - } + /* if this type can't be dereferenced, then there's already an error + in the session saying so. Just bail out for now */ + None => break } } } diff --git a/src/test/compile-fail/deref-non-pointer.rs b/src/test/compile-fail/deref-non-pointer.rs index 5f93faef5fc1d..7b1b0f6243ac4 100644 --- a/src/test/compile-fail/deref-non-pointer.rs +++ b/src/test/compile-fail/deref-non-pointer.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:cannot be dereferenced fn main() { - match *1 { + match *1 { //~ ERROR: cannot be dereferenced _ => { fail!(); } } } From be9f4ef65f5a2fa0d3ba610daaf328309130f7fb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 19 Apr 2013 18:13:35 -0400 Subject: [PATCH 314/403] Fix an ICE when dereferencing types which cannot be dereferenced --- src/librustc/middle/typeck/check/regionck.rs | 9 +++------ src/test/compile-fail/deref-non-pointer.rs | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index dff794c548bd5..56a8aaecae281 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -413,12 +413,9 @@ fn constrain_derefs(rcx: @mut Rcx, match ty::deref(tcx, derefd_ty, true) { Some(mt) => derefd_ty = mt.ty, - None => { - tcx.sess.span_bug( - deref_expr.span, - fmt!("%?'th deref is of a non-deref'able type `%s`", - i, rcx.fcx.infcx().ty_to_str(derefd_ty))); - } + /* if this type can't be dereferenced, then there's already an error + in the session saying so. Just bail out for now */ + None => break } } } diff --git a/src/test/compile-fail/deref-non-pointer.rs b/src/test/compile-fail/deref-non-pointer.rs index 5f93faef5fc1d..7b1b0f6243ac4 100644 --- a/src/test/compile-fail/deref-non-pointer.rs +++ b/src/test/compile-fail/deref-non-pointer.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:cannot be dereferenced fn main() { - match *1 { + match *1 { //~ ERROR: cannot be dereferenced _ => { fail!(); } } } From 3c7aea3a6a5fcf04066d0368bfd6618e9494176c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 17 Apr 2013 12:15:08 -0400 Subject: [PATCH 315/403] syntax: de-mode and prepare for de-modeing rustc --- src/libsyntax/abi.rs | 4 +- src/libsyntax/ast.rs | 28 +++--- src/libsyntax/ast_map.rs | 32 +++---- src/libsyntax/ast_util.rs | 22 ++--- src/libsyntax/attr.rs | 8 +- src/libsyntax/codemap.rs | 32 +++---- src/libsyntax/ext/auto_encode.rs | 90 ++++++++++---------- src/libsyntax/ext/base.rs | 6 +- src/libsyntax/ext/build.rs | 74 ++++++++-------- src/libsyntax/ext/deriving/encodable.rs | 2 +- src/libsyntax/ext/deriving/iter_bytes.rs | 2 +- src/libsyntax/ext/deriving/mod.rs | 2 +- src/libsyntax/ext/expand.rs | 4 +- src/libsyntax/ext/pipes/ast_builder.rs | 84 +++++++++--------- src/libsyntax/ext/pipes/parse_proto.rs | 4 +- src/libsyntax/ext/pipes/proto.rs | 12 +-- src/libsyntax/ext/quote.rs | 6 +- src/libsyntax/ext/tt/macro_parser.rs | 24 +++--- src/libsyntax/ext/tt/transcribe.rs | 4 +- src/libsyntax/opt_vec.rs | 14 +-- src/libsyntax/parse/classify.rs | 2 +- src/libsyntax/parse/comments.rs | 2 +- src/libsyntax/parse/common.rs | 4 +- src/libsyntax/parse/mod.rs | 42 ++++----- src/libsyntax/parse/obsolete.rs | 2 +- src/libsyntax/parse/parser.rs | 60 ++++++------- src/libsyntax/print/pp.rs | 4 +- src/libsyntax/print/pprust.rs | 48 +++++------ src/libsyntax/syntax.rc | 5 +- src/libsyntax/visit.rs | 104 +++++++++++------------ 30 files changed, 363 insertions(+), 364 deletions(-) diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index a848f97d2e09e..b6580b4c5a1b2 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -255,13 +255,13 @@ pub impl AbiSet { } impl to_bytes::IterBytes for Abi { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.index().iter_bytes(lsb0, f) } } impl to_bytes::IterBytes for AbiSet { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.bits.iter_bytes(lsb0, f) } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 6f4693adb9f4a..b0b3e45abe501 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -97,7 +97,7 @@ impl Decodable for ident { } impl to_bytes::IterBytes for ident { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.repr.iter_bytes(lsb0, f) } } @@ -284,7 +284,7 @@ pub enum binding_mode { } impl to_bytes::IterBytes for binding_mode { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { bind_by_copy => 0u8.iter_bytes(lsb0, f), @@ -330,7 +330,7 @@ pub enum pat_ { pub enum mutability { m_mutbl, m_imm, m_const, } impl to_bytes::IterBytes for mutability { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -345,7 +345,7 @@ pub enum Sigil { } impl to_bytes::IterBytes for Sigil { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f) } } @@ -428,7 +428,7 @@ pub enum inferable { } impl to_bytes::IterBytes for inferable { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { expl(ref t) => to_bytes::iter_bytes_2(&0u8, t, lsb0, f), @@ -446,7 +446,7 @@ impl to_bytes::IterBytes for inferable { pub enum rmode { by_ref, by_copy } impl to_bytes::IterBytes for rmode { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -781,7 +781,7 @@ impl ToStr for int_ty { } impl to_bytes::IterBytes for int_ty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -798,7 +798,7 @@ impl ToStr for uint_ty { } impl to_bytes::IterBytes for uint_ty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -815,7 +815,7 @@ impl ToStr for float_ty { } impl to_bytes::IterBytes for float_ty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -860,7 +860,7 @@ impl ToStr for Onceness { } impl to_bytes::IterBytes for Onceness { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f); } } @@ -911,7 +911,7 @@ pub enum ty_ { } impl to_bytes::IterBytes for Ty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f); } } @@ -979,7 +979,7 @@ impl ToStr for purity { } impl to_bytes::IterBytes for purity { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -994,7 +994,7 @@ pub enum ret_style { } impl to_bytes::IterBytes for ret_style { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } @@ -1268,7 +1268,7 @@ pub enum item_ { pub enum struct_mutability { struct_mutable, struct_immutable } impl to_bytes::IterBytes for struct_mutability { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) } } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 147d8227b81ea..05e67196b4c15 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -115,7 +115,7 @@ pub struct Ctx { pub type vt = visit::vt<@mut Ctx>; -pub fn extend(cx: @mut Ctx, +elt: ident) -> @path { +pub fn extend(cx: @mut Ctx, elt: ident) -> @path { @(vec::append(copy cx.path, ~[path_name(elt)])) } @@ -132,7 +132,7 @@ pub fn mk_ast_map_visitor() -> vt { }); } -pub fn map_crate(diag: @span_handler, c: crate) -> map { +pub fn map_crate(diag: @span_handler, c: @crate) -> map { let cx = @mut Ctx { map: @mut HashMap::new(), path: ~[], @@ -148,8 +148,8 @@ pub fn map_crate(diag: @span_handler, c: crate) -> map { // the item itself. pub fn map_decoded_item(diag: @span_handler, map: map, - +path: path, - ii: inlined_item) { + path: path, + ii: &inlined_item) { // I believe it is ok for the local IDs of inlined items from other crates // to overlap with the local ids from this crate, so just generate the ids // starting from 0. (In particular, I think these ids are only used in @@ -167,7 +167,7 @@ pub fn map_decoded_item(diag: @span_handler, // methods get added to the AST map when their impl is visited. Since we // don't decode and instantiate the impl, but just the method, we have to // add it to the table now: - match ii { + match *ii { ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, @@ -190,7 +190,7 @@ pub fn map_fn( body: &blk, sp: codemap::span, id: node_id, - &&cx: @mut Ctx, + cx: @mut Ctx, v: visit::vt<@mut Ctx> ) { for decl.inputs.each |a| { @@ -222,7 +222,7 @@ pub fn map_fn( visit::visit_fn(fk, decl, body, sp, id, cx, v); } -pub fn map_block(b: &blk, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { +pub fn map_block(b: &blk, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { cx.map.insert(b.node.id, node_block(/* FIXME (#2543) */ copy *b)); visit::visit_block(b, cx, v); } @@ -239,24 +239,24 @@ pub fn number_pat(cx: @mut Ctx, pat: @pat) { }; } -pub fn map_local(loc: @local, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { +pub fn map_local(loc: @local, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { number_pat(cx, loc.node.pat); visit::visit_local(loc, cx, v); } -pub fn map_arm(arm: &arm, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { +pub fn map_arm(arm: &arm, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { number_pat(cx, arm.pats[0]); visit::visit_arm(arm, cx, v); } pub fn map_method(impl_did: def_id, impl_path: @path, - m: @method, &&cx: @mut Ctx) { + m: @method, cx: @mut Ctx) { cx.map.insert(m.id, node_method(m, impl_did, impl_path)); cx.map.insert(m.self_id, node_local(cx.local_id)); cx.local_id += 1u; } -pub fn map_item(i: @item, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { +pub fn map_item(i: @item, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { let item_path = @/* FIXME (#2543) */ copy cx.path; cx.map.insert(i.id, node_item(i, item_path)); match i.node { @@ -355,13 +355,13 @@ pub fn map_struct_def( } } -pub fn map_expr(ex: @expr, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { +pub fn map_expr(ex: @expr, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { cx.map.insert(ex.id, node_expr(ex)); visit::visit_expr(ex, cx, v); } -pub fn map_stmt(stmt: @stmt, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { - cx.map.insert(stmt_id(*stmt), node_stmt(stmt)); +pub fn map_stmt(stmt: @stmt, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { + cx.map.insert(stmt_id(stmt), node_stmt(stmt)); visit::visit_stmt(stmt, cx, v); } @@ -408,7 +408,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { } Some(&node_stmt(stmt)) => { fmt!("stmt %s (id=%?)", - pprust::stmt_to_str(*stmt, itr), id) + pprust::stmt_to_str(stmt, itr), id) } Some(&node_arg(_, _)) => { // add more info here fmt!("arg (id=%?)", id) @@ -430,7 +430,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { pub fn node_item_query(items: map, id: node_id, query: &fn(@item) -> Result, - +error_msg: ~str) -> Result { + error_msg: ~str) -> Result { match items.find(&id) { Some(&node_item(it, _)) => query(it), _ => fail!(error_msg) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 59a640bb57163..910c9857d2d63 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -39,7 +39,7 @@ pub fn local_def(id: node_id) -> def_id { pub fn is_local(did: ast::def_id) -> bool { did.crate == local_crate } -pub fn stmt_id(s: stmt) -> node_id { +pub fn stmt_id(s: &stmt) -> node_id { match s.node { stmt_decl(_, id) => id, stmt_expr(_, id) => id, @@ -200,7 +200,7 @@ pub fn is_call_expr(e: @expr) -> bool { // This makes def_id hashable impl to_bytes::IterBytes for def_id { #[inline(always)] - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f); } } @@ -211,7 +211,7 @@ pub fn block_from_expr(e: @expr) -> blk { } pub fn default_block( - +stmts1: ~[@stmt], + stmts1: ~[@stmt], expr1: Option<@expr>, id1: node_id ) -> blk_ { @@ -224,7 +224,7 @@ pub fn default_block( } } -pub fn ident_to_path(s: span, +i: ident) -> @Path { +pub fn ident_to_path(s: span, i: ident) -> @Path { @ast::Path { span: s, global: false, idents: ~[i], @@ -232,7 +232,7 @@ pub fn ident_to_path(s: span, +i: ident) -> @Path { types: ~[] } } -pub fn ident_to_pat(id: node_id, s: span, +i: ident) -> @pat { +pub fn ident_to_pat(id: node_id, s: span, i: ident) -> @pat { @ast::pat { id: id, node: pat_ident(bind_by_copy, ident_to_path(s, i), None), span: s } @@ -300,7 +300,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility { pub trait inlined_item_utils { fn ident(&self) -> ident; fn id(&self) -> ast::node_id; - fn accept(&self, e: E, v: visit::vt); + fn accept(&self, e: E, v: visit::vt); } impl inlined_item_utils for inlined_item { @@ -322,7 +322,7 @@ impl inlined_item_utils for inlined_item { } } - fn accept(&self, e: E, v: visit::vt) { + fn accept(&self, e: E, v: visit::vt) { match *self { ii_item(i) => (v.visit_item)(i, e, v), ii_foreign(i) => (v.visit_foreign_item)(i, e, v), @@ -435,7 +435,7 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { visit_local: |l| vfn(l.node.id), visit_block: |b| vfn(b.node.id), - visit_stmt: |s| vfn(ast_util::stmt_id(*s)), + visit_stmt: |s| vfn(ast_util::stmt_id(s)), visit_arm: |_| {}, visit_pat: |p| vfn(p.id), visit_decl: |_| {}, @@ -491,7 +491,7 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { }) } -pub fn visit_ids_for_inlined_item(item: inlined_item, vfn: @fn(node_id)) { +pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(node_id)) { item.accept((), id_visitor(vfn)); } @@ -505,7 +505,7 @@ pub fn compute_id_range(visit_ids_fn: &fn(@fn(node_id))) -> id_range { id_range { min: *min, max: *max } } -pub fn compute_id_range_for_inlined_item(item: inlined_item) -> id_range { +pub fn compute_id_range_for_inlined_item(item: &inlined_item) -> id_range { compute_id_range(|f| visit_ids_for_inlined_item(item, f)) } @@ -609,7 +609,7 @@ pub fn mk_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable) pub fn mk_sctable() -> SCTable { ~[EmptyCtxt] } /// Add a value to the end of a vec, return its index -fn idx_push(vec: &mut ~[T], +val: T) -> uint { +fn idx_push(vec: &mut ~[T], val: T) -> uint { vec.push(val); vec.len() - 1 } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 5063a0381e782..98cfdd33ef6b6 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -31,12 +31,12 @@ pub fn mk_name_value_item_str(name: @~str, value: @~str) mk_name_value_item(name, value_lit) } -pub fn mk_name_value_item(name: @~str, +value: ast::lit) +pub fn mk_name_value_item(name: @~str, value: ast::lit) -> @ast::meta_item { @dummy_spanned(ast::meta_name_value(name, value)) } -pub fn mk_list_item(name: @~str, +items: ~[@ast::meta_item]) -> +pub fn mk_list_item(name: @~str, items: ~[@ast::meta_item]) -> @ast::meta_item { @dummy_spanned(ast::meta_list(name, items)) } @@ -51,8 +51,8 @@ pub fn mk_attr(item: @ast::meta_item) -> ast::attribute { is_sugared_doc: false }) } -pub fn mk_sugared_doc_attr(+text: ~str, - +lo: BytePos, +hi: BytePos) -> ast::attribute { +pub fn mk_sugared_doc_attr(text: ~str, + lo: BytePos, hi: BytePos) -> ast::attribute { let style = doc_comment_style(text); let lit = spanned(lo, hi, ast::lit_str(@text)); let attr = ast::attribute_ { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 0ed371d9c9afe..bd8aa7011b7b7 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -71,7 +71,7 @@ impl Sub for BytePos { } impl to_bytes::IterBytes for BytePos { - fn iter_bytes(&self, +lsb0: bool, &&f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (**self).iter_bytes(lsb0, f) } } @@ -89,7 +89,7 @@ impl cmp::Ord for CharPos { } impl to_bytes::IterBytes for CharPos { - fn iter_bytes(&self, +lsb0: bool, &&f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (**self).iter_bytes(lsb0, f) } } @@ -141,20 +141,20 @@ impl Decodable for span { } } -pub fn spanned(+lo: BytePos, +hi: BytePos, +t: T) -> spanned { +pub fn spanned(lo: BytePos, hi: BytePos, t: T) -> spanned { respan(mk_sp(lo, hi), t) } -pub fn respan(sp: span, +t: T) -> spanned { +pub fn respan(sp: span, t: T) -> spanned { spanned {node: t, span: sp} } -pub fn dummy_spanned(+t: T) -> spanned { +pub fn dummy_spanned(t: T) -> spanned { respan(dummy_sp(), t) } /* assuming that we're not in macro expansion */ -pub fn mk_sp(+lo: BytePos, +hi: BytePos) -> span { +pub fn mk_sp(lo: BytePos, hi: BytePos) -> span { span {lo: lo, hi: hi, expn_info: None} } @@ -247,7 +247,7 @@ pub impl FileMap { // UNCHECKED INVARIANT: these offsets must be added in the right // order and must be in the right places; there is shared knowledge // about what ends a line between this file and parse.rs - fn next_line(&self, +pos: BytePos) { + fn next_line(&self, pos: BytePos) { // the new charpos must be > the last one (or it's the first one). let lines = &mut *self.lines; assert!((lines.len() == 0) || (lines[lines.len() - 1] < pos)); @@ -287,14 +287,14 @@ pub impl CodeMap { } /// Add a new FileMap to the CodeMap and return it - fn new_filemap(&self, +filename: FileName, src: @~str) -> @FileMap { + fn new_filemap(&self, filename: FileName, src: @~str) -> @FileMap { return self.new_filemap_w_substr(filename, FssNone, src); } fn new_filemap_w_substr( &self, - +filename: FileName, - +substr: FileSubstr, + filename: FileName, + substr: FileSubstr, src: @~str ) -> @FileMap { let files = &mut *self.files; @@ -325,11 +325,11 @@ pub impl CodeMap { } /// Lookup source information about a BytePos - pub fn lookup_char_pos(&self, +pos: BytePos) -> Loc { + pub fn lookup_char_pos(&self, pos: BytePos) -> Loc { return self.lookup_pos(pos); } - pub fn lookup_char_pos_adj(&self, +pos: BytePos) -> LocWithOpt + pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt { let loc = self.lookup_char_pos(pos); match (loc.file.substr) { @@ -405,7 +405,7 @@ pub impl CodeMap { priv impl CodeMap { - fn lookup_filemap_idx(&self, +pos: BytePos) -> uint { + fn lookup_filemap_idx(&self, pos: BytePos) -> uint { let files = &*self.files; let len = files.len(); let mut a = 0u; @@ -440,7 +440,7 @@ priv impl CodeMap { return FileMapAndLine {fm: f, line: a}; } - fn lookup_pos(&self, +pos: BytePos) -> Loc { + fn lookup_pos(&self, pos: BytePos) -> Loc { let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); let line = a + 1u; // Line numbers start at 1 let chpos = self.bytepos_to_local_charpos(pos); @@ -466,7 +466,7 @@ priv impl CodeMap { lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint()) } - fn lookup_byte_offset(&self, +bpos: BytePos) + fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos { let idx = self.lookup_filemap_idx(bpos); let fm = self.files[idx]; @@ -476,7 +476,7 @@ priv impl CodeMap { // Converts an absolute BytePos to a CharPos relative to the file it is // located in - fn bytepos_to_local_charpos(&self, +bpos: BytePos) -> CharPos { + fn bytepos_to_local_charpos(&self, bpos: BytePos) -> CharPos { debug!("codemap: converting %? to char pos", bpos); let idx = self.lookup_filemap_idx(bpos); let map = self.files[idx]; diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index e53a8f361b5fe..67c09c00733f8 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -239,7 +239,7 @@ priv impl @ext_ctxt { } } - fn expr(&self, span: span, +node: ast::expr_) -> @ast::expr { + fn expr(&self, span: span, node: ast::expr_) -> @ast::expr { @ast::expr { id: self.next_id(), callee_id: self.next_id(), @@ -248,7 +248,7 @@ priv impl @ext_ctxt { } } - fn path(&self, span: span, +strs: ~[ast::ident]) -> @ast::Path { + fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { @ast::Path { span: span, global: false, @@ -258,7 +258,7 @@ priv impl @ext_ctxt { } } - fn path_global(&self, span: span, +strs: ~[ast::ident]) -> @ast::Path { + fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { @ast::Path { span: span, global: true, @@ -271,8 +271,8 @@ priv impl @ext_ctxt { fn path_tps( &self, span: span, - +strs: ~[ast::ident], - +tps: ~[@ast::Ty] + strs: ~[ast::ident], + tps: ~[@ast::Ty] ) -> @ast::Path { @ast::Path { span: span, @@ -286,8 +286,8 @@ priv impl @ext_ctxt { fn path_tps_global( &self, span: span, - +strs: ~[ast::ident], - +tps: ~[@ast::Ty] + strs: ~[ast::ident], + tps: ~[@ast::Ty] ) -> @ast::Path { @ast::Path { span: span, @@ -301,8 +301,8 @@ priv impl @ext_ctxt { fn ty_path( &self, span: span, - +strs: ~[ast::ident], - +tps: ~[@ast::Ty] + strs: ~[ast::ident], + tps: ~[@ast::Ty] ) -> @ast::Ty { @ast::Ty { id: self.next_id(), @@ -349,13 +349,13 @@ priv impl @ext_ctxt { span: span})) } - fn lambda(&self, +blk: ast::blk) -> @ast::expr { + fn lambda(&self, blk: ast::blk) -> @ast::expr { let ext_cx = *self; let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); quote_expr!( || $blk_e ) } - fn blk(&self, span: span, +stmts: ~[@ast::stmt]) -> ast::blk { + fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk { codemap::spanned { node: ast::blk_ { view_items: ~[], @@ -381,19 +381,19 @@ priv impl @ext_ctxt { } } - fn expr_path(&self, span: span, +strs: ~[ast::ident]) -> @ast::expr { + fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr { self.expr(span, ast::expr_path(self.path(span, strs))) } fn expr_path_global( &self, span: span, - +strs: ~[ast::ident] + strs: ~[ast::ident] ) -> @ast::expr { self.expr(span, ast::expr_path(self.path_global(span, strs))) } - fn expr_var(&self, span: span, +var: ~str) -> @ast::expr { + fn expr_var(&self, span: span, var: ~str) -> @ast::expr { self.expr_path(span, ~[self.ident_of(var)]) } @@ -410,7 +410,7 @@ priv impl @ext_ctxt { &self, span: span, expr: @ast::expr, - +args: ~[@ast::expr] + args: ~[@ast::expr] ) -> @ast::expr { self.expr(span, ast::expr_call(expr, args, ast::NoSugar)) } @@ -420,7 +420,7 @@ priv impl @ext_ctxt { span: span, expr: @ast::expr, ident: ast::ident, - +args: ~[@ast::expr] + args: ~[@ast::expr] ) -> @ast::expr { self.expr(span, ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar)) } @@ -429,7 +429,7 @@ priv impl @ext_ctxt { self.lambda(self.expr_blk(expr)) } - fn lambda_stmts(&self, span: span, +stmts: ~[@ast::stmt]) -> @ast::expr { + fn lambda_stmts(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr { self.lambda(self.blk(span, stmts)) } } @@ -597,7 +597,7 @@ fn mk_deser_impl( fn mk_ser_method( cx: @ext_ctxt, span: span, - +ser_body: ast::blk + ser_body: ast::blk ) -> @ast::method { let ty_s = @ast::Ty { id: cx.next_id(), @@ -660,7 +660,7 @@ fn mk_deser_method( cx: @ext_ctxt, span: span, ty: @ast::Ty, - +deser_body: ast::blk + deser_body: ast::blk ) -> @ast::method { let ty_d = @ast::Ty { id: cx.next_id(), @@ -864,7 +864,7 @@ fn mk_enum_ser_impl( cx: @ext_ctxt, span: span, ident: ast::ident, - +enum_def: ast::enum_def, + enum_def: ast::enum_def, generics: &ast::Generics ) -> @ast::item { let body = mk_enum_ser_body( @@ -881,7 +881,7 @@ fn mk_enum_deser_impl( cx: @ext_ctxt, span: span, ident: ast::ident, - +enum_def: ast::enum_def, + enum_def: ast::enum_def, generics: &ast::Generics ) -> @ast::item { let body = mk_enum_deser_body( @@ -974,7 +974,7 @@ fn mk_enum_ser_body( cx: @ext_ctxt, span: span, name: ast::ident, - +variants: ~[ast::variant] + variants: ~[ast::variant] ) -> @ast::expr { let arms = do variants.mapi |v_idx, variant| { match variant.node.kind { @@ -1219,37 +1219,37 @@ mod test { impl Encoder for TestEncoder { fn emit_nil(&self) { self.add_to_log(CallToEmitNil) } - fn emit_uint(&self, +v: uint) {self.add_to_log(CallToEmitUint(v)); } - fn emit_u64(&self, +_v: u64) { self.add_unknown_to_log(); } - fn emit_u32(&self, +_v: u32) { self.add_unknown_to_log(); } - fn emit_u16(&self, +_v: u16) { self.add_unknown_to_log(); } - fn emit_u8(&self, +_v: u8) { self.add_unknown_to_log(); } + fn emit_uint(&self, v: uint) {self.add_to_log(CallToEmitUint(v)); } + fn emit_u64(&self, _v: u64) { self.add_unknown_to_log(); } + fn emit_u32(&self, _v: u32) { self.add_unknown_to_log(); } + fn emit_u16(&self, _v: u16) { self.add_unknown_to_log(); } + fn emit_u8(&self, _v: u8) { self.add_unknown_to_log(); } - fn emit_int(&self, +_v: int) { self.add_unknown_to_log(); } - fn emit_i64(&self, +_v: i64) { self.add_unknown_to_log(); } - fn emit_i32(&self, +_v: i32) { self.add_unknown_to_log(); } - fn emit_i16(&self, +_v: i16) { self.add_unknown_to_log(); } - fn emit_i8(&self, +_v: i8) { self.add_unknown_to_log(); } + fn emit_int(&self, _v: int) { self.add_unknown_to_log(); } + fn emit_i64(&self, _v: i64) { self.add_unknown_to_log(); } + fn emit_i32(&self, _v: i32) { self.add_unknown_to_log(); } + fn emit_i16(&self, _v: i16) { self.add_unknown_to_log(); } + fn emit_i8(&self, _v: i8) { self.add_unknown_to_log(); } - fn emit_bool(&self, +_v: bool) { self.add_unknown_to_log(); } + fn emit_bool(&self, _v: bool) { self.add_unknown_to_log(); } - fn emit_f64(&self, +_v: f64) { self.add_unknown_to_log(); } - fn emit_f32(&self, +_v: f32) { self.add_unknown_to_log(); } - fn emit_float(&self, +_v: float) { self.add_unknown_to_log(); } + fn emit_f64(&self, _v: f64) { self.add_unknown_to_log(); } + fn emit_f32(&self, _v: f32) { self.add_unknown_to_log(); } + fn emit_float(&self, _v: float) { self.add_unknown_to_log(); } - fn emit_char(&self, +_v: char) { self.add_unknown_to_log(); } - fn emit_str(&self, +_v: &str) { self.add_unknown_to_log(); } + fn emit_char(&self, _v: char) { self.add_unknown_to_log(); } + fn emit_str(&self, _v: &str) { self.add_unknown_to_log(); } fn emit_enum(&self, name: &str, f: &fn()) { self.add_to_log(CallToEmitEnum(name.to_str())); f(); } - fn emit_enum_variant(&self, name: &str, +id: uint, - +cnt: uint, f: &fn()) { + fn emit_enum_variant(&self, name: &str, id: uint, + cnt: uint, f: &fn()) { self.add_to_log(CallToEmitEnumVariant (name.to_str(),id,cnt)); f(); } - fn emit_enum_variant_arg(&self, +idx: uint, f: &fn()) { + fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) { self.add_to_log(CallToEmitEnumVariantArg (idx)); f(); } @@ -1261,10 +1261,10 @@ mod test { self.emit_enum_variant_arg(idx, f) } - fn emit_struct(&self, name: &str, +len: uint, f: &fn()) { + fn emit_struct(&self, name: &str, len: uint, f: &fn()) { self.add_to_log(CallToEmitStruct (name.to_str(),len)); f(); } - fn emit_struct_field(&self, name: &str, +idx: uint, f: &fn()) { + fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) { self.add_to_log(CallToEmitField (name.to_str(),idx)); f(); } @@ -1294,10 +1294,10 @@ mod test { f(); } - fn emit_seq(&self, +_len: uint, f: &fn()) { + fn emit_seq(&self, _len: uint, f: &fn()) { self.add_unknown_to_log(); f(); } - fn emit_seq_elt(&self, +_idx: uint, f: &fn()) { + fn emit_seq_elt(&self, _idx: uint, f: &fn()) { self.add_unknown_to_log(); f(); } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 886af694920f7..4eb48d12bfeab 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -238,7 +238,7 @@ pub trait ext_ctxt { fn ident_of(@mut self, st: ~str) -> ast::ident; } -pub fn mk_ctxt(parse_sess: @mut parse::ParseSess, +cfg: ast::crate_cfg) +pub fn mk_ctxt(parse_sess: @mut parse::ParseSess, cfg: ast::crate_cfg) -> @ext_ctxt { struct CtxtRepr { parse_sess: @mut parse::ParseSess, @@ -439,7 +439,7 @@ pub enum MapChain { impl MapChain{ // Constructor. I don't think we need a zero-arg one. - fn new(+init: ~HashMap) -> @mut MapChain { + fn new(init: ~HashMap) -> @mut MapChain { @mut BaseMapChain(init) } @@ -509,7 +509,7 @@ impl MapChain{ } // insert the binding into the top-level map - fn insert (&mut self, +key: K, +ext: @V) -> bool { + fn insert (&mut self, key: K, ext: @V) -> bool { // can't abstract over get_map because of flow sensitivity... match *self { BaseMapChain (~ref mut map) => map.insert(key, ext), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b375adef9263d..ff78ddb803cde 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -27,7 +27,7 @@ pub struct Field { pub fn mk_expr(cx: @ext_ctxt, sp: codemap::span, - +expr: ast::expr_) + expr: ast::expr_) -> @ast::expr { @ast::expr { id: cx.next_id(), @@ -63,12 +63,12 @@ pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr) cx.next_id(); // see ast_util::op_expr_callee_id mk_expr(cx, sp, ast::expr_unary(op, e)) } -pub fn mk_raw_path(sp: span, +idents: ~[ast::ident]) -> @ast::Path { +pub fn mk_raw_path(sp: span, idents: ~[ast::ident]) -> @ast::Path { mk_raw_path_(sp, idents, ~[]) } pub fn mk_raw_path_(sp: span, - +idents: ~[ast::ident], - +types: ~[@ast::Ty]) + idents: ~[ast::ident], + types: ~[@ast::Ty]) -> @ast::Path { @ast::Path { span: sp, global: false, @@ -76,23 +76,23 @@ pub fn mk_raw_path_(sp: span, rp: None, types: types } } -pub fn mk_raw_path_global(sp: span, +idents: ~[ast::ident]) -> @ast::Path { +pub fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::Path { mk_raw_path_global_(sp, idents, ~[]) } pub fn mk_raw_path_global_(sp: span, - +idents: ~[ast::ident], - +types: ~[@ast::Ty]) -> @ast::Path { + idents: ~[ast::ident], + types: ~[@ast::Ty]) -> @ast::Path { @ast::Path { span: sp, global: true, idents: idents, rp: None, types: types } } -pub fn mk_path(cx: @ext_ctxt, sp: span, +idents: ~[ast::ident]) +pub fn mk_path(cx: @ext_ctxt, sp: span, idents: ~[ast::ident]) -> @ast::expr { mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents))) } -pub fn mk_path_global(cx: @ext_ctxt, sp: span, +idents: ~[ast::ident]) +pub fn mk_path_global(cx: @ext_ctxt, sp: span, idents: ~[ast::ident]) -> @ast::expr { mk_expr(cx, sp, ast::expr_path(mk_raw_path_global(sp, idents))) } @@ -100,7 +100,7 @@ pub fn mk_access_(cx: @ext_ctxt, sp: span, p: @ast::expr, m: ast::ident) -> @ast::expr { mk_expr(cx, sp, ast::expr_field(p, m, ~[])) } -pub fn mk_access(cx: @ext_ctxt, sp: span, +p: ~[ast::ident], m: ast::ident) +pub fn mk_access(cx: @ext_ctxt, sp: span, p: ~[ast::ident], m: ast::ident) -> @ast::expr { let pathexpr = mk_path(cx, sp, p); return mk_access_(cx, sp, pathexpr, m); @@ -115,25 +115,25 @@ pub fn mk_method_call(cx: @ext_ctxt, sp: span, rcvr_expr: @ast::expr, method_ident: ast::ident, - +args: ~[@ast::expr]) -> @ast::expr { + args: ~[@ast::expr]) -> @ast::expr { mk_expr(cx, sp, ast::expr_method_call(rcvr_expr, method_ident, ~[], args, ast::NoSugar)) } pub fn mk_call_(cx: @ext_ctxt, sp: span, fn_expr: @ast::expr, - +args: ~[@ast::expr]) -> @ast::expr { + args: ~[@ast::expr]) -> @ast::expr { mk_expr(cx, sp, ast::expr_call(fn_expr, args, ast::NoSugar)) } -pub fn mk_call(cx: @ext_ctxt, sp: span, +fn_path: ~[ast::ident], - +args: ~[@ast::expr]) -> @ast::expr { +pub fn mk_call(cx: @ext_ctxt, sp: span, fn_path: ~[ast::ident], + args: ~[@ast::expr]) -> @ast::expr { let pathexpr = mk_path(cx, sp, fn_path); return mk_call_(cx, sp, pathexpr, args); } -pub fn mk_call_global(cx: @ext_ctxt, sp: span, +fn_path: ~[ast::ident], - +args: ~[@ast::expr]) -> @ast::expr { +pub fn mk_call_global(cx: @ext_ctxt, sp: span, fn_path: ~[ast::ident], + args: ~[@ast::expr]) -> @ast::expr { let pathexpr = mk_path_global(cx, sp, fn_path); return mk_call_(cx, sp, pathexpr, args); } // e = expr, t = type -pub fn mk_base_vec_e(cx: @ext_ctxt, sp: span, +exprs: ~[@ast::expr]) +pub fn mk_base_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { let vecexpr = ast::expr_vec(exprs, ast::m_imm); mk_expr(cx, sp, vecexpr) @@ -143,20 +143,20 @@ pub fn mk_vstore_e(cx: @ext_ctxt, sp: span, expr: @ast::expr, @ast::expr { mk_expr(cx, sp, ast::expr_vstore(expr, vst)) } -pub fn mk_uniq_vec_e(cx: @ext_ctxt, sp: span, +exprs: ~[@ast::expr]) +pub fn mk_uniq_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), ast::expr_vstore_uniq) } -pub fn mk_slice_vec_e(cx: @ext_ctxt, sp: span, +exprs: ~[@ast::expr]) +pub fn mk_slice_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), ast::expr_vstore_slice) } -pub fn mk_base_str(cx: @ext_ctxt, sp: span, +s: ~str) -> @ast::expr { +pub fn mk_base_str(cx: @ext_ctxt, sp: span, s: ~str) -> @ast::expr { let lit = ast::lit_str(@s); return mk_lit(cx, sp, lit); } -pub fn mk_uniq_str(cx: @ext_ctxt, sp: span, +s: ~str) -> @ast::expr { +pub fn mk_uniq_str(cx: @ext_ctxt, sp: span, s: ~str) -> @ast::expr { mk_vstore_e(cx, sp, mk_base_str(cx, sp, s), ast::expr_vstore_uniq) } pub fn mk_field(sp: span, f: &Field) -> ast::field { @@ -170,8 +170,8 @@ pub fn mk_fields(sp: span, fields: ~[Field]) -> ~[ast::field] { } pub fn mk_struct_e(cx: @ext_ctxt, sp: span, - +ctor_path: ~[ast::ident], - +fields: ~[Field]) + ctor_path: ~[ast::ident], + fields: ~[Field]) -> @ast::expr { mk_expr(cx, sp, ast::expr_struct(mk_raw_path(sp, ctor_path), @@ -180,8 +180,8 @@ pub fn mk_struct_e(cx: @ext_ctxt, } pub fn mk_global_struct_e(cx: @ext_ctxt, sp: span, - +ctor_path: ~[ast::ident], - +fields: ~[Field]) + ctor_path: ~[ast::ident], + fields: ~[Field]) -> @ast::expr { mk_expr(cx, sp, ast::expr_struct(mk_raw_path_global(sp, ctor_path), @@ -190,7 +190,7 @@ pub fn mk_global_struct_e(cx: @ext_ctxt, } pub fn mk_glob_use(cx: @ext_ctxt, sp: span, - +path: ~[ast::ident]) -> @ast::view_item { + path: ~[ast::ident]) -> @ast::view_item { let glob = @codemap::spanned { node: ast::view_path_glob(mk_raw_path(sp, path), cx.next_id()), span: sp, @@ -226,8 +226,8 @@ pub fn mk_local(cx: @ext_ctxt, sp: span, mutbl: bool, @codemap::spanned { node: ast::stmt_decl(@decl, cx.next_id()), span: sp } } pub fn mk_block(cx: @ext_ctxt, span: span, - +view_items: ~[@ast::view_item], - +stmts: ~[@ast::stmt], + view_items: ~[@ast::view_item], + stmts: ~[@ast::stmt], expr: Option<@ast::expr>) -> @ast::expr { let blk = codemap::spanned { node: ast::blk_ { @@ -243,7 +243,7 @@ pub fn mk_block(cx: @ext_ctxt, span: span, } pub fn mk_block_(cx: @ext_ctxt, span: span, - +stmts: ~[@ast::stmt]) + stmts: ~[@ast::stmt]) -> ast::blk { codemap::spanned { node: ast::blk_ { @@ -307,7 +307,7 @@ pub fn mk_copy(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { pub fn mk_managed(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { mk_expr(cx, sp, ast::expr_unary(ast::box(ast::m_imm), e)) } -pub fn mk_pat(cx: @ext_ctxt, span: span, +pat: ast::pat_) -> @ast::pat { +pub fn mk_pat(cx: @ext_ctxt, span: span, pat: ast::pat_) -> @ast::pat { @ast::pat { id: cx.next_id(), node: pat, span: span } } pub fn mk_pat_wild(cx: @ext_ctxt, span: span) -> @ast::pat { @@ -335,7 +335,7 @@ pub fn mk_pat_ident_with_binding_mode(cx: @ext_ctxt, pub fn mk_pat_enum(cx: @ext_ctxt, span: span, path: @ast::Path, - +subpats: ~[@ast::pat]) + subpats: ~[@ast::pat]) -> @ast::pat { let pat = ast::pat_enum(path, Some(subpats)); mk_pat(cx, span, pat) @@ -343,7 +343,7 @@ pub fn mk_pat_enum(cx: @ext_ctxt, pub fn mk_pat_struct(cx: @ext_ctxt, span: span, path: @ast::Path, - +field_pats: ~[ast::field_pat]) + field_pats: ~[ast::field_pat]) -> @ast::pat { let pat = ast::pat_struct(path, field_pats, false); mk_pat(cx, span, pat) @@ -360,7 +360,7 @@ pub fn mk_stmt(cx: @ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt { } pub fn mk_ty_path(cx: @ext_ctxt, span: span, - +idents: ~[ ast::ident ]) + idents: ~[ ast::ident ]) -> @ast::Ty { let ty = build::mk_raw_path(span, idents); let ty = ast::ty_path(ty, cx.next_id()); @@ -369,7 +369,7 @@ pub fn mk_ty_path(cx: @ext_ctxt, } pub fn mk_ty_path_global(cx: @ext_ctxt, span: span, - +idents: ~[ ast::ident ]) + idents: ~[ ast::ident ]) -> @ast::Ty { let ty = build::mk_raw_path_global(span, idents); let ty = ast::ty_path(ty, cx.next_id()); @@ -399,7 +399,7 @@ pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty { } pub fn mk_trait_ref_global(cx: @ext_ctxt, span: span, - +idents: ~[ ast::ident ]) + idents: ~[ ast::ident ]) -> @ast::trait_ref { mk_trait_ref_(cx, build::mk_raw_path_global(span, idents)) @@ -430,12 +430,12 @@ pub fn mk_arg(cx: @ext_ctxt, id: cx.next_id() } } -pub fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { +pub fn mk_fn_decl(inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { ast::fn_decl { inputs: inputs, output: output, cf: ast::return_val } } pub fn mk_trait_ty_param_bound_global(cx: @ext_ctxt, span: span, - +idents: ~[ast::ident]) + idents: ~[ast::ident]) -> ast::TyParamBound { ast::TraitTyParamBound(mk_trait_ref_global(cx, span, idents)) } diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 9776f484818cc..6fd27c5f3d732 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -91,7 +91,7 @@ fn create_derived_encodable_impl( fn create_encode_method( cx: @ext_ctxt, span: span, - +statements: ~[@stmt] + statements: ~[@stmt] ) -> @method { // Create the `e` parameter. let e_arg_type = build::mk_ty_rptr( diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index 75215b90eb0da..85592d142abcf 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -64,7 +64,7 @@ fn create_derived_iter_bytes_impl(cx: @ext_ctxt, // signature of the `iter_bytes` method. fn create_iter_bytes_method(cx: @ext_ctxt, span: span, - +statements: ~[@stmt]) + statements: ~[@stmt]) -> @method { // Create the `lsb0` parameter. let bool_ident = cx.ident_of(~"bool"); diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 78faf5556b2ce..577cf4c01cfde 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -142,7 +142,7 @@ pub fn expand_deriving(cx: @ext_ctxt, result } -fn create_impl_item(cx: @ext_ctxt, span: span, +item: item_) -> @item { +fn create_impl_item(cx: @ext_ctxt, span: span, item: item_) -> @item { let doc_attr = respan(span, ast::lit_str(@~"Automatically derived.")); let doc_attr = respan(span, ast::meta_name_value(@~"doc", doc_attr)); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 430402a8982fc..61032429c93a7 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -237,8 +237,8 @@ macro_rules! without_macro_scoping( // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. -pub fn expand_item_mac(+extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, &&it: @ast::item, +pub fn expand_item_mac(extsbox: @mut SyntaxEnv, + cx: @ext_ctxt, it: @ast::item, fld: @ast_fold) -> Option<@ast::item> { let (pth, tts) = match it.node { diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 5eea58b89b1c6..e0f6c90f5b378 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -34,7 +34,7 @@ mod syntax { pub use parse; } -pub fn path(+ids: ~[ident], span: span) -> @ast::Path { +pub fn path(ids: ~[ident], span: span) -> @ast::Path { @ast::Path { span: span, global: false, idents: ids, @@ -42,7 +42,7 @@ pub fn path(+ids: ~[ident], span: span) -> @ast::Path { types: ~[] } } -pub fn path_global(+ids: ~[ident], span: span) -> @ast::Path { +pub fn path_global(ids: ~[ident], span: span) -> @ast::Path { @ast::Path { span: span, global: true, idents: ids, @@ -52,7 +52,7 @@ pub fn path_global(+ids: ~[ident], span: span) -> @ast::Path { pub trait append_types { fn add_ty(&self, ty: @ast::Ty) -> @ast::Path; - fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::Path; + fn add_tys(&self, tys: ~[@ast::Ty]) -> @ast::Path; } impl append_types for @ast::Path { @@ -63,7 +63,7 @@ impl append_types for @ast::Path { } } - fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::Path { + fn add_tys(&self, tys: ~[@ast::Ty]) -> @ast::Path { @ast::Path { types: vec::append(copy self.types, tys), .. copy **self @@ -76,63 +76,63 @@ pub trait ext_ctxt_ast_builder { -> ast::TyParam; fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg; fn expr_block(&self, e: @ast::expr) -> ast::blk; - fn fn_decl(&self, +inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; - fn item(&self, name: ident, span: span, +node: ast::item_) -> @ast::item; + fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; + fn item(&self, name: ident, span: span, node: ast::item_) -> @ast::item; fn item_fn_poly(&self, ame: ident, - +inputs: ~[ast::arg], + inputs: ~[ast::arg], output: @ast::Ty, - +generics: Generics, - +body: ast::blk) -> @ast::item; + generics: Generics, + body: ast::blk) -> @ast::item; fn item_fn(&self, name: ident, - +inputs: ~[ast::arg], + inputs: ~[ast::arg], output: @ast::Ty, - +body: ast::blk) -> @ast::item; + body: ast::blk) -> @ast::item; fn item_enum_poly(&self, name: ident, span: span, - +enum_definition: ast::enum_def, - +generics: Generics) -> @ast::item; + enum_definition: ast::enum_def, + generics: Generics) -> @ast::item; fn item_enum(&self, name: ident, span: span, - +enum_definition: ast::enum_def) -> @ast::item; + enum_definition: ast::enum_def) -> @ast::item; fn item_struct_poly(&self, name: ident, span: span, - +struct_def: ast::struct_def, - +generics: Generics) -> @ast::item; + struct_def: ast::struct_def, + generics: Generics) -> @ast::item; fn item_struct(&self, name: ident, span: span, - +struct_def: ast::struct_def) -> @ast::item; + struct_def: ast::struct_def) -> @ast::item; fn struct_expr(&self, path: @ast::Path, - +fields: ~[ast::field]) -> @ast::expr; + fields: ~[ast::field]) -> @ast::expr; fn variant(&self, name: ident, span: span, - +tys: ~[@ast::Ty]) -> ast::variant; + tys: ~[@ast::Ty]) -> ast::variant; fn item_mod(&self, name: ident, span: span, - +items: ~[@ast::item]) -> @ast::item; + items: ~[@ast::item]) -> @ast::item; fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty; fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty, - +generics: Generics) -> @ast::item; + generics: Generics) -> @ast::item; fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item; fn ty_vars(&self, ty_params: &OptVec) -> ~[@ast::Ty]; fn ty_vars_global(&self, ty_params: &OptVec) -> ~[@ast::Ty]; fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field; fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field; - fn block(&self, +stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; + fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt; fn stmt_expr(&self, e: @ast::expr) -> @ast::stmt; - fn block_expr(&self, +b: ast::blk) -> @ast::expr; + fn block_expr(&self, b: ast::blk) -> @ast::expr; fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty; fn ty_infer(&self) -> @ast::Ty; fn ty_nil_ast_builder(&self) -> @ast::Ty; @@ -148,7 +148,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { ], dummy_sp()).add_ty(ty)) } - fn block_expr(&self, +b: ast::blk) -> @ast::expr { + fn block_expr(&self, b: ast::blk) -> @ast::expr { @expr { id: self.next_id(), callee_id: self.next_id(), @@ -215,7 +215,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } } - fn block(&self, +stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk { + fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk { let blk = ast::blk_ { view_items: ~[], stmts: stmts, @@ -231,7 +231,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { self.block(~[], e) } - fn fn_decl(&self, +inputs: ~[ast::arg], + fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { ast::fn_decl { inputs: inputs, @@ -241,7 +241,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn item(&self, name: ident, span: span, - +node: ast::item_) -> @ast::item { + node: ast::item_) -> @ast::item { // XXX: Would be nice if our generated code didn't violate // Rust coding conventions @@ -265,10 +265,10 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn item_fn_poly(&self, name: ident, - +inputs: ~[ast::arg], + inputs: ~[ast::arg], output: @ast::Ty, - +generics: Generics, - +body: ast::blk) -> @ast::item { + generics: Generics, + body: ast::blk) -> @ast::item { self.item(name, dummy_sp(), ast::item_fn(self.fn_decl(inputs, output), @@ -280,9 +280,9 @@ impl ext_ctxt_ast_builder for @ext_ctxt { fn item_fn(&self, name: ident, - +inputs: ~[ast::arg], + inputs: ~[ast::arg], output: @ast::Ty, - +body: ast::blk + body: ast::blk ) -> @ast::item { self.item_fn_poly( name, @@ -294,13 +294,13 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn item_enum_poly(&self, name: ident, span: span, - +enum_definition: ast::enum_def, - +generics: Generics) -> @ast::item { + enum_definition: ast::enum_def, + generics: Generics) -> @ast::item { self.item(name, span, ast::item_enum(enum_definition, generics)) } fn item_enum(&self, name: ident, span: span, - +enum_definition: ast::enum_def) -> @ast::item { + enum_definition: ast::enum_def) -> @ast::item { self.item_enum_poly(name, span, enum_definition, ast_util::empty_generics()) } @@ -308,7 +308,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { fn item_struct( &self, name: ident, span: span, - +struct_def: ast::struct_def + struct_def: ast::struct_def ) -> @ast::item { self.item_struct_poly( name, @@ -322,14 +322,14 @@ impl ext_ctxt_ast_builder for @ext_ctxt { &self, name: ident, span: span, - +struct_def: ast::struct_def, - +generics: Generics + struct_def: ast::struct_def, + generics: Generics ) -> @ast::item { self.item(name, span, ast::item_struct(@struct_def, generics)) } fn struct_expr(&self, path: @ast::Path, - +fields: ~[ast::field]) -> @ast::expr { + fields: ~[ast::field]) -> @ast::expr { @ast::expr { id: self.next_id(), callee_id: self.next_id(), @@ -339,7 +339,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn variant(&self, name: ident, span: span, - +tys: ~[@ast::Ty]) -> ast::variant { + tys: ~[@ast::Ty]) -> ast::variant { let args = do tys.map |ty| { ast::variant_arg { ty: *ty, id: self.next_id() } }; @@ -358,7 +358,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn item_mod(&self, name: ident, span: span, - +items: ~[@ast::item]) -> @ast::item { + items: ~[@ast::item]) -> @ast::item { // XXX: Total hack: import `core::kinds::Owned` to work around a // parser bug whereby `fn f` doesn't parse. @@ -425,7 +425,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { } fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty, - +generics: Generics) -> @ast::item { + generics: Generics) -> @ast::item { self.item(name, span, ast::item_ty(ty, generics)) } diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 0725f2889499d..7339ebdaa98fa 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -19,13 +19,13 @@ use parse::token; use core::prelude::*; pub trait proto_parser { - fn parse_proto(&self, +id: ~str) -> protocol; + fn parse_proto(&self, id: ~str) -> protocol; fn parse_state(&self, proto: protocol); fn parse_message(&self, state: state); } impl proto_parser for parser::Parser { - fn parse_proto(&self, +id: ~str) -> protocol { + fn parse_proto(&self, id: ~str) -> protocol { let proto = protocol(id, *self.span); self.parse_seq_to_before_end( diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index 4a8ceedc8e301..6495750f93b75 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -81,8 +81,8 @@ pub struct state_ { } pub impl state_ { - fn add_message(@self, +name: ~str, span: span, - +data: ~[@ast::Ty], +next: Option) { + fn add_message(@self, name: ~str, span: span, + data: ~[@ast::Ty], next: Option) { self.messages.push(message(name, span, data, self, next)); } @@ -119,11 +119,11 @@ pub impl state_ { pub type protocol = @mut protocol_; -pub fn protocol(+name: ~str, +span: span) -> protocol { +pub fn protocol(name: ~str, span: span) -> protocol { @mut protocol_(name, span) } -pub fn protocol_(+name: ~str, span: span) -> protocol_ { +pub fn protocol_(name: ~str, span: span) -> protocol_ { protocol_ { name: name, span: span, @@ -177,10 +177,10 @@ pub impl protocol_ { pub impl protocol_ { fn add_state_poly(@mut self, - +name: ~str, + name: ~str, ident: ast::ident, dir: direction, - +generics: ast::Generics) + generics: ast::Generics) -> state { let messages = @mut ~[]; let states = &*self.states; diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index a6f078d07b420..f355d327d4fa0 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -419,7 +419,7 @@ fn ids_ext(cx: @ext_ctxt, strs: ~[~str]) -> ~[ast::ident] { strs.map(|str| cx.parse_sess().interner.intern(@copy *str)) } -fn id_ext(cx: @ext_ctxt, +str: ~str) -> ast::ident { +fn id_ext(cx: @ext_ctxt, str: ~str) -> ast::ident { cx.parse_sess().interner.intern(@str) } @@ -734,8 +734,8 @@ fn expand_tts(cx: @ext_ctxt, fn expand_parse_call(cx: @ext_ctxt, sp: span, - +parse_method: ~str, - +arg_exprs: ~[@ast::expr], + parse_method: ~str, + arg_exprs: ~[@ast::expr], tts: &[ast::token_tree]) -> @ast::expr { let tts_expr = expand_tts(cx, sp, tts); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index afb7e04a53204..9df7a8e7e1db7 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -98,9 +98,9 @@ pub enum matcher_pos_up { /* to break a circularity */ matcher_pos_up(Option<~MatcherPos>) } -pub fn is_some(&&mpu: matcher_pos_up) -> bool { - match &mpu { - &matcher_pos_up(None) => false, +pub fn is_some(mpu: &matcher_pos_up) -> bool { + match *mpu { + matcher_pos_up(None) => false, _ => true } } @@ -115,9 +115,9 @@ pub struct MatcherPos { sp_lo: BytePos, } -pub fn copy_up(&& mpu: matcher_pos_up) -> ~MatcherPos { - match &mpu { - &matcher_pos_up(Some(ref mp)) => copy (*mp), +pub fn copy_up(mpu: &matcher_pos_up) -> ~MatcherPos { + match *mpu { + matcher_pos_up(Some(ref mp)) => copy (*mp), _ => fail!() } } @@ -132,7 +132,7 @@ pub fn count_names(ms: &[matcher]) -> uint { } #[allow(non_implicitly_copyable_typarams)] -pub fn initial_matcher_pos(+ms: ~[matcher], +sep: Option, lo: BytePos) +pub fn initial_matcher_pos(ms: ~[matcher], sep: Option, lo: BytePos) -> ~MatcherPos { let mut match_idx_hi = 0u; for ms.each |elt| { @@ -220,7 +220,7 @@ pub enum parse_result { pub fn parse_or_else( sess: @mut ParseSess, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, rdr: @reader, ms: ~[matcher] ) -> HashMap { @@ -257,7 +257,7 @@ pub fn parse( /* at end of sequence */ if idx >= len { // can't move out of `match`es, so: - if is_some(ei.up) { + if is_some(&ei.up) { // hack: a matcher sequence is repeating iff it has a // parent (the top level is just a container) @@ -267,7 +267,7 @@ pub fn parse( if idx == len { // pop from the matcher position - let mut new_pos = copy_up(ei.up); + let mut new_pos = copy_up(&ei.up); // update matches (the MBE "parse tree") by appending // each tree as a subtree. @@ -394,7 +394,7 @@ pub fn parse( match ei.elts[ei.idx].node { match_nonterminal(_, name, idx) => { ei.matches[idx].push(@matched_nonterminal( - parse_nt(rust_parser, *sess.interner.get(name)))); + parse_nt(&rust_parser, *sess.interner.get(name)))); ei.idx += 1u; } _ => fail!() @@ -411,7 +411,7 @@ pub fn parse( } } -pub fn parse_nt(p: Parser, name: ~str) -> nonterminal { +pub fn parse_nt(p: &Parser, name: ~str) -> nonterminal { match name { ~"item" => match p.parse_item(~[]) { Some(i) => token::nt_item(i), diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index f39f3a01328ba..482e7b80339be 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -53,7 +53,7 @@ pub struct TtReader { pub fn new_tt_reader(sp_diag: @span_handler, itr: @ident_interner, interp: Option>, - +src: ~[ast::token_tree]) + src: ~[ast::token_tree]) -> @mut TtReader { let r = @mut TtReader { sp_diag: sp_diag, @@ -109,7 +109,7 @@ pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader { fn lookup_cur_matched_by_matched(r: &mut TtReader, start: @named_match) -> @named_match { - fn red(+ad: @named_match, idx: &uint) -> @named_match { + fn red(ad: @named_match, idx: &uint) -> @named_match { match *ad { matched_nonterminal(_) => { // end of the line; duplicate henceforth diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 1604c40f91763..c7ca9eba5124e 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -27,11 +27,11 @@ pub enum OptVec { Vec(~[T]) } -pub fn with(+t: T) -> OptVec { +pub fn with(t: T) -> OptVec { Vec(~[t]) } -pub fn from(+t: ~[T]) -> OptVec { +pub fn from(t: ~[T]) -> OptVec { if t.len() == 0 { Empty } else { @@ -40,7 +40,7 @@ pub fn from(+t: ~[T]) -> OptVec { } impl OptVec { - fn push(&mut self, +t: T) { + fn push(&mut self, t: T) { match *self { Vec(ref mut v) => { v.push(t); @@ -91,7 +91,7 @@ impl OptVec { } } -pub fn take_vec(+v: OptVec) -> ~[T] { +pub fn take_vec(v: OptVec) -> ~[T] { match v { Empty => ~[], Vec(v) => v @@ -99,7 +99,7 @@ pub fn take_vec(+v: OptVec) -> ~[T] { } impl OptVec { - fn prepend(&self, +t: T) -> OptVec { + fn prepend(&self, t: T) -> OptVec { let mut v0 = ~[t]; match *self { Empty => {} @@ -157,7 +157,7 @@ impl BaseIter for OptVec { impl iter::ExtendedIter for OptVec { #[inline(always)] - fn eachi(&self, blk: &fn(+v: uint, v: &A) -> bool) { + fn eachi(&self, blk: &fn(v: uint, v: &A) -> bool) { iter::eachi(self, blk) } #[inline(always)] @@ -169,7 +169,7 @@ impl iter::ExtendedIter for OptVec { iter::any(self, blk) } #[inline(always)] - fn foldl(&self, +b0: B, blk: &fn(&B, &A) -> B) -> B { + fn foldl(&self, b0: B, blk: &fn(&B, &A) -> B) -> B { iter::foldl(self, b0, blk) } #[inline(always)] diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index 4125a0bc3b406..840fb891bff2c 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -40,7 +40,7 @@ pub fn expr_is_simple_block(e: @ast::expr) -> bool { } } -pub fn stmt_ends_with_semi(stmt: ast::stmt) -> bool { +pub fn stmt_ends_with_semi(stmt: &ast::stmt) -> bool { return match stmt.node { ast::stmt_decl(d, _) => { match d.node { diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index f90ff21cdf004..2f6bfd4cfc53b 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -319,7 +319,7 @@ pub struct lit { pub fn gather_comments_and_literals(span_diagnostic: @diagnostic::span_handler, - +path: ~str, + path: ~str, srdr: @io::Reader) -> (~[cmnt], ~[lit]) { let src = @str::from_bytes(srdr.read_whole_stream()); diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index f353d94894a43..2d4a6d47eaa58 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -28,13 +28,13 @@ pub struct SeqSep { trailing_sep_allowed: bool } -pub fn seq_sep_trailing_disallowed(+t: token::Token) -> SeqSep { +pub fn seq_sep_trailing_disallowed(t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: false, } } -pub fn seq_sep_trailing_allowed(+t: token::Token) -> SeqSep { +pub fn seq_sep_trailing_allowed(t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: true, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9348b72981d9e..4d8fdcfe617cc 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -126,7 +126,7 @@ pub fn parse_crate_from_source_str( pub fn parse_expr_from_source_str( name: ~str, source: @~str, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, sess: @mut ParseSess ) -> @ast::expr { let p = new_parser_from_source_str( @@ -142,8 +142,8 @@ pub fn parse_expr_from_source_str( pub fn parse_item_from_source_str( name: ~str, source: @~str, - +cfg: ast::crate_cfg, - +attrs: ~[ast::attribute], + cfg: ast::crate_cfg, + attrs: ~[ast::attribute], sess: @mut ParseSess ) -> Option<@ast::item> { let p = new_parser_from_source_str( @@ -159,7 +159,7 @@ pub fn parse_item_from_source_str( pub fn parse_meta_from_source_str( name: ~str, source: @~str, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, sess: @mut ParseSess ) -> @ast::meta_item { let p = new_parser_from_source_str( @@ -175,8 +175,8 @@ pub fn parse_meta_from_source_str( pub fn parse_stmt_from_source_str( name: ~str, source: @~str, - +cfg: ast::crate_cfg, - +attrs: ~[ast::attribute], + cfg: ast::crate_cfg, + attrs: ~[ast::attribute], sess: @mut ParseSess ) -> @ast::stmt { let p = new_parser_from_source_str( @@ -192,7 +192,7 @@ pub fn parse_stmt_from_source_str( pub fn parse_tts_from_source_str( name: ~str, source: @~str, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, sess: @mut ParseSess ) -> ~[ast::token_tree] { let p = new_parser_from_source_str( @@ -207,20 +207,20 @@ pub fn parse_tts_from_source_str( } pub fn parse_from_source_str( - f: &fn (Parser) -> T, + f: &fn(&Parser) -> T, name: ~str, ss: codemap::FileSubstr, source: @~str, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, sess: @mut ParseSess ) -> T { let p = new_parser_from_source_str( sess, cfg, - /*bad*/ copy name, - /*bad*/ copy ss, + name, + ss, source ); - let r = f(p); + let r = f(&p); if !p.reader.is_eof() { p.reader.fatal(~"expected end-of-string"); } @@ -236,9 +236,9 @@ pub fn next_node_id(sess: @mut ParseSess) -> node_id { } pub fn new_parser_from_source_str(sess: @mut ParseSess, - +cfg: ast::crate_cfg, - +name: ~str, - +ss: codemap::FileSubstr, + cfg: ast::crate_cfg, + name: ~str, + ss: codemap::FileSubstr, source: @~str) -> Parser { let filemap = sess.cm.new_filemap_w_substr(name, ss, source); @@ -254,7 +254,7 @@ pub fn new_parser_from_source_str(sess: @mut ParseSess, /// that draws from that string pub fn new_parser_result_from_file( sess: @mut ParseSess, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, path: &Path ) -> Result { match io::read_whole_file_str(path) { @@ -274,7 +274,7 @@ pub fn new_parser_result_from_file( /// if the file doesn't exist pub fn new_parser_from_file( sess: @mut ParseSess, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, path: &Path ) -> Parser { match new_parser_result_from_file(sess, cfg, path) { @@ -289,7 +289,7 @@ pub fn new_parser_from_file( /// error messages correctly when the file does not exist. pub fn new_sub_parser_from_file( sess: @mut ParseSess, - +cfg: ast::crate_cfg, + cfg: ast::crate_cfg, path: &Path, sp: span ) -> Parser { @@ -303,8 +303,8 @@ pub fn new_sub_parser_from_file( pub fn new_parser_from_tts( sess: @mut ParseSess, - +cfg: ast::crate_cfg, - +tts: ~[ast::token_tree] + cfg: ast::crate_cfg, + tts: ~[ast::token_tree] ) -> Parser { let trdr = lexer::new_tt_reader( copy sess.span_diagnostic, @@ -316,7 +316,7 @@ pub fn new_parser_from_tts( } // abort if necessary -pub fn maybe_aborted(+result : T, p: Parser) -> T { +pub fn maybe_aborted(result : T, p: Parser) -> T { p.abort_if_errors(); result } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 75a3d9ab2b14a..423fc6dca6d80 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -66,7 +66,7 @@ pub enum ObsoleteSyntax { impl to_bytes::IterBytes for ObsoleteSyntax { #[inline(always)] - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c1f781f8570e0..e892f212b0577 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -201,7 +201,7 @@ macro_rules! maybe_whole ( ) -fn maybe_append(+lhs: ~[attribute], rhs: Option<~[attribute]>) +fn maybe_append(lhs: ~[attribute], rhs: Option<~[attribute]>) -> ~[attribute] { match rhs { None => lhs, @@ -220,8 +220,8 @@ struct ParsedItemsAndViewItems { /* ident is handled by common.rs */ pub fn Parser(sess: @mut ParseSess, - +cfg: ast::crate_cfg, - +rdr: @reader) + cfg: ast::crate_cfg, + rdr: @reader) -> Parser { let tok0 = copy rdr.next_token(); let interner = rdr.interner(); @@ -299,7 +299,7 @@ pub impl Parser { *self.tokens_consumed += 1u; } // EFFECT: replace the current token and span with the given one - fn replace_token(&self, +next: token::Token, +lo: BytePos, +hi: BytePos) { + fn replace_token(&self, next: token::Token, lo: BytePos, hi: BytePos) { *self.token = next; *self.span = mk_sp(lo, hi); } @@ -713,7 +713,7 @@ pub impl Parser { fn parse_box_or_uniq_pointee( &self, sigil: ast::Sigil, - ctor: &fn(+v: mt) -> ty_) -> ty_ + ctor: &fn(v: mt) -> ty_) -> ty_ { // @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types: match *self.token { @@ -1112,7 +1112,7 @@ pub impl Parser { spanned(lo, e.span.hi, ast::field_ { mutbl: m, ident: i, expr: e }) } - fn mk_expr(&self, +lo: BytePos, +hi: BytePos, +node: expr_) -> @expr { + fn mk_expr(&self, lo: BytePos, hi: BytePos, node: expr_) -> @expr { @expr { id: self.get_id(), callee_id: self.get_id(), @@ -1121,7 +1121,7 @@ pub impl Parser { } } - fn mk_mac_expr(&self, +lo: BytePos, +hi: BytePos, +m: mac_) -> @expr { + fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @expr { @expr { id: self.get_id(), callee_id: self.get_id(), @@ -1897,7 +1897,7 @@ pub impl Parser { fn parse_sugary_call_expr(&self, keyword: ~str, sugar: CallSugar, - ctor: &fn(+v: @expr) -> expr_) -> @expr { + ctor: &fn(v: @expr) -> expr_) -> @expr { let lo = self.last_span; // Parse the callee `foo` in // for foo || { @@ -2472,7 +2472,7 @@ pub impl Parser { }) } - fn parse_stmt(&self, +first_item_attrs: ~[attribute]) -> @stmt { + fn parse_stmt(&self, first_item_attrs: ~[attribute]) -> @stmt { maybe_whole!(self, nt_stmt); fn check_expected_item(p: &Parser, current_attrs: &[attribute]) { @@ -2612,7 +2612,7 @@ pub impl Parser { // parse the rest of a block expression or function body fn parse_block_tail_(&self, lo: BytePos, s: blk_check_mode, - +first_item_attrs: ~[attribute]) -> blk { + first_item_attrs: ~[attribute]) -> blk { let mut stmts = ~[]; let mut expr = None; @@ -2658,7 +2658,7 @@ pub impl Parser { expr = Some(e); } copy t => { - if classify::stmt_ends_with_semi(*stmt) { + if classify::stmt_ends_with_semi(stmt) { self.fatal( fmt!( "expected `;` or `}` after \ @@ -2696,7 +2696,7 @@ pub impl Parser { _ => { // All other kinds of statements: stmts.push(stmt); - if classify::stmt_ends_with_semi(*stmt) { + if classify::stmt_ends_with_semi(stmt) { self.expect(&token::SEMI); } } @@ -2891,7 +2891,7 @@ pub impl Parser { &fn(&Parser) -> arg_or_capture_item ) -> (self_ty, fn_decl) { fn maybe_parse_self_ty( - cnstr: &fn(+v: mutability) -> ast::self_ty_, + cnstr: &fn(v: mutability) -> ast::self_ty_, p: &Parser ) -> ast::self_ty_ { // We need to make sure it isn't a mode or a type @@ -3064,9 +3064,9 @@ pub impl Parser { (id, generics) } - fn mk_item(&self, +lo: BytePos, +hi: BytePos, +ident: ident, - +node: item_, vis: visibility, - +attrs: ~[attribute]) -> @item { + fn mk_item(&self, lo: BytePos, hi: BytePos, ident: ident, + node: item_, vis: visibility, + attrs: ~[attribute]) -> @item { @ast::item { ident: ident, attrs: attrs, id: self.get_id(), @@ -3305,7 +3305,7 @@ pub impl Parser { None) } - fn token_is_pound_or_doc_comment(&self, ++tok: token::Token) -> bool { + fn token_is_pound_or_doc_comment(&self, tok: token::Token) -> bool { match tok { token::POUND | token::DOC_COMMENT(_) => true, _ => false @@ -3340,7 +3340,7 @@ pub impl Parser { a_var } - fn parse_dtor(&self, +attrs: ~[attribute]) -> class_contents { + fn parse_dtor(&self, attrs: ~[attribute]) -> class_contents { let lo = self.last_span.lo; let body = self.parse_block(); dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi)) @@ -3392,7 +3392,7 @@ pub impl Parser { // given a termination token and a vector of already-parsed // attributes (of length 0 or 1), parse all of the items in a module fn parse_mod_items(&self, term: token::Token, - +first_item_attrs: ~[attribute]) -> _mod { + first_item_attrs: ~[attribute]) -> _mod { // parse all of the items up to closing or an attribute. // view items are legal here. let ParsedItemsAndViewItems { @@ -3553,7 +3553,7 @@ pub impl Parser { outer_attrs, id_sp) } - fn eval_src_mod_from_path(&self, prefix: Path, +path: Path, + fn eval_src_mod_from_path(&self, prefix: Path, path: Path, outer_attrs: ~[ast::attribute], id_sp: span ) -> (ast::item_, ~[ast::attribute]) { @@ -3576,7 +3576,7 @@ pub impl Parser { let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs); return (ast::item_mod(m0), mod_attrs); - fn cdir_path_opt(+default: ~str, attrs: ~[ast::attribute]) -> ~str { + fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str { match ::attr::first_attr_value_str_by_name(attrs, ~"path") { Some(d) => copy *d, None => default @@ -3584,7 +3584,7 @@ pub impl Parser { } } - fn parse_item_foreign_fn(&self, +attrs: ~[attribute]) -> @foreign_item { + fn parse_item_foreign_fn(&self, attrs: ~[attribute]) -> @foreign_item { let lo = self.span.lo; let vis = self.parse_visibility(); let purity = self.parse_fn_purity(); @@ -3601,7 +3601,7 @@ pub impl Parser { } fn parse_item_foreign_const(&self, vis: ast::visibility, - +attrs: ~[attribute]) -> @foreign_item { + attrs: ~[attribute]) -> @foreign_item { let lo = self.span.lo; // XXX: Obsolete; remove after snap. @@ -3638,7 +3638,7 @@ pub impl Parser { else { self.unexpected(); } } - fn parse_foreign_item(&self, +attrs: ~[attribute]) -> @foreign_item { + fn parse_foreign_item(&self, attrs: ~[attribute]) -> @foreign_item { let vis = self.parse_visibility(); if self.is_keyword(&~"const") || self.is_keyword(&~"static") { self.parse_item_foreign_const(vis, attrs) @@ -3648,8 +3648,8 @@ pub impl Parser { } fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort, - +abis: AbiSet, - +first_item_attrs: ~[attribute]) + abis: AbiSet, + first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr let ParsedItemsAndViewItems { @@ -3987,7 +3987,7 @@ pub impl Parser { // flags; on failure, return iovi_none. fn parse_item_or_view_item( &self, - +attrs: ~[attribute], + attrs: ~[attribute], items_allowed: bool, foreign_items_allowed: bool, macros_allowed: bool @@ -4198,7 +4198,7 @@ pub impl Parser { return iovi_none; } - fn parse_item(&self, +attrs: ~[attribute]) -> Option<@ast::item> { + fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> { match self.parse_item_or_view_item(attrs, true, false, true) { iovi_none => None, @@ -4337,7 +4337,7 @@ pub impl Parser { // parse a view item. fn parse_view_item( &self, - +attrs: ~[attribute], + attrs: ~[attribute], vis: visibility ) -> @view_item { let lo = self.span.lo; @@ -4363,7 +4363,7 @@ pub impl Parser { // - mod_items uses VIEW_ITEMS_AND_ITEMS_ALLOWED // - block_tail_ uses IMPORTS_AND_ITEMS_ALLOWED // - foreign_mod_items uses FOREIGN_ITEMS_ALLOWED - fn parse_items_and_view_items(&self, +first_item_attrs: ~[attribute], + fn parse_items_and_view_items(&self, first_item_attrs: ~[attribute], mode: view_item_parse_mode, macros_allowed: bool) -> ParsedItemsAndViewItems { diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index e742bdc056aa0..eff7524e194ae 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -104,7 +104,7 @@ pub impl token { } } -pub fn tok_str(++t: token) -> ~str { +pub fn tok_str(t: token) -> ~str { match t { STRING(s, len) => return fmt!("STR(%s,%d)", *s, len), BREAK(_) => return ~"BREAK", @@ -398,7 +398,7 @@ pub impl Printer { self.right %= self.buf_len; assert!((self.right != self.left)); } - fn advance_left(&mut self, ++x: token, L: int) { + fn advance_left(&mut self, x: token, L: int) { debug!("advnce_left ~[%u,%u], sizeof(%u)=%d", self.left, self.right, self.left, L); if L >= 0 { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 88ecabe28f526..8cf7359956283 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -134,7 +134,7 @@ pub fn print_crate(cm: @CodeMap, print_crate_(s, crate); } -pub fn print_crate_(s: @ps, &&crate: @ast::crate) { +pub fn print_crate_(s: @ps, crate: @ast::crate) { print_mod(s, &crate.node.module, crate.node.attrs); print_remaining_comments(s); eof(s.s); @@ -164,7 +164,7 @@ pub fn tts_to_str(tts: &[ast::token_tree], intr: @ident_interner) -> ~str { to_str(tts, print_tts, intr) } -pub fn stmt_to_str(s: ast::stmt, intr: @ident_interner) -> ~str { +pub fn stmt_to_str(s: &ast::stmt, intr: @ident_interner) -> ~str { to_str(s, print_stmt, intr) } @@ -177,7 +177,7 @@ pub fn generics_to_str(generics: &ast::Generics, to_str(generics, print_generics, intr) } -pub fn path_to_str(&&p: @ast::Path, intr: @ident_interner) -> ~str { +pub fn path_to_str(p: @ast::Path, intr: @ident_interner) -> ~str { to_str(p, |a,b| print_path(a, b, false), intr) } @@ -312,7 +312,7 @@ pub fn synth_comment(s: @ps, text: ~str) { word(s.s, ~"*/"); } -pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { +pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { box(s, 0u, b); let mut first = true; for elts.each |elt| { @@ -323,8 +323,8 @@ pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { } -pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), - get_span: &fn(IN) -> codemap::span) { +pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), + get_span: &fn(IN) -> codemap::span) { box(s, 0u, b); let len = elts.len(); let mut i = 0u; @@ -343,7 +343,7 @@ pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), } pub fn commasep_exprs(s: @ps, b: breaks, exprs: &[@ast::expr]) { - fn expr_span(&&expr: @ast::expr) -> codemap::span { return expr.span; } + fn expr_span(expr: @ast::expr) -> codemap::span { return expr.span; } commasep_cmnt(s, b, exprs, print_expr, expr_span); } @@ -371,7 +371,7 @@ pub fn print_opt_lifetime(s: @ps, lifetime: Option<@ast::Lifetime>) { } } -pub fn print_type(s: @ps, &&ty: @ast::Ty) { +pub fn print_type(s: @ps, ty: @ast::Ty) { maybe_print_comment(s, ty.span.lo); ibox(s, 0u); match ty.node { @@ -465,7 +465,7 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) { } } -pub fn print_item(s: @ps, &&item: @ast::item) { +pub fn print_item(s: @ps, item: @ast::item) { hardbreak_if_not_bol(s); maybe_print_comment(s, item.span.lo); print_outer_attributes(s, item.attrs); @@ -760,7 +760,7 @@ pub fn print_tt(s: @ps, tt: ast::token_tree) { } } -pub fn print_tts(s: @ps, &&tts: &[ast::token_tree]) { +pub fn print_tts(s: @ps, tts: &[ast::token_tree]) { ibox(s, 0); for tts.eachi |i, tt| { if i != 0 { @@ -872,7 +872,7 @@ pub fn print_attribute(s: @ps, attr: ast::attribute) { } -pub fn print_stmt(s: @ps, st: ast::stmt) { +pub fn print_stmt(s: @ps, st: &ast::stmt) { maybe_print_comment(s, st.span.lo); match st.node { ast::stmt_decl(decl, _) => { @@ -950,7 +950,7 @@ pub fn print_possibly_embedded_block_(s: @ps, for blk.node.view_items.each |vi| { print_view_item(s, *vi); } for blk.node.stmts.each |st| { - print_stmt(s, **st); + print_stmt(s, *st); } match blk.node.expr { Some(expr) => { @@ -1089,7 +1089,7 @@ pub fn print_call_post(s: @ps, } } -pub fn print_expr(s: @ps, &&expr: @ast::expr) { +pub fn print_expr(s: @ps, expr: @ast::expr) { fn print_field(s: @ps, field: ast::field) { ibox(s, indent_unit); if field.node.mutbl == ast::m_mutbl { word_nbsp(s, ~"mut"); } @@ -1454,7 +1454,7 @@ pub fn print_decl(s: @ps, decl: @ast::decl) { word_nbsp(s, ~"mut"); } - fn print_local(s: @ps, &&loc: @ast::local) { + fn print_local(s: @ps, loc: @ast::local) { ibox(s, indent_unit); print_local_decl(s, loc); end(s); @@ -1485,7 +1485,7 @@ pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) { print_expr(s, coll); } -pub fn print_path(s: @ps, &&path: @ast::Path, colons_before_params: bool) { +pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { maybe_print_comment(s, path.span.lo); if path.global { word(s.s, ~"::"); } let mut first = true; @@ -1513,15 +1513,15 @@ pub fn print_path(s: @ps, &&path: @ast::Path, colons_before_params: bool) { } } -pub fn print_irrefutable_pat(s: @ps, &&pat: @ast::pat) { +pub fn print_irrefutable_pat(s: @ps, pat: @ast::pat) { print_pat(s, pat, false) } -pub fn print_refutable_pat(s: @ps, &&pat: @ast::pat) { +pub fn print_refutable_pat(s: @ps, pat: @ast::pat) { print_pat(s, pat, true) } -pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) { +pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { maybe_print_comment(s, pat.span.lo); let ann_node = node_pat(s, pat); (s.ann.pre)(ann_node); @@ -1758,12 +1758,12 @@ pub fn print_bounds(s: @ps, bounds: @OptVec) { } } -pub fn print_lifetime(s: @ps, &&lifetime: &ast::Lifetime) { +pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) { word(s.s, ~"'"); print_ident(s, lifetime.ident); } -pub fn print_generics(s: @ps, &&generics: &ast::Generics) { +pub fn print_generics(s: @ps, generics: &ast::Generics) { let total = generics.lifetimes.len() + generics.ty_params.len(); if total > 0 { word(s.s, ~"<"); @@ -1790,7 +1790,7 @@ pub fn print_generics(s: @ps, &&generics: &ast::Generics) { } } -pub fn print_meta_item(s: @ps, &&item: @ast::meta_item) { +pub fn print_meta_item(s: @ps, item: @ast::meta_item) { ibox(s, indent_unit); match item.node { ast::meta_word(name) => word(s.s, *name), @@ -1814,7 +1814,7 @@ pub fn print_meta_item(s: @ps, &&item: @ast::meta_item) { end(s); } -pub fn print_view_path(s: @ps, &&vp: @ast::view_path) { +pub fn print_view_path(s: @ps, vp: @ast::view_path) { match vp.node { ast::view_path_simple(ident, path, namespace, _) => { if namespace == ast::module_ns { @@ -2006,7 +2006,7 @@ pub fn print_remaining_comments(s: @ps) { } } -pub fn print_literal(s: @ps, &&lit: @ast::lit) { +pub fn print_literal(s: @ps, lit: @ast::lit) { maybe_print_comment(s, lit.span.lo); match next_lit(s, lit.span.lo) { Some(ref ltrl) => { @@ -2137,7 +2137,7 @@ pub fn print_string(s: @ps, st: &str) { word(s.s, ~"\""); } -pub fn to_str(t: T, f: @fn(@ps, T), intr: @ident_interner) -> ~str { +pub fn to_str(t: T, f: @fn(@ps, T), intr: @ident_interner) -> ~str { do io::with_str_writer |wr| { let s = rust_printer(wr, intr); f(s, t); diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index c1b857a6cdba7..6e70bd22b4fa3 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -17,11 +17,10 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -#[legacy_modes]; - #[allow(vecs_implicitly_copyable)]; #[allow(non_camel_case_types)]; -#[allow(deprecated_mode)]; +#[deny(deprecated_mode)]; +#[deny(deprecated_pattern)]; #[no_core]; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index c4c187bc4c7c4..0aaa08f2e78f6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -101,7 +101,7 @@ pub struct Visitor { pub type visitor = @Visitor; -pub fn default_visitor() -> visitor { +pub fn default_visitor() -> visitor { return @Visitor { visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), visit_view_item: |a,b,c|visit_view_item::(a, b, c), @@ -127,18 +127,18 @@ pub fn default_visitor() -> visitor { }; } -pub fn visit_crate(c: crate, e: E, v: vt) { +pub fn visit_crate(c: &crate, e: E, v: vt) { (v.visit_mod)(&c.node.module, c.span, crate_node_id, e, v); } -pub fn visit_mod(m: &_mod, _sp: span, _id: node_id, e: E, v: vt) { +pub fn visit_mod(m: &_mod, _sp: span, _id: node_id, e: E, v: vt) { for m.view_items.each |vi| { (v.visit_view_item)(*vi, e, v); } for m.items.each |i| { (v.visit_item)(*i, e, v); } } pub fn visit_view_item(_vi: @view_item, _e: E, _v: vt) { } -pub fn visit_local(loc: @local, e: E, v: vt) { +pub fn visit_local(loc: @local, e: E, v: vt) { (v.visit_pat)(loc.node.pat, e, v); (v.visit_ty)(loc.node.ty, e, v); match loc.node.init { @@ -147,11 +147,11 @@ pub fn visit_local(loc: @local, e: E, v: vt) { } } -fn visit_trait_ref(tref: @ast::trait_ref, e: E, v: vt) { +fn visit_trait_ref(tref: @ast::trait_ref, e: E, v: vt) { visit_path(tref.path, e, v); } -pub fn visit_item(i: @item, e: E, v: vt) { +pub fn visit_item(i: @item, e: E, v: vt) { match i.node { item_const(t, ex) => { (v.visit_ty)(t, e, v); @@ -216,10 +216,10 @@ pub fn visit_item(i: @item, e: E, v: vt) { } } -pub fn visit_enum_def(enum_definition: ast::enum_def, - tps: &Generics, - e: E, - v: vt) { +pub fn visit_enum_def(enum_definition: ast::enum_def, + tps: &Generics, + e: E, + v: vt) { for enum_definition.variants.each |vr| { match vr.node.kind { tuple_variant_kind(ref variant_args) => { @@ -237,7 +237,7 @@ pub fn visit_enum_def(enum_definition: ast::enum_def, pub fn skip_ty(_t: @Ty, _e: E, _v: vt) {} -pub fn visit_ty(t: @Ty, e: E, v: vt) { +pub fn visit_ty(t: @Ty, e: E, v: vt) { match t.node { ty_box(mt) | ty_uniq(mt) | ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) => { @@ -265,11 +265,11 @@ pub fn visit_ty(t: @Ty, e: E, v: vt) { } } -pub fn visit_path(p: @Path, e: E, v: vt) { +pub fn visit_path(p: @Path, e: E, v: vt) { for p.types.each |tp| { (v.visit_ty)(*tp, e, v); } } -pub fn visit_pat(p: @pat, e: E, v: vt) { +pub fn visit_pat(p: @pat, e: E, v: vt) { match p.node { pat_enum(path, ref children) => { visit_path(path, e, v); @@ -315,7 +315,7 @@ pub fn visit_pat(p: @pat, e: E, v: vt) { } } -pub fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { +pub fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { match ni.node { foreign_item_fn(ref fd, _, ref generics) => { visit_fn_decl(fd, e, v); @@ -327,8 +327,8 @@ pub fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { } } -pub fn visit_ty_param_bounds(bounds: @OptVec, - e: E, v: vt) { +pub fn visit_ty_param_bounds(bounds: @OptVec, + e: E, v: vt) { for bounds.each |bound| { match *bound { TraitTyParamBound(ty) => visit_trait_ref(ty, e, v), @@ -337,13 +337,13 @@ pub fn visit_ty_param_bounds(bounds: @OptVec, } } -pub fn visit_generics(generics: &Generics, e: E, v: vt) { +pub fn visit_generics(generics: &Generics, e: E, v: vt) { for generics.ty_params.each |tp| { visit_ty_param_bounds(tp.bounds, e, v); } } -pub fn visit_fn_decl(fd: &fn_decl, e: E, v: vt) { +pub fn visit_fn_decl(fd: &fn_decl, e: E, v: vt) { for fd.inputs.each |a| { (v.visit_pat)(a.pat, e, v); (v.visit_ty)(a.ty, e, v); @@ -355,7 +355,7 @@ pub fn visit_fn_decl(fd: &fn_decl, e: E, v: vt) { // visit_fn() and check for fk_method(). I named this visit_method_helper() // because it is not a default impl of any method, though I doubt that really // clarifies anything. - Niko -pub fn visit_method_helper(m: &method, e: E, v: vt) { +pub fn visit_method_helper(m: &method, e: E, v: vt) { (v.visit_fn)( &fk_method( /* FIXME (#2543) */ copy m.ident, @@ -390,28 +390,28 @@ pub fn visit_struct_dtor_helper(dtor: struct_dtor, generics: &Generics, } -pub fn visit_fn(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span, - _id: node_id, e: E, v: vt) { +pub fn visit_fn(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span, + _id: node_id, e: E, v: vt) { visit_fn_decl(decl, e, v); let generics = generics_of_fn(fk); (v.visit_generics)(&generics, e, v); (v.visit_block)(body, e, v); } -pub fn visit_ty_method(m: &ty_method, e: E, v: vt) { +pub fn visit_ty_method(m: &ty_method, e: E, v: vt) { for m.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); } (v.visit_generics)(&m.generics, e, v); (v.visit_ty)(m.decl.output, e, v); } -pub fn visit_trait_method(m: &trait_method, e: E, v: vt) { +pub fn visit_trait_method(m: &trait_method, e: E, v: vt) { match *m { required(ref ty_m) => (v.visit_ty_method)(ty_m, e, v), provided(m) => visit_method_helper(m, e, v) } } -pub fn visit_struct_def( +pub fn visit_struct_def( sd: @struct_def, _nm: ast::ident, generics: &Generics, @@ -433,15 +433,15 @@ pub fn visit_struct_def( } } -pub fn visit_struct_field(sf: @struct_field, e: E, v: vt) { +pub fn visit_struct_field(sf: @struct_field, e: E, v: vt) { (v.visit_ty)(sf.node.ty, e, v); } -pub fn visit_struct_method(m: @method, e: E, v: vt) { +pub fn visit_struct_method(m: @method, e: E, v: vt) { visit_method_helper(m, e, v); } -pub fn visit_block(b: &blk, e: E, v: vt) { +pub fn visit_block(b: &blk, e: E, v: vt) { for b.node.view_items.each |vi| { (v.visit_view_item)(*vi, e, v); } @@ -460,7 +460,7 @@ pub fn visit_stmt(s: @stmt, e: E, v: vt) { } } -pub fn visit_decl(d: @decl, e: E, v: vt) { +pub fn visit_decl(d: @decl, e: E, v: vt) { match d.node { decl_local(ref locs) => { for locs.each |loc| { @@ -475,7 +475,7 @@ pub fn visit_expr_opt(eo: Option<@expr>, e: E, v: vt) { match eo { None => (), Some(ex) => (v.visit_expr)(ex, e, v) } } -pub fn visit_exprs(exprs: &[@expr], e: E, v: vt) { +pub fn visit_exprs(exprs: &[@expr], e: E, v: vt) { for exprs.each |ex| { (v.visit_expr)(*ex, e, v); } } @@ -483,7 +483,7 @@ pub fn visit_mac(_m: mac, _e: E, _v: vt) { /* no user-serviceable parts inside */ } -pub fn visit_expr(ex: @expr, e: E, v: vt) { +pub fn visit_expr(ex: @expr, e: E, v: vt) { match ex.node { expr_vstore(x, _) => (v.visit_expr)(x, e, v), expr_vec(ref es, _) => visit_exprs(*es, e, v), @@ -588,7 +588,7 @@ pub fn visit_expr(ex: @expr, e: E, v: vt) { (v.visit_expr_post)(ex, e, v); } -pub fn visit_arm(a: &arm, e: E, v: vt) { +pub fn visit_arm(a: &arm, e: E, v: vt) { for a.pats.each |p| { (v.visit_pat)(*p, e, v); } visit_expr_opt(a.guard, e, v); (v.visit_block)(&a.body, e, v); @@ -655,67 +655,67 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { m: &_mod, sp: span, id: node_id, - &&e: (), + e: (), v: vt<()> ) { f(m, sp, id); visit_mod(m, sp, id, e, v); } - fn v_view_item(f: @fn(@view_item), vi: @view_item, &&e: (), v: vt<()>) { + fn v_view_item(f: @fn(@view_item), vi: @view_item, e: (), v: vt<()>) { f(vi); visit_view_item(vi, e, v); } - fn v_foreign_item(f: @fn(@foreign_item), ni: @foreign_item, &&e: (), + fn v_foreign_item(f: @fn(@foreign_item), ni: @foreign_item, e: (), v: vt<()>) { f(ni); visit_foreign_item(ni, e, v); } - fn v_item(f: @fn(@item), i: @item, &&e: (), v: vt<()>) { + fn v_item(f: @fn(@item), i: @item, e: (), v: vt<()>) { f(i); visit_item(i, e, v); } - fn v_local(f: @fn(@local), l: @local, &&e: (), v: vt<()>) { + fn v_local(f: @fn(@local), l: @local, e: (), v: vt<()>) { f(l); visit_local(l, e, v); } - fn v_block(f: @fn(&ast::blk), bl: &ast::blk, &&e: (), v: vt<()>) { + fn v_block(f: @fn(&ast::blk), bl: &ast::blk, e: (), v: vt<()>) { f(bl); visit_block(bl, e, v); } - fn v_stmt(f: @fn(@stmt), st: @stmt, &&e: (), v: vt<()>) { + fn v_stmt(f: @fn(@stmt), st: @stmt, e: (), v: vt<()>) { f(st); visit_stmt(st, e, v); } - fn v_arm(f: @fn(&arm), a: &arm, &&e: (), v: vt<()>) { + fn v_arm(f: @fn(&arm), a: &arm, e: (), v: vt<()>) { f(a); visit_arm(a, e, v); } - fn v_pat(f: @fn(@pat), p: @pat, &&e: (), v: vt<()>) { + fn v_pat(f: @fn(@pat), p: @pat, e: (), v: vt<()>) { f(p); visit_pat(p, e, v); } - fn v_decl(f: @fn(@decl), d: @decl, &&e: (), v: vt<()>) { + fn v_decl(f: @fn(@decl), d: @decl, e: (), v: vt<()>) { f(d); visit_decl(d, e, v); } - fn v_expr(f: @fn(@expr), ex: @expr, &&e: (), v: vt<()>) { + fn v_expr(f: @fn(@expr), ex: @expr, e: (), v: vt<()>) { f(ex); visit_expr(ex, e, v); } - fn v_expr_post(f: @fn(@expr), ex: @expr, &&_e: (), _v: vt<()>) { + fn v_expr_post(f: @fn(@expr), ex: @expr, _e: (), _v: vt<()>) { f(ex); } - fn v_ty(f: @fn(@Ty), ty: @Ty, &&e: (), v: vt<()>) { + fn v_ty(f: @fn(@Ty), ty: @Ty, e: (), v: vt<()>) { f(ty); visit_ty(ty, e, v); } - fn v_ty_method(f: @fn(&ty_method), ty: &ty_method, &&e: (), v: vt<()>) { + fn v_ty_method(f: @fn(&ty_method), ty: &ty_method, e: (), v: vt<()>) { f(ty); visit_ty_method(ty, e, v); } fn v_trait_method(f: @fn(&trait_method), m: &trait_method, - &&e: (), + e: (), v: vt<()>) { f(m); visit_trait_method(m, e, v); @@ -726,7 +726,7 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { nm: ident, generics: &Generics, id: node_id, - &&e: (), + e: (), v: vt<()> ) { f(sd, nm, generics, id); @@ -735,7 +735,7 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { fn v_generics( f: @fn(&Generics), ps: &Generics, - &&e: (), + e: (), v: vt<()> ) { f(ps); @@ -748,20 +748,20 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> { body: &blk, sp: span, id: node_id, - &&e: (), + e: (), v: vt<()> ) { f(fk, decl, body, sp, id); visit_fn(fk, decl, body, sp, id, e, v); } - let visit_ty: @fn(@Ty, &&x: (), vt<()>) = + let visit_ty: @fn(@Ty, x: (), vt<()>) = |a,b,c| v_ty(v.visit_ty, a, b, c); - fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, &&e: (), + fn v_struct_field(f: @fn(@struct_field), sf: @struct_field, e: (), v: vt<()>) { f(sf); visit_struct_field(sf, e, v); } - fn v_struct_method(f: @fn(@method), m: @method, &&e: (), v: vt<()>) { + fn v_struct_method(f: @fn(@method), m: @method, e: (), v: vt<()>) { f(m); visit_struct_method(m, e, v); } From 1e4a439f7fbc97cdb3b4f297ec8645e22723202f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 17 Apr 2013 12:15:37 -0400 Subject: [PATCH 316/403] rustc: de-mode + fallout from libsyntax changes --- src/librustc/back/link.rs | 22 +-- src/librustc/driver/driver.rs | 52 +++---- src/librustc/driver/session.rs | 8 +- src/librustc/front/config.rs | 14 +- src/librustc/front/test.rs | 10 +- src/librustc/lib/llvm.rs | 2 +- src/librustc/metadata/creader.rs | 12 +- src/librustc/metadata/encoder.rs | 138 +++++++++--------- src/librustc/metadata/filesearch.rs | 8 +- src/librustc/metadata/loader.rs | 8 +- src/librustc/metadata/tyencode.rs | 20 +-- src/librustc/middle/astencode.rs | 87 +++++------ src/librustc/middle/borrowck/check_loans.rs | 12 +- src/librustc/middle/borrowck/gather_loans.rs | 12 +- src/librustc/middle/borrowck/loan.rs | 8 +- src/librustc/middle/borrowck/mod.rs | 6 +- src/librustc/middle/check_const.rs | 12 +- src/librustc/middle/check_loop.rs | 2 +- src/librustc/middle/check_match.rs | 66 ++++----- src/librustc/middle/const_eval.rs | 10 +- src/librustc/middle/freevars.rs | 6 +- src/librustc/middle/kind.rs | 4 +- src/librustc/middle/lang_items.rs | 2 +- src/librustc/middle/lint.rs | 8 +- src/librustc/middle/liveness.rs | 22 +-- src/librustc/middle/moves.rs | 6 +- src/librustc/middle/privacy.rs | 2 +- src/librustc/middle/region.rs | 26 ++-- src/librustc/middle/resolve.rs | 40 ++--- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/base.rs | 75 +++++----- src/librustc/middle/trans/cabi_x86_64.rs | 2 +- src/librustc/middle/trans/callee.rs | 22 +-- src/librustc/middle/trans/common.rs | 24 +-- src/librustc/middle/trans/controlflow.rs | 2 +- src/librustc/middle/trans/datum.rs | 4 +- src/librustc/middle/trans/debuginfo.rs | 6 +- src/librustc/middle/trans/expr.rs | 4 +- src/librustc/middle/trans/foreign.rs | 14 +- src/librustc/middle/trans/glue.rs | 6 +- src/librustc/middle/trans/inline.rs | 4 +- src/librustc/middle/trans/meth.rs | 10 +- src/librustc/middle/trans/monomorphize.rs | 4 +- src/librustc/middle/trans/reachable.rs | 32 ++-- src/librustc/middle/trans/reflect.rs | 4 +- src/librustc/middle/ty.rs | 54 +++---- src/librustc/middle/typeck/astconv.rs | 2 +- src/librustc/middle/typeck/check/_match.rs | 12 +- src/librustc/middle/typeck/check/method.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 34 ++--- src/librustc/middle/typeck/check/regionck.rs | 18 +-- src/librustc/middle/typeck/check/vtable.rs | 6 +- src/librustc/middle/typeck/check/writeback.rs | 12 +- src/librustc/middle/typeck/coherence.rs | 4 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustc/middle/typeck/infer/combine.rs | 2 +- src/librustc/middle/typeck/infer/lattice.rs | 26 ++-- src/librustc/middle/typeck/infer/mod.rs | 4 +- .../middle/typeck/infer/region_inference.rs | 24 +-- src/librustc/middle/typeck/infer/unify.rs | 24 +-- src/librustc/middle/typeck/mod.rs | 4 +- src/librustc/middle/typeck/rscope.rs | 2 +- src/librustc/rustc.rc | 14 +- src/librustc/util/common.rs | 14 +- 64 files changed, 547 insertions(+), 553 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index eb7965e1ac6dd..3dfa318826b7b 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -48,7 +48,7 @@ pub enum output_type { output_type_exe, } -pub fn llvm_err(sess: Session, +msg: ~str) -> ! { +pub fn llvm_err(sess: Session, msg: ~str) -> ! { unsafe { let cstr = llvm::LLVMRustGetLastError(); if cstr == ptr::null() { @@ -153,7 +153,7 @@ pub mod jit { code: entry, env: ptr::null() }; - let func: &fn(++argv: ~[@~str]) = cast::transmute(closure); + let func: &fn(argv: ~[@~str]) = cast::transmute(closure); func(~[sess.opts.binary]); } @@ -519,7 +519,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, // This calculates CMH as defined above fn crate_meta_extras_hash(symbol_hasher: &hash::State, - +cmh_items: ~[@ast::meta_item], + cmh_items: ~[@ast::meta_item], dep_hashes: ~[~str]) -> @str { fn len_and_str(s: &str) -> ~str { fmt!("%u_%s", s.len(), s) @@ -568,7 +568,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path, name, default)); } - fn crate_meta_name(sess: Session, output: &Path, +opt_name: Option<@str>) + fn crate_meta_name(sess: Session, output: &Path, opt_name: Option<@str>) -> @str { return match opt_name { Some(v) => v, @@ -703,7 +703,7 @@ pub fn mangle(sess: Session, ss: path) -> ~str { } pub fn exported_name(sess: Session, - +path: path, + path: path, hash: &str, vers: &str) -> ~str { return mangle(sess, @@ -713,7 +713,7 @@ pub fn exported_name(sess: Session, } pub fn mangle_exported_name(ccx: @CrateContext, - +path: path, + path: path, t: ty::t) -> ~str { let hash = get_symbol_hash(ccx, t); return exported_name(ccx.sess, path, @@ -733,17 +733,17 @@ pub fn mangle_internal_name_by_type_only(ccx: @CrateContext, } pub fn mangle_internal_name_by_path_and_seq(ccx: @CrateContext, - +path: path, - +flav: ~str) -> ~str { + path: path, + flav: ~str) -> ~str { return mangle(ccx.sess, vec::append_one(path, path_name((ccx.names)(flav)))); } -pub fn mangle_internal_name_by_path(ccx: @CrateContext, +path: path) -> ~str { +pub fn mangle_internal_name_by_path(ccx: @CrateContext, path: path) -> ~str { return mangle(ccx.sess, path); } -pub fn mangle_internal_name_by_seq(ccx: @CrateContext, +flav: ~str) -> ~str { +pub fn mangle_internal_name_by_seq(ccx: @CrateContext, flav: ~str) -> ~str { return fmt!("%s_%u", flav, (ccx.names)(flav).repr); } @@ -768,7 +768,7 @@ pub fn link_binary(sess: Session, out_filename: &Path, lm: LinkMeta) { // Converts a library file-stem into a cc -l argument - fn unlib(config: @session::config, +stem: ~str) -> ~str { + fn unlib(config: @session::config, stem: ~str) -> ~str { if stem.starts_with("lib") && config.os != session::os_win32 { stem.slice(3, stem.len()).to_owned() diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 7ea1fe8015825..fae73d7faf2d4 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -55,14 +55,14 @@ pub enum pp_mode { */ pub fn anon_src() -> ~str { ~"" } -pub fn source_name(input: input) -> ~str { - match input { +pub fn source_name(input: &input) -> ~str { + match *input { file_input(ref ifile) => ifile.to_str(), str_input(_) => anon_src() } } -pub fn default_configuration(sess: Session, argv0: @~str, input: input) -> +pub fn default_configuration(sess: Session, argv0: @~str, input: &input) -> ast::crate_cfg { let libc = match sess.targ_cfg.os { session::os_win32 => ~"msvcrt.dll", @@ -105,7 +105,7 @@ pub fn default_configuration(sess: Session, argv0: @~str, input: input) -> mk(@~"build_input", @source_name(input))]; } -pub fn append_configuration(+cfg: ast::crate_cfg, +name: ~str) +pub fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg { if attr::contains_name(cfg, name) { cfg @@ -114,7 +114,7 @@ pub fn append_configuration(+cfg: ast::crate_cfg, +name: ~str) } } -pub fn build_configuration(sess: Session, argv0: @~str, input: input) -> +pub fn build_configuration(sess: Session, argv0: @~str, input: &input) -> ast::crate_cfg { // Combine the configuration requested by the session (command line) with // some default and generated configuration items @@ -132,7 +132,7 @@ pub fn build_configuration(sess: Session, argv0: @~str, input: input) -> } // Convert strings provided as --cfg [cfgspec] into a crate_cfg -fn parse_cfgspecs(+cfgspecs: ~[~str], +fn parse_cfgspecs(cfgspecs: ~[~str], demitter: diagnostic::Emitter) -> ast::crate_cfg { do vec::map_consume(cfgspecs) |s| { let sess = parse::new_parse_sess(Some(demitter)); @@ -147,9 +147,9 @@ pub enum input { str_input(~str) } -pub fn parse_input(sess: Session, +cfg: ast::crate_cfg, input: input) +pub fn parse_input(sess: Session, cfg: ast::crate_cfg, input: &input) -> @ast::crate { - match input { + match *input { file_input(ref file) => { parse::parse_crate_from_file_using_tts(&(*file), cfg, sess.parse_sess) } @@ -207,10 +207,10 @@ pub fn compile_rest(sess: Session, lint::build_settings_crate(sess, crate)); let ast_map = time(time_passes, ~"ast indexing", || - syntax::ast_map::map_crate(sess.diagnostic(), *crate)); + syntax::ast_map::map_crate(sess.diagnostic(), crate)); time(time_passes, ~"external crate/lib resolution", || - creader::read_crates(sess.diagnostic(), *crate, sess.cstore, + creader::read_crates(sess.diagnostic(), crate, sess.cstore, sess.filesearch, session::sess_os_to_meta_os(sess.targ_cfg.os), sess.opts.is_static, @@ -344,8 +344,8 @@ pub fn compile_rest(sess: Session, return (crate, None); } -pub fn compile_upto(sess: Session, +cfg: ast::crate_cfg, - input: input, upto: compile_upto, +pub fn compile_upto(sess: Session, cfg: ast::crate_cfg, + input: &input, upto: compile_upto, outputs: Option<@OutputFilenames>) -> (@ast::crate, Option) { let time_passes = sess.time_passes(); @@ -356,7 +356,7 @@ pub fn compile_upto(sess: Session, +cfg: ast::crate_cfg, compile_rest(sess, cfg, upto, outputs, Some(crate)) } -pub fn compile_input(sess: Session, +cfg: ast::crate_cfg, input: input, +pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input, outdir: &Option, output: &Option) { let upto = if sess.opts.parse_only { cu_parse } else if sess.opts.no_trans { cu_no_trans } @@ -365,7 +365,7 @@ pub fn compile_input(sess: Session, +cfg: ast::crate_cfg, input: input, compile_upto(sess, cfg, input, upto, Some(outputs)); } -pub fn pretty_print_input(sess: Session, +cfg: ast::crate_cfg, input: input, +pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input, ppm: pp_mode) { fn ann_paren_for_expr(node: pprust::ann_node) { match node { @@ -690,7 +690,7 @@ pub fn build_session_(sopts: @session::options, cm); let cstore = @mut cstore::mk_cstore(p_s.interner); let filesearch = filesearch::mk_filesearch( - sopts.maybe_sysroot, + &sopts.maybe_sysroot, sopts.target_triple, /*bad*/copy sopts.addl_lib_search_paths); let lint_settings = lint::mk_lint_settings(); @@ -711,13 +711,13 @@ pub fn build_session_(sopts: @session::options, } } -pub fn parse_pretty(sess: Session, &&name: ~str) -> pp_mode { +pub fn parse_pretty(sess: Session, name: &str) -> pp_mode { match name { - ~"normal" => ppm_normal, - ~"expanded" => ppm_expanded, - ~"typed" => ppm_typed, - ~"expanded,identified" => ppm_expanded_identified, - ~"identified" => ppm_identified, + &"normal" => ppm_normal, + &"expanded" => ppm_expanded, + &"typed" => ppm_typed, + &"expanded,identified" => ppm_expanded_identified, + &"identified" => ppm_identified, _ => { sess.fatal(~"argument to `pretty` must be one of `normal`, \ `expanded`, `typed`, `identified`, \ @@ -790,7 +790,7 @@ pub struct OutputFilenames { obj_filename: Path } -pub fn build_output_filenames(input: input, +pub fn build_output_filenames(input: &input, odir: &Option, ofile: &Option, sess: Session) @@ -820,13 +820,13 @@ pub fn build_output_filenames(input: input, // We want to toss everything after the final '.' let dirpath = match *odir { Some(ref d) => (/*bad*/copy *d), - None => match input { + None => match *input { str_input(_) => os::getcwd(), file_input(ref ifile) => (*ifile).dir_path() } }; - let stem = match input { + let stem = match *input { file_input(ref ifile) => (*ifile).filestem().get(), str_input(_) => ~"rust_out" }; @@ -903,7 +903,7 @@ mod test { let sessopts = build_session_options( @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); - let cfg = build_configuration(sess, @~"whatever", str_input(~"")); + let cfg = build_configuration(sess, @~"whatever", &str_input(~"")); assert!((attr::contains_name(cfg, ~"test"))); } @@ -922,7 +922,7 @@ mod test { let sessopts = build_session_options( @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); - let cfg = build_configuration(sess, @~"whatever", str_input(~"")); + let cfg = build_configuration(sess, @~"whatever", &str_input(~"")); let test_items = attr::find_meta_items_by_name(cfg, ~"test"); assert!((vec::len(test_items) == 1u)); } diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 6171ebd8610e4..1912c922524fb 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -215,7 +215,7 @@ pub impl Session_ { fn unimpl(@self, msg: ~str) -> ! { self.span_diagnostic.handler().unimpl(msg) } - fn span_lint_level(@self, level: lint::level, sp: span, +msg: ~str) { + fn span_lint_level(@self, level: lint::level, sp: span, msg: ~str) { match level { lint::allow => { }, lint::warn => self.span_warn(sp, msg), @@ -228,7 +228,7 @@ pub impl Session_ { expr_id: ast::node_id, item_id: ast::node_id, span: span, - +msg: ~str) { + msg: ~str) { let level = lint::get_lint_settings_level( self.lint_settings, lint_mode, expr_id, item_id); self.span_lint_level(level, span, msg); @@ -278,7 +278,7 @@ pub impl Session_ { fn str_of(@self, id: ast::ident) -> @~str { self.parse_sess.interner.get(id) } - fn ident_of(@self, +st: ~str) -> ast::ident { + fn ident_of(@self, st: ~str) -> ast::ident { self.parse_sess.interner.intern(@st) } fn intr(@self) -> @syntax::parse::token::ident_interner { @@ -361,7 +361,7 @@ mod test { use syntax::ast; use syntax::codemap; - fn make_crate_type_attr(+t: ~str) -> ast::attribute { + fn make_crate_type_attr(t: ~str) -> ast::attribute { codemap::respan(codemap::dummy_sp(), ast::attribute_ { style: ast::attr_outer, value: @codemap::respan(codemap::dummy_sp(), diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index b92acb111e163..966f2a4ac70f3 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -15,7 +15,7 @@ use syntax::{ast, fold, attr}; use core::option; use core::vec; -type in_cfg_pred = @fn(+attrs: ~[ast::attribute]) -> bool; +type in_cfg_pred = @fn(attrs: ~[ast::attribute]) -> bool; struct Context { in_cfg: in_cfg_pred @@ -49,12 +49,12 @@ pub fn strip_items(crate: @ast::crate, in_cfg: in_cfg_pred) return res; } -fn filter_item(cx: @Context, &&item: @ast::item) -> +fn filter_item(cx: @Context, item: @ast::item) -> Option<@ast::item> { if item_in_cfg(cx, item) { option::Some(item) } else { option::None } } -fn filter_view_item(cx: @Context, &&view_item: @ast::view_item +fn filter_view_item(cx: @Context, view_item: @ast::view_item )-> Option<@ast::view_item> { if view_item_in_cfg(cx, view_item) { option::Some(view_item) @@ -74,7 +74,7 @@ fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod { } } -fn filter_foreign_item(cx: @Context, &&item: @ast::foreign_item) -> +fn filter_foreign_item(cx: @Context, item: @ast::foreign_item) -> Option<@ast::foreign_item> { if foreign_item_in_cfg(cx, item) { option::Some(item) @@ -115,7 +115,7 @@ fn fold_item_underscore(cx: @Context, item: &ast::item_, fold::noop_fold_item_underscore(&item, fld) } -fn filter_stmt(cx: @Context, &&stmt: @ast::stmt) -> +fn filter_stmt(cx: @Context, stmt: @ast::stmt) -> Option<@ast::stmt> { match stmt.node { ast::stmt_decl(decl, _) => { @@ -173,12 +173,12 @@ fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool { // Determine if an item should be translated in the current crate // configuration based on the item's attributes -fn in_cfg(+cfg: ast::crate_cfg, +attrs: ~[ast::attribute]) -> bool { +fn in_cfg(cfg: ast::crate_cfg, attrs: ~[ast::attribute]) -> bool { metas_in_cfg(cfg, attr::attr_metas(attrs)) } pub fn metas_in_cfg(cfg: ast::crate_cfg, - +metas: ~[@ast::meta_item]) -> bool { + metas: ~[@ast::meta_item]) -> bool { // The "cfg" attributes on the item let cfg_metas = attr::find_meta_items_by_name(metas, ~"cfg"); diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 8d3e9d5e89fb0..4a122d238d496 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -138,7 +138,7 @@ fn fold_crate(cx: @mut TestCtxt, } -fn fold_item(cx: @mut TestCtxt, &&i: @ast::item, fld: @fold::ast_fold) +fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold) -> Option<@ast::item> { cx.path.push(i.ident); debug!("current path: %s", @@ -336,7 +336,7 @@ fn nospan(t: T) -> codemap::spanned { codemap::spanned { node: t, span: dummy_sp() } } -fn path_node(+ids: ~[ast::ident]) -> @ast::Path { +fn path_node(ids: ~[ast::ident]) -> @ast::Path { @ast::Path { span: dummy_sp(), global: false, idents: ids, @@ -344,7 +344,7 @@ fn path_node(+ids: ~[ast::ident]) -> @ast::Path { types: ~[] } } -fn path_node_global(+ids: ~[ast::ident]) -> @ast::Path { +fn path_node_global(ids: ~[ast::ident]) -> @ast::Path { @ast::Path { span: dummy_sp(), global: true, idents: ids, @@ -381,7 +381,7 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr { debug!("building test vector from %u tests", cx.testfns.len()); let mut descs = ~[]; for cx.testfns.each |test| { - descs.push(mk_test_desc_and_fn_rec(cx, *test)); + descs.push(mk_test_desc_and_fn_rec(cx, test)); } let sess = cx.sess; @@ -400,7 +400,7 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr { } } -fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: Test) -> @ast::expr { +fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr { let span = test.span; let path = /*bad*/copy test.path; diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 0ab883d330d9d..369e6aeb4a598 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1929,7 +1929,7 @@ pub fn type_to_str(names: @TypeNames, ty: TypeRef) -> @str { return type_to_str_inner(names, [], ty); } -pub fn type_to_str_inner(names: @TypeNames, +outer0: &[TypeRef], ty: TypeRef) +pub fn type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef) -> @str { unsafe { match type_has_name(names, ty) { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 8609434e6df29..909e351acb1be 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -30,7 +30,7 @@ use syntax::ast; // Traverses an AST, reading all the information about use'd crates and extern // libraries necessary for later resolving, typechecking, linking, etc. pub fn read_crates(diag: @span_handler, - crate: ast::crate, + crate: @ast::crate, cstore: @mut cstore::CStore, filesearch: @FileSearch, os: loader::os, @@ -126,7 +126,7 @@ struct Env { intr: @ident_interner } -fn visit_crate(e: @mut Env, c: ast::crate) { +fn visit_crate(e: @mut Env, c: &ast::crate) { let cstore = e.cstore; let link_args = attr::find_attrs_by_name(c.node.attrs, "link_args"); @@ -204,7 +204,7 @@ fn visit_item(e: @mut Env, i: @ast::item) { } } -fn metas_with(ident: @~str, key: @~str, +metas: ~[@ast::meta_item]) +fn metas_with(ident: @~str, key: @~str, metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] { let name_items = attr::find_meta_items_by_name(metas, *key); if name_items.is_empty() { @@ -214,7 +214,7 @@ fn metas_with(ident: @~str, key: @~str, +metas: ~[@ast::meta_item]) } } -fn metas_with_ident(ident: @~str, +metas: ~[@ast::meta_item]) +fn metas_with_ident(ident: @~str, metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] { metas_with(ident, @~"name", metas) } @@ -232,7 +232,7 @@ fn existing_match(e: @mut Env, metas: &[@ast::meta_item], hash: @~str) fn resolve_crate(e: @mut Env, ident: ast::ident, - +metas: ~[@ast::meta_item], + metas: ~[@ast::meta_item], hash: @~str, span: span) -> ast::crate_num { @@ -251,7 +251,7 @@ fn resolve_crate(e: @mut Env, is_static: e.statik, intr: e.intr }; - let (lident, ldata) = loader::load_library_crate(load_ctxt); + let (lident, ldata) = loader::load_library_crate(&load_ctxt); let cfilename = Path(lident); let cdata = ldata; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index cc86d50af4288..aaafc7c18d6f3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -53,7 +53,7 @@ use writer = std::ebml::writer; type abbrev_map = @mut HashMap; pub type encode_inlined_item = @fn(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, path: &[ast_map::path_elt], ii: ast::inlined_item); @@ -101,31 +101,31 @@ pub fn reachable(ecx: @EncodeContext, id: node_id) -> bool { ecx.reachable.contains(&id) } -fn encode_name(ecx: @EncodeContext, ebml_w: writer::Encoder, name: ident) { +fn encode_name(ecx: @EncodeContext, ebml_w: &writer::Encoder, name: ident) { ebml_w.wr_tagged_str(tag_paths_data_name, *ecx.tcx.sess.str_of(name)); } -fn encode_impl_type_basename(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_impl_type_basename(ecx: @EncodeContext, ebml_w: &writer::Encoder, name: ident) { ebml_w.wr_tagged_str(tag_item_impl_type_basename, *ecx.tcx.sess.str_of(name)); } -pub fn encode_def_id(ebml_w: writer::Encoder, id: def_id) { +pub fn encode_def_id(ebml_w: &writer::Encoder, id: def_id) { ebml_w.wr_tagged_str(tag_def_id, def_to_str(id)); } -fn encode_region_param(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_region_param(ecx: @EncodeContext, ebml_w: &writer::Encoder, it: @ast::item) { let opt_rp = ecx.tcx.region_paramd_items.find(&it.id); for opt_rp.each |rp| { do ebml_w.wr_tag(tag_region_param) { - (*rp).encode(&ebml_w); + rp.encode(ebml_w); } } } -fn encode_mutability(ebml_w: writer::Encoder, mt: struct_mutability) { +fn encode_mutability(ebml_w: &writer::Encoder, mt: struct_mutability) { do ebml_w.wr_tag(tag_struct_mut) { let val = match mt { struct_immutable => 'a', @@ -140,7 +140,7 @@ struct entry { pos: uint } -fn add_to_index(ecx: @EncodeContext, ebml_w: writer::Encoder, path: &[ident], +fn add_to_index(ecx: @EncodeContext, ebml_w: &writer::Encoder, path: &[ident], index: &mut ~[entry<~str>], name: ident) { let mut full_path = ~[]; full_path.push_all(path); @@ -153,7 +153,7 @@ fn add_to_index(ecx: @EncodeContext, ebml_w: writer::Encoder, path: &[ident], }); } -fn encode_trait_ref(ebml_w: writer::Encoder, +fn encode_trait_ref(ebml_w: &writer::Encoder, ecx: @EncodeContext, trait_ref: &ty::TraitRef, tag: uint) @@ -171,7 +171,7 @@ fn encode_trait_ref(ebml_w: writer::Encoder, } // Item info table encoding -fn encode_family(ebml_w: writer::Encoder, c: char) { +fn encode_family(ebml_w: &writer::Encoder, c: char) { ebml_w.start_tag(tag_items_data_item_family); ebml_w.writer.write(&[c as u8]); ebml_w.end_tag(); @@ -179,7 +179,7 @@ fn encode_family(ebml_w: writer::Encoder, c: char) { pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } -fn encode_ty_type_param_defs(ebml_w: writer::Encoder, +fn encode_ty_type_param_defs(ebml_w: &writer::Encoder, ecx: @EncodeContext, params: @~[ty::TypeParameterDef], tag: uint) { @@ -196,7 +196,7 @@ fn encode_ty_type_param_defs(ebml_w: writer::Encoder, } } -fn encode_type_param_bounds(ebml_w: writer::Encoder, +fn encode_type_param_bounds(ebml_w: &writer::Encoder, ecx: @EncodeContext, params: &OptVec) { let ty_param_defs = @@ -206,13 +206,13 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder, } -fn encode_variant_id(ebml_w: writer::Encoder, vid: def_id) { +fn encode_variant_id(ebml_w: &writer::Encoder, vid: def_id) { ebml_w.start_tag(tag_items_data_item_variant); ebml_w.writer.write(str::to_bytes(def_to_str(vid))); ebml_w.end_tag(); } -pub fn write_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { +pub fn write_type(ecx: @EncodeContext, ebml_w: &writer::Encoder, typ: ty::t) { let ty_str_ctxt = @tyencode::ctxt { diag: ecx.diag, ds: def_to_str, @@ -222,7 +222,7 @@ pub fn write_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } -pub fn write_vstore(ecx: @EncodeContext, ebml_w: writer::Encoder, +pub fn write_vstore(ecx: @EncodeContext, ebml_w: &writer::Encoder, vstore: ty::vstore) { let ty_str_ctxt = @tyencode::ctxt { diag: ecx.diag, @@ -233,14 +233,14 @@ pub fn write_vstore(ecx: @EncodeContext, ebml_w: writer::Encoder, tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } -fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { +fn encode_type(ecx: @EncodeContext, ebml_w: &writer::Encoder, typ: ty::t) { ebml_w.start_tag(tag_items_data_item_type); write_type(ecx, ebml_w, typ); ebml_w.end_tag(); } fn encode_transformed_self_ty(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, opt_typ: Option) { for opt_typ.each |&typ| { @@ -251,7 +251,7 @@ fn encode_transformed_self_ty(ecx: @EncodeContext, } fn encode_method_fty(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, typ: &ty::BareFnTy) { ebml_w.start_tag(tag_item_method_fty); @@ -267,7 +267,7 @@ fn encode_method_fty(ecx: @EncodeContext, ebml_w.end_tag(); } -fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) { +fn encode_symbol(ecx: @EncodeContext, ebml_w: &writer::Encoder, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); match ecx.item_symbols.find(&id) { Some(x) => { @@ -282,27 +282,27 @@ fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) { ebml_w.end_tag(); } -fn encode_discriminant(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_discriminant(ecx: @EncodeContext, ebml_w: &writer::Encoder, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); ebml_w.writer.write(str::to_bytes(**ecx.discrim_symbols.get(&id))); ebml_w.end_tag(); } -fn encode_disr_val(_ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_disr_val(_ecx: @EncodeContext, ebml_w: &writer::Encoder, disr_val: int) { ebml_w.start_tag(tag_disr_val); ebml_w.writer.write(str::to_bytes(int::to_str(disr_val))); ebml_w.end_tag(); } -fn encode_parent_item(ebml_w: writer::Encoder, id: def_id) { +fn encode_parent_item(ebml_w: &writer::Encoder, id: def_id) { ebml_w.start_tag(tag_items_data_parent_item); ebml_w.writer.write(str::to_bytes(def_to_str(id))); ebml_w.end_tag(); } -fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: &writer::Encoder, id: node_id, variants: &[variant], path: &[ast_map::path_elt], index: @mut ~[entry], @@ -343,9 +343,9 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder, } } -fn encode_path(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_path(ecx: @EncodeContext, ebml_w: &writer::Encoder, path: &[ast_map::path_elt], name: ast_map::path_elt) { - fn encode_path_elt(ecx: @EncodeContext, ebml_w: writer::Encoder, + fn encode_path_elt(ecx: @EncodeContext, ebml_w: &writer::Encoder, elt: ast_map::path_elt) { let (tag, name) = match elt { ast_map::path_mod(name) => (tag_path_elt_mod, name), @@ -364,7 +364,7 @@ fn encode_path(ecx: @EncodeContext, ebml_w: writer::Encoder, } } -fn encode_info_for_mod(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_info_for_mod(ecx: @EncodeContext, ebml_w: &writer::Encoder, md: &_mod, id: node_id, path: &[ast_map::path_elt], name: ident) { ebml_w.start_tag(tag_items_data_item); @@ -422,7 +422,7 @@ fn encode_info_for_mod(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.end_tag(); } -fn encode_struct_field_family(ebml_w: writer::Encoder, +fn encode_struct_field_family(ebml_w: &writer::Encoder, visibility: visibility) { encode_family(ebml_w, match visibility { public => 'g', @@ -431,7 +431,7 @@ fn encode_struct_field_family(ebml_w: writer::Encoder, }); } -fn encode_visibility(ebml_w: writer::Encoder, visibility: visibility) { +fn encode_visibility(ebml_w: &writer::Encoder, visibility: visibility) { ebml_w.start_tag(tag_items_data_item_visibility); let ch = match visibility { public => 'y', @@ -442,7 +442,7 @@ fn encode_visibility(ebml_w: writer::Encoder, visibility: visibility) { ebml_w.end_tag(); } -fn encode_self_type(ebml_w: writer::Encoder, self_type: ast::self_ty_) { +fn encode_self_type(ebml_w: &writer::Encoder, self_type: ast::self_ty_) { ebml_w.start_tag(tag_item_trait_method_self_ty); // Encode the base self type. @@ -470,7 +470,7 @@ fn encode_self_type(ebml_w: writer::Encoder, self_type: ast::self_ty_) { ebml_w.end_tag(); - fn encode_mutability(ebml_w: writer::Encoder, + fn encode_mutability(ebml_w: &writer::Encoder, m: ast::mutability) { match m { m_imm => { @@ -486,14 +486,14 @@ fn encode_self_type(ebml_w: writer::Encoder, self_type: ast::self_ty_) { } } -fn encode_method_sort(ebml_w: writer::Encoder, sort: char) { +fn encode_method_sort(ebml_w: &writer::Encoder, sort: char) { ebml_w.start_tag(tag_item_trait_method_sort); ebml_w.writer.write(&[ sort as u8 ]); ebml_w.end_tag(); } /* Returns an index of items in this class */ -fn encode_info_for_struct(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_info_for_struct(ecx: @EncodeContext, ebml_w: &writer::Encoder, path: &[ast_map::path_elt], fields: &[@struct_field], global_index: @mut~[entry]) -> ~[entry] { @@ -532,7 +532,7 @@ fn encode_info_for_struct(ecx: @EncodeContext, ebml_w: writer::Encoder, // This is for encoding info for ctors and dtors fn encode_info_for_ctor(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, id: node_id, ident: ident, path: &[ast_map::path_elt], @@ -550,8 +550,8 @@ fn encode_info_for_ctor(ecx: @EncodeContext, encode_type(ecx, ebml_w, its_ty); encode_path(ecx, ebml_w, path, ast_map::path_name(ident)); match item { - Some(ref it) => { - (ecx.encode_inlined_item)(ecx, ebml_w, path, (*it)); + Some(it) => { + (ecx.encode_inlined_item)(ecx, ebml_w, path, it); } None => { encode_symbol(ecx, ebml_w, id); @@ -561,7 +561,7 @@ fn encode_info_for_ctor(ecx: @EncodeContext, } fn encode_info_for_struct_ctor(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, path: &[ast_map::path_elt], name: ast::ident, ctor_id: node_id, @@ -583,7 +583,7 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext, } fn encode_method_ty_fields(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, method_ty: &ty::method) { encode_def_id(ebml_w, method_ty.def_id); @@ -598,7 +598,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext, } fn encode_info_for_method(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, impl_path: &[ast_map::path_elt], should_inline: bool, parent_id: node_id, @@ -669,7 +669,7 @@ fn should_inline(attrs: &[attribute]) -> bool { } -fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_info_for_item(ecx: @EncodeContext, ebml_w: &writer::Encoder, item: @item, index: @mut ~[entry], path: &[ast_map::path_elt]) { @@ -682,7 +682,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, }; if !must_write && !reachable(ecx, item.id) { return; } - fn add_to_index_(item: @item, ebml_w: writer::Encoder, + fn add_to_index_(item: @item, ebml_w: &writer::Encoder, index: @mut ~[entry]) { index.push(entry { val: item.id, pos: ebml_w.writer.tell() }); } @@ -998,10 +998,10 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder, } fn encode_info_for_foreign_item(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, nitem: @foreign_item, index: @mut ~[entry], - +path: ast_map::path, + path: ast_map::path, abi: AbiSet) { if !reachable(ecx, nitem.id) { return; } index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() }); @@ -1031,7 +1031,7 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext, ebml_w.end_tag(); } -fn encode_info_for_items(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_info_for_items(ecx: @EncodeContext, ebml_w: &writer::Encoder, crate: &crate) -> ~[entry] { let index = @mut ~[]; ebml_w.start_tag(tag_items_data); @@ -1039,15 +1039,15 @@ fn encode_info_for_items(ecx: @EncodeContext, ebml_w: writer::Encoder, encode_info_for_mod(ecx, ebml_w, &crate.node.module, crate_node_id, ~[], syntax::parse::token::special_idents::invalid); - visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { + visit::visit_crate(crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |_e, _cx, _v| { }, visit_item: { - let ebml_w = copy ebml_w; + let ebml_w = copy *ebml_w; |i, cx, v| { visit::visit_item(i, cx, v); match *ecx.tcx.items.get(&i.id) { ast_map::node_item(_, pt) => { - encode_info_for_item(ecx, ebml_w, i, + encode_info_for_item(ecx, &ebml_w, i, index, *pt); } _ => fail!(~"bad item") @@ -1055,12 +1055,12 @@ fn encode_info_for_items(ecx: @EncodeContext, ebml_w: writer::Encoder, } }, visit_foreign_item: { - let ebml_w = copy ebml_w; + let ebml_w = copy *ebml_w; |ni, cx, v| { visit::visit_foreign_item(ni, cx, v); match *ecx.tcx.items.get(&ni.id) { ast_map::node_foreign_item(_, abi, _, pt) => { - encode_info_for_foreign_item(ecx, ebml_w, ni, + encode_info_for_foreign_item(ecx, &ebml_w, ni, index, /*bad*/copy *pt, abi); } @@ -1094,8 +1094,8 @@ fn create_index(index: ~[entry]) -> return buckets_frozen; } -fn encode_index(ebml_w: writer::Encoder, buckets: ~[@~[entry]], - write_fn: &fn(@io::Writer, T)) { +fn encode_index(ebml_w: &writer::Encoder, buckets: ~[@~[entry]], + write_fn: &fn(@io::Writer, &T)) { let writer = ebml_w.writer; ebml_w.start_tag(tag_index); let mut bucket_locs: ~[uint] = ~[]; @@ -1107,7 +1107,7 @@ fn encode_index(ebml_w: writer::Encoder, buckets: ~[@~[entry]], ebml_w.start_tag(tag_index_buckets_bucket_elt); assert!(elt.pos < 0xffff_ffff); writer.write_be_u32(elt.pos as u32); - write_fn(writer, elt.val); + write_fn(writer, &elt.val); ebml_w.end_tag(); } ebml_w.end_tag(); @@ -1122,14 +1122,14 @@ fn encode_index(ebml_w: writer::Encoder, buckets: ~[@~[entry]], ebml_w.end_tag(); } -fn write_str(writer: @io::Writer, &&s: ~str) { writer.write_str(s); } +fn write_str(writer: @io::Writer, s: ~str) { writer.write_str(s); } -fn write_int(writer: @io::Writer, &&n: int) { +fn write_int(writer: @io::Writer, &n: &int) { assert!(n < 0x7fff_ffff); writer.write_be_u32(n as u32); } -fn encode_meta_item(ebml_w: writer::Encoder, mi: @meta_item) { +fn encode_meta_item(ebml_w: &writer::Encoder, mi: @meta_item) { match mi.node { meta_word(name) => { ebml_w.start_tag(tag_meta_item_word); @@ -1166,7 +1166,7 @@ fn encode_meta_item(ebml_w: writer::Encoder, mi: @meta_item) { } } -fn encode_attributes(ebml_w: writer::Encoder, attrs: &[attribute]) { +fn encode_attributes(ebml_w: &writer::Encoder, attrs: &[attribute]) { ebml_w.start_tag(tag_attributes); for attrs.each |attr| { ebml_w.start_tag(tag_attribute); @@ -1183,7 +1183,7 @@ fn encode_attributes(ebml_w: writer::Encoder, attrs: &[attribute]) { fn synthesize_crate_attrs(ecx: @EncodeContext, crate: &crate) -> ~[attribute] { - fn synthesize_link_attr(ecx: @EncodeContext, +items: ~[@meta_item]) -> + fn synthesize_link_attr(ecx: @EncodeContext, items: ~[@meta_item]) -> attribute { assert!(!ecx.link_meta.name.is_empty()); @@ -1231,7 +1231,7 @@ fn synthesize_crate_attrs(ecx: @EncodeContext, } fn encode_crate_deps(ecx: @EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, cstore: @mut cstore::CStore) { fn get_ordered_deps(ecx: @EncodeContext, cstore: @mut cstore::CStore) -> ~[decoder::crate_dep] { @@ -1272,7 +1272,7 @@ fn encode_crate_deps(ecx: @EncodeContext, ebml_w.end_tag(); } -fn encode_lang_items(ecx: @EncodeContext, ebml_w: writer::Encoder) { +fn encode_lang_items(ecx: @EncodeContext, ebml_w: &writer::Encoder) { ebml_w.start_tag(tag_lang_items); for ecx.tcx.lang_items.each_item |def_id, i| { @@ -1297,7 +1297,7 @@ fn encode_lang_items(ecx: @EncodeContext, ebml_w: writer::Encoder) { } fn encode_link_args(ecx: @EncodeContext, - ebml_w: writer::Encoder) { + ebml_w: &writer::Encoder) { ebml_w.start_tag(tag_link_args); let link_args = cstore::get_used_link_args(ecx.cstore); @@ -1310,7 +1310,7 @@ fn encode_link_args(ecx: @EncodeContext, ebml_w.end_tag(); } -fn encode_crate_dep(ecx: @EncodeContext, ebml_w: writer::Encoder, +fn encode_crate_dep(ecx: @EncodeContext, ebml_w: &writer::Encoder, dep: decoder::crate_dep) { ebml_w.start_tag(tag_crate_dep); ebml_w.start_tag(tag_crate_dep_name); @@ -1325,7 +1325,7 @@ fn encode_crate_dep(ecx: @EncodeContext, ebml_w: writer::Encoder, ebml_w.end_tag(); } -fn encode_hash(ebml_w: writer::Encoder, hash: &str) { +fn encode_hash(ebml_w: &writer::Encoder, hash: &str) { ebml_w.start_tag(tag_crate_hash); ebml_w.writer.write(str::to_bytes(hash)); ebml_w.end_tag(); @@ -1339,7 +1339,7 @@ pub static metadata_encoding_version : &'static [u8] = 0x74, //'t' as u8, 0, 0, 0, 1 ]; -pub fn encode_metadata(+parms: EncodeParams, crate: &crate) -> ~[u8] { +pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { let wr = @io::BytesWriter(); let mut stats = Stats { inline_bytes: 0, @@ -1372,36 +1372,36 @@ pub fn encode_metadata(+parms: EncodeParams, crate: &crate) -> ~[u8] { let ebml_w = writer::Encoder(wr as @io::Writer); - encode_hash(ebml_w, ecx.link_meta.extras_hash); + encode_hash(&ebml_w, ecx.link_meta.extras_hash); let mut i = wr.pos; let crate_attrs = synthesize_crate_attrs(ecx, crate); - encode_attributes(ebml_w, crate_attrs); + encode_attributes(&ebml_w, crate_attrs); ecx.stats.attr_bytes = wr.pos - i; i = wr.pos; - encode_crate_deps(ecx, ebml_w, ecx.cstore); + encode_crate_deps(ecx, &ebml_w, ecx.cstore); ecx.stats.dep_bytes = wr.pos - i; // Encode the language items. i = wr.pos; - encode_lang_items(ecx, ebml_w); + encode_lang_items(ecx, &ebml_w); ecx.stats.lang_item_bytes = wr.pos - i; // Encode the link args. i = wr.pos; - encode_link_args(ecx, ebml_w); + encode_link_args(ecx, &ebml_w); ecx.stats.link_args_bytes = wr.pos - i; // Encode and index the items. ebml_w.start_tag(tag_items); i = wr.pos; - let items_index = encode_info_for_items(ecx, ebml_w, crate); + let items_index = encode_info_for_items(ecx, &ebml_w, crate); ecx.stats.item_bytes = wr.pos - i; i = wr.pos; let items_buckets = create_index(items_index); - encode_index(ebml_w, items_buckets, write_int); + encode_index(&ebml_w, items_buckets, write_int); ecx.stats.index_bytes = wr.pos - i; ebml_w.end_tag(); diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 1e58ac5e94a84..25cbb97e39e12 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -35,9 +35,9 @@ pub trait FileSearch { fn get_target_lib_file_path(&self, file: &Path) -> Path; } -pub fn mk_filesearch(maybe_sysroot: Option, +pub fn mk_filesearch(maybe_sysroot: &Option, target_triple: &str, - +addl_lib_search_paths: ~[Path]) + addl_lib_search_paths: ~[Path]) -> @FileSearch { struct FileSearchImpl { sysroot: Path, @@ -117,8 +117,8 @@ fn get_or_default_sysroot() -> Path { } } -fn get_sysroot(maybe_sysroot: Option) -> Path { - match maybe_sysroot { +fn get_sysroot(maybe_sysroot: &Option) -> Path { + match *maybe_sysroot { option::Some(ref sr) => (/*bad*/copy *sr), option::None => get_or_default_sysroot() } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index cfe9c8cd40a66..b21b6b4983bd2 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -55,7 +55,7 @@ pub struct Context { intr: @ident_interner } -pub fn load_library_crate(cx: Context) -> (~str, @~[u8]) { +pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) { match find_library_crate(cx) { Some(ref t) => return (/*bad*/copy *t), None => { @@ -66,12 +66,12 @@ pub fn load_library_crate(cx: Context) -> (~str, @~[u8]) { } } -fn find_library_crate(cx: Context) -> Option<(~str, @~[u8])> { +fn find_library_crate(cx: &Context) -> Option<(~str, @~[u8])> { attr::require_unique_names(cx.diag, cx.metas); find_library_crate_aux(cx, libname(cx), cx.filesearch) } -fn libname(cx: Context) -> (~str, ~str) { +fn libname(cx: &Context) -> (~str, ~str) { if cx.is_static { return (~"lib", ~".rlib"); } let (dll_prefix, dll_suffix) = match cx.os { os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), @@ -85,7 +85,7 @@ fn libname(cx: Context) -> (~str, ~str) { } fn find_library_crate_aux( - cx: Context, + cx: &Context, (prefix, suffix): (~str, ~str), filesearch: @filesearch::FileSearch ) -> Option<(~str, @~[u8])> { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index f6338f83ca611..0c290ac08a78e 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -116,16 +116,16 @@ fn enc_mt(w: @io::Writer, cx: @ctxt, mt: ty::mt) { } fn enc_opt(w: @io::Writer, t: Option, enc_f: &fn(T)) { - match &t { - &None => w.write_char('n'), - &Some(ref v) => { + match t { + None => w.write_char('n'), + Some(v) => { w.write_char('s'); - enc_f((*v)); + enc_f(v); } } } -fn enc_substs(w: @io::Writer, cx: @ctxt, substs: ty::substs) { +fn enc_substs(w: @io::Writer, cx: @ctxt, substs: &ty::substs) { do enc_opt(w, substs.self_r) |r| { enc_region(w, cx, r) } do enc_opt(w, substs.self_ty) |t| { enc_ty(w, cx, t) } w.write_char('['); @@ -210,7 +210,7 @@ pub fn enc_vstore(w: @io::Writer, cx: @ctxt, v: ty::vstore) { pub fn enc_trait_ref(w: @io::Writer, cx: @ctxt, s: &ty::TraitRef) { w.write_str((cx.ds)(s.def_id)); w.write_char('|'); - enc_substs(w, cx, s.substs); + enc_substs(w, cx, &s.substs); } pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) { @@ -224,7 +224,7 @@ pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) { } } -fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) { +fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) { match st { ty::ty_nil => w.write_char('n'), ty::ty_bot => w.write_char('z'), @@ -259,14 +259,14 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) { w.write_str(&"t["); w.write_str((cx.ds)(def)); w.write_char('|'); - enc_substs(w, cx, (*substs)); + enc_substs(w, cx, substs); w.write_char(']'); } ty::ty_trait(def, ref substs, store, mt) => { w.write_str(&"x["); w.write_str((cx.ds)(def)); w.write_char('|'); - enc_substs(w, cx, (*substs)); + enc_substs(w, cx, substs); enc_trait_store(w, cx, store); enc_mutability(w, mt); w.write_char(']'); @@ -330,7 +330,7 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) { w.write_str(s); debug!("~~~~ %s", ~"|"); w.write_char('|'); - enc_substs(w, cx, (*substs)); + enc_substs(w, cx, substs); debug!("~~~~ %s", ~"]"); w.write_char(']'); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index a67be995171ff..7d4cb01510607 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -80,7 +80,7 @@ trait tr_intern { // Top-level methods. pub fn encode_inlined_item(ecx: @e::EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, path: &[ast_map::path_elt], ii: ast::inlined_item, maps: Maps) { @@ -89,11 +89,11 @@ pub fn encode_inlined_item(ecx: @e::EncodeContext, *ecx.tcx.sess.str_of(ii.ident()), ebml_w.writer.tell()); - let id_range = ast_util::compute_id_range_for_inlined_item(ii); + let id_range = ast_util::compute_id_range_for_inlined_item(&ii); do ebml_w.wr_tag(c::tag_ast as uint) { - id_range.encode(&ebml_w); - encode_ast(ebml_w, simplify_ast(ii)); - encode_side_tables_for_ii(ecx, maps, ebml_w, ii); + id_range.encode(ebml_w); + encode_ast(ebml_w, simplify_ast(&ii)); + encode_side_tables_for_ii(ecx, maps, ebml_w, &ii); } debug!("< Encoded inlined fn: %s::%s (%u)", @@ -105,7 +105,7 @@ pub fn encode_inlined_item(ecx: @e::EncodeContext, pub fn decode_inlined_item(cdata: @cstore::crate_metadata, tcx: ty::ctxt, maps: Maps, - +path: ast_map::path, + path: ast_map::path, par_doc: ebml::Doc) -> Option { let dcx = @DecodeContext { @@ -133,7 +133,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata, ast_map::path_to_str(path, tcx.sess.parse_sess.interner), *tcx.sess.str_of(ii.ident())); ast_map::map_decoded_item(tcx.sess.diagnostic(), - dcx.tcx.items, path, ii); + dcx.tcx.items, path, &ii); decode_side_tables(xcx, ast_doc); match ii { ast::ii_item(i) => { @@ -275,9 +275,9 @@ impl def_id_decoder_helpers for D { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: writer::Encoder, item: ast::inlined_item) { +fn encode_ast(ebml_w: &writer::Encoder, item: ast::inlined_item) { do ebml_w.wr_tag(c::tag_tree as uint) { - item.encode(&ebml_w) + item.encode(ebml_w) } } @@ -291,7 +291,7 @@ fn encode_ast(ebml_w: writer::Encoder, item: ast::inlined_item) { // As it happens, trans relies on the fact that we do not export // nested items, as otherwise it would get confused when translating // inlined items. -fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { +fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item { fn drop_nested_items(blk: &ast::blk_, fld: @fold::ast_fold) -> ast::blk_ { let stmts_sans_items = do blk.stmts.filtered |stmt| { match stmt.node { @@ -319,7 +319,7 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { .. *fold::default_ast_fold() }); - match ii { + match *ii { ast::ii_item(i) => { ast::ii_item(fld.fold_item(i).get()) //hack: we're not dropping items } @@ -388,8 +388,8 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item) // ______________________________________________________________________ // Encoding and decoding of ast::def -fn encode_def(ebml_w: writer::Encoder, def: ast::def) { - def.encode(&ebml_w) +fn encode_def(ebml_w: &writer::Encoder, def: ast::def) { + def.encode(ebml_w) } fn decode_def(xcx: @ExtendedDecodeContext, doc: ebml::Doc) -> ast::def { @@ -499,8 +499,8 @@ impl tr for ty::bound_region { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(ebml_w: writer::Encoder, fv: @freevar_entry) { - (*fv).encode(&ebml_w) +fn encode_freevar_entry(ebml_w: &writer::Encoder, fv: @freevar_entry) { + (*fv).encode(ebml_w) } trait ebml_decoder_helper { @@ -561,17 +561,17 @@ trait read_method_map_entry_helper { #[cfg(stage0)] fn encode_method_map_entry(ecx: @e::EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, mme: method_map_entry) { do ebml_w.emit_struct("method_map_entry", 3) { do ebml_w.emit_field(~"self_arg", 0u) { ebml_w.emit_arg(ecx, mme.self_arg); } do ebml_w.emit_field(~"explicit_self", 2u) { - mme.explicit_self.encode(&ebml_w); + mme.explicit_self.encode(ebml_w); } do ebml_w.emit_field(~"origin", 1u) { - mme.origin.encode(&ebml_w); + mme.origin.encode(ebml_w); } } } @@ -580,17 +580,17 @@ fn encode_method_map_entry(ecx: @e::EncodeContext, #[cfg(stage2)] #[cfg(stage3)] fn encode_method_map_entry(ecx: @e::EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, mme: method_map_entry) { do ebml_w.emit_struct("method_map_entry", 3) { do ebml_w.emit_struct_field("self_arg", 0u) { ebml_w.emit_arg(ecx, mme.self_arg); } do ebml_w.emit_struct_field("explicit_self", 2u) { - mme.explicit_self.encode(&ebml_w); + mme.explicit_self.encode(ebml_w); } do ebml_w.emit_struct_field("origin", 1u) { - mme.origin.encode(&ebml_w); + mme.origin.encode(ebml_w); } } } @@ -672,22 +672,22 @@ impl tr for method_origin { // Encoding and decoding vtable_res fn encode_vtable_res(ecx: @e::EncodeContext, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, dr: typeck::vtable_res) { // can't autogenerate this code because automatic code of // ty::t doesn't work, and there is no way (atm) to have // hand-written encoding routines combine with auto-generated // ones. perhaps we should fix this. do ebml_w.emit_from_vec(*dr) |vtable_origin| { - encode_vtable_origin(ecx, ebml_w, *vtable_origin) + encode_vtable_origin(ecx, ebml_w, vtable_origin) } } fn encode_vtable_origin(ecx: @e::EncodeContext, - ebml_w: writer::Encoder, - vtable_origin: typeck::vtable_origin) { + ebml_w: &writer::Encoder, + vtable_origin: &typeck::vtable_origin) { do ebml_w.emit_enum(~"vtable_origin") { - match vtable_origin { + match *vtable_origin { typeck::vtable_static(def_id, ref tys, vtable_res) => { do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) { do ebml_w.emit_enum_variant_arg(0u) { @@ -798,13 +798,13 @@ trait ebml_writer_helpers { impl ebml_writer_helpers for writer::Encoder { fn emit_ty(&self, ecx: @e::EncodeContext, ty: ty::t) { do self.emit_opaque { - e::write_type(ecx, *self, ty) + e::write_type(ecx, self, ty) } } fn emit_vstore(&self, ecx: @e::EncodeContext, vstore: ty::vstore) { do self.emit_opaque { - e::write_vstore(ecx, *self, vstore) + e::write_vstore(ecx, self, vstore) } } @@ -897,24 +897,25 @@ impl write_tag_and_id for writer::Encoder { fn encode_side_tables_for_ii(ecx: @e::EncodeContext, maps: Maps, - ebml_w: writer::Encoder, - ii: ast::inlined_item) { + ebml_w: &writer::Encoder, + ii: &ast::inlined_item) { do ebml_w.wr_tag(c::tag_table as uint) { - let ebml_w = copy ebml_w; + let ebml_w = copy *ebml_w; ast_util::visit_ids_for_inlined_item( ii, |id: ast::node_id| { // Note: this will cause a copy of ebml_w, which is bad as // it has mut fields. But I believe it's harmless since // we generate balanced EBML. - encode_side_tables_for_id(ecx, maps, ebml_w, id) + /*let ebml_w = copy ebml_w;*/ + encode_side_tables_for_id(ecx, maps, &ebml_w, id) }); } } fn encode_side_tables_for_id(ecx: @e::EncodeContext, maps: Maps, - ebml_w: writer::Encoder, + ebml_w: &writer::Encoder, id: ast::node_id) { let tcx = ecx.tcx; @@ -924,7 +925,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, do ebml_w.tag(c::tag_table_def) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - (*def).encode(&ebml_w) + (*def).encode(ebml_w) } } } @@ -1004,7 +1005,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { do ebml_w.emit_from_vec(/*bad*/ copy **m) |id| { - id.encode(&ebml_w); + id.encode(ebml_w); } } } @@ -1032,7 +1033,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, do ebml_w.tag(c::tag_table_adjustments) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - (**adj).encode(&ebml_w) + (**adj).encode(ebml_w) } } } @@ -1048,7 +1049,7 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext, ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { do ebml_w.emit_from_vec(*cap_vars) |cap_var| { - cap_var.encode(&ebml_w); + cap_var.encode(ebml_w); } } } @@ -1279,9 +1280,9 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext, // Testing of astencode_gen #[cfg(test)] -fn encode_item_ast(ebml_w: writer::Encoder, item: @ast::item) { +fn encode_item_ast(ebml_w: &writer::Encoder, item: @ast::item) { do ebml_w.wr_tag(c::tag_tree as uint) { - (*item).encode(&ebml_w) + (*item).encode(ebml_w) } } @@ -1297,7 +1298,7 @@ trait fake_ext_ctxt { fn cfg(&self) -> ast::crate_cfg; fn parse_sess(&self) -> @mut parse::ParseSess; fn call_site(&self) -> span; - fn ident_of(&self, +st: ~str) -> ast::ident; + fn ident_of(&self, st: ~str) -> ast::ident; } #[cfg(test)] @@ -1314,7 +1315,7 @@ impl fake_ext_ctxt for fake_session { expn_info: None } } - fn ident_of(&self, +st: ~str) -> ast::ident { + fn ident_of(&self, st: ~str) -> ast::ident { self.interner.intern(@st) } } @@ -1331,7 +1332,7 @@ fn roundtrip(in_item: Option<@ast::item>) { let in_item = in_item.get(); let bytes = do io::with_bytes_writer |wr| { let ebml_w = writer::Encoder(wr); - encode_item_ast(ebml_w, in_item); + encode_item_ast(&ebml_w, in_item); }; let ebml_doc = reader::Doc(@bytes); let out_item = decode_item_ast(ebml_doc); @@ -1375,7 +1376,7 @@ fn test_simplification() { return alist {eq_fn: eq_int, data: ~[]}; } ).get()); - let item_out = simplify_ast(item_in); + let item_out = simplify_ast(&item_in); let item_exp = ast::ii_item(quote_item!( fn new_int_alist() -> alist { return alist {eq_fn: eq_int, data: ~[]}; diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 116b70bf7e320..4766fe1fb94a9 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -79,7 +79,7 @@ enum impurity_cause { } pub fn check_loans(bccx: @BorrowckCtxt, - +req_maps: ReqMaps, + req_maps: ReqMaps, crate: @ast::crate) { let clcx = @mut CheckLoanCtxt { bccx: bccx, @@ -94,7 +94,7 @@ pub fn check_loans(bccx: @BorrowckCtxt, visit_block: check_loans_in_block, visit_fn: check_loans_in_fn, .. *visit::default_visitor()}); - visit::visit_crate(*crate, clcx, vt); + visit::visit_crate(crate, clcx, vt); } #[deriving(Eq)] @@ -619,7 +619,7 @@ fn check_loans_in_fn(fk: &visit::fn_kind, body: &ast::blk, sp: span, id: ast::node_id, - &&self: @mut CheckLoanCtxt, + self: @mut CheckLoanCtxt, visitor: visit::vt<@mut CheckLoanCtxt>) { let is_stack_closure = self.is_stack_closure(id); let fty = ty::node_id_to_type(self.tcx(), id); @@ -726,13 +726,13 @@ fn check_loans_in_fn(fk: &visit::fn_kind, } fn check_loans_in_local(local: @ast::local, - &&self: @mut CheckLoanCtxt, + self: @mut CheckLoanCtxt, vt: visit::vt<@mut CheckLoanCtxt>) { visit::visit_local(local, self, vt); } fn check_loans_in_expr(expr: @ast::expr, - &&self: @mut CheckLoanCtxt, + self: @mut CheckLoanCtxt, vt: visit::vt<@mut CheckLoanCtxt>) { debug!("check_loans_in_expr(expr=%?/%s)", expr.id, pprust::expr_to_str(expr, self.tcx().sess.intr())); @@ -794,7 +794,7 @@ fn check_loans_in_expr(expr: @ast::expr, } fn check_loans_in_block(blk: &ast::blk, - &&self: @mut CheckLoanCtxt, + self: @mut CheckLoanCtxt, vt: visit::vt<@mut CheckLoanCtxt>) { do save_and_restore_managed(self.declared_purity) { self.check_for_conflicting_loans(blk.node.id); diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 4e61b5738912f..4f2e41dca5c04 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -88,7 +88,7 @@ pub fn gather_loans(bccx: @BorrowckCtxt, crate: @ast::crate) -> ReqMaps { visit_fn: req_loans_in_fn, visit_stmt: add_stmt_to_map, .. *visit::default_visitor()}); - visit::visit_crate(*crate, glcx, v); + visit::visit_crate(crate, glcx, v); let @GatherLoanCtxt{req_maps, _} = glcx; return req_maps; } @@ -98,7 +98,7 @@ fn req_loans_in_fn(fk: &visit::fn_kind, body: &ast::blk, sp: span, id: ast::node_id, - &&self: @mut GatherLoanCtxt, + self: @mut GatherLoanCtxt, v: visit::vt<@mut GatherLoanCtxt>) { // see explanation attached to the `root_ub` field: let old_item_id = self.item_ub; @@ -119,7 +119,7 @@ fn req_loans_in_fn(fk: &visit::fn_kind, } fn req_loans_in_expr(ex: @ast::expr, - &&self: @mut GatherLoanCtxt, + self: @mut GatherLoanCtxt, vt: visit::vt<@mut GatherLoanCtxt>) { let bccx = self.bccx; let tcx = bccx.tcx; @@ -489,7 +489,7 @@ pub impl GatherLoanCtxt { cmt: cmt, loan_kind: LoanKind, scope_r: ty::Region, - +loans: ~[Loan]) { + loans: ~[Loan]) { if loans.len() == 0 { return; } @@ -555,7 +555,7 @@ pub impl GatherLoanCtxt { fn add_loans_to_scope_id(&mut self, scope_id: ast::node_id, - +loans: ~[Loan]) { + loans: ~[Loan]) { debug!("adding %u loans to scope_id %?: %s", loans.len(), scope_id, str::connect(loans.map(|l| self.bccx.loan_to_repr(l)), ", ")); @@ -665,7 +665,7 @@ pub impl GatherLoanCtxt { // Setting up info that preserve needs. // This is just the most convenient place to do it. fn add_stmt_to_map(stmt: @ast::stmt, - &&self: @mut GatherLoanCtxt, + self: @mut GatherLoanCtxt, vt: visit::vt<@mut GatherLoanCtxt>) { match stmt.node { ast::stmt_expr(_, id) | ast::stmt_semi(_, id) => { diff --git a/src/librustc/middle/borrowck/loan.rs b/src/librustc/middle/borrowck/loan.rs index a38cd015654b5..15189a552fb0c 100644 --- a/src/librustc/middle/borrowck/loan.rs +++ b/src/librustc/middle/borrowck/loan.rs @@ -257,10 +257,10 @@ pub impl LoanContext { } fn issue_loan(&mut self, - +cmt: cmt, - +scope_ub: ty::Region, - +loan_kind: LoanKind, - +owns_lent_data: bool) -> bckres<()> { + cmt: cmt, + scope_ub: ty::Region, + loan_kind: LoanKind, + owns_lent_data: bool) -> bckres<()> { // Subtle: the `scope_ub` is the maximal lifetime of `cmt`. // Therefore, if `cmt` owns the data being lent, then the // scope of the loan must be less than `scope_ub`, or else the diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 01fea2a960d4b..dec194aa8e3b9 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -443,7 +443,7 @@ pub impl LoanKind { /// Creates and returns a new root_map impl to_bytes::IterBytes for root_map_key { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.id, &self.derefs, lsb0, f); } } @@ -529,11 +529,11 @@ pub impl BorrowckCtxt { self.note_and_explain_bckerr(err); } - fn span_err(&self, s: span, +m: ~str) { + fn span_err(&self, s: span, m: ~str) { self.tcx.sess.span_err(s, m); } - fn span_note(&self, s: span, +m: ~str) { + fn span_note(&self, s: span, m: ~str) { self.tcx.sess.span_note(s, m); } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 4bbedf5fc0038..1953841e65081 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -26,7 +26,7 @@ pub fn check_crate(sess: Session, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt) { - visit::visit_crate(*crate, false, visit::mk_vt(@visit::Visitor { + visit::visit_crate(crate, false, visit::mk_vt(@visit::Visitor { visit_item: |a,b,c| check_item(sess, ast_map, def_map, a, b, c), visit_pat: check_pat, visit_expr: |a,b,c| @@ -40,7 +40,7 @@ pub fn check_item(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, it: @item, - &&_is_const: bool, + _is_const: bool, v: visit::vt) { match it.node { item_const(_, ex) => { @@ -58,7 +58,7 @@ pub fn check_item(sess: Session, } } -pub fn check_pat(p: @pat, &&_is_const: bool, v: visit::vt) { +pub fn check_pat(p: @pat, _is_const: bool, v: visit::vt) { fn is_str(e: @expr) -> bool { match e.node { expr_vstore( @@ -87,7 +87,7 @@ pub fn check_expr(sess: Session, method_map: typeck::method_map, tcx: ty::ctxt, e: @expr, - &&is_const: bool, + is_const: bool, v: visit::vt) { if is_const { match e.node { @@ -224,7 +224,7 @@ pub fn check_item_recursion(sess: Session, }); (visitor.visit_item)(it, env, visitor); - fn visit_item(it: @item, &&env: env, v: visit::vt) { + fn visit_item(it: @item, env: env, v: visit::vt) { if env.idstack.contains(&(it.id)) { env.sess.span_fatal(env.root_it.span, ~"recursive constant"); } @@ -233,7 +233,7 @@ pub fn check_item_recursion(sess: Session, env.idstack.pop(); } - fn visit_expr(e: @expr, &&env: env, v: visit::vt) { + fn visit_expr(e: @expr, env: env, v: visit::vt) { match e.node { expr_path(*) => { match env.def_map.find(&e.id) { diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 74a79e5e56096..9f26f7f83724f 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -20,7 +20,7 @@ pub struct Context { } pub fn check_crate(tcx: ty::ctxt, crate: @crate) { - visit::visit_crate(*crate, + visit::visit_crate(crate, Context { in_loop: false, can_ret: true }, visit::mk_vt(@visit::Visitor { visit_item: |i, _cx, v| { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 6898dcca45dd8..1db8f8cc8de81 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -40,7 +40,7 @@ pub fn check_crate(tcx: ty::ctxt, let cx = @MatchCheckCtxt {tcx: tcx, method_map: method_map, moves_map: moves_map}; - visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { + visit::visit_crate(crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |a,b,c| check_expr(cx, a, b, c), visit_local: |a,b,c| check_local(cx, a, b, c), visit_fn: |kind, decl, body, sp, id, e, v| @@ -58,7 +58,7 @@ pub fn expr_is_non_moving_lvalue(cx: @MatchCheckCtxt, expr: @expr) -> bool { !cx.moves_map.contains(&expr.id) } -pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { +pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, s: (), v: visit::vt<()>) { visit::visit_expr(ex, s, v); match ex.node { expr_match(scrut, ref arms) => { @@ -259,7 +259,7 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful { not_useful } _ => { - let arity = ctor_arity(cx, single, left_ty); + let arity = ctor_arity(cx, &single, left_ty); is_useful_specialized(cx, m, v, single, arity, left_ty) } } @@ -268,14 +268,14 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful { match is_useful(cx, &m.filter_mapped(|r| default(cx, *r)), v.tail()) { - useful_ => useful(left_ty, (/*bad*/copy *ctor)), + useful_ => useful(left_ty, /*bad*/copy *ctor), ref u => (/*bad*/copy *u) } } } } Some(ref v0_ctor) => { - let arity = ctor_arity(cx, (*v0_ctor), left_ty); + let arity = ctor_arity(cx, v0_ctor, left_ty); is_useful_specialized(cx, m, v, /*bad*/copy *v0_ctor, arity, left_ty) } } @@ -284,13 +284,13 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful { pub fn is_useful_specialized(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat], - +ctor: ctor, + ctor: ctor, arity: uint, lty: ty::t) -> useful { - let ms = m.filter_mapped(|r| specialize(cx, *r, ctor, arity, lty)); + let ms = m.filter_mapped(|r| specialize(cx, *r, &ctor, arity, lty)); let could_be_useful = is_useful( - cx, &ms, specialize(cx, v, ctor, arity, lty).get()); + cx, &ms, specialize(cx, v, &ctor, arity, lty).get()); match could_be_useful { useful_ => useful(lty, ctor), ref u => (/*bad*/copy *u) @@ -447,12 +447,12 @@ pub fn missing_ctor(cx: @MatchCheckCtxt, } } -pub fn ctor_arity(cx: @MatchCheckCtxt, ctor: ctor, ty: ty::t) -> uint { +pub fn ctor_arity(cx: @MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint { match ty::get(ty).sty { ty::ty_tup(ref fs) => fs.len(), ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u, ty::ty_enum(eid, _) => { - let id = match ctor { variant(id) => id, + let id = match *ctor { variant(id) => id, _ => fail!(~"impossible case") }; match vec::find(*ty::enum_variants(cx.tcx, eid), |v| v.id == id ) { Some(v) => v.args.len(), @@ -461,7 +461,7 @@ pub fn ctor_arity(cx: @MatchCheckCtxt, ctor: ctor, ty: ty::t) -> uint { } ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(), ty::ty_unboxed_vec(*) | ty::ty_evec(*) => { - match ctor { + match *ctor { vec(n) => n, _ => 0u } @@ -476,7 +476,7 @@ pub fn wild() -> @pat { pub fn specialize(cx: @MatchCheckCtxt, r: &[@pat], - ctor_id: ctor, + ctor_id: &ctor, arity: uint, left_ty: ty::t) -> Option<~[@pat]> { @@ -491,7 +491,7 @@ pub fn specialize(cx: @MatchCheckCtxt, pat_ident(_, _, _) => { match cx.tcx.def_map.find(&pat_id) { Some(&def_variant(_, id)) => { - if variant(id) == ctor_id { + if variant(id) == *ctor_id { Some(vec::from_slice(r.tail())) } else { None @@ -501,11 +501,11 @@ pub fn specialize(cx: @MatchCheckCtxt, let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); - let match_ = match ctor_id { - val(ref v) => compare_const_vals(e_v, (*v)) == 0, + let match_ = match *ctor_id { + val(ref v) => compare_const_vals(&e_v, v) == 0, range(ref c_lo, ref c_hi) => { - compare_const_vals((*c_lo), e_v) >= 0 && - compare_const_vals((*c_hi), e_v) <= 0 + compare_const_vals(c_lo, &e_v) >= 0 && + compare_const_vals(c_hi, &e_v) <= 0 } single => true, _ => fail!(~"type error") @@ -532,11 +532,11 @@ pub fn specialize(cx: @MatchCheckCtxt, let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); - let match_ = match ctor_id { - val(ref v) => compare_const_vals(e_v, (*v)) == 0, + let match_ = match *ctor_id { + val(ref v) => compare_const_vals(&e_v, v) == 0, range(ref c_lo, ref c_hi) => { - compare_const_vals((*c_lo), e_v) >= 0 && - compare_const_vals((*c_hi), e_v) <= 0 + compare_const_vals(c_lo, &e_v) >= 0 && + compare_const_vals(c_hi, &e_v) <= 0 } single => true, _ => fail!(~"type error") @@ -547,7 +547,7 @@ pub fn specialize(cx: @MatchCheckCtxt, None } } - def_variant(_, id) if variant(id) == ctor_id => { + def_variant(_, id) if variant(id) == *ctor_id => { let args = match args { Some(args) => args, None => vec::from_elem(arity, wild()) @@ -571,7 +571,7 @@ pub fn specialize(cx: @MatchCheckCtxt, // Is this a struct or an enum variant? match *cx.tcx.def_map.get(&pat_id) { def_variant(_, variant_id) => { - if variant(variant_id) == ctor_id { + if variant(variant_id) == *ctor_id { // FIXME #4731: Is this right? --pcw let args = flds.map(|ty_field| { match flds.find(|f| @@ -620,11 +620,11 @@ pub fn specialize(cx: @MatchCheckCtxt, } pat_lit(expr) => { let e_v = eval_const_expr(cx.tcx, expr); - let match_ = match ctor_id { - val(ref v) => compare_const_vals(e_v, (*v)) == 0, + let match_ = match *ctor_id { + val(ref v) => compare_const_vals(&e_v, v) == 0, range(ref c_lo, ref c_hi) => { - compare_const_vals((*c_lo), e_v) >= 0 && - compare_const_vals((*c_hi), e_v) <= 0 + compare_const_vals(c_lo, &e_v) >= 0 && + compare_const_vals(c_hi, &e_v) <= 0 } single => true, _ => fail!(~"type error") @@ -632,7 +632,7 @@ pub fn specialize(cx: @MatchCheckCtxt, if match_ { Some(vec::from_slice(r.tail())) } else { None } } pat_range(lo, hi) => { - let (c_lo, c_hi) = match ctor_id { + let (c_lo, c_hi) = match *ctor_id { val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)), range(ref lo, ref hi) => ((/*bad*/copy *lo), (/*bad*/copy *hi)), @@ -641,12 +641,12 @@ pub fn specialize(cx: @MatchCheckCtxt, }; let v_lo = eval_const_expr(cx.tcx, lo), v_hi = eval_const_expr(cx.tcx, hi); - let match_ = compare_const_vals(c_lo, v_lo) >= 0 && - compare_const_vals(c_hi, v_hi) <= 0; + let match_ = compare_const_vals(&c_lo, &v_lo) >= 0 && + compare_const_vals(&c_hi, &v_hi) <= 0; if match_ { Some(vec::from_slice(r.tail())) } else { None } } pat_vec(before, slice, after) => { - match ctor_id { + match *ctor_id { vec(_) => { let num_elements = before.len() + after.len(); if num_elements < arity && slice.is_some() { @@ -682,7 +682,7 @@ pub fn default(cx: @MatchCheckCtxt, r: &[@pat]) -> Option<~[@pat]> { pub fn check_local(cx: @MatchCheckCtxt, loc: @local, - &&s: (), + s: (), v: visit::vt<()>) { visit::visit_local(loc, s, v); if is_refutable(cx, loc.node.pat) { @@ -704,7 +704,7 @@ pub fn check_fn(cx: @MatchCheckCtxt, body: &blk, sp: span, id: node_id, - &&s: (), + s: (), v: visit::vt<()>) { visit::visit_fn(kind, decl, body, sp, id, s, v); for decl.inputs.each |input| { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 63122a82eafdf..5148ea7fba403 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -229,7 +229,7 @@ pub fn process_crate(crate: @ast::crate, visit_expr_post: |e| { classify(e, tcx); }, .. *visit::default_simple_visitor() }); - visit::visit_crate(*crate, (), v); + visit::visit_crate(crate, (), v); tcx.sess.abort_if_errors(); } @@ -426,8 +426,8 @@ pub fn lit_to_const(lit: @lit) -> const_val { } } -pub fn compare_const_vals(a: const_val, b: const_val) -> int { - match (&a, &b) { +pub fn compare_const_vals(a: &const_val, b: &const_val) -> int { + match (a, b) { (&const_int(a), &const_int(b)) => { if a == b { 0 @@ -478,7 +478,7 @@ pub fn compare_const_vals(a: const_val, b: const_val) -> int { } pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> int { - compare_const_vals(eval_const_expr(tcx, a), eval_const_expr(tcx, b)) + compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b)) } pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool { @@ -486,7 +486,7 @@ pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool { } pub fn lit_eq(a: @lit, b: @lit) -> bool { - compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0 + compare_const_vals(&lit_to_const(a), &lit_to_const(b)) == 0 } diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index e6e9f3be85d21..b25c3be0d683d 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -42,9 +42,9 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::blk) let seen = @mut HashMap::new(); let refs = @mut ~[]; - fn ignore_item(_i: @ast::item, &&_depth: int, _v: visit::vt) { } + fn ignore_item(_i: @ast::item, _depth: int, _v: visit::vt) { } - let walk_expr: @fn(expr: @ast::expr, &&depth: int, v: visit::vt) = + let walk_expr: @fn(expr: @ast::expr, depth: int, v: visit::vt) = |expr, depth, v| { match expr.node { ast::expr_fn_block(*) => visit::visit_expr(expr, depth + 1, v), @@ -107,7 +107,7 @@ pub fn annotate_freevars(def_map: resolve::DefMap, crate: @ast::crate) -> visit::mk_simple_visitor(@visit::SimpleVisitor { visit_fn: walk_fn, .. *visit::default_simple_visitor()}); - visit::visit_crate(*crate, (), visitor); + visit::visit_crate(crate, (), visitor); return freevars; } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 59ae4812f2778..390ffded2fe36 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -81,7 +81,7 @@ pub fn check_crate(tcx: ty::ctxt, visit_block: check_block, .. *visit::default_visitor() }); - visit::visit_crate(*crate, ctx, visit); + visit::visit_crate(crate, ctx, visit); tcx.sess.abort_if_errors(); } @@ -573,7 +573,7 @@ pub fn check_cast_for_escaping_regions( true }); - fn is_re_scope(+r: ty::Region) -> bool { + fn is_re_scope(r: ty::Region) -> bool { match r { ty::re_scope(*) => true, _ => false diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index bacbeb851aa82..435cb896ac7a1 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -370,7 +370,7 @@ pub impl<'self> LanguageItemCollector<'self> { fn collect_local_language_items(&self) { let this = ptr::addr_of(&self); - visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor { + visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { for item.attrs.each |attribute| { unsafe { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 876ed76f98741..39144d46c83c4 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -348,7 +348,7 @@ pub impl Context { } } - fn span_lint(&self, level: level, span: span, +msg: ~str) { + fn span_lint(&self, level: level, span: span, msg: ~str) { self.sess.span_lint_level(level, span, msg); } @@ -438,7 +438,7 @@ pub impl Context { } -fn build_settings_item(i: @ast::item, &&cx: Context, v: visit::vt) { +fn build_settings_item(i: @ast::item, cx: Context, v: visit::vt) { do cx.with_lint_attrs(/*bad*/copy i.attrs) |cx| { if !cx.is_default { cx.sess.lint_settings.settings_map.insert(i.id, cx.curr); @@ -481,7 +481,7 @@ pub fn build_settings_crate(sess: session::Session, crate: @ast::crate) { visit_item: build_settings_item, .. *visit::default_visitor() }); - visit::visit_crate(*crate, cx, visit); + visit::visit_crate(crate, cx, visit); } sess.abort_if_errors(); @@ -1088,7 +1088,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { check_fn(tcx, fk, decl, body, span, id), .. *visit::default_simple_visitor() }); - visit::visit_crate(*crate, (), v); + visit::visit_crate(crate, (), v); tcx.sess.abort_if_errors(); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3a649e7cc3b2b..3136d7bf4e4ac 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -182,7 +182,7 @@ pub fn check_crate(tcx: ty::ctxt, capture_map, last_use_map, 0); - visit::visit_crate(*crate, initial_maps, visitor); + visit::visit_crate(crate, initial_maps, visitor); tcx.sess.abort_if_errors(); return last_use_map; } @@ -358,7 +358,7 @@ pub impl IrMaps { } } - fn set_captures(&mut self, node_id: node_id, +cs: ~[CaptureInfo]) { + fn set_captures(&mut self, node_id: node_id, cs: ~[CaptureInfo]) { self.capture_info_map.insert(node_id, @cs); } @@ -402,7 +402,7 @@ pub impl IrMaps { } } -fn visit_item(item: @item, &&self: @mut IrMaps, v: vt<@mut IrMaps>) { +fn visit_item(item: @item, self: @mut IrMaps, v: vt<@mut IrMaps>) { do with(&mut self.cur_item, item.id) { visit::visit_item(item, self, v) } @@ -413,7 +413,7 @@ fn visit_fn(fk: &visit::fn_kind, body: &blk, sp: span, id: node_id, - &&self: @mut IrMaps, + self: @mut IrMaps, v: vt<@mut IrMaps>) { debug!("visit_fn: id=%d", id); let _i = ::util::common::indenter(); @@ -489,7 +489,7 @@ fn visit_fn(fk: &visit::fn_kind, lsets.warn_about_unused_args(decl, entry_ln); } -fn visit_local(local: @local, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) { +fn visit_local(local: @local, self: @mut IrMaps, vt: vt<@mut IrMaps>) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| { debug!("adding local variable %d", p_id); @@ -509,7 +509,7 @@ fn visit_local(local: @local, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) { visit::visit_local(local, self, vt); } -fn visit_arm(arm: &arm, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) { +fn visit_arm(arm: &arm, self: @mut IrMaps, vt: vt<@mut IrMaps>) { let def_map = self.tcx.def_map; for arm.pats.each |pat| { do pat_util::pat_bindings(def_map, *pat) |bm, p_id, sp, path| { @@ -528,7 +528,7 @@ fn visit_arm(arm: &arm, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) { visit::visit_arm(arm, self, vt); } -fn visit_expr(expr: @expr, &&self: @mut IrMaps, vt: vt<@mut IrMaps>) { +fn visit_expr(expr: @expr, self: @mut IrMaps, vt: vt<@mut IrMaps>) { match expr.node { // live nodes required for uses or definitions of variables: expr_path(_) => { @@ -1510,7 +1510,7 @@ pub impl Liveness { // _______________________________________________________________________ // Checking for error conditions -fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) { +fn check_local(local: @local, self: @Liveness, vt: vt<@Liveness>) { match local.node.init { Some(_) => { @@ -1544,14 +1544,14 @@ fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) { visit::visit_local(local, self, vt); } -fn check_arm(arm: &arm, &&self: @Liveness, vt: vt<@Liveness>) { +fn check_arm(arm: &arm, self: @Liveness, vt: vt<@Liveness>) { do self.arm_pats_bindings(arm.pats) |ln, var, sp, id| { self.warn_about_unused(sp, id, ln, var); } visit::visit_arm(arm, self, vt); } -fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { +fn check_expr(expr: @expr, self: @Liveness, vt: vt<@Liveness>) { match expr.node { expr_path(_) => { for self.variable_from_def_map(expr.id, expr.span).each |var| { @@ -1632,7 +1632,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { fn check_fn(_fk: &visit::fn_kind, _decl: &fn_decl, _body: &blk, _sp: span, _id: node_id, - &&_self: @Liveness, _v: vt<@Liveness>) { + _self: @Liveness, _v: vt<@Liveness>) { // do not check contents of nested fns } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index 1401d86123e64..66ce4d16d4bc2 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -285,7 +285,7 @@ pub fn compute_moves(tcx: ty::ctxt, capture_map: @mut HashMap::new() } }; - visit::visit_crate(*crate, visit_cx, visitor); + visit::visit_crate(crate, visit_cx, visitor); return visit_cx.move_maps; } @@ -293,7 +293,7 @@ pub fn compute_moves(tcx: ty::ctxt, // Expressions fn compute_modes_for_expr(expr: @expr, - &&cx: VisitContext, + cx: VisitContext, v: vt) { cx.consume_expr(expr, v); @@ -760,7 +760,7 @@ pub impl VisitContext { fn arms_have_by_move_bindings(&self, moves_map: MovesMap, - +arms: &[arm]) -> bool + arms: &[arm]) -> bool { for arms.each |arm| { for arm.pats.each |pat| { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index e59ca9e658123..89dad7fc01c10 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -604,6 +604,6 @@ pub fn check_crate(tcx: ty::ctxt, }, .. *visit::default_visitor() }); - visit::visit_crate(*crate, method_map, visitor); + visit::visit_crate(crate, method_map, visitor); } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index ecb9fc2cd08b8..043aa8d2533fa 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -496,7 +496,7 @@ pub fn resolve_crate(sess: Session, visit_local: resolve_local, .. *visit::default_visitor() }); - visit::visit_crate(*crate, cx, visitor); + visit::visit_crate(crate, cx, visitor); return region_maps; } @@ -549,8 +549,8 @@ pub struct DetermineRpCtxt { ambient_variance: region_variance, } -pub fn join_variance(++variance1: region_variance, - ++variance2: region_variance) +pub fn join_variance(variance1: region_variance, + variance2: region_variance) -> region_variance { match (variance1, variance2) { (rv_invariant, _) => {rv_invariant} @@ -570,8 +570,8 @@ pub fn join_variance(++variance1: region_variance, /// appears in a co-variant position. This implies that this /// occurrence of `r` is contra-variant with respect to the current /// item, and hence the function returns `rv_contravariant`. -pub fn add_variance(+ambient_variance: region_variance, - +variance: region_variance) +pub fn add_variance(ambient_variance: region_variance, + variance: region_variance) -> region_variance { match (ambient_variance, variance) { (rv_invariant, _) => rv_invariant, @@ -719,7 +719,7 @@ pub impl DetermineRpCtxt { } pub fn determine_rp_in_item(item: @ast::item, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { do cx.with(item.id, true) { visit::visit_item(item, cx, visitor); @@ -731,7 +731,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind, body: &ast::blk, _: span, _: ast::node_id, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { do cx.with(cx.item_id, false) { do cx.with_ambient_variance(rv_contravariant) { @@ -747,7 +747,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind, } pub fn determine_rp_in_ty_method(ty_m: &ast::ty_method, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { do cx.with(cx.item_id, false) { visit::visit_ty_method(ty_m, cx, visitor); @@ -755,7 +755,7 @@ pub fn determine_rp_in_ty_method(ty_m: &ast::ty_method, } pub fn determine_rp_in_ty(ty: @ast::Ty, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { // we are only interested in types that will require an item to // be region-parameterized. if cx.item_id is zero, then this type @@ -871,7 +871,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, } fn visit_mt(mt: ast::mt, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { // mutability is invariant if mt.mutbl == ast::m_mutbl { @@ -886,7 +886,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, pub fn determine_rp_in_struct_field( cm: @ast::struct_field, - &&cx: @mut DetermineRpCtxt, + cx: @mut DetermineRpCtxt, visitor: visit::vt<@mut DetermineRpCtxt>) { match cm.node.kind { ast::named_field(_, ast::struct_mutable, _) => { @@ -903,7 +903,7 @@ pub fn determine_rp_in_struct_field( pub fn determine_rp_in_crate(sess: Session, ast_map: ast_map::map, - +def_map: resolve::DefMap, + def_map: resolve::DefMap, crate: @ast::crate) -> region_paramd_items { let cx = @mut DetermineRpCtxt { @@ -927,7 +927,7 @@ pub fn determine_rp_in_crate(sess: Session, visit_struct_field: determine_rp_in_struct_field, .. *visit::default_visitor() }); - visit::visit_crate(*crate, cx, visitor); + visit::visit_crate(crate, cx, visitor); // Propagate indirect dependencies // diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index b2225963d2c33..3c158c0d081f8 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -351,7 +351,7 @@ pub struct ImportDirective { } pub fn ImportDirective(privacy: Privacy, - +module_path: ~[ident], + module_path: ~[ident], subclass: @ImportDirectiveSubclass, span: span) -> ImportDirective { @@ -401,7 +401,7 @@ pub struct ImportResolution { } pub fn ImportResolution(privacy: Privacy, - +span: span, + span: span, state: @mut ImportState) -> ImportResolution { ImportResolution { privacy: privacy, @@ -904,7 +904,7 @@ pub impl Resolver { fn build_reduced_graph(@mut self) { let initial_parent = ModuleReducedGraphParent(self.graph_root.get_module()); - visit_crate(*self.crate, initial_parent, mk_vt(@Visitor { + visit_crate(self.crate, initial_parent, mk_vt(@Visitor { visit_item: |item, context, visitor| self.build_reduced_graph_for_item(item, context, visitor), @@ -1088,7 +1088,7 @@ pub impl Resolver { fn build_reduced_graph_for_item(@mut self, item: @item, parent: ReducedGraphParent, - &&visitor: vt) { + visitor: vt) { let ident = item.ident; let sp = item.span; let privacy = visibility_to_privacy(item.vis); @@ -1173,7 +1173,7 @@ pub impl Resolver { (privacy, def_ty(local_def(item.id)), sp); for (*enum_definition).variants.each |variant| { - self.build_reduced_graph_for_variant(*variant, + self.build_reduced_graph_for_variant(variant, local_def(item.id), // inherited => privacy of the enum item variant_visibility_to_privacy(variant.node.vis, @@ -1362,11 +1362,11 @@ pub impl Resolver { // Constructs the reduced graph for one variant. Variants exist in the // type and/or value namespaces. fn build_reduced_graph_for_variant(@mut self, - variant: variant, + variant: &variant, item_id: def_id, - +parent_privacy: Privacy, + parent_privacy: Privacy, parent: ReducedGraphParent, - &&_visitor: vt) { + _visitor: vt) { let ident = variant.node.name; let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues, variant.span); @@ -1402,7 +1402,7 @@ pub impl Resolver { fn build_reduced_graph_for_view_item(@mut self, view_item: @view_item, parent: ReducedGraphParent, - &&_visitor: vt) { + _visitor: vt) { let privacy = visibility_to_privacy(view_item.vis); match view_item.node { view_item_use(ref view_paths) => { @@ -1495,7 +1495,7 @@ pub impl Resolver { fn build_reduced_graph_for_foreign_item(@mut self, foreign_item: @foreign_item, parent: ReducedGraphParent, - &&visitor: + visitor: vt) { let name = foreign_item.ident; let (name_bindings, new_parent) = @@ -1526,7 +1526,7 @@ pub impl Resolver { fn build_reduced_graph_for_block(@mut self, block: &blk, parent: ReducedGraphParent, - &&visitor: vt) { + visitor: vt) { let mut new_parent; if self.block_needs_anonymous_module(block) { let block_id = block.node.id; @@ -1849,7 +1849,7 @@ pub impl Resolver { fn build_import_directive(@mut self, privacy: Privacy, module_: @mut Module, - +module_path: ~[ident], + module_path: ~[ident], subclass: @ImportDirectiveSubclass, span: span) { let directive = @ImportDirective(privacy, module_path, @@ -2912,7 +2912,7 @@ pub impl Resolver { module_: @mut Module, name: ident, namespace: Namespace, - +name_search_type: NameSearchType) + name_search_type: NameSearchType) -> ResolveResult { debug!("(resolving name in module) resolving `%s` in `%s`", *self.session.str_of(name), @@ -3352,7 +3352,7 @@ pub impl Resolver { fn resolve_crate(@mut self) { debug!("(resolving crate) starting"); - visit_crate(*self.crate, (), mk_vt(@Visitor { + visit_crate(self.crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| self.resolve_item(item, visitor), visit_arm: |arm, _context, visitor| @@ -3509,7 +3509,7 @@ pub impl Resolver { self.resolve_struct(item.id, generics, struct_def.fields, - struct_def.dtor, + &struct_def.dtor, visitor); } @@ -3768,7 +3768,7 @@ pub impl Resolver { id: node_id, generics: &Generics, fields: &[@struct_field], - optional_destructor: Option, + optional_destructor: &Option, visitor: ResolveVisitor) { // If applicable, create a rib for the type parameters. do self.with_type_parameter_rib(HasTypeParameters @@ -3784,7 +3784,7 @@ pub impl Resolver { } // Resolve the destructor, if applicable. - match optional_destructor { + match *optional_destructor { None => { // Nothing to do. } @@ -4525,7 +4525,7 @@ pub impl Resolver { fn resolve_module_relative_path(@mut self, path: @Path, - +xray: XrayFlag, + xray: XrayFlag, namespace: Namespace) -> Option { let module_path_idents = self.intern_module_part_of_path(path); @@ -4571,7 +4571,7 @@ pub impl Resolver { /// import resolution. fn resolve_crate_relative_path(@mut self, path: @Path, - +xray: XrayFlag, + xray: XrayFlag, namespace: Namespace) -> Option { let module_path_idents = self.intern_module_part_of_path(path); @@ -5076,7 +5076,7 @@ pub impl Resolver { fn add_fixed_trait_for_expr(@mut self, expr_id: node_id, - +trait_id: def_id) { + trait_id: def_id) { self.trait_map.insert(expr_id, @mut ~[trait_id]); } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 32c9189ad2d7d..7339003c6143a 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -785,7 +785,7 @@ pub fn enter_region<'r>(bcx: block, // on a set of enum variants or a literal. pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] { let ccx = bcx.ccx(); - fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], +val: Opt) { + fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) { if set.any(|l| opt_eq(tcx, l, &val)) {return;} set.push(val); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index c4c7eb0b8e726..e1c60234f0ff0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -136,7 +136,7 @@ fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool { } } -pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec, +pub fn log_fn_time(ccx: @CrateContext, name: ~str, start: time::Timespec, end: time::Timespec) { let elapsed = 1000 * ((end.sec - start.sec) as int) + ((end.nsec as int) - (start.nsec as int)) / 1000000; @@ -165,7 +165,7 @@ pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, llty: TypeRef) // Only use this if you are going to actually define the function. It's // not valid to simply declare a function as internal. -pub fn decl_internal_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) -> +pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) -> ValueRef { let llfn = decl_cdecl_fn(llmod, name, llty); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); @@ -828,7 +828,7 @@ pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t) }; } -pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) +pub fn invoke(bcx: block, llfn: ValueRef, llargs: ~[ValueRef]) -> (ValueRef, block) { let _icx = bcx.insn_ctxt("invoke_"); if bcx.unreachable { @@ -924,7 +924,7 @@ pub fn have_cached_lpad(bcx: block) -> bool { return res; } -pub fn in_lpad_scope_cx(bcx: block, f: &fn(+si: &mut scope_info)) { +pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) { let mut bcx = bcx; loop { { @@ -1057,10 +1057,7 @@ pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef { // Since this function does *not* root, it is the caller's responsibility to // ensure that the referent is pointed to by a root. -// [Note-arg-mode] -// ++ mode is temporary, due to how borrowck treats enums. With hope, -// will go away anyway when we get rid of modes. -pub fn do_spill_noroot(++cx: block, v: ValueRef) -> ValueRef { +pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef { let llptr = alloca(cx, val_ty(v)); Store(cx, v, llptr); return llptr; @@ -1163,7 +1160,7 @@ pub fn init_local(bcx: block, local: @ast::local) -> block { _match::BindLocal); } -pub fn trans_stmt(cx: block, s: ast::stmt) -> block { +pub fn trans_stmt(cx: block, s: &ast::stmt) -> block { let _icx = cx.insn_ctxt("trans_stmt"); debug!("trans_stmt(%s)", stmt_to_str(s, cx.tcx().sess.intr())); @@ -1189,7 +1186,7 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block { } } } - ast::decl_item(i) => trans_item(*cx.fcx.ccx, *i) + ast::decl_item(i) => trans_item(*cx.fcx.ccx, i) } } ast::stmt_mac(*) => cx.tcx().sess.bug(~"unexpanded macro") @@ -1200,8 +1197,8 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block { // You probably don't want to use this one. See the // next three functions instead. -pub fn new_block(cx: fn_ctxt, parent: Option, +kind: block_kind, - is_lpad: bool, +name: ~str, opt_node_info: Option) +pub fn new_block(cx: fn_ctxt, parent: Option, kind: block_kind, + is_lpad: bool, name: ~str, opt_node_info: Option) -> block { let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo { @@ -1245,7 +1242,7 @@ pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option) pub fn scope_block(bcx: block, opt_node_info: Option, - +n: ~str) -> block { + n: ~str) -> block { return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad, n, opt_node_info); } @@ -1253,7 +1250,7 @@ pub fn scope_block(bcx: block, pub fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option, - +n: ~str, + n: ~str, opt_node_info: Option) -> block { return new_block(bcx.fcx, Some(bcx), block_scope(scope_info { loop_break: Some(loop_break), @@ -1265,12 +1262,12 @@ pub fn loop_scope_block(bcx: block, } // Use this when creating a block for the inside of a landing pad. -pub fn lpad_block(bcx: block, +n: ~str) -> block { +pub fn lpad_block(bcx: block, n: ~str) -> block { new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None) } // Use this when you're making a general CFG BB within a scope. -pub fn sub_block(bcx: block, +n: ~str) -> block { +pub fn sub_block(bcx: block, n: ~str) -> block { new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None) } @@ -1286,12 +1283,12 @@ pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block { // need to make sure those variables go out of scope when the block ends. We // do that by running a 'cleanup' function for each variable. // trans_block_cleanups runs all the cleanup functions for the block. -pub fn trans_block_cleanups(bcx: block, +cleanups: ~[cleanup]) -> block { +pub fn trans_block_cleanups(bcx: block, cleanups: ~[cleanup]) -> block { trans_block_cleanups_(bcx, cleanups, false) } pub fn trans_block_cleanups_(bcx: block, - +cleanups: ~[cleanup], + cleanups: ~[cleanup], /* cleanup_cx: block, */ is_lpad: bool) -> block { let _icx = bcx.insn_ctxt("trans_block_cleanups"); @@ -1387,7 +1384,7 @@ pub fn leave_block(bcx: block, out_of: block) -> block { pub fn with_scope(bcx: block, opt_node_info: Option, - +name: ~str, + name: ~str, f: &fn(block) -> block) -> block { let _icx = bcx.insn_ctxt("with_scope"); @@ -1402,7 +1399,7 @@ pub fn with_scope(bcx: block, pub fn with_scope_result(bcx: block, opt_node_info: Option, - +name: ~str, + name: ~str, f: &fn(block) -> Result) -> Result { let _icx = bcx.insn_ctxt("with_scope_result"); let scope_cx = scope_block(bcx, opt_node_info, name); @@ -1412,7 +1409,7 @@ pub fn with_scope_result(bcx: block, } pub fn with_scope_datumblock(bcx: block, opt_node_info: Option, - +name: ~str, f: &fn(block) -> datum::DatumBlock) + name: ~str, f: &fn(block) -> datum::DatumBlock) -> datum::DatumBlock { use middle::trans::datum::DatumBlock; @@ -1620,7 +1617,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef { // - new_fn_ctxt // - trans_args pub fn new_fn_ctxt_w_id(ccx: @CrateContext, - +path: path, + path: path, llfndecl: ValueRef, id: ast::node_id, output_type: ty::t, @@ -1674,7 +1671,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, } pub fn new_fn_ctxt(ccx: @CrateContext, - +path: path, + path: path, llfndecl: ValueRef, output_type: ty::t, sp: Option) @@ -1839,7 +1836,7 @@ pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, } // If the function closes over its environment a closure will be // returned. pub fn trans_closure(ccx: @CrateContext, - +path: path, + path: path, decl: &ast::fn_decl, body: &ast::blk, llfndecl: ValueRef, @@ -1920,7 +1917,7 @@ pub fn trans_closure(ccx: @CrateContext, // trans_fn: creates an LLVM function corresponding to a source language // function. pub fn trans_fn(ccx: @CrateContext, - +path: path, + path: path, decl: &ast::fn_decl, body: &ast::blk, llfndecl: ValueRef, @@ -1965,7 +1962,7 @@ pub fn trans_fn(ccx: @CrateContext, pub fn trans_enum_variant(ccx: @CrateContext, enum_id: ast::node_id, - variant: ast::variant, + variant: &ast::variant, args: &[ast::variant_arg], disr: int, param_substs: Option<@param_substs>, @@ -2108,7 +2105,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext, } pub fn trans_struct_dtor(ccx: @CrateContext, - +path: path, + path: path, body: &ast::blk, dtor_id: ast::node_id, psubsts: Option<@param_substs>, @@ -2154,7 +2151,7 @@ pub fn trans_struct_dtor(ccx: @CrateContext, lldecl } -pub fn trans_enum_def(ccx: @CrateContext, enum_definition: ast::enum_def, +pub fn trans_enum_def(ccx: @CrateContext, enum_definition: &ast::enum_def, id: ast::node_id, path: @ast_map::path, vi: @~[ty::VariantInfo], i: &mut uint) { @@ -2165,7 +2162,7 @@ pub fn trans_enum_def(ccx: @CrateContext, enum_definition: ast::enum_def, match variant.node.kind { ast::tuple_variant_kind(ref args) if args.len() > 0 => { let llfn = get_item_val(ccx, variant.node.id); - trans_enum_variant(ccx, id, *variant, *args, + trans_enum_variant(ccx, id, variant, *args, disr_val, None, llfn); } ast::tuple_variant_kind(_) => { @@ -2179,7 +2176,7 @@ pub fn trans_enum_def(ccx: @CrateContext, enum_definition: ast::enum_def, } } -pub fn trans_item(ccx: @CrateContext, item: ast::item) { +pub fn trans_item(ccx: @CrateContext, item: &ast::item) { let _icx = ccx.insn_ctxt("trans_item"); let path = match *ccx.tcx.items.get(&item.id) { ast_map::node_item(_, p) => p, @@ -2214,7 +2211,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { match stmt.node { ast::stmt_decl(@codemap::spanned { node: ast::decl_item(i), _ }, _) => { - trans_item(ccx, *i); + trans_item(ccx, i); } _ => () } @@ -2232,7 +2229,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { if !generics.is_type_parameterized() { let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); let mut i = 0; - trans_enum_def(ccx, (*enum_definition), item.id, + trans_enum_def(ccx, enum_definition, item.id, path, vi, &mut i); } } @@ -2279,13 +2276,13 @@ pub fn trans_struct_def(ccx: @CrateContext, struct_def: @ast::struct_def, pub fn trans_mod(ccx: @CrateContext, m: &ast::_mod) { let _icx = ccx.insn_ctxt("trans_mod"); for m.items.each |item| { - trans_item(ccx, **item); + trans_item(ccx, *item); } } pub fn register_fn(ccx: @CrateContext, sp: span, - +path: path, + path: path, node_id: ast::node_id, attrs: &[ast::attribute]) -> ValueRef { @@ -2295,7 +2292,7 @@ pub fn register_fn(ccx: @CrateContext, pub fn register_fn_full(ccx: @CrateContext, sp: span, - +path: path, + path: path, node_id: ast::node_id, attrs: &[ast::attribute], node_type: ty::t) @@ -2307,7 +2304,7 @@ pub fn register_fn_full(ccx: @CrateContext, pub fn register_fn_fuller(ccx: @CrateContext, sp: span, - +path: path, + path: path, node_id: ast::node_id, attrs: &[ast::attribute], node_type: ty::t, @@ -2495,7 +2492,7 @@ pub fn item_path(ccx: @CrateContext, i: @ast::item) -> path { /* If there's already a symbol for the dtor with and substs , return it; otherwise, create one and register it, returning it as well */ pub fn get_dtor_symbol(ccx: @CrateContext, - +path: path, + path: path, id: ast::node_id, substs: Option<@param_substs>) -> ~str { @@ -2749,7 +2746,7 @@ pub fn trans_constant(ccx: @CrateContext, it: @ast::item) { pub fn trans_constants(ccx: @CrateContext, crate: &ast::crate) { visit::visit_crate( - *crate, (), + crate, (), visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |a| trans_constant(ccx, a), ..*visit::default_simple_visitor() @@ -3146,7 +3143,7 @@ pub fn trans_crate(sess: session::Session, tcx: ty::ctxt, output: &Path, emap2: resolve::ExportMap2, - +maps: astencode::Maps) -> (ModuleRef, LinkMeta) { + maps: astencode::Maps) -> (ModuleRef, LinkMeta) { let symbol_hasher = @hash::default_state(); let link_meta = diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index 31ac4534462a5..ecde50f347072 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -41,7 +41,7 @@ enum x86_64_reg_class { memory_class } -fn is_sse(++c: x86_64_reg_class) -> bool { +fn is_sse(c: x86_64_reg_class) -> bool { return match c { sse_fs_class | sse_fv_class | sse_ds_class | sse_dv_class => true, diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 88d185740298f..3301ed62cbe1f 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -444,7 +444,7 @@ pub fn body_contains_ret(body: &ast::blk) -> bool { } // See [Note-arg-mode] -pub fn trans_call_inner(++in_cx: block, +pub fn trans_call_inner(in_cx: block, call_info: Option, fn_expr_ty: ty::t, ret_ty: ty::t, @@ -592,7 +592,7 @@ pub enum CallArgs<'self> { ArgVals(&'self [ValueRef]) } -pub fn trans_ret_slot(+bcx: block, +fn_ty: ty::t, +dest: expr::Dest) +pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest) -> ValueRef { let retty = ty::ty_fn_ret(fn_ty); @@ -610,12 +610,12 @@ pub fn trans_ret_slot(+bcx: block, +fn_ty: ty::t, +dest: expr::Dest) } } -pub fn trans_args(+cx: block, - +args: CallArgs, - +fn_ty: ty::t, - +ret_flag: Option, - +autoref_arg: AutorefArg, - +llargs: &mut ~[ValueRef]) -> block +pub fn trans_args(cx: block, + args: CallArgs, + fn_ty: ty::t, + ret_flag: Option, + autoref_arg: AutorefArg, + llargs: &mut ~[ValueRef]) -> block { let _icx = cx.insn_ctxt("trans_args"); let mut temp_cleanups = ~[]; @@ -663,9 +663,9 @@ pub enum AutorefArg { pub fn trans_arg_expr(bcx: block, formal_ty: ty::arg, arg_expr: @ast::expr, - +temp_cleanups: &mut ~[ValueRef], - +ret_flag: Option, - +autoref_arg: AutorefArg) -> Result { + temp_cleanups: &mut ~[ValueRef], + ret_flag: Option, + autoref_arg: AutorefArg) -> Result { let _icx = bcx.insn_ctxt("trans_arg_expr"); let ccx = bcx.ccx(); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 76f0892277e28..a2ce83c45c2e7 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -59,9 +59,9 @@ use syntax::parse::token::ident_interner; use syntax::{ast, ast_map}; use syntax::abi::{X86, X86_64, Arm, Mips}; -pub type namegen = @fn(+s: ~str) -> ident; +pub type namegen = @fn(s: ~str) -> ident; pub fn new_namegen(intr: @ident_interner) -> namegen { - let f: @fn(+s: ~str) -> ident = |prefix| { + let f: @fn(s: ~str) -> ident = |prefix| { intr.gensym(@fmt!("%s_%u", prefix, intr.gensym(@prefix).repr)) @@ -395,7 +395,7 @@ pub struct cleanup_path { dest: BasicBlockRef } -pub fn scope_clean_changed(+scope_info: &mut scope_info) { +pub fn scope_clean_changed(scope_info: &mut scope_info) { if scope_info.cleanup_paths.len() > 0u { scope_info.cleanup_paths = ~[]; } scope_info.landing_pad = None; } @@ -626,7 +626,7 @@ pub struct block_ { fcx: fn_ctxt } -pub fn block_(llbb: BasicBlockRef, parent: Option, +kind: block_kind, +pub fn block_(llbb: BasicBlockRef, parent: Option, kind: block_kind, is_lpad: bool, node_info: Option, fcx: fn_ctxt) -> block_ { @@ -644,7 +644,7 @@ pub fn block_(llbb: BasicBlockRef, parent: Option, +kind: block_kind, pub type block = @mut block_; -pub fn mk_block(llbb: BasicBlockRef, parent: Option, +kind: block_kind, +pub fn mk_block(llbb: BasicBlockRef, parent: Option, kind: block_kind, is_lpad: bool, node_info: Option, fcx: fn_ctxt) -> block { @mut block_(llbb, parent, kind, is_lpad, node_info, fcx) @@ -663,7 +663,7 @@ pub fn rslt(bcx: block, val: ValueRef) -> Result { } pub impl Result { - fn unpack(&self, +bcx: &mut block) -> ValueRef { + fn unpack(&self, bcx: &mut block) -> ValueRef { *bcx = self.bcx; return self.val; } @@ -683,7 +683,7 @@ pub fn val_str(tn: @TypeNames, v: ValueRef) -> @str { return ty_str(tn, val_ty(v)); } -pub fn in_scope_cx(cx: block, f: &fn(+si: &mut scope_info)) { +pub fn in_scope_cx(cx: block, f: &fn(si: &mut scope_info)) { let mut cur = cx; loop { { @@ -1252,7 +1252,7 @@ pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef { } } -pub fn C_shape(ccx: @CrateContext, +bytes: ~[u8]) -> ValueRef { +pub fn C_shape(ccx: @CrateContext, bytes: ~[u8]) -> ValueRef { unsafe { let llshape = C_bytes_plus_null(bytes); let name = fmt!("shape%u", (ccx.names)(~"shape").repr); @@ -1325,7 +1325,7 @@ pub struct mono_id_ { pub type mono_id = @mono_id_; impl to_bytes::IterBytes for mono_param_id { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { mono_precise(t, ref mids) => to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), mids, lsb0, f), @@ -1339,7 +1339,7 @@ impl to_bytes::IterBytes for mono_param_id { } impl to_bytes::IterBytes for mono_id_ { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f); } } @@ -1433,7 +1433,7 @@ pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res) // Apply the typaram substitutions in the fn_ctxt to a vtable. This should // eliminate any vtable_params. -pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin) +pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin) -> typeck::vtable_origin { let tcx = fcx.ccx.tcx; match vt { @@ -1479,7 +1479,7 @@ pub fn find_vtable(tcx: ty::ctxt, ps: ¶m_substs, /*bad*/ copy ps.vtables.get()[vtable_off] } -pub fn dummy_substs(+tps: ~[ty::t]) -> ty::substs { +pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs { substs { self_r: Some(ty::re_bound(ty::br_self)), self_ty: None, diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 69e267744351d..4f51e32f7732a 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -39,7 +39,7 @@ pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block { }; for vec::each(b.node.stmts) |s| { debuginfo::update_source_pos(bcx, b.span); - bcx = trans_stmt(bcx, **s); + bcx = trans_stmt(bcx, *s); } match b.node.expr { Some(e) => { diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 477065377a527..ac0cf7064538c 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -159,7 +159,7 @@ pub impl DatumMode { } impl to_bytes::IterBytes for DatumMode { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f) } } @@ -811,7 +811,7 @@ pub impl Datum { } pub impl DatumBlock { - fn unpack(&self, +bcx: &mut block) -> Datum { + fn unpack(&self, bcx: &mut block) -> Datum { *bcx = self.bcx; return self.datum; } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 4f6057bc12508..fdd978fea3d7d 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -104,7 +104,7 @@ pub struct DebugContext { crate_file: ~str } -pub fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> DebugContext { +pub fn mk_ctxt(crate: ~str, intr: @ident_interner) -> DebugContext { DebugContext { llmetadata: @mut HashMap::new(), names: new_namegen(intr), @@ -249,7 +249,7 @@ fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { }, work_dir.to_owned()) } -fn create_file(cx: @CrateContext, +full_path: ~str) +fn create_file(cx: @CrateContext, full_path: ~str) -> @Metadata { let cache = get_cache(cx);; let tg = FileDescriptorTag; @@ -589,7 +589,7 @@ fn create_boxed_type(cx: @CrateContext, contents: ty::t, fn create_composite_type(type_tag: int, name: &str, file: ValueRef, line: int, size: int, align: int, offset: int, derived: Option, - +members: Option<~[ValueRef]>) + members: Option<~[ValueRef]>) -> ValueRef { let lldata = ~[lltag(type_tag), file, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 21d62f95cc51c..ba6965f0eaea3 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1572,7 +1572,7 @@ fn trans_binary(bcx: block, fn trans_overloaded_op(bcx: block, expr: @ast::expr, rcvr: @ast::expr, - +args: ~[@ast::expr], + args: ~[@ast::expr], ret_ty: ty::t, dest: Dest) -> block { @@ -1746,6 +1746,6 @@ fn trans_assign_op(bcx: block, return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum); } -fn shorten(+x: ~str) -> ~str { +fn shorten(x: ~str) -> ~str { if x.len() > 60 { x.substr(0, 60).to_owned() } else { x } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 86ce556be7235..854ec585d5cc2 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -39,7 +39,7 @@ use syntax::{ast, ast_util}; use syntax::{attr, ast_map}; use syntax::opt_vec; use syntax::parse::token::special_idents; -use syntax::abi::{Architecture, X86, X86_64, Arm, Mips}; +use syntax::abi::{X86, X86_64, Arm, Mips}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, Cdecl, Aapcs, C}; @@ -139,7 +139,7 @@ type shim_ret_builder<'self> = llretval: ValueRef); fn build_shim_fn_(ccx: @CrateContext, - +shim_name: ~str, + shim_name: ~str, llbasefn: ValueRef, tys: &ShimTypes, cc: lib::llvm::CallConv, @@ -544,7 +544,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, pub fn trans_intrinsic(ccx: @CrateContext, decl: ValueRef, item: @ast::foreign_item, - +path: ast_map::path, + path: ast_map::path, substs: @param_substs, ref_id: Option) { debug!("trans_intrinsic(item.ident=%s)", *ccx.sess.str_of(item.ident)); @@ -1089,7 +1089,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, * } */ pub fn trans_foreign_fn(ccx: @CrateContext, - +path: ast_map::path, + path: ast_map::path, decl: &ast::fn_decl, body: &ast::blk, llwrapfn: ValueRef, @@ -1097,7 +1097,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); fn build_rust_fn(ccx: @CrateContext, - +path: ast_map::path, + path: ast_map::path, decl: &ast::fn_decl, body: &ast::blk, id: ast::node_id) @@ -1125,7 +1125,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext, } fn build_shim_fn(ccx: @CrateContext, - +path: ast_map::path, + path: ast_map::path, llrustfn: ValueRef, tys: &ShimTypes) -> ValueRef { @@ -1266,7 +1266,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext, pub fn register_foreign_fn(ccx: @CrateContext, sp: span, - +path: ast_map::path, + path: ast_map::path, node_id: ast::node_id, attrs: &[ast::attribute]) -> ValueRef { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 2072c47124573..9031871de560d 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -321,7 +321,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, } // See [Note-arg-mode] -pub fn call_tydesc_glue_full(++bcx: block, +pub fn call_tydesc_glue_full(bcx: block, v: ValueRef, tydesc: ValueRef, field: uint, @@ -388,7 +388,7 @@ pub fn call_tydesc_glue_full(++bcx: block, } // See [Note-arg-mode] -pub fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint) +pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint) -> block { let _icx = cx.insn_ctxt("call_tydesc_glue"); let ti = get_tydesc(cx.ccx(), t); @@ -713,7 +713,7 @@ pub fn declare_tydesc(ccx: @CrateContext, t: ty::t) -> @mut tydesc_info { pub type glue_helper = @fn(block, ValueRef, ty::t); pub fn declare_generic_glue(ccx: @CrateContext, t: ty::t, llfnty: TypeRef, - +name: ~str) -> ValueRef { + name: ~str) -> ValueRef { let _icx = ccx.insn_ctxt("declare_generic_glue"); let name = name; //XXX this triggers duplicate LLVM symbols diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 3f2fb95513a39..6e8a782fd421f 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -54,7 +54,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); ccx.stats.n_inlines += 1; - if translate { trans_item(ccx, *item); } + if translate { trans_item(ccx, item); } local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { @@ -76,7 +76,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, _ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \ non-enum parent") } - if translate { trans_item(ccx, *item); } + if translate { trans_item(ccx, item); } local_def(my_id) } csearch::found_parent(_, _) => { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index d3a15cbbfe150..acb6353aa8b39 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -42,7 +42,7 @@ for non-monomorphized methods only. Other methods will be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ -pub fn trans_impl(ccx: @CrateContext, +path: path, name: ast::ident, +pub fn trans_impl(ccx: @CrateContext, path: path, name: ast::ident, methods: &[@ast::method], generics: &ast::Generics, self_ty: Option, id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); @@ -89,7 +89,7 @@ Translates a (possibly monomorphized) method body. - `impl_id`: the node ID of the impl this method is inside */ pub fn trans_method(ccx: @CrateContext, - +path: path, + path: path, method: &ast::method, param_substs: Option<@param_substs>, base_self_ty: Option, @@ -443,7 +443,7 @@ pub fn trans_monomorphized_callee(bcx: block, mentry: typeck::method_map_entry, trait_id: ast::def_id, n_method: uint, - +vtbl: typeck::vtable_origin) + vtbl: typeck::vtable_origin) -> Callee { let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee"); return match vtbl { @@ -724,7 +724,7 @@ pub fn trans_trait_callee_from_llval(bcx: block, } pub fn vtable_id(ccx: @CrateContext, - +origin: typeck::vtable_origin) + origin: typeck::vtable_origin) -> mono_id { match origin { typeck::vtable_static(impl_id, substs, sub_vtables) => { @@ -747,7 +747,7 @@ pub fn vtable_id(ccx: @CrateContext, } pub fn get_vtable(ccx: @CrateContext, - +origin: typeck::vtable_origin) + origin: typeck::vtable_origin) -> ValueRef { // XXX: Bad copy. let hash_id = vtable_id(ccx, copy origin); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index a6930b339ae72..9d63ac854a90c 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -221,9 +221,9 @@ pub fn monomorphic_fn(ccx: @CrateContext, let this_tv = vec::find(*tvs, |tv| { tv.id.node == fn_id.node}).get(); let d = mk_lldecl(); set_inline_hint(d); - match (*v).node.kind { + match v.node.kind { ast::tuple_variant_kind(ref args) => { - trans_enum_variant(ccx, enum_item.id, *v, /*bad*/copy *args, + trans_enum_variant(ccx, enum_item.id, v, /*bad*/copy *args, this_tv.disr_val, psubsts, d); } ast::struct_variant_kind(_) => diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 9f9323bf9f788..d7ca346dd20ee 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -49,13 +49,13 @@ pub fn find_reachable(crate_mod: &_mod, exp_map2: resolve::ExportMap2, method_map: method_map, rmap: &mut rmap }; - traverse_public_mod(cx, ast::crate_node_id, crate_mod); - traverse_all_resources_and_impls(cx, crate_mod); + traverse_public_mod(&cx, ast::crate_node_id, crate_mod); + traverse_all_resources_and_impls(&cx, crate_mod); } return @rmap; } -fn traverse_exports(cx: ctx, mod_id: node_id) -> bool { +fn traverse_exports(cx: &ctx, mod_id: node_id) -> bool { let mut found_export = false; match cx.exp_map2.find(&mod_id) { Some(ref exp2s) => { @@ -69,7 +69,7 @@ fn traverse_exports(cx: ctx, mod_id: node_id) -> bool { return found_export; } -fn traverse_def_id(cx: ctx, did: def_id) { +fn traverse_def_id(cx: &ctx, did: def_id) { if did.crate != local_crate { return; } match cx.tcx.items.find(&did.node) { None => (), // This can happen for self, for example @@ -85,7 +85,7 @@ fn traverse_def_id(cx: ctx, did: def_id) { } } -fn traverse_public_mod(cx: ctx, mod_id: node_id, m: &_mod) { +fn traverse_public_mod(cx: &ctx, mod_id: node_id, m: &_mod) { if !traverse_exports(cx, mod_id) { // No exports, so every local item is exported for m.items.each |item| { @@ -94,7 +94,7 @@ fn traverse_public_mod(cx: ctx, mod_id: node_id, m: &_mod) { } } -fn traverse_public_item(cx: ctx, item: @item) { +fn traverse_public_item(cx: &ctx, item: @item) { // XXX: it shouldn't be necessary to do this let rmap: &mut HashSet = cx.rmap; if rmap.contains(&item.id) { return; } @@ -139,7 +139,9 @@ fn traverse_public_item(cx: ctx, item: @item) { } } item_ty(t, _) => { - traverse_ty(t, cx, mk_ty_visitor()); + traverse_ty(t, cx, + visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, + ..*visit::default_visitor()})) } item_const(*) | item_enum(*) | item_trait(*) => (), @@ -147,12 +149,7 @@ fn traverse_public_item(cx: ctx, item: @item) { } } -fn mk_ty_visitor() -> visit::vt { - visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, - ..*visit::default_visitor()}) -} - -fn traverse_ty<'a>(ty: @Ty, cx: ctx<'a>, v: visit::vt>) { +fn traverse_ty<'a, 'b>(ty: @Ty, cx: &'b ctx<'a>, v: visit::vt<&'b ctx<'a>>) { // XXX: it shouldn't be necessary to do this let rmap: &mut HashSet = cx.rmap; if rmap.contains(&ty.id) { return; } @@ -175,8 +172,9 @@ fn traverse_ty<'a>(ty: @Ty, cx: ctx<'a>, v: visit::vt>) { } } -fn traverse_inline_body(cx: ctx, body: &blk) { - fn traverse_expr<'a>(e: @expr, cx: ctx<'a>, v: visit::vt>) { +fn traverse_inline_body(cx: &ctx, body: &blk) { + fn traverse_expr<'a, 'b>(e: @expr, cx: &'b ctx<'a>, + v: visit::vt<&'b ctx<'a>>) { match e.node { expr_path(_) => { match cx.tcx.def_map.find(&e.id) { @@ -221,7 +219,7 @@ fn traverse_inline_body(cx: ctx, body: &blk) { // Don't ignore nested items: for example if a generic fn contains a // generic impl (as in deque::create), we need to monomorphize the // impl as well - fn traverse_item(i: @item, cx: ctx, _v: visit::vt) { + fn traverse_item(i: @item, cx: &ctx, _v: visit::vt<&ctx>) { traverse_public_item(cx, i); } visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor { @@ -231,7 +229,7 @@ fn traverse_inline_body(cx: ctx, body: &blk) { })); } -fn traverse_all_resources_and_impls(cx: ctx, crate_mod: &_mod) { +fn traverse_all_resources_and_impls(cx: &ctx, crate_mod: &_mod) { visit::visit_mod( crate_mod, codemap::dummy_sp(), diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 30c14ab679f31..ffb2cc01ab249 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -121,7 +121,7 @@ pub impl Reflector { fn bracketed(&mut self, bracket_name: ~str, - +extra: ~[ValueRef], + extra: ~[ValueRef], inner: &fn(&mut Reflector)) { // XXX: Bad copy. self.visit(~"enter_" + bracket_name, copy extra); @@ -145,7 +145,7 @@ pub impl Reflector { } } - fn leaf(&mut self, +name: ~str) { + fn leaf(&mut self, name: ~str) { self.visit(name, ~[]); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ff41f6f5ae125..32ea381c020a3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -126,7 +126,7 @@ pub struct creader_cache_key { type creader_cache = @mut HashMap; impl to_bytes::IterBytes for creader_cache_key { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f); } } @@ -150,7 +150,7 @@ impl cmp::Eq for intern_key { } impl to_bytes::IterBytes for intern_key { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { unsafe { (*self.sty).iter_bytes(lsb0, f); } @@ -390,13 +390,13 @@ pub struct FnSig { } impl to_bytes::IterBytes for BareFnTy { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f) } } impl to_bytes::IterBytes for ClosureTy { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness, &self.region, &self.sig, lsb0, f) } @@ -685,7 +685,7 @@ pub enum InferTy { } impl to_bytes::IterBytes for InferTy { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f), IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f), @@ -702,7 +702,7 @@ pub enum InferRegion { } impl to_bytes::IterBytes for InferRegion { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f), ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f) @@ -790,25 +790,25 @@ impl ToStr for IntVarValue { } impl to_bytes::IterBytes for TyVid { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.to_uint().iter_bytes(lsb0, f) } } impl to_bytes::IterBytes for IntVid { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.to_uint().iter_bytes(lsb0, f) } } impl to_bytes::IterBytes for FloatVid { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.to_uint().iter_bytes(lsb0, f) } } impl to_bytes::IterBytes for RegionVid { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { self.to_uint().iter_bytes(lsb0, f) } } @@ -877,7 +877,7 @@ pub fn mk_ctxt(s: session::Session, freevars: freevars::freevar_map, region_maps: @mut middle::region::RegionMaps, region_paramd_items: middle::region::region_paramd_items, - +lang_items: middle::lang_items::LanguageItems, + lang_items: middle::lang_items::LanguageItems, crate: @ast::crate) -> ctxt { let mut legacy_modes = false; @@ -942,7 +942,7 @@ pub fn mk_ctxt(s: session::Session, // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for t above). -fn mk_t(cx: ctxt, +st: sty) -> t { +fn mk_t(cx: ctxt, st: sty) -> t { // Check for primitive types. match st { ty_nil => return mk_nil(cx), @@ -1141,7 +1141,7 @@ pub fn mk_estr(cx: ctxt, t: vstore) -> t { mk_t(cx, ty_estr(t)) } -pub fn mk_enum(cx: ctxt, did: ast::def_id, +substs: substs) -> t { +pub fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t { // take a copy of substs so that we own the vectors inside mk_t(cx, ty_enum(did, substs)) } @@ -1192,13 +1192,13 @@ pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t { mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm})) } -pub fn mk_tup(cx: ctxt, +ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) } +pub fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) } -pub fn mk_closure(cx: ctxt, +fty: ClosureTy) -> t { +pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t { mk_t(cx, ty_closure(fty)) } -pub fn mk_bare_fn(cx: ctxt, +fty: BareFnTy) -> t { +pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t { mk_t(cx, ty_bare_fn(fty)) } @@ -1217,7 +1217,7 @@ pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t { pub fn mk_trait(cx: ctxt, did: ast::def_id, - +substs: substs, + substs: substs, store: TraitStore, mutability: ast::mutability) -> t { @@ -1225,7 +1225,7 @@ pub fn mk_trait(cx: ctxt, mk_t(cx, ty_trait(did, substs, store, mutability)) } -pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, +substs: substs) -> t { +pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, substs: substs) -> t { // take a copy of substs so that we own the vectors inside mk_t(cx, ty_struct(struct_id, substs)) } @@ -1236,7 +1236,7 @@ pub fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) } pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) } -pub fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) } +pub fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) } pub fn mk_self(cx: ctxt, did: ast::def_id) -> t { mk_t(cx, ty_self(did)) } @@ -2672,7 +2672,7 @@ impl cmp::TotalEq for bound_region { } impl to_bytes::IterBytes for vstore { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { vstore_fixed(ref u) => to_bytes::iter_bytes_2(&0u8, u, lsb0, f), @@ -2687,7 +2687,7 @@ impl to_bytes::IterBytes for vstore { } impl to_bytes::IterBytes for substs { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_3(&self.self_r, &self.self_ty, &self.tps, lsb0, f) @@ -2695,28 +2695,28 @@ impl to_bytes::IterBytes for substs { } impl to_bytes::IterBytes for mt { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.ty, &self.mutbl, lsb0, f) } } impl to_bytes::IterBytes for field { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.ident, &self.mt, lsb0, f) } } impl to_bytes::IterBytes for arg { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.mode, &self.ty, lsb0, f) } } impl to_bytes::IterBytes for FnSig { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.inputs, &self.output, lsb0, f); @@ -2724,7 +2724,7 @@ impl to_bytes::IterBytes for FnSig { } impl to_bytes::IterBytes for sty { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { ty_nil => 0u8.iter_bytes(lsb0, f), ty_bool => 1u8.iter_bytes(lsb0, f), @@ -3383,7 +3383,7 @@ pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { // Maintains a little union-set tree for inferred modes. `canon()` returns // the current head value for `m0`. fn canon(tbl: &mut HashMap>, - +m0: ast::inferable) -> ast::inferable { + m0: ast::inferable) -> ast::inferable { match m0 { ast::infer(id) => { let m1 = match tbl.find(&id) { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 9f6ab8704cbd6..10acea1291f92 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -248,7 +248,7 @@ pub static NO_TPS: uint = 2; // internal notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: pub fn ast_ty_to_ty( - self: &AC, rscope: &RS, &&ast_ty: @ast::Ty) -> ty::t { + self: &AC, rscope: &RS, ast_ty: @ast::Ty) -> ty::t { fn ast_mt_to_mt( self: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt { diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index e0c3e71a5a1ad..c58ad0bfa3b34 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -44,7 +44,7 @@ pub fn check_match(fcx: @mut FnCtxt, block_region: ty::re_scope(arm.body.node.id) }; - for arm.pats.each |p| { check_pat(pcx, *p, pattern_ty);} + for arm.pats.each |p| { check_pat(&pcx, *p, pattern_ty);} } // Now typecheck the blocks. @@ -99,7 +99,7 @@ pub struct pat_ctxt { block_region: ty::Region, // Region for the block of the arm } -pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::Path, +pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, subpats: &Option<~[@ast::pat]>, expected: ty::t) { // Typecheck the path. @@ -247,7 +247,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::Path, /// `substitutions` are the type substitutions applied to this struct type /// (e.g. K,V in HashMap). /// `etc` is true if the pattern said '...' and false otherwise. -pub fn check_struct_pat_fields(pcx: pat_ctxt, +pub fn check_struct_pat_fields(pcx: &pat_ctxt, span: span, path: @ast::Path, fields: &[ast::field_pat], @@ -299,7 +299,7 @@ pub fn check_struct_pat_fields(pcx: pat_ctxt, } } -pub fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span, +pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::node_id, span: span, expected: ty::t, path: @ast::Path, fields: &[ast::field_pat], etc: bool, class_id: ast::def_id, substitutions: &ty::substs) { @@ -337,7 +337,7 @@ pub fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span, substitutions, etc); } -pub fn check_struct_like_enum_variant_pat(pcx: pat_ctxt, +pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt, pat_id: ast::node_id, span: span, expected: ty::t, @@ -375,7 +375,7 @@ pub fn check_struct_like_enum_variant_pat(pcx: pat_ctxt, // Pattern checking is top-down rather than bottom-up so that bindings get // their types immediately. -pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { +pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 131cef1c7f2f0..9d8a1145f22eb 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1298,7 +1298,7 @@ pub impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did) } - fn bug(&self, +s: ~str) -> ! { + fn bug(&self, s: ~str) -> ! { self.tcx().sess.bug(s) } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5ec4c233bc0d2..d6f892cac3c31 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -257,7 +257,7 @@ pub fn check_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) { visit_item: |a| check_item(ccx, a), .. *visit::default_simple_visitor() }); - visit::visit_crate(*crate, (), visit); + visit::visit_crate(crate, (), visit); } pub fn check_bare_fn(ccx: @mut CrateCtxt, @@ -430,11 +430,11 @@ pub fn check_fn(ccx: @mut CrateCtxt, match_region: region, block_region: region, }; - _match::check_pat(pcx, input.pat, *arg_ty); + _match::check_pat(&pcx, input.pat, *arg_ty); } // Add explicitly-declared locals. - let visit_local: @fn(@ast::local, &&e: (), visit::vt<()>) = + let visit_local: @fn(@ast::local, e: (), visit::vt<()>) = |local, e, v| { let o_ty = match local.node.ty.node { ast::ty_infer => None, @@ -449,7 +449,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, }; // Add pattern bindings. - let visit_pat: @fn(@ast::pat, &&e: (), visit::vt<()>) = |p, e, v| { + let visit_pat: @fn(@ast::pat, e: (), visit::vt<()>) = |p, e, v| { match p.node { ast::pat_ident(_, path, _) if pat_util::pat_is_binding(fcx.ccx.tcx.def_map, p) => { @@ -464,7 +464,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, visit::visit_pat(p, e, v); }; - let visit_block: @fn(&ast::blk, &&e: (), visit::vt<()>) = |b, e, v| { + let visit_block: @fn(&ast::blk, e: (), visit::vt<()>) = |b, e, v| { // non-obvious: the `blk` variable maps to region lb, so // we have to keep this up-to-date. This // is... unfortunate. It'd be nice to not need this. @@ -476,9 +476,9 @@ pub fn check_fn(ccx: @mut CrateCtxt, // Don't descend into fns and items fn visit_fn(_fk: &visit::fn_kind, _decl: &ast::fn_decl, _body: &ast::blk, _sp: span, - _id: ast::node_id, &&_t: (), _v: visit::vt<()>) { + _id: ast::node_id, _t: (), _v: visit::vt<()>) { } - fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { } + fn visit_item(_i: @ast::item, _e: (), _v: visit::vt<()>) { } let visit = visit::mk_vt( @visit::Visitor {visit_local: visit_local, @@ -714,7 +714,7 @@ pub impl FnCtxt { self.inh.node_types.insert(node_id, ty); } - fn write_substs(&self, node_id: ast::node_id, +substs: ty::substs) { + fn write_substs(&self, node_id: ast::node_id, substs: ty::substs) { if !ty::substs_is_noop(&substs) { debug!("write_substs(%d, %s) in fcx %s", node_id, @@ -727,7 +727,7 @@ pub impl FnCtxt { fn write_ty_substs(&self, node_id: ast::node_id, ty: ty::t, - +substs: ty::substs) { + substs: ty::substs) { let ty = ty::subst(self.tcx(), &substs, ty); self.write_ty(node_id, ty); self.write_substs(node_id, substs); @@ -1429,9 +1429,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, self_ex: @ast::expr, self_t: ty::t, opname: ast::ident, - +args: ~[@ast::expr], - +deref_args: DerefArgs, - +autoderef_receiver: AutoderefReceiverFlag, + args: ~[@ast::expr], + deref_args: DerefArgs, + autoderef_receiver: AutoderefReceiverFlag, unbound_method: &fn(), _expected_result: Option ) @@ -1570,7 +1570,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fn check_user_unop(fcx: @mut FnCtxt, op_str: ~str, - +mname: ~str, + mname: ~str, ex: @ast::expr, rhs_expr: @ast::expr, rhs_t: ty::t, @@ -1775,7 +1775,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, span: span, class_id: ast::def_id, node_id: ast::node_id, - +substitutions: ty::substs, + substitutions: ty::substs, field_types: &[ty::field_ty], ast_fields: &[ast::field], check_completeness: bool) { @@ -2859,7 +2859,7 @@ pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::local) { match_region: region, block_region: region, }; - _match::check_pat(pcx, local.node.pat, t); + _match::check_pat(&pcx, local.node.pat, t); let pat_ty = fcx.node_ty(local.node.pat.id); if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) { fcx.write_ty(local.node.id, pat_ty); @@ -2947,7 +2947,7 @@ pub fn check_block_with_expected(fcx0: @mut FnCtxt, let mut any_err = false; for blk.node.stmts.each |s| { check_stmt(fcx, *s); - let s_ty = fcx.node_ty(ast_util::stmt_id(**s)); + let s_ty = fcx.node_ty(ast_util::stmt_id(*s)); if last_was_bot && !warned && match s.node { ast::stmt_decl(@codemap::spanned { node: ast::decl_local(_), _}, _) | @@ -3350,7 +3350,7 @@ pub fn may_break(cx: ty::ctxt, id: ast::node_id, b: &ast::blk) -> bool { // First: is there an unlabeled break immediately // inside the loop? (loop_query(b, |e| { - match e { + match *e { ast::expr_break(_) => true, _ => false } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 56a8aaecae281..aec7399d5eb97 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -159,11 +159,11 @@ fn regionck_visitor() -> rvt { .. *visit::default_visitor()}) } -fn visit_item(_item: @ast::item, &&_rcx: @mut Rcx, _v: rvt) { +fn visit_item(_item: @ast::item, _rcx: @mut Rcx, _v: rvt) { // Ignore items } -fn visit_local(l: @ast::local, &&rcx: @mut Rcx, v: rvt) { +fn visit_local(l: @ast::local, rcx: @mut Rcx, v: rvt) { // Check to make sure that the regions in all local variables are // within scope. // @@ -194,11 +194,11 @@ fn visit_local(l: @ast::local, &&rcx: @mut Rcx, v: rvt) { } } -fn visit_block(b: &ast::blk, &&rcx: @mut Rcx, v: rvt) { +fn visit_block(b: &ast::blk, rcx: @mut Rcx, v: rvt) { visit::visit_block(b, rcx, v); } -fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { +fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) { debug!("regionck::visit_expr(e=%s)", rcx.fcx.expr_to_str(expr)); for rcx.fcx.inh.adjustments.find(&expr.id).each |&adjustment| { @@ -333,7 +333,7 @@ fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) { visit::visit_expr(expr, rcx, v); } -fn visit_stmt(s: @ast::stmt, &&rcx: @mut Rcx, v: rvt) { +fn visit_stmt(s: @ast::stmt, rcx: @mut Rcx, v: rvt) { visit::visit_stmt(s, rcx, v); } @@ -973,10 +973,10 @@ pub mod guarantor { } fn apply_autoderefs( - +rcx: @mut Rcx, - +expr: @ast::expr, - +autoderefs: uint, - +ct: ExprCategorizationType) + rcx: @mut Rcx, + expr: @ast::expr, + autoderefs: uint, + ct: ExprCategorizationType) -> ExprCategorizationType { let mut ct = ct; let tcx = rcx.fcx.ccx.tcx; diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index cc7519c1db4ed..39715f295ade9 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -135,7 +135,7 @@ fn lookup_vtables(vcx: &VtableContext, } fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, - id: ast::def_id, +substs: ty::substs, + id: ast::def_id, substs: ty::substs, is_early: bool) -> Option { let tcx = vcx.tcx(); // use a dummy type just to package up the substs that need fixing up @@ -480,7 +480,7 @@ pub fn location_info_for_expr(expr: @ast::expr) -> LocationInfo { } pub fn early_resolve_expr(ex: @ast::expr, - &&fcx: @mut FnCtxt, + fcx: @mut FnCtxt, is_early: bool) { debug!("vtable: early_resolve_expr() ex with id %? (early: %b): %s", ex.id, is_early, expr_to_str(ex, fcx.tcx().sess.intr())); @@ -656,7 +656,7 @@ pub fn early_resolve_expr(ex: @ast::expr, } fn resolve_expr(ex: @ast::expr, - &&fcx: @mut FnCtxt, + fcx: @mut FnCtxt, v: visit::vt<@mut FnCtxt>) { early_resolve_expr(ex, fcx, false); visit::visit_expr(ex, fcx, v); diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 3af4cb7f10cb4..0dba55b4e72cf 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -212,12 +212,12 @@ struct WbCtxt { type wb_vt = visit::vt<@mut WbCtxt>; -fn visit_stmt(s: @ast::stmt, &&wbcx: @mut WbCtxt, v: wb_vt) { +fn visit_stmt(s: @ast::stmt, wbcx: @mut WbCtxt, v: wb_vt) { if !wbcx.success { return; } resolve_type_vars_for_node(wbcx, s.span, ty::stmt_node_id(s)); visit::visit_stmt(s, wbcx, v); } -fn visit_expr(e: @ast::expr, &&wbcx: @mut WbCtxt, v: wb_vt) { +fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) { if !wbcx.success { return; } resolve_type_vars_for_node(wbcx, e.span, e.id); resolve_method_map_entry(wbcx.fcx, e.span, e.id); @@ -256,12 +256,12 @@ fn visit_expr(e: @ast::expr, &&wbcx: @mut WbCtxt, v: wb_vt) { } visit::visit_expr(e, wbcx, v); } -fn visit_block(b: &ast::blk, &&wbcx: @mut WbCtxt, v: wb_vt) { +fn visit_block(b: &ast::blk, wbcx: @mut WbCtxt, v: wb_vt) { if !wbcx.success { return; } resolve_type_vars_for_node(wbcx, b.span, b.node.id); visit::visit_block(b, wbcx, v); } -fn visit_pat(p: @ast::pat, &&wbcx: @mut WbCtxt, v: wb_vt) { +fn visit_pat(p: @ast::pat, wbcx: @mut WbCtxt, v: wb_vt) { if !wbcx.success { return; } resolve_type_vars_for_node(wbcx, p.span, p.id); debug!("Type for pattern binding %s (id %d) resolved to %s", @@ -271,7 +271,7 @@ fn visit_pat(p: @ast::pat, &&wbcx: @mut WbCtxt, v: wb_vt) { p.id))); visit::visit_pat(p, wbcx, v); } -fn visit_local(l: @ast::local, &&wbcx: @mut WbCtxt, v: wb_vt) { +fn visit_local(l: @ast::local, wbcx: @mut WbCtxt, v: wb_vt) { if !wbcx.success { return; } let var_ty = wbcx.fcx.local_ty(l.span, l.node.id); match resolve_type(wbcx.fcx.infcx(), var_ty, resolve_all | force_all) { @@ -293,7 +293,7 @@ fn visit_local(l: @ast::local, &&wbcx: @mut WbCtxt, v: wb_vt) { } visit::visit_local(l, wbcx, v); } -fn visit_item(_item: @ast::item, &&_wbcx: @mut WbCtxt, _v: wb_vt) { +fn visit_item(_item: @ast::item, _wbcx: @mut WbCtxt, _v: wb_vt) { // Ignore items } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 2afe674db9c55..4225b5da418de 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -203,7 +203,7 @@ pub impl CoherenceChecker { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. - visit_crate(*crate, (), mk_simple_visitor(@SimpleVisitor { + visit_crate(crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { // debug!("(checking coherence) item '%s'", // self.crate_context.tcx.sess.str_of(item.ident)); @@ -655,7 +655,7 @@ pub impl CoherenceChecker { // Privileged scope checking fn check_privileged_scopes(self, crate: @crate) { - visit_crate(*crate, (), mk_vt(@Visitor { + visit_crate(crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| { match item.node { item_mod(ref module_) => { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 36b4626731626..8356b06e8a6c9 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -111,7 +111,7 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) { } visit::visit_crate( - *crate, (), + crate, (), visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |a| convert(ccx, a), visit_foreign_item: |a|convert_foreign(ccx, a), diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 0bdf2842ccac3..fdc96a21b8b5c 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -124,7 +124,7 @@ pub struct CombineFields { } pub fn expected_found( - self: &C, +a: T, +b: T) -> ty::expected_found { + self: &C, a: T, b: T) -> ty::expected_found { if self.a_is_expected() { ty::expected_found {expected: a, found: b} } else { diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 27d3b3ddd86a1..db229a407b39a 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -77,8 +77,8 @@ pub impl CombineFields { fn var_sub_var>>( &self, - +a_id: V, - +b_id: V) -> ures + a_id: V, + b_id: V) -> ures { /*! * @@ -130,8 +130,8 @@ pub impl CombineFields { fn var_sub_t>>( &self, - +a_id: V, - +b: T) -> ures + a_id: V, + b: T) -> ures { /*! * @@ -154,8 +154,8 @@ pub impl CombineFields { fn t_sub_var>>( &self, - +a: T, - +b_id: V) -> ures + a: T, + b_id: V) -> ures { /*! * @@ -206,7 +206,7 @@ pub impl CombineFields { fn set_var_to_merged_bounds>>( &self, - +v_id: V, + v_id: V, a: &Bounds, b: &Bounds, rank: uint) -> ures @@ -296,7 +296,7 @@ pub impl CombineFields { pub trait LatticeDir { fn combine_fields(&self) -> CombineFields; fn bnd(&self, b: &Bounds) -> Option; - fn with_bnd(&self, b: &Bounds, +t: T) -> Bounds; + fn with_bnd(&self, b: &Bounds, t: T) -> Bounds; } pub trait TyLatticeDir { @@ -306,7 +306,7 @@ pub trait TyLatticeDir { impl LatticeDir for Lub { fn combine_fields(&self) -> CombineFields { **self } fn bnd(&self, b: &Bounds) -> Option { b.ub } - fn with_bnd(&self, b: &Bounds, +t: T) -> Bounds { + fn with_bnd(&self, b: &Bounds, t: T) -> Bounds { Bounds { ub: Some(t), ..*b } } } @@ -320,7 +320,7 @@ impl TyLatticeDir for Lub { impl LatticeDir for Glb { fn combine_fields(&self) -> CombineFields { **self } fn bnd(&self, b: &Bounds) -> Option { b.lb } - fn with_bnd(&self, b: &Bounds, +t: T) -> Bounds { + fn with_bnd(&self, b: &Bounds, t: T) -> Bounds { Bounds { lb: Some(t), ..*b } } } @@ -401,8 +401,8 @@ pub fn lattice_vars>>( self: &L, // defines whether we want LUB or GLB - +a_vid: V, // first variable - +b_vid: V, // second variable + a_vid: V, // first variable + b_vid: V, // second variable lattice_dir_op: LatticeDirOp) // LUB or GLB operation on types -> cres> { let nde_a = self.infcx().get(a_vid); @@ -447,7 +447,7 @@ pub fn lattice_var_and_t>>( self: &L, - +a_id: V, + a_id: V, b: &T, lattice_dir_op: LatticeDirOp) -> cres { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 3cefe7646def2..a4a48cf5b788a 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -643,8 +643,8 @@ pub impl InferCtxt { } fn next_simple_var( - +counter: &mut uint, - +bindings: &mut ValsAndBindings>) + counter: &mut uint, + bindings: &mut ValsAndBindings>) -> uint { let id = *counter; *counter += 1; diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index 7252566d84c17..f34a990977ebe 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -563,7 +563,7 @@ enum Constraint { } impl to_bytes::IterBytes for Constraint { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { match *self { ConstrainVarSubVar(ref v0, ref v1) => to_bytes::iter_bytes_3(&0u8, v0, v1, lsb0, f), @@ -584,7 +584,7 @@ struct TwoRegions { } impl to_bytes::IterBytes for TwoRegions { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.a, &self.b, lsb0, f) } } @@ -729,7 +729,7 @@ pub impl RegionVarBindings { re_bound(br_fresh(sc)) } - fn add_constraint(&mut self, +constraint: Constraint, span: span) { + fn add_constraint(&mut self, constraint: Constraint, span: span) { // cannot add constraints once regions are resolved assert!(self.values.is_empty()); @@ -995,7 +995,7 @@ pub impl RegionVarBindings { return result_set; - fn consider_adding_edge(+result_set: ~[Region], + fn consider_adding_edge(result_set: ~[Region], r: &Region, r1: &Region, r2: &Region) -> ~[Region] @@ -1030,7 +1030,7 @@ priv impl RegionVarBindings { rm.is_subregion_of(sub, sup) } - fn lub_concrete_regions(&self, +a: Region, +b: Region) -> Region { + fn lub_concrete_regions(&self, a: Region, b: Region) -> Region { match (a, b) { (re_static, _) | (_, re_static) => { re_static // nothing lives longer than static @@ -1122,8 +1122,8 @@ priv impl RegionVarBindings { } fn glb_concrete_regions(&self, - +a: Region, - +b: Region) + a: Region, + b: Region) -> cres { debug!("glb_concrete_regions(%?, %?)", a, b); match (a, b) { @@ -1330,7 +1330,7 @@ pub impl RegionVarBindings { return (graph); - fn insert_edge(+graph: &mut Graph, + fn insert_edge(graph: &mut Graph, node_id: RegionVid, edge_dir: Direction, edge_idx: uint) { @@ -1457,9 +1457,9 @@ pub impl RegionVarBindings { } }; - fn check_node(+self: &mut RegionVarBindings, + fn check_node(self: &mut RegionVarBindings, a_vid: RegionVid, - +a_node: &mut GraphNode, + a_node: &mut GraphNode, a_region: Region, b_region: Region) -> bool { @@ -1471,9 +1471,9 @@ pub impl RegionVarBindings { false } - fn adjust_node(+self: &mut RegionVarBindings, + fn adjust_node(self: &mut RegionVarBindings, a_vid: RegionVid, - +a_node: &mut GraphNode, + a_node: &mut GraphNode, a_region: Region, b_region: Region) -> bool { diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index 75dac7fd7c5df..220cc91dfdb4b 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -42,7 +42,7 @@ pub trait UnifyVid { pub impl InferCtxt { fn get>( &mut self, - +vid: V) -> Node + vid: V) -> Node { /*! * @@ -88,8 +88,8 @@ pub impl InferCtxt { fn set>( &mut self, - +vid: V, - +new_v: VarValue) { + vid: V, + new_v: VarValue) { /*! * * Sets the value for `vid` to `new_v`. `vid` MUST be a root node! @@ -147,9 +147,9 @@ pub trait SimplyUnifiable { fn to_type_err(expected_found) -> ty::type_err; } -pub fn mk_err(+a_is_expected: bool, - +a_t: T, - +b_t: T) -> ures { +pub fn mk_err(a_is_expected: bool, + a_t: T, + b_t: T) -> ures { if a_is_expected { Err(SimplyUnifiable::to_type_err( ty::expected_found {expected: a_t, found: b_t})) @@ -163,9 +163,9 @@ pub impl InferCtxt { fn simple_vars>>( &mut self, - +a_is_expected: bool, - +a_id: V, - +b_id: V) + a_is_expected: bool, + a_id: V, + b_id: V) -> ures { /*! * @@ -201,9 +201,9 @@ pub impl InferCtxt { fn simple_var_t>>( &mut self, - +a_is_expected: bool, - +a_id: V, - +b: T) + a_is_expected: bool, + a_id: V, + b: T) -> ures { /*! * diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 98117278f3826..f87c0dad5a993 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -194,7 +194,7 @@ pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t) { } pub fn write_substs_to_tcx(tcx: ty::ctxt, node_id: ast::node_id, - +substs: ~[ty::t]) { + substs: ~[ty::t]) { if substs.len() > 0u { debug!("write_substs_to_tcx(%d, %?)", node_id, substs.map(|t| ppaux::ty_to_str(tcx, *t))); @@ -397,7 +397,7 @@ fn check_for_entry_fn(ccx: @mut CrateCtxt) { } pub fn check_crate(tcx: ty::ctxt, - +trait_map: resolve::TraitMap, + trait_map: resolve::TraitMap, crate: @ast::crate) -> (method_map, vtable_map) { let time_passes = tcx.sess.time_passes(); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 3ff36a409a71f..62320a1d34d56 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -272,7 +272,7 @@ pub struct binding_rscope { pub fn in_binding_rscope( self: &RS, - +region_param_names: RegionParamNames) + region_param_names: RegionParamNames) -> binding_rscope { let base = @copy *self; let base = base as @region_scope; diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 845f0e2c522a4..573ba4ca41175 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -18,12 +18,10 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -#[legacy_modes]; - #[allow(non_implicitly_copyable_typarams)]; #[allow(non_camel_case_types)]; -#[allow(deprecated_mode)]; -#[warn(deprecated_pattern)]; +#[deny(deprecated_pattern)]; +#[deny(deprecated_mode)]; #[no_core]; @@ -259,12 +257,12 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { let odir = odir.map(|o| Path(*o)); let ofile = getopts::opt_maybe_str(matches, ~"o"); let ofile = ofile.map(|o| Path(*o)); - let cfg = build_configuration(sess, binary, input); + let cfg = build_configuration(sess, binary, &input); let pretty = getopts::opt_default(matches, ~"pretty", "normal").map( |a| parse_pretty(sess, *a)); match pretty { Some::(ppm) => { - pretty_print_input(sess, cfg, input, ppm); + pretty_print_input(sess, cfg, &input, ppm); return; } None:: => {/* continue */ } @@ -282,7 +280,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { return; } - compile_input(sess, cfg, input, &odir, &ofile); + compile_input(sess, cfg, &input, &odir, &ofile); } #[deriving(Eq)] @@ -303,7 +301,7 @@ diagnostic emitter which records when we hit a fatal error. If the task fails without recording a fatal error then we've encountered a compiler bug and need to present an error. */ -pub fn monitor(+f: ~fn(diagnostic::Emitter)) { +pub fn monitor(f: ~fn(diagnostic::Emitter)) { use core::comm::*; let (p, ch) = stream(); let ch = SharedChan::new(ch); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 30152c2284574..93deeecc10106 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -63,12 +63,12 @@ pub fn field_exprs(fields: ~[ast::field]) -> ~[@ast::expr] { // Takes a predicate p, returns true iff p is true for any subexpressions // of b -- skipping any inner loops (loop, while, loop_body) -pub fn loop_query(b: &ast::blk, p: @fn(ast::expr_) -> bool) -> bool { +pub fn loop_query(b: &ast::blk, p: @fn(&ast::expr_) -> bool) -> bool { let rs = @mut false; let visit_expr: @fn(@ast::expr, - &&flag: @mut bool, - v: visit::vt<@mut bool>) = |e, &&flag, v| { - *flag |= p(e.node); + flag: @mut bool, + v: visit::vt<@mut bool>) = |e, flag, v| { + *flag |= p(&e.node); match e.node { // Skip inner loops, since a break in the inner loop isn't a // break inside the outer loop @@ -89,8 +89,8 @@ pub fn loop_query(b: &ast::blk, p: @fn(ast::expr_) -> bool) -> bool { pub fn block_query(b: &ast::blk, p: @fn(@ast::expr) -> bool) -> bool { let rs = @mut false; let visit_expr: @fn(@ast::expr, - &&flag: @mut bool, - v: visit::vt<@mut bool>) = |e, &&flag, v| { + flag: @mut bool, + v: visit::vt<@mut bool>) = |e, flag, v| { *flag |= p(e); visit::visit_expr(e, flag, v) }; @@ -108,7 +108,7 @@ pub fn local_rhs_span(l: @ast::local, def: span) -> span { } } -pub fn pluralize(n: uint, +s: ~str) -> ~str { +pub fn pluralize(n: uint, s: ~str) -> ~str { if n == 1 { s } else { str::concat([s, ~"s"]) } } From c97bee26967bfb5a7dccbb1ae1572a6c4da38f15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 18 Apr 2013 17:56:41 -0400 Subject: [PATCH 317/403] Assorted fixes from de-modeing rustc/syntax (rusti, rustdoc, fuzzer, rustpkg) --- src/libfuzzer/fuzzer.rc | 22 +++++++++++----------- src/librustdoc/astsrv.rs | 2 +- src/librustdoc/parse.rs | 2 +- src/librusti/rusti.rc | 20 ++++++++++---------- src/librustpkg/rustpkg.rc | 8 ++++---- src/librustpkg/util.rs | 10 +++++----- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index 46c7d4da22e4e..917ab3e8801a1 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -160,7 +160,7 @@ pub fn stash_ty_if(c: @fn(@ast::Ty, test_mode)->bool, pub struct StolenStuff {exprs: ~[ast::expr], tys: ~[ast::Ty]} -pub fn steal(crate: ast::crate, tm: test_mode) -> StolenStuff { +pub fn steal(crate: @ast::crate, tm: test_mode) -> StolenStuff { let exprs = @mut ~[]; let tys = @mut ~[]; let v = visit::mk_simple_visitor(@visit::SimpleVisitor { @@ -197,7 +197,7 @@ pub fn safe_to_replace_ty(t: &ast::ty_, _tm: test_mode) -> bool { } // Replace the |i|th expr (in fold order) of |crate| with |newexpr|. -pub fn replace_expr_in_crate(crate: ast::crate, i: uint, +pub fn replace_expr_in_crate(crate: @ast::crate, i: uint, newexpr: ast::expr, tm: test_mode) -> ast::crate { let j: @mut uint = @mut 0u; @@ -222,13 +222,13 @@ pub fn replace_expr_in_crate(crate: ast::crate, i: uint, .. *fold::default_ast_fold() }; let af = fold::make_fold(afp); - let crate2: @ast::crate = @af.fold_crate(&crate); + let crate2: @ast::crate = @af.fold_crate(crate); *crate2 } // Replace the |i|th ty (in fold order) of |crate| with |newty|. -pub fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, +pub fn replace_ty_in_crate(crate: @ast::crate, i: uint, newty: ast::Ty, tm: test_mode) -> ast::crate { let j: @mut uint = @mut 0u; fn fold_ty_rep(j_: @mut uint, @@ -248,7 +248,7 @@ pub fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, .. *fold::default_ast_fold() }; let af = fold::make_fold(afp); - let crate2: @ast::crate = @af.fold_crate(&crate); + let crate2: @ast::crate = @af.fold_crate(crate); *crate2 } @@ -261,7 +261,7 @@ pub fn as_str(f: @fn(+x: @io::Writer)) -> ~str { io::with_str_writer(f) } -pub fn check_variants_of_ast(crate: ast::crate, codemap: @codemap::CodeMap, +pub fn check_variants_of_ast(crate: @ast::crate, codemap: @codemap::CodeMap, filename: &Path, cx: Context) { let stolen = steal(crate, cx.mode); let extra_exprs = do common_exprs().filtered |a| { @@ -275,13 +275,13 @@ pub fn check_variants_of_ast(crate: ast::crate, codemap: @codemap::CodeMap, } pub fn check_variants_T( - crate: ast::crate, + crate: @ast::crate, codemap: @codemap::CodeMap, filename: &Path, thing_label: ~str, things: ~[T], stringifier: @fn(@T, @syntax::parse::token::ident_interner) -> ~str, - replacer: @fn(ast::crate, uint, T, test_mode) -> ast::crate, + replacer: @fn(@ast::crate, uint, T, test_mode) -> ast::crate, cx: Context ) { error!("%s contains %u %s objects", filename.to_str(), @@ -323,7 +323,7 @@ pub fn check_variants_T( last_part(filename.to_str()), thing_label, i, j); let safe_to_run = !(content_is_dangerous_to_run(*str3) - || has_raw_pointers(*crate2)); + || has_raw_pointers(crate2)); check_whole_compiler(*str3, &Path(file_label), safe_to_run); } @@ -480,7 +480,7 @@ pub fn parse_and_print(code: @~str) -> ~str { } } -pub fn has_raw_pointers(c: ast::crate) -> bool { +pub fn has_raw_pointers(c: @ast::crate) -> bool { let has_rp = @mut false; fn visit_ty(flag: @mut bool, t: @ast::Ty) { match t.node { @@ -634,7 +634,7 @@ pub fn check_variants(files: &[Path], cx: Context) { pprust::no_ann(), false))) }); - check_variants_of_ast(*crate, sess.cm, file, cx); + check_variants_of_ast(crate, sess.cm, file, cx); } } diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index c4c81b5ec2c70..5e103d6848aa5 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -117,7 +117,7 @@ fn build_ctxt(sess: Session, let ast = syntax::ext::expand::expand_crate(sess.parse_sess, copy sess.opts.cfg, ast); let ast = front::test::modify_for_testing(sess, ast); - let ast_map = ast_map::map_crate(sess.diagnostic(), *ast); + let ast_map = ast_map::map_crate(sess.diagnostic(), ast); Ctxt { ast: ast, diff --git a/src/librustdoc/parse.rs b/src/librustdoc/parse.rs index 6c759e935b931..455720f47ef90 100644 --- a/src/librustdoc/parse.rs +++ b/src/librustdoc/parse.rs @@ -39,5 +39,5 @@ pub fn from_str_sess(sess: session::Session, source: ~str) -> @ast::crate { } fn cfg(sess: session::Session, input: driver::input) -> ast::crate_cfg { - driver::build_configuration(sess, @~"rustdoc", input) + driver::build_configuration(sess, @~"rustdoc", &input) } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index e14a6e0e7409e..53912e7c94712 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -93,7 +93,7 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl { for blk.node.stmts.each |stmt| { match stmt.node { ast::stmt_decl(*) | ast::stmt_mac(*) => { - pprust::print_stmt(pp, **stmt); + pprust::print_stmt(pp, *stmt); writer.write_line(~""); } ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => { @@ -101,7 +101,7 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl { ast::expr_assign(*) | ast::expr_assign_op(*) | ast::expr_swap(*) => { - pprust::print_stmt(pp, **stmt); + pprust::print_stmt(pp, *stmt); writer.write_line(~""); } _ => {} @@ -147,13 +147,13 @@ fn run(repl: Repl, input: ~str) -> Repl { debug!("building driver configuration"); let cfg = driver::build_configuration(sess, @repl.binary, - wrapped); + &wrapped); - let outputs = driver::build_output_filenames(wrapped, &None, &None, sess); + let outputs = driver::build_output_filenames(&wrapped, &None, &None, sess); debug!("calling compile_upto"); - let (crate, _) = driver::compile_upto(sess, cfg, wrapped, - driver::cu_everything, - Some(outputs)); + let (crate, _) = driver::compile_upto(sess, cfg, &wrapped, + driver::cu_everything, + Some(outputs)); let mut opt = None; @@ -198,9 +198,9 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { let input = driver::file_input(src_path); let sess = driver::build_session(options, diagnostic::emit); *sess.building_library = true; - let cfg = driver::build_configuration(sess, @binary, input); + let cfg = driver::build_configuration(sess, @binary, &input); let outputs = driver::build_output_filenames( - input, &None, &None, sess); + &input, &None, &None, sess); // If the library already exists and is newer than the source // file, skip compilation and return None. let mut should_compile = true; @@ -228,7 +228,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { } if (should_compile) { io::println(fmt!("compiling %s...", src_filename)); - driver::compile_upto(sess, cfg, input, driver::cu_everything, + driver::compile_upto(sess, cfg, &input, driver::cu_everything, Some(outputs)); true } else { false } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 76d145cb2b726..705bcc8242750 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -37,7 +37,7 @@ use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; use path_util::{dest_dir, normalize}; -use rustc::driver::session::{lib_crate, bin_crate, unknown_crate, crate_type}; +use rustc::driver::session::{lib_crate, bin_crate, crate_type}; mod conditions; mod usage; @@ -82,8 +82,8 @@ impl PkgScript { }; let input = driver::file_input(script); let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, @binary, input); - let (crate, _) = driver::compile_upto(sess, cfg, input, + let cfg = driver::build_configuration(sess, @binary, &input); + let (crate, _) = driver::compile_upto(sess, cfg, &input, driver::cu_parse, None); let work_dir = dest_dir(id); @@ -112,7 +112,7 @@ impl PkgScript { // Collect together any user-defined commands in the package script let crate = util::ready_crate(sess, self.crate); debug!("Building output filenames with script name %s", - driver::source_name(self.input)); + driver::source_name(&self.input)); match filesearch::get_rustpkg_sysroot() { Ok(r) => { let root = r.pop().pop().pop().pop(); // :-\ diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 7581329f1fc69..2ab1ea1e7d2ea 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -12,7 +12,7 @@ use core::*; use core::cmp::Ord; use core::hash::Streaming; use rustc::driver::{driver, session}; -use rustc::driver::session::{lib_crate, bin_crate, unknown_crate}; +use rustc::driver::session::{lib_crate, unknown_crate}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; use std::semver; @@ -25,7 +25,7 @@ use syntax::{ast, attr, codemap, diagnostic, fold}; use syntax::ast::{meta_name_value, meta_list, attribute, crate_}; use syntax::attr::{mk_attr}; use rustc::back::link::output_type_exe; -use rustc::driver::session::{lib_crate, bin_crate, unknown_crate, crate_type}; +use rustc::driver::session::{lib_crate, unknown_crate, crate_type}; pub type ExitCode = int; // For now @@ -516,9 +516,9 @@ pub fn compile_crate_from_input(input: driver::input, binary: ~str, what: driver::compile_upto) -> @ast::crate { debug!("Calling build_output_filenames with %?", build_dir_opt); - let outputs = driver::build_output_filenames(input, &build_dir_opt, &Some(out_file), sess); + let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess); debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); - let cfg = driver::build_configuration(sess, @binary, input); + let cfg = driver::build_configuration(sess, @binary, &input); match crate_opt { Some(c) => { debug!("Calling compile_rest, outputs = %?", outputs); @@ -528,7 +528,7 @@ pub fn compile_crate_from_input(input: driver::input, } None => { debug!("Calling compile_upto, outputs = %?", outputs); - let (crate, _) = driver::compile_upto(sess, cfg, input, + let (crate, _) = driver::compile_upto(sess, cfg, &input, driver::cu_parse, Some(outputs)); // Inject the inferred link_meta info if it's not already there From 98dfeb173fc1fbe8724abf8cf0943bd32653dd65 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 18 Apr 2013 20:40:37 -0400 Subject: [PATCH 318/403] core: clean up tests (mostly unused unsafe blocks) --- src/libcore/comm.rs | 4 --- src/libcore/rt/sched/local_sched.rs | 22 ++++++++--------- src/libcore/rt/uv/net.rs | 2 +- src/libcore/stackwalk.rs | 4 +-- src/libcore/str.rs | 4 +-- src/libcore/task/local_data.rs | 38 +++++++++++++---------------- 6 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index fc13463bd1c2a..2656115dca258 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -112,8 +112,6 @@ pub mod streamp { #[allow(non_camel_case_types)] pub mod server { - priv use core::kinds::Owned; - #[allow(non_camel_case_types)] pub type Open = ::core::pipes::RecvPacket>; } @@ -388,8 +386,6 @@ pub mod oneshot { #[allow(non_camel_case_types)] pub mod server { - priv use core::kinds::Owned; - #[allow(non_camel_case_types)] pub type Oneshot = ::core::pipes::RecvPacketBuffered, diff --git a/src/libcore/rt/sched/local_sched.rs b/src/libcore/rt/sched/local_sched.rs index 2ab50252ac69e..77fbadf0bb7bb 100644 --- a/src/libcore/rt/sched/local_sched.rs +++ b/src/libcore/rt/sched/local_sched.rs @@ -66,18 +66,16 @@ pub fn borrow(f: &fn(&mut Scheduler)) { /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased pub unsafe fn unsafe_borrow() -> &mut Scheduler { - unsafe { - let key = tls_key(); - let mut void_sched: *mut c_void = tls::get(key); - assert!(void_sched.is_not_null()); - { - let void_sched_ptr = &mut void_sched; - let sched: &mut ~Scheduler = { - transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) - }; - let sched: &mut Scheduler = &mut **sched; - return sched; - } + let key = tls_key(); + let mut void_sched: *mut c_void = tls::get(key); + assert!(void_sched.is_not_null()); + { + let void_sched_ptr = &mut void_sched; + let sched: &mut ~Scheduler = { + transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) + }; + let sched: &mut Scheduler = &mut **sched; + return sched; } } diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index 0dc1a4d86cbc9..b4a08c1492894 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -388,7 +388,7 @@ fn connect_read() { vec_to_uv_buf(vec::from_elem(size, 0)) }; do stream_watcher.read_start(alloc) - |stream_watcher, nread, buf, status| { + |stream_watcher, _nread, buf, status| { let buf = vec_from_uv_buf(buf); rtdebug!("read cb!"); diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs index 99bbc93056bbb..21e75354e740c 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libcore/stackwalk.rs @@ -64,9 +64,7 @@ fn test_simple_deep() { if i == 0 { return } for walk_stack |_frame| { - unsafe { - breakpoint(); - } + breakpoint(); } run(i - 1); } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 837f9c1a9adea..d72b4a71e2a6e 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -3346,7 +3346,7 @@ mod tests { #[test] fn test_shift_byte() { let mut s = ~"ABC"; - let b = unsafe { raw::shift_byte(&mut s) }; + let b = raw::shift_byte(&mut s); assert!((s == ~"BC")); assert!((b == 65u8)); } @@ -3354,7 +3354,7 @@ mod tests { #[test] fn test_pop_byte() { let mut s = ~"ABC"; - let b = unsafe { raw::pop_byte(&mut s) }; + let b = raw::pop_byte(&mut s); assert!((s == ~"AB")); assert!((b == 67u8)); } diff --git a/src/libcore/task/local_data.rs b/src/libcore/task/local_data.rs index 261671f6de9ae..6050aca6dc1f5 100644 --- a/src/libcore/task/local_data.rs +++ b/src/libcore/task/local_data.rs @@ -150,32 +150,28 @@ fn test_tls_modify() { #[test] fn test_tls_crust_automorestack_memorial_bug() { - unsafe { - // This might result in a stack-canary clobber if the runtime fails to - // set sp_limit to 0 when calling the cleanup extern - it might - // automatically jump over to the rust stack, which causes next_c_sp - // to get recorded as something within a rust stack segment. Then a - // subsequent upcall (esp. for logging, think vsnprintf) would run on - // a stack smaller than 1 MB. - fn my_key(_x: @~str) { } - do task::spawn { - unsafe { local_data_set(my_key, @~"hax"); } - } + // This might result in a stack-canary clobber if the runtime fails to + // set sp_limit to 0 when calling the cleanup extern - it might + // automatically jump over to the rust stack, which causes next_c_sp + // to get recorded as something within a rust stack segment. Then a + // subsequent upcall (esp. for logging, think vsnprintf) would run on + // a stack smaller than 1 MB. + fn my_key(_x: @~str) { } + do task::spawn { + unsafe { local_data_set(my_key, @~"hax"); } } } #[test] fn test_tls_multiple_types() { - unsafe { - fn str_key(_x: @~str) { } - fn box_key(_x: @@()) { } - fn int_key(_x: @int) { } - do task::spawn { - unsafe { - local_data_set(str_key, @~"string data"); - local_data_set(box_key, @@()); - local_data_set(int_key, @42); - } + fn str_key(_x: @~str) { } + fn box_key(_x: @@()) { } + fn int_key(_x: @int) { } + do task::spawn { + unsafe { + local_data_set(str_key, @~"string data"); + local_data_set(box_key, @@()); + local_data_set(int_key, @42); } } } From cd982ad3f74673c55af6034a4f757e60be9b381c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 18 Apr 2013 20:40:53 -0400 Subject: [PATCH 319/403] std: clean up tests (mostly unused unsafe blocks) --- src/libstd/c_vec.rs | 6 +-- src/libstd/rope.rs | 22 ++++---- src/libstd/uv_iotask.rs | 114 +++++++++++++++++++--------------------- src/libstd/uv_ll.rs | 106 ++++++++++++++++++------------------- 4 files changed, 116 insertions(+), 132 deletions(-) diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index a59c76c809b13..dd85e886b1ec6 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -159,8 +159,8 @@ mod tests { assert!(mem as int != 0); - return unsafe { c_vec_with_dtor(mem as *mut u8, n as uint, - || unsafe { free(mem) }) }; + return c_vec_with_dtor(mem as *mut u8, n as uint, + || unsafe { free(mem) }); } } @@ -196,7 +196,7 @@ mod tests { #[test] fn test_and_I_mean_it() { let cv = malloc(16u as size_t); - let p = unsafe { ptr(cv) }; + let p = ptr(cv); set(cv, 0u, 32u8); set(cv, 1u, 33u8); diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index 653283f2e78b9..890712a97085b 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -1287,18 +1287,16 @@ mod tests { node::Content(x) => { let str = @mut ~""; fn aux(str: @mut ~str, node: @node::Node) { - unsafe { - match (*node) { - node::Leaf(x) => { - *str += str::slice( - *x.content, x.byte_offset, - x.byte_offset + x.byte_len).to_owned(); - } - node::Concat(ref x) => { - aux(str, x.left); - aux(str, x.right); - } - } + match (*node) { + node::Leaf(x) => { + *str += str::slice( + *x.content, x.byte_offset, + x.byte_offset + x.byte_len).to_owned(); + } + node::Concat(ref x) => { + aux(str, x.left); + aux(str, x.right); + } } } aux(str, x); diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index c7a78f3891923..7e1c9d858ce0c 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -224,36 +224,32 @@ struct AhData { #[cfg(test)] fn impl_uv_iotask_async(iotask: &IoTask) { - unsafe { - let async_handle = ll::async_t(); - let ah_ptr = ptr::addr_of(&async_handle); - let (exit_po, exit_ch) = stream::<()>(); - let ah_data = AhData { - iotask: iotask.clone(), - exit_ch: SharedChan::new(exit_ch) - }; - let ah_data_ptr: *AhData = unsafe { - ptr::to_unsafe_ptr(&ah_data) - }; - debug!("about to interact"); - do interact(iotask) |loop_ptr| { - unsafe { - debug!("interacting"); - ll::async_init(loop_ptr, ah_ptr, async_handle_cb); - ll::set_data_for_uv_handle( - ah_ptr, ah_data_ptr as *libc::c_void); - ll::async_send(ah_ptr); - } - }; - debug!("waiting for async close"); - exit_po.recv(); - } + let async_handle = ll::async_t(); + let ah_ptr = ptr::addr_of(&async_handle); + let (exit_po, exit_ch) = stream::<()>(); + let ah_data = AhData { + iotask: iotask.clone(), + exit_ch: SharedChan::new(exit_ch) + }; + let ah_data_ptr: *AhData = ptr::to_unsafe_ptr(&ah_data); + debug!("about to interact"); + do interact(iotask) |loop_ptr| { + unsafe { + debug!("interacting"); + ll::async_init(loop_ptr, ah_ptr, async_handle_cb); + ll::set_data_for_uv_handle( + ah_ptr, ah_data_ptr as *libc::c_void); + ll::async_send(ah_ptr); + } + }; + debug!("waiting for async close"); + exit_po.recv(); } // this fn documents the bear minimum neccesary to roll your own // high_level_loop #[cfg(test)] -unsafe fn spawn_test_loop(exit_ch: ~Chan<()>) -> IoTask { +fn spawn_test_loop(exit_ch: ~Chan<()>) -> IoTask { let (iotask_port, iotask_ch) = stream::(); do task::spawn_sched(task::ManualThreads(1u)) { debug!("about to run a test loop"); @@ -265,9 +261,7 @@ unsafe fn spawn_test_loop(exit_ch: ~Chan<()>) -> IoTask { #[cfg(test)] extern fn lifetime_handle_close(handle: *libc::c_void) { - unsafe { - debug!("lifetime_handle_close ptr %?", handle); - } + debug!("lifetime_handle_close ptr %?", handle); } #[cfg(test)] @@ -279,38 +273,36 @@ extern fn lifetime_async_callback(handle: *libc::c_void, #[test] fn test_uv_iotask_async() { - unsafe { - let (exit_po, exit_ch) = stream::<()>(); - let iotask = &spawn_test_loop(~exit_ch); - - debug!("spawned iotask"); - - // using this handle to manage the lifetime of the - // high_level_loop, as it will exit the first time one of - // the impl_uv_hl_async() is cleaned up with no one ref'd - // handles on the loop (Which can happen under - // race-condition type situations.. this ensures that the - // loop lives until, at least, all of the - // impl_uv_hl_async() runs have been called, at least. - let (work_exit_po, work_exit_ch) = stream::<()>(); - let work_exit_ch = SharedChan::new(work_exit_ch); - for iter::repeat(7u) { - let iotask_clone = iotask.clone(); - let work_exit_ch_clone = work_exit_ch.clone(); - do task::spawn_sched(task::ManualThreads(1u)) { - debug!("async"); - impl_uv_iotask_async(&iotask_clone); - debug!("done async"); - work_exit_ch_clone.send(()); - }; + let (exit_po, exit_ch) = stream::<()>(); + let iotask = &spawn_test_loop(~exit_ch); + + debug!("spawned iotask"); + + // using this handle to manage the lifetime of the + // high_level_loop, as it will exit the first time one of + // the impl_uv_hl_async() is cleaned up with no one ref'd + // handles on the loop (Which can happen under + // race-condition type situations.. this ensures that the + // loop lives until, at least, all of the + // impl_uv_hl_async() runs have been called, at least. + let (work_exit_po, work_exit_ch) = stream::<()>(); + let work_exit_ch = SharedChan::new(work_exit_ch); + for iter::repeat(7u) { + let iotask_clone = iotask.clone(); + let work_exit_ch_clone = work_exit_ch.clone(); + do task::spawn_sched(task::ManualThreads(1u)) { + debug!("async"); + impl_uv_iotask_async(&iotask_clone); + debug!("done async"); + work_exit_ch_clone.send(()); }; - for iter::repeat(7u) { - debug!("waiting"); - work_exit_po.recv(); - }; - debug!(~"sending teardown_loop msg.."); - exit(iotask); - exit_po.recv(); - debug!(~"after recv on exit_po.. exiting.."); - } + }; + for iter::repeat(7u) { + debug!("waiting"); + work_exit_po.recv(); + }; + debug!(~"sending teardown_loop msg.."); + exit(iotask); + exit_po.recv(); + debug!(~"after recv on exit_po.. exiting.."); } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 98d76c6b9aa56..a5c531004003a 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1422,10 +1422,8 @@ mod test { } extern fn server_after_close_cb(handle: *libc::c_void) { - unsafe { - debug!("SERVER server stream closed, should exit. h: %?", - handle); - } + debug!("SERVER server stream closed, should exit. h: %?", + handle); } extern fn client_stream_after_close_cb(handle: *libc::c_void) { @@ -1709,48 +1707,46 @@ mod test { // this is the impl for a test that is (maybe) ran on a // per-platform/arch basis below pub fn impl_uv_tcp_server_and_request() { - unsafe { - let bind_ip = ~"0.0.0.0"; - let request_ip = ~"127.0.0.1"; - let port = 8886; - let kill_server_msg = ~"does a dog have buddha nature?"; - let server_resp_msg = ~"mu!"; - let (client_port, client_chan) = stream::<~str>(); - let client_chan = SharedChan::new(client_chan); - let (server_port, server_chan) = stream::<~str>(); - let server_chan = SharedChan::new(server_chan); - - let (continue_port, continue_chan) = stream::(); - let continue_chan = SharedChan::new(continue_chan); - - let kill_server_msg_copy = copy kill_server_msg; - let server_resp_msg_copy = copy server_resp_msg; - do task::spawn_sched(task::ManualThreads(1)) { - impl_uv_tcp_server(bind_ip, port, - copy kill_server_msg_copy, - copy server_resp_msg_copy, - server_chan.clone(), - continue_chan.clone()); - }; - - // block until the server up is.. possibly a race? - debug!(~"before receiving on server continue_port"); - continue_port.recv(); - debug!(~"received on continue port, set up tcp client"); - - let kill_server_msg_copy = copy kill_server_msg; - do task::spawn_sched(task::ManualThreads(1u)) { - impl_uv_tcp_request(request_ip, port, - kill_server_msg_copy, - client_chan.clone()); - }; - - let msg_from_client = server_port.recv(); - let msg_from_server = client_port.recv(); - - assert!(str::contains(msg_from_client, kill_server_msg)); - assert!(str::contains(msg_from_server, server_resp_msg)); - } + let bind_ip = ~"0.0.0.0"; + let request_ip = ~"127.0.0.1"; + let port = 8886; + let kill_server_msg = ~"does a dog have buddha nature?"; + let server_resp_msg = ~"mu!"; + let (client_port, client_chan) = stream::<~str>(); + let client_chan = SharedChan::new(client_chan); + let (server_port, server_chan) = stream::<~str>(); + let server_chan = SharedChan::new(server_chan); + + let (continue_port, continue_chan) = stream::(); + let continue_chan = SharedChan::new(continue_chan); + + let kill_server_msg_copy = copy kill_server_msg; + let server_resp_msg_copy = copy server_resp_msg; + do task::spawn_sched(task::ManualThreads(1)) { + impl_uv_tcp_server(bind_ip, port, + copy kill_server_msg_copy, + copy server_resp_msg_copy, + server_chan.clone(), + continue_chan.clone()); + }; + + // block until the server up is.. possibly a race? + debug!(~"before receiving on server continue_port"); + continue_port.recv(); + debug!(~"received on continue port, set up tcp client"); + + let kill_server_msg_copy = copy kill_server_msg; + do task::spawn_sched(task::ManualThreads(1u)) { + impl_uv_tcp_request(request_ip, port, + kill_server_msg_copy, + client_chan.clone()); + }; + + let msg_from_client = server_port.recv(); + let msg_from_server = client_port.recv(); + + assert!(str::contains(msg_from_client, kill_server_msg)); + assert!(str::contains(msg_from_server, server_resp_msg)); } // FIXME don't run on fbsd or linux 32 bit(#2064) @@ -1784,17 +1780,15 @@ mod test { fn struct_size_check_common(t_name: ~str, foreign_size: libc::c_uint) { - unsafe { - let rust_size = sys::size_of::(); - let sizes_match = foreign_size as uint == rust_size; - if !sizes_match { - let output = fmt!( - "STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u", - t_name, rust_size, foreign_size as uint); - debug!(output); - } - assert!(sizes_match); + let rust_size = sys::size_of::(); + let sizes_match = foreign_size as uint == rust_size; + if !sizes_match { + let output = fmt!( + "STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u", + t_name, rust_size, foreign_size as uint); + debug!(output); } + assert!(sizes_match); } // struct size tests From 5c2e9b29f10694ad76dcb6b88e95243a44813c05 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 20 Apr 2013 14:34:18 +1000 Subject: [PATCH 320/403] libcore: wrappers for size/align_of to act on values without needing explicit :: annotations --- src/libcore/sys.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 04f96f5eb229e..c4ec83aa17662 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -83,12 +83,24 @@ pub fn get_type_desc() -> *TypeDesc { unsafe { rusti::get_tydesc::() as *TypeDesc } } +/// Returns a pointer to a type descriptor. +#[inline(always)] +pub fn get_type_desc_val(_val: &T) -> *TypeDesc { + get_type_desc::() +} + /// Returns the size of a type #[inline(always)] pub fn size_of() -> uint { unsafe { rusti::size_of::() } } +/// Returns the size of the type that `_val` points to +#[inline(always)] +pub fn size_of_val(_val: &T) -> uint { + size_of::() +} + /** * Returns the size of a type, or 1 if the actual size is zero. * @@ -100,6 +112,13 @@ pub fn nonzero_size_of() -> uint { if s == 0 { 1 } else { s } } +/// Returns the size of the type of the value that `_val` points to +#[inline(always)] +pub fn nonzero_size_of_val(_val: &T) -> uint { + nonzero_size_of::() +} + + /** * Returns the ABI-required minimum alignment of a type * @@ -111,12 +130,26 @@ pub fn min_align_of() -> uint { unsafe { rusti::min_align_of::() } } +/// Returns the ABI-required minimum alignment of the type of the value that +/// `_val` points to +#[inline(always)] +pub fn min_align_of_val(_val: &T) -> uint { + min_align_of::() +} + /// Returns the preferred alignment of a type #[inline(always)] pub fn pref_align_of() -> uint { unsafe { rusti::pref_align_of::() } } +/// Returns the preferred alignment of the type of the value that +/// `_val` points to +#[inline(always)] +pub fn pref_align_of_val(_val: &T) -> uint { + pref_align_of::() +} + /// Returns the refcount of a shared box (as just before calling this) #[inline(always)] pub fn refcount(t: @T) -> uint { @@ -162,7 +195,7 @@ pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! { #[cfg(test)] mod tests { use cast; - use sys::{Closure, pref_align_of, size_of, nonzero_size_of}; + use sys::*; #[test] fn size_of_basic() { @@ -188,6 +221,14 @@ mod tests { assert!(size_of::<*uint>() == 8u); } + #[test] + fn size_of_val_basic() { + assert_eq!(size_of_val(&1u8), 1); + assert_eq!(size_of_val(&1u16), 2); + assert_eq!(size_of_val(&1u32), 4); + assert_eq!(size_of_val(&1u64), 8); + } + #[test] fn nonzero_size_of_basic() { type Z = [i8, ..0]; @@ -196,6 +237,14 @@ mod tests { assert!(nonzero_size_of::() == size_of::()); } + #[test] + fn nonzero_size_of_val_basic() { + let z = [0u8, ..0]; + assert_eq!(size_of_val(&z), 0u); + assert_eq!(nonzero_size_of_val(&z), 1u); + assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u)); + } + #[test] fn align_of_basic() { assert!(pref_align_of::() == 1u); @@ -219,6 +268,13 @@ mod tests { assert!(pref_align_of::<*uint>() == 8u); } + #[test] + fn align_of_val_basic() { + assert_eq!(pref_align_of_val(&1u8), 1u); + assert_eq!(pref_align_of_val(&1u16), 2u); + assert_eq!(pref_align_of_val(&1u32), 4u); + } + #[test] fn synthesize_closure() { unsafe { From a0c2949e7c8c67fc7739482de8cee374a253b523 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 20 Apr 2013 13:32:27 +1000 Subject: [PATCH 321/403] libcore: add a ScanIterator, a generalisation of MapIterator to have internal state. --- src/libcore/iterator.rs | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 4929b1b8dba37..4a3a98df0d0ea 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -39,6 +39,8 @@ pub trait IteratorUtil { fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; fn skip(self, n: uint) -> SkipIterator; fn take(self, n: uint) -> TakeIterator; + fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) + -> ScanIterator<'r, A, B, Self, St>; fn advance(&mut self, f: &fn(A) -> bool); } @@ -93,6 +95,12 @@ impl> IteratorUtil for T { TakeIterator{iter: self, n: n} } + #[inline(always)] + fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) + -> ScanIterator<'r, A, B, T, St> { + ScanIterator{iter: self, f: f, state: initial_state} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) { @@ -306,12 +314,13 @@ impl> Iterator for TakeIterator { pub struct UnfoldrIterator<'self, A, St> { priv f: &'self fn(&mut St) -> Option, - priv state: St + state: St } pub impl<'self, A, St> UnfoldrIterator<'self, A, St> { #[inline] - fn new(f: &'self fn(&mut St) -> Option, initial_state: St) -> UnfoldrIterator<'self, A, St> { + fn new(f: &'self fn(&mut St) -> Option, initial_state: St) + -> UnfoldrIterator<'self, A, St> { UnfoldrIterator { f: f, state: initial_state @@ -326,6 +335,19 @@ impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { } } +pub struct ScanIterator<'self, A, B, T, St> { + priv iter: T, + priv f: &'self fn(&mut St, A) -> Option, + state: St +} + +impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, T, St> { + #[inline] + fn next(&mut self) -> Option { + self.iter.next().chain(|a| (self.f)(&mut self.state, a)) + } +} + #[cfg(test)] mod tests { use super::*; @@ -406,6 +428,25 @@ mod tests { assert_eq!(i, ys.len()); } + #[test] + fn test_iterator_scan() { + // test the type inference + fn add(old: &mut int, new: &uint) -> Option { + *old += *new as int; + Some(*old as float) + } + let xs = [0u, 1, 2, 3, 4]; + let ys = [0f, 1f, 3f, 6f, 10f]; + + let mut it = xs.iter().scan(0, add); + let mut i = 0; + for it.advance |x| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + #[test] fn test_unfoldr() { fn count(st: &mut uint) -> Option { From 93c0888b6c6111c645d5aa2ef78da6fe8ab2c307 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 20 Apr 2013 21:58:56 +1000 Subject: [PATCH 322/403] librustc: implement and use `fixed_stack_segment` attribute for intrinsics. --- src/libcore/unstable/intrinsics.rs | 13 ++++++++++++- src/librustc/middle/trans/foreign.rs | 6 ++++++ src/librustc/middle/trans/monomorphize.rs | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs index ba96c6e5d3036..a18ad1738861d 100644 --- a/src/libcore/unstable/intrinsics.rs +++ b/src/libcore/unstable/intrinsics.rs @@ -70,16 +70,28 @@ pub extern "rust-intrinsic" { pub fn powif32(a: f32, x: i32) -> f32; pub fn powif64(a: f64, x: i32) -> f64; + // the following kill the stack canary without + // `fixed_stack_segment`. This possibly only affects the f64 + // variants, but it's hard to be sure since it seems to only + // occur with fairly specific arguments. + #[fixed_stack_segment] pub fn sinf32(x: f32) -> f32; + #[fixed_stack_segment] pub fn sinf64(x: f64) -> f64; + #[fixed_stack_segment] pub fn cosf32(x: f32) -> f32; + #[fixed_stack_segment] pub fn cosf64(x: f64) -> f64; + #[fixed_stack_segment] pub fn powf32(a: f32, x: f32) -> f32; + #[fixed_stack_segment] pub fn powf64(a: f64, x: f64) -> f64; + #[fixed_stack_segment] pub fn expf32(x: f32) -> f32; + #[fixed_stack_segment] pub fn expf64(x: f64) -> f64; pub fn exp2f32(x: f32) -> f32; @@ -128,4 +140,3 @@ pub extern "rust-intrinsic" { pub fn bswap32(x: i32) -> i32; pub fn bswap64(x: i64) -> i64; } - diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 854ec585d5cc2..956ee3bf1443e 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -546,6 +546,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, item: @ast::foreign_item, path: ast_map::path, substs: @param_substs, + attributes: &[ast::attribute], ref_id: Option) { debug!("trans_intrinsic(item.ident=%s)", *ccx.sess.str_of(item.ident)); @@ -561,6 +562,11 @@ pub fn trans_intrinsic(ccx: @CrateContext, Some(copy substs), Some(item.span)); + // Set the fixed stack segment flag if necessary. + if attr::attrs_contains_name(attributes, "fixed_stack_segment") { + set_fixed_stack_segment(fcx.llfn); + } + let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 9d63ac854a90c..52ca8ec49bb7f 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -212,7 +212,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, } ast_map::node_foreign_item(i, _, _, _) => { let d = mk_lldecl(); - foreign::trans_intrinsic(ccx, d, i, pt, psubsts.get(), + foreign::trans_intrinsic(ccx, d, i, pt, psubsts.get(), i.attrs, ref_id); d } From d9c54f83877c813964923f6a00ece8804ae4f3b8 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 4 Apr 2013 03:08:53 +1100 Subject: [PATCH 323/403] librustc: use LLVM intrinsics for several floating point operations. Achieves at least 5x speed up for some functions! Also, reorganise the delegation code so that the delegated function wrappers have the #[inline(always)] annotation, and reduce the repetition of delegate!(..). --- src/libcore/num/f32.rs | 152 +++++++++++++++++++----------------- src/libcore/num/f64.rs | 165 ++++++++++++++++++++------------------- src/libcore/num/float.rs | 2 +- 3 files changed, 166 insertions(+), 153 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 404f1a82de5d0..6233f8c2a61b5 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -10,12 +10,9 @@ //! Operations and constants for `f32` -use cmath; -use libc::{c_float, c_int}; use num::strconv; use num; use option::Option; -use unstable::intrinsics::floorf32; use from_str; use to_str; @@ -24,79 +21,93 @@ use to_str; pub use cmath::c_float_targ_consts::*; +// An inner module is required to get the #[inline(always)] attribute on the +// functions. +pub use self::delegated::*; + macro_rules! delegate( ( - fn $name:ident( - $( - $arg:ident : $arg_ty:ty - ),* - ) -> $rv:ty = $bound_name:path + $( + fn $name:ident( + $( + $arg:ident : $arg_ty:ty + ),* + ) -> $rv:ty = $bound_name:path + ),* ) => ( - pub fn $name($( $arg : $arg_ty ),*) -> $rv { - unsafe { - $bound_name($( $arg ),*) - } + mod delegated { + use cmath::c_float_utils; + use libc::{c_float, c_int}; + use unstable::intrinsics; + + $( + #[inline(always)] + pub fn $name($( $arg : $arg_ty ),*) -> $rv { + unsafe { + $bound_name($( $arg ),*) + } + } + )* } ) ) -delegate!(fn acos(n: c_float) -> c_float = cmath::c_float_utils::acos) -delegate!(fn asin(n: c_float) -> c_float = cmath::c_float_utils::asin) -delegate!(fn atan(n: c_float) -> c_float = cmath::c_float_utils::atan) -delegate!(fn atan2(a: c_float, b: c_float) -> c_float = - cmath::c_float_utils::atan2) -delegate!(fn cbrt(n: c_float) -> c_float = cmath::c_float_utils::cbrt) -delegate!(fn ceil(n: c_float) -> c_float = cmath::c_float_utils::ceil) -delegate!(fn copysign(x: c_float, y: c_float) -> c_float = - cmath::c_float_utils::copysign) -delegate!(fn cos(n: c_float) -> c_float = cmath::c_float_utils::cos) -delegate!(fn cosh(n: c_float) -> c_float = cmath::c_float_utils::cosh) -delegate!(fn erf(n: c_float) -> c_float = cmath::c_float_utils::erf) -delegate!(fn erfc(n: c_float) -> c_float = cmath::c_float_utils::erfc) -delegate!(fn exp(n: c_float) -> c_float = cmath::c_float_utils::exp) -delegate!(fn expm1(n: c_float) -> c_float = cmath::c_float_utils::expm1) -delegate!(fn exp2(n: c_float) -> c_float = cmath::c_float_utils::exp2) -delegate!(fn abs(n: c_float) -> c_float = cmath::c_float_utils::abs) -delegate!(fn abs_sub(a: c_float, b: c_float) -> c_float = - cmath::c_float_utils::abs_sub) -delegate!(fn mul_add(a: c_float, b: c_float, c: c_float) -> c_float = - cmath::c_float_utils::mul_add) -delegate!(fn fmax(a: c_float, b: c_float) -> c_float = - cmath::c_float_utils::fmax) -delegate!(fn fmin(a: c_float, b: c_float) -> c_float = - cmath::c_float_utils::fmin) -delegate!(fn nextafter(x: c_float, y: c_float) -> c_float = - cmath::c_float_utils::nextafter) -delegate!(fn frexp(n: c_float, value: &mut c_int) -> c_float = - cmath::c_float_utils::frexp) -delegate!(fn hypot(x: c_float, y: c_float) -> c_float = - cmath::c_float_utils::hypot) -delegate!(fn ldexp(x: c_float, n: c_int) -> c_float = - cmath::c_float_utils::ldexp) -delegate!(fn lgamma(n: c_float, sign: &mut c_int) -> c_float = - cmath::c_float_utils::lgamma) -delegate!(fn ln(n: c_float) -> c_float = cmath::c_float_utils::ln) -delegate!(fn log_radix(n: c_float) -> c_float = - cmath::c_float_utils::log_radix) -delegate!(fn ln1p(n: c_float) -> c_float = cmath::c_float_utils::ln1p) -delegate!(fn log10(n: c_float) -> c_float = cmath::c_float_utils::log10) -delegate!(fn log2(n: c_float) -> c_float = cmath::c_float_utils::log2) -delegate!(fn ilog_radix(n: c_float) -> c_int = - cmath::c_float_utils::ilog_radix) -delegate!(fn modf(n: c_float, iptr: &mut c_float) -> c_float = - cmath::c_float_utils::modf) -delegate!(fn pow(n: c_float, e: c_float) -> c_float = - cmath::c_float_utils::pow) -delegate!(fn round(n: c_float) -> c_float = cmath::c_float_utils::round) -delegate!(fn ldexp_radix(n: c_float, i: c_int) -> c_float = - cmath::c_float_utils::ldexp_radix) -delegate!(fn sin(n: c_float) -> c_float = cmath::c_float_utils::sin) -delegate!(fn sinh(n: c_float) -> c_float = cmath::c_float_utils::sinh) -delegate!(fn sqrt(n: c_float) -> c_float = cmath::c_float_utils::sqrt) -delegate!(fn tan(n: c_float) -> c_float = cmath::c_float_utils::tan) -delegate!(fn tanh(n: c_float) -> c_float = cmath::c_float_utils::tanh) -delegate!(fn tgamma(n: c_float) -> c_float = cmath::c_float_utils::tgamma) -delegate!(fn trunc(n: c_float) -> c_float = cmath::c_float_utils::trunc) +delegate!( + // intrinsics + fn abs(n: f32) -> f32 = intrinsics::fabsf32, + fn cos(n: f32) -> f32 = intrinsics::cosf32, + fn exp(n: f32) -> f32 = intrinsics::expf32, + fn exp2(n: f32) -> f32 = intrinsics::exp2f32, + fn floor(x: f32) -> f32 = intrinsics::floorf32, + fn ln(n: f32) -> f32 = intrinsics::logf32, + fn log10(n: f32) -> f32 = intrinsics::log10f32, + fn log2(n: f32) -> f32 = intrinsics::log2f32, + fn mul_add(a: f32, b: f32, c: f32) -> f32 = intrinsics::fmaf32, + fn pow(n: f32, e: f32) -> f32 = intrinsics::powf32, + fn powi(n: f32, e: c_int) -> f32 = intrinsics::powif32, + fn sin(n: f32) -> f32 = intrinsics::sinf32, + fn sqrt(n: f32) -> f32 = intrinsics::sqrtf32, + + // LLVM 3.3 required to use intrinsics for these four + fn ceil(n: c_float) -> c_float = c_float_utils::ceil, + fn trunc(n: c_float) -> c_float = c_float_utils::trunc, + /* + fn ceil(n: f32) -> f32 = intrinsics::ceilf32, + fn trunc(n: f32) -> f32 = intrinsics::truncf32, + fn rint(n: f32) -> f32 = intrinsics::rintf32, + fn nearbyint(n: f32) -> f32 = intrinsics::nearbyintf32, + */ + + // cmath + fn acos(n: c_float) -> c_float = c_float_utils::acos, + fn asin(n: c_float) -> c_float = c_float_utils::asin, + fn atan(n: c_float) -> c_float = c_float_utils::atan, + fn atan2(a: c_float, b: c_float) -> c_float = c_float_utils::atan2, + fn cbrt(n: c_float) -> c_float = c_float_utils::cbrt, + fn copysign(x: c_float, y: c_float) -> c_float = c_float_utils::copysign, + fn cosh(n: c_float) -> c_float = c_float_utils::cosh, + fn erf(n: c_float) -> c_float = c_float_utils::erf, + fn erfc(n: c_float) -> c_float = c_float_utils::erfc, + fn expm1(n: c_float) -> c_float = c_float_utils::expm1, + fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub, + fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax, + fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin, + fn nextafter(x: c_float, y: c_float) -> c_float = c_float_utils::nextafter, + fn frexp(n: c_float, value: &mut c_int) -> c_float = c_float_utils::frexp, + fn hypot(x: c_float, y: c_float) -> c_float = c_float_utils::hypot, + fn ldexp(x: c_float, n: c_int) -> c_float = c_float_utils::ldexp, + fn lgamma(n: c_float, sign: &mut c_int) -> c_float = c_float_utils::lgamma, + fn log_radix(n: c_float) -> c_float = c_float_utils::log_radix, + fn ln1p(n: c_float) -> c_float = c_float_utils::ln1p, + fn ilog_radix(n: c_float) -> c_int = c_float_utils::ilog_radix, + fn modf(n: c_float, iptr: &mut c_float) -> c_float = c_float_utils::modf, + fn round(n: c_float) -> c_float = c_float_utils::round, + fn ldexp_radix(n: c_float, i: c_int) -> c_float = c_float_utils::ldexp_radix, + fn sinh(n: c_float) -> c_float = c_float_utils::sinh, + fn tan(n: c_float) -> c_float = c_float_utils::tan, + fn tanh(n: c_float) -> c_float = c_float_utils::tanh, + fn tgamma(n: c_float) -> c_float = c_float_utils::tgamma) + // These are not defined inside consts:: for consistency with // the integer types @@ -143,9 +154,6 @@ pub fn ge(x: f32, y: f32) -> bool { return x >= y; } #[inline(always)] pub fn gt(x: f32, y: f32) -> bool { return x > y; } -/// Returns `x` rounded down -#[inline(always)] -pub fn floor(x: f32) -> f32 { unsafe { floorf32(x) } } // FIXME (#1999): replace the predicates below with llvm intrinsics or // calls to the libmath macros in the rust runtime for performance. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index b4eaa0e7fdc60..7f32893f5bff7 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -10,12 +10,9 @@ //! Operations and constants for `f64` -use cmath; -use libc::{c_double, c_int}; use num::strconv; use num; use option::Option; -use unstable::intrinsics::floorf64; use to_str; use from_str; @@ -25,87 +22,98 @@ use from_str; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; +// An inner module is required to get the #[inline(always)] attribute on the +// functions. +pub use self::delegated::*; + macro_rules! delegate( ( - fn $name:ident( - $( - $arg:ident : $arg_ty:ty - ),* - ) -> $rv:ty = $bound_name:path + $( + fn $name:ident( + $( + $arg:ident : $arg_ty:ty + ),* + ) -> $rv:ty = $bound_name:path + ),* ) => ( - pub fn $name($( $arg : $arg_ty ),*) -> $rv { - unsafe { - $bound_name($( $arg ),*) - } + mod delegated { + use cmath::c_double_utils; + use libc::{c_double, c_int}; + use unstable::intrinsics; + + $( + #[inline(always)] + pub fn $name($( $arg : $arg_ty ),*) -> $rv { + unsafe { + $bound_name($( $arg ),*) + } + } + )* } ) ) -delegate!(fn acos(n: c_double) -> c_double = cmath::c_double_utils::acos) -delegate!(fn asin(n: c_double) -> c_double = cmath::c_double_utils::asin) -delegate!(fn atan(n: c_double) -> c_double = cmath::c_double_utils::atan) -delegate!(fn atan2(a: c_double, b: c_double) -> c_double = - cmath::c_double_utils::atan2) -delegate!(fn cbrt(n: c_double) -> c_double = cmath::c_double_utils::cbrt) -delegate!(fn ceil(n: c_double) -> c_double = cmath::c_double_utils::ceil) -delegate!(fn copysign(x: c_double, y: c_double) -> c_double = - cmath::c_double_utils::copysign) -delegate!(fn cos(n: c_double) -> c_double = cmath::c_double_utils::cos) -delegate!(fn cosh(n: c_double) -> c_double = cmath::c_double_utils::cosh) -delegate!(fn erf(n: c_double) -> c_double = cmath::c_double_utils::erf) -delegate!(fn erfc(n: c_double) -> c_double = cmath::c_double_utils::erfc) -delegate!(fn exp(n: c_double) -> c_double = cmath::c_double_utils::exp) -delegate!(fn expm1(n: c_double) -> c_double = cmath::c_double_utils::expm1) -delegate!(fn exp2(n: c_double) -> c_double = cmath::c_double_utils::exp2) -delegate!(fn abs(n: c_double) -> c_double = cmath::c_double_utils::abs) -delegate!(fn abs_sub(a: c_double, b: c_double) -> c_double = - cmath::c_double_utils::abs_sub) -delegate!(fn mul_add(a: c_double, b: c_double, c: c_double) -> c_double = - cmath::c_double_utils::mul_add) -delegate!(fn fmax(a: c_double, b: c_double) -> c_double = - cmath::c_double_utils::fmax) -delegate!(fn fmin(a: c_double, b: c_double) -> c_double = - cmath::c_double_utils::fmin) -delegate!(fn nextafter(x: c_double, y: c_double) -> c_double = - cmath::c_double_utils::nextafter) -delegate!(fn frexp(n: c_double, value: &mut c_int) -> c_double = - cmath::c_double_utils::frexp) -delegate!(fn hypot(x: c_double, y: c_double) -> c_double = - cmath::c_double_utils::hypot) -delegate!(fn ldexp(x: c_double, n: c_int) -> c_double = - cmath::c_double_utils::ldexp) -delegate!(fn lgamma(n: c_double, sign: &mut c_int) -> c_double = - cmath::c_double_utils::lgamma) -delegate!(fn ln(n: c_double) -> c_double = cmath::c_double_utils::ln) -delegate!(fn log_radix(n: c_double) -> c_double = - cmath::c_double_utils::log_radix) -delegate!(fn ln1p(n: c_double) -> c_double = cmath::c_double_utils::ln1p) -delegate!(fn log10(n: c_double) -> c_double = cmath::c_double_utils::log10) -delegate!(fn log2(n: c_double) -> c_double = cmath::c_double_utils::log2) -delegate!(fn ilog_radix(n: c_double) -> c_int = - cmath::c_double_utils::ilog_radix) -delegate!(fn modf(n: c_double, iptr: &mut c_double) -> c_double = - cmath::c_double_utils::modf) -delegate!(fn pow(n: c_double, e: c_double) -> c_double = - cmath::c_double_utils::pow) -delegate!(fn round(n: c_double) -> c_double = cmath::c_double_utils::round) -delegate!(fn ldexp_radix(n: c_double, i: c_int) -> c_double = - cmath::c_double_utils::ldexp_radix) -delegate!(fn sin(n: c_double) -> c_double = cmath::c_double_utils::sin) -delegate!(fn sinh(n: c_double) -> c_double = cmath::c_double_utils::sinh) -delegate!(fn sqrt(n: c_double) -> c_double = cmath::c_double_utils::sqrt) -delegate!(fn tan(n: c_double) -> c_double = cmath::c_double_utils::tan) -delegate!(fn tanh(n: c_double) -> c_double = cmath::c_double_utils::tanh) -delegate!(fn tgamma(n: c_double) -> c_double = cmath::c_double_utils::tgamma) -delegate!(fn trunc(n: c_double) -> c_double = cmath::c_double_utils::trunc) -delegate!(fn j0(n: c_double) -> c_double = cmath::c_double_utils::j0) -delegate!(fn j1(n: c_double) -> c_double = cmath::c_double_utils::j1) -delegate!(fn jn(i: c_int, n: c_double) -> c_double = - cmath::c_double_utils::jn) -delegate!(fn y0(n: c_double) -> c_double = cmath::c_double_utils::y0) -delegate!(fn y1(n: c_double) -> c_double = cmath::c_double_utils::y1) -delegate!(fn yn(i: c_int, n: c_double) -> c_double = - cmath::c_double_utils::yn) +delegate!( + // intrinsics + fn abs(n: f64) -> f64 = intrinsics::fabsf64, + fn cos(n: f64) -> f64 = intrinsics::cosf64, + fn exp(n: f64) -> f64 = intrinsics::expf64, + fn exp2(n: f64) -> f64 = intrinsics::exp2f64, + fn floor(x: f64) -> f64 = intrinsics::floorf64, + fn ln(n: f64) -> f64 = intrinsics::logf64, + fn log10(n: f64) -> f64 = intrinsics::log10f64, + fn log2(n: f64) -> f64 = intrinsics::log2f64, + fn mul_add(a: f64, b: f64, c: f64) -> f64 = intrinsics::fmaf64, + fn pow(n: f64, e: f64) -> f64 = intrinsics::powf64, + fn powi(n: f64, e: c_int) -> f64 = intrinsics::powif64, + fn sin(n: f64) -> f64 = intrinsics::sinf64, + fn sqrt(n: f64) -> f64 = intrinsics::sqrtf64, + + // LLVM 3.3 required to use intrinsics for these four + fn ceil(n: c_double) -> c_double = c_double_utils::ceil, + fn trunc(n: c_double) -> c_double = c_double_utils::trunc, + /* + fn ceil(n: f64) -> f64 = intrinsics::ceilf64, + fn trunc(n: f64) -> f64 = intrinsics::truncf64, + fn rint(n: c_double) -> c_double = intrinsics::rintf64, + fn nearbyint(n: c_double) -> c_double = intrinsics::nearbyintf64, + */ + + // cmath + fn acos(n: c_double) -> c_double = c_double_utils::acos, + fn asin(n: c_double) -> c_double = c_double_utils::asin, + fn atan(n: c_double) -> c_double = c_double_utils::atan, + fn atan2(a: c_double, b: c_double) -> c_double = c_double_utils::atan2, + fn cbrt(n: c_double) -> c_double = c_double_utils::cbrt, + fn copysign(x: c_double, y: c_double) -> c_double = c_double_utils::copysign, + fn cosh(n: c_double) -> c_double = c_double_utils::cosh, + fn erf(n: c_double) -> c_double = c_double_utils::erf, + fn erfc(n: c_double) -> c_double = c_double_utils::erfc, + fn expm1(n: c_double) -> c_double = c_double_utils::expm1, + fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub, + fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax, + fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin, + fn nextafter(x: c_double, y: c_double) -> c_double = c_double_utils::nextafter, + fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp, + fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot, + fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp, + fn lgamma(n: c_double, sign: &mut c_int) -> c_double = c_double_utils::lgamma, + fn log_radix(n: c_double) -> c_double = c_double_utils::log_radix, + fn ln1p(n: c_double) -> c_double = c_double_utils::ln1p, + fn ilog_radix(n: c_double) -> c_int = c_double_utils::ilog_radix, + fn modf(n: c_double, iptr: &mut c_double) -> c_double = c_double_utils::modf, + fn round(n: c_double) -> c_double = c_double_utils::round, + fn ldexp_radix(n: c_double, i: c_int) -> c_double = c_double_utils::ldexp_radix, + fn sinh(n: c_double) -> c_double = c_double_utils::sinh, + fn tan(n: c_double) -> c_double = c_double_utils::tan, + fn tanh(n: c_double) -> c_double = c_double_utils::tanh, + fn tgamma(n: c_double) -> c_double = c_double_utils::tgamma, + fn j0(n: c_double) -> c_double = c_double_utils::j0, + fn j1(n: c_double) -> c_double = c_double_utils::j1, + fn jn(i: c_int, n: c_double) -> c_double = c_double_utils::jn, + fn y0(n: c_double) -> c_double = c_double_utils::y0, + fn y1(n: c_double) -> c_double = c_double_utils::y1, + fn yn(i: c_int, n: c_double) -> c_double = c_double_utils::yn) // FIXME (#1433): obtain these in a different way @@ -218,9 +226,6 @@ pub fn is_finite(x: f64) -> bool { return !(is_NaN(x) || is_infinite(x)); } -/// Returns `x` rounded down -#[inline(always)] -pub fn floor(x: f64) -> f64 { unsafe { floorf64(x) } } // FIXME (#1999): add is_normal, is_subnormal, and fpclassify diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 38111210c73c1..c9cda20640d56 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -36,7 +36,7 @@ pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor}; pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub}; pub use f64::{mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp}; pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix}; -pub use f64::{modf, pow, round, sinh, tanh, tgamma, trunc}; +pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc}; pub use f64::signbit; pub use f64::{j0, j1, jn, y0, y1, yn}; From c5baeb1db3d84e1ab0d14a8055db3a7d3cba638d Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 21 Apr 2013 00:59:08 +1000 Subject: [PATCH 324/403] testsuite: update tests to not use math intrinsics directly --- src/test/bench/shootout-nbody.rs | 6 ++---- src/test/bench/shootout-spectralnorm.rs | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index e633f307bc227..da06b36af67ee 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -1,6 +1,5 @@ use core::from_str::FromStr; use core::uint::range; -use core::unstable::intrinsics::sqrtf64; static PI: f64 = 3.141592653589793; static SOLAR_MASS: f64 = 4.0 * PI * PI; @@ -88,7 +87,7 @@ fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) { d[2] = bodies[i].x[2] - bodies[j].x[2]; let d2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; - let mag = dt / (d2 * sqrtf64(d2)); + let mag = dt / (d2 * f64::sqrt(d2)); let a_mass = bodies[i].mass, b_mass = bodies[j].mass; bodies[i].v[0] -= d[0] * b_mass * mag; @@ -121,7 +120,7 @@ fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 { for range(0, 3) |k| { d[k] = bodies[i].x[k] - bodies[j].x[k]; } - let dist = sqrtf64(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); + let dist = f64::sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); e -= bodies[i].mass * bodies[j].mass / dist; } } @@ -147,4 +146,3 @@ fn main() { println(fmt!("%.9f", energy(&bodies) as float)); } - diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index 00e255d890b9d..6840384ca7c8a 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -1,6 +1,5 @@ use core::from_str::FromStr; use core::iter::ExtendedMutableIter; -use core::unstable::intrinsics::sqrtf64; #[inline] fn A(i: i32, j: i32) -> i32 { @@ -49,6 +48,5 @@ fn main() { mult_AtAv(v, u, tmp); } - println(fmt!("%.9f", sqrtf64(dot(u,v) / dot(v,v)) as float)); + println(fmt!("%.9f", f64::sqrt(dot(u,v) / dot(v,v)) as float)); } - From 3c2a44b60f472827884c868c527debbd7e61b054 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 20 Apr 2013 15:51:29 -0400 Subject: [PATCH 325/403] Don't warn about unsafe functions which don't need to be unsafe --- src/librustc/middle/lint.rs | 13 +------------ src/test/compile-fail/unused-unsafe.rs | 7 ++----- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 39144d46c83c4..9087afe596937 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -260,7 +260,7 @@ pub fn get_lint_dict() -> LintDict { (~"unused_unsafe", LintSpec { lint: unused_unsafe, - desc: "unnecessary use of an \"unsafe\" block or function", + desc: "unnecessary use of an \"unsafe\" block", default: warn }), @@ -958,17 +958,6 @@ fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl, _body: &ast::blk, span: span, id: ast::node_id) { debug!("lint check_fn fk=%? id=%?", fk, id); - // Check for an 'unsafe fn' which doesn't need to be unsafe - match *fk { - visit::fk_item_fn(_, _, ast::unsafe_fn, _) => { - if !tcx.used_unsafe.contains(&id) { - tcx.sess.span_lint(unused_unsafe, id, id, span, - ~"unnecessary \"unsafe\" function"); - } - } - _ => () - } - // Check for deprecated modes match *fk { // don't complain about blocks, since they tend to get their modes diff --git a/src/test/compile-fail/unused-unsafe.rs b/src/test/compile-fail/unused-unsafe.rs index 368a0fbe9bece..b29148cd3bc55 100644 --- a/src/test/compile-fail/unused-unsafe.rs +++ b/src/test/compile-fail/unused-unsafe.rs @@ -18,9 +18,7 @@ fn callback(_f: &fn() -> T) -> T { fail!() } fn bad1() { unsafe {} } //~ ERROR: unnecessary "unsafe" block fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary "unsafe" block -unsafe fn bad3() {} //~ ERROR: unnecessary "unsafe" function -unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary "unsafe" function - //~^ ERROR: unnecessary "unsafe" block +unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary "unsafe" block fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary "unsafe" block unsafe fn good0() { libc::exit(1) } @@ -38,7 +36,6 @@ fn good2() { } } -#[allow(unused_unsafe)] unsafe fn allowed0() {} -#[allow(unused_unsafe)] fn allowed1() { unsafe {} } +#[allow(unused_unsafe)] fn allowed() { unsafe {} } fn main() { } From 51a68eb9b14f5d6f8ac358eed8c11e8567d5f87b Mon Sep 17 00:00:00 2001 From: Matthijs Hofstra Date: Sat, 20 Apr 2013 16:27:16 +0200 Subject: [PATCH 326/403] Replaced many instances of reinterpret_cast with transmute --- src/libcore/at_vec.rs | 8 +++--- src/libcore/gc.rs | 18 +++++++------- src/libcore/os.rs | 6 ++--- src/libcore/ptr.rs | 34 +++++++++++++------------- src/libcore/run.rs | 6 ++--- src/libcore/stackwalk.rs | 8 +++--- src/libcore/str.rs | 18 +++++++------- src/libcore/task/local_data_priv.rs | 10 ++++---- src/libcore/unstable.rs | 8 +++--- src/libcore/unstable/global.rs | 4 +-- src/libcore/vec.rs | 28 ++++++++++----------- src/librustc/metadata/loader.rs | 2 +- src/librustc/middle/trans/build.rs | 6 ++--- src/librustc/middle/trans/common.rs | 4 +-- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustc/middle/ty.rs | 6 ++--- src/libstd/arena.rs | 32 ++++++++++++------------ src/libstd/dbg.rs | 8 +++--- src/libstd/par.rs | 2 +- src/libstd/rope.rs | 2 +- src/libstd/sync.rs | 4 +-- 21 files changed, 107 insertions(+), 109 deletions(-) diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 532dcf6157b54..e2bce1bd0f01a 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -41,7 +41,7 @@ pub mod rustrt { pub fn capacity(v: @[T]) -> uint { unsafe { let repr: **raw::VecRepr = - ::cast::reinterpret_cast(&addr_of(&v)); + ::cast::transmute(addr_of(&v)); (**repr).unboxed.alloc / sys::size_of::() } } @@ -208,7 +208,7 @@ pub mod raw { */ #[inline(always)] pub unsafe fn set_len(v: @[T], new_len: uint) { - let repr: **mut VecRepr = ::cast::reinterpret_cast(&addr_of(&v)); + let repr: **mut VecRepr = ::cast::transmute(addr_of(&v)); (**repr).unboxed.fill = new_len * sys::size_of::(); } @@ -226,7 +226,7 @@ pub mod raw { #[inline(always)] // really pretty please pub unsafe fn push_fast(v: &mut @[T], initval: T) { - let repr: **mut VecRepr = ::cast::reinterpret_cast(&v); + let repr: **mut VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; (**repr).unboxed.fill += sys::size_of::(); let p = addr_of(&((**repr).unboxed.data)); @@ -322,4 +322,4 @@ mod test { assert!(from_slice([@"abc", @"123"]) == @[@"abc", @"123"]); assert!(from_slice([@[42]]) == @[@[42]]); } -} \ No newline at end of file +} diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 9fd9ac3a8c8ec..ec2658147c5a5 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -77,14 +77,14 @@ pub mod rustrt { } unsafe fn bump(ptr: *T, count: uint) -> *U { - return cast::reinterpret_cast(&ptr::offset(ptr, count)); + return cast::transmute(ptr::offset(ptr, count)); } unsafe fn align_to_pointer(ptr: *T) -> *T { let align = sys::min_align_of::<*T>(); - let ptr: uint = cast::reinterpret_cast(&ptr); + let ptr: uint = cast::transmute(ptr); let ptr = (ptr + (align - 1)) & -align; - return cast::reinterpret_cast(&ptr); + return cast::transmute(ptr); } unsafe fn get_safe_point_count() -> uint { @@ -129,8 +129,8 @@ type Visitor<'self> = &'self fn(root: **Word, tydesc: *Word) -> bool; // Walks the list of roots for the given safe point, and calls visitor // on each root. unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) { - let fp_bytes: *u8 = cast::reinterpret_cast(&fp); - let sp_meta: *u32 = cast::reinterpret_cast(&sp.sp_meta); + let fp_bytes: *u8 = cast::transmute(fp); + let sp_meta: *u32 = cast::transmute(sp.sp_meta); let num_stack_roots = *sp_meta as uint; let num_reg_roots = *ptr::offset(sp_meta, 1) as uint; @@ -171,9 +171,9 @@ unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) { // Is fp contained in segment? unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool { - let begin: Word = cast::reinterpret_cast(&segment); - let end: Word = cast::reinterpret_cast(&(*segment).end); - let frame: Word = cast::reinterpret_cast(&fp); + let begin: Word = cast::transmute(segment); + let end: Word = cast::transmute((*segment).end); + let frame: Word = cast::transmute(fp); return begin <= frame && frame <= end; } @@ -339,7 +339,7 @@ pub fn cleanup_stack_for_failure() { // own stack roots on the stack anyway. let sentinel_box = ~0; let sentinel: **Word = if expect_sentinel() { - cast::reinterpret_cast(&ptr::addr_of(&sentinel_box)) + cast::transmute(ptr::addr_of(&sentinel_box)) } else { ptr::null() }; diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 4f1edf3449412..0e7131a86f394 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -239,10 +239,10 @@ pub fn getenv(n: &str) -> Option<~str> { unsafe { do with_env_lock { let s = str::as_c_str(n, |s| libc::getenv(s)); - if ptr::null::() == cast::reinterpret_cast(&s) { + if ptr::null::() == cast::transmute(s) { option::None::<~str> } else { - let s = cast::reinterpret_cast(&s); + let s = cast::transmute(s); option::Some::<~str>(str::raw::from_buf(s)) } } @@ -644,7 +644,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool { // FIXME: turn mode into something useful? #2623 do as_utf16_p(p.to_str()) |buf| { libc::CreateDirectoryW(buf, unsafe { - cast::reinterpret_cast(&0) + cast::transmute(0) }) != (0 as libc::BOOL) } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index ebde37e77b42f..94474c3c02d62 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -86,11 +86,11 @@ pub unsafe fn position(buf: *T, f: &fn(&T) -> bool) -> uint { /// Create an unsafe null pointer #[inline(always)] -pub fn null() -> *T { unsafe { cast::reinterpret_cast(&0u) } } +pub fn null() -> *T { unsafe { cast::transmute(0u) } } /// Create an unsafe mutable null pointer #[inline(always)] -pub fn mut_null() -> *mut T { unsafe { cast::reinterpret_cast(&0u) } } +pub fn mut_null() -> *mut T { unsafe { cast::transmute(0u) } } /// Returns true if the pointer is equal to the null pointer. #[inline(always)] @@ -134,7 +134,7 @@ pub unsafe fn set_memory(dst: *mut T, c: int, count: uint) { */ #[inline(always)] pub fn to_unsafe_ptr(thing: &T) -> *T { - unsafe { cast::reinterpret_cast(&thing) } + unsafe { cast::transmute(thing) } } /** @@ -144,7 +144,7 @@ pub fn to_unsafe_ptr(thing: &T) -> *T { */ #[inline(always)] pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { - unsafe { cast::reinterpret_cast(&thing) } + unsafe { cast::transmute(thing) } } /** @@ -154,7 +154,7 @@ pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { */ #[inline(always)] pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { - unsafe { cast::reinterpret_cast(&thing) } + unsafe { cast::transmute(thing) } } /** @@ -167,7 +167,7 @@ pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { #[inline(always)] pub fn to_uint(thing: &T) -> uint { unsafe { - cast::reinterpret_cast(&thing) + cast::transmute(thing) } } @@ -259,8 +259,8 @@ impl Eq for *const T { #[inline(always)] fn eq(&self, other: &*const T) -> bool { unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); + let a: uint = cast::transmute(*self); + let b: uint = cast::transmute(*other); return a == b; } } @@ -274,32 +274,32 @@ impl Ord for *const T { #[inline(always)] fn lt(&self, other: &*const T) -> bool { unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); + let a: uint = cast::transmute(*self); + let b: uint = cast::transmute(*other); return a < b; } } #[inline(always)] fn le(&self, other: &*const T) -> bool { unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); + let a: uint = cast::transmute(*self); + let b: uint = cast::transmute(*other); return a <= b; } } #[inline(always)] fn ge(&self, other: &*const T) -> bool { unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); + let a: uint = cast::transmute(*self); + let b: uint = cast::transmute(*other); return a >= b; } } #[inline(always)] fn gt(&self, other: &*const T) -> bool { unsafe { - let a: uint = cast::reinterpret_cast(&(*self)); - let b: uint = cast::reinterpret_cast(&(*other)); + let a: uint = cast::transmute(*self); + let b: uint = cast::transmute(*other); return a > b; } } @@ -350,7 +350,7 @@ pub mod ptr_tests { struct Pair {mut fst: int, mut snd: int}; let mut p = Pair {fst: 10, snd: 20}; let pptr: *mut Pair = &mut p; - let iptr: *mut int = cast::reinterpret_cast(&pptr); + let iptr: *mut int = cast::transmute(pptr); assert!((*iptr == 10));; *iptr = 30; assert!((*iptr == 30)); diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 8b18cc3c6968c..087ee6cdf850c 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -147,7 +147,7 @@ fn with_envp(env: &Option<~[(~str,~str)]>, } ptrs.push(ptr::null()); vec::as_imm_buf(ptrs, |p, _len| - unsafe { cb(::cast::reinterpret_cast(&p)) } + unsafe { cb(::cast::transmute(p)) } ) } _ => cb(ptr::null()) @@ -167,12 +167,12 @@ fn with_envp(env: &Option<~[(~str,~str)]>, for vec::each(*es) |e| { let (k,v) = copy *e; let t = fmt!("%s=%s", k, v); - let mut v : ~[u8] = ::cast::reinterpret_cast(&t); + let mut v : ~[u8] = ::cast::transmute(t); blk += v; ::cast::forget(v); } blk += ~[0_u8]; - vec::as_imm_buf(blk, |p, _len| cb(::cast::reinterpret_cast(&p))) + vec::as_imm_buf(blk, |p, _len| cb(::cast::transmute(p))) } _ => cb(ptr::null()) } diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs index 21e75354e740c..be5f898936843 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libcore/stackwalk.rs @@ -10,7 +10,7 @@ #[doc(hidden)]; // FIXME #3538 -use cast::reinterpret_cast; +use cast::transmute; pub type Word = uint; @@ -30,16 +30,16 @@ pub fn walk_stack(visit: &fn(Frame) -> bool) { do frame_address |frame_pointer| { let mut frame_address: *Word = unsafe { - reinterpret_cast(&frame_pointer) + transmute(frame_pointer) }; loop { let fr = Frame(frame_address); - debug!("frame: %x", unsafe { reinterpret_cast(&fr.fp) }); + debug!("frame: %x", unsafe { transmute(fr.fp) }); visit(fr); unsafe { - let next_fp: **Word = reinterpret_cast(&frame_address); + let next_fp: **Word = transmute(frame_address); frame_address = *next_fp; if *frame_address == 0u { debug!("encountered task_start_wrapper. ending walk"); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d72b4a71e2a6e..f1cacc6a34868 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -121,7 +121,7 @@ pub fn push_char(s: &mut ~str, ch: char) { reserve_at_least(&mut *s, new_len); let off = len; do as_buf(*s) |buf, _len| { - let buf: *mut u8 = ::cast::reinterpret_cast(&buf); + let buf: *mut u8 = ::cast::transmute(buf); if nb == 1u { *ptr::mut_offset(buf, off) = code as u8; @@ -2023,9 +2023,9 @@ pub fn as_bytes(s: &const ~str, f: &fn(&~[u8]) -> T) -> T { */ pub fn as_bytes_slice<'a>(s: &'a str) -> &'a [u8] { unsafe { - let (ptr, len): (*u8, uint) = ::cast::reinterpret_cast(&s); + let (ptr, len): (*u8, uint) = ::cast::transmute(s); let outgoing_tuple: (*u8, uint) = (ptr, len - 1); - return ::cast::reinterpret_cast(&outgoing_tuple); + return ::cast::transmute(outgoing_tuple); } } @@ -2067,7 +2067,7 @@ pub fn as_c_str(s: &str, f: &fn(*libc::c_char) -> T) -> T { #[inline(always)] pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { unsafe { - let v : *(*u8,uint) = ::cast::reinterpret_cast(&ptr::addr_of(&s)); + let v : *(*u8,uint) = ::cast::transmute(ptr::addr_of(&s)); let (buf,len) = *v; f(buf, len) } @@ -2217,12 +2217,12 @@ pub mod raw { /// Create a Rust string from a null-terminated C string pub unsafe fn from_c_str(c_str: *libc::c_char) -> ~str { - from_buf(::cast::reinterpret_cast(&c_str)) + from_buf(::cast::transmute(c_str)) } /// Create a Rust string from a `*c_char` buffer of the given length pub unsafe fn from_c_str_len(c_str: *libc::c_char, len: uint) -> ~str { - from_buf_len(::cast::reinterpret_cast(&c_str), len) + from_buf_len(::cast::transmute(c_str), len) } /// Converts a vector of bytes to a new owned string. @@ -2246,7 +2246,7 @@ pub mod raw { pub unsafe fn buf_as_slice(buf: *u8, len: uint, f: &fn(v: &str) -> T) -> T { let v = (buf, len + 1); - assert!(is_utf8(::cast::reinterpret_cast(&v))); + assert!(is_utf8(::cast::transmute(v))); f(::cast::transmute(v)) } @@ -2294,7 +2294,7 @@ pub mod raw { assert!((end <= n)); let tuple = (ptr::offset(sbuf, begin), end - begin + 1); - ::cast::reinterpret_cast(&tuple) + ::cast::transmute(tuple) } } @@ -2303,7 +2303,7 @@ pub mod raw { let new_len = s.len() + 1; reserve_at_least(&mut *s, new_len); do as_buf(*s) |buf, len| { - let buf: *mut u8 = ::cast::reinterpret_cast(&buf); + let buf: *mut u8 = ::cast::transmute(buf); *ptr::mut_offset(buf, len) = b; } set_len(&mut *s, new_len); diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index 43f5fa4654bc7..5d1cba79c053d 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -25,8 +25,8 @@ impl LocalData for @T { } impl Eq for @LocalData { fn eq(&self, other: &@LocalData) -> bool { unsafe { - let ptr_a: (uint, uint) = cast::reinterpret_cast(&(*self)); - let ptr_b: (uint, uint) = cast::reinterpret_cast(other); + let ptr_a: (uint, uint) = cast::transmute(*self); + let ptr_b: (uint, uint) = cast::transmute(*other); return ptr_a == ptr_b; } } @@ -44,7 +44,7 @@ extern fn cleanup_task_local_map(map_ptr: *libc::c_void) { assert!(!map_ptr.is_null()); // Get and keep the single reference that was created at the // beginning. - let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr); + let _map: TaskLocalMap = cast::transmute(map_ptr); // All local_data will be destroyed along with the map. } } @@ -61,7 +61,7 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap { let map: TaskLocalMap = @mut ~[]; // Use reinterpret_cast -- transmute would take map away from us also. rt::rust_set_task_local_data( - task, cast::reinterpret_cast(&map)); + task, cast::transmute(map)); rt::rust_task_local_data_atexit(task, cleanup_task_local_map); // Also need to reference it an extra time to keep it for now. let nonmut = cast::transmute::( // own on it can be dropped when the box is destroyed. The unsafe pointer // does not have a reference associated with it, so it may become invalid // when the box is destroyed. - let data_ptr = cast::reinterpret_cast(&data); + let data_ptr = cast::transmute(data); let data_box = @data as @LocalData; // Construct new entry to store in the map. let new_entry = Some((keyval, data_ptr, data_box)); diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index c057fce0abd8c..a6bb93c20cd0b 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -121,7 +121,7 @@ impl Drop for ArcDestruct{ fn finalize(&self) { unsafe { do task::unkillable { - let mut data: ~ArcData = cast::reinterpret_cast(&self.data); + let mut data: ~ArcData = cast::transmute(self.data); let new_count = intrinsics::atomic_xsub(&mut data.count, 1) - 1; assert!(new_count >= 0); @@ -160,7 +160,7 @@ pub unsafe fn shared_mutable_state(data: T) -> pub unsafe fn get_shared_mutable_state( rc: *SharedMutableState) -> *mut T { - let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + let ptr: ~ArcData = cast::transmute((*rc).data); assert!(ptr.count > 0); let r = cast::transmute(ptr.data.get_ref()); cast::forget(ptr); @@ -169,7 +169,7 @@ pub unsafe fn get_shared_mutable_state( #[inline(always)] pub unsafe fn get_shared_immutable_state<'a,T:Owned>( rc: &'a SharedMutableState) -> &'a T { - let ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + let ptr: ~ArcData = cast::transmute((*rc).data); assert!(ptr.count > 0); // Cast us back into the correct region let r = cast::transmute_region(ptr.data.get_ref()); @@ -179,7 +179,7 @@ pub unsafe fn get_shared_immutable_state<'a,T:Owned>( pub unsafe fn clone_shared_mutable_state(rc: &SharedMutableState) -> SharedMutableState { - let mut ptr: ~ArcData = cast::reinterpret_cast(&(*rc).data); + let mut ptr: ~ArcData = cast::transmute((*rc).data); let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1; assert!(new_count >= 2); cast::forget(ptr); diff --git a/src/libcore/unstable/global.rs b/src/libcore/unstable/global.rs index 41d0842002f67..eac686e28d1c6 100644 --- a/src/libcore/unstable/global.rs +++ b/src/libcore/unstable/global.rs @@ -25,7 +25,7 @@ which case the value should be cached locally whenever possible to avoid hitting the mutex. */ -use cast::{transmute, reinterpret_cast}; +use cast::{transmute}; use clone::Clone; use kinds::Owned; use libc::{c_void}; @@ -223,7 +223,7 @@ fn get_global_state() -> Exclusive { fn key_ptr(key: GlobalDataKey) -> uint { unsafe { - let closure: Closure = reinterpret_cast(&key); + let closure: Closure = transmute(key); return transmute(closure.code); } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 04b15977665e1..1ef567e9cef01 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -279,8 +279,8 @@ pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { assert!(end <= len(v)); do as_imm_buf(v) |p, _len| { unsafe { - ::cast::reinterpret_cast( - &(ptr::offset(p, start), + ::cast::transmute( + (ptr::offset(p, start), (end - start) * sys::nonzero_size_of::())) } } @@ -294,8 +294,8 @@ pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) assert!(end <= v.len()); do as_mut_buf(v) |p, _len| { unsafe { - ::cast::reinterpret_cast( - &(ptr::mut_offset(p, start), + ::cast::transmute( + (ptr::mut_offset(p, start), (end - start) * sys::nonzero_size_of::())) } } @@ -309,8 +309,8 @@ pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint) assert!(end <= len(v)); do as_const_buf(v) |p, _len| { unsafe { - ::cast::reinterpret_cast( - &(ptr::const_offset(p, start), + ::cast::transmute( + (ptr::const_offset(p, start), (end - start) * sys::nonzero_size_of::())) } } @@ -1617,7 +1617,7 @@ pub fn as_imm_buf(s: &[T], unsafe { let v : *(*T,uint) = - ::cast::reinterpret_cast(&addr_of(&s)); + ::cast::transmute(addr_of(&s)); let (buf,len) = *v; f(buf, len / sys::nonzero_size_of::()) } @@ -1628,7 +1628,7 @@ pub fn as_imm_buf(s: &[T], pub fn as_const_buf(s: &const [T], f: &fn(*const T, uint) -> U) -> U { unsafe { let v : *(*const T,uint) = - ::cast::reinterpret_cast(&addr_of(&s)); + ::cast::transmute(addr_of(&s)); let (buf,len) = *v; f(buf, len / sys::nonzero_size_of::()) } @@ -1639,7 +1639,7 @@ pub fn as_const_buf(s: &const [T], f: &fn(*const T, uint) -> U) -> U { pub fn as_mut_buf(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { unsafe { let v : *(*mut T,uint) = - ::cast::reinterpret_cast(&addr_of(&s)); + ::cast::transmute(addr_of(&s)); let (buf,len) = *v; f(buf, len / sys::nonzero_size_of::()) } @@ -2468,21 +2468,21 @@ pub mod raw { #[inline(always)] pub unsafe fn to_ptr(v: &[T]) -> *T { let repr: **SliceRepr = ::cast::transmute(&v); - ::cast::reinterpret_cast(&addr_of(&((**repr).data))) + ::cast::transmute(addr_of(&((**repr).data))) } /** see `to_ptr()` */ #[inline(always)] pub unsafe fn to_const_ptr(v: &const [T]) -> *const T { let repr: **SliceRepr = ::cast::transmute(&v); - ::cast::reinterpret_cast(&addr_of(&((**repr).data))) + ::cast::transmute(addr_of(&((**repr).data))) } /** see `to_ptr()` */ #[inline(always)] pub unsafe fn to_mut_ptr(v: &mut [T]) -> *mut T { let repr: **SliceRepr = ::cast::transmute(&v); - ::cast::reinterpret_cast(&addr_of(&((**repr).data))) + ::cast::transmute(addr_of(&((**repr).data))) } /** @@ -2495,7 +2495,7 @@ pub mod raw { f: &fn(v: &[T]) -> U) -> U { let pair = (p, len * sys::nonzero_size_of::()); let v : *(&'blk [T]) = - ::cast::reinterpret_cast(&addr_of(&pair)); + ::cast::transmute(addr_of(&pair)); f(*v) } @@ -2509,7 +2509,7 @@ pub mod raw { f: &fn(v: &mut [T]) -> U) -> U { let pair = (p, len * sys::nonzero_size_of::()); let v : *(&'blk mut [T]) = - ::cast::reinterpret_cast(&addr_of(&pair)); + ::cast::transmute(addr_of(&pair)); f(*v) } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index b21b6b4983bd2..df61ed0e26261 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -212,7 +212,7 @@ fn get_metadata_section(os: os, let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let mut found = None; unsafe { - let cvbuf: *u8 = cast::reinterpret_cast(&cbuf); + let cvbuf: *u8 = cast::transmute(cbuf); let vlen = vec::len(encoder::metadata_encoding_version); debug!("checking %u bytes of metadata-version stamp", vlen); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index fe2461632ad76..774844c06902e 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -177,7 +177,7 @@ pub fn IndirectBr(cx: block, Addr: ValueRef, NumDests: uint) { pub fn noname() -> *libc::c_char { unsafe { static cnull: uint = 0u; - return cast::reinterpret_cast(&ptr::addr_of(&cnull)); + return cast::transmute(ptr::addr_of(&cnull)); } } @@ -834,8 +834,8 @@ pub fn Phi(cx: block, Ty: TypeRef, vals: &[ValueRef], bbs: &[BasicBlockRef]) pub fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) { unsafe { if llvm::LLVMIsUndef(phi) == lib::llvm::True { return; } - let valptr = cast::reinterpret_cast(&ptr::addr_of(&val)); - let bbptr = cast::reinterpret_cast(&ptr::addr_of(&bb)); + let valptr = cast::transmute(ptr::addr_of(&val)); + let bbptr = cast::transmute(ptr::addr_of(&bb)); llvm::LLVMAddIncoming(phi, valptr, bbptr, 1 as c_uint); } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index a2ce83c45c2e7..3180fb5a4c8f4 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1239,7 +1239,7 @@ pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef { pub fn C_bytes(bytes: &[u8]) -> ValueRef { unsafe { return llvm::LLVMConstString( - cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), + cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, True); } } @@ -1247,7 +1247,7 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef { pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef { unsafe { return llvm::LLVMConstString( - cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), + cast::transmute(vec::raw::to_ptr(bytes)), bytes.len() as c_uint, False); } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index fdd978fea3d7d..eb8209bf7a718 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -84,7 +84,7 @@ fn llunused() -> ValueRef { } fn llnull() -> ValueRef { unsafe { - cast::reinterpret_cast(&ptr::null::()) + cast::transmute(ptr::null::()) } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 32ea381c020a3..95d0fa984aea0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -337,10 +337,8 @@ pub type t = *t_opaque; pub fn get(t: t) -> t_box { unsafe { - let t2 = cast::reinterpret_cast::(&t); - let t3 = t2; - cast::forget(t2); - t3 + let t2: t_box = cast::transmute(t); + t2 } } diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 3d2c3ac70b610..6b536ff6b46e5 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -36,7 +36,7 @@ use list; use list::{List, Cons, Nil}; use core::at_vec; -use core::cast::reinterpret_cast; +use core::cast::transmute; use core::cast; use core::libc::size_t; use core::prelude::*; @@ -135,7 +135,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { let fill = chunk.fill; while idx < fill { - let tydesc_data: *uint = reinterpret_cast(&ptr::offset(buf, idx)); + let tydesc_data: *uint = transmute(ptr::offset(buf, idx)); let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data); let size = (*tydesc).size, align = (*tydesc).align; @@ -161,12 +161,12 @@ unsafe fn destroy_chunk(chunk: &Chunk) { // during an initializer. #[inline(always)] unsafe fn bitpack_tydesc_ptr(p: *TypeDesc, is_done: bool) -> uint { - let p_bits: uint = reinterpret_cast(&p); + let p_bits: uint = transmute(p); p_bits | (is_done as uint) } #[inline(always)] unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) { - (reinterpret_cast(&(p & !1)), p & 1 == 1) + (transmute(p & !1), p & 1 == 1) } pub impl Arena { @@ -207,9 +207,9 @@ pub impl Arena { unsafe { let tydesc = sys::get_type_desc::(); let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); - let ptr: *mut T = reinterpret_cast(&ptr); + let ptr: *mut T = transmute(ptr); rusti::move_val_init(&mut (*ptr), op()); - return reinterpret_cast(&ptr); + return transmute(ptr); } } @@ -221,9 +221,9 @@ pub impl Arena { unsafe { let tydesc = sys::get_type_desc::(); let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); - let ptr: *mut T = reinterpret_cast(&ptr); + let ptr: *mut T = transmute(ptr); rusti::move_val_init(&mut (*ptr), op()); - return reinterpret_cast(&ptr); + return transmute(ptr); } } @@ -268,18 +268,18 @@ pub impl Arena { let tydesc = sys::get_type_desc::(); let (ty_ptr, ptr) = self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align); - let ty_ptr: *mut uint = reinterpret_cast(&ty_ptr); - let ptr: *mut T = reinterpret_cast(&ptr); + let ty_ptr: *mut uint = transmute(ty_ptr); + let ptr: *mut T = transmute(ptr); // Write in our tydesc along with a bit indicating that it // has *not* been initialized yet. - *ty_ptr = reinterpret_cast(&tydesc); + *ty_ptr = transmute(tydesc); // Actually initialize it rusti::move_val_init(&mut(*ptr), op()); // Now that we are done, update the tydesc to indicate that // the object is there. *ty_ptr = bitpack_tydesc_ptr(tydesc, true); - return reinterpret_cast(&ptr); + return transmute(ptr); } } @@ -292,18 +292,18 @@ pub impl Arena { let tydesc = sys::get_type_desc::(); let (ty_ptr, ptr) = self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align); - let ty_ptr: *mut uint = reinterpret_cast(&ty_ptr); - let ptr: *mut T = reinterpret_cast(&ptr); + let ty_ptr: *mut uint = transmute(ty_ptr); + let ptr: *mut T = transmute(ptr); // Write in our tydesc along with a bit indicating that it // has *not* been initialized yet. - *ty_ptr = reinterpret_cast(&tydesc); + *ty_ptr = transmute(tydesc); // Actually initialize it rusti::move_val_init(&mut(*ptr), op()); // Now that we are done, update the tydesc to indicate that // the object is there. *ty_ptr = bitpack_tydesc_ptr(tydesc, true); - return reinterpret_cast(&ptr); + return transmute(ptr); } } diff --git a/src/libstd/dbg.rs b/src/libstd/dbg.rs index 9a9c19ca1768c..0b297e9e6ba72 100644 --- a/src/libstd/dbg.rs +++ b/src/libstd/dbg.rs @@ -10,7 +10,7 @@ //! Unsafe debugging functions for inspecting values. -use core::cast::reinterpret_cast; +use core::cast::transmute; use core::ptr; use core::sys; @@ -64,9 +64,9 @@ pub fn debug_fn(x: T) { } pub unsafe fn ptr_cast(x: @T) -> @U { - reinterpret_cast( - &rustrt::debug_ptrcast(sys::get_type_desc::(), - reinterpret_cast(&x))) + transmute( + rustrt::debug_ptrcast(sys::get_type_desc::(), + transmute(x))) } /// Triggers a debugger breakpoint diff --git a/src/libstd/par.rs b/src/libstd/par.rs index bb83cfc494b4c..3992cc41961d8 100644 --- a/src/libstd/par.rs +++ b/src/libstd/par.rs @@ -65,7 +65,7 @@ fn map_slices( len * sys::size_of::()); info!("pre-slice: %?", (base, slice)); let slice : &[A] = - cast::reinterpret_cast(&slice); + cast::transmute(slice); info!("slice: %?", (base, vec::len(slice), end - base)); assert!((vec::len(slice) == end - base)); diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index 890712a97085b..48ecc0fc851d3 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -839,7 +839,7 @@ pub mod node { option::Some(x) => { //FIXME (#2744): Replace with memcpy or something similar let mut local_buf: ~[u8] = - cast::reinterpret_cast(&*x.content); + cast::transmute(*x.content); let mut i = x.byte_offset; while i < x.byte_len { buf[offset] = local_buf[i]; diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 971bb51f7e9f4..2497064ae0408 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -833,7 +833,7 @@ mod tests { let ptr = ptr::addr_of(&(*sharedstate)); do task::spawn || { let sharedstate: &mut int = - unsafe { cast::reinterpret_cast(&ptr) }; + unsafe { cast::transmute(ptr) }; access_shared(sharedstate, m2, 10); c.send(()); @@ -1111,7 +1111,7 @@ mod tests { let ptr = ptr::addr_of(&(*sharedstate)); do task::spawn || { let sharedstate: &mut int = - unsafe { cast::reinterpret_cast(&ptr) }; + unsafe { cast::transmute(ptr) }; access_shared(sharedstate, &x2, mode1, 10); c.send(()); } From 276293af7c0fb901c8344e88562ce635f26f47a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Thu, 18 Apr 2013 10:01:23 +0200 Subject: [PATCH 327/403] Cleaned up case related functions a bit --- src/libcore/char.rs | 18 ++++++++++++++++-- src/libcore/str.rs | 41 +++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 6ca33540ceef6..c07a31490c346 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -234,6 +234,21 @@ pub fn escape_default(c: char) -> ~str { } } +/// Returns the amount of bytes this character would need if encoded in utf8 +pub fn len_utf8_bytes(c: char) -> uint { + static max_one_b: uint = 128u; + static max_two_b: uint = 2048u; + static max_three_b: uint = 65536u; + static max_four_b: uint = 2097152u; + + let code = c as uint; + if code < max_one_b { 1u } + else if code < max_two_b { 2u } + else if code < max_three_b { 3u } + else if code < max_four_b { 4u } + else { fail!(~"invalid character!") } +} + /** * Compare two chars * @@ -334,7 +349,6 @@ fn test_escape_default() { assert_eq!(escape_default('\U0001d4b6'), ~"\\U0001d4b6"); } - #[test] fn test_escape_unicode() { assert_eq!(escape_unicode('\x00'), ~"\\x00"); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d72b4a71e2a6e..cbdd145195304 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -789,16 +789,18 @@ pub fn each_split_within<'a>(ss: &'a str, /// Convert a string to lowercase. ASCII only pub fn to_lower(s: &str) -> ~str { - map(s, - |c| unsafe{(libc::tolower(c as libc::c_char)) as char} - ) + do map(s) |c| { + assert!(char::is_ascii(c)); + (unsafe{libc::tolower(c as libc::c_char)}) as char + } } /// Convert a string to uppercase. ASCII only pub fn to_upper(s: &str) -> ~str { - map(s, - |c| unsafe{(libc::toupper(c as libc::c_char)) as char} - ) + do map(s) |c| { + assert!(char::is_ascii(c)); + (unsafe{libc::toupper(c as libc::c_char)}) as char + } } /** @@ -3096,12 +3098,11 @@ mod tests { #[test] fn test_to_lower() { - unsafe { - assert!(~"" == map(~"", - |c| libc::tolower(c as c_char) as char)); - assert!(~"ymca" == map(~"YMCA", - |c| libc::tolower(c as c_char) as char)); - } + // libc::tolower, and hence str::to_lower + // are culturally insensitive: they only work for ASCII + // (see Issue #1347) + assert!(~"" == to_lower("")); + assert!(~"ymca" == to_lower("YMCA")); } #[test] @@ -3666,12 +3667,8 @@ mod tests { #[test] fn test_map() { - unsafe { - assert!(~"" == map(~"", |c| - libc::toupper(c as c_char) as char)); - assert!(~"YMCA" == map(~"ymca", - |c| libc::toupper(c as c_char) as char)); - } + assert!(~"" == map(~"", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert!(~"YMCA" == map(~"ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); } #[test] @@ -3685,11 +3682,11 @@ mod tests { #[test] fn test_any() { - assert!(false == any(~"", char::is_uppercase)); + assert!(false == any(~"", char::is_uppercase)); assert!(false == any(~"ymca", char::is_uppercase)); assert!(true == any(~"YMCA", char::is_uppercase)); - assert!(true == any(~"yMCA", char::is_uppercase)); - assert!(true == any(~"Ymcy", char::is_uppercase)); + assert!(true == any(~"yMCA", char::is_uppercase)); + assert!(true == any(~"Ymcy", char::is_uppercase)); } #[test] From 4357cbf2fac1e5a0d9723c1f0f9e94c831dc397c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Sat, 20 Apr 2013 10:58:54 +0200 Subject: [PATCH 328/403] Made unsafely safe functions unsafe again, for safety --- src/libcore/str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index cbdd145195304..2296fea045471 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -2319,20 +2319,20 @@ pub mod raw { } /// Removes the last byte from a string and returns it. (Not UTF-8 safe). - pub fn pop_byte(s: &mut ~str) -> u8 { + pub unsafe fn pop_byte(s: &mut ~str) -> u8 { let len = len(*s); assert!((len > 0u)); let b = s[len - 1u]; - unsafe { set_len(s, len - 1u) }; + set_len(s, len - 1u); return b; } /// Removes the first byte from a string and returns it. (Not UTF-8 safe). - pub fn shift_byte(s: &mut ~str) -> u8 { + pub unsafe fn shift_byte(s: &mut ~str) -> u8 { let len = len(*s); assert!((len > 0u)); let b = s[0]; - *s = unsafe { raw::slice_bytes_owned(*s, 1u, len) }; + *s = raw::slice_bytes_owned(*s, 1u, len); return b; } From 61ffee738d505328fae14ac7c53bc388c69c5938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Sat, 20 Apr 2013 19:39:15 +0200 Subject: [PATCH 329/403] Added Ascii type --- src/libcore/prelude.rs | 7 +- src/libcore/str.rs | 17 ++- src/libcore/str/ascii.rs | 216 +++++++++++++++++++++++++++++++++++++++ src/libcore/to_str.rs | 6 ++ 4 files changed, 243 insertions(+), 3 deletions(-) create mode 100644 src/libcore/str/ascii.rs diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 822fb2e476beb..8479369458258 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -40,9 +40,14 @@ pub use path::Path; pub use path::PosixPath; pub use path::WindowsPath; pub use ptr::Ptr; +// NOTE: Remove markers after snapshot +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub use str::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii}; pub use str::{StrSlice, OwnedStr}; pub use to_bytes::IterBytes; -pub use to_str::ToStr; +pub use to_str::{ToStr, ToStrConsume}; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use vec::{CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 2296fea045471..11301c9f1dbdb 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -17,6 +17,12 @@ * some heavy-duty uses, try std::rope. */ +// NOTE: Remove markers after snapshot +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub use self::ascii::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii}; + use at_vec; use cast; use char; @@ -34,6 +40,13 @@ use to_str::ToStr; #[cfg(notest)] use cmp::{Eq, Ord, Equiv, TotalEq}; +// NOTE: Remove markers after snapshot +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +#[path = "str/ascii.rs"] +mod ascii; + /* Section: Creating a string */ @@ -3347,7 +3360,7 @@ mod tests { #[test] fn test_shift_byte() { let mut s = ~"ABC"; - let b = raw::shift_byte(&mut s); + let b = unsafe{raw::shift_byte(&mut s)}; assert!((s == ~"BC")); assert!((b == 65u8)); } @@ -3355,7 +3368,7 @@ mod tests { #[test] fn test_pop_byte() { let mut s = ~"ABC"; - let b = raw::pop_byte(&mut s); + let b = unsafe{raw::pop_byte(&mut s)}; assert!((s == ~"AB")); assert!((b == 67u8)); } diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs new file mode 100644 index 0000000000000..1e882daeef991 --- /dev/null +++ b/src/libcore/str/ascii.rs @@ -0,0 +1,216 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use to_str::{ToStr,ToStrConsume}; +use str; +use cast; + +#[cfg(test)] +pub struct Ascii { priv chr: u8 } + +/// Datatype to hold one ascii character. It is 8 bit long. +#[cfg(notest)] +#[deriving(Clone, Eq, Ord)] +pub struct Ascii { priv chr: u8 } + +pub impl Ascii { + /// Converts a ascii character into a `u8`. + fn to_byte(self) -> u8 { + self.chr + } + + /// Converts a ascii character into a `char`. + fn to_char(self) -> char { + self.chr as char + } +} + +impl ToStr for Ascii { + fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) } +} + +/// Trait for converting into an ascii type. +pub trait AsciiCast { + /// Convert to an ascii type + fn to_ascii(&self) -> T; + + /// Check if convertible to ascii + fn is_ascii(&self) -> bool; +} + +impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { + fn to_ascii(&self) -> &'self[Ascii] { + assert!(self.is_ascii()); + + unsafe{ cast::transmute(*self) } + } + + fn is_ascii(&self) -> bool { + for self.each |b| { + if !b.is_ascii() { return false; } + } + true + } +} + +impl<'self> AsciiCast<&'self[Ascii]> for &'self str { + fn to_ascii(&self) -> &'self[Ascii] { + assert!(self.is_ascii()); + + let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) }; + unsafe{ cast::transmute((p, len - 1))} + } + + fn is_ascii(&self) -> bool { + for self.each |b| { + if !b.is_ascii() { return false; } + } + true + } +} + +impl AsciiCast for u8 { + fn to_ascii(&self) -> Ascii { + assert!(self.is_ascii()); + Ascii{ chr: *self } + } + + fn is_ascii(&self) -> bool { + *self & 128 == 0u8 + } +} + +impl AsciiCast for char { + fn to_ascii(&self) -> Ascii { + assert!(self.is_ascii()); + Ascii{ chr: *self as u8 } + } + + fn is_ascii(&self) -> bool { + *self - ('\x7F' & *self) == '\x00' + } +} + +/// Trait for copyless casting to an ascii vector. +pub trait OwnedAsciiCast { + /// Take ownership and cast to an ascii vector without trailing zero element. + fn to_ascii_consume(self) -> ~[Ascii]; +} + +impl OwnedAsciiCast for ~[u8] { + fn to_ascii_consume(self) -> ~[Ascii] { + assert!(self.is_ascii()); + + unsafe {cast::transmute(self)} + } +} + +impl OwnedAsciiCast for ~str { + fn to_ascii_consume(self) -> ~[Ascii] { + let mut s = self; + unsafe { + str::raw::pop_byte(&mut s); + cast::transmute(s) + } + } +} + +/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str` +pub trait ToStrAscii { + /// Convert to a string. + fn to_str_ascii(&self) -> ~str; +} + +impl<'self> ToStrAscii for &'self [Ascii] { + fn to_str_ascii(&self) -> ~str { + let mut cpy = self.to_owned(); + cpy.push(0u8.to_ascii()); + unsafe {cast::transmute(cpy)} + } +} + +impl ToStrConsume for ~[Ascii] { + fn to_str_consume(self) -> ~str { + let mut cpy = self; + cpy.push(0u8.to_ascii()); + unsafe {cast::transmute(cpy)} + } +} + +// NOTE: Remove stage0 marker after snapshot +#[cfg(and(test, not(stage0)))] +mod tests { + use super::*; + use to_str::{ToStr,ToStrConsume}; + use str; + use cast; + + macro_rules! v2ascii ( + ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); + (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]); + ) + + #[test] + fn test_ascii() { + assert_eq!(65u8.to_ascii().to_byte(), 65u8); + assert_eq!(65u8.to_ascii().to_char(), 'A'); + assert_eq!('A'.to_ascii().to_char(), 'A'); + assert_eq!('A'.to_ascii().to_byte(), 65u8); + } + + #[test] + fn test_ascii_vec() { + assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59])); + assert_eq!("( ;".to_ascii(), v2ascii!([40, 32, 59])); + // FIXME: #5475 borrowchk error, owned vectors do not live long enough + // if chained-from directly + let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); + let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); + } + + #[test] + fn test_owned_ascii_vec() { + // FIXME: #4318 Compiler crashes on moving self + //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59])); + //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59])); + //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0])); + //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(), + // v2ascii!(~[40, 32, 59, 0])); + } + + #[test] + fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); } + + #[test] + fn test_ascii_to_str_consume() { + // FIXME: #4318 Compiler crashes on moving self + //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;"); + } + + #[test] #[should_fail] + fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); } + + #[test] #[should_fail] + fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } +} + + + + + + + + diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 980d4b445d04d..7f8e6915add16 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -20,6 +20,12 @@ pub trait ToStr { fn to_str(&self) -> ~str; } +/// Trait for converting a type to a string, consuming it in the process. +pub trait ToStrConsume { + // Cosume and convert to a string. + fn to_str_consume(self) -> ~str; +} + impl ToStr for bool { #[inline(always)] fn to_str(&self) -> ~str { ::bool::to_str(*self) } From 7ca216d7500c8e7e0226aeb8baca7f0e588cd120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Sat, 20 Apr 2013 22:50:50 +0200 Subject: [PATCH 330/403] Added case functions to Ascii --- src/libcore/str/ascii.rs | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 1e882daeef991..22303ef0ddc21 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -22,17 +22,46 @@ pub struct Ascii { priv chr: u8 } pub impl Ascii { /// Converts a ascii character into a `u8`. + #[inline(always)] fn to_byte(self) -> u8 { self.chr } /// Converts a ascii character into a `char`. + #[inline(always)] fn to_char(self) -> char { self.chr as char } + + /// Convert to lowercase. + #[inline(always)] + fn to_lower(self) -> Ascii { + if self.chr >= 65 && self.chr <= 90 { + Ascii{chr: self.chr | 0x20 } + } else { + self + } + } + + /// Convert to uppercase. + #[inline(always)] + fn to_upper(self) -> Ascii { + if self.chr >= 97 && self.chr <= 122 { + Ascii{chr: self.chr & !0x20 } + } else { + self + } + } + + // Compares two ascii characters of equality, ignoring case. + #[inline(always)] + fn eq_ignore_case(self, other: Ascii) -> bool { + self.to_lower().chr == other.to_lower().chr + } } impl ToStr for Ascii { + #[inline(always)] fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) } } @@ -46,12 +75,14 @@ pub trait AsciiCast { } impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { + #[inline(always)] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); unsafe{ cast::transmute(*self) } } + #[inline(always)] fn is_ascii(&self) -> bool { for self.each |b| { if !b.is_ascii() { return false; } @@ -61,6 +92,7 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { } impl<'self> AsciiCast<&'self[Ascii]> for &'self str { + #[inline(always)] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); @@ -68,6 +100,7 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str { unsafe{ cast::transmute((p, len - 1))} } + #[inline(always)] fn is_ascii(&self) -> bool { for self.each |b| { if !b.is_ascii() { return false; } @@ -77,22 +110,27 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str { } impl AsciiCast for u8 { + #[inline(always)] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); Ascii{ chr: *self } } + #[inline(always)] fn is_ascii(&self) -> bool { *self & 128 == 0u8 } } impl AsciiCast for char { + + #[inline(always)] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); Ascii{ chr: *self as u8 } } + #[inline(always)] fn is_ascii(&self) -> bool { *self - ('\x7F' & *self) == '\x00' } @@ -105,6 +143,7 @@ pub trait OwnedAsciiCast { } impl OwnedAsciiCast for ~[u8] { + #[inline(always)] fn to_ascii_consume(self) -> ~[Ascii] { assert!(self.is_ascii()); @@ -113,6 +152,7 @@ impl OwnedAsciiCast for ~[u8] { } impl OwnedAsciiCast for ~str { + #[inline(always)] fn to_ascii_consume(self) -> ~[Ascii] { let mut s = self; unsafe { @@ -129,6 +169,7 @@ pub trait ToStrAscii { } impl<'self> ToStrAscii for &'self [Ascii] { + #[inline(always)] fn to_str_ascii(&self) -> ~str { let mut cpy = self.to_owned(); cpy.push(0u8.to_ascii()); @@ -137,6 +178,7 @@ impl<'self> ToStrAscii for &'self [Ascii] { } impl ToStrConsume for ~[Ascii] { + #[inline(always)] fn to_str_consume(self) -> ~str { let mut cpy = self; cpy.push(0u8.to_ascii()); @@ -163,6 +205,16 @@ mod tests { assert_eq!(65u8.to_ascii().to_char(), 'A'); assert_eq!('A'.to_ascii().to_char(), 'A'); assert_eq!('A'.to_ascii().to_byte(), 65u8); + + assert_eq!('A'.to_ascii().to_lower().to_char, 'a'); + assert_eq!('Z'.to_ascii().to_lower().to_char, 'z'); + assert_eq!('a'.to_ascii().to_upper().to_char, 'A'); + assert_eq!('z'.to_ascii().to_upper().to_char, 'Z'); + + assert_eq!('@'.to_ascii().to_lower().to_char, '@'); + assert_eq!('['.to_ascii().to_lower().to_char, '['); + assert_eq!('`'.to_ascii().to_upper().to_char, '`'); + assert_eq!('{'.to_ascii().to_upper().to_char, '{'); } #[test] From df61ec2da6c4bb6e77ec15d0e5a60e4122b79d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Sat, 20 Apr 2013 22:54:13 +0200 Subject: [PATCH 331/403] Corrected history --- src/libcore/str/ascii.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 22303ef0ddc21..7de62a2c9347c 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // From d1985c9dd06379b8a173239e90007db926ec052e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Apr 2013 01:09:54 -0400 Subject: [PATCH 332/403] Implement a lint mode to deal with unused 'mut' variables --- src/librustc/middle/borrowck/check_loans.rs | 13 ++++- src/librustc/middle/borrowck/loan.rs | 14 ++++- src/librustc/middle/lint.rs | 57 +++++++++++++++++++ src/librustc/middle/liveness.rs | 43 ++++++++------ src/librustc/middle/mem_categorization.rs | 10 ++++ src/librustc/middle/ty.rs | 6 ++ src/test/compile-fail/unused-mut-variables.rs | 42 ++++++++++++++ 7 files changed, 164 insertions(+), 21 deletions(-) create mode 100644 src/test/compile-fail/unused-mut-variables.rs diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 4766fe1fb94a9..6f3075717ed86 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -367,7 +367,18 @@ pub impl CheckLoanCtxt { // are only assigned once } else { match cmt.mutbl { - McDeclared | McInherited => { /*ok*/ } + McDeclared | McInherited => { + // Ok, but if this loan is a mutable loan, then mark the + // loan path (if it exists) as being used. This is similar + // to the check performed in loan.rs in issue_loan(). This + // type of use of mutable is different from issuing a loan, + // however. + for cmt.lp.each |lp| { + for lp.node_id().each |&id| { + self.tcx().used_mut_nodes.insert(id); + } + } + } McReadOnly | McImmutable => { self.bccx.span_err( ex.span, diff --git a/src/librustc/middle/borrowck/loan.rs b/src/librustc/middle/borrowck/loan.rs index 15189a552fb0c..3c37b5dae64a2 100644 --- a/src/librustc/middle/borrowck/loan.rs +++ b/src/librustc/middle/borrowck/loan.rs @@ -51,7 +51,7 @@ use middle::mem_categorization::{cat_arg, cat_binding, cat_discr, cat_comp}; use middle::mem_categorization::{cat_deref, cat_discr, cat_local, cat_self}; use middle::mem_categorization::{cat_special, cat_stack_upvar, cmt}; use middle::mem_categorization::{comp_field, comp_index, comp_variant}; -use middle::mem_categorization::{gc_ptr, region_ptr}; +use middle::mem_categorization::{gc_ptr, region_ptr, lp_local, lp_arg}; use middle::ty; use util::common::indenter; @@ -274,7 +274,17 @@ pub impl LoanContext { if !owns_lent_data || self.bccx.is_subregion_of(self.scope_region, scope_ub) { - if loan_kind.is_take() && !cmt.mutbl.is_mutable() { + if cmt.mutbl.is_mutable() { + // If this loan is a mutable loan, then mark the loan path (if + // it exists) as being used. This is similar to the check + // performed in check_loans.rs in check_assignment(), but this + // is for a different purpose of having the 'mut' qualifier. + for cmt.lp.each |lp| { + for lp.node_id().each |&id| { + self.tcx().used_mut_nodes.insert(id); + } + } + } else if loan_kind.is_take() { // We do not allow non-mutable data to be "taken" // under any circumstances. return Err(bckerr { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 9087afe596937..bda97f4f530d1 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -13,6 +13,7 @@ use core::prelude::*; use driver::session::Session; use driver::session; use middle::ty; +use middle::pat_util; use util::ppaux::{ty_to_str}; use core::hashmap::HashMap; @@ -86,6 +87,7 @@ pub enum lint { unused_variable, dead_assignment, + unused_mut, } pub fn level_to_str(lv: level) -> &'static str { @@ -277,6 +279,13 @@ pub fn get_lint_dict() -> LintDict { desc: "detect assignments that will never be read", default: warn }), + + (~"unused_mut", + LintSpec { + lint: unused_mut, + desc: "detect mut variables which don't need to be mutable", + default: warn + }), ]; let mut map = HashMap::new(); do vec::consume(v) |_, (k, v)| { @@ -499,6 +508,7 @@ fn check_item(i: @ast::item, cx: ty::ctxt) { check_item_deprecated_mutable_fields(cx, i); check_item_deprecated_drop(cx, i); check_item_unused_unsafe(cx, i); + check_item_unused_mut(cx, i); } // Take a visitor, and modify it so that it will not proceed past subitems. @@ -954,6 +964,53 @@ fn check_item_unused_unsafe(cx: ty::ctxt, it: @ast::item) { visit::visit_item(it, (), visit); } +fn check_item_unused_mut(tcx: ty::ctxt, it: @ast::item) { + let check_pat: @fn(@ast::pat) = |p| { + let mut used = false; + let mut bindings = 0; + do pat_util::pat_bindings(tcx.def_map, p) |_, id, _, _| { + used = used || tcx.used_mut_nodes.contains(&id); + bindings += 1; + } + if !used { + let msg = if bindings == 1 { + ~"variable does not need to be mutable" + } else { + ~"variables do not need to be mutable" + }; + tcx.sess.span_lint(unused_mut, p.id, it.id, p.span, msg); + } + }; + + let visit_fn_decl: @fn(&ast::fn_decl) = |fd| { + for fd.inputs.each |arg| { + if arg.is_mutbl { + check_pat(arg.pat); + } + } + }; + + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_local: |l| { + if l.node.is_mutbl { + check_pat(l.node.pat); + } + }, + visit_fn: |_, fd, _, _, _| visit_fn_decl(fd), + visit_ty_method: |tm| visit_fn_decl(&tm.decl), + visit_struct_method: |sm| visit_fn_decl(&sm.decl), + visit_trait_method: |tm| { + match *tm { + ast::required(ref tm) => visit_fn_decl(&tm.decl), + ast::provided(m) => visit_fn_decl(&m.decl), + } + }, + .. *visit::default_simple_visitor() + })); + visit::visit_item(it, (), visit); +} + fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl, _body: &ast::blk, span: span, id: ast::node_id) { debug!("lint check_fn fk=%? id=%?", fk, id); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3136d7bf4e4ac..2b36ce4ce031a 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1516,9 +1516,8 @@ fn check_local(local: @local, self: @Liveness, vt: vt<@Liveness>) { // Initializer: self.warn_about_unused_or_dead_vars_in_pat(local.node.pat); - if !local.node.is_mutbl { - self.check_for_reassignments_in_pat(local.node.pat); - } + self.check_for_reassignments_in_pat(local.node.pat, + local.node.is_mutbl); } None => { @@ -1702,12 +1701,15 @@ pub impl Liveness { match expr.node { expr_path(_) => { match *self.tcx.def_map.get(&expr.id) { - def_local(nid, false) => { - // Assignment to an immutable variable or argument: - // only legal if there is no later assignment. + def_local(nid, mutbl) => { + // Assignment to an immutable variable or argument: only legal + // if there is no later assignment. If this local is actually + // mutable, then check for a reassignment to flag the mutability + // as being used. let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); - self.check_for_reassignment(ln, var, expr.span); + self.check_for_reassignment(ln, var, expr.span, + if mutbl {Some(nid)} else {None}); self.warn_about_dead_assign(expr.span, expr.id, ln, var); } def => { @@ -1731,23 +1733,28 @@ pub impl Liveness { } } - fn check_for_reassignments_in_pat(@self, pat: @pat) { - do self.pat_bindings(pat) |ln, var, sp, _id| { - self.check_for_reassignment(ln, var, sp); + fn check_for_reassignments_in_pat(@self, pat: @pat, mutbl: bool) { + do self.pat_bindings(pat) |ln, var, sp, id| { + self.check_for_reassignment(ln, var, sp, + if mutbl {Some(id)} else {None}); } } fn check_for_reassignment(@self, ln: LiveNode, var: Variable, - orig_span: span) { + orig_span: span, mutbl: Option) { match self.assigned_on_exit(ln, var) { Some(ExprNode(span)) => { - self.tcx.sess.span_err( - span, - ~"re-assignment of immutable variable"); - - self.tcx.sess.span_note( - orig_span, - ~"prior assignment occurs here"); + match mutbl { + Some(id) => { self.tcx.used_mut_nodes.insert(id); } + None => { + self.tcx.sess.span_err( + span, + ~"re-assignment of immutable variable"); + self.tcx.sess.span_note( + orig_span, + ~"prior assignment occurs here"); + } + } } Some(lnk) => { self.tcx.sess.span_bug( diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 6473cb8e8e006..51e6860432a2e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -351,6 +351,16 @@ pub impl MutabilityCategory { } } +pub impl loan_path { + fn node_id(&self) -> Option { + match *self { + lp_local(id) | lp_arg(id) => Some(id), + lp_deref(lp, _) | lp_comp(lp, _) => lp.node_id(), + lp_self => None + } + } +} + pub impl mem_categorization_ctxt { fn cat_expr(&self, expr: @ast::expr) -> cmt { match self.tcx.adjustments.find(&expr.id) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 95d0fa984aea0..be362904dc42d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -304,6 +304,11 @@ struct ctxt_ { // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. used_unsafe: @mut HashSet, + + // Set of nodes which mark locals as mutable which end up getting used at + // some point. Local variable definitions not in this set can be warned + // about. + used_mut_nodes: @mut HashSet, } pub enum tbox_flag { @@ -933,6 +938,7 @@ pub fn mk_ctxt(s: session::Session, destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), + used_mut_nodes: @mut HashSet::new(), } } diff --git a/src/test/compile-fail/unused-mut-variables.rs b/src/test/compile-fail/unused-mut-variables.rs new file mode 100644 index 0000000000000..d1223cd889307 --- /dev/null +++ b/src/test/compile-fail/unused-mut-variables.rs @@ -0,0 +1,42 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Exercise the unused_mut attribute in some positive and negative cases + +#[allow(dead_assignment)]; +#[allow(unused_variable)]; +#[deny(unused_mut)]; + +fn main() { + // negative cases + let mut a = 3; //~ ERROR: variable does not need to be mutable + let mut a = 2, b = 3; //~ ERROR: variable does not need to be mutable + //~^ ERROR: variable does not need to be mutable + let mut a = ~[3]; //~ ERROR: variable does not need to be mutable + + // positive cases + let mut a = 2; + a = 3; + let mut a = ~[]; + a.push(3); + let mut a = ~[]; + do callback { + a.push(3); + } +} + +fn callback(f: &fn()) {} + +// make sure the lint attribute can be turned off +#[allow(unused_mut)] +fn foo(mut a: int) { + let mut a = 3; + let mut b = ~[2]; +} From 13537d2e0ce54f88909e6f44006254490ae1d1ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Apr 2013 01:10:01 -0400 Subject: [PATCH 333/403] core: remove unused 'mut' variables --- src/libcore/cell.rs | 2 +- src/libcore/flate.rs | 2 +- src/libcore/path.rs | 2 +- src/libcore/rand.rs | 2 +- src/libcore/repr.rs | 4 ++-- src/libcore/rt/uv/mod.rs | 2 +- src/libcore/rt/uv/net.rs | 2 +- src/libcore/rt/uvio.rs | 2 +- src/libcore/run.rs | 2 +- src/libcore/str.rs | 6 +++--- src/libcore/task/spawn.rs | 2 +- src/libcore/unstable/extfmt.rs | 4 ++-- src/libcore/vec.rs | 4 ++-- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 1707bddc2b9d4..79125a67aa74e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -121,7 +121,7 @@ fn test_with_ref() { #[test] fn test_with_mut_ref() { let good = ~[1, 2, 3]; - let mut v = ~[1, 2]; + let v = ~[1, 2]; let c = Cell(v); do c.with_mut_ref() |v| { v.push(3); } let v = c.take(); diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs index a4f12f7da7e2e..70c96c9c806e4 100644 --- a/src/libcore/flate.rs +++ b/src/libcore/flate.rs @@ -67,7 +67,7 @@ pub fn deflate_bytes(bytes: &const [u8]) -> ~[u8] { pub fn inflate_bytes(bytes: &const [u8]) -> ~[u8] { do vec::as_const_buf(bytes) |b, len| { unsafe { - let mut outsz : size_t = 0; + let outsz : size_t = 0; let res = rustrt::tinfl_decompress_mem_to_heap(b as *c_void, len as size_t, diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 0e8dbd144b143..dbed4b8e0bf02 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -844,7 +844,7 @@ pub mod windows { while i < s.len() { if is_sep(s[i]) { let pre = s.slice(2, i).to_owned(); - let mut rest = s.slice(i, s.len()).to_owned(); + let rest = s.slice(i, s.len()).to_owned(); return Some((pre, rest)); } i += 1; diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 0a93a651a8572..89062ff465bfa 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -693,7 +693,7 @@ struct XorShiftState { impl Rng for XorShiftState { fn next(&self) -> u32 { let x = self.x; - let mut t = x ^ (x << 11); + let t = x ^ (x << 11); self.x = self.y; self.y = self.z; self.z = self.w; diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index ca67e6366b5f4..03e44e00d8831 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -210,7 +210,7 @@ pub impl ReprVisitor { #[inline(always)] fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { - let mut u = ReprVisitor(ptr, self.writer); + let u = ReprVisitor(ptr, self.writer); let v = reflect::MovePtrAdaptor(u); visit_tydesc(inner, @v as @TyVisitor); true @@ -667,7 +667,7 @@ pub fn write_repr(writer: @Writer, object: &T) { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *c_void; let tydesc = intrinsic::get_tydesc::(); - let mut u = ReprVisitor(ptr, writer); + let u = ReprVisitor(ptr, writer); let v = reflect::MovePtrAdaptor(u); visit_tydesc(tydesc, @v as @TyVisitor) } diff --git a/src/libcore/rt/uv/mod.rs b/src/libcore/rt/uv/mod.rs index 32757d6376e73..4cbc8d7056970 100644 --- a/src/libcore/rt/uv/mod.rs +++ b/src/libcore/rt/uv/mod.rs @@ -402,7 +402,7 @@ fn loop_smoke_test() { fn idle_new_then_close() { do run_in_bare_thread { let mut loop_ = Loop::new(); - let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; + let idle_watcher = { IdleWatcher::new(&mut loop_) }; idle_watcher.close(); } } diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index b4a08c1492894..bcfe8b2cfdf9f 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -393,7 +393,7 @@ fn connect_read() { let buf = vec_from_uv_buf(buf); rtdebug!("read cb!"); if status.is_none() { - let bytes = buf.unwrap(); + let _bytes = buf.unwrap(); rtdebug!("%s", bytes.slice(0, nread as uint).to_str()); } else { rtdebug!("status after read: %s", status.get().to_str()); diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index ff5397398354a..d4e547de3837b 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -206,7 +206,7 @@ impl TcpListener for UvTcpListener { let mut server_stream_watcher = server_stream_watcher; let mut loop_ = loop_from_watcher(&server_stream_watcher); let mut client_tcp_watcher = TcpWatcher::new(&mut loop_); - let mut client_tcp_watcher = client_tcp_watcher.as_stream(); + let client_tcp_watcher = client_tcp_watcher.as_stream(); // XXX: Need's to be surfaced in interface server_stream_watcher.accept(client_tcp_watcher); Some(~UvStream::new(client_tcp_watcher)) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 087ee6cdf850c..f9d7f4a229c42 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -343,7 +343,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); } } - let mut repr = ProgRepr { + let repr = ProgRepr { pid: pid, in_fd: pipe_input.out, out_file: os::fdopen(pipe_output.in), diff --git a/src/libcore/str.rs b/src/libcore/str.rs index f1cacc6a34868..38d68175679ca 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -673,7 +673,7 @@ pub fn levdistance(s: &str, t: &str) -> uint { for t.each_chari |j, tc| { - let mut next = dcol[j + 1]; + let next = dcol[j + 1]; if sc == tc { dcol[j + 1] = current; @@ -909,7 +909,7 @@ impl TotalOrd for @str { /// Bytewise slice less than fn lt(a: &str, b: &str) -> bool { let (a_len, b_len) = (a.len(), b.len()); - let mut end = uint::min(a_len, b_len); + let end = uint::min(a_len, b_len); let mut i = 0; while i < end { @@ -1715,7 +1715,7 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) { let len = vec::len(v); let mut i = 0u; while (i < len && v[i] != 0u16) { - let mut u = v[i]; + let u = v[i]; if u <= 0xD7FF_u16 || u >= 0xE000_u16 { f(u as char); diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 118c4cc23125b..d872d38a27801 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -575,7 +575,7 @@ fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) { }; assert!(!new_task.is_null()); // Getting killed after here would leak the task. - let mut notify_chan = if opts.notify_chan.is_none() { + let notify_chan = if opts.notify_chan.is_none() { None } else { Some(opts.notify_chan.swap_unwrap()) diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs index ad3dce0a74992..ee33e2ed20bba 100644 --- a/src/libcore/unstable/extfmt.rs +++ b/src/libcore/unstable/extfmt.rs @@ -538,7 +538,7 @@ pub mod rt { pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) { // For strings, precision is the maximum characters // displayed - let mut unpadded = match cv.precision { + let unpadded = match cv.precision { CountImplied => s, CountIs(max) => if (max as uint) < str::char_len(s) { str::slice(s, 0, max as uint) @@ -596,7 +596,7 @@ pub mod rt { #[deriving(Eq)] pub enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat } - pub fn pad(cv: Conv, mut s: &str, head: Option, mode: PadMode, + pub fn pad(cv: Conv, s: &str, head: Option, mode: PadMode, buf: &mut ~str) { let headsize = match head { Some(_) => 1, _ => 0 }; let uwidth : uint = match cv.width { diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 1ef567e9cef01..e478936ff65cc 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1755,7 +1755,7 @@ impl TotalOrd for @[T] { fn lt(a: &[T], b: &[T]) -> bool { let (a_len, b_len) = (a.len(), b.len()); - let mut end = uint::min(a_len, b_len); + let end = uint::min(a_len, b_len); let mut i = 0; while i < end { @@ -3897,7 +3897,7 @@ mod tests { #[test] fn reversed_mut() { - let mut v2 = reversed::(~[10, 20]); + let v2 = reversed::(~[10, 20]); assert!(v2[0] == 20); assert!(v2[1] == 10); } From 7d317fe7e584832f4aac113d3d5d19d90536c081 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Apr 2013 01:10:12 -0400 Subject: [PATCH 334/403] std: remove unused 'mut' variables --- src/libstd/bitv.rs | 2 +- src/libstd/deque.rs | 8 ++++---- src/libstd/dlist.rs | 8 ++++---- src/libstd/num/rational.rs | 4 ++-- src/libstd/rope.rs | 5 ++--- src/libstd/sha1.rs | 4 ++-- src/libstd/sort.rs | 4 ++-- src/libstd/test.rs | 3 +-- src/libstd/time.rs | 4 ++-- 9 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index d89ce4232b175..d1f6bf982a7ff 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -891,7 +891,7 @@ mod tests { #[test] fn test_0_elements() { let mut act; - let mut exp; + let exp; act = Bitv::new(0u, false); exp = vec::from_elem::(0u, 0u); assert!(act.eq_vec(exp)); diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs index a88d13fda6621..b120e40ec25ca 100644 --- a/src/libstd/deque.rs +++ b/src/libstd/deque.rs @@ -113,7 +113,7 @@ pub impl Deque { /// /// Fails if the deque is empty fn pop_front(&mut self) -> T { - let mut result = self.elts[self.lo].swap_unwrap(); + let result = self.elts[self.lo].swap_unwrap(); self.lo = (self.lo + 1u) % self.elts.len(); self.nelts -= 1u; result @@ -126,7 +126,7 @@ pub impl Deque { if self.hi == 0u { self.hi = self.elts.len() - 1u; } else { self.hi -= 1u; } - let mut result = self.elts[self.hi].swap_unwrap(); + let result = self.elts[self.hi].swap_unwrap(); self.elts[self.hi] = None; self.nelts -= 1u; result @@ -204,7 +204,7 @@ pub impl Deque { /// /// Fails if the deque is empty fn pop_front(&mut self) -> T { - let mut result = self.elts[self.lo].swap_unwrap(); + let result = self.elts[self.lo].swap_unwrap(); self.lo = (self.lo + 1u) % self.elts.len(); self.nelts -= 1u; result @@ -217,7 +217,7 @@ pub impl Deque { if self.hi == 0u { self.hi = self.elts.len() - 1u; } else { self.hi -= 1u; } - let mut result = self.elts[self.hi].swap_unwrap(); + let result = self.elts[self.hi].swap_unwrap(); self.elts[self.hi] = None; self.nelts -= 1u; result diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs index f9de2e0f58ad0..e736273a5eed1 100644 --- a/src/libstd/dlist.rs +++ b/src/libstd/dlist.rs @@ -220,7 +220,7 @@ pub impl DList { * node. O(1). */ fn push_head_n(@mut self, data: T) -> @mut DListNode { - let mut nobe = DList::new_link(data); + let nobe = DList::new_link(data); self.add_head(nobe); nobe.get() } @@ -233,7 +233,7 @@ pub impl DList { * node. O(1). */ fn push_n(@mut self, data: T) -> @mut DListNode { - let mut nobe = DList::new_link(data); + let nobe = DList::new_link(data); self.add_tail(nobe); nobe.get() } @@ -263,7 +263,7 @@ pub impl DList { data: T, neighbour: @mut DListNode ) -> @mut DListNode { - let mut nobe = DList::new_link(data); + let nobe = DList::new_link(data); self.insert_left(nobe, neighbour); nobe.get() } @@ -293,7 +293,7 @@ pub impl DList { data: T, neighbour: @mut DListNode ) -> @mut DListNode { - let mut nobe = DList::new_link(data); + let nobe = DList::new_link(data); self.insert_right(neighbour, nobe); nobe.get() } diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs index f15b382dcd351..b171bd6e2a963 100644 --- a/src/libstd/num/rational.rs +++ b/src/libstd/num/rational.rs @@ -60,7 +60,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq> /// Put self into lowest terms, with denom > 0. fn reduce(&mut self) { - let mut g : T = gcd(self.numer, self.denom); + let g : T = gcd(self.numer, self.denom); self.numer /= g; self.denom /= g; @@ -508,4 +508,4 @@ mod test { test(s); } } -} \ No newline at end of file +} diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index 48ecc0fc851d3..33bc393e4703a 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -838,8 +838,7 @@ pub mod node { option::None => break, option::Some(x) => { //FIXME (#2744): Replace with memcpy or something similar - let mut local_buf: ~[u8] = - cast::transmute(*x.content); + let local_buf: ~[u8] = cast::transmute(*x.content); let mut i = x.byte_offset; while i < x.byte_len { buf[offset] = local_buf[i]; @@ -1156,7 +1155,7 @@ pub mod node { } pub fn empty() -> T { - let mut stack : ~[@Node] = ~[]; + let stack : ~[@Node] = ~[]; T { stack: stack, stackpos: -1 } } diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index 6aa4d1c54bc9e..7371250b38a91 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -93,7 +93,7 @@ pub fn sha1() -> @Sha1 { assert!((vec::len(st.h) == digest_buf_len)); assert!((vec::uniq_len(st.work_buf) == work_buf_len)); let mut t: int; // Loop counter - let mut w = st.work_buf; + let w = st.work_buf; // Initialize the first 16 words of the vector w t = 0; @@ -260,7 +260,7 @@ pub fn sha1() -> @Sha1 { return s; } } - let mut st = Sha1State { + let st = Sha1State { h: vec::from_elem(digest_buf_len, 0u32), len_low: 0u32, len_high: 0u32, diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 72a888fcc917b..febaea637efe1 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -239,7 +239,7 @@ fn binarysort(array: &mut [T], start: uint) { } } assert!(left == right); - let mut n = start-left; + let n = start-left; copy_vec(array, left+1, array, left, n); array[left] = pivot; @@ -416,7 +416,7 @@ impl MergeState { } fn merge_at(&mut self, n: uint, array: &mut [T]) { - let mut size = self.runs.len(); + let size = self.runs.len(); assert!(size >= 2); assert!(n == size-2 || n == size-3); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 4ccbf207170e9..addc1da6394ee 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -427,8 +427,7 @@ fn run_tests(opts: &TestOpts, let filtered_descs = filtered_tests.map(|t| t.desc); callback(TeFiltered(filtered_descs)); - let mut (filtered_tests, - filtered_benchs) = + let (filtered_tests, filtered_benchs) = do vec::partition(filtered_tests) |e| { match e.testfn { StaticTestFn(_) | DynTestFn(_) => true, diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 70dc4d8cfebbf..a763aa1592e83 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -147,7 +147,7 @@ pub fn empty_tm() -> Tm { /// Returns the specified time in UTC pub fn at_utc(clock: Timespec) -> Tm { unsafe { - let mut Timespec { sec, nsec } = clock; + let Timespec { sec, nsec } = clock; let mut tm = empty_tm(); rustrt::rust_gmtime(sec, nsec, &mut tm); tm @@ -162,7 +162,7 @@ pub fn now_utc() -> Tm { /// Returns the specified time in the local timezone pub fn at(clock: Timespec) -> Tm { unsafe { - let mut Timespec { sec, nsec } = clock; + let Timespec { sec, nsec } = clock; let mut tm = empty_tm(); rustrt::rust_localtime(sec, nsec, &mut tm); tm From fd97cac251224e936508541e99fb63ac02fe6eca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Apr 2013 01:10:31 -0400 Subject: [PATCH 335/403] syntax: remove unused 'mut' variables --- src/libsyntax/diagnostic.rs | 2 +- src/libsyntax/ext/fmt.rs | 8 +++++--- src/libsyntax/parse/attr.rs | 8 ++++---- src/libsyntax/parse/comments.rs | 2 +- src/libsyntax/parse/parser.rs | 28 ++++++++++++++-------------- src/libsyntax/print/pp.rs | 6 +++--- src/libsyntax/print/pprust.rs | 2 +- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 807371490dbc2..c170ee5c1195c 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -342,7 +342,7 @@ fn highlight_lines_internal(cm: @codemap::CodeMap, while num > 0u { num /= 10u; digits += 1u; } // indent past |name:## | and the 0-offset column location - let mut left = str::len(fm.name) + digits + lo.col.to_uint() + 3u; + let left = str::len(fm.name) + digits + lo.col.to_uint() + 3u; let mut s = ~""; // Skip is the number of characters we need to skip because they are // part of the 'filename:line ' part of the previous line. diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 3ebe844950a40..6a877040f4808 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -96,7 +96,7 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, } } fn make_ty(cx: @ext_ctxt, sp: span, t: Ty) -> @ast::expr { - let mut rt_type; + let rt_type; match t { TyHex(c) => match c { CaseUpper => rt_type = ~"TyHexUpper", @@ -272,6 +272,7 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, /* Translate each piece (portion of the fmt expression) by invoking the corresponding function in core::unstable::extfmt. Each function takes a buffer to insert data into along with the data being formatted. */ + let npieces = pieces.len(); do vec::consume(pieces) |i, pc| { match pc { /* Raw strings get appended via str::push_str */ @@ -279,9 +280,10 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, let portion = mk_uniq_str(cx, fmt_sp, s); /* If this is the first portion, then initialize the local - buffer with it directly */ + buffer with it directly. If it's actually the only piece, + then there's no need for it to be mutable */ if i == 0 { - stms.push(mk_local(cx, fmt_sp, true, ident, portion)); + stms.push(mk_local(cx, fmt_sp, npieces > 1, ident, portion)); } else { let args = ~[mk_mut_addr_of(cx, fmt_sp, buf()), portion]; let call = mk_call_global(cx, diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index bf8f03d4bf69e..f851b9781ab83 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -73,7 +73,7 @@ impl parser_attr for Parser { self.expect(&token::LBRACKET); let meta_item = self.parse_meta_item(); self.expect(&token::RBRACKET); - let mut hi = self.span.hi; + let hi = self.span.hi; return spanned(lo, hi, ast::attribute_ { style: style, value: meta_item, is_sugared_doc: false }); @@ -141,16 +141,16 @@ impl parser_attr for Parser { token::EQ => { self.bump(); let lit = self.parse_lit(); - let mut hi = self.span.hi; + let hi = self.span.hi; @spanned(lo, hi, ast::meta_name_value(name, lit)) } token::LPAREN => { let inner_items = self.parse_meta_seq(); - let mut hi = self.span.hi; + let hi = self.span.hi; @spanned(lo, hi, ast::meta_list(name, inner_items)) } _ => { - let mut hi = self.span.hi; + let hi = self.span.hi; @spanned(lo, hi, ast::meta_word(name)) } } diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 2f6bfd4cfc53b..b73544e95d608 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -229,7 +229,7 @@ fn read_block_comment(rdr: @mut StringReader, debug!(">>> block comment"); let p = rdr.last_pos; let mut lines: ~[~str] = ~[]; - let mut col: CharPos = rdr.col; + let col: CharPos = rdr.col; bump(rdr); bump(rdr); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e892f212b0577..f164eb06df532 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -810,7 +810,7 @@ pub impl Parser { // This version of parse arg doesn't necessarily require // identifier names. fn parse_arg_general(&self, require_name: bool) -> arg { - let mut m; + let m; let mut is_mutbl = false; let pat = if require_name || self.is_named_argument() { m = self.parse_arg_mode(); @@ -1154,7 +1154,7 @@ pub impl Parser { let lo = self.span.lo; let mut hi = self.span.hi; - let mut ex: expr_; + let ex: expr_; if *self.token == token::LPAREN { self.bump(); @@ -1629,9 +1629,9 @@ pub impl Parser { // parse a prefix-operator expr fn parse_prefix_expr(&self) -> @expr { let lo = self.span.lo; - let mut hi; + let hi; - let mut ex; + let ex; match *self.token { token::NOT => { self.bump(); @@ -1781,7 +1781,7 @@ pub impl Parser { token::BINOPEQ(op) => { self.bump(); let rhs = self.parse_expr(); - let mut aop; + let aop; match op { token::PLUS => aop = add, token::MINUS => aop = subtract, @@ -1956,7 +1956,7 @@ pub impl Parser { let lo = self.last_span.lo; let cond = self.parse_expr(); let body = self.parse_block_no_value(); - let mut hi = body.span.hi; + let hi = body.span.hi; return self.mk_expr(lo, hi, expr_while(cond, body)); } @@ -1984,7 +1984,7 @@ pub impl Parser { let lo = self.last_span.lo; let body = self.parse_block_no_value(); - let mut hi = body.span.hi; + let hi = body.span.hi; return self.mk_expr(lo, hi, expr_loop(body, opt_ident)); } else { // This is a 'continue' expression @@ -2043,7 +2043,7 @@ pub impl Parser { arms.push(ast::arm { pats: pats, guard: guard, body: blk }); } - let mut hi = self.span.hi; + let hi = self.span.hi; self.bump(); return self.mk_expr(lo, hi, expr_match(discriminant, arms)); } @@ -2162,7 +2162,7 @@ pub impl Parser { let hi1 = self.last_span.lo; let fieldpath = ast_util::ident_to_path(mk_sp(lo1, hi1), fieldname); - let mut subpat; + let subpat; if *self.token == token::COLON { self.bump(); subpat = self.parse_pat(refutable); @@ -2183,7 +2183,7 @@ pub impl Parser { let lo = self.span.lo; let mut hi = self.span.hi; - let mut pat; + let pat; match *self.token { token::UNDERSCORE => { self.bump(); pat = pat_wild; } token::AT => { @@ -2534,7 +2534,7 @@ pub impl Parser { match self.parse_item_or_view_item(/*bad*/ copy item_attrs, true, false, false) { iovi_item(i) => { - let mut hi = i.span.hi; + let hi = i.span.hi; let decl = @spanned(lo, hi, decl_item(i)); return @spanned(lo, hi, stmt_decl(decl, self.get_id())); } @@ -2704,7 +2704,7 @@ pub impl Parser { } } } - let mut hi = self.span.hi; + let hi = self.span.hi; self.bump(); let bloc = ast::blk_ { view_items: view_items, @@ -3590,7 +3590,7 @@ pub impl Parser { let purity = self.parse_fn_purity(); let (ident, generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(|p| p.parse_arg()); - let mut hi = self.span.hi; + let hi = self.span.hi; self.expect(&token::SEMI); @ast::foreign_item { ident: ident, attrs: attrs, @@ -3798,7 +3798,7 @@ pub impl Parser { } } self.bump(); - let mut actual_dtor = do the_dtor.map |dtor| { + let actual_dtor = do the_dtor.map |dtor| { let (d_body, d_attrs, d_s) = copy *dtor; codemap::spanned { node: ast::struct_dtor_ { id: self.get_id(), attrs: d_attrs, diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index eff7524e194ae..17add33d67316 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -146,9 +146,9 @@ pub fn mk_printer(out: @io::Writer, linewidth: uint) -> @mut Printer { // fall behind. let n: uint = 3 * linewidth; debug!("mk_printer %u", linewidth); - let mut token: ~[token] = vec::from_elem(n, EOF); - let mut size: ~[int] = vec::from_elem(n, 0); - let mut scan_stack: ~[uint] = vec::from_elem(n, 0u); + let token: ~[token] = vec::from_elem(n, EOF); + let size: ~[int] = vec::from_elem(n, 0); + let scan_stack: ~[uint] = vec::from_elem(n, 0u); @mut Printer { out: @out, buf_len: n, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8cf7359956283..ce772ca7c35f2 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1972,7 +1972,7 @@ pub fn print_ty_fn(s: @ps, pub fn maybe_print_trailing_comment(s: @ps, span: codemap::span, next_pos: Option) { - let mut cm; + let cm; match s.cm { Some(ccm) => cm = ccm, _ => return } match next_comment(s) { Some(ref cmnt) => { From c389d0b0dd2273c9f7d16917a1738509f5522491 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 12 Apr 2013 01:15:30 -0400 Subject: [PATCH 336/403] rustc: remove unused 'mut' variables --- src/librustc/back/link.rs | 6 +++--- src/librustc/driver/driver.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/borrowck/gather_loans.rs | 2 +- src/librustc/middle/borrowck/loan.rs | 2 +- src/librustc/middle/check_match.rs | 2 +- src/librustc/middle/resolve.rs | 18 +++++++++--------- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/callee.rs | 6 +++--- src/librustc/middle/trans/closure.rs | 2 +- src/librustc/middle/trans/expr.rs | 6 +++--- src/librustc/middle/trans/foreign.rs | 3 ++- src/librustc/middle/trans/monomorphize.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 9 +++++---- src/librustc/middle/typeck/check/vtable.rs | 2 +- src/librustc/middle/typeck/rscope.rs | 2 +- 17 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3dfa318826b7b..a176b0163a499 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -273,7 +273,7 @@ pub mod write { let LLVMOptDefault = 2 as c_int; // -O2, -Os let LLVMOptAggressive = 3 as c_int; // -O3 - let mut CodeGenOptLevel = match opts.optimize { + let CodeGenOptLevel = match opts.optimize { session::No => LLVMOptNone, session::Less => LLVMOptLess, session::Default => LLVMOptDefault, @@ -294,7 +294,7 @@ pub mod write { return; } - let mut FileType; + let FileType; if output_type == output_type_object || output_type == output_type_exe { FileType = lib::llvm::ObjectFile; @@ -820,7 +820,7 @@ pub fn link_binary(sess: Session, cc_args.push(output.to_str()); cc_args.push(obj_filename.to_str()); - let mut lib_cmd; + let lib_cmd; let os = sess.targ_cfg.os; if os == session::os_macos { lib_cmd = ~"-dynamiclib"; diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index fae73d7faf2d4..c4f37c2170dbb 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -349,7 +349,7 @@ pub fn compile_upto(sess: Session, cfg: ast::crate_cfg, outputs: Option<@OutputFilenames>) -> (@ast::crate, Option) { let time_passes = sess.time_passes(); - let mut crate = time(time_passes, ~"parsing", + let crate = time(time_passes, ~"parsing", || parse_input(sess, copy cfg, input) ); if upto == cu_parse { return (crate, None); } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index aaafc7c18d6f3..8515e0c6e9b7c 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1341,7 +1341,7 @@ pub static metadata_encoding_version : &'static [u8] = pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { let wr = @io::BytesWriter(); - let mut stats = Stats { + let stats = Stats { inline_bytes: 0, attr_bytes: 0, dep_bytes: 0, diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 4f2e41dca5c04..b8e0bba6b2348 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -305,7 +305,7 @@ pub impl GatherLoanCtxt { let mcx = &mem_categorization_ctxt { tcx: self.tcx(), method_map: self.bccx.method_map}; - let mut cmt = mcx.cat_expr_autoderefd(expr, autoderefs); + let cmt = mcx.cat_expr_autoderefd(expr, autoderefs); debug!("after autoderef, cmt=%s", self.bccx.cmt_to_repr(cmt)); match autoref.kind { diff --git a/src/librustc/middle/borrowck/loan.rs b/src/librustc/middle/borrowck/loan.rs index 3c37b5dae64a2..aedd6bb5467c5 100644 --- a/src/librustc/middle/borrowck/loan.rs +++ b/src/librustc/middle/borrowck/loan.rs @@ -51,7 +51,7 @@ use middle::mem_categorization::{cat_arg, cat_binding, cat_discr, cat_comp}; use middle::mem_categorization::{cat_deref, cat_discr, cat_local, cat_self}; use middle::mem_categorization::{cat_special, cat_stack_upvar, cmt}; use middle::mem_categorization::{comp_field, comp_index, comp_variant}; -use middle::mem_categorization::{gc_ptr, region_ptr, lp_local, lp_arg}; +use middle::mem_categorization::{gc_ptr, region_ptr}; use middle::ty; use util::common::indenter; diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 1db8f8cc8de81..8fc94cf51e2a0 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -481,7 +481,7 @@ pub fn specialize(cx: @MatchCheckCtxt, left_ty: ty::t) -> Option<~[@pat]> { // Sad, but I can't get rid of this easily - let mut r0 = copy *raw_pat(r[0]); + let r0 = copy *raw_pat(r[0]); match r0 { pat{id: pat_id, node: n, span: pat_span} => match n { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 3c158c0d081f8..f4d6d5c599a1a 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -960,7 +960,7 @@ pub impl Resolver { // child name directly. Otherwise, we create or reuse an anonymous // module and add the child to that. - let mut module_; + let module_; match reduced_graph_parent { ModuleReducedGraphParent(parent_module) => { module_ = parent_module; @@ -1527,7 +1527,7 @@ pub impl Resolver { block: &blk, parent: ReducedGraphParent, visitor: vt) { - let mut new_parent; + let new_parent; if self.block_needs_anonymous_module(block) { let block_id = block.node.id; @@ -2427,7 +2427,7 @@ pub impl Resolver { let merge_import_resolution = |ident, name_bindings: @mut NameBindings| { - let mut dest_import_resolution; + let dest_import_resolution; match module_.import_resolutions.find(ident) { None => { // Create a new import resolution from this child. @@ -2583,8 +2583,8 @@ pub impl Resolver { let module_prefix_result = self.resolve_module_prefix(module_, module_path); - let mut search_module; - let mut start_index; + let search_module; + let start_index; match module_prefix_result { Failed => { self.session.span_err(span, ~"unresolved name"); @@ -3221,7 +3221,7 @@ pub impl Resolver { allow_capturing_self: AllowCapturingSelfFlag) -> Option { let mut def; - let mut is_ty_param; + let is_ty_param; match def_like { dl_def(d @ def_local(*)) | dl_def(d @ def_upvar(*)) | @@ -4530,7 +4530,7 @@ pub impl Resolver { -> Option { let module_path_idents = self.intern_module_part_of_path(path); - let mut containing_module; + let containing_module; match self.resolve_module_path_for_import(self.current_module, module_path_idents, UseLexicalScope, @@ -4578,7 +4578,7 @@ pub impl Resolver { let root_module = self.graph_root.get_module(); - let mut containing_module; + let containing_module; match self.resolve_module_path_from_root(root_module, module_path_idents, 0, @@ -4622,7 +4622,7 @@ pub impl Resolver { span: span) -> Option { // Check the local set of ribs. - let mut search_result; + let search_result; match namespace { ValueNS => { search_result = self.search_ribs(&mut self.value_ribs, ident, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 7339003c6143a..dc59fcecb5a1e 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -248,7 +248,7 @@ pub enum opt_result { pub fn trans_opt(bcx: block, o: &Opt) -> opt_result { let _icx = bcx.insn_ctxt("match::trans_opt"); let ccx = bcx.ccx(); - let mut bcx = bcx; + let bcx = bcx; match *o { lit(ExprLit(lit_expr)) => { let datumblock = expr::trans_to_datum(bcx, lit_expr); diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 3301ed62cbe1f..7a174be1e5724 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -292,7 +292,7 @@ pub fn trans_fn_ref_with_vtables( } // Find the actual function pointer. - let mut val = { + let val = { if def_id.crate == ast::local_crate { // Internal reference. get_item_val(ccx, def_id.node) @@ -415,7 +415,7 @@ pub fn trans_lang_call_with_type_params(bcx: block, type_params, None, fty); - let mut llfnty = type_of::type_of(callee.bcx.ccx(), + let llfnty = type_of::type_of(callee.bcx.ccx(), substituted); new_llval = PointerCast(callee.bcx, fn_data.llfn, llfnty); } @@ -712,7 +712,7 @@ pub fn trans_arg_expr(bcx: block, } }; let mut arg_datum = arg_datumblock.datum; - let mut bcx = arg_datumblock.bcx; + let bcx = arg_datumblock.bcx; debug!(" arg datum: %s", arg_datum.to_str(bcx.ccx())); diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index cb815506c39d2..4fc4cae464dab 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -261,7 +261,7 @@ pub fn build_closure(bcx0: block, include_ret_handle: Option) -> ClosureResult { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call - let mut bcx = bcx0;; + let bcx = bcx0;; let ccx = bcx.ccx(), tcx = ccx.tcx; // Package up the captured upvars diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index ba6965f0eaea3..48c76ab37c6e3 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -192,7 +192,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { } Some(&@AutoAddEnv(*)) => { let mut bcx = bcx; - let mut datum = unpack_datum!(bcx, { + let datum = unpack_datum!(bcx, { trans_to_datum_unadjusted(bcx, expr) }); add_env(bcx, expr, datum) @@ -1187,7 +1187,7 @@ fn trans_rec_or_struct(bcx: block, dest: Dest) -> block { let _icx = bcx.insn_ctxt("trans_rec"); - let mut bcx = bcx; + let bcx = bcx; let ty = node_id_type(bcx, id); let tcx = bcx.tcx(); @@ -1505,7 +1505,7 @@ fn trans_lazy_binop(bcx: block, b: @ast::expr) -> DatumBlock { let _icx = bcx.insn_ctxt("trans_lazy_binop"); let binop_ty = expr_ty(bcx, binop_expr); - let mut bcx = bcx; + let bcx = bcx; let Result {bcx: past_lhs, val: lhs} = { do base::with_scope_result(bcx, a.info(), ~"lhs") |bcx| { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 956ee3bf1443e..cb15a2e8c644a 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -567,7 +567,8 @@ pub fn trans_intrinsic(ccx: @CrateContext, set_fixed_stack_segment(fcx.llfn); } - let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let mut bcx = top_scope_block(fcx, None); + let lltop = bcx.llbb; match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { let old = AtomicCmpXchg(bcx, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 52ca8ec49bb7f..b240dcb80845e 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -102,7 +102,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, } let tpt = ty::lookup_item_type(ccx.tcx, fn_id); - let mut llitem_ty = tpt.ty; + let llitem_ty = tpt.ty; let map_node = session::expect(ccx.sess, ccx.tcx.items.find(&fn_id.node), || fmt!("While monomorphizing %?, couldn't find it in the item map \ diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 9d8a1145f22eb..e778986b2d1c3 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -180,7 +180,7 @@ pub struct Candidate { pub impl<'self> LookupContext<'self> { fn do_lookup(&self, self_ty: ty::t) -> Option { - let mut self_ty = structurally_resolved_type(self.fcx, + let self_ty = structurally_resolved_type(self.fcx, self.self_expr.span, self_ty); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d6f892cac3c31..ca9b3602d5d37 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1625,7 +1625,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // block syntax lambdas; that is, lambdas without explicit // sigils. let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); - let mut error_happened = false; + let error_happened = false; let (expected_sig, expected_purity, expected_sigil, @@ -1706,7 +1706,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, field: ast::ident, tys: &[@ast::Ty]) { let tcx = fcx.ccx.tcx; - let mut bot = check_expr(fcx, base); + let bot = check_expr(fcx, base); let expr_t = structurally_resolved_type(fcx, expr.span, fcx.expr_ty(base)); let (base_t, derefs) = do_autoderef(fcx, expr.span, expr_t); @@ -2867,7 +2867,7 @@ pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::local) { } pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::stmt) { - let mut node_id; + let node_id; let mut saw_bot = false; let mut saw_err = false; match stmt.node { @@ -3124,7 +3124,8 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, ccx.tcx.enum_var_cache.insert(local_def(id), @variants); // Check that it is possible to represent this enum: - let mut outer = true, did = local_def(id); + let mut outer = true; + let did = local_def(id); if ty::type_structurally_contains(ccx.tcx, rty, |sty| { match *sty { ty::ty_enum(id, _) if id == did => { diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 39715f295ade9..ad173c6956060 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -11,7 +11,7 @@ use core::prelude::*; use middle::resolve::Impl; -use middle::ty::{param_ty}; +use middle::ty::param_ty; use middle::ty; use middle::typeck::check::{FnCtxt, impl_self_ty}; use middle::typeck::check::{structurally_resolved_type}; diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 62320a1d34d56..869825e607e56 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -158,7 +158,7 @@ impl MethodRscope { variance: Option, rcvr_generics: &ast::Generics) -> MethodRscope { - let mut region_param_names = + let region_param_names = RegionParamNames::from_generics(rcvr_generics); MethodRscope { self_ty: self_ty, From 59caef02ed4f8213adb73aa04828e0ab71cec8a2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Apr 2013 23:47:35 -0700 Subject: [PATCH 337/403] xfail two benchmarks that are failing on the bots --- src/test/bench/shootout-fasta-redux.rs | 2 ++ src/test/bench/shootout-threadring.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 5cb04fcd27a8f..35b5eab8a28ca 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -1,3 +1,5 @@ +// xfail-test FIXME #5985 Doesn't typecheck on x86 + use core::cast::transmute; use core::from_str::FromStr; use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite}; diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs index 9eb8a29cec030..213c5140ccf0c 100644 --- a/src/test/bench/shootout-threadring.rs +++ b/src/test/bench/shootout-threadring.rs @@ -10,6 +10,8 @@ // Based on threadring.erlang by Jira Isa +// xfail-test FIXME #5985 OOM's on the mac bot + fn start(n_tasks: int, token: int) { let mut (p, ch1) = comm::stream(); ch1.send(token); From 91d1d00367755e55deeea4913a5aad03d8dbd88a Mon Sep 17 00:00:00 2001 From: Matthijs Hofstra Date: Sun, 21 Apr 2013 13:35:43 +0200 Subject: [PATCH 338/403] Changed shootout-fasta-redux to use size_t when calling fwrite, removed XFAIL --- src/test/bench/shootout-fasta-redux.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 35b5eab8a28ca..5ece98102063b 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -1,8 +1,6 @@ -// xfail-test FIXME #5985 Doesn't typecheck on x86 - use core::cast::transmute; use core::from_str::FromStr; -use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite}; +use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t}; use core::uint::{min, range}; use core::vec::bytes::copy_memory; @@ -101,7 +99,7 @@ impl RepeatFasta { let mut pos = 0, bytes, n = n; while n > 0 { bytes = min(LINE_LEN, n); - fwrite(transmute(&buf[pos]), bytes as u64, 1, stdout); + fwrite(transmute(&buf[pos]), bytes as size_t, 1, stdout); fputc('\n' as c_int, stdout); pos += bytes; if pos > alu_len { @@ -166,14 +164,14 @@ impl RandomFasta { } buf[LINE_LEN] = '\n' as u8; fwrite(transmute(&buf[0]), - LINE_LEN as u64 + 1, + LINE_LEN as size_t + 1, 1, self.stdout); } for range(0, chars_left) |i| { buf[i] = self.nextc(); } - fwrite(transmute(&buf[0]), chars_left as u64, 1, self.stdout); + fwrite(transmute(&buf[0]), chars_left as size_t, 1, self.stdout); } } } From aa763cdb238bb9c9f26d84a699d9f0de8289d8c4 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 21 Apr 2013 22:09:33 +1000 Subject: [PATCH 339/403] libcore: make rand::random return a generic value implementing `Rand`. --- src/libcore/rand.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 0a93a651a8572..a2f103fdbc90e 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -55,6 +55,12 @@ impl Rand for i64 { } } +impl Rand for uint { + fn rand(rng: @rand::Rng) -> uint { + rng.gen_uint() + } +} + impl Rand for u8 { fn rand(rng: @rand::Rng) -> u8 { rng.gen_u8() @@ -149,6 +155,7 @@ pub struct Weighted { } pub trait RngUtil { + /// Return a random value for a Rand type fn gen(&self) -> T; /** * Return a random int @@ -739,10 +746,11 @@ pub fn task_rng() -> @Rng { } /** - * Returns a random uint, using the task's based random number generator. + * Returns a random value of a Rand type, using the task's random number + * generator. */ -pub fn random() -> uint { - task_rng().gen_uint() +pub fn random() -> T { + task_rng().gen() } @@ -915,8 +923,10 @@ mod tests { #[test] fn random() { - // not sure how to test this aside from just getting a number + // not sure how to test this aside from just getting some values let _n : uint = rand::random(); + let _f : f32 = rand::random(); + let _o : Option> = rand::random(); } } From 01eb5e8ad39a57e9fc31569983c1b9d5905a7e58 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 22 Apr 2013 01:58:53 +1000 Subject: [PATCH 340/403] Rename Div operator trait to Quot and Modulo operator trait to Rem --- doc/rust.md | 16 ++++---- doc/tutorial.md | 2 +- src/etc/kate/rust.xml | 4 +- src/etc/vim/syntax/rust.vim | 2 +- src/libcore/core.rc | 5 +++ src/libcore/num/f32.rs | 49 ++++++++++++++-------- src/libcore/num/f64.rs | 49 ++++++++++++++-------- src/libcore/num/float.rs | 45 ++++++++++++-------- src/libcore/num/int-template.rs | 50 ++++++++++++---------- src/libcore/num/num.rs | 35 +++++++++++++--- src/libcore/num/strconv.rs | 21 +++++++--- src/libcore/num/uint-template.rs | 50 ++++++++++++---------- src/libcore/ops.rs | 16 ++++++++ src/libcore/prelude.rs | 5 +++ src/librustc/middle/const_eval.rs | 14 +++---- src/librustc/middle/kind.rs | 2 +- src/librustc/middle/lang_items.rs | 20 ++++----- src/librustc/middle/resolve.rs | 8 ++-- src/librustc/middle/trans/base.rs | 8 ++-- src/librustc/middle/trans/consts.rs | 2 +- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/libstd/base64.rs | 2 +- src/libstd/num/bigint.rs | 64 ++++++++++++++--------------- src/libstd/num/complex.rs | 32 ++++++--------- src/libstd/num/rational.rs | 41 +++++++++--------- src/libstd/std.rc | 9 ++++ src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_util.rs | 8 ++-- src/libsyntax/parse/parser.rs | 4 +- src/libsyntax/parse/prec.rs | 2 +- src/test/compile-fail/eval-enum.rs | 4 +- src/test/run-fail/divide-by-zero.rs | 2 +- src/test/run-fail/mod-zero.rs | 2 +- 34 files changed, 344 insertions(+), 235 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index e9c88fc34121c..b1eb5521b398f 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1467,10 +1467,10 @@ A complete list of the built-in language items follows: : Elements can be subtracted. `mul` : Elements can be multiplied. -`div` - : Elements can be divided. -`mod` - : Elements have a modulo operation. +`quot` + : Elements have a quotient operation. +`rem` + : Elements have a remainder operation. `neg` : Elements can be negated arithmetically. `not` @@ -1856,11 +1856,11 @@ The default meaning of the operators on standard types is given here. : Multiplication. Calls the `mul` method on the `core::ops::Mul` trait. `/` - : Division. - Calls the `div` method on the `core::ops::Div` trait. + : Quotient. + Calls the `quot` method on the `core::ops::Quot` trait. `%` - : Modulo (a.k.a. "remainder"). - Calls the `modulo` method on the `core::ops::Modulo` trait. + : Remainder. + Calls the `rem` method on the `core::ops::Rem` trait. #### Bitwise operators diff --git a/doc/tutorial.md b/doc/tutorial.md index 56629b93b1a49..c10bc8a294c5d 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -362,7 +362,7 @@ The nil type, written `()`, has a single value, also written `()`. ## Operators Rust's set of operators contains very few surprises. Arithmetic is done with -`*`, `/`, `%`, `+`, and `-` (multiply, divide, take remainder, add, and subtract). `-` is +`*`, `/`, `%`, `+`, and `-` (multiply, quotient, remainder, add, and subtract). `-` is also a unary prefix operator that negates numbers. As in C, the bitwise operators `>>`, `<<`, `&`, `|`, and `^` are also supported. diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index 59f8c164588b3..6a751bd1c8588 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -57,8 +57,8 @@ Add Sub Mul - Div - Modulo + Quot + Rem Neg BitAnd BitOr diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 3e6c11c6238b1..eab3627ae16d1 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -46,7 +46,7 @@ syn keyword rustType off_t dev_t ino_t pid_t mode_t ssize_t syn keyword rustTrait Const Copy Send Owned " inherent traits syn keyword rustTrait Eq Ord Num Ptr -syn keyword rustTrait Drop Add Sub Mul Div Modulo Neg BitAnd BitOr +syn keyword rustTrait Drop Add Sub Mul Quot Rem Neg BitAnd BitOr syn keyword rustTrait BitXor Shl Shr Index syn keyword rustSelf self diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 81190ea8fc62e..fd8813d0c4a45 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -75,7 +75,12 @@ they contained the following prologue: pub use kinds::{Const, Copy, Owned, Durable}; pub use ops::{Drop}; +#[cfg(stage0)] pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not}; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Shl, Shr, Index}; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 6233f8c2a61b5..2e7dc98e3c56c 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -16,8 +16,13 @@ use option::Option; use from_str; use to_str; -#[cfg(notest)] use cmp; -#[cfg(notest)] use ops; +#[cfg(notest)] use cmp::{Eq, Ord}; +#[cfg(stage0,notest)] +use ops::{Add, Sub, Mul, Div, Modulo, Neg}; +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +use ops::{Add, Sub, Mul, Quot, Rem, Neg}; pub use cmath::c_float_targ_consts::*; @@ -131,7 +136,7 @@ pub fn sub(x: f32, y: f32) -> f32 { return x - y; } pub fn mul(x: f32, y: f32) -> f32 { return x * y; } #[inline(always)] -pub fn div(x: f32, y: f32) -> f32 { return x / y; } +pub fn quot(x: f32, y: f32) -> f32 { return x / y; } #[inline(always)] pub fn rem(x: f32, y: f32) -> f32 { return x % y; } @@ -265,7 +270,7 @@ pub fn logarithm(n: f32, b: f32) -> f32 { } #[cfg(notest)] -impl cmp::Eq for f32 { +impl Eq for f32 { #[inline(always)] fn eq(&self, other: &f32) -> bool { (*self) == (*other) } #[inline(always)] @@ -273,7 +278,7 @@ impl cmp::Eq for f32 { } #[cfg(notest)] -impl cmp::Ord for f32 { +impl Ord for f32 { #[inline(always)] fn lt(&self, other: &f32) -> bool { (*self) < (*other) } #[inline(always)] @@ -295,33 +300,41 @@ impl num::One for f32 { } #[cfg(notest)] -impl ops::Add for f32 { - #[inline(always)] +impl Add for f32 { fn add(&self, other: &f32) -> f32 { *self + *other } } #[cfg(notest)] -impl ops::Sub for f32 { - #[inline(always)] +impl Sub for f32 { fn sub(&self, other: &f32) -> f32 { *self - *other } } #[cfg(notest)] -impl ops::Mul for f32 { - #[inline(always)] +impl Mul for f32 { fn mul(&self, other: &f32) -> f32 { *self * *other } } -#[cfg(notest)] -impl ops::Div for f32 { - #[inline(always)] +#[cfg(stage0,notest)] +impl Div for f32 { fn div(&self, other: &f32) -> f32 { *self / *other } } -#[cfg(notest)] -impl ops::Modulo for f32 { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Quot for f32 { #[inline(always)] + fn quot(&self, other: &f32) -> f32 { *self / *other } +} +#[cfg(stage0,notest)] +impl Modulo for f32 { fn modulo(&self, other: &f32) -> f32 { *self % *other } } -#[cfg(notest)] -impl ops::Neg for f32 { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Rem for f32 { #[inline(always)] + fn rem(&self, other: &f32) -> f32 { *self % *other } +} +#[cfg(notest)] +impl Neg for f32 { fn neg(&self) -> f32 { -*self } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 7f32893f5bff7..4762c395a2561 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -16,8 +16,13 @@ use option::Option; use to_str; use from_str; -#[cfg(notest)] use cmp; -#[cfg(notest)] use ops; +#[cfg(notest)] use cmp::{Eq, Ord}; +#[cfg(stage0,notest)] +use ops::{Add, Sub, Mul, Div, Modulo, Neg}; +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +use ops::{Add, Sub, Mul, Quot, Rem, Neg}; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; @@ -155,7 +160,7 @@ pub fn sub(x: f64, y: f64) -> f64 { return x - y; } pub fn mul(x: f64, y: f64) -> f64 { return x * y; } #[inline(always)] -pub fn div(x: f64, y: f64) -> f64 { return x / y; } +pub fn quot(x: f64, y: f64) -> f64 { return x / y; } #[inline(always)] pub fn rem(x: f64, y: f64) -> f64 { return x % y; } @@ -284,7 +289,7 @@ pub fn logarithm(n: f64, b: f64) -> f64 { } #[cfg(notest)] -impl cmp::Eq for f64 { +impl Eq for f64 { #[inline(always)] fn eq(&self, other: &f64) -> bool { (*self) == (*other) } #[inline(always)] @@ -292,7 +297,7 @@ impl cmp::Eq for f64 { } #[cfg(notest)] -impl cmp::Ord for f64 { +impl Ord for f64 { #[inline(always)] fn lt(&self, other: &f64) -> bool { (*self) < (*other) } #[inline(always)] @@ -314,33 +319,41 @@ impl num::One for f64 { } #[cfg(notest)] -impl ops::Add for f64 { - #[inline(always)] +impl Add for f64 { fn add(&self, other: &f64) -> f64 { *self + *other } } #[cfg(notest)] -impl ops::Sub for f64 { - #[inline(always)] +impl Sub for f64 { fn sub(&self, other: &f64) -> f64 { *self - *other } } #[cfg(notest)] -impl ops::Mul for f64 { - #[inline(always)] +impl Mul for f64 { fn mul(&self, other: &f64) -> f64 { *self * *other } } -#[cfg(notest)] -impl ops::Div for f64 { - #[inline(always)] +#[cfg(stage0,notest)] +impl Div for f64 { fn div(&self, other: &f64) -> f64 { *self / *other } } -#[cfg(notest)] -impl ops::Modulo for f64 { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Quot for f64 { #[inline(always)] + fn quot(&self, other: &f64) -> f64 { *self / *other } +} +#[cfg(stage0,notest)] +impl Modulo for f64 { fn modulo(&self, other: &f64) -> f64 { *self % *other } } -#[cfg(notest)] -impl ops::Neg for f64 { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Rem for f64 { #[inline(always)] + fn rem(&self, other: &f64) -> f64 { *self % *other } +} +#[cfg(notest)] +impl Neg for f64 { fn neg(&self) -> f64 { -*self } } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index c9cda20640d56..9cf14cf0f494b 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -28,9 +28,14 @@ use to_str; use from_str; #[cfg(notest)] use cmp::{Eq, Ord}; -#[cfg(notest)] use ops; - -pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt}; +#[cfg(stage0,notest)] +use ops::{Add, Sub, Mul, Div, Modulo, Neg}; +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +use ops::{Add, Sub, Mul, Quot, Rem, Neg}; + +pub use f64::{add, sub, mul, quot, rem, lt, le, eq, ne, ge, gt}; pub use f64::logarithm; pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor}; pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub}; @@ -449,33 +454,41 @@ impl num::Round for float { } #[cfg(notest)] -impl ops::Add for float { - #[inline(always)] +impl Add for float { fn add(&self, other: &float) -> float { *self + *other } } #[cfg(notest)] -impl ops::Sub for float { - #[inline(always)] +impl Sub for float { fn sub(&self, other: &float) -> float { *self - *other } } #[cfg(notest)] -impl ops::Mul for float { - #[inline(always)] +impl Mul for float { fn mul(&self, other: &float) -> float { *self * *other } } -#[cfg(notest)] -impl ops::Div for float { - #[inline(always)] +#[cfg(stage0,notest)] +impl Div for float { fn div(&self, other: &float) -> float { *self / *other } } -#[cfg(notest)] -impl ops::Modulo for float { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Quot for float { #[inline(always)] + fn quot(&self, other: &float) -> float { *self / *other } +} +#[cfg(stage0,notest)] +impl Modulo for float { fn modulo(&self, other: &float) -> float { *self % *other } } -#[cfg(notest)] -impl ops::Neg for float { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Rem for float { #[inline(always)] + fn rem(&self, other: &float) -> float { *self % *other } +} +#[cfg(notest)] +impl Neg for float { fn neg(&self) -> float { -*self } } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index e170d85cc716e..8f448994c9811 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -17,8 +17,6 @@ use num::strconv; use num; use prelude::*; -#[cfg(notest)] use cmp::{Eq, Ord}; - pub use cmp::{min, max}; pub static bits : uint = inst::bits; @@ -34,7 +32,7 @@ pub fn sub(x: T, y: T) -> T { x - y } #[inline(always)] pub fn mul(x: T, y: T) -> T { x * y } #[inline(always)] -pub fn div(x: T, y: T) -> T { x / y } +pub fn quot(x: T, y: T) -> T { x / y } /** * Returns the remainder of y / x. @@ -176,63 +174,71 @@ impl num::One for T { } #[cfg(notest)] -impl ops::Add for T { - #[inline(always)] +impl Add for T { fn add(&self, other: &T) -> T { *self + *other } } #[cfg(notest)] -impl ops::Sub for T { - #[inline(always)] +impl Sub for T { fn sub(&self, other: &T) -> T { *self - *other } } #[cfg(notest)] -impl ops::Mul for T { - #[inline(always)] +impl Mul for T { fn mul(&self, other: &T) -> T { *self * *other } } -#[cfg(notest)] -impl ops::Div for T { - #[inline(always)] +#[cfg(stage0,notest)] +impl Div for T { fn div(&self, other: &T) -> T { *self / *other } } -#[cfg(notest)] -impl ops::Modulo for T { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Quot for T { #[inline(always)] + fn quot(&self, other: &T) -> T { *self / *other } +} +#[cfg(stage0,notest)] +impl Modulo for T { fn modulo(&self, other: &T) -> T { *self % *other } } -#[cfg(notest)] -impl ops::Neg for T { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Rem for T { #[inline(always)] + fn rem(&self, other: &T) -> T { *self % *other } +} +#[cfg(notest)] +impl Neg for T { fn neg(&self) -> T { -*self } } #[cfg(notest)] -impl ops::BitOr for T { +impl BitOr for T { #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } #[cfg(notest)] -impl ops::BitAnd for T { +impl BitAnd for T { #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } #[cfg(notest)] -impl ops::BitXor for T { +impl BitXor for T { #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } #[cfg(notest)] -impl ops::Shl for T { +impl Shl for T { #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } #[cfg(notest)] -impl ops::Shr for T { +impl Shr for T { #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } #[cfg(notest)] -impl ops::Not for T { +impl Not for T { #[inline(always)] fn not(&self) -> T { !*self } } diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 5834214475219..a0ff510cde7da 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -10,7 +10,16 @@ //! An interface for numeric types use cmp::{Eq, Ord}; -use ops::{Neg, Add, Sub, Mul, Div, Modulo}; +#[cfg(stage0)] +use ops::{Add, Sub, Mul, Neg}; +#[cfg(stage0)] +use Quot = ops::Div; +#[cfg(stage0)] +use Rem = ops::Modulo; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +use ops::{Add, Sub, Mul, Quot, Rem, Neg}; use option::Option; use kinds::Copy; @@ -21,8 +30,8 @@ pub trait Num: Eq + Zero + One + Add + Sub + Mul - + Div - + Modulo {} + + Quot + + Rem {} impl Num for u8 {} impl Num for u16 {} @@ -174,7 +183,7 @@ pub trait FromStrRadix { * - If code written to use this function doesn't care about it, it's * probably assuming that `x^0` always equals `1`. */ -pub fn pow_with_uint+Mul>( +pub fn pow_with_uint+Mul>( radix: uint, pow: uint) -> T { let _0: T = Zero::zero(); let _1: T = One::one(); @@ -194,7 +203,7 @@ pub fn pow_with_uint+Mul>( total } -#[cfg(test)] +#[cfg(stage0,test)] fn test_num(ten: T, two: T) { assert_eq!(ten.add(&two), cast(12)); assert_eq!(ten.sub(&two), cast(8)); @@ -208,6 +217,22 @@ fn test_num(ten: T, two: T) { assert_eq!(ten.div(&two), ten / two); assert_eq!(ten.modulo(&two), ten % two); } +#[cfg(stage1,test)] +#[cfg(stage2,test)] +#[cfg(stage3,test)] +fn test_num(ten: T, two: T) { + assert_eq!(ten.add(&two), cast(12)); + assert_eq!(ten.sub(&two), cast(8)); + assert_eq!(ten.mul(&two), cast(20)); + assert_eq!(ten.quot(&two), cast(5)); + assert_eq!(ten.rem(&two), cast(0)); + + assert_eq!(ten.add(&two), ten + two); + assert_eq!(ten.sub(&two), ten - two); + assert_eq!(ten.mul(&two), ten * two); + assert_eq!(ten.quot(&two), ten / two); + assert_eq!(ten.rem(&two), ten % two); +} #[test] fn test_u8_num() { test_num(10u8, 2u8) } #[test] fn test_u16_num() { test_num(10u16, 2u16) } diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index de699a3756b6e..4a45a1d97023e 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -9,7 +9,16 @@ // except according to those terms. use core::cmp::{Ord, Eq}; -use ops::{Add, Div, Modulo, Mul, Neg, Sub}; +#[cfg(stage0)] +use ops::{Add, Sub, Mul, Neg}; +#[cfg(stage0)] +use Quot = ops::Div; +#[cfg(stage0)] +use Rem = ops::Modulo; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +use ops::{Add, Sub, Mul, Quot, Rem, Neg}; use option::{None, Option, Some}; use char; use str; @@ -58,7 +67,7 @@ fn is_neg_inf(num: &T) -> bool { } #[inline(always)] -fn is_neg_zero>(num: &T) -> bool { +fn is_neg_zero>(num: &T) -> bool { let _0: T = Zero::zero(); let _1: T = One::one(); @@ -171,7 +180,7 @@ static nan_buf: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8]; * - Fails if `radix` < 2 or `radix` > 36. */ pub fn to_str_bytes_common+Neg+Modulo+Mul>( + Quot+Neg+Rem+Mul>( num: &T, radix: uint, negative_zero: bool, sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { if (radix as int) < 2 { @@ -379,7 +388,7 @@ pub fn to_str_bytes_common+Neg+Modulo+Mul>( + Quot+Neg+Rem+Mul>( num: &T, radix: uint, negative_zero: bool, sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { let (bytes, special) = to_str_bytes_common(num, radix, @@ -432,7 +441,7 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * - Fails if `radix` > 18 and `special == true` due to conflict * between digit and lowest first character in `inf` and `NaN`, the `'i'`. */ -pub fn from_str_bytes_common+ +pub fn from_str_bytes_common+ Mul+Sub+Neg+Add+ NumStrConv>( buf: &[u8], radix: uint, negative: bool, fractional: bool, @@ -629,7 +638,7 @@ pub fn from_str_bytes_common+ * `from_str_bytes_common()`, for details see there. */ #[inline(always)] -pub fn from_str_common+Mul+ +pub fn from_str_common+Mul+ Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool, diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 0fb6ea614d861..6f3f402f92d69 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -19,8 +19,6 @@ use num; use option::Option; use prelude::*; -#[cfg(notest)] use cmp::{Eq, Ord}; - pub use cmp::{min, max}; pub static bits : uint = inst::bits; @@ -36,7 +34,7 @@ pub fn sub(x: T, y: T) -> T { x - y } #[inline(always)] pub fn mul(x: T, y: T) -> T { x * y } #[inline(always)] -pub fn div(x: T, y: T) -> T { x / y } +pub fn quot(x: T, y: T) -> T { x / y } #[inline(always)] pub fn rem(x: T, y: T) -> T { x % y } @@ -141,63 +139,71 @@ impl num::One for T { } #[cfg(notest)] -impl ops::Add for T { - #[inline(always)] +impl Add for T { fn add(&self, other: &T) -> T { *self + *other } } #[cfg(notest)] -impl ops::Sub for T { - #[inline(always)] +impl Sub for T { fn sub(&self, other: &T) -> T { *self - *other } } #[cfg(notest)] -impl ops::Mul for T { - #[inline(always)] +impl Mul for T { fn mul(&self, other: &T) -> T { *self * *other } } -#[cfg(notest)] -impl ops::Div for T { - #[inline(always)] +#[cfg(stage0,notest)] +impl Div for T { fn div(&self, other: &T) -> T { *self / *other } } -#[cfg(notest)] -impl ops::Modulo for T { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Quot for T { #[inline(always)] + fn quot(&self, other: &T) -> T { *self / *other } +} +#[cfg(stage0,notest)] +impl Modulo for T { fn modulo(&self, other: &T) -> T { *self % *other } } -#[cfg(notest)] -impl ops::Neg for T { +#[cfg(stage1,notest)] +#[cfg(stage2,notest)] +#[cfg(stage3,notest)] +impl Rem for T { #[inline(always)] + fn rem(&self, other: &T) -> T { *self % *other } +} +#[cfg(notest)] +impl Neg for T { fn neg(&self) -> T { -*self } } #[cfg(notest)] -impl ops::BitOr for T { +impl BitOr for T { #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } #[cfg(notest)] -impl ops::BitAnd for T { +impl BitAnd for T { #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } #[cfg(notest)] -impl ops::BitXor for T { +impl BitXor for T { #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } #[cfg(notest)] -impl ops::Shl for T { +impl Shl for T { #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } #[cfg(notest)] -impl ops::Shr for T { +impl Shr for T { #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } #[cfg(notest)] -impl ops::Not for T { +impl Not for T { #[inline(always)] fn not(&self) -> T { !*self } } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 4d89d8a957c7b..465a9330f74c0 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -31,14 +31,30 @@ pub trait Mul { } #[lang="div"] +#[cfg(stage0)] pub trait Div { fn div(&self, rhs: &RHS) -> Result; } +#[lang="quot"] +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait Quot { + fn quot(&self, rhs: &RHS) -> Result; +} #[lang="modulo"] +#[cfg(stage0)] pub trait Modulo { fn modulo(&self, rhs: &RHS) -> Result; } +#[lang="rem"] +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub trait Rem { + fn rem(&self, rhs: &RHS) -> Result; +} #[lang="neg"] pub trait Neg { diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 822fb2e476beb..7d8b3edcab152 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -14,7 +14,12 @@ pub use either::{Either, Left, Right}; pub use kinds::{Const, Copy, Owned, Durable}; +#[cfg(stage0)] pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not}; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] +pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; pub use ops::{Shl, Shr, Index}; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 5148ea7fba403..c1cc01ed05a72 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -283,7 +283,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_float(a + b)), subtract => Ok(const_float(a - b)), mul => Ok(const_float(a * b)), - div => Ok(const_float(a / b)), + quot => Ok(const_float(a / b)), rem => Ok(const_float(a % b)), eq => fromb(a == b), lt => fromb(a < b), @@ -299,9 +299,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_int(a + b)), subtract => Ok(const_int(a - b)), mul => Ok(const_int(a * b)), - div if b == 0 => Err(~"divide by zero"), - div => Ok(const_int(a / b)), - rem if b == 0 => Err(~"modulo zero"), + quot if b == 0 => Err(~"quotient zero"), + quot => Ok(const_int(a / b)), + rem if b == 0 => Err(~"remainder zero"), rem => Ok(const_int(a % b)), and | bitand => Ok(const_int(a & b)), or | bitor => Ok(const_int(a | b)), @@ -321,9 +321,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_uint(a + b)), subtract => Ok(const_uint(a - b)), mul => Ok(const_uint(a * b)), - div if b == 0 => Err(~"divide by zero"), - div => Ok(const_uint(a / b)), - rem if b == 0 => Err(~"modulo zero"), + quot if b == 0 => Err(~"quotient zero"), + quot => Ok(const_uint(a / b)), + rem if b == 0 => Err(~"remainder zero"), rem => Ok(const_uint(a % b)), and | bitand => Ok(const_uint(a & b)), or | bitor => Ok(const_uint(a | b)), diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 390ffded2fe36..0558df60b7303 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -480,7 +480,7 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { /// This is rather subtle. When we are casting a value to a instantiated /// trait like `a as trait<'r>`, regionck already ensures that any borrowed -/// pointers that appear in the type of `a` are bounded by `'r` (ed.: modulo +/// pointers that appear in the type of `a` are bounded by `'r` (ed.: rem /// FIXME(#5723)). However, it is possible that there are *type parameters* /// in the type of `a`, and those *type parameters* may have borrowed pointers /// within them. We have to guarantee that the regions which appear in those diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 435cb896ac7a1..5b302108ef062 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -45,8 +45,8 @@ pub enum LangItem { AddTraitLangItem, // 5 SubTraitLangItem, // 6 MulTraitLangItem, // 7 - DivTraitLangItem, // 8 - ModuloTraitLangItem, // 9 + QuotTraitLangItem, // 8 + RemTraitLangItem, // 9 NegTraitLangItem, // 10 NotTraitLangItem, // 11 BitXorTraitLangItem, // 12 @@ -108,8 +108,8 @@ pub impl LanguageItems { 5 => "add", 6 => "sub", 7 => "mul", - 8 => "div", - 9 => "modulo", + 8 => "quot", + 9 => "rem", 10 => "neg", 11 => "not", 12 => "bitxor", @@ -170,11 +170,11 @@ pub impl LanguageItems { pub fn mul_trait(&const self) -> def_id { self.items[MulTraitLangItem as uint].get() } - pub fn div_trait(&const self) -> def_id { - self.items[DivTraitLangItem as uint].get() + pub fn quot_trait(&const self) -> def_id { + self.items[QuotTraitLangItem as uint].get() } - pub fn modulo_trait(&const self) -> def_id { - self.items[ModuloTraitLangItem as uint].get() + pub fn rem_trait(&const self) -> def_id { + self.items[RemTraitLangItem as uint].get() } pub fn neg_trait(&const self) -> def_id { self.items[NegTraitLangItem as uint].get() @@ -271,8 +271,8 @@ fn LanguageItemCollector<'r>(crate: @crate, item_refs.insert(@~"add", AddTraitLangItem as uint); item_refs.insert(@~"sub", SubTraitLangItem as uint); item_refs.insert(@~"mul", MulTraitLangItem as uint); - item_refs.insert(@~"div", DivTraitLangItem as uint); - item_refs.insert(@~"modulo", ModuloTraitLangItem as uint); + item_refs.insert(@~"quot", QuotTraitLangItem as uint); + item_refs.insert(@~"rem", RemTraitLangItem as uint); item_refs.insert(@~"neg", NegTraitLangItem as uint); item_refs.insert(@~"not", NotTraitLangItem as uint); item_refs.insert(@~"bitxor", BitXorTraitLangItem as uint); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 3c158c0d081f8..41b372119cd29 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -37,7 +37,7 @@ use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op}; use syntax::ast::{expr_binary, expr_break, expr_field}; use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path}; use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param}; -use syntax::ast::{def_upvar, def_use, def_variant, div, eq}; +use syntax::ast::{def_upvar, def_use, def_variant, quot, eq}; use syntax::ast::{expr, expr_again, expr_assign_op}; use syntax::ast::{expr_index, expr_loop}; use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl}; @@ -4899,13 +4899,13 @@ pub impl Resolver { self.add_fixed_trait_for_expr(expr.id, self.lang_items.mul_trait()); } - expr_binary(div, _, _) | expr_assign_op(div, _, _) => { + expr_binary(quot, _, _) | expr_assign_op(quot, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.div_trait()); + self.lang_items.quot_trait()); } expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.modulo_trait()); + self.lang_items.rem_trait()); } expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => { self.add_fixed_trait_for_expr(expr.id, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e1c60234f0ff0..3ad021b2f518f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -782,12 +782,12 @@ pub fn cast_shift_rhs(op: ast::binop, } } -pub fn fail_if_zero(cx: block, span: span, divmod: ast::binop, +pub fn fail_if_zero(cx: block, span: span, quotrem: ast::binop, rhs: ValueRef, rhs_t: ty::t) -> block { - let text = if divmod == ast::div { - @~"divide by zero" + let text = if quotrem == ast::quot { + @~"quotient zero" } else { - @~"modulo zero" + @~"remainder zero" }; let is_zero = match ty::get(rhs_t).sty { ty::ty_int(t) => { diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index c5e708569dc25..d0aeec89750aa 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -272,7 +272,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { if is_float { llvm::LLVMConstFMul(te1, te2) } else { llvm::LLVMConstMul(te1, te2) } } - ast::div => { + ast::quot => { if is_float { llvm::LLVMConstFDiv(te1, te2) } else if signed { llvm::LLVMConstSDiv(te1, te2) } else { llvm::LLVMConstUDiv(te1, te2) } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index ba6965f0eaea3..4b4d0869a3ed3 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1437,7 +1437,7 @@ fn trans_eager_binop(bcx: block, if is_float { FMul(bcx, lhs, rhs) } else { Mul(bcx, lhs, rhs) } } - ast::div => { + ast::quot => { if is_float { FDiv(bcx, lhs, rhs) } else { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 95d0fa984aea0..033fbecc08b37 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4255,7 +4255,7 @@ pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool { ast::add => opcat_add, ast::subtract => opcat_sub, ast::mul => opcat_mult, - ast::div => opcat_mult, + ast::quot => opcat_mult, ast::rem => opcat_mult, ast::and => opcat_logic, ast::or => opcat_logic, diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index e90f0fb3c81d4..cbdd2b19d276c 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -118,7 +118,7 @@ pub trait FromBase64 { impl FromBase64 for ~[u8] { /** * Convert base64 `u8` vector into u8 byte values. - * Every 4 encoded characters is converted into 3 octets, modulo padding. + * Every 4 encoded characters is converted into 3 octets, rem padding. * * *Example*: * diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index ec5d2cded8d56..08c65d190bf99 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -262,16 +262,16 @@ impl Mul for BigUint { } } -impl Div for BigUint { - fn div(&self, other: &BigUint) -> BigUint { - let (d, _) = self.divmod(other); +impl Quot for BigUint { + fn quot(&self, other: &BigUint) -> BigUint { + let (d, _) = self.quot_rem(other); return d; } } -impl Modulo for BigUint { - fn modulo(&self, other: &BigUint) -> BigUint { - let (_, m) = self.divmod(other); +impl Rem for BigUint { + fn rem(&self, other: &BigUint) -> BigUint { + let (_, m) = self.quot_rem(other); return m; } } @@ -304,7 +304,7 @@ impl ToStrRadix for BigUint { let mut result = ~[]; let mut r = n; while r > divider { - let (d, r0) = r.divmod(÷r); + let (d, r0) = r.quot_rem(÷r); result += [r0.to_uint() as BigDigit]; r = d; } @@ -384,7 +384,7 @@ pub impl BigUint { fn abs(&self) -> BigUint { copy *self } - fn divmod(&self, other: &BigUint) -> (BigUint, BigUint) { + fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) { if other.is_zero() { fail!() } if self.is_zero() { return (Zero::zero(), Zero::zero()); } if *other == One::one() { return (copy *self, Zero::zero()); } @@ -402,10 +402,10 @@ pub impl BigUint { shift += 1; } assert!(shift < BigDigit::bits); - let (d, m) = divmod_inner(self << shift, other << shift); + let (d, m) = quot_rem_inner(self << shift, other << shift); return (d, m >> shift); - fn divmod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { + fn quot_rem_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { let mut r = a; let mut d = Zero::zero::(); let mut n = 1; @@ -464,7 +464,7 @@ pub impl BigUint { return r; } fn quotrem(&self, other: &BigUint) -> (BigUint, BigUint) { - self.divmod(other) + self.quot_rem(other) } fn is_zero(&self) -> bool { self.data.is_empty() } @@ -737,16 +737,16 @@ impl Mul for BigInt { } } -impl Div for BigInt { - fn div(&self, other: &BigInt) -> BigInt { - let (d, _) = self.divmod(other); +impl Quot for BigInt { + fn quot(&self, other: &BigInt) -> BigInt { + let (d, _) = self.quot_rem(other); return d; } } -impl Modulo for BigInt { - fn modulo(&self, other: &BigInt) -> BigInt { - let (_, m) = self.divmod(other); +impl Rem for BigInt { + fn rem(&self, other: &BigInt) -> BigInt { + let (_, m) = self.quot_rem(other); return m; } } @@ -841,9 +841,9 @@ pub impl BigInt { BigInt::from_biguint(Plus, copy self.data) } - fn divmod(&self, other: &BigInt) -> (BigInt, BigInt) { + fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign - let (d_ui, m_ui) = self.data.divmod(&other.data); + let (d_ui, m_ui) = self.data.quot_rem(&other.data); let d = BigInt::from_biguint(Plus, d_ui), m = BigInt::from_biguint(Plus, m_ui); match (self.sign, other.sign) { @@ -1150,7 +1150,7 @@ mod biguint_tests { (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]) ]; - static divmod_quadruples: &'static [(&'static [BigDigit], + static quot_rem_quadruples: &'static [(&'static [BigDigit], &'static [BigDigit], &'static [BigDigit], &'static [BigDigit])] @@ -1174,7 +1174,7 @@ mod biguint_tests { assert!(b * a == c); } - for divmod_quadruples.each |elm| { + for quot_rem_quadruples.each |elm| { let (aVec, bVec, cVec, dVec) = *elm; let a = BigUint::from_slice(aVec); let b = BigUint::from_slice(bVec); @@ -1187,7 +1187,7 @@ mod biguint_tests { } #[test] - fn test_divmod() { + fn test_quot_rem() { for mul_triples.each |elm| { let (aVec, bVec, cVec) = *elm; let a = BigUint::from_slice(aVec); @@ -1195,21 +1195,21 @@ mod biguint_tests { let c = BigUint::from_slice(cVec); if a.is_not_zero() { - assert!(c.divmod(&a) == (b, Zero::zero())); + assert!(c.quot_rem(&a) == (b, Zero::zero())); } if b.is_not_zero() { - assert!(c.divmod(&b) == (a, Zero::zero())); + assert!(c.quot_rem(&b) == (a, Zero::zero())); } } - for divmod_quadruples.each |elm| { + for quot_rem_quadruples.each |elm| { let (aVec, bVec, cVec, dVec) = *elm; let a = BigUint::from_slice(aVec); let b = BigUint::from_slice(bVec); let c = BigUint::from_slice(cVec); let d = BigUint::from_slice(dVec); - if b.is_not_zero() { assert!(a.divmod(&b) == (c, d)); } + if b.is_not_zero() { assert!(a.quot_rem(&b) == (c, d)); } } } @@ -1516,7 +1516,7 @@ mod bigint_tests { (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]) ]; - static divmod_quadruples: &'static [(&'static [BigDigit], + static quot_rem_quadruples: &'static [(&'static [BigDigit], &'static [BigDigit], &'static [BigDigit], &'static [BigDigit])] @@ -1543,7 +1543,7 @@ mod bigint_tests { assert!((-b) * a == -c); } - for divmod_quadruples.each |elm| { + for quot_rem_quadruples.each |elm| { let (aVec, bVec, cVec, dVec) = *elm; let a = BigInt::from_slice(Plus, aVec); let b = BigInt::from_slice(Plus, bVec); @@ -1556,9 +1556,9 @@ mod bigint_tests { } #[test] - fn test_divmod() { + fn test_quot_rem() { fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { - let (d, m) = a.divmod(b); + let (d, m) = a.quot_rem(b); if m.is_not_zero() { assert!(m.sign == b.sign); } @@ -1592,7 +1592,7 @@ mod bigint_tests { if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); } } - for divmod_quadruples.each |elm| { + for quot_rem_quadruples.each |elm| { let (aVec, bVec, cVec, dVec) = *elm; let a = BigInt::from_slice(Plus, aVec); let b = BigInt::from_slice(Plus, bVec); @@ -1635,7 +1635,7 @@ mod bigint_tests { if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); } } - for divmod_quadruples.each |elm| { + for quot_rem_quadruples.each |elm| { let (aVec, bVec, cVec, dVec) = *elm; let a = BigInt::from_slice(Plus, aVec); let b = BigInt::from_slice(Plus, bVec); diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs index 949850f3ca677..ef7fa397d7f1b 100644 --- a/src/libstd/num/complex.rs +++ b/src/libstd/num/complex.rs @@ -32,8 +32,7 @@ pub type Complex = Cmplx; pub type Complex32 = Cmplx; pub type Complex64 = Cmplx; -impl + Sub + Mul + Div + Neg> - Cmplx { +impl Cmplx { /// Create a new Cmplx #[inline] pub fn new(re: T, im: T) -> Cmplx { @@ -80,24 +79,21 @@ impl + Sub + Mul + Div + Neg> /* arithmetic */ // (a + i b) + (c + i d) == (a + c) + i (b + d) -impl + Sub + Mul + Div + Neg> - Add, Cmplx> for Cmplx { +impl Add, Cmplx> for Cmplx { #[inline] fn add(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re + other.re, self.im + other.im) } } // (a + i b) - (c + i d) == (a - c) + i (b - d) -impl + Sub + Mul + Div + Neg> - Sub, Cmplx> for Cmplx { +impl Sub, Cmplx> for Cmplx { #[inline] fn sub(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re - other.re, self.im - other.im) } } // (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) -impl + Sub + Mul + Div + Neg> - Mul, Cmplx> for Cmplx { +impl Mul, Cmplx> for Cmplx { #[inline] fn mul(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re*other.re - self.im*other.im, @@ -107,18 +103,16 @@ impl + Sub + Mul + Div + Neg> // (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d) // == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)] -impl + Sub + Mul + Div + Neg> - Div, Cmplx> for Cmplx { +impl Quot, Cmplx> for Cmplx { #[inline] - fn div(&self, other: &Cmplx) -> Cmplx { + fn quot(&self, other: &Cmplx) -> Cmplx { let norm_sqr = other.norm_sqr(); Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr, (self.im*other.re - self.re*other.im) / norm_sqr) } } -impl + Sub + Mul + Div + Neg> - Neg> for Cmplx { +impl Neg> for Cmplx { #[inline] fn neg(&self) -> Cmplx { Cmplx::new(-self.re, -self.im) @@ -126,16 +120,14 @@ impl + Sub + Mul + Div + Neg> } /* constants */ -impl + Sub + Mul + Div + Neg + Zero> - Zero for Cmplx { +impl Zero for Cmplx { #[inline] fn zero() -> Cmplx { Cmplx::new(Zero::zero(), Zero::zero()) } } -impl + Sub + Mul + Div + Neg + Zero + One> - One for Cmplx { +impl One for Cmplx { #[inline] fn one() -> Cmplx { Cmplx::new(One::one(), Zero::zero()) @@ -143,7 +135,7 @@ impl + Sub + Mul + Div + Neg + Zero + One> } /* string conversions */ -impl> ToStr for Cmplx { +impl ToStr for Cmplx { fn to_str(&self) -> ~str { if self.im < Zero::zero() { fmt!("%s-%si", self.re.to_str(), (-self.im).to_str()) @@ -153,7 +145,7 @@ impl> ToStr for Cmplx { } } -impl> ToStrRadix for Cmplx { +impl ToStrRadix for Cmplx { fn to_str_radix(&self, radix: uint) -> ~str { if self.im < Zero::zero() { fmt!("%s-%si", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix)) @@ -280,7 +272,7 @@ mod test { } } #[test] - fn test_div() { + fn test_quot() { assert_eq!(_neg1_1i / _0_1i, _1_1i); for all_consts.each |&c| { if c != Zero::zero() { diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs index f15b382dcd351..2098429833dfc 100644 --- a/src/libstd/num/rational.rs +++ b/src/libstd/num/rational.rs @@ -33,7 +33,7 @@ pub type Rational64 = Ratio; /// Alias for arbitrary precision rationals. pub type BigRational = Ratio; -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl Ratio { /// Create a ratio representing the integer `t`. #[inline(always)] @@ -51,7 +51,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq> #[inline(always)] pub fn new(numer: T, denom: T) -> Ratio { if denom == Zero::zero() { - fail!(~"divide by 0"); + fail!(~"quotient of 0"); } let mut ret = Ratio::new_raw(numer, denom); ret.reduce(); @@ -85,7 +85,7 @@ Compute the greatest common divisor of two numbers, via Euclid's algorithm. The result can be negative. */ #[inline] -pub fn gcd_raw + Zero + Eq>(n: T, m: T) -> T { +pub fn gcd_raw(n: T, m: T) -> T { let mut m = m, n = n; while m != Zero::zero() { let temp = m; @@ -101,7 +101,7 @@ Compute the greatest common divisor of two numbers, via Euclid's algorithm. The result is always positive. */ #[inline] -pub fn gcd + Neg + Zero + Ord + Eq>(n: T, m: T) -> T { +pub fn gcd(n: T, m: T) -> T { let g = gcd_raw(n, m); if g < Zero::zero() { -g } else { g } @@ -136,7 +136,7 @@ cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering) /* Arithmetic */ // a/b * c/d = (a*c)/(b*d) -impl + Div + Modulo + Neg + Zero + One + Ord + Eq> +impl Mul,Ratio> for Ratio { #[inline] fn mul(&self, rhs: &Ratio) -> Ratio { @@ -145,10 +145,10 @@ impl + Div + Modulo + Neg + Zero + One + Ord + E } // (a/b) / (c/d) = (a*d)/(b*c) -impl + Div + Modulo + Neg + Zero + One + Ord + Eq> - Div,Ratio> for Ratio { +impl + Quot,Ratio> for Ratio { #[inline] - fn div(&self, rhs: &Ratio) -> Ratio { + fn quot(&self, rhs: &Ratio) -> Ratio { Ratio::new(self.numer * rhs.denom, self.denom * rhs.numer) } } @@ -156,9 +156,7 @@ impl + Div + Modulo + Neg + Zero + One + Ord + E // Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern macro_rules! arith_impl { (impl $imp:ident, $method:ident) => { - impl + Sub + Mul + Div + Modulo + Neg + - Zero + One + Ord + Eq> + impl $imp,Ratio> for Ratio { #[inline] fn $method(&self, rhs: &Ratio) -> Ratio { @@ -176,9 +174,9 @@ arith_impl!(impl Add, add) arith_impl!(impl Sub, sub) // a/b % c/d = (a*d % b*c)/(b*d) -arith_impl!(impl Modulo, modulo) +arith_impl!(impl Rem, rem) -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl Neg> for Ratio { #[inline] fn neg(&self) -> Ratio { @@ -187,7 +185,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq> } /* Constants */ -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl Zero for Ratio { #[inline] fn zero() -> Ratio { @@ -195,7 +193,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq> } } -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl One for Ratio { #[inline] fn one() -> Ratio { @@ -204,8 +202,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq> } /* Utils */ -impl + Sub + Mul + Div + Modulo + Neg + - Zero + One + Ord + Eq> +impl Round for Ratio { fn round(&self, mode: num::RoundMode) -> Ratio { match mode { @@ -256,7 +253,7 @@ impl ToStrRadix for Ratio { } } -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl FromStr for Ratio { /// Parses `numer/denom`. fn from_str(s: &str) -> Option> { @@ -273,7 +270,7 @@ impl + Modulo + Neg + Zero + One + Ord + Eq } } } -impl + Modulo + Neg + Zero + One + Ord + Eq> +impl FromStrRadix for Ratio { /// Parses `numer/denom` where the numbers are in base `radix`. fn from_str_radix(s: &str, radix: uint) -> Option> { @@ -386,14 +383,14 @@ mod test { } #[test] - fn test_div() { + fn test_quot() { assert_eq!(_1 / _1_2, _2); assert_eq!(_3_2 / _1_2, _1 + _2); assert_eq!(_1 / _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2); } #[test] - fn test_modulo() { + fn test_rem() { assert_eq!(_3_2 % _1, _1_2); assert_eq!(_2 % _neg1_2, _0); assert_eq!(_1_2 % _2, _1_2); @@ -415,7 +412,7 @@ mod test { } #[test] #[should_fail] - fn test_div_0() { + fn test_quot_0() { let _a = _1 / _0; } } diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 3dfc3200f0f52..7bedef0f84110 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -98,10 +98,19 @@ pub mod cmp; pub mod base64; pub mod rl; pub mod workcache; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] #[path="num/bigint.rs"] pub mod bigint; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] #[path="num/rational.rs"] pub mod rational; +#[cfg(stage1)] +#[cfg(stage2)] +#[cfg(stage3)] #[path="num/complex.rs"] pub mod complex; pub mod stats; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b0b3e45abe501..a086a1db0aaf1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -389,7 +389,7 @@ pub enum binop { add, subtract, mul, - div, + quot, rem, and, or, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 910c9857d2d63..f0a14b39049a8 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -80,7 +80,7 @@ pub fn binop_to_str(op: binop) -> ~str { add => return ~"+", subtract => return ~"-", mul => return ~"*", - div => return ~"/", + quot => return ~"/", rem => return ~"%", and => return ~"&&", or => return ~"||", @@ -103,8 +103,8 @@ pub fn binop_to_method_name(op: binop) -> Option<~str> { add => return Some(~"add"), subtract => return Some(~"sub"), mul => return Some(~"mul"), - div => return Some(~"div"), - rem => return Some(~"modulo"), + quot => return Some(~"quot"), + rem => return Some(~"rem"), bitxor => return Some(~"bitxor"), bitand => return Some(~"bitand"), bitor => return Some(~"bitor"), @@ -348,7 +348,7 @@ pub fn is_self(d: ast::def) -> bool { /// Maps a binary operator to its precedence pub fn operator_prec(op: ast::binop) -> uint { match op { - mul | div | rem => 12u, + mul | quot | rem => 12u, // 'as' sits between here with 11 add | subtract => 10u, shl | shr => 9u, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e892f212b0577..42275aca0a3e2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -21,7 +21,7 @@ use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; use ast::{bind_by_copy, bitand, bitor, bitxor, blk}; use ast::{blk_check_mode, box, by_copy, by_ref}; use ast::{crate, crate_cfg, decl, decl_item}; -use ast::{decl_local, default_blk, deref, div, enum_def}; +use ast::{decl_local, default_blk, deref, quot, enum_def}; use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again}; use ast::{expr_assign, expr_assign_op, expr_binary, expr_block}; use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body}; @@ -1786,7 +1786,7 @@ pub impl Parser { token::PLUS => aop = add, token::MINUS => aop = subtract, token::STAR => aop = mul, - token::SLASH => aop = div, + token::SLASH => aop = quot, token::PERCENT => aop = rem, token::CARET => aop = bitxor, token::AND => aop = bitand, diff --git a/src/libsyntax/parse/prec.rs b/src/libsyntax/parse/prec.rs index 79adabec9b773..d8c829740fa3f 100644 --- a/src/libsyntax/parse/prec.rs +++ b/src/libsyntax/parse/prec.rs @@ -31,7 +31,7 @@ pub static as_prec: uint = 11u; pub fn token_to_binop(tok: Token) -> Option { match tok { BINOP(STAR) => Some(mul), - BINOP(SLASH) => Some(div), + BINOP(SLASH) => Some(quot), BINOP(PERCENT) => Some(rem), // 'as' sits between here with 11 BINOP(PLUS) => Some(add), diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs index d8443f836f50a..d368f9d6769de 100644 --- a/src/test/compile-fail/eval-enum.rs +++ b/src/test/compile-fail/eval-enum.rs @@ -1,6 +1,6 @@ enum test { - div_zero = 1/0, //~ERROR expected constant: divide by zero - rem_zero = 1%0 //~ERROR expected constant: modulo zero + quot_zero = 1/0, //~ERROR expected constant: quotient zero + rem_zero = 1%0 //~ERROR expected constant: remainder zero } fn main() {} diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs index 6bad7ab194acd..7a17dd024153c 100644 --- a/src/test/run-fail/divide-by-zero.rs +++ b/src/test/run-fail/divide-by-zero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:divide by zero +// error-pattern:quotient zero fn main() { let y = 0; let z = 1 / y; diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs index 05ff7bd96bdf8..c379a8fc65fd7 100644 --- a/src/test/run-fail/mod-zero.rs +++ b/src/test/run-fail/mod-zero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:modulo zero +// error-pattern:remainder zero fn main() { let y = 0; let z = 1 % y; From 5cc6a0bf327e84569166d0ae7c07615e5afd5238 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 10 Apr 2013 10:28:26 -0400 Subject: [PATCH 341/403] rt: Make the C stack segment accessible to runtime users. --- src/libcore/gc.rs | 1 + src/rt/rust_builtin.cpp | 5 +++++ src/rt/rust_task.h | 1 + src/rt/rustrt.def.in | 1 + 4 files changed, 8 insertions(+) diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 9fd9ac3a8c8ec..7262c4f58f50a 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -73,6 +73,7 @@ pub mod rustrt { pub unsafe fn rust_gc_metadata() -> *Word; pub unsafe fn rust_get_stack_segment() -> *StackSegment; + pub unsafe fn rust_get_c_stack() -> *StackSegment; } } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 3c6cc9d924522..a2bbaf80c0aa8 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -544,6 +544,11 @@ rust_get_stack_segment() { return rust_get_current_task()->stk; } +extern "C" CDECL stk_seg * +rust_get_c_stack() { + return rust_get_current_task()->get_c_stack(); +} + extern "C" CDECL void start_task(rust_task *target, fn_env_pair *f) { target->start(f->f, f->env, NULL); diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 00d20fefc0ee5..a529db7d31752 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -367,6 +367,7 @@ rust_task : public kernel_owned void call_on_c_stack(void *args, void *fn_ptr); void call_on_rust_stack(void *args, void *fn_ptr); bool have_c_stack() { return c_stack != NULL; } + stk_seg *get_c_stack() { return c_stack; } rust_task_state get_state() { return state; } rust_cond *get_cond() { return cond; } diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 73dbe661d3f86..b7ca28d5960da 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -48,6 +48,7 @@ rust_task_yield rust_task_is_unwinding rust_get_task rust_get_stack_segment +rust_get_c_stack rust_log_str start_task vec_reserve_shared_actual From 7f45ae54ea6609febda24a116e8c30b8fcda466b Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 7 Apr 2013 15:12:39 -0700 Subject: [PATCH 342/403] Fix LLVM bug affecting i1 switches emitted for nullable enum match. --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index 56dd407f4f97a..2e9f0d21fe321 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 56dd407f4f97a01b8df6554c569170d2fc276fcb +Subproject commit 2e9f0d21fe321849a4759a01fc28eae82ef196d6 From e6c4471ed8c54a035f1cc2096d04cc44fd4cd14b Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 22 Apr 2013 16:02:24 +1000 Subject: [PATCH 343/403] libstd: denominator isn't quotient --- src/libstd/num/rational.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs index 2098429833dfc..ee6879e31d974 100644 --- a/src/libstd/num/rational.rs +++ b/src/libstd/num/rational.rs @@ -51,7 +51,7 @@ impl #[inline(always)] pub fn new(numer: T, denom: T) -> Ratio { if denom == Zero::zero() { - fail!(~"quotient of 0"); + fail!(~"denominator == 0"); } let mut ret = Ratio::new_raw(numer, denom); ret.reduce(); From 56679024c551c51a1eea8a03dbe8570f56687521 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 22 Apr 2013 19:01:48 +1000 Subject: [PATCH 344/403] libcore: Rand impls for tuples and ~/@ boxes --- src/libcore/rand.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index a2f103fdbc90e..1e33f382df544 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -115,6 +115,40 @@ impl Rand for bool { } } +macro_rules! tuple_impl { + // use variables to indicate the arity of the tuple + ($($tyvar:ident),* ) => { + // the trailing commas are for the 1 tuple + impl< + $( $tyvar : Rand ),* + > Rand for ( $( $tyvar ),* , ) { + + fn rand (_rng: @Rng) -> ( $( $tyvar ),* , ) { + ( + // use the $var's to get the appropriate number of repeats + // (they're not actually needed) + $( + _rng.gen::<$tyvar>() + ),* + , + ) + } + } + } +} + +impl Rand for () { fn rand(_: @Rng) -> () { () } } +tuple_impl!{A} +tuple_impl!{A, B} +tuple_impl!{A, B, C} +tuple_impl!{A, B, C, D} +tuple_impl!{A, B, C, D, E} +tuple_impl!{A, B, C, D, E, F} +tuple_impl!{A, B, C, D, E, F, G} +tuple_impl!{A, B, C, D, E, F, G, H} +tuple_impl!{A, B, C, D, E, F, G, H, I} +tuple_impl!{A, B, C, D, E, F, G, H, I, J} + impl Rand for Option { fn rand(rng: @rand::Rng) -> Option { if rng.gen_bool() { @@ -125,6 +159,14 @@ impl Rand for Option { } } +impl Rand for ~T { + fn rand(rng: @Rng) -> ~T { ~rng.gen() } +} + +impl Rand for @T { + fn rand(rng: @Rng) -> @T { @rng.gen() } +} + #[allow(non_camel_case_types)] // runtime type pub enum rust_rng {} @@ -927,6 +969,10 @@ mod tests { let _n : uint = rand::random(); let _f : f32 = rand::random(); let _o : Option> = rand::random(); + let _many : ((), + (~uint, @int, ~Option<~(@char, ~(@bool,))>), + (u8, i8, u16, i16, u32, i32, u64, i64), + (f32, (f64, (float,)))) = rand::random(); } } From ba1f3c9b1fdf2c5ff8426f1a2ac97fd8f6429505 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Mon, 22 Apr 2013 20:17:25 +0900 Subject: [PATCH 345/403] Convert to C string inside WriteOutputFile --- src/librustc/back/link.rs | 99 +++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 57 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3dfa318826b7b..3d2b46eb51abd 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -61,23 +61,28 @@ pub fn llvm_err(sess: Session, msg: ~str) -> ! { pub fn WriteOutputFile(sess: Session, PM: lib::llvm::PassManagerRef, M: ModuleRef, - Triple: *c_char, + Triple: &str, + Output: &str, // FIXME: When #2334 is fixed, change // c_uint to FileType - Output: *c_char, FileType: c_uint, + FileType: c_uint, OptLevel: c_int, EnableSegmentedStacks: bool) { unsafe { - let result = llvm::LLVMRustWriteOutputFile( - PM, - M, - Triple, - Output, - FileType, - OptLevel, - EnableSegmentedStacks); - if (!result) { - llvm_err(sess, ~"Could not write output"); + do str::as_c_str(Triple) |Triple| { + do str::as_c_str(Output) |Output| { + let result = llvm::LLVMRustWriteOutputFile( + PM, + M, + Triple, + Output, + FileType, + OptLevel, + EnableSegmentedStacks); + if (!result) { + llvm_err(sess, ~"Could not write output"); + } + } } } } @@ -310,66 +315,46 @@ pub mod write { llvm::LLVMWriteBitcodeToFile(llmod, buf) }); pm = mk_pass_manager(); - // Save the assembly file if -S is used + // Save the assembly file if -S is used if output_type == output_type_assembly { - let _: () = str::as_c_str( + WriteOutputFile( + sess, + pm.llpm, + llmod, sess.targ_cfg.target_strs.target_triple, - |buf_t| { - str::as_c_str(output.to_str(), |buf_o| { - WriteOutputFile( - sess, - pm.llpm, - llmod, - buf_t, - buf_o, - lib::llvm::AssemblyFile as c_uint, - CodeGenOptLevel, - true) - }) - }); + output.to_str(), + lib::llvm::AssemblyFile as c_uint, + CodeGenOptLevel, + true); } - // Save the object file for -c or --save-temps alone // This .o is needed when an exe is built if output_type == output_type_object || output_type == output_type_exe { - let _: () = str::as_c_str( + WriteOutputFile( + sess, + pm.llpm, + llmod, sess.targ_cfg.target_strs.target_triple, - |buf_t| { - str::as_c_str(output.to_str(), |buf_o| { - WriteOutputFile( - sess, - pm.llpm, - llmod, - buf_t, - buf_o, - lib::llvm::ObjectFile as c_uint, - CodeGenOptLevel, - true) - }) - }); + output.to_str(), + lib::llvm::ObjectFile as c_uint, + CodeGenOptLevel, + true); } } else { // If we aren't saving temps then just output the file // type corresponding to the '-c' or '-S' flag used - - let _: () = str::as_c_str( + WriteOutputFile( + sess, + pm.llpm, + llmod, sess.targ_cfg.target_strs.target_triple, - |buf_t| { - str::as_c_str(output.to_str(), |buf_o| { - WriteOutputFile( - sess, - pm.llpm, - llmod, - buf_t, - buf_o, - FileType as c_uint, - CodeGenOptLevel, - true) - }) - }); + output.to_str(), + FileType as c_uint, + CodeGenOptLevel, + true); } // Clean up and return From da4bc490e6fcd8042f6ce49da0039d38c22d37f4 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Mon, 22 Apr 2013 20:54:12 +0900 Subject: [PATCH 346/403] Choose target features --- src/librustc/back/link.rs | 29 ++++++++++++++++++----------- src/librustc/driver/driver.rs | 9 +++++++++ src/librustc/driver/session.rs | 2 ++ src/librustc/lib/llvm.rs | 3 ++- src/rustllvm/RustWrapper.cpp | 3 ++- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3d2b46eb51abd..6bf09f30898c2 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -62,6 +62,7 @@ pub fn llvm_err(sess: Session, msg: ~str) -> ! { pub fn WriteOutputFile(sess: Session, PM: lib::llvm::PassManagerRef, M: ModuleRef, Triple: &str, + Feature: &str, Output: &str, // FIXME: When #2334 is fixed, change // c_uint to FileType @@ -70,17 +71,20 @@ pub fn WriteOutputFile(sess: Session, EnableSegmentedStacks: bool) { unsafe { do str::as_c_str(Triple) |Triple| { - do str::as_c_str(Output) |Output| { - let result = llvm::LLVMRustWriteOutputFile( - PM, - M, - Triple, - Output, - FileType, - OptLevel, - EnableSegmentedStacks); - if (!result) { - llvm_err(sess, ~"Could not write output"); + do str::as_c_str(Feature) |Feature| { + do str::as_c_str(Output) |Output| { + let result = llvm::LLVMRustWriteOutputFile( + PM, + M, + Triple, + Feature, + Output, + FileType, + OptLevel, + EnableSegmentedStacks); + if (!result) { + llvm_err(sess, ~"Could not write output"); + } } } } @@ -323,6 +327,7 @@ pub mod write { pm.llpm, llmod, sess.targ_cfg.target_strs.target_triple, + opts.target_feature, output.to_str(), lib::llvm::AssemblyFile as c_uint, CodeGenOptLevel, @@ -338,6 +343,7 @@ pub mod write { pm.llpm, llmod, sess.targ_cfg.target_strs.target_triple, + opts.target_feature, output.to_str(), lib::llvm::ObjectFile as c_uint, CodeGenOptLevel, @@ -351,6 +357,7 @@ pub mod write { pm.llpm, llmod, sess.targ_cfg.target_strs.target_triple, + opts.target_feature, output.to_str(), FileType as c_uint, CodeGenOptLevel, diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index fae73d7faf2d4..857a06f13f91c 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -599,6 +599,7 @@ pub fn build_session_options(binary: @~str, let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot"); let sysroot_opt = sysroot_opt.map(|m| Path(*m)); let target_opt = getopts::opt_maybe_str(matches, ~"target"); + let target_feature_opt = getopts::opt_maybe_str(matches, ~"target-feature"); let save_temps = getopts::opt_present(matches, ~"save-temps"); match output_type { // unless we're emitting huamn-readable assembly, omit comments. @@ -637,6 +638,10 @@ pub fn build_session_options(binary: @~str, None => host_triple(), Some(s) => s }; + let target_feature = match target_feature_opt { + None => ~"", + Some(s) => s + }; let addl_lib_search_paths = getopts::opt_strs(matches, ~"L") @@ -659,6 +664,7 @@ pub fn build_session_options(binary: @~str, addl_lib_search_paths: addl_lib_search_paths, maybe_sysroot: sysroot_opt, target_triple: target, + target_feature: target_feature, cfg: cfg, binary: binary, test: test, @@ -769,6 +775,9 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] { ~"Target triple cpu-manufacturer-kernel[-os] to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/ for detail)", ~"TRIPLE"), + optopt(~"", ~"target-feature", + ~"Target specific attributes (llc -mattr=help + for detail)", ~"FEATURE"), optopt(~"", ~"android-cross-path", ~"The path to the Android NDK", "PATH"), optmulti(~"W", ~"warn", diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 1912c922524fb..a2bbbca0c5aaf 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -126,6 +126,7 @@ pub struct options { addl_lib_search_paths: ~[Path], maybe_sysroot: Option, target_triple: ~str, + target_feature: ~str, // User-specified cfg meta items. The compiler itself will add additional // items to the crate config, and during parsing the entire crate config // will be added to the crate AST node. This should not be used for @@ -302,6 +303,7 @@ pub fn basic_options() -> @options { addl_lib_search_paths: ~[], maybe_sysroot: None, target_triple: host_triple(), + target_feature: ~"", cfg: ~[], binary: @~"rustc", test: false, diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 369e6aeb4a598..1ab84c7978c22 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -1799,9 +1799,10 @@ pub mod llvm { pub unsafe fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef, Triple: *c_char, + Feature: *c_char, + Output: *c_char, // FIXME: When #2334 is fixed, // change c_uint to FileType - Output: *c_char, FileType: c_uint, OptLevel: c_int, EnableSegmentedStacks: bool) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 141276e86f098..451a390876c6b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -434,6 +434,7 @@ extern "C" bool LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, LLVMModuleRef M, const char *triple, + const char *feature, const char *path, TargetMachine::CodeGenFileType FileType, CodeGenOpt::Level OptLevel, @@ -461,7 +462,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR, std::string Err; std::string Trip(Triple::normalize(triple)); - std::string FeaturesStr; + std::string FeaturesStr(feature); std::string CPUStr("generic"); const Target *TheTarget = TargetRegistry::lookupTarget(Trip, Err); TargetMachine *Target = From 70452e5231d4101811b2ea6a2c4be4adc2b5460b Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sat, 6 Apr 2013 19:52:35 -0700 Subject: [PATCH 347/403] Consider nullability for equivalence of monomorphized fns. --- src/librustc/middle/trans/base.rs | 5 ++++ src/librustc/middle/trans/common.rs | 33 ++++++++++++++++++++++- src/librustc/middle/trans/monomorphize.rs | 14 +++------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 3ad021b2f518f..2d9f834040a8e 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2007,6 +2007,11 @@ pub fn trans_enum_variant(ccx: @CrateContext, // XXX is there a better way to reconstruct the ty::t? let repr = adt::represent_type(ccx, enum_ty); + debug!("trans_enum_variant: name=%s tps=%s repr=%? enum_ty=%s", + unsafe { str::raw::from_c_str(llvm::LLVMGetValueName(llfndecl)) }, + ~"[" + str::connect(ty_param_substs.map(|&t| ty_to_str(ccx.tcx, t)), ", ") + ~"]", + repr, ty_to_str(ccx.tcx, enum_ty)); + adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); for vec::eachi(args) |i, va| { let lldestptr = adt::trans_field_ptr(bcx, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 3180fb5a4c8f4..faf7ddd4ff7c1 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1311,10 +1311,35 @@ pub enum mono_param_id { mono_any, mono_repr(uint /* size */, uint /* align */, - bool /* is_float */, + MonoDataClass, datum::DatumMode), } +#[deriving(Eq)] +pub enum MonoDataClass { + MonoBits, // Anything not treated differently from arbitrary integer data + MonoNonNull, // Non-null pointers (used for optional-pointer optimization) + // FIXME(#3547)---scalars and floats are + // treated differently in most ABIs. But we + // should be doing something more detailed + // here. + MonoFloat +} + +pub fn mono_data_classify(t: ty::t) -> MonoDataClass { + match ty::get(t).sty { + ty::ty_float(_) => MonoFloat, + ty::ty_rptr(*) | ty::ty_uniq(*) | + ty::ty_box(*) | ty::ty_opaque_box(*) | + ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) | + ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) | + ty::ty_bare_fn(*) => MonoNonNull, + // Is that everything? Would closures or slices qualify? + _ => MonoBits + } +} + + #[deriving(Eq)] pub struct mono_id_ { def: ast::def_id, @@ -1338,6 +1363,12 @@ impl to_bytes::IterBytes for mono_param_id { } } +impl to_bytes::IterBytes for MonoDataClass { + fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) { + (*self as u8).iter_bytes(lsb0, f) + } +} + impl to_bytes::IterBytes for mono_id_ { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 52ca8ec49bb7f..a0fcdf7fde8bd 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -395,22 +395,14 @@ pub fn make_mono_id(ccx: @CrateContext, let size = machine::llbitsize_of_real(ccx, llty); let align = machine::llalign_of_pref(ccx, llty); let mode = datum::appropriate_mode(subst); - - // FIXME(#3547)---scalars and floats are - // treated differently in most ABIs. But we - // should be doing something more detailed - // here. - let is_float = match ty::get(subst).sty { - ty::ty_float(_) => true, - _ => false - }; + let data_class = mono_data_classify(subst); // Special value for nil to prevent problems // with undef return pointers. if size <= 8u && ty::type_is_nil(subst) { - mono_repr(0u, 0u, is_float, mode) + mono_repr(0u, 0u, data_class, mode) } else { - mono_repr(size, align, is_float, mode) + mono_repr(size, align, data_class, mode) } } else { mono_precise(subst, None) From 22f751f0f398c508be6966b9d6d1a498cd05baac Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Sun, 31 Mar 2013 15:55:30 -0700 Subject: [PATCH 348/403] Use nullable pointers to represent enums like Option<~T>. See comments in adt.rs for details. --- src/librustc/middle/trans/adt.rs | 186 ++++++++++++++++++++++------ src/librustc/middle/trans/common.rs | 6 + 2 files changed, 156 insertions(+), 36 deletions(-) diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 36958fa706ed5..7db6e44adcf16 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -29,11 +29,6 @@ * that might contain one and adjust GEP indices accordingly. See * issue #4578. * - * - Rendering `Option<&T>` as a possibly-null `*T` instead of using - * an extra word (and likewise for `@T` and `~T`). Can and probably - * should also apply to any enum with one empty case and one case - * starting with a non-null pointer (e.g., `Result<(), ~str>`). - * * - Using smaller integer types for discriminants. * * - Store nested enums' discriminants in the same word. Rather, if @@ -54,7 +49,8 @@ use core::libc::c_ulonglong; use core::option::{Option, Some, None}; use core::vec; -use lib::llvm::{ValueRef, TypeRef, True}; +use lib::llvm::{ValueRef, TypeRef, True, IntEQ, IntNE}; +use lib::llvm::llvm::LLVMDumpValue; use middle::trans::_match; use middle::trans::build::*; use middle::trans::common::*; @@ -81,7 +77,20 @@ pub enum Repr { * General-case enums: for each case there is a struct, and they * all start with a field for the discriminant. */ - General(~[Struct]) + General(~[Struct]), + /** + * Two cases distinguished by a nullable pointer: the case with discriminant + * `nndiscr` is represented by the struct `nonnull`, where the `ptrfield`th + * field is known to be nonnull due to its type; if that field is null, then + * it represents the other case, which is inhabited by at most one value + * (and all other fields are undefined/unused). + * + * For example, `core::option::Option` instantiated at a safe pointer type + * is represented such that `None` is a null pointer and `Some` is the + * identity function. + */ + NullablePointer{ nonnull: Struct, nndiscr: int, ptrfield: uint, + nullfields: ~[ty::t] } } /// For structs, and struct-like parts of anything fancier. @@ -108,9 +117,16 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { Some(repr) => return *repr, None => { } } - let repr = @match ty::get(t).sty { + let repr = @represent_type_uncached(cx, t); + debug!("Represented as: %?", repr) + cx.adt_reprs.insert(t, repr); + return repr; +} + +fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { + match ty::get(t).sty { ty::ty_tup(ref elems) => { - Univariant(mk_struct(cx, *elems, false), false) + return Univariant(mk_struct(cx, *elems, false), false) } ty::ty_struct(def_id, ref substs) => { let fields = ty::lookup_struct_fields(cx.tcx, def_id); @@ -121,10 +137,18 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { let dtor = ty::ty_dtor(cx.tcx, def_id).is_present(); let ftys = if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { ftys }; - Univariant(mk_struct(cx, ftys, packed), dtor) + return Univariant(mk_struct(cx, ftys, packed), dtor) } ty::ty_enum(def_id, ref substs) => { struct Case { discr: int, tys: ~[ty::t] }; + impl Case { + fn is_zerolen(&self, cx: @CrateContext) -> bool { + mk_struct(cx, self.tys, false).size == 0 + } + fn find_ptr(&self) -> Option { + self.tys.position(|&ty| mono_data_classify(ty) == MonoNonNull) + } + } let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| { let arg_tys = do vi.args.map |&raw_ty| { @@ -132,34 +156,59 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr { }; Case { discr: vi.disr_val, tys: arg_tys } }; + if cases.len() == 0 { // Uninhabitable; represent as unit - Univariant(mk_struct(cx, ~[], false), false) - } else if cases.all(|c| c.tys.len() == 0) { + return Univariant(mk_struct(cx, ~[], false), false); + } + + if cases.all(|c| c.tys.len() == 0) { // All bodies empty -> intlike let discrs = cases.map(|c| c.discr); - CEnum(discrs.min(), discrs.max()) - } else if cases.len() == 1 { + return CEnum(discrs.min(), discrs.max()); + } + + if cases.len() == 1 { // Equivalent to a struct/tuple/newtype. assert!(cases[0].discr == 0); - Univariant(mk_struct(cx, cases[0].tys, false), false) - } else { - // The general case. Since there's at least one - // non-empty body, explicit discriminants should have - // been rejected by a checker before this point. - if !cases.alli(|i,c| c.discr == (i as int)) { - cx.sess.bug(fmt!("non-C-like enum %s with specified \ - discriminants", - ty::item_path_str(cx.tcx, def_id))) + return Univariant(mk_struct(cx, cases[0].tys, false), false) + } + + // Since there's at least one + // non-empty body, explicit discriminants should have + // been rejected by a checker before this point. + if !cases.alli(|i,c| c.discr == (i as int)) { + cx.sess.bug(fmt!("non-C-like enum %s with specified \ + discriminants", + ty::item_path_str(cx.tcx, def_id))) + } + + if cases.len() == 2 { + let mut discr = 0; + while discr < 2 { + if cases[1 - discr].is_zerolen(cx) { + match cases[discr].find_ptr() { + Some(ptrfield) => { + return NullablePointer { + nndiscr: discr, + nonnull: mk_struct(cx, cases[discr].tys, false), + ptrfield: ptrfield, + nullfields: copy cases[1 - discr].tys + } + } + None => { } + } + } + discr += 1; } - let discr = ~[ty::mk_int(cx.tcx)]; - General(cases.map(|c| mk_struct(cx, discr + c.tys, false))) } + + // The general case. + let discr = ~[ty::mk_int(cx.tcx)]; + return General(cases.map(|c| mk_struct(cx, discr + c.tys, false))) } _ => cx.sess.bug(~"adt::represent_type called on non-ADT type") - }; - cx.adt_reprs.insert(t, repr); - return repr; + } } fn mk_struct(cx: @CrateContext, tys: &[ty::t], packed: bool) -> Struct { @@ -190,6 +239,7 @@ fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool) match *r { CEnum(*) => ~[T_enum_discrim(cx)], Univariant(ref st, _dtor) => struct_llfields(cx, st, sizing), + NullablePointer{ nonnull: ref st, _ } => struct_llfields(cx, st, sizing), General(ref sts) => { // To get "the" type of a general enum, we pick the case // with the largest alignment (so it will always align @@ -239,12 +289,17 @@ pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) CEnum(*) | General(*) => { (_match::switch, Some(trans_get_discr(bcx, r, scrutinee))) } + NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => { + (_match::switch, Some(nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee))) + } Univariant(*) => { (_match::single, None) } } } + + /// Obtain the actual discriminant of a value. pub fn trans_get_discr(bcx: block, r: &Repr, scrutinee: ValueRef) -> ValueRef { @@ -252,10 +307,22 @@ pub fn trans_get_discr(bcx: block, r: &Repr, scrutinee: ValueRef) CEnum(min, max) => load_discr(bcx, scrutinee, min, max), Univariant(*) => C_int(bcx.ccx(), 0), General(ref cases) => load_discr(bcx, scrutinee, 0, - (cases.len() - 1) as int) + (cases.len() - 1) as int), + NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => { + ZExt(bcx, nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee), + T_enum_discrim(bcx.ccx())) + } } } +fn nullable_bitdiscr(bcx: block, nonnull: &Struct, nndiscr: int, ptrfield: uint, + scrutinee: ValueRef) -> ValueRef { + let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; + let llptr = Load(bcx, GEPi(bcx, scrutinee, [0, ptrfield])); + let llptrty = type_of::type_of(bcx.ccx(), nonnull.fields[ptrfield]); + ICmp(bcx, cmp, llptr, C_null(llptrty)) +} + /// Helper for cases where the discriminant is simply loaded. fn load_discr(bcx: block, scrutinee: ValueRef, min: int, max: int) -> ValueRef { @@ -286,12 +353,16 @@ pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result { CEnum(*) => { _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr))) } - Univariant(*)=> { + Univariant(*) => { bcx.ccx().sess.bug(~"no cases for univariants or structs") } General(*) => { _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr))) } + NullablePointer{ _ } => { + assert!(discr == 0 || discr == 1); + _match::single_result(rslt(bcx, C_i1(discr != 0))) + } } } @@ -317,6 +388,13 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) { General(*) => { Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0])) } + NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => { + if discr != nndiscr { + let llptrptr = GEPi(bcx, val, [0, ptrfield]); + let llptrty = type_of::type_of(bcx.ccx(), nonnull.fields[ptrfield]); + Store(bcx, C_null(llptrty), llptrptr) + } + } } } @@ -331,7 +409,10 @@ pub fn num_args(r: &Repr, discr: int) -> uint { assert!(discr == 0); st.fields.len() - (if dtor { 1 } else { 0 }) } - General(ref cases) => cases[discr as uint].fields.len() - 1 + General(ref cases) => cases[discr as uint].fields.len() - 1, + NullablePointer{ nonnull: ref nonnull, nndiscr, _ } => { + if discr == nndiscr { nonnull.fields.len() } else { 0 } + } } } @@ -352,6 +433,19 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int, General(ref cases) => { struct_field_ptr(bcx, &cases[discr as uint], val, ix + 1, true) } + NullablePointer{ nonnull: ref nonnull, nullfields: ref nullfields, nndiscr, _ } => { + if (discr == nndiscr) { + struct_field_ptr(bcx, nonnull, val, ix, false) + } else { + // The unit-like case might have a nonzero number of unit-like fields. + // (e.g., Result or Either with () as one side.) + let llty = type_of::type_of(bcx.ccx(), nullfields[ix]); + assert!(machine::llsize_of_alloc(bcx.ccx(), llty) == 0); + // The contents of memory at this pointer can't matter, but use + // the value that's "reasonable" in case of pointer comparison. + PointerCast(bcx, val, T_ptr(llty)) + } + } } } @@ -420,6 +514,18 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int, ~[C_int(ccx, discr)] + vals); C_struct(contents + [padding(max_sz - case.size)]) } + NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => { + if discr == nndiscr { + C_struct(build_const_struct(ccx, nonnull, vals)) + } else { + assert!(vals.len() == 0); + let vals = do nonnull.fields.mapi |i, &ty| { + let llty = type_of::sizing_type_of(ccx, ty); + if i == ptrfield { C_null(llty) } else { C_undef(llty) } + }; + C_struct(build_const_struct(ccx, nonnull, vals)) + } + } } } @@ -451,10 +557,14 @@ fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef]) cfields.push(padding(target_offset - offset)); offset = target_offset; } - assert!(!is_undef(vals[i])); - // If that assert fails, could change it to wrap in a struct? - // (See `const_struct_field` for why real fields must not be undef.) - cfields.push(vals[i]); + let val = if is_undef(vals[i]) { + let wrapped = C_struct([vals[i]]); + assert!(!is_undef(wrapped)); + wrapped + } else { + vals[i] + }; + cfields.push(val); } return cfields; @@ -475,6 +585,9 @@ pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef) CEnum(*) => const_to_int(val) as int, Univariant(*) => 0, General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int, + NullablePointer{ nndiscr, ptrfield, _ } => { + if is_null(const_struct_field(ccx, val, ptrfield)) { 1 - nndiscr } else { nndiscr } + } } } @@ -490,7 +603,8 @@ pub fn const_get_field(ccx: @CrateContext, r: &Repr, val: ValueRef, match *r { CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"), Univariant(*) => const_struct_field(ccx, val, ix), - General(*) => const_struct_field(ccx, val, ix + 1) + General(*) => const_struct_field(ccx, val, ix + 1), + NullablePointer{ _ } => const_struct_field(ccx, val, ix) } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index faf7ddd4ff7c1..83fe135d8721f 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1304,6 +1304,12 @@ pub fn is_undef(val: ValueRef) -> bool { } } +pub fn is_null(val: ValueRef) -> bool { + unsafe { + llvm::LLVMIsNull(val) != False + } +} + // Used to identify cached monomorphized functions and vtables #[deriving(Eq)] pub enum mono_param_id { From edc1324e7e665080e6695625ba6a5ede3e32f5a8 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Mon, 22 Apr 2013 08:49:21 -0700 Subject: [PATCH 349/403] Add some tests for nullable-pointer enums --- .../nullable-pointer-iotareduction.rs | 87 +++++++++++++++++++ src/test/run-pass/nullable-pointer-size.rs | 44 ++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/test/run-pass/nullable-pointer-iotareduction.rs create mode 100644 src/test/run-pass/nullable-pointer-size.rs diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs new file mode 100644 index 0000000000000..0c4d297403cfb --- /dev/null +++ b/src/test/run-pass/nullable-pointer-iotareduction.rs @@ -0,0 +1,87 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::{option, cast}; + +// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, +// which "says that a destructor applied to an object built from a constructor +// behaves as expected". -- http://coq.inria.fr/doc/Reference-Manual006.html +// +// It's a little more complicated here, because of pointers and regions and +// trying to get assert failure messages that at least identify which case +// failed. + +enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } +impl E { + fn is_none(&self) -> bool { + match *self { + Thing(*) => false, + Nothing(*) => true + } + } + fn get_ref<'r>(&'r self) -> (int, &'r T) { + match *self { + Nothing(*) => fail!(fmt!("E::get_ref(Nothing::<%s>)", stringify!($T))), + Thing(x, ref y) => (x, y) + } + } +} + +macro_rules! check_option { + ($e:expr: $T:ty) => {{ + // FIXME #6000: remove the copy + check_option!(copy $e: $T, |ptr| assert!(*ptr == $e)); + }}; + ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ + assert!(option::None::<$T>.is_none()); + let s_ = option::Some::<$T>($e); + let $v = s_.get_ref(); + $chk + }} +} + +macro_rules! check_fancy { + ($e:expr: $T:ty) => {{ + // FIXME #6000: remove the copy + check_fancy!(copy $e: $T, |ptr| assert!(*ptr == $e)); + }}; + ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ + assert!(Nothing::<$T>((), ((), ()), [23i8, ..0]).is_none()); + let t_ = Thing::<$T>(23, $e); + match t_.get_ref() { + (23, $v) => { $chk } + _ => fail!(fmt!("Thing::<%s>(23, %s).get_ref() != (23, _)", + stringify!($T), stringify!($e))) + } + }} +} + +macro_rules! check_type { + ($($a:tt)*) => {{ + check_option!($($a)*); + check_fancy!($($a)*); + }} +} + +pub fn main() { + check_type!(&17: &int); + check_type!(~18: ~int); + check_type!(@19: @int); + check_type!(~"foo": ~str); + check_type!(@"bar": @str); + check_type!(~[]: ~[int]); + check_type!(~[20, 22]: ~[int]); + check_type!(@[]: @[int]); + check_type!(@[24, 26]: @[int]); + let mint: uint = unsafe { cast::transmute(main) }; + check_type!(main: extern fn(), |pthing| { + assert!(mint == unsafe { cast::transmute(*pthing) }) + }); +} diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs new file mode 100644 index 0000000000000..246fc4e304df3 --- /dev/null +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -0,0 +1,44 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } +struct S(int, T); + +// These are macros so we get useful assert messages. + +macro_rules! check_option { + ($T:ty) => { + assert!(sys::size_of::>() == sys::size_of::<$T>()); + } +} + +macro_rules! check_fancy { + ($T:ty) => { + assert!(sys::size_of::>() == sys::size_of::>()); + } +} + +macro_rules! check_type { + ($T:ty) => {{ + check_option!($T); + check_fancy!($T); + }} +} + +pub fn main() { + check_type!(&'static int); + check_type!(~int); + check_type!(@int); + check_type!(~str); + check_type!(@str); + check_type!(~[int]); + check_type!(@[int]); + check_type!(extern fn()); +} From c99409b332a2bee95e1139c6786c99a06cca9d3b Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 22 Apr 2013 13:01:32 -0400 Subject: [PATCH 350/403] cell: public field is unsafe use core::cell; fn main() { let x = cell::Cell(Some(~"foo")); let y = x.value.get_ref().get_ref(); do x.with_mut_ref |z| { *z = None; } println(*y) // boom! } --- src/libcore/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 1707bddc2b9d4..8c2175eeaca2d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -20,7 +20,7 @@ Similar to a mutable option type, but friendlier. */ pub struct Cell { - value: Option + priv value: Option } impl cmp::Eq for Cell { From 2c5afa4753a7a5b525be83e42a767cf556103faa Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 19 Apr 2013 22:22:46 -0700 Subject: [PATCH 351/403] libcore: Add `is_absolute()` to paths. Closes #5851. --- src/libcore/path.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 0e8dbd144b143..23f7e912f9637 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -67,6 +67,8 @@ pub trait GenericPath { fn is_restricted(&self) -> bool; fn normalize(&self) -> Self; + + fn is_absolute(&self) -> bool; } #[cfg(windows)] @@ -379,10 +381,11 @@ impl ToStr for PosixPath { // FIXME (#3227): when default methods in traits are working, de-duplicate // PosixPath and WindowsPath, most of their methods are common. impl GenericPath for PosixPath { - fn from_str(s: &str) -> PosixPath { let mut components = ~[]; - for str::each_split_nonempty(s, |c| c == '/') |s| { components.push(s.to_owned()) } + for str::each_split_nonempty(s, |c| c == '/') |s| { + components.push(s.to_owned()) + } let is_absolute = (s.len() != 0 && s[0] == '/' as u8); return PosixPath { is_absolute: is_absolute, components: components } @@ -540,6 +543,10 @@ impl GenericPath for PosixPath { // ..self } } + + fn is_absolute(&self) -> bool { + self.is_absolute + } } @@ -563,7 +570,6 @@ impl ToStr for WindowsPath { impl GenericPath for WindowsPath { - fn from_str(s: &str) -> WindowsPath { let host; let device; @@ -809,6 +815,10 @@ impl GenericPath for WindowsPath { components: normalize(self.components) } } + + fn is_absolute(&self) -> bool { + self.is_absolute + } } From 25129ee81c74f41b44bc770bd4fbdf483715a860 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 22 Apr 2013 12:32:59 -0700 Subject: [PATCH 352/403] librustc: Remove `use mod` from the language --- src/librustc/front/test.rs | 1 - src/librustc/middle/resolve.rs | 4 ++-- src/libsyntax/ast.rs | 7 +------ src/libsyntax/ast_util.rs | 5 +++-- src/libsyntax/ext/pipes/ast_builder.rs | 1 - src/libsyntax/parse/parser.rs | 21 ++++++++------------- src/libsyntax/print/pprust.rs | 5 +---- src/test/run-pass/use-mod.rs | 24 ------------------------ 8 files changed, 15 insertions(+), 53 deletions(-) delete mode 100644 src/test/run-pass/use-mod.rs diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 4a122d238d496..fdef3f6764d3b 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -274,7 +274,6 @@ fn mk_std(cx: &TestCtxt) -> @ast::view_item { ast::view_item_use( ~[@nospan(ast::view_path_simple(id_std, path_node(~[id_std]), - ast::type_value_ns, cx.sess.next_node_id()))]) } else { ast::view_item_extern_mod(id_std, ~[@mi], diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 41b372119cd29..d923ecf4bb7e9 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1413,7 +1413,7 @@ pub impl Resolver { let mut module_path = ~[]; match view_path.node { - view_path_simple(_, full_path, _, _) => { + view_path_simple(_, full_path, _) => { let path_len = full_path.idents.len(); assert!(path_len != 0); @@ -1435,7 +1435,7 @@ pub impl Resolver { // Build up the import directives. let module_ = self.get_module_from_parent(parent); match view_path.node { - view_path_simple(binding, full_path, _, _) => { + view_path_simple(binding, full_path, _) => { let source_ident = *full_path.idents.last(); let subclass = @SingleImport(binding, source_ident); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a086a1db0aaf1..4137b3b8aa1fb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1100,11 +1100,6 @@ pub struct path_list_ident_ { pub type path_list_ident = spanned; -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] -pub enum namespace { module_ns, type_value_ns } - pub type view_path = spanned; #[auto_encode] @@ -1117,7 +1112,7 @@ pub enum view_path_ { // or just // // foo::bar::baz (with 'baz =' implicitly on the left) - view_path_simple(ident, @Path, namespace, node_id), + view_path_simple(ident, @Path, node_id), // foo::bar::* view_path_glob(@Path, node_id), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f0a14b39049a8..4ae140a265e53 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -413,7 +413,7 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { view_item_use(ref vps) => { for vps.each |vp| { match vp.node { - view_path_simple(_, _, _, id) => vfn(id), + view_path_simple(_, _, id) => vfn(id), view_path_glob(_, id) => vfn(id), view_path_list(_, _, id) => vfn(id) } @@ -551,7 +551,8 @@ pub fn walk_pat(pat: @pat, it: &fn(@pat)) { pub fn view_path_id(p: @view_path) -> node_id { match p.node { - view_path_simple(_, _, _, id) | view_path_glob(_, id) | + view_path_simple(_, _, id) | + view_path_glob(_, id) | view_path_list(_, _, id) => id } } diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index e0f6c90f5b378..9434172c1f4c6 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -374,7 +374,6 @@ impl ext_ctxt_ast_builder for @ext_ctxt { ], codemap::dummy_sp() ), - ast::type_value_ns, self.next_id() ), span: codemap::dummy_sp() diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 42275aca0a3e2..8cdbf9ac9e216 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -40,7 +40,7 @@ use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const}; use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal}; -use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability}; +use ast::{match_seq, match_tok, method, mode, mt, mul, mutability}; use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum}; use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct}; use ast::{pat_tup, pat_uniq, pat_wild, private}; @@ -54,7 +54,7 @@ use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box}; use ast::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn}; use ast::{ty_infer, ty_method}; use ast::{ty_nil, TyParam, TyParamBound, ty_path, ty_ptr, ty_rptr}; -use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq}; +use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, uniq}; use ast::{unnamed_field, unsafe_blk, unsafe_fn, view_item}; use ast::{view_item_, view_item_extern_mod, view_item_use}; use ast::{view_path, view_path_glob, view_path_list, view_path_simple}; @@ -4224,13 +4224,6 @@ pub impl Parser { fn parse_view_path(&self) -> @view_path { let lo = self.span.lo; - let namespace; - if self.eat_keyword(&~"mod") { - namespace = module_ns; - } else { - namespace = type_value_ns; - } - let first_ident = self.parse_ident(); let mut path = ~[first_ident]; debug!("parsed view_path: %s", *self.id_to_str(first_ident)); @@ -4250,8 +4243,9 @@ pub impl Parser { rp: None, types: ~[] }; return @spanned(lo, self.span.hi, - view_path_simple(first_ident, path, namespace, - self.get_id())); + view_path_simple(first_ident, + path, + self.get_id())); } token::MOD_SEP => { @@ -4306,8 +4300,9 @@ pub impl Parser { idents: path, rp: None, types: ~[] }; - return @spanned(lo, self.span.hi, - view_path_simple(last, path, namespace, self.get_id())); + return @spanned(lo, + self.span.hi, + view_path_simple(last, path, self.get_id())); } // matches view_paths = view_path | view_path , view_paths diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8cf7359956283..3ea04c8e40bf6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1816,10 +1816,7 @@ pub fn print_meta_item(s: @ps, item: @ast::meta_item) { pub fn print_view_path(s: @ps, vp: @ast::view_path) { match vp.node { - ast::view_path_simple(ident, path, namespace, _) => { - if namespace == ast::module_ns { - word_space(s, ~"mod"); - } + ast::view_path_simple(ident, path, _) => { if path.idents[vec::len(path.idents)-1u] != ident { print_ident(s, ident); space(s.s); diff --git a/src/test/run-pass/use-mod.rs b/src/test/run-pass/use-mod.rs deleted file mode 100644 index 1b1402e0a0e7c..0000000000000 --- a/src/test/run-pass/use-mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -// xfail-fast - -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use mod a::b; - -mod a { - pub mod b { - pub fn f() {} - } -} - -pub fn main() { - b::f(); -} - From 582a05fc95c8adf6ecf6318ea09ed6cd5bbe5b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Mon, 22 Apr 2013 21:42:25 +0200 Subject: [PATCH 353/403] Moved ascii out of str Removed deriving Ord, which allowed to remove the stage markers --- src/libcore/core.rc | 3 +++ src/libcore/prelude.rs | 6 +---- src/libcore/str.rs | 13 ---------- src/libcore/str/ascii.rs | 51 ++++++++++++++++++++++++---------------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 81190ea8fc62e..6d38d72e3f649 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -159,6 +159,9 @@ pub mod vec; pub mod at_vec; pub mod str; +#[path = "str/ascii.rs"] +pub mod ascii; + pub mod ptr; pub mod owned; pub mod managed; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 8479369458258..fb4f9188b3bd0 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -40,11 +40,7 @@ pub use path::Path; pub use path::PosixPath; pub use path::WindowsPath; pub use ptr::Ptr; -// NOTE: Remove markers after snapshot -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] -pub use str::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii}; +pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; pub use str::{StrSlice, OwnedStr}; pub use to_bytes::IterBytes; pub use to_str::{ToStr, ToStrConsume}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 11301c9f1dbdb..dc97af22c470f 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -17,12 +17,6 @@ * some heavy-duty uses, try std::rope. */ -// NOTE: Remove markers after snapshot -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] -pub use self::ascii::{Ascii, AsciiCast, OwnedAsciiCast, ToStrAscii}; - use at_vec; use cast; use char; @@ -40,13 +34,6 @@ use to_str::ToStr; #[cfg(notest)] use cmp::{Eq, Ord, Equiv, TotalEq}; -// NOTE: Remove markers after snapshot -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] -#[path = "str/ascii.rs"] -mod ascii; - /* Section: Creating a string */ diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 7de62a2c9347c..447ca3497e873 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -12,12 +12,8 @@ use to_str::{ToStr,ToStrConsume}; use str; use cast; -#[cfg(test)] -pub struct Ascii { priv chr: u8 } - /// Datatype to hold one ascii character. It is 8 bit long. -#[cfg(notest)] -#[deriving(Clone, Eq, Ord)] +#[deriving(Clone, Eq)] pub struct Ascii { priv chr: u8 } pub impl Ascii { @@ -163,18 +159,35 @@ impl OwnedAsciiCast for ~str { } /// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str` -pub trait ToStrAscii { +pub trait AsciiStr { /// Convert to a string. fn to_str_ascii(&self) -> ~str; + + /// Convert to vector representing a lower cased ascii string. + fn to_lower(&self) -> ~[Ascii]; + + /// Convert to vector representing a upper cased ascii string. + fn to_upper(&self) -> ~[Ascii]; + } -impl<'self> ToStrAscii for &'self [Ascii] { +impl<'self> AsciiStr for &'self [Ascii] { #[inline(always)] fn to_str_ascii(&self) -> ~str { let mut cpy = self.to_owned(); cpy.push(0u8.to_ascii()); unsafe {cast::transmute(cpy)} } + + #[inline(always)] + fn to_lower(&self) -> ~[Ascii] { + self.map(|a| a.to_lower()) + } + + #[inline(always)] + fn to_upper(&self) -> ~[Ascii] { + self.map(|a| a.to_upper()) + } } impl ToStrConsume for ~[Ascii] { @@ -186,13 +199,8 @@ impl ToStrConsume for ~[Ascii] { } } -// NOTE: Remove stage0 marker after snapshot -#[cfg(and(test, not(stage0)))] mod tests { use super::*; - use to_str::{ToStr,ToStrConsume}; - use str; - use cast; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); @@ -206,15 +214,15 @@ mod tests { assert_eq!('A'.to_ascii().to_char(), 'A'); assert_eq!('A'.to_ascii().to_byte(), 65u8); - assert_eq!('A'.to_ascii().to_lower().to_char, 'a'); - assert_eq!('Z'.to_ascii().to_lower().to_char, 'z'); - assert_eq!('a'.to_ascii().to_upper().to_char, 'A'); - assert_eq!('z'.to_ascii().to_upper().to_char, 'Z'); + assert_eq!('A'.to_ascii().to_lower().to_char(), 'a'); + assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z'); + assert_eq!('a'.to_ascii().to_upper().to_char(), 'A'); + assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z'); - assert_eq!('@'.to_ascii().to_lower().to_char, '@'); - assert_eq!('['.to_ascii().to_lower().to_char, '['); - assert_eq!('`'.to_ascii().to_upper().to_char, '`'); - assert_eq!('{'.to_ascii().to_upper().to_char, '{'); + assert_eq!('@'.to_ascii().to_lower().to_char(), '@'); + assert_eq!('['.to_ascii().to_lower().to_char(), '['); + assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); + assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); } #[test] @@ -225,6 +233,9 @@ mod tests { // if chained-from directly let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59])); + + assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#"); + assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#"); } #[test] From bf4f088eaccfe24d4c30e7bf52e4c2bd20b9ff47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Mon, 22 Apr 2013 22:05:39 +0200 Subject: [PATCH 354/403] Added missing assert, did some formating --- src/libcore/str/ascii.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 447ca3497e873..339274ab47e4f 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -74,7 +74,6 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { #[inline(always)] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - unsafe{ cast::transmute(*self) } } @@ -91,7 +90,6 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str { #[inline(always)] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) }; unsafe{ cast::transmute((p, len - 1))} } @@ -119,7 +117,6 @@ impl AsciiCast for u8 { } impl AsciiCast for char { - #[inline(always)] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); @@ -142,7 +139,6 @@ impl OwnedAsciiCast for ~[u8] { #[inline(always)] fn to_ascii_consume(self) -> ~[Ascii] { assert!(self.is_ascii()); - unsafe {cast::transmute(self)} } } @@ -150,6 +146,7 @@ impl OwnedAsciiCast for ~[u8] { impl OwnedAsciiCast for ~str { #[inline(always)] fn to_ascii_consume(self) -> ~[Ascii] { + assert!(self.is_ascii()); let mut s = self; unsafe { str::raw::pop_byte(&mut s); @@ -269,11 +266,3 @@ mod tests { #[test] #[should_fail] fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); } } - - - - - - - - From a117cf03bc90addb9c0b6364db8ff7e54b10d753 Mon Sep 17 00:00:00 2001 From: gifnksm Date: Mon, 22 Apr 2013 23:19:34 +0900 Subject: [PATCH 355/403] libstd: correct bigint's quot/rem, div/modulo --- src/libstd/num/bigint.rs | 113 ++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index 08c65d190bf99..ee9749af5320e 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -264,15 +264,15 @@ impl Mul for BigUint { impl Quot for BigUint { fn quot(&self, other: &BigUint) -> BigUint { - let (d, _) = self.quot_rem(other); - return d; + let (q, _) = self.quot_rem(other); + return q; } } impl Rem for BigUint { fn rem(&self, other: &BigUint) -> BigUint { - let (_, m) = self.quot_rem(other); - return m; + let (_, r) = self.quot_rem(other); + return r; } } @@ -302,14 +302,14 @@ impl ToStrRadix for BigUint { fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] { let divider = BigUint::from_uint(base); let mut result = ~[]; - let mut r = n; - while r > divider { - let (d, r0) = r.quot_rem(÷r); - result += [r0.to_uint() as BigDigit]; - r = d; + let mut m = n; + while m > divider { + let (d, m0) = m.div_mod(÷r); + result += [m0.to_uint() as BigDigit]; + m = d; } - if r.is_not_zero() { - result += [r.to_uint() as BigDigit]; + if m.is_not_zero() { + result += [m.to_uint() as BigDigit]; } return result; } @@ -384,7 +384,16 @@ pub impl BigUint { fn abs(&self) -> BigUint { copy *self } - fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) { + fn div(&self, other: &BigUint) -> BigUint { + let (d, _) = self.div_mod(other); + return d; + } + fn modulo(&self, other: &BigUint) -> BigUint { + let (_, m) = self.div_mod(other); + return m; + } + + fn div_mod(&self, other: &BigUint) -> (BigUint, BigUint) { if other.is_zero() { fail!() } if self.is_zero() { return (Zero::zero(), Zero::zero()); } if *other == One::one() { return (copy *self, Zero::zero()); } @@ -402,17 +411,17 @@ pub impl BigUint { shift += 1; } assert!(shift < BigDigit::bits); - let (d, m) = quot_rem_inner(self << shift, other << shift); + let (d, m) = div_mod_inner(self << shift, other << shift); return (d, m >> shift); - fn quot_rem_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { - let mut r = a; + fn div_mod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { + let mut m = a; let mut d = Zero::zero::(); let mut n = 1; - while r >= b { - let mut (d0, d_unit, b_unit) = div_estimate(&r, &b, n); + while m >= b { + let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n); let mut prod = b * d0; - while prod > r { + while prod > m { d0 -= d_unit; prod -= b_unit; } @@ -422,9 +431,9 @@ pub impl BigUint { } n = 1; d += d0; - r -= prod; + m -= prod; } - return (d, r); + return (d, m); } fn div_estimate(a: &BigUint, b: &BigUint, n: uint) @@ -455,16 +464,8 @@ pub impl BigUint { } } - fn quot(&self, other: &BigUint) -> BigUint { - let (q, _) = self.quotrem(other); - return q; - } - fn rem(&self, other: &BigUint) -> BigUint { - let (_, r) = self.quotrem(other); - return r; - } - fn quotrem(&self, other: &BigUint) -> (BigUint, BigUint) { - self.quot_rem(other) + fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) { + self.div_mod(other) } fn is_zero(&self) -> bool { self.data.is_empty() } @@ -739,15 +740,15 @@ impl Mul for BigInt { impl Quot for BigInt { fn quot(&self, other: &BigInt) -> BigInt { - let (d, _) = self.quot_rem(other); - return d; + let (q, _) = self.quot_rem(other); + return q; } } impl Rem for BigInt { fn rem(&self, other: &BigInt) -> BigInt { - let (_, m) = self.quot_rem(other); - return m; + let (_, r) = self.quot_rem(other); + return r; } } @@ -841,7 +842,16 @@ pub impl BigInt { BigInt::from_biguint(Plus, copy self.data) } - fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) { + fn div(&self, other: &BigInt) -> BigInt { + let (d, _) = self.div_mod(other); + return d; + } + fn modulo(&self, other: &BigInt) -> BigInt { + let (_, m) = self.div_mod(other); + return m; + } + + fn div_mod(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign let (d_ui, m_ui) = self.data.quot_rem(&other.data); let d = BigInt::from_biguint(Plus, d_ui), @@ -863,18 +873,9 @@ pub impl BigInt { } } - fn quot(&self, other: &BigInt) -> BigInt { - let (q, _) = self.quotrem(other); - return q; - } - fn rem(&self, other: &BigInt) -> BigInt { - let (_, r) = self.quotrem(other); - return r; - } - - fn quotrem(&self, other: &BigInt) -> (BigInt, BigInt) { + fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // r.sign == self.sign - let (q_ui, r_ui) = self.data.quotrem(&other.data); + let (q_ui, r_ui) = self.data.div_mod(&other.data); let q = BigInt::from_biguint(Plus, q_ui); let r = BigInt::from_biguint(Plus, r_ui); match (self.sign, other.sign) { @@ -1151,9 +1152,9 @@ mod biguint_tests { ]; static quot_rem_quadruples: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] + &'static [BigDigit], + &'static [BigDigit], + &'static [BigDigit])] = &[ (&[ 1], &[ 2], &[], &[1]), (&[ 1, 1], &[ 2], &[-1/2+1], &[1]), @@ -1517,9 +1518,9 @@ mod bigint_tests { ]; static quot_rem_quadruples: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] + &'static [BigDigit], + &'static [BigDigit], + &'static [BigDigit])] = &[ (&[ 1], &[ 2], &[], &[1]), (&[ 1, 1], &[ 2], &[-1/2+1], &[1]), @@ -1556,9 +1557,9 @@ mod bigint_tests { } #[test] - fn test_quot_rem() { + fn test_div_mod() { fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { - let (d, m) = a.quot_rem(b); + let (d, m) = a.div_mod(b); if m.is_not_zero() { assert!(m.sign == b.sign); } @@ -1607,9 +1608,9 @@ mod bigint_tests { #[test] - fn test_quotrem() { + fn test_quot_rem() { fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { - let (q, r) = a.quotrem(b); + let (q, r) = a.quot_rem(b); if r.is_not_zero() { assert!(r.sign == a.sign); } From 81110c55e89e22ba8da3d049c62f3f048c67ec02 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Apr 2013 17:47:49 -0700 Subject: [PATCH 356/403] Revert "Errors with the same span print the span once" This reverts commit 6030e3982a52c8d9ede225f992088bb75fba4ef1. --- src/libsyntax/diagnostic.rs | 160 +++--------------------------------- 1 file changed, 13 insertions(+), 147 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index c170ee5c1195c..35022b68ebbbe 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -33,7 +33,6 @@ pub trait handler { fn bump_err_count(@mut self); fn has_errors(@mut self) -> bool; fn abort_if_errors(@mut self); - fn abort_error_print(@mut self); fn warn(@mut self, msg: &str); fn note(@mut self, msg: &str); // used to indicate a bug in the compiler: @@ -43,7 +42,6 @@ pub trait handler { cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level); - fn emit_print(@mut self, lvl: level); } // a span-handler is like a handler but also @@ -59,15 +57,8 @@ pub trait span_handler { fn handler(@mut self) -> @handler; } -struct emitter_arg { - cmsp: Option<(@codemap::CodeMap, span)>, - msg: ~str, - lvl: level, -} - struct HandlerT { err_count: uint, - emitters: ~[emitter_arg], emit: Emitter, } @@ -78,11 +69,7 @@ struct CodemapT { impl span_handler for CodemapT { fn span_fatal(@mut self, sp: span, msg: &str) -> ! { - self.handler.bump_err_count(); self.handler.emit(Some((self.cm, sp)), msg, fatal); - self.handler.emit_print(error); - self.handler.emit_print(note); - self.handler.abort_error_print(); fail!(); } fn span_err(@mut self, sp: span, msg: &str) { @@ -90,7 +77,7 @@ impl span_handler for CodemapT { self.handler.bump_err_count(); } fn span_warn(@mut self, sp: span, msg: &str) { - emit_one(Some((self.cm, sp)), msg, warning); + self.handler.emit(Some((self.cm, sp)), msg, warning); } fn span_note(@mut self, sp: span, msg: &str) { self.handler.emit(Some((self.cm, sp)), msg, note); @@ -108,13 +95,11 @@ impl span_handler for CodemapT { impl handler for HandlerT { fn fatal(@mut self, msg: &str) -> ! { - self.emit_print(error); - self.emit_print(note); - emit_one(None, msg, fatal); + (self.emit)(None, msg, fatal); fail!(); } fn err(@mut self, msg: &str) { - emit_one(None, msg, error); + (self.emit)(None, msg, error); self.bump_err_count(); } fn bump_err_count(@mut self) { @@ -133,26 +118,13 @@ impl handler for HandlerT { } self.fatal(s); } - fn abort_error_print(@mut self) { - let s; - match self.err_count { - 0u => return, - 1u => s = ~"aborting due to previous error", - _ => { - s = fmt!("aborting due to %u previous errors", - self.err_count); - } - } - emit_one(None, s, fatal); - } fn warn(@mut self, msg: &str) { - emit_one(None, msg, warning); + (self.emit)(None, msg, warning); } fn note(@mut self, msg: &str) { - self.emit(None, msg, note); + (self.emit)(None, msg, note); } fn bug(@mut self, msg: &str) -> ! { - self.bump_err_count(); self.fatal(ice_msg(msg)); } fn unimpl(@mut self, msg: &str) -> ! { @@ -163,50 +135,6 @@ impl handler for HandlerT { msg: &str, lvl: level) { (self.emit)(cmsp, msg, lvl); - let emitter = emitter_arg { cmsp: cmsp, - msg: str::from_slice(msg), - lvl: lvl }; - self.emitters.push(emitter); - } - - fn emit_print(@mut self, lvl: level) { - let mut old_cmsp = None; - let mut old_line = 0u; - - let emitters = self.emitters; - let length = emitters.len(); - for uint::range(0, length) |i| { - let emitter = copy self.emitters[i]; - let cmsp = emitter.cmsp; - let msg = emitter.msg; - if diagnosticstr(lvl) == diagnosticstr(emitter.lvl) { - match cmsp { - Some((cm, sp)) => { - let lo = cm.lookup_char_pos_adj(sp.lo); - let sp = cm.adjust_span(sp); - let ss = cm.span_to_str(sp); - if i == 0 || old_line == lo.line { - if old_line == lo.line { - highlight_lines_cmp(cmsp, old_cmsp); - } - print_diagnostic(ss, lvl, msg); - highlight_lines_cmp(old_cmsp, cmsp); - } else { - highlight_lines(old_cmsp); - print_macro_backtrace(old_cmsp); - print_diagnostic(ss, lvl, msg); - } - old_line = lo.line; - old_cmsp = emitter.cmsp; - } - None => { - print_diagnostic(~"", lvl, msg); - } - } - } - } - highlight_lines(old_cmsp); - print_macro_backtrace(old_cmsp); } } @@ -228,9 +156,7 @@ pub fn mk_handler(emitter: Option) -> @handler { } }; - @mut HandlerT { err_count: 0, - emitters: ~[], - emit: emit } as @handler + @mut HandlerT { err_count: 0, emit: emit } as @handler } #[deriving(Eq)] @@ -282,19 +208,15 @@ pub fn collect(messages: @mut ~[~str]) f } -pub fn emit(_cmsp: Option<(@codemap::CodeMap, span)>, _msg: &str, _lvl: level) { - // Nothing to do -} - -pub fn emit_one(cmsp: Option<(@codemap::CodeMap, span)>, - msg: &str, lvl: level) { +pub fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) { match cmsp { Some((cm, sp)) => { let sp = cm.adjust_span(sp); let ss = cm.span_to_str(sp); + let lines = cm.span_to_lines(sp); print_diagnostic(ss, lvl, msg); - highlight_lines(cmsp); - print_macro_backtrace(cmsp); + highlight_lines(cm, sp, lines); + print_macro_backtrace(cm, sp); } None => { print_diagnostic(~"", lvl, msg); @@ -302,7 +224,7 @@ pub fn emit_one(cmsp: Option<(@codemap::CodeMap, span)>, } } -fn highlight_lines_internal(cm: @codemap::CodeMap, +fn highlight_lines(cm: @codemap::CodeMap, sp: span, lines: @codemap::FileLines) { let fm = lines.file; @@ -369,70 +291,14 @@ fn highlight_lines_internal(cm: @codemap::CodeMap, } } -fn highlight_lines(cmsp: Option<(@codemap::CodeMap, span)>) { - match cmsp { - Some((cm, sp)) => { - let sp = cm.adjust_span(sp); - let lines = cm.span_to_lines(sp); - highlight_lines_internal(cm, sp, lines); - } - None => () - } -} - -fn highlight_lines_cmp(old_cmsp: Option<(@codemap::CodeMap, span)>, - cmsp: Option<(@codemap::CodeMap, span)> ){ - let mut old_line = ~[]; - let mut new_line = ~[]; - let mut old_lo = 0u; - let mut new_lo = 0u; - let mut flag = true; - match old_cmsp { - Some((cm, sp)) => { - let lo = cm.lookup_char_pos(sp.lo); - let sp = cm.adjust_span(sp); - let lines = cm.span_to_lines(sp); - old_line = lines.lines; - old_lo = lo.col.to_uint(); - } - None => { flag = false; } - } - - match cmsp { - Some((cm, sp)) => { - let lo = cm.lookup_char_pos(sp.lo); - let sp = cm.adjust_span(sp); - let lines = cm.span_to_lines(sp); - new_line = lines.lines; - new_lo = lo.col.to_uint(); - } - None => { flag = false; } - } - - if flag { - if old_line == new_line && old_lo > new_lo { - highlight_lines(cmsp); - } - } -} - -fn print_macro_backtrace_internal(cm: @codemap::CodeMap, sp: span) { +fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) { for sp.expn_info.each |ei| { let ss = ei.callee.span.map_default(@~"", |span| @cm.span_to_str(*span)); print_diagnostic(*ss, note, fmt!("in expansion of %s!", ei.callee.name)); let ss = cm.span_to_str(ei.call_site); print_diagnostic(ss, note, ~"expansion site"); - print_macro_backtrace_internal(cm, ei.call_site); - } -} - -fn print_macro_backtrace(cmsp: Option<(@codemap::CodeMap, span)>) { - match cmsp { - Some((cm, sp)) => { - print_macro_backtrace_internal(cm, sp); - } - None => () + print_macro_backtrace(cm, ei.call_site); } } From d834c0d59d7b4febbf8dc411b5d3aa925ee7a447 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 18 Apr 2013 16:15:17 -0700 Subject: [PATCH 357/403] docs: Sketch out rustpkg manual --- doc/rustpkg.md | 103 ++++++++++++++++++ mk/docs.mk | 14 +++ .../no-inferred-crates/src}/zzyzx.rs | 0 .../testsuite/pass/simple-lib/simple-lib.rc | 21 ---- .../deeply/nested/path/foo/src}/main.rs | 0 .../external-crate/src}/main.rs | 0 .../testsuite/pass/{ => src}/fancy-lib/pkg.rs | 0 .../{fancy-lib => src/fancy-lib/src}/bar.rs | 0 .../fancy-lib/src}/fancy-lib.rs | 0 .../{fancy-lib => src/fancy-lib/src}/foo.rs | 0 .../hello-world/src}/main.rs | 0 .../install-paths/src}/bench.rs | 0 .../install-paths/src}/lib.rs | 0 .../install-paths/src}/main.rs | 0 .../install-paths/src}/test.rs | 0 .../{simple-lib => src/simple-lib/src}/bar.rs | 0 .../{simple-lib => src/simple-lib/src}/foo.rs | 0 .../{simple-lib => src/simple-lib/src}/lib.rs | 0 18 files changed, 117 insertions(+), 21 deletions(-) create mode 100644 doc/rustpkg.md rename src/librustpkg/testsuite/fail/{no-inferred-crates => src/no-inferred-crates/src}/zzyzx.rs (100%) delete mode 100644 src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc rename src/librustpkg/testsuite/pass/{deeply/nested/path/foo => src/deeply/nested/path/foo/src}/main.rs (100%) rename src/librustpkg/testsuite/pass/{external-crate => src/external-crate/src}/main.rs (100%) rename src/librustpkg/testsuite/pass/{ => src}/fancy-lib/pkg.rs (100%) rename src/librustpkg/testsuite/pass/{fancy-lib => src/fancy-lib/src}/bar.rs (100%) rename src/librustpkg/testsuite/pass/{fancy-lib => src/fancy-lib/src}/fancy-lib.rs (100%) rename src/librustpkg/testsuite/pass/{fancy-lib => src/fancy-lib/src}/foo.rs (100%) rename src/librustpkg/testsuite/pass/{hello-world => src/hello-world/src}/main.rs (100%) rename src/librustpkg/testsuite/pass/{install-paths => src/install-paths/src}/bench.rs (100%) rename src/librustpkg/testsuite/pass/{install-paths => src/install-paths/src}/lib.rs (100%) rename src/librustpkg/testsuite/pass/{install-paths => src/install-paths/src}/main.rs (100%) rename src/librustpkg/testsuite/pass/{install-paths => src/install-paths/src}/test.rs (100%) rename src/librustpkg/testsuite/pass/{simple-lib => src/simple-lib/src}/bar.rs (100%) rename src/librustpkg/testsuite/pass/{simple-lib => src/simple-lib/src}/foo.rs (100%) rename src/librustpkg/testsuite/pass/{simple-lib => src/simple-lib/src}/lib.rs (100%) diff --git a/doc/rustpkg.md b/doc/rustpkg.md new file mode 100644 index 0000000000000..d4c1aa67332d8 --- /dev/null +++ b/doc/rustpkg.md @@ -0,0 +1,103 @@ +% Rustpkg Reference Manual + +# Introduction + +This document is the reference manual for the Rustpkg packaging and build tool for the Rust programming language. + +## Disclaimer + +Rustpkg is a work in progress, as is this reference manual. +If the actual behavior of rustpkg differs from the behavior described in this reference, +that reflects either an incompleteness or a bug in rustpkg. + +# Package searching + +rustpkg searches for packages using the `RUST_PATH` environment variable, +which is a colon-separated list (semicolon-separated on Windows) of directories. + +Each directory in this list is a *workspace* for rustpkg. + +`RUST_PATH` implicitly contains an entry for `./.rust` (as well as +`../.rust`, `../../.rust`, +and so on for every parent of `.` up to the filesystem root). +That means that if `RUST_PATH` is not set, +then rustpkg will still search for workspaces in `./.rust` and so on + +Each workspace may contain one or more packages. + +# Package structure + +A valid workspace must contain each of the following subdirectories: + +* 'src/': contains one subdirectory per package. Each subdirectory contains source files for a given package. + + For example, if `foo` is a workspace containing the package `bar`, + then `foo/src/bar/main.rs` could be the `main` entry point for + building a `bar` executable. +* 'lib/': `rustpkg install` installs libraries into a target-specific subdirectory of this directory. + + For example, on a 64-bit machine running Mac OS X, + if `foo` is a workspace containing the package `bar`, + rustpkg will install libraries for bar to `foo/lib/x86_64-apple-darwin/`. + The libraries will have names of the form `foo/lib/x86_64-apple-darwin/libbar-[hash].dylib`, + where [hash] is a hash of the package ID. +* 'bin/': `rustpkg install` installs executable binaries into a target-specific subdirectory of this directory. + + For example, on a 64-bit machine running Mac OS X, + if `foo` is a workspace, containing the package `bar`, + rustpkg will install executables for `bar` to + `foo/bin/x86_64-apple-darwin/`. + The executables will have names of the form `foo/bin/x86_64-apple-darwin/bar`. +* 'build/': `rustpkg build` stores temporary build artifacts in a target-specific subdirectory of this directory. + + For example, on a 64-bit machine running Mac OS X, + if `foo` is a workspace containing the package `bar` and `foo/src/bar/main.rs` exists, + then `rustpkg build` will create `foo/build/x86_64-apple-darwin/bar/main.o`. + +# Package identifiers + +A package identifier identifies a package uniquely. +A package can be stored in a workspace on the local file system, +or on a remote Web server, in which case the package ID resembles a URL. +For example, `github.com/mozilla/rust` is a package ID +that would refer to the git repository browsable at `http://github.com/mozilla/rust`. + +## Source files + +rustpkg searches for four different fixed filenames in order to determine the crates to build: + +* `main.rs`: Assumed to be a main entry point for building an executable. +* `lib.rs`: Assumed to be a library crate. +* `test.rs`: Assumed to contain tests declared with the `#[test]` attribute. +* `bench.rs`: Assumed to contain benchmarks declared with the `#[bench]` attribute. + +# Custom build scripts + +A file called `pkg.rs` at the root level in a workspace is called a *package script*. +If a package script exists, rustpkg executes it to build the package +rather than inferring crates as described previously. + +# Command reference + +## build + +`rustpkg build foo` searches for a package with ID `foo` +and builds it in any workspace(s) where it finds one. +Supposing such packages are found in workspaces X, Y, and Z, +the command leaves behind files in `X`'s, `Y`'s, and `Z`'s `build` directories, +but not in their `lib` or `bin` directories. + +## clean + +`rustpkg clean foo` deletes the contents of `foo`'s `build` directory. + +## install + +`rustpkg install foo` builds the libraries and/or executables that are targets for `foo`, +and then installs them either into `foo`'s `lib` and `bin` directories, +or into the `lib` and `bin` subdirectories of the first entry in `RUST_PATH`. + +## test + +`rustpkg test foo` builds `foo`'s `test.rs` file if necessary, +then runs the resulting test executable. diff --git a/mk/docs.mk b/mk/docs.mk index 10d7c9b0301d9..6873d433e951f 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -81,6 +81,20 @@ doc/rust.pdf: doc/rust.tex endif endif +DOCS += doc/rustpkg.html +doc/rustpkg.html: rustpkg.md doc/version_info.html doc/rust.css doc/manual.css + @$(call E, pandoc: $@) + $(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \ + "$(CFG_PANDOC)" \ + --standalone --toc \ + --section-divs \ + --number-sections \ + --from=markdown --to=html \ + --css=rust.css \ + --css=manual.css \ + --include-before-body=doc/version_info.html \ + --output=$@ + ###################################################################### # Node (tutorial related) ###################################################################### diff --git a/src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs b/src/librustpkg/testsuite/fail/src/no-inferred-crates/src/zzyzx.rs similarity index 100% rename from src/librustpkg/testsuite/fail/no-inferred-crates/zzyzx.rs rename to src/librustpkg/testsuite/fail/src/no-inferred-crates/src/zzyzx.rs diff --git a/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc b/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc deleted file mode 100644 index 1cdca6cdd5d87..0000000000000 --- a/src/librustpkg/testsuite/pass/simple-lib/simple-lib.rc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/* -The test runner should check that, after `rustpkg build simple-lib`: - * testsuite/simple-lib/build/ exists - * testsuite/simple-lib/build/ contains a library named libsimple_lib - * testsuite/simple-lib/build/ does not contain an executable -*/ - -extern mod std; - -pub mod foo; -pub mod bar; diff --git a/src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs b/src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/src/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/deeply/nested/path/foo/main.rs rename to src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/src/main.rs diff --git a/src/librustpkg/testsuite/pass/external-crate/main.rs b/src/librustpkg/testsuite/pass/src/external-crate/src/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/external-crate/main.rs rename to src/librustpkg/testsuite/pass/src/external-crate/src/main.rs diff --git a/src/librustpkg/testsuite/pass/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs similarity index 100% rename from src/librustpkg/testsuite/pass/fancy-lib/pkg.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs diff --git a/src/librustpkg/testsuite/pass/fancy-lib/bar.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs similarity index 100% rename from src/librustpkg/testsuite/pass/fancy-lib/bar.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs diff --git a/src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs similarity index 100% rename from src/librustpkg/testsuite/pass/fancy-lib/fancy-lib.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs diff --git a/src/librustpkg/testsuite/pass/fancy-lib/foo.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs similarity index 100% rename from src/librustpkg/testsuite/pass/fancy-lib/foo.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs diff --git a/src/librustpkg/testsuite/pass/hello-world/main.rs b/src/librustpkg/testsuite/pass/src/hello-world/src/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/hello-world/main.rs rename to src/librustpkg/testsuite/pass/src/hello-world/src/main.rs diff --git a/src/librustpkg/testsuite/pass/install-paths/bench.rs b/src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs similarity index 100% rename from src/librustpkg/testsuite/pass/install-paths/bench.rs rename to src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs diff --git a/src/librustpkg/testsuite/pass/install-paths/lib.rs b/src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs similarity index 100% rename from src/librustpkg/testsuite/pass/install-paths/lib.rs rename to src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs diff --git a/src/librustpkg/testsuite/pass/install-paths/main.rs b/src/librustpkg/testsuite/pass/src/install-paths/src/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/install-paths/main.rs rename to src/librustpkg/testsuite/pass/src/install-paths/src/main.rs diff --git a/src/librustpkg/testsuite/pass/install-paths/test.rs b/src/librustpkg/testsuite/pass/src/install-paths/src/test.rs similarity index 100% rename from src/librustpkg/testsuite/pass/install-paths/test.rs rename to src/librustpkg/testsuite/pass/src/install-paths/src/test.rs diff --git a/src/librustpkg/testsuite/pass/simple-lib/bar.rs b/src/librustpkg/testsuite/pass/src/simple-lib/src/bar.rs similarity index 100% rename from src/librustpkg/testsuite/pass/simple-lib/bar.rs rename to src/librustpkg/testsuite/pass/src/simple-lib/src/bar.rs diff --git a/src/librustpkg/testsuite/pass/simple-lib/foo.rs b/src/librustpkg/testsuite/pass/src/simple-lib/src/foo.rs similarity index 100% rename from src/librustpkg/testsuite/pass/simple-lib/foo.rs rename to src/librustpkg/testsuite/pass/src/simple-lib/src/foo.rs diff --git a/src/librustpkg/testsuite/pass/simple-lib/lib.rs b/src/librustpkg/testsuite/pass/src/simple-lib/src/lib.rs similarity index 100% rename from src/librustpkg/testsuite/pass/simple-lib/lib.rs rename to src/librustpkg/testsuite/pass/src/simple-lib/src/lib.rs From 4508da226ab598e646ef7cbac805cdcc8deb07a4 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:46:37 -0700 Subject: [PATCH 358/403] rustpkg: In doc, mention other implicit RUST_PATH entries as per Graydon's comment --- doc/rustpkg.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/rustpkg.md b/doc/rustpkg.md index d4c1aa67332d8..ac3d32dcd8e61 100644 --- a/doc/rustpkg.md +++ b/doc/rustpkg.md @@ -21,7 +21,12 @@ Each directory in this list is a *workspace* for rustpkg. `../.rust`, `../../.rust`, and so on for every parent of `.` up to the filesystem root). That means that if `RUST_PATH` is not set, -then rustpkg will still search for workspaces in `./.rust` and so on +then rustpkg will still search for workspaces in `./.rust` and so on. +`RUST_PATH` also implicitly contains an entry for the system path: +`/usr/local` or the equivalent on Windows. +This entry comes after the implicit entries for `./.rust` and so on. +Finally, the last implicit entry in `RUST_PATH` is `~/.rust` +or the equivalent on Windows. Each workspace may contain one or more packages. From 08bbf4b019de4305f010abb8c10c0aafa786fe7c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 22 Apr 2013 19:25:25 -0700 Subject: [PATCH 359/403] core: ignore test from_str_ignore_underscores. Broken on i686. #6018 --- src/libcore/num/strconv.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 4a45a1d97023e..8d050e65c9812 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -655,6 +655,7 @@ mod test { use option::*; #[test] + #[ignore(reason = "fails in x86")] fn from_str_ignore_underscores() { let s : Option = from_str_common("__1__", 2, false, false, false, ExpNone, false, true); From 8eb22ecd6d14c99231043e677fe1bf39ce5e043a Mon Sep 17 00:00:00 2001 From: Young-il Choi Date: Tue, 23 Apr 2013 11:31:54 +0900 Subject: [PATCH 360/403] test: fix for missing ARM support --- src/test/run-pass/bitwise.rs | 1 + src/test/run-pass/conditional-compile-arch.rs | 3 +++ src/test/run-pass/dupe-first-attr.rc | 3 +++ src/test/run-pass/intrinsic-alignment.rs | 11 +++++++++++ src/test/run-pass/issue-2895.rs | 1 + src/test/run-pass/rec-align-u32.rs | 1 + src/test/run-pass/rec-align-u64.rs | 9 +++++++++ src/test/run-pass/struct-return.rs | 1 + src/test/run-pass/x86stdcall2.rs | 1 + 9 files changed, 31 insertions(+) diff --git a/src/test/run-pass/bitwise.rs b/src/test/run-pass/bitwise.rs index 1a67329ff82b0..ce06f09d32132 100644 --- a/src/test/run-pass/bitwise.rs +++ b/src/test/run-pass/bitwise.rs @@ -11,6 +11,7 @@ #[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] fn target() { assert!((-1000 as uint >> 3u == 536870787u)); } diff --git a/src/test/run-pass/conditional-compile-arch.rs b/src/test/run-pass/conditional-compile-arch.rs index a47e9d9ea8117..106f59d7c7860 100644 --- a/src/test/run-pass/conditional-compile-arch.rs +++ b/src/test/run-pass/conditional-compile-arch.rs @@ -13,3 +13,6 @@ pub fn main() { } #[cfg(target_arch = "x86_64")] pub fn main() { } + +#[cfg(target_arch = "arm")] +pub fn main() { } diff --git a/src/test/run-pass/dupe-first-attr.rc b/src/test/run-pass/dupe-first-attr.rc index f57f18affcb84..d39a2aa447623 100644 --- a/src/test/run-pass/dupe-first-attr.rc +++ b/src/test/run-pass/dupe-first-attr.rc @@ -22,3 +22,6 @@ mod hello; #[cfg(target_os = "freebsd")] mod hello; + +#[cfg(target_os = "android")] +mod hello; diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index d6a59fac57a4d..adc085d210853 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -49,3 +49,14 @@ mod m { } } } + +#[cfg(target_os = "android")] +mod m { + #[cfg(target_arch = "arm")] + pub fn main() { + unsafe { + assert!(::rusti::pref_align_of::() == 8u); + assert!(::rusti::min_align_of::() == 4u); + } + } +} diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs index 2560c1ba77ebc..bd075555df193 100644 --- a/src/test/run-pass/issue-2895.rs +++ b/src/test/run-pass/issue-2895.rs @@ -27,6 +27,7 @@ pub fn main() { } #[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] pub fn main() { assert!((sys::size_of::() == 4 as uint)); assert!((sys::size_of::() == 8 as uint)); diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs index 703852d20bd25..ff72eab7df16c 100644 --- a/src/test/run-pass/rec-align-u32.rs +++ b/src/test/run-pass/rec-align-u32.rs @@ -32,6 +32,7 @@ struct Outer { #[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] mod m { pub fn align() -> uint { 4u } pub fn size() -> uint { 8u } diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index 96713d120be25..0fad3e1f511f8 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -57,6 +57,15 @@ mod m { } } +#[cfg(target_os = "android")] +mod m { + #[cfg(target_arch = "arm")] + pub mod m { + pub fn align() -> uint { 4u } + pub fn size() -> uint { 12u } + } +} + pub fn main() { unsafe { let x = Outer {c8: 22u8, t: Inner {c64: 44u64}}; diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs index f702ca5144ea8..5427ee38b430c 100644 --- a/src/test/run-pass/struct-return.rs +++ b/src/test/run-pass/struct-return.rs @@ -56,6 +56,7 @@ fn test2() { } #[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] fn test2() { } diff --git a/src/test/run-pass/x86stdcall2.rs b/src/test/run-pass/x86stdcall2.rs index 452bfbf90b150..53cc483c44f28 100644 --- a/src/test/run-pass/x86stdcall2.rs +++ b/src/test/run-pass/x86stdcall2.rs @@ -40,4 +40,5 @@ pub fn main() { #[cfg(target_os = "macos")] #[cfg(target_os = "linux")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "android")] pub fn main() { } From 391de1c690927ed430708f659a68581368e1e254 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Apr 2013 00:53:43 -0400 Subject: [PATCH 361/403] Remove a stray new operator in rust_task.h --- src/rt/rust_task.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 7aa216042039f..4aa1199cabc3f 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -396,12 +396,6 @@ rust_task : public kernel_owned void allow_yield(); }; -// FIXME (#2697): It would be really nice to be able to get rid of this. -inline void *operator new[](size_t size, rust_task *task, const char *tag) { - return task->malloc(size, tag); -} - - template struct task_owned { inline void *operator new(size_t size, rust_task *task, const char *tag) { From ca73fbf72615575f106ee18160580711aca89d85 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 22 Apr 2013 22:08:09 -0700 Subject: [PATCH 362/403] Use correct grammar for error message. When the number of parameters is 1, then 'parameter' should remain singular. Otherwise pluralize it. --- src/librustc/middle/typeck/collect.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index f1d743e79e58a..772bb4598061f 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -403,10 +403,11 @@ pub fn compare_impl_method(tcx: ty::ctxt, if vec::len(impl_m.fty.sig.inputs) != vec::len(trait_m.fty.sig.inputs) { tcx.sess.span_err( cm.span, - fmt!("method `%s` has %u parameters \ + fmt!("method `%s` has %u parameter%s \ but the trait has %u", *tcx.sess.str_of(trait_m.ident), vec::len(impl_m.fty.sig.inputs), + if vec::len(impl_m.fty.sig.inputs) == 1 { "" } else { "s" }, vec::len(trait_m.fty.sig.inputs))); return; } From 8884c6abdba9e564a06f21f6238011ad11e92c96 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Apr 2013 02:06:47 -0400 Subject: [PATCH 363/403] Use backticks for the unsafe keyword in error messages --- src/librustc/middle/lint.rs | 4 ++-- src/test/compile-fail/unused-unsafe.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index bda97f4f530d1..95af2f15bc4ea 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -262,7 +262,7 @@ pub fn get_lint_dict() -> LintDict { (~"unused_unsafe", LintSpec { lint: unused_unsafe, - desc: "unnecessary use of an \"unsafe\" block", + desc: "unnecessary use of an `unsafe` block", default: warn }), @@ -949,7 +949,7 @@ fn check_item_unused_unsafe(cx: ty::ctxt, it: @ast::item) { if !cx.used_unsafe.contains(&blk.node.id) { cx.sess.span_lint(unused_unsafe, blk.node.id, it.id, blk.span, - ~"unnecessary \"unsafe\" block"); + ~"unnecessary `unsafe` block"); } } _ => () diff --git a/src/test/compile-fail/unused-unsafe.rs b/src/test/compile-fail/unused-unsafe.rs index b29148cd3bc55..7d9044f5d8921 100644 --- a/src/test/compile-fail/unused-unsafe.rs +++ b/src/test/compile-fail/unused-unsafe.rs @@ -16,10 +16,10 @@ use core::libc; fn callback(_f: &fn() -> T) -> T { fail!() } -fn bad1() { unsafe {} } //~ ERROR: unnecessary "unsafe" block -fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary "unsafe" block -unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary "unsafe" block -fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary "unsafe" block +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block unsafe fn good0() { libc::exit(1) } fn good1() { unsafe { libc::exit(1) } } From b813d68abe84e0e30c6138219a3f9f23e8f5d9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Tue, 23 Apr 2013 11:10:37 +0200 Subject: [PATCH 364/403] Attempt to fix x86 only strconv test failure --- src/libcore/num/strconv.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 8d050e65c9812..2f3cd92dac09e 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -655,7 +655,6 @@ mod test { use option::*; #[test] - #[ignore(reason = "fails in x86")] fn from_str_ignore_underscores() { let s : Option = from_str_common("__1__", 2, false, false, false, ExpNone, false, true); @@ -665,9 +664,9 @@ mod test { ExpNone, false, false); assert_eq!(n, None); - let f : Option = from_str_common("_1_._1_e_1_", 10, false, true, false, + let f : Option = from_str_common("_1_._5_e_1_", 10, false, true, false, ExpDec, false, true); - assert_eq!(f, Some(1.1e1f32)); + assert_eq!(f, Some(1.5e1f32)); } #[test] From 52d3f5558e663c4fab407a9ab703132b4ef6443d Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 20:19:05 -0700 Subject: [PATCH 365/403] core, rustc: Warning police --- src/libcore/rt/io/stdio.rs | 4 +- src/libcore/rt/uvio.rs | 2 +- src/libcore/task/spawn.rs | 2 +- src/librustc/metadata/decoder.rs | 2 +- src/librustc/metadata/tydecode.rs | 34 +- src/librustc/middle/check_match.rs | 2 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/trans/_match.rs | 6 +- src/librustc/middle/trans/adt.rs | 5 +- src/librustc/middle/trans/base.rs | 9 +- src/librustc/middle/trans/closure.rs | 9 +- src/librustc/middle/trans/common.rs | 4 +- src/librustc/middle/trans/debuginfo.rs | 10 +- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/foreign.rs | 8 +- src/librustc/middle/trans/glue.rs | 14 +- src/librustc/middle/trans/monomorphize.rs | 6 +- src/librustc/middle/trans/reflect.rs | 6 +- src/librustc/middle/ty.rs | 96 ++--- src/librustc/middle/typeck/astconv.rs | 14 +- src/librustc/middle/typeck/check/_match.rs | 10 +- src/librustc/middle/typeck/check/mod.rs | 351 +++++++++--------- src/librustc/middle/typeck/check/regionck.rs | 2 +- src/librustc/middle/typeck/check/writeback.rs | 2 +- src/librustc/middle/typeck/infer/combine.rs | 8 +- src/librustc/middle/typeck/infer/lattice.rs | 2 +- src/librustc/middle/typeck/infer/resolve.rs | 10 +- src/librustc/middle/typeck/mod.rs | 8 +- 28 files changed, 310 insertions(+), 320 deletions(-) diff --git a/src/libcore/rt/io/stdio.rs b/src/libcore/rt/io/stdio.rs index 21989f5e873d0..26950986f7a09 100644 --- a/src/libcore/rt/io/stdio.rs +++ b/src/libcore/rt/io/stdio.rs @@ -17,9 +17,9 @@ pub fn stdout() -> StdWriter { fail!() } pub fn stderr() -> StdReader { fail!() } -pub fn print(s: &str) { fail!() } +pub fn print(_s: &str) { fail!() } -pub fn println(s: &str) { fail!() } +pub fn println(_s: &str) { fail!() } pub enum StdStream { StdIn, diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index d4e547de3837b..7bf1792baf49b 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -11,7 +11,7 @@ use option::*; use result::*; -use super::io::net::ip::{IpAddr, Ipv4}; +use super::io::net::ip::{IpAddr, Ipv4}; // n.b. Ipv4 is used only in tests use super::uv::*; use super::rtio::*; use ops::Drop; diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index d872d38a27801..43fdee67b7a85 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -549,7 +549,7 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { } } -fn spawn_raw_newsched(opts: TaskOpts, f: ~fn()) { +fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { use rt::sched::*; let mut sched = local_sched::take(); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 248d847f89dae..460da76500428 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -247,7 +247,7 @@ fn doc_transformed_self_ty(doc: ebml::Doc, } } -pub fn item_type(item_id: ast::def_id, item: ebml::Doc, +pub fn item_type(_item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { doc_type(item, tcx, cdata) } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 709f1d4fc35d7..5d5169a5181dc 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -279,28 +279,28 @@ fn parse_trait_ref(st: @mut PState, conv: conv_did) -> ty::TraitRef { fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { match next(st) { - 'n' => return ty::mk_nil(st.tcx), - 'z' => return ty::mk_bot(st.tcx), - 'b' => return ty::mk_bool(st.tcx), - 'i' => return ty::mk_int(st.tcx), - 'u' => return ty::mk_uint(st.tcx), - 'l' => return ty::mk_float(st.tcx), + 'n' => return ty::mk_nil(), + 'z' => return ty::mk_bot(), + 'b' => return ty::mk_bool(), + 'i' => return ty::mk_int(), + 'u' => return ty::mk_uint(), + 'l' => return ty::mk_float(), 'M' => { match next(st) { - 'b' => return ty::mk_mach_uint(st.tcx, ast::ty_u8), - 'w' => return ty::mk_mach_uint(st.tcx, ast::ty_u16), - 'l' => return ty::mk_mach_uint(st.tcx, ast::ty_u32), - 'd' => return ty::mk_mach_uint(st.tcx, ast::ty_u64), - 'B' => return ty::mk_mach_int(st.tcx, ast::ty_i8), - 'W' => return ty::mk_mach_int(st.tcx, ast::ty_i16), - 'L' => return ty::mk_mach_int(st.tcx, ast::ty_i32), - 'D' => return ty::mk_mach_int(st.tcx, ast::ty_i64), - 'f' => return ty::mk_mach_float(st.tcx, ast::ty_f32), - 'F' => return ty::mk_mach_float(st.tcx, ast::ty_f64), + 'b' => return ty::mk_mach_uint(ast::ty_u8), + 'w' => return ty::mk_mach_uint(ast::ty_u16), + 'l' => return ty::mk_mach_uint(ast::ty_u32), + 'd' => return ty::mk_mach_uint(ast::ty_u64), + 'B' => return ty::mk_mach_int(ast::ty_i8), + 'W' => return ty::mk_mach_int(ast::ty_i16), + 'L' => return ty::mk_mach_int(ast::ty_i32), + 'D' => return ty::mk_mach_int(ast::ty_i64), + 'f' => return ty::mk_mach_float(ast::ty_f32), + 'F' => return ty::mk_mach_float(ast::ty_f64), _ => fail!(~"parse_ty: bad numeric type") } } - 'c' => return ty::mk_char(st.tcx), + 'c' => return ty::mk_char(), 't' => { assert!((next(st) == '[')); let def = parse_def(st, NominalType, conv); diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 8fc94cf51e2a0..04d47bf5d06d4 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -211,7 +211,7 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful { let real_pat = match m.find(|r| r[0].id != 0) { Some(r) => r[0], None => v[0] }; - let left_ty = if real_pat.id == 0 { ty::mk_nil(cx.tcx) } + let left_ty = if real_pat.id == 0 { ty::mk_nil() } else { ty::node_id_to_type(cx.tcx, real_pat.id) }; match pat_ctor_id(cx, v[0]) { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 51e6860432a2e..1696e5566e223 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -749,7 +749,7 @@ pub impl mem_categorization_ctxt { fn cat_index(&self, elt: N, base_cmt: cmt) -> cmt { - let mt = match ty::index(self.tcx, base_cmt.ty) { + let mt = match ty::index(base_cmt.ty) { Some(mt) => mt, None => { self.tcx.sess.span_bug( diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index dc59fcecb5a1e..6e84adae6dce0 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1073,8 +1073,7 @@ pub fn compare_values(cx: block, match ty::get(rhs_t).sty { ty::ty_estr(ty::vstore_uniq) => { - let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()), - false); + let scratch_result = scratch_datum(cx, ty::mk_bool(), false); let scratch_lhs = alloca(cx, val_ty(lhs)); Store(cx, lhs, scratch_lhs); let scratch_rhs = alloca(cx, val_ty(rhs)); @@ -1092,8 +1091,7 @@ pub fn compare_values(cx: block, } } ty::ty_estr(_) => { - let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()), - false); + let scratch_result = scratch_datum(cx, ty::mk_bool(), false); let did = cx.tcx().lang_items.str_eq_fn(); let bcx = callee::trans_lang_call(cx, did, ~[lhs, rhs], diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 7db6e44adcf16..b3e24fcc93951 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -50,7 +50,6 @@ use core::option::{Option, Some, None}; use core::vec; use lib::llvm::{ValueRef, TypeRef, True, IntEQ, IntNE}; -use lib::llvm::llvm::LLVMDumpValue; use middle::trans::_match; use middle::trans::build::*; use middle::trans::common::*; @@ -136,7 +135,7 @@ fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { let packed = ty::lookup_packed(cx.tcx, def_id); let dtor = ty::ty_dtor(cx.tcx, def_id).is_present(); let ftys = - if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { ftys }; + if dtor { ftys + [ty::mk_bool()] } else { ftys }; return Univariant(mk_struct(cx, ftys, packed), dtor) } ty::ty_enum(def_id, ref substs) => { @@ -204,7 +203,7 @@ fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { } // The general case. - let discr = ~[ty::mk_int(cx.tcx)]; + let discr = ~[ty::mk_int()]; return General(cases.map(|c| mk_struct(cx, discr + c.tys, false))) } _ => cx.sess.bug(~"adt::represent_type called on non-ADT type") diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 2d9f834040a8e..b86e9a512932a 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -707,7 +707,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, substs.tps, f); } (_match::switch, Some(lldiscrim_a)) => { - cx = f(cx, lldiscrim_a, ty::mk_int(cx.tcx())); + cx = f(cx, lldiscrim_a, ty::mk_int()); let unr_cx = sub_block(cx, ~"enum-iter-unr"); Unreachable(unr_cx); let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, @@ -2361,7 +2361,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext, } fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef { - let nt = ty::mk_nil(ccx.tcx); + let nt = ty::mk_nil(); let llfty = type_of_fn(ccx, ~[], nt); let llfdecl = decl_fn(ccx.llmod, ~"_rust_main", lib::llvm::CCallConv, llfty); @@ -2407,9 +2407,8 @@ pub fn create_entry_wrapper(ccx: @CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - let crate_map = ccx.crate_map; let start_def_id = ccx.tcx.lang_items.start_fn(); - let start_fn = if start_def_id.crate == ast::local_crate { + if start_def_id.crate == ast::local_crate { ccx.sess.bug(~"start lang item is never in the local crate") } else { let start_fn_type = csearch::get_type(ccx.tcx, @@ -2727,7 +2726,7 @@ pub fn trans_constant(ccx: @CrateContext, it: @ast::item) { path_name(variant.node.name), path_name(special_idents::descrim) ]); - let s = @mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); + let s = @mangle_exported_name(ccx, p, ty::mk_int()); let disr_val = vi[i].disr_val; note_unique_llvm_symbol(ccx, s); let discrim_gvar = str::as_c_str(*s, |buf| { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 4fc4cae464dab..e532e5e1dfd09 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -261,8 +261,7 @@ pub fn build_closure(bcx0: block, include_ret_handle: Option) -> ClosureResult { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call - let bcx = bcx0;; - let ccx = bcx.ccx(), tcx = ccx.tcx; + let bcx = bcx0; // Package up the captured upvars let mut env_vals = ~[]; @@ -290,7 +289,7 @@ pub fn build_closure(bcx0: block, // variables: for include_ret_handle.each |flagptr| { // Flag indicating we have returned (a by-ref bool): - let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(tcx), + let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(), mode: ByRef, source: ZeroMem}; env_vals.push(EnvValue {action: EnvRef, datum: flag_datum}); @@ -302,7 +301,7 @@ pub fn build_closure(bcx0: block, None => bcx.fcx.llretptr.get() }; let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil())); - let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(tcx), + let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(), mode: ByRef, source: ZeroMem}; env_vals.push(EnvValue {action: EnvRef, datum: ret_datum}); @@ -420,7 +419,7 @@ pub fn trans_expr_fn(bcx: block, } let real_return_type = if is_loop_body.is_some() { - ty::mk_bool(bcx.tcx()) + ty::mk_bool() } else { ty::ty_fn_ret(fty) }; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 83fe135d8721f..7aade041fbc33 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -999,9 +999,9 @@ pub fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef { pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { let ptr = ty::mk_ptr( tcx, - ty::mt {ty: ty::mk_nil(tcx), mutbl: ast::m_imm} + ty::mt {ty: ty::mk_nil(), mutbl: ast::m_imm} ); - return ty::mk_tup(tcx, ~[ty::mk_uint(tcx), ty::mk_type(tcx), + return ty::mk_tup(tcx, ~[ty::mk_uint(), ty::mk_type(tcx), ptr, ptr, t]); } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index eb8209bf7a718..6c1fbff664b6e 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -560,7 +560,7 @@ fn create_boxed_type(cx: @CrateContext, contents: ty::t, let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); //let cu_node = create_compile_unit_metadata(cx, fname); - let int_t = ty::mk_int(cx.tcx); + let int_t = ty::mk_int(); let refcount_type = create_basic_type(cx, int_t, span); let name = ty_to_str(cx.tcx, contents); let scx = create_structure(file_node, @fmt!("box<%s>", name), 0); @@ -643,7 +643,7 @@ fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, let elem_ty_md = create_ty(cx, elem_t, vec_ty_span); let vec_scx = create_structure(file_node, @/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0); - let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span); + let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span); add_member(vec_scx, ~"fill", 0, sys::size_of::() as int, sys::min_align_of::() as int, size_t_type.node); add_member(vec_scx, ~"alloc", 0, sys::size_of::() as int, @@ -666,7 +666,7 @@ fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, }; let box_scx = create_structure(file_node, @fmt!("box<%s>", name), 0); - let int_t = ty::mk_int(cx.tcx); + let int_t = ty::mk_int(); let refcount_type = create_basic_type(cx, int_t, vec_ty_span); add_member(box_scx, ~"refcnt", 0, sys::size_of::() as int, sys::min_align_of::() as int, refcount_type.node); @@ -692,7 +692,7 @@ fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); let elem_ty_md = create_ty(cx, elem_t, span); - let uint_type = create_basic_type(cx, ty::mk_uint(cx.tcx), span); + let uint_type = create_basic_type(cx, ty::mk_uint(), span); let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md); let scx = create_structure(file_node, @ty_to_str(cx.tcx, vec_t), 0); let (_, ptr_size, ptr_align) = voidptr(); @@ -744,7 +744,7 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) => create_basic_type(cx, t, span), ty::ty_estr(ref vstore) => { - let i8_t = ty::mk_i8(cx.tcx); + let i8_t = ty::mk_i8(); match *vstore { ty::vstore_fixed(len) => { create_fixed_vec(cx, t, i8_t, len as int + 1, span) diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 8727db27fff0b..21fb11813e8e8 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -791,7 +791,7 @@ fn trans_def_datum_unadjusted(bcx: block, let rust_ty = ty::mk_ptr( bcx.tcx(), ty::mt { - ty: ty::mk_mach_uint(bcx.tcx(), ast::ty_u8), + ty: ty::mk_mach_uint(ast::ty_u8), mutbl: ast::m_imm }); // *u8 (rust_ty, PointerCast(bcx, fn_data.llfn, T_ptr(T_i8()))) diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index cb15a2e8c644a..22a60a1ed2e3b 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -768,7 +768,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let frameaddress_val = Call(bcx, frameaddress, ~[C_i32(0i32)]); let star_u8 = ty::mk_imm_ptr( bcx.tcx(), - ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)); + ty::mk_mach_uint(ast::ty_u8)); let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy { purity: ast::impure_fn, sigil: ast::BorrowedSigil, @@ -777,13 +777,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, sig: FnSig {bound_lifetime_names: opt_vec::Empty, inputs: ~[arg {mode: ast::expl(ast::by_copy), ty: star_u8}], - output: ty::mk_nil(bcx.tcx())} + output: ty::mk_nil()} }); let datum = Datum {val: get_param(decl, first_real_arg), mode: ByRef, ty: fty, source: ZeroMem}; let arg_vals = ~[frameaddress_val]; bcx = trans_call_inner( - bcx, None, fty, ty::mk_nil(bcx.tcx()), + bcx, None, fty, ty::mk_nil(), |bcx| Callee {bcx: bcx, data: Closure(datum)}, ArgVals(arg_vals), Ignore, DontAutorefArg); } @@ -791,7 +791,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, // XXX This is a hack to grab the address of this particular // native function. There should be a general in-language // way to do this - let llfty = type_of_fn(bcx.ccx(), ~[], ty::mk_nil(bcx.tcx())); + let llfty = type_of_fn(bcx.ccx(), ~[], ty::mk_nil()); let morestack_addr = decl_cdecl_fn( bcx.ccx().llmod, ~"__morestack", llfty); let morestack_addr = PointerCast(bcx, morestack_addr, diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 9031871de560d..bdf50619e62d5 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -168,19 +168,19 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { field == abi::tydesc_field_drop_glue || field == abi::tydesc_field_free_glue) && ! ty::type_needs_drop(tcx, t) { - return ty::mk_u32(tcx); + return ty::mk_u32(); } if field == abi::tydesc_field_take_glue { match ty::get(t).sty { - ty::ty_unboxed_vec(*) => { return ty::mk_u32(tcx); } + ty::ty_unboxed_vec(*) => { return ty::mk_u32(); } _ => () } } if field == abi::tydesc_field_take_glue && ty::type_is_boxed(t) { - return ty::mk_imm_box(tcx, ty::mk_u32(tcx)); + return ty::mk_imm_box(tcx, ty::mk_u32()); } if field == abi::tydesc_field_free_glue { @@ -193,7 +193,7 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) | ty::ty_opaque_closure_ptr(*) => (), - _ => { return ty::mk_u32(tcx); } + _ => { return ty::mk_u32(); } } } @@ -203,12 +203,12 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { ty::ty_box(mt) | ty::ty_evec(mt, ty::vstore_box) if ! ty::type_needs_drop(tcx, mt.ty) => - return ty::mk_imm_box(tcx, ty::mk_u32(tcx)), + return ty::mk_imm_box(tcx, ty::mk_u32()), ty::ty_uniq(mt) | ty::ty_evec(mt, ty::vstore_uniq) if ! ty::type_needs_drop(tcx, mt.ty) => - return ty::mk_imm_uniq(tcx, ty::mk_u32(tcx)), + return ty::mk_imm_uniq(tcx, ty::mk_u32()), _ => () } @@ -736,7 +736,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, helper: glue_helper) -> ValueRef { let _icx = ccx.insn_ctxt("make_generic_glue_inner"); - let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(ccx.tcx), None); + let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); ccx.stats.n_glues_created += 1u; // All glue functions take values passed *by alias*; this is a diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 052bea1b022c5..a7221297eca02 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -307,7 +307,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, abis: AbiSet::Rust(), sig: FnSig {bound_lifetime_names: opt_vec::Empty, inputs: ~[], - output: ty::mk_nil(tcx)}})) + output: ty::mk_nil()}})) } ty::ty_closure(ref fty) => { Some(normalized_closure_ty(tcx, fty.sigil)) @@ -323,7 +323,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, Some(normalized_closure_ty(tcx, sigil)) } ty::ty_ptr(_) => { - Some(ty::mk_uint(tcx)) + Some(ty::mk_uint()) } _ => { None @@ -342,7 +342,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, region: ty::re_static, sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty, inputs: ~[], - output: ty::mk_nil(tcx)}}) + output: ty::mk_nil()}}) } } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index ffb2cc01ab249..741b111b6a0a7 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -98,7 +98,7 @@ pub impl Reflector { for args.eachi |i, a| { debug!("arg %u: %s", i, val_str(bcx.ccx().tn, *a)); } - let bool_ty = ty::mk_bool(tcx); + let bool_ty = ty::mk_bool(); let scratch = scratch_datum(bcx, bool_ty, false); // XXX: Should not be BoxTraitStore! let bcx = callee::trans_call_inner( @@ -283,7 +283,7 @@ pub impl Reflector { let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr"); let args = [ty::arg { mode: ast::expl(ast::by_copy), ty: opaqueptrty }]; - let llfty = type_of_fn(ccx, args, ty::mk_int(ccx.tcx)); + let llfty = type_of_fn(ccx, args, ty::mk_int()); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); let arg = unsafe { llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) @@ -291,7 +291,7 @@ pub impl Reflector { let fcx = new_fn_ctxt(ccx, ~[], llfdecl, - ty::mk_uint(ccx.tcx), + ty::mk_uint(), None); let bcx = top_scope_block(fcx, None); let arg = BitCast(bcx, arg, llptrty); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7cdd7c8a6f278..f312dbca5c3c8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -949,12 +949,12 @@ pub fn mk_ctxt(s: session::Session, fn mk_t(cx: ctxt, st: sty) -> t { // Check for primitive types. match st { - ty_nil => return mk_nil(cx), - ty_err => return mk_err(cx), - ty_bool => return mk_bool(cx), - ty_int(i) => return mk_mach_int(cx, i), - ty_uint(u) => return mk_mach_uint(cx, u), - ty_float(f) => return mk_mach_float(cx, f), + ty_nil => return mk_nil(), + ty_err => return mk_err(), + ty_bool => return mk_bool(), + ty_int(i) => return mk_mach_int(i), + ty_uint(u) => return mk_mach_uint(u), + ty_float(f) => return mk_mach_float(f), _ => {} }; @@ -1052,94 +1052,94 @@ fn mk_t(cx: ctxt, st: sty) -> t { } #[inline(always)] -pub fn mk_prim_t(cx: ctxt, primitive: &'static t_box_) -> t { +pub fn mk_prim_t(primitive: &'static t_box_) -> t { unsafe { cast::transmute::<&'static t_box_, t>(primitive) } } #[inline(always)] -pub fn mk_nil(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_NIL) } +pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) } #[inline(always)] -pub fn mk_err(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_ERR) } +pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) } #[inline(always)] -pub fn mk_bot(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOT) } +pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) } #[inline(always)] -pub fn mk_bool(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOOL) } +pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) } #[inline(always)] -pub fn mk_int(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_INT) } +pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) } #[inline(always)] -pub fn mk_i8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I8) } +pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) } #[inline(always)] -pub fn mk_i16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I16) } +pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) } #[inline(always)] -pub fn mk_i32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I32) } +pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) } #[inline(always)] -pub fn mk_i64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I64) } +pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) } #[inline(always)] -pub fn mk_float(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_FLOAT) } +pub fn mk_float() -> t { mk_prim_t(&primitives::TY_FLOAT) } #[inline(always)] -pub fn mk_f32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F32) } +pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) } #[inline(always)] -pub fn mk_f64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F64) } +pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) } #[inline(always)] -pub fn mk_uint(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_UINT) } +pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) } #[inline(always)] -pub fn mk_u8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U8) } +pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) } #[inline(always)] -pub fn mk_u16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U16) } +pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) } #[inline(always)] -pub fn mk_u32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U32) } +pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) } #[inline(always)] -pub fn mk_u64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U64) } +pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) } -pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { +pub fn mk_mach_int(tm: ast::int_ty) -> t { match tm { - ast::ty_i => mk_int(cx), - ast::ty_char => mk_char(cx), - ast::ty_i8 => mk_i8(cx), - ast::ty_i16 => mk_i16(cx), - ast::ty_i32 => mk_i32(cx), - ast::ty_i64 => mk_i64(cx), + ast::ty_i => mk_int(), + ast::ty_char => mk_char(), + ast::ty_i8 => mk_i8(), + ast::ty_i16 => mk_i16(), + ast::ty_i32 => mk_i32(), + ast::ty_i64 => mk_i64(), } } -pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { +pub fn mk_mach_uint(tm: ast::uint_ty) -> t { match tm { - ast::ty_u => mk_uint(cx), - ast::ty_u8 => mk_u8(cx), - ast::ty_u16 => mk_u16(cx), - ast::ty_u32 => mk_u32(cx), - ast::ty_u64 => mk_u64(cx), + ast::ty_u => mk_uint(), + ast::ty_u8 => mk_u8(), + ast::ty_u16 => mk_u16(), + ast::ty_u32 => mk_u32(), + ast::ty_u64 => mk_u64(), } } -pub fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t { +pub fn mk_mach_float(tm: ast::float_ty) -> t { match tm { - ast::ty_f => mk_float(cx), - ast::ty_f32 => mk_f32(cx), - ast::ty_f64 => mk_f64(cx), + ast::ty_f => mk_float(), + ast::ty_f32 => mk_f32(), + ast::ty_f64 => mk_f64(), } } #[inline(always)] -pub fn mk_char(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_CHAR) } +pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) } pub fn mk_estr(cx: ctxt, t: vstore) -> t { mk_t(cx, ty_estr(t)) @@ -1182,7 +1182,7 @@ pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t { } pub fn mk_nil_ptr(cx: ctxt) -> t { - mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::m_imm}) + mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm}) } pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t { @@ -1610,7 +1610,7 @@ pub fn type_is_str(ty: t) -> bool { pub fn sequence_element_type(cx: ctxt, ty: t) -> t { match get(ty).sty { - ty_estr(_) => return mk_mach_uint(cx, ast::ty_u8), + ty_estr(_) => return mk_mach_uint(ast::ty_u8), ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty, _ => cx.sess.bug( ~"sequence_element_type called on non-sequence value"), @@ -2614,14 +2614,14 @@ pub fn type_autoderef(cx: ctxt, t: t) -> t { } // Returns the type and mutability of t[i] -pub fn index(cx: ctxt, t: t) -> Option { - index_sty(cx, &get(t).sty) +pub fn index(t: t) -> Option { + index_sty(&get(t).sty) } -pub fn index_sty(cx: ctxt, sty: &sty) -> Option { +pub fn index_sty(sty: &sty) -> Option { match *sty { ty_evec(mt, _) => Some(mt), - ty_estr(_) => Some(mt {ty: mk_u8(cx), mutbl: ast::m_imm}), + ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}), _ => None } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 10acea1291f92..f75ec183473c1 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -352,8 +352,8 @@ pub fn ast_ty_to_ty( tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved); let typ = match ast_ty.node { - ast::ty_nil => ty::mk_nil(tcx), - ast::ty_bot => ty::mk_bot(tcx), + ast::ty_nil => ty::mk_nil(), + ast::ty_bot => ty::mk_bot(), ast::ty_box(ref mt) => { mk_pointer(self, rscope, mt, ty::vstore_box, |tmt| ty::mk_box(tcx, tmt)) @@ -413,7 +413,7 @@ pub fn ast_ty_to_ty( fmt!("reference to trait `%s` where a type is expected; \ try `@%s`, `~%s`, or `&%s`", path_str, path_str, path_str, path_str)); - ty::mk_err(tcx) + ty::mk_err() } ast::def_ty(did) | ast::def_struct(did) => { ast_path_to_ty(self, rscope, did, path).ty @@ -422,19 +422,19 @@ pub fn ast_ty_to_ty( match nty { ast::ty_bool => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_bool(tcx) + ty::mk_bool() } ast::ty_int(it) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_mach_int(tcx, it) + ty::mk_mach_int(it) } ast::ty_uint(uit) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_mach_uint(tcx, uit) + ty::mk_mach_uint(uit) } ast::ty_float(ft) => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_mach_float(tcx, ft) + ty::mk_mach_float(ft) } ast::ty_str => { tcx.sess.span_err(ast_ty.span, diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index c58ad0bfa3b34..c52989c5d22cd 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -56,7 +56,7 @@ pub fn check_match(fcx: @mut FnCtxt, let mut guard_bot = false; match arm.guard { Some(e) => { - check_expr_has_type(fcx, e, ty::mk_bool(tcx)); + check_expr_has_type(fcx, e, ty::mk_bool()); let e_ty = fcx.expr_ty(e); if ty::type_is_error(e_ty) { guard_err = true; @@ -84,10 +84,10 @@ pub fn check_match(fcx: @mut FnCtxt, demand::suptype(fcx, arm.body.span, result_ty, bty); } if saw_err { - result_ty = ty::mk_err(tcx); + result_ty = ty::mk_err(); } else if !arm_non_bot { - result_ty = ty::mk_bot(tcx); + result_ty = ty::mk_bot(); } fcx.write_ty(expr.id, result_ty); } @@ -230,11 +230,9 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, } if error_happened { - let tcx = pcx.fcx.ccx.tcx; - for subpats.each |pats| { for pats.each |pat| { - check_pat(pcx, *pat, ty::mk_err(tcx)); + check_pat(pcx, *pat, ty::mk_err()); } } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index ca9b3602d5d37..dd147d9e46887 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -753,13 +753,13 @@ pub impl FnCtxt { } fn write_nil(&self, node_id: ast::node_id) { - self.write_ty(node_id, ty::mk_nil(self.tcx())); + self.write_ty(node_id, ty::mk_nil()); } fn write_bot(&self, node_id: ast::node_id) { - self.write_ty(node_id, ty::mk_bot(self.tcx())); + self.write_ty(node_id, ty::mk_bot()); } fn write_error(@mut self, node_id: ast::node_id) { - self.write_ty(node_id, ty::mk_err(self.tcx())); + self.write_ty(node_id, ty::mk_err()); } fn to_ty(&self, ast_t: @ast::Ty) -> ty::t { @@ -1008,21 +1008,21 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t { match lit.node { ast::lit_str(*) => ty::mk_estr(tcx, ty::vstore_slice(ty::re_static)), - ast::lit_int(_, t) => ty::mk_mach_int(tcx, t), - ast::lit_uint(_, t) => ty::mk_mach_uint(tcx, t), + ast::lit_int(_, t) => ty::mk_mach_int(t), + ast::lit_uint(_, t) => ty::mk_mach_uint(t), ast::lit_int_unsuffixed(_) => { // An unsuffixed integer literal could have any integral type, // so we create an integral type variable for it. ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()) } - ast::lit_float(_, t) => ty::mk_mach_float(tcx, t), + ast::lit_float(_, t) => ty::mk_mach_float(t), ast::lit_float_unsuffixed(_) => { // An unsuffixed floating point literal could have any floating point // type, so we create a floating point type variable for it. ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()) } - ast::lit_nil => ty::mk_nil(tcx), - ast::lit_bool(_) => ty::mk_bool(tcx) + ast::lit_nil => ty::mk_nil(), + ast::lit_bool(_) => ty::mk_bool() } } @@ -1146,7 +1146,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, deref_args: DerefArgs) -> ty::t { if ty::type_is_error(method_fn_ty) { - let err_inputs = err_args(fcx.tcx(), args.len()); + let err_inputs = err_args(args.len()); check_argument_types(fcx, sp, err_inputs, callee_expr, args, sugar, deref_args); method_fn_ty @@ -1209,7 +1209,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, tcx.sess.span_err(sp, msg); - vec::from_elem(supplied_arg_count, ty::mk_err(tcx)) + vec::from_elem(supplied_arg_count, ty::mk_err()) }; debug!("check_argument_types: formal_tys=%?", @@ -1265,9 +1265,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - fn err_args(tcx: ty::ctxt, len: uint) -> ~[ty::arg] { + fn err_args(len: uint) -> ~[ty::arg] { vec::from_fn(len, |_| ty::arg {mode: ast::expl(ast::by_copy), - ty: ty::mk_err(tcx)}) + ty: ty::mk_err()}) } // A generic function for checking assignment expressions @@ -1278,7 +1278,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, check_expr(fcx, lhs); let lhs_type = fcx.expr_ty(lhs); check_expr_has_type(fcx, rhs, lhs_type); - fcx.write_ty(id, ty::mk_nil(fcx.ccx.tcx)); + fcx.write_ty(id, ty::mk_nil()); // The callee checks for bot / err, we don't need to } @@ -1321,8 +1321,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // check each arg against "error", in order to set up // all the node type bindings FnSig {bound_lifetime_names: opt_vec::Empty, - inputs: err_args(fcx.tcx(), args.len()), - output: ty::mk_err(fcx.tcx())} + inputs: err_args(args.len()), + output: ty::mk_err()} } }; @@ -1417,7 +1417,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } None => { check_block_no_value(fcx, thn); - ty::mk_nil(fcx.ccx.tcx) + ty::mk_nil() } }; @@ -1448,15 +1448,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::NoSugar, deref_args) } _ => { - let tcx = fcx.tcx(); unbound_method(); // Check the args anyway // so we get all the error messages - let expected_ty = ty::mk_err(tcx); + let expected_ty = ty::mk_err(); check_method_argument_types(fcx, op_ex.span, expected_ty, op_ex, args, ast::NoSugar, deref_args); - ty::mk_err(tcx) + ty::mk_err() } } } @@ -1494,7 +1493,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let result_t = match op { ast::eq | ast::ne | ast::lt | ast::le | ast::ge | ast::gt => { - ty::mk_bool(tcx) + ty::mk_bool() } _ => { lhs_t @@ -1565,7 +1564,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - ty::mk_err(tcx) + ty::mk_err() } fn check_user_unop(fcx: @mut FnCtxt, @@ -1671,11 +1670,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, bound_lifetime_names: opt_vec::Empty, inputs: fn_ty.sig.inputs.map(|an_arg| { arg { mode: an_arg.mode, - ty: ty::mk_err(tcx) + ty: ty::mk_err() }}), - output: ty::mk_err(tcx) + output: ty::mk_err() }; - ty::mk_err(tcx) + ty::mk_err() } else { let fn_ty_copy = copy fn_ty; @@ -1792,7 +1791,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Typecheck each field. for ast_fields.each |field| { - let mut expected_field_type = ty::mk_err(tcx); + let mut expected_field_type = ty::mk_err(); let pair = class_field_map.find(&field.node.ident). map_consume(|x| *x); @@ -1934,7 +1933,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fields, base_expr.is_none()); if ty::type_is_error(fcx.node_ty(id)) { - struct_type = ty::mk_err(tcx); + struct_type = ty::mk_err(); } // Check the base expression if necessary. @@ -1943,7 +1942,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, Some(base_expr) => { check_expr_has_type(fcx, base_expr, struct_type); if ty::type_is_bot(fcx.node_ty(base_expr.id)) { - struct_type = ty::mk_bot(tcx); + struct_type = ty::mk_bot(); } } } @@ -2040,10 +2039,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let inner_ty = match expected_sty { Some(ty::ty_closure(ref fty)) => { match fcx.mk_subty(false, expr.span, - fty.sig.output, ty::mk_bool(tcx)) { + fty.sig.output, ty::mk_bool()) { result::Ok(_) => { ty::mk_closure(tcx, ty::ClosureTy { - sig: FnSig {output: ty::mk_nil(tcx), + sig: FnSig {output: ty::mk_nil(), ..copy fty.sig}, ..copy *fty }) @@ -2070,7 +2069,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, None); err_happened = true; fcx.write_error(expr.id); - ty::mk_err(tcx) + ty::mk_err() } } } @@ -2085,7 +2084,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, actual) }, expected_t, None); - let err_ty = ty::mk_err(tcx); + let err_ty = ty::mk_err(); fcx.write_error(expr.id); err_happened = true; err_ty @@ -2131,7 +2130,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } else { let loop_body_ty = ty::replace_closure_return_type( - tcx, block_ty, ty::mk_bool(tcx)); + tcx, block_ty, ty::mk_bool()); fcx.write_ty(expr.id, loop_body_ty); } } @@ -2168,10 +2167,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } if any_error { - ty::mk_err(tcx) + ty::mk_err() } else if any_bot { - ty::mk_bot(tcx) + ty::mk_bot() } else { ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutability}, tt) @@ -2179,7 +2178,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } ast::expr_repeat(element, count_expr, mutbl) => { let _ = ty::eval_repeat_count(tcx, count_expr); - check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx)); + check_expr_with_hint(fcx, count_expr, ty::mk_uint()); let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); let mutability = match vst { ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => { @@ -2191,9 +2190,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, check_expr_has_type(fcx, element, t); let arg_t = fcx.expr_ty(element); if ty::type_is_error(arg_t) { - ty::mk_err(tcx) + ty::mk_err() } else if ty::type_is_bot(arg_t) { - ty::mk_bot(tcx) + ty::mk_bot() } else { ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutability}, tt) } @@ -2351,9 +2350,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let tm = ty::mt { ty: fcx.expr_ty(oprnd), mutbl: mutbl }; let oprnd_t = if ty::type_is_error(tm.ty) { - ty::mk_err(tcx) + ty::mk_err() } else if ty::type_is_bot(tm.ty) { - ty::mk_bot(tcx) + ty::mk_bot() } else { ty::mk_rptr(tcx, region, tm) @@ -2387,7 +2386,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, }; match expr_opt { None => match fcx.mk_eqty(false, expr.span, - ret_ty, ty::mk_nil(tcx)) { + ret_ty, ty::mk_nil()) { result::Ok(_) => { /* fall through */ } result::Err(_) => { tcx.sess.span_err( @@ -2403,7 +2402,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } ast::expr_log(lv, e) => { check_expr_has_type(fcx, lv, - ty::mk_mach_uint(tcx, ast::ty_u32)); + ty::mk_mach_uint(ast::ty_u32)); // Note: this does not always execute, so do not propagate bot: check_expr(fcx, e); @@ -2451,7 +2450,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } ast::expr_if(cond, ref thn, elsopt) => { - check_expr_has_type(fcx, cond, ty::mk_bool(tcx)); + check_expr_has_type(fcx, cond, ty::mk_bool()); check_then_else(fcx, thn, elsopt, id, expr.span); let cond_ty = fcx.expr_ty(cond); let then_ty = fcx.node_ty(thn.node.id); @@ -2471,7 +2470,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Other cases were handled by check_then_else } ast::expr_while(cond, ref body) => { - check_expr_has_type(fcx, cond, ty::mk_bool(tcx)); + check_expr_has_type(fcx, cond, ty::mk_bool()); check_block_no_value(fcx, body); let cond_ty = fcx.expr_ty(cond); let body_ty = fcx.node_ty(body.node.id); @@ -2539,7 +2538,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, has non-closure type: %s", actual) }, expected_t, None); - let err_ty = ty::mk_err(tcx); + let err_ty = ty::mk_err(); fcx.write_ty(id, err_ty); err_ty } @@ -2706,7 +2705,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } ast::expr_repeat(element, count_expr, mutbl) => { let count = ty::eval_repeat_count(tcx, count_expr); - check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx)); + check_expr_with_hint(fcx, count_expr, ty::mk_uint()); let t: ty::t = fcx.infcx().next_ty_var(); check_expr_has_type(fcx, element, t); let element_ty = fcx.expr_ty(element); @@ -2782,7 +2781,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, else { let (base_t, derefs) = do_autoderef(fcx, expr.span, raw_base_t); let base_sty = structure_of(fcx, expr.span, base_t); - match ty::index_sty(tcx, &base_sty) { + match ty::index_sty(&base_sty) { Some(mt) => { require_integral(fcx, idx.span, idx_t); fcx.write_ty(id, mt.ty); @@ -2886,7 +2885,7 @@ pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::stmt) { ast::stmt_expr(expr, id) => { node_id = id; // Check with expected type of () - check_expr_has_type(fcx, expr, ty::mk_nil(fcx.ccx.tcx)); + check_expr_has_type(fcx, expr, ty::mk_nil()); let expr_ty = fcx.expr_ty(expr); saw_bot = saw_bot || ty::type_is_bot(expr_ty); saw_err = saw_err || ty::type_is_error(expr_ty); @@ -2912,7 +2911,7 @@ pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::stmt) { } pub fn check_block_no_value(fcx: @mut FnCtxt, blk: &ast::blk) { - check_block_with_expected(fcx, blk, Some(ty::mk_nil(fcx.ccx.tcx))); + check_block_with_expected(fcx, blk, Some(ty::mk_nil())); let blkty = fcx.node_ty(blk.node.id); if ty::type_is_error(blkty) { fcx.write_error(blk.node.id); @@ -2921,7 +2920,7 @@ pub fn check_block_no_value(fcx: @mut FnCtxt, blk: &ast::blk) { fcx.write_bot(blk.node.id); } else { - let nilty = ty::mk_nil(fcx.ccx.tcx); + let nilty = ty::mk_nil(); demand::suptype(fcx, blk.span, nilty, blkty); } } @@ -3054,7 +3053,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, let e = *e_ref; debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr())); - let declty = ty::mk_int(ccx.tcx); + let declty = ty::mk_int(); let fcx = blank_fn_ctxt(ccx, rty, e.id); check_const_with_ty(fcx, e.span, e, declty); // check_expr (from check_const pass) doesn't guarantee @@ -3173,7 +3172,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, ty: ty::mk_ptr( fcx.ccx.tcx, ty::mt { - ty: ty::mk_mach_uint(fcx.ccx.tcx, ast::ty_u8), + ty: ty::mk_mach_uint(ast::ty_u8), mutbl: ast::m_imm }) }; @@ -3296,7 +3295,7 @@ pub fn structurally_resolved_type(fcx: @mut FnCtxt, sp: span, tp: ty::t) fcx.type_error_message(sp, |_actual| { ~"the type of this value must be known in this context" }, tp, None); - demand::suptype(fcx, sp, ty::mk_err(fcx.tcx()), tp); + demand::suptype(fcx, sp, ty::mk_err(), tp); tp } } @@ -3413,10 +3412,10 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { let tcx = ccx.tcx; let (n_tps, inputs, output) = match *ccx.tcx.sess.str_of(it.ident) { ~"size_of" | - ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint(ccx.tcx)), + ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()), ~"init" => (1u, ~[], param(ccx, 0u)), ~"forget" => (1u, ~[arg(ast::by_copy, param(ccx, 0u))], - ty::mk_nil(tcx)), + ty::mk_nil()), ~"reinterpret_cast" => (2u, ~[arg(ast::by_ref, param(ccx, 0u))], param(ccx, 1u)), ~"addr_of" => (1u, ~[arg(ast::by_ref, param(ccx, 0u))], @@ -3426,41 +3425,41 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0u))), arg(ast::by_copy, param(ccx, 0u))], - ty::mk_nil(tcx)) + ty::mk_nil()) } - ~"needs_drop" => (1u, ~[], ty::mk_bool(tcx)), + ~"needs_drop" => (1u, ~[], ty::mk_bool()), ~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => { (0u, ~[arg(ast::by_copy, ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), - ty::mk_int(tcx))), - arg(ast::by_copy, ty::mk_int(tcx)), - arg(ast::by_copy, ty::mk_int(tcx))], - ty::mk_int(tcx)) + ty::mk_int())), + arg(ast::by_copy, ty::mk_int()), + arg(ast::by_copy, ty::mk_int())], + ty::mk_int()) } ~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" | ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" | ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => { (0u, ~[arg(ast::by_copy, ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), - ty::mk_int(tcx))), - arg(ast::by_copy, ty::mk_int(tcx))], - ty::mk_int(tcx)) + ty::mk_int())), + arg(ast::by_copy, ty::mk_int())], + ty::mk_int()) } ~"get_tydesc" => { // FIXME (#3730): return *intrinsic::tydesc, not *() - (1u, ~[], ty::mk_nil_ptr(tcx)) + (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) } ~"visit_tydesc" => { let tydesc_name = special_idents::tydesc; assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name); - let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); + let (_, visitor_object_ty) = ty::visitor_object_ty(ccx.tcx); let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty, mutbl: ast::m_imm}); (0u, ~[arg(ast::by_copy, td_ptr), - arg(ast::by_ref, visitor_object_ty)], ty::mk_nil(tcx)) + arg(ast::by_ref, visitor_object_ty)], ty::mk_nil()) } ~"frame_address" => { let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { @@ -3473,224 +3472,224 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { inputs: ~[arg {mode: ast::expl(ast::by_copy), ty: ty::mk_imm_ptr( ccx.tcx, - ty::mk_mach_uint(ccx.tcx, ast::ty_u8))}], - output: ty::mk_nil(ccx.tcx) + ty::mk_mach_uint(ast::ty_u8))}], + output: ty::mk_nil() } }); - (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil(tcx)) + (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil()) } ~"morestack_addr" => { - (0u, ~[], ty::mk_nil_ptr(tcx)) + (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) } ~"memmove32" => { (0, ~[arg(ast::by_copy, ty::mk_ptr(tcx, - ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl })), + ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })), arg(ast::by_copy, ty::mk_ptr(tcx, - ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_imm })), + ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })), arg(ast::by_copy, - ty::mk_u32(tcx))], - ty::mk_nil(tcx)) + ty::mk_u32())], + ty::mk_nil()) } ~"memmove64" => { (0, ~[arg(ast::by_copy, ty::mk_ptr(tcx, - ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl })), + ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })), arg(ast::by_copy, ty::mk_ptr(tcx, - ty::mt { ty: ty::mk_u8(tcx), mutbl: ast::m_imm })), + ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })), arg(ast::by_copy, - ty::mk_u64(tcx))], - ty::mk_nil(tcx)) + ty::mk_u64())], + ty::mk_nil()) } ~"sqrtf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"sqrtf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"powif32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)), - arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32()), + arg(ast::by_copy, ty::mk_i32())], + ty::mk_f32()) } ~"powif64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)), - arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64()), + arg(ast::by_copy, ty::mk_i32())], + ty::mk_f64()) } ~"sinf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"sinf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"cosf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"cosf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"powf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)), - arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32()), + arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"powf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)), - arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64()), + arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"expf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"expf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"exp2f32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"exp2f64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"logf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"logf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"log10f32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"log10f64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"log2f32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"log2f64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"fmaf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)), - arg(ast::by_copy, ty::mk_f32(tcx)), - arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32()), + arg(ast::by_copy, ty::mk_f32()), + arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"fmaf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)), - arg(ast::by_copy, ty::mk_f64(tcx)), - arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64()), + arg(ast::by_copy, ty::mk_f64()), + arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"fabsf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"fabsf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"floorf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"floorf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"ceilf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"ceilf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"truncf32" => { - (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))], - ty::mk_f32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f32())], + ty::mk_f32()) } ~"truncf64" => { - (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))], - ty::mk_f64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_f64())], + ty::mk_f64()) } ~"ctpop8" => { - (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], - ty::mk_i8(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i8())], + ty::mk_i8()) } ~"ctpop16" => { - (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], - ty::mk_i16(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i16())], + ty::mk_i16()) } ~"ctpop32" => { - (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_i32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i32())], + ty::mk_i32()) } ~"ctpop64" => { - (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], - ty::mk_i64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i64())], + ty::mk_i64()) } ~"ctlz8" => { - (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], - ty::mk_i8(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i8())], + ty::mk_i8()) } ~"ctlz16" => { - (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], - ty::mk_i16(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i16())], + ty::mk_i16()) } ~"ctlz32" => { - (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_i32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i32())], + ty::mk_i32()) } ~"ctlz64" => { - (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], - ty::mk_i64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i64())], + ty::mk_i64()) } ~"cttz8" => { - (0u, ~[arg(ast::by_copy, ty::mk_i8(tcx))], - ty::mk_i8(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i8())], + ty::mk_i8()) } ~"cttz16" => { - (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], - ty::mk_i16(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i16())], + ty::mk_i16()) } ~"cttz32" => { - (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_i32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i32())], + ty::mk_i32()) } ~"cttz64" => { - (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], - ty::mk_i64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i64())], + ty::mk_i64()) } ~"bswap16" => { - (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], - ty::mk_i16(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i16())], + ty::mk_i16()) } ~"bswap32" => { - (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], - ty::mk_i32(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i32())], + ty::mk_i32()) } ~"bswap64" => { - (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], - ty::mk_i64(tcx)) + (0u, ~[arg(ast::by_copy, ty::mk_i64())], + ty::mk_i64()) } ref other => { tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" + diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index aec7399d5eb97..cd10e1f9787cb 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -108,7 +108,7 @@ pub impl Rcx { match resolve_type(self.fcx.infcx(), unresolved_ty, resolve_and_force_all_but_regions) { Ok(t) => t, - Err(_) => ty::mk_err(self.fcx.tcx()) + Err(_) => ty::mk_err() } } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 0dba55b4e72cf..894b508b30965 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -57,7 +57,7 @@ fn resolve_type_vars_in_types(fcx: @mut FnCtxt, sp: span, tys: &[ty::t]) tys.map(|t| { match resolve_type_vars_in_type(fcx, sp, *t) { Some(t1) => t1, - None => ty::mk_err(fcx.ccx.tcx) + None => ty::mk_err() } }) } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index fdc96a21b8b5c..3f58a32247245 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -613,14 +613,13 @@ pub fn super_tys( vid: ty::IntVid, val: ty::IntVarValue) -> cres { - let tcx = self.infcx().tcx; if val == IntType(ast::ty_char) { Err(ty::terr_integer_as_char) } else { if_ok!(self.infcx().simple_var_t(vid_is_expected, vid, val)); match val { - IntType(v) => Ok(ty::mk_mach_int(tcx, v)), - UintType(v) => Ok(ty::mk_mach_uint(tcx, v)) + IntType(v) => Ok(ty::mk_mach_int(v)), + UintType(v) => Ok(ty::mk_mach_uint(v)) } } } @@ -631,9 +630,8 @@ pub fn super_tys( vid: ty::FloatVid, val: ast::float_ty) -> cres { - let tcx = self.infcx().tcx; if_ok!(self.infcx().simple_var_t(vid_is_expected, vid, val)); - Ok(ty::mk_mach_float(tcx, val)) + Ok(ty::mk_mach_float(val)) } } diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index db229a407b39a..52a938a34d30f 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -327,7 +327,7 @@ impl LatticeDir for Glb { impl TyLatticeDir for Glb { fn ty_bot(&self, _t: ty::t) -> cres { - Ok(ty::mk_bot(self.infcx.tcx)) + Ok(ty::mk_bot()) } } diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index c208d1d24fc62..53b7b4f19585e 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -245,12 +245,12 @@ pub impl ResolveState { let node = self.infcx.get(vid); match node.possible_types { - Some(IntType(t)) => ty::mk_mach_int(self.infcx.tcx, t), - Some(UintType(t)) => ty::mk_mach_uint(self.infcx.tcx, t), + Some(IntType(t)) => ty::mk_mach_int(t), + Some(UintType(t)) => ty::mk_mach_uint(t), None => { if self.should(force_ivar) { // As a last resort, default to int. - let ty = ty::mk_int(self.infcx.tcx); + let ty = ty::mk_int(); self.infcx.set(vid, Root(Some(IntType(ast::ty_i)), node.rank)); ty @@ -268,11 +268,11 @@ pub impl ResolveState { let node = self.infcx.get(vid); match node.possible_types { - Some(t) => ty::mk_mach_float(self.infcx.tcx, t), + Some(t) => ty::mk_mach_float(t), None => { if self.should(force_fvar) { // As a last resort, default to float. - let ty = ty::mk_float(self.infcx.tcx); + let ty = ty::mk_float(); self.infcx.set(vid, Root(Some(ast::ty_f), node.rank)); ty } else { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index f87c0dad5a993..ad4938c9869bf 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -363,11 +363,11 @@ fn check_start_fn_ty(ccx: @mut CrateCtxt, purity: ast::impure_fn, abis: abi::AbiSet::Rust(), sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty, - inputs: ~[arg(ast::by_copy, ty::mk_int(tcx)), + inputs: ~[arg(ast::by_copy, ty::mk_int()), arg(ast::by_copy, ty::mk_imm_ptr(tcx, - ty::mk_imm_ptr(tcx, ty::mk_u8(tcx)))), - arg(ast::by_copy, ty::mk_imm_ptr(tcx, ty::mk_u8(tcx)))], - output: ty::mk_int(tcx)} + ty::mk_imm_ptr(tcx, ty::mk_u8()))), + arg(ast::by_copy, ty::mk_imm_ptr(tcx, ty::mk_u8()))], + output: ty::mk_int()} }); require_same_types(tcx, None, false, start_span, start_t, se_ty, From aac73b24ae98b92489a5d175fb04c4aed24d8991 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 20:23:58 -0700 Subject: [PATCH 366/403] rustc: Comments only: change XXX to FIXME --- src/librustc/middle/trans/reachable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index d7ca346dd20ee..8d0a043a9a1f4 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -95,7 +95,7 @@ fn traverse_public_mod(cx: &ctx, mod_id: node_id, m: &_mod) { } fn traverse_public_item(cx: &ctx, item: @item) { - // XXX: it shouldn't be necessary to do this + // FIXME #6021: naming rmap shouldn't be necessary let rmap: &mut HashSet = cx.rmap; if rmap.contains(&item.id) { return; } rmap.insert(item.id); @@ -150,7 +150,7 @@ fn traverse_public_item(cx: &ctx, item: @item) { } fn traverse_ty<'a, 'b>(ty: @Ty, cx: &'b ctx<'a>, v: visit::vt<&'b ctx<'a>>) { - // XXX: it shouldn't be necessary to do this + // FIXME #6021: naming rmap shouldn't be necessary let rmap: &mut HashSet = cx.rmap; if rmap.contains(&ty.id) { return; } rmap.insert(ty.id); From 7169907e9f2b0c335b20251c7b4e2aaeb59091d8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 20:24:12 -0700 Subject: [PATCH 367/403] rustc: Remove dead code --- src/librustc/middle/ty.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index f312dbca5c3c8..b487fedf01dbb 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4164,14 +4164,6 @@ pub fn lookup_struct_field(cx: ctxt, } } -fn is_public(f: field_ty) -> bool { - // XXX: This is wrong. - match f.vis { - public | inherited => true, - private => false - } -} - fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] { do fields.map |field| { match field.node.kind { From a3e33cfb6e6eddf0e47bc98fd46075fab30978e1 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 23 Apr 2013 13:56:49 -0400 Subject: [PATCH 368/403] inline the primitive numeric operations --- src/libcore/num/f32.rs | 13 +++++++++++++ src/libcore/num/float.rs | 9 +++++++++ src/libcore/num/int-template.rs | 18 ++++++++++++++++++ src/libcore/num/uint-template.rs | 18 ++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 2e7dc98e3c56c..62004710196ec 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -301,20 +301,28 @@ impl num::One for f32 { #[cfg(notest)] impl Add for f32 { + #[inline(always)] fn add(&self, other: &f32) -> f32 { *self + *other } } + #[cfg(notest)] impl Sub for f32 { + #[inline(always)] fn sub(&self, other: &f32) -> f32 { *self - *other } } + #[cfg(notest)] impl Mul for f32 { + #[inline(always)] fn mul(&self, other: &f32) -> f32 { *self * *other } } + #[cfg(stage0,notest)] impl Div for f32 { + #[inline(always)] fn div(&self, other: &f32) -> f32 { *self / *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -322,10 +330,13 @@ impl Quot for f32 { #[inline(always)] fn quot(&self, other: &f32) -> f32 { *self / *other } } + #[cfg(stage0,notest)] impl Modulo for f32 { + #[inline(always)] fn modulo(&self, other: &f32) -> f32 { *self % *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -333,8 +344,10 @@ impl Rem for f32 { #[inline(always)] fn rem(&self, other: &f32) -> f32 { *self % *other } } + #[cfg(notest)] impl Neg for f32 { + #[inline(always)] fn neg(&self) -> f32 { -*self } } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 9cf14cf0f494b..c5c1e52a14cd7 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -455,18 +455,25 @@ impl num::Round for float { #[cfg(notest)] impl Add for float { + #[inline(always)] fn add(&self, other: &float) -> float { *self + *other } } + #[cfg(notest)] impl Sub for float { + #[inline(always)] fn sub(&self, other: &float) -> float { *self - *other } } + #[cfg(notest)] impl Mul for float { + #[inline(always)] fn mul(&self, other: &float) -> float { *self * *other } } + #[cfg(stage0,notest)] impl Div for float { + #[inline(always)] fn div(&self, other: &float) -> float { *self / *other } } #[cfg(stage1,notest)] @@ -478,6 +485,7 @@ impl Quot for float { } #[cfg(stage0,notest)] impl Modulo for float { + #[inline(always)] fn modulo(&self, other: &float) -> float { *self % *other } } #[cfg(stage1,notest)] @@ -489,6 +497,7 @@ impl Rem for float { } #[cfg(notest)] impl Neg for float { + #[inline(always)] fn neg(&self) -> float { -*self } } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 8f448994c9811..684083f53e992 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -175,20 +175,28 @@ impl num::One for T { #[cfg(notest)] impl Add for T { + #[inline(always)] fn add(&self, other: &T) -> T { *self + *other } } + #[cfg(notest)] impl Sub for T { + #[inline(always)] fn sub(&self, other: &T) -> T { *self - *other } } + #[cfg(notest)] impl Mul for T { + #[inline(always)] fn mul(&self, other: &T) -> T { *self * *other } } + #[cfg(stage0,notest)] impl Div for T { + #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -196,10 +204,13 @@ impl Quot for T { #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } } + #[cfg(stage0,notest)] impl Modulo for T { + #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -207,8 +218,10 @@ impl Rem for T { #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } } + #[cfg(notest)] impl Neg for T { + #[inline(always)] fn neg(&self) -> T { -*self } } @@ -217,26 +230,31 @@ impl BitOr for T { #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } + #[cfg(notest)] impl BitAnd for T { #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } + #[cfg(notest)] impl BitXor for T { #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } + #[cfg(notest)] impl Shl for T { #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } + #[cfg(notest)] impl Shr for T { #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } + #[cfg(notest)] impl Not for T { #[inline(always)] diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 6f3f402f92d69..4bb93907a3a50 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -140,20 +140,28 @@ impl num::One for T { #[cfg(notest)] impl Add for T { + #[inline(always)] fn add(&self, other: &T) -> T { *self + *other } } + #[cfg(notest)] impl Sub for T { + #[inline(always)] fn sub(&self, other: &T) -> T { *self - *other } } + #[cfg(notest)] impl Mul for T { + #[inline(always)] fn mul(&self, other: &T) -> T { *self * *other } } + #[cfg(stage0,notest)] impl Div for T { + #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -161,10 +169,13 @@ impl Quot for T { #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } } + #[cfg(stage0,notest)] impl Modulo for T { + #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } + #[cfg(stage1,notest)] #[cfg(stage2,notest)] #[cfg(stage3,notest)] @@ -172,8 +183,10 @@ impl Rem for T { #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } } + #[cfg(notest)] impl Neg for T { + #[inline(always)] fn neg(&self) -> T { -*self } } @@ -182,26 +195,31 @@ impl BitOr for T { #[inline(always)] fn bitor(&self, other: &T) -> T { *self | *other } } + #[cfg(notest)] impl BitAnd for T { #[inline(always)] fn bitand(&self, other: &T) -> T { *self & *other } } + #[cfg(notest)] impl BitXor for T { #[inline(always)] fn bitxor(&self, other: &T) -> T { *self ^ *other } } + #[cfg(notest)] impl Shl for T { #[inline(always)] fn shl(&self, other: &T) -> T { *self << *other } } + #[cfg(notest)] impl Shr for T { #[inline(always)] fn shr(&self, other: &T) -> T { *self >> *other } } + #[cfg(notest)] impl Not for T { #[inline(always)] From 91aeecf7e38e01a9e323683c39649e201a9f726c Mon Sep 17 00:00:00 2001 From: gareth Date: Mon, 22 Apr 2013 20:05:07 +0100 Subject: [PATCH 369/403] Fix issue #5976 - HANDLE leaks and undefined/bad behavour on windows. --- src/libcore/libc.rs | 1 + src/libcore/os.rs | 8 +++- src/libcore/run.rs | 91 +++++++++++++++++++++++++++---------- src/rt/rust_run_program.cpp | 59 ++++++++++++++++++------ 4 files changed, 119 insertions(+), 40 deletions(-) diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 945d08323b4e5..44864630f9873 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1725,6 +1725,7 @@ pub mod funcs { findFileData: HANDLE) -> BOOL; unsafe fn FindClose(findFile: HANDLE) -> BOOL; + unsafe fn CloseHandle(hObject: HANDLE) -> BOOL; unsafe fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL; } } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 0e7131a86f394..0b73eb9dca3ee 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -60,7 +60,7 @@ pub mod rustrt { unsafe fn rust_get_argv() -> **c_char; unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int; unsafe fn rust_path_exists(path: *libc::c_char) -> c_int; - unsafe fn rust_process_wait(handle: c_int) -> c_int; + unsafe fn rust_process_wait(pid: c_int) -> c_int; unsafe fn rust_set_exit_status(code: libc::intptr_t); } } @@ -356,7 +356,11 @@ pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int { #[cfg(windows)] pub fn waitpid(pid: pid_t) -> c_int { unsafe { - return rustrt::rust_process_wait(pid); + let status = rustrt::rust_process_wait(pid); + if status < 0 { + fail!(fmt!("failure in rust_process_wait: %s", last_os_error())); + } + return status; } } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index f9d7f4a229c42..4c5da132532d4 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -24,8 +24,9 @@ use task; use vec; pub mod rustrt { - use libc::{c_int, c_void, pid_t}; + use libc::{c_int, c_void}; use libc; + use run; #[abi = "cdecl"] pub extern { @@ -34,11 +35,18 @@ pub mod rustrt { dir: *libc::c_char, in_fd: c_int, out_fd: c_int, - err_fd: c_int) - -> pid_t; + err_fd: c_int) -> run::RunProgramResult; } } +pub struct RunProgramResult { + // the process id of the program, or -1 if in case of errors + pid: pid_t, + // a handle to the process - on unix this will always be NULL, but on windows it will be a + // HANDLE to the process, which will prevent the pid being re-used until the handle is closed. + handle: *(), +} + /// A value representing a child process pub trait Program { /// Returns the process id of the program @@ -100,16 +108,24 @@ pub trait Program { * The process id of the spawned process */ pub fn spawn_process(prog: &str, args: &[~str], - env: &Option<~[(~str,~str)]>, - dir: &Option<~str>, - in_fd: c_int, out_fd: c_int, err_fd: c_int) - -> pid_t { + env: &Option<~[(~str,~str)]>, + dir: &Option<~str>, + in_fd: c_int, out_fd: c_int, err_fd: c_int) -> pid_t { + + let res = spawn_process_internal(prog, args, env, dir, in_fd, out_fd, err_fd); + free_handle(res.handle); + return res.pid; +} + +fn spawn_process_internal(prog: &str, args: &[~str], + env: &Option<~[(~str,~str)]>, + dir: &Option<~str>, + in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult { unsafe { do with_argv(prog, args) |argv| { do with_envp(env) |envp| { do with_dirp(dir) |dirp| { - rustrt::rust_run_program(argv, envp, dirp, - in_fd, out_fd, err_fd) + rustrt::rust_run_program(argv, envp, dirp, in_fd, out_fd, err_fd) } } } @@ -195,6 +211,18 @@ priv unsafe fn fclose_and_null(f: &mut *libc::FILE) { } } +#[cfg(windows)] +priv fn free_handle(handle: *()) { + unsafe { + libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle)); + } +} + +#[cfg(unix)] +priv fn free_handle(_handle: *()) { + // unix has no process handle object, just a pid +} + /** * Spawns a process and waits for it to terminate * @@ -208,10 +236,13 @@ priv unsafe fn fclose_and_null(f: &mut *libc::FILE) { * The process's exit code */ pub fn run_program(prog: &str, args: &[~str]) -> int { - let pid = spawn_process(prog, args, &None, &None, - 0i32, 0i32, 0i32); - if pid == -1 as pid_t { fail!(); } - return waitpid(pid); + let res = spawn_process_internal(prog, args, &None, &None, + 0i32, 0i32, 0i32); + if res.pid == -1 as pid_t { fail!(); } + + let code = waitpid(res.pid); + free_handle(res.handle); + return code; } /** @@ -234,13 +265,13 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { let pipe_input = os::pipe(); let pipe_output = os::pipe(); let pipe_err = os::pipe(); - let pid = - spawn_process(prog, args, &None, &None, - pipe_input.in, pipe_output.out, - pipe_err.out); + let res = + spawn_process_internal(prog, args, &None, &None, + pipe_input.in, pipe_output.out, + pipe_err.out); unsafe { - if pid == -1 as pid_t { fail!(); } + if res.pid == -1 as pid_t { fail!(); } libc::close(pipe_input.in); libc::close(pipe_output.out); libc::close(pipe_err.out); @@ -248,6 +279,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { struct ProgRepr { pid: pid_t, + handle: *(), in_fd: c_int, out_file: *libc::FILE, err_file: *libc::FILE, @@ -317,6 +349,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { finish_repr(cast::transmute(&self.r)); close_repr_outputs(cast::transmute(&self.r)); } + free_handle(self.r.handle); } } @@ -343,8 +376,9 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); } } - let repr = ProgRepr { - pid: pid, + let mut repr = ProgRepr { + pid: res.pid, + handle: res.handle, in_fd: pipe_input.out, out_file: os::fdopen(pipe_output.in), err_file: os::fdopen(pipe_err.in), @@ -385,13 +419,13 @@ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { let pipe_in = os::pipe(); let pipe_out = os::pipe(); let pipe_err = os::pipe(); - let pid = spawn_process(prog, args, &None, &None, - pipe_in.in, pipe_out.out, pipe_err.out); + let res = spawn_process_internal(prog, args, &None, &None, + pipe_in.in, pipe_out.out, pipe_err.out); os::close(pipe_in.in); os::close(pipe_out.out); os::close(pipe_err.out); - if pid == -1i32 { + if res.pid == -1i32 { os::close(pipe_in.out); os::close(pipe_out.in); os::close(pipe_err.in); @@ -415,7 +449,10 @@ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { let output = readclose(pipe_out.in); ch_clone.send((1, output)); }; - let status = run::waitpid(pid); + + let status = waitpid(res.pid); + free_handle(res.handle); + let mut errs = ~""; let mut outs = ~""; let mut count = 2; @@ -563,6 +600,12 @@ mod tests { assert!(status == 1); } + #[test] + #[should_fail] + fn waitpid_non_existant_pid() { + run::waitpid(123456789); // assume that this pid doesn't exist + } + #[test] fn test_destroy_once() { let mut p = run::start_program("echo", []); diff --git a/src/rt/rust_run_program.cpp b/src/rt/rust_run_program.cpp index 0e8d1d09ee99d..cf4beed1a00c6 100644 --- a/src/rt/rust_run_program.cpp +++ b/src/rt/rust_run_program.cpp @@ -15,6 +15,11 @@ #include #endif +struct RunProgramResult { + pid_t pid; + void* handle; +}; + #if defined(__WIN32__) #include @@ -78,7 +83,7 @@ void append_arg(char *& buf, char const *arg, bool last) { } } -extern "C" CDECL int +extern "C" CDECL RunProgramResult rust_run_program(const char* argv[], void* envp, const char* dir, @@ -88,19 +93,21 @@ rust_run_program(const char* argv[], si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; + RunProgramResult result = {-1, NULL}; + HANDLE curproc = GetCurrentProcess(); HANDLE origStdin = (HANDLE)_get_osfhandle(in_fd ? in_fd : 0); if (!DuplicateHandle(curproc, origStdin, curproc, &si.hStdInput, 0, 1, DUPLICATE_SAME_ACCESS)) - return -1; + return result; HANDLE origStdout = (HANDLE)_get_osfhandle(out_fd ? out_fd : 1); if (!DuplicateHandle(curproc, origStdout, curproc, &si.hStdOutput, 0, 1, DUPLICATE_SAME_ACCESS)) - return -1; + return result; HANDLE origStderr = (HANDLE)_get_osfhandle(err_fd ? err_fd : 2); if (!DuplicateHandle(curproc, origStderr, curproc, &si.hStdError, 0, 1, DUPLICATE_SAME_ACCESS)) - return -1; + return result; size_t cmd_len = 0; for (const char** arg = argv; *arg; arg++) { @@ -124,18 +131,39 @@ rust_run_program(const char* argv[], CloseHandle(si.hStdError); free(cmd); - if (!created) return -1; - return (int)pi.hProcess; + if (!created) { + return result; + } + + // We close the thread handle because we don't care about keeping the thread id valid, + // and we aren't keeping the thread handle around to be able to close it later. We don't + // close the process handle however because we want the process id to stay valid at least + // until the calling rust code closes the process handle. + CloseHandle(pi.hThread); + result.pid = pi.dwProcessId; + result.handle = pi.hProcess; + return result; } extern "C" CDECL int -rust_process_wait(int proc) { +rust_process_wait(int pid) { + + HANDLE proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid); + if (proc == NULL) { + return -1; + } + DWORD status; while (true) { - if (GetExitCodeProcess((HANDLE)proc, &status) && - status != STILL_ACTIVE) - return (int)status; - WaitForSingleObject((HANDLE)proc, INFINITE); + if (!GetExitCodeProcess(proc, &status)) { + CloseHandle(proc); + return -1; + } + if (status != STILL_ACTIVE) { + CloseHandle(proc); + return (int) status; + } + WaitForSingleObject(proc, INFINITE); } } @@ -151,13 +179,16 @@ rust_process_wait(int proc) { extern char **environ; #endif -extern "C" CDECL int +extern "C" CDECL RunProgramResult rust_run_program(const char* argv[], void* envp, const char* dir, int in_fd, int out_fd, int err_fd) { int pid = fork(); - if (pid != 0) return pid; + if (pid != 0) { + RunProgramResult result = {pid, NULL}; + return result; + } sigset_t sset; sigemptyset(&sset); @@ -187,7 +218,7 @@ rust_run_program(const char* argv[], } extern "C" CDECL int -rust_process_wait(int proc) { +rust_process_wait(int pid) { // FIXME: stub; exists to placate linker. (#2692) return 0; } From 690120d6bc217338afc9b34cb458b086ab3f86d9 Mon Sep 17 00:00:00 2001 From: gareth Date: Mon, 22 Apr 2013 21:58:19 +0100 Subject: [PATCH 370/403] Remove os::waitpid because: - The return value meant different things on different platforms (on windows, it was the exit code, on unix it was the status information returned from waitpid). - It was undocumented. - There also exists run::waitpid, which does much the same thing but has a more consistent return value and also some documentation. --- src/libcore/os.rs | 26 -------------------------- src/libcore/run.rs | 23 +++++++++++++++++++---- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 0b73eb9dca3ee..4c660507f15a0 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -60,7 +60,6 @@ pub mod rustrt { unsafe fn rust_get_argv() -> **c_char; unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int; unsafe fn rust_path_exists(path: *libc::c_char) -> c_int; - unsafe fn rust_process_wait(pid: c_int) -> c_int; unsafe fn rust_set_exit_status(code: libc::intptr_t); } } @@ -352,31 +351,6 @@ pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int { } } - -#[cfg(windows)] -pub fn waitpid(pid: pid_t) -> c_int { - unsafe { - let status = rustrt::rust_process_wait(pid); - if status < 0 { - fail!(fmt!("failure in rust_process_wait: %s", last_os_error())); - } - return status; - } -} - -#[cfg(unix)] -pub fn waitpid(pid: pid_t) -> c_int { - unsafe { - use libc::funcs::posix01::wait::*; - let mut status = 0 as c_int; - - assert!((waitpid(pid, &mut status, 0 as c_int) != - (-1 as c_int))); - return status; - } -} - - pub struct Pipe { mut in: c_int, mut out: c_int } #[cfg(unix)] diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 4c5da132532d4..701ab1c59df5c 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -36,6 +36,7 @@ pub mod rustrt { in_fd: c_int, out_fd: c_int, err_fd: c_int) -> run::RunProgramResult; + unsafe fn rust_process_wait(pid: c_int) -> c_int; } } @@ -503,17 +504,27 @@ pub fn readclose(fd: c_int) -> ~str { } } -/// Waits for a process to exit and returns the exit code +/** + * Waits for a process to exit and returns the exit code, failing + * if there is no process with the specified id. + */ pub fn waitpid(pid: pid_t) -> int { return waitpid_os(pid); #[cfg(windows)] fn waitpid_os(pid: pid_t) -> int { - os::waitpid(pid) as int + let status = unsafe { rustrt::rust_process_wait(pid) }; + if status < 0 { + fail!(fmt!("failure in rust_process_wait: %s", os::last_os_error())); + } + return status as int; } #[cfg(unix)] fn waitpid_os(pid: pid_t) -> int { + + use libc::funcs::posix01::wait::*; + #[cfg(target_os = "linux")] #[cfg(target_os = "android")] fn WIFEXITED(status: i32) -> bool { @@ -538,7 +549,11 @@ pub fn waitpid(pid: pid_t) -> int { status >> 8i32 } - let status = os::waitpid(pid); + let mut status = 0 as c_int; + if unsafe { waitpid(pid, &mut status, 0) } == -1 { + fail!(fmt!("failure in waitpid: %s", os::last_os_error())); + } + return if WIFEXITED(status) { WEXITSTATUS(status) as int } else { @@ -584,7 +599,7 @@ mod tests { writeclose(pipe_in.out, copy expected); let actual = readclose(pipe_out.in); readclose(pipe_err.in); - os::waitpid(pid); + run::waitpid(pid); debug!(copy expected); debug!(copy actual); From ceeffa1ec662f4c1e214f3762ac116a21886078e Mon Sep 17 00:00:00 2001 From: gareth Date: Tue, 23 Apr 2013 20:02:47 +0100 Subject: [PATCH 371/403] Oops, the should_fail test needs to be ignored on windows. --- src/libcore/run.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 701ab1c59df5c..2ca0449cb59f6 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -617,6 +617,7 @@ mod tests { #[test] #[should_fail] + #[ignore(cfg(windows))] fn waitpid_non_existant_pid() { run::waitpid(123456789); // assume that this pid doesn't exist } From 62befac51fadbdd64050d84c796e3952789870a1 Mon Sep 17 00:00:00 2001 From: gareth Date: Tue, 23 Apr 2013 21:22:19 +0100 Subject: [PATCH 372/403] Cleanup some mistakes made during rebasing/merging. --- src/libcore/os.rs | 2 +- src/libcore/run.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 4c660507f15a0..fa3ca4577c6d1 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -30,7 +30,7 @@ use cast; use io; use libc; use libc::{c_char, c_void, c_int, size_t}; -use libc::{mode_t, pid_t, FILE}; +use libc::{mode_t, FILE}; use option; use option::{Some, None}; use prelude::*; diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 2ca0449cb59f6..2455954ebe128 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -18,7 +18,6 @@ use option::{Some, None}; use os; use prelude::*; use ptr; -use run; use str; use task; use vec; @@ -377,7 +376,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); } } - let mut repr = ProgRepr { + let repr = ProgRepr { pid: res.pid, handle: res.handle, in_fd: pipe_input.out, From c089a17854669925c008a5944d0490f1692dde7e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Apr 2013 11:11:50 -0400 Subject: [PATCH 373/403] Improve the unused unsafe block warning to include unsafe blocks in unsafe functions --- src/librustc/middle/borrowck/check_loans.rs | 25 ++-------- src/librustc/middle/typeck/check/mod.rs | 55 +++++++++++++++------ src/test/compile-fail/unused-unsafe.rs | 34 ++++++++++--- 3 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 6f3075717ed86..8fed8e78094c2 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -20,6 +20,7 @@ use core::prelude::*; use middle::moves; +use middle::typeck::check::PurityState; use middle::borrowck::{Loan, bckerr, BorrowckCtxt, inherent_mutability}; use middle::borrowck::{ReqMaps, root_map_key, save_and_restore_managed}; use middle::borrowck::{MoveError, MoveOk, MoveFromIllegalCmt}; @@ -41,11 +42,6 @@ use syntax::codemap::span; use syntax::print::pprust; use syntax::visit; -struct PurityState { - def: ast::node_id, - purity: ast::purity -} - struct CheckLoanCtxt { bccx: @BorrowckCtxt, req_maps: ReqMaps, @@ -85,8 +81,7 @@ pub fn check_loans(bccx: @BorrowckCtxt, bccx: bccx, req_maps: req_maps, reported: HashSet::new(), - declared_purity: @mut PurityState { purity: ast::impure_fn, - def: 0 }, + declared_purity: @mut PurityState::function(ast::impure_fn, 0), fn_args: @mut @~[] }; let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr, @@ -658,9 +653,7 @@ fn check_loans_in_fn(fk: &visit::fn_kind, debug!("purity on entry=%?", copy self.declared_purity); do save_and_restore_managed(self.declared_purity) { do save_and_restore_managed(self.fn_args) { - self.declared_purity = @mut PurityState { - purity: declared_purity, def: src - }; + self.declared_purity = @mut PurityState::function(declared_purity, src); match *fk { visit::fk_anon(*) | @@ -810,17 +803,7 @@ fn check_loans_in_block(blk: &ast::blk, do save_and_restore_managed(self.declared_purity) { self.check_for_conflicting_loans(blk.node.id); - match blk.node.rules { - ast::default_blk => { - } - ast::unsafe_blk => { - *self.declared_purity = PurityState { - purity: ast::unsafe_fn, - def: blk.node.id, - }; - } - } - + *self.declared_purity = self.declared_purity.recurse(blk); visit::visit_block(blk, self, vt); } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index dd147d9e46887..536de78c752f9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -115,6 +115,7 @@ use core::result::{Result, Ok, Err}; use core::result; use core::str; use core::vec; +use core::util::replace; use std::list::Nil; use syntax::abi::AbiSet; use syntax::ast::{provided, required}; @@ -179,9 +180,36 @@ pub enum FnKind { Vanilla } -struct PurityState { +pub struct PurityState { + def: ast::node_id, purity: ast::purity, - from: ast::node_id, + priv from_fn: bool +} + +pub impl PurityState { + pub fn function(purity: ast::purity, def: ast::node_id) -> PurityState { + PurityState { def: def, purity: purity, from_fn: true } + } + + pub fn recurse(&mut self, blk: &ast::blk) -> PurityState { + match self.purity { + // If this unsafe, then if the outer function was already marked as + // unsafe we shouldn't attribute the unsafe'ness to the block. This + // way the block can be warned about instead of ignoring this + // extraneous block (functions are never warned about). + ast::unsafe_fn if self.from_fn => *self, + + purity => { + let (purity, def) = match blk.node.rules { + ast::unsafe_blk => (ast::unsafe_fn, blk.node.id), + ast::default_blk => (purity, self.def), + }; + PurityState{ def: def, + purity: purity, + from_fn: false } + } + } + } } pub struct FnCtxt { @@ -243,7 +271,7 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt, @mut FnCtxt { ret_ty: rty, indirect_ret_ty: None, - ps: PurityState { purity: ast::pure_fn, from: 0 }, + ps: PurityState::function(ast::pure_fn, 0), region_lb: region_bnd, in_scope_regions: @Nil, fn_kind: Vanilla, @@ -348,7 +376,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, @mut FnCtxt { ret_ty: ret_ty, indirect_ret_ty: indirect_ret_ty, - ps: PurityState { purity: purity, from: id }, + ps: PurityState::function(purity, id), region_lb: body.node.id, in_scope_regions: isr, fn_kind: fn_kind, @@ -876,8 +904,8 @@ pub impl FnCtxt { match self.ps.purity { ast::unsafe_fn => { // ok, but flag that we used the source of unsafeness - debug!("flagging %? as a used unsafe source", self.ps.from); - self.tcx().used_unsafe.insert(self.ps.from); + debug!("flagging %? as a used unsafe source", self.ps); + self.tcx().used_unsafe.insert(self.ps.def); } _ => { self.ccx.tcx.sess.span_err( @@ -1689,7 +1717,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(expr.id, fty); let (inherited_purity, id) = - ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.from), + ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.def), (purity, expr.id), sigil); @@ -2929,16 +2957,11 @@ pub fn check_block(fcx0: @mut FnCtxt, blk: &ast::blk) { check_block_with_expected(fcx0, blk, None) } -pub fn check_block_with_expected(fcx0: @mut FnCtxt, +pub fn check_block_with_expected(fcx: @mut FnCtxt, blk: &ast::blk, expected: Option) { - let fcx = match blk.node.rules { - ast::unsafe_blk => @mut FnCtxt { - ps: PurityState { purity: ast::unsafe_fn, from: blk.node.id }, - .. copy *fcx0 - }, - ast::default_blk => fcx0 - }; + let prev = replace(&mut fcx.ps, fcx.ps.recurse(blk)); + do fcx.with_region_lb(blk.node.id) { let mut warned = false; let mut last_was_bot = false; @@ -2990,6 +3013,8 @@ pub fn check_block_with_expected(fcx0: @mut FnCtxt, } }; } + + fcx.ps = prev; } pub fn check_const(ccx: @mut CrateCtxt, diff --git a/src/test/compile-fail/unused-unsafe.rs b/src/test/compile-fail/unused-unsafe.rs index 7d9044f5d8921..9552badb57f67 100644 --- a/src/test/compile-fail/unused-unsafe.rs +++ b/src/test/compile-fail/unused-unsafe.rs @@ -12,30 +12,50 @@ #[deny(unused_unsafe)]; -use core::libc; +extern mod foo { + fn bar(); +} fn callback(_f: &fn() -> T) -> T { fail!() } +unsafe fn unsf() {} fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block -unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary `unsafe` block -fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block +fn bad6() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { // don't put the warning here + unsf() + } + } +} +unsafe fn bad7() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} -unsafe fn good0() { libc::exit(1) } -fn good1() { unsafe { libc::exit(1) } } +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } fn good2() { /* bug uncovered when implementing warning about unused unsafe blocks. Be sure that when purity is inherited that the source of the unsafe-ness is tracked correctly */ unsafe { - unsafe fn what() -> ~[~str] { libc::exit(2) } + unsafe fn what() -> ~[~str] { fail!() } do callback { what(); } } } +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } #[allow(unused_unsafe)] fn allowed() { unsafe {} } -fn main() { } +fn main() {} From 4c08a8d6c31f55bfeed0ef0c2bf8b91f90415cfe Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Apr 2013 19:33:33 -0400 Subject: [PATCH 374/403] Removing more unnecessary unsafe blocks throughout --- src/libcore/gc.rs | 102 ++++++++++++++-------------- src/libcore/pipes.rs | 4 +- src/libcore/rt/sched/local_sched.rs | 6 +- src/libcore/rt/uvll.rs | 4 +- src/libcore/unstable.rs | 20 +++--- src/libcore/unstable/weak_task.rs | 4 +- src/librustc/middle/trans/base.rs | 6 +- src/libstd/arc.rs | 34 ++++------ 8 files changed, 83 insertions(+), 97 deletions(-) diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 71d9ab439f34f..a6bae3c76631c 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -231,66 +231,64 @@ unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) { // the stack. let mut reached_sentinel = ptr::is_null(sentinel); for stackwalk::walk_stack |frame| { - unsafe { - let pc = last_ret; - let Segment {segment: next_segment, boundary: boundary} = - find_segment_for_frame(frame.fp, segment); - segment = next_segment; - // Each stack segment is bounded by a morestack frame. The - // morestack frame includes two return addresses, one for - // morestack itself, at the normal offset from the frame - // pointer, and then a second return address for the - // function prologue (which called morestack after - // determining that it had hit the end of the stack). - // Since morestack itself takes two parameters, the offset - // for this second return address is 3 greater than the - // return address for morestack. - let ret_offset = if boundary { 4 } else { 1 }; - last_ret = *ptr::offset(frame.fp, ret_offset) as *Word; - - if ptr::is_null(pc) { - loop; - } + let pc = last_ret; + let Segment {segment: next_segment, boundary: boundary} = + find_segment_for_frame(frame.fp, segment); + segment = next_segment; + // Each stack segment is bounded by a morestack frame. The + // morestack frame includes two return addresses, one for + // morestack itself, at the normal offset from the frame + // pointer, and then a second return address for the + // function prologue (which called morestack after + // determining that it had hit the end of the stack). + // Since morestack itself takes two parameters, the offset + // for this second return address is 3 greater than the + // return address for morestack. + let ret_offset = if boundary { 4 } else { 1 }; + last_ret = *ptr::offset(frame.fp, ret_offset) as *Word; + + if ptr::is_null(pc) { + loop; + } - let mut delay_reached_sentinel = reached_sentinel; - let sp = is_safe_point(pc); - match sp { - Some(sp_info) => { - for walk_safe_point(frame.fp, sp_info) |root, tydesc| { - // Skip roots until we see the sentinel. - if !reached_sentinel { - if root == sentinel { - delay_reached_sentinel = true; - } - loop; + let mut delay_reached_sentinel = reached_sentinel; + let sp = is_safe_point(pc); + match sp { + Some(sp_info) => { + for walk_safe_point(frame.fp, sp_info) |root, tydesc| { + // Skip roots until we see the sentinel. + if !reached_sentinel { + if root == sentinel { + delay_reached_sentinel = true; } + loop; + } - // Skip null pointers, which can occur when a - // unique pointer has already been freed. - if ptr::is_null(*root) { - loop; - } + // Skip null pointers, which can occur when a + // unique pointer has already been freed. + if ptr::is_null(*root) { + loop; + } - if ptr::is_null(tydesc) { - // Root is a generic box. - let refcount = **root; - if mem | task_local_heap != 0 && refcount != -1 { - if !visitor(root, tydesc) { return; } - } else if mem | exchange_heap != 0 && refcount == -1 { - if !visitor(root, tydesc) { return; } - } - } else { - // Root is a non-immediate. - if mem | stack != 0 { - if !visitor(root, tydesc) { return; } - } + if ptr::is_null(tydesc) { + // Root is a generic box. + let refcount = **root; + if mem | task_local_heap != 0 && refcount != -1 { + if !visitor(root, tydesc) { return; } + } else if mem | exchange_heap != 0 && refcount == -1 { + if !visitor(root, tydesc) { return; } + } + } else { + // Root is a non-immediate. + if mem | stack != 0 { + if !visitor(root, tydesc) { return; } } } - } - None => () } - reached_sentinel = delay_reached_sentinel; + } + None => () } + reached_sentinel = delay_reached_sentinel; } } diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 36cfdbf5617aa..2ec3afca61269 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -156,9 +156,7 @@ pub impl PacketHeader { unsafe fn unblock(&self) { let old_task = swap_task(&mut self.blocked_task, ptr::null()); if !old_task.is_null() { - unsafe { - rustrt::rust_task_deref(old_task) - } + rustrt::rust_task_deref(old_task) } match swap_state_acq(&mut self.state, Empty) { Empty | Blocked => (), diff --git a/src/libcore/rt/sched/local_sched.rs b/src/libcore/rt/sched/local_sched.rs index 77fbadf0bb7bb..2d1e06163beb8 100644 --- a/src/libcore/rt/sched/local_sched.rs +++ b/src/libcore/rt/sched/local_sched.rs @@ -80,10 +80,8 @@ pub unsafe fn unsafe_borrow() -> &mut Scheduler { } pub unsafe fn unsafe_borrow_io() -> &mut IoFactoryObject { - unsafe { - let sched = unsafe_borrow(); - return sched.event_loop.io().unwrap(); - } + let sched = unsafe_borrow(); + return sched.event_loop.io().unwrap(); } fn tls_key() -> tls::Key { diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs index 640a69743ba6a..b7eff217ff8c6 100644 --- a/src/libcore/rt/uvll.rs +++ b/src/libcore/rt/uvll.rs @@ -98,7 +98,7 @@ pub enum uv_req_type { pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void { assert!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX); - let size = unsafe { rust_uv_handle_size(handle as uint) }; + let size = rust_uv_handle_size(handle as uint); let p = malloc(size); assert!(p.is_not_null()); return p; @@ -110,7 +110,7 @@ pub unsafe fn free_handle(v: *c_void) { pub unsafe fn malloc_req(req: uv_req_type) -> *c_void { assert!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX); - let size = unsafe { rust_uv_req_size(req as uint) }; + let size = rust_uv_req_size(req as uint); let p = malloc(size); assert!(p.is_not_null()); return p; diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index a6bb93c20cd0b..4a69de26f6b13 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -262,18 +262,16 @@ pub impl Exclusive { // the exclusive. Supporting that is a work in progress. #[inline(always)] unsafe fn with(&self, f: &fn(x: &mut T) -> U) -> U { - unsafe { - let rec = get_shared_mutable_state(&self.x); - do (*rec).lock.lock { - if (*rec).failed { - fail!( - ~"Poisoned exclusive - another task failed inside!"); - } - (*rec).failed = true; - let result = f(&mut (*rec).data); - (*rec).failed = false; - result + let rec = get_shared_mutable_state(&self.x); + do (*rec).lock.lock { + if (*rec).failed { + fail!( + ~"Poisoned exclusive - another task failed inside!"); } + (*rec).failed = true; + let result = f(&mut (*rec).data); + (*rec).failed = false; + result } } diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs index 4e2174fd5d24c..7a30bb92111b1 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -43,11 +43,11 @@ pub unsafe fn weaken_task(f: &fn(Port)) { let task = get_task_id(); // Expect the weak task service to be alive assert!(service.try_send(RegisterWeakTask(task, shutdown_chan))); - unsafe { rust_dec_kernel_live_count(); } + rust_dec_kernel_live_count(); do (|| { f(shutdown_port.take()) }).finally || { - unsafe { rust_inc_kernel_live_count(); } + rust_inc_kernel_live_count(); // Service my have already exited service.send(UnregisterWeakTask(task)); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b86e9a512932a..68405f4fc5fe2 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2628,13 +2628,11 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { let class_ty = ty::lookup_item_type(tcx, parent_id).ty; // This code shouldn't be reached if the class is generic assert!(!ty::type_has_params(class_ty)); - let lldty = unsafe { - T_fn(~[ + let lldty = T_fn(~[ T_ptr(T_i8()), T_ptr(type_of(ccx, class_ty)) ], - T_nil()) - }; + T_nil()); let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None); /* Make the declaration for the dtor */ diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 8abe0262314b5..33aa6171de4b7 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -177,15 +177,13 @@ pub impl MutexARC { */ #[inline(always)] unsafe fn access(&self, blk: &fn(x: &mut T) -> U) -> U { - unsafe { - let state = get_shared_mutable_state(&self.x); - // Borrowck would complain about this if the function were - // not already unsafe. See borrow_rwlock, far below. - do (&(*state).lock).lock { - check_poison(true, (*state).failed); - let _z = PoisonOnFail(&mut (*state).failed); - blk(&mut (*state).data) - } + let state = get_shared_mutable_state(&self.x); + // Borrowck would complain about this if the function were + // not already unsafe. See borrow_rwlock, far below. + do (&(*state).lock).lock { + check_poison(true, (*state).failed); + let _z = PoisonOnFail(&mut (*state).failed); + blk(&mut (*state).data) } } @@ -195,16 +193,14 @@ pub impl MutexARC { &self, blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U { - unsafe { - let state = get_shared_mutable_state(&self.x); - do (&(*state).lock).lock_cond |cond| { - check_poison(true, (*state).failed); - let _z = PoisonOnFail(&mut (*state).failed); - blk(&mut (*state).data, - &Condvar {is_mutex: true, - failed: &mut (*state).failed, - cond: cond }) - } + let state = get_shared_mutable_state(&self.x); + do (&(*state).lock).lock_cond |cond| { + check_poison(true, (*state).failed); + let _z = PoisonOnFail(&mut (*state).failed); + blk(&mut (*state).data, + &Condvar {is_mutex: true, + failed: &mut (*state).failed, + cond: cond }) } } } From 0c2ab662b71377efd2da7dced4f56e75cb68f540 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Apr 2013 19:38:49 -0400 Subject: [PATCH 375/403] Fixing some various warnings about unused imports --- src/libcore/rt/uvio.rs | 3 ++- src/libcore/str/ascii.rs | 1 + src/librustc/back/link.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/ty.rs | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 7bf1792baf49b..abdd8d6619a8a 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -11,7 +11,7 @@ use option::*; use result::*; -use super::io::net::ip::{IpAddr, Ipv4}; // n.b. Ipv4 is used only in tests +use super::io::net::ip::IpAddr; use super::uv::*; use super::rtio::*; use ops::Drop; @@ -19,6 +19,7 @@ use cell::{Cell, empty_cell}; use cast::transmute; use super::sched::{Scheduler, local_sched}; +#[cfg(test)] use super::io::net::ip::Ipv4; #[cfg(test)] use super::sched::Task; #[cfg(test)] use unstable::run_in_bare_thread; #[cfg(test)] use uint; diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 339274ab47e4f..f6c0176eafc63 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -196,6 +196,7 @@ impl ToStrConsume for ~[Ascii] { } } +#[cfg(test)] mod tests { use super::*; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 99ea0bc0c865e..8befa4c82031a 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -26,7 +26,7 @@ use core::char; use core::hash::Streaming; use core::hash; use core::io::WriterUtil; -use core::libc::{c_int, c_uint, c_char}; +use core::libc::{c_int, c_uint}; use core::os::consts::{macos, freebsd, linux, android, win32}; use core::os; use core::ptr; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 68405f4fc5fe2..da87568b3d0c0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -70,7 +70,7 @@ use core::hash; use core::hashmap::{HashMap, HashSet}; use core::int; use core::io; -use core::libc::{c_uint, c_ulonglong}; +use core::libc::c_uint; use core::uint; use std::time; use syntax::ast::ident; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b487fedf01dbb..47c9c3bdb6be4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -514,7 +514,7 @@ pub struct substs { } mod primitives { - use super::{sty, t_box_}; + use super::t_box_; use syntax::ast; From aef249056e55ad2bf3d658609c440fad4a9255eb Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 23 Apr 2013 17:59:49 +1000 Subject: [PATCH 376/403] Implement Signed and Unsigned traits and remove related predicate functions --- src/libcore/core.rc | 2 +- src/libcore/num/f32.rs | 114 +++++++++++++++++--------- src/libcore/num/f64.rs | 112 +++++++++++++++++--------- src/libcore/num/float.rs | 134 +++++++++++++++++-------------- src/libcore/num/int-template.rs | 68 +++++++++++++--- src/libcore/num/num.rs | 11 +++ src/libcore/num/uint-template.rs | 12 +-- src/libcore/prelude.rs | 2 +- src/libstd/num/bigint.rs | 33 ++++++-- src/test/run-pass/block-arg.rs | 18 ++--- 10 files changed, 328 insertions(+), 178 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index b0a3939db73a0..123fbcca9d536 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -105,7 +105,7 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use iter::{ExtendedMutableIter}; -pub use num::{Num, NumCast}; +pub use num::{Num, Signed, Unsigned, NumCast}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 62004710196ec..5d663844e5b79 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -11,6 +11,7 @@ //! Operations and constants for `f32` use num::strconv; +use num::Signed; use num; use option::Option; use from_str; @@ -163,38 +164,6 @@ pub fn gt(x: f32, y: f32) -> bool { return x > y; } // FIXME (#1999): replace the predicates below with llvm intrinsics or // calls to the libmath macros in the rust runtime for performance. -/// Returns true if `x` is a positive number, including +0.0f320 and +Infinity -#[inline(always)] -pub fn is_positive(x: f32) -> bool { - x > 0.0f32 || (1.0f32/x) == infinity -} - -/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity -#[inline(always)] -pub fn is_negative(x: f32) -> bool { - x < 0.0f32 || (1.0f32/x) == neg_infinity -} - -/** - * Returns true if `x` is a negative number, including -0.0f320 and -Infinity - * - * This is the same as `f32::is_negative`. - */ -#[inline(always)] -pub fn is_nonpositive(x: f32) -> bool { - return x < 0.0f32 || (1.0f32/x) == neg_infinity; -} - -/** - * Returns true if `x` is a positive number, including +0.0f320 and +Infinity - * - * This is the same as `f32::is_positive`.) - */ -#[inline(always)] -pub fn is_nonnegative(x: f32) -> bool { - return x > 0.0f32 || (1.0f32/x) == infinity; -} - /// Returns true if `x` is a zero number (positive or negative zero) #[inline(always)] pub fn is_zero(x: f32) -> bool { @@ -259,11 +228,6 @@ pub mod consts { pub static ln_10: f32 = 2.30258509299404568401799145468436421_f32; } -#[inline(always)] -pub fn signbit(x: f32) -> int { - if is_negative(x) { return 1; } else { return 0; } -} - #[inline(always)] pub fn logarithm(n: f32, b: f32) -> f32 { return log2(n) / log2(b); @@ -351,15 +315,41 @@ impl Neg for f32 { fn neg(&self) -> f32 { -*self } } +impl Signed for f32 { + /// Computes the absolute value. Returns `NaN` if the number is `NaN`. + #[inline(always)] + fn abs(&self) -> f32 { abs(*self) } + + /** + * # Returns + * + * - `1.0` if the number is positive, `+0.0` or `infinity` + * - `-1.0` if the number is negative, `-0.0` or `neg_infinity` + * - `NaN` if the number is `NaN` + */ + #[inline(always)] + fn signum(&self) -> f32 { + if is_NaN(*self) { NaN } else { copysign(1.0, *self) } + } + + /// Returns `true` if the number is positive, including `+0.0` and `infinity` + #[inline(always)] + fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } + + /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` + #[inline(always)] + fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } +} + impl num::Round for f32 { #[inline(always)] fn round(&self, mode: num::RoundMode) -> f32 { match mode { num::RoundDown => floor(*self), num::RoundUp => ceil(*self), - num::RoundToZero if is_negative(*self) => ceil(*self), + num::RoundToZero if self.is_negative() => ceil(*self), num::RoundToZero => floor(*self), - num::RoundFromZero if is_negative(*self) => floor(*self), + num::RoundFromZero if self.is_negative() => floor(*self), num::RoundFromZero => ceil(*self) } } @@ -370,7 +360,7 @@ impl num::Round for f32 { fn ceil(&self) -> f32 { ceil(*self) } #[inline(always)] fn fract(&self) -> f32 { - if is_negative(*self) { + if self.is_negative() { (*self) - ceil(*self) } else { (*self) - floor(*self) @@ -595,6 +585,50 @@ impl num::FromStrRadix for f32 { } } +#[cfg(test)] +mod tests { + use f32::*; + + #[test] + pub fn test_signed() { + assert_eq!(infinity.abs(), infinity); + assert_eq!(1f32.abs(), 1f32); + assert_eq!(0f32.abs(), 0f32); + assert_eq!((-0f32).abs(), 0f32); + assert_eq!((-1f32).abs(), 1f32); + assert_eq!(neg_infinity.abs(), infinity); + assert_eq!((1f32/neg_infinity).abs(), 0f32); + assert!(is_NaN(NaN.abs())); + + assert_eq!(infinity.signum(), 1f32); + assert_eq!(1f32.signum(), 1f32); + assert_eq!(0f32.signum(), 1f32); + assert_eq!((-0f32).signum(), -1f32); + assert_eq!((-1f32).signum(), -1f32); + assert_eq!(neg_infinity.signum(), -1f32); + assert_eq!((1f32/neg_infinity).signum(), -1f32); + assert!(is_NaN(NaN.signum())); + + assert!(infinity.is_positive()); + assert!(1f32.is_positive()); + assert!(0f32.is_positive()); + assert!(!(-0f32).is_positive()); + assert!(!(-1f32).is_positive()); + assert!(!neg_infinity.is_positive()); + assert!(!(1f32/neg_infinity).is_positive()); + assert!(!NaN.is_positive()); + + assert!(!infinity.is_negative()); + assert!(!1f32.is_negative()); + assert!(!0f32.is_negative()); + assert!((-0f32).is_negative()); + assert!((-1f32).is_negative()); + assert!(neg_infinity.is_negative()); + assert!((1f32/neg_infinity).is_negative()); + assert!(!NaN.is_negative()); + } +} + // // Local Variables: // mode: rust diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 4762c395a2561..48f23fe8ba946 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -11,6 +11,7 @@ //! Operations and constants for `f64` use num::strconv; +use num::Signed; use num; use option::Option; use to_str; @@ -183,36 +184,6 @@ pub fn ge(x: f64, y: f64) -> bool { return x >= y; } #[inline(always)] pub fn gt(x: f64, y: f64) -> bool { return x > y; } -/// Returns true if `x` is a positive number, including +0.0f640 and +Infinity -#[inline(always)] -pub fn is_positive(x: f64) -> bool - { return x > 0.0f64 || (1.0f64/x) == infinity; } - -/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity -#[inline(always)] -pub fn is_negative(x: f64) -> bool - { return x < 0.0f64 || (1.0f64/x) == neg_infinity; } - -/** - * Returns true if `x` is a negative number, including -0.0f640 and -Infinity - * - * This is the same as `f64::is_negative`. - */ -#[inline(always)] -pub fn is_nonpositive(x: f64) -> bool { - return x < 0.0f64 || (1.0f64/x) == neg_infinity; -} - -/** - * Returns true if `x` is a positive number, including +0.0f640 and +Infinity - * - * This is the same as `f64::positive`. - */ -#[inline(always)] -pub fn is_nonnegative(x: f64) -> bool { - return x > 0.0f64 || (1.0f64/x) == infinity; -} - /// Returns true if `x` is a zero number (positive or negative zero) #[inline(always)] pub fn is_zero(x: f64) -> bool { @@ -278,11 +249,6 @@ pub mod consts { pub static ln_10: f64 = 2.30258509299404568401799145468436421_f64; } -#[inline(always)] -pub fn signbit(x: f64) -> int { - if is_negative(x) { return 1; } else { return 0; } -} - #[inline(always)] pub fn logarithm(n: f64, b: f64) -> f64 { return log2(n) / log2(b); @@ -357,15 +323,41 @@ impl Neg for f64 { fn neg(&self) -> f64 { -*self } } +impl Signed for f64 { + /// Computes the absolute value. Returns `NaN` if the number is `NaN`. + #[inline(always)] + fn abs(&self) -> f64 { abs(*self) } + + /** + * # Returns + * + * - `1.0` if the number is positive, `+0.0` or `infinity` + * - `-1.0` if the number is negative, `-0.0` or `neg_infinity` + * - `NaN` if the number is `NaN` + */ + #[inline(always)] + fn signum(&self) -> f64 { + if is_NaN(*self) { NaN } else { copysign(1.0, *self) } + } + + /// Returns `true` if the number is positive, including `+0.0` and `infinity` + #[inline(always)] + fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } + + /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` + #[inline(always)] + fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } +} + impl num::Round for f64 { #[inline(always)] fn round(&self, mode: num::RoundMode) -> f64 { match mode { num::RoundDown => floor(*self), num::RoundUp => ceil(*self), - num::RoundToZero if is_negative(*self) => ceil(*self), + num::RoundToZero if self.is_negative() => ceil(*self), num::RoundToZero => floor(*self), - num::RoundFromZero if is_negative(*self) => floor(*self), + num::RoundFromZero if self.is_negative() => floor(*self), num::RoundFromZero => ceil(*self) } } @@ -376,7 +368,7 @@ impl num::Round for f64 { fn ceil(&self) -> f64 { ceil(*self) } #[inline(always)] fn fract(&self) -> f64 { - if is_negative(*self) { + if self.is_negative() { (*self) - ceil(*self) } else { (*self) - floor(*self) @@ -601,6 +593,50 @@ impl num::FromStrRadix for f64 { } } +#[cfg(test)] +mod tests { + use f64::*; + + #[test] + pub fn test_signed() { + assert_eq!(infinity.abs(), infinity); + assert_eq!(1f64.abs(), 1f64); + assert_eq!(0f64.abs(), 0f64); + assert_eq!((-0f64).abs(), 0f64); + assert_eq!((-1f64).abs(), 1f64); + assert_eq!(neg_infinity.abs(), infinity); + assert_eq!((1f64/neg_infinity).abs(), 0f64); + assert!(is_NaN(NaN.abs())); + + assert_eq!(infinity.signum(), 1f64); + assert_eq!(1f64.signum(), 1f64); + assert_eq!(0f64.signum(), 1f64); + assert_eq!((-0f64).signum(), -1f64); + assert_eq!((-1f64).signum(), -1f64); + assert_eq!(neg_infinity.signum(), -1f64); + assert_eq!((1f64/neg_infinity).signum(), -1f64); + assert!(is_NaN(NaN.signum())); + + assert!(infinity.is_positive()); + assert!(1f64.is_positive()); + assert!(0f64.is_positive()); + assert!(!(-0f64).is_positive()); + assert!(!(-1f64).is_positive()); + assert!(!neg_infinity.is_positive()); + assert!(!(1f64/neg_infinity).is_positive()); + assert!(!NaN.is_positive()); + + assert!(!infinity.is_negative()); + assert!(!1f64.is_negative()); + assert!(!0f64.is_negative()); + assert!((-0f64).is_negative()); + assert!((-1f64).is_negative()); + assert!(neg_infinity.is_negative()); + assert!((1f64/neg_infinity).is_negative()); + assert!(!NaN.is_negative()); + } +} + // // Local Variables: // mode: rust diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index c5c1e52a14cd7..036d295943c7b 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -22,6 +22,7 @@ use f64; use num::strconv; +use num::Signed; use num; use option::Option; use to_str; @@ -42,7 +43,6 @@ pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub}; pub use f64::{mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp}; pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix}; pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc}; -pub use f64::signbit; pub use f64::{j0, j1, jn, y0, y1, yn}; pub static NaN: float = 0.0/0.0; @@ -348,14 +348,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float { return total; } -#[inline(always)] -pub fn is_positive(x: float) -> bool { f64::is_positive(x as f64) } -#[inline(always)] -pub fn is_negative(x: float) -> bool { f64::is_negative(x as f64) } -#[inline(always)] -pub fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) } -#[inline(always)] -pub fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) } #[inline(always)] pub fn is_zero(x: float) -> bool { f64::is_zero(x as f64) } #[inline(always)] @@ -428,11 +420,11 @@ impl num::Round for float { => f64::floor(*self as f64) as float, num::RoundUp => f64::ceil(*self as f64) as float, - num::RoundToZero if is_negative(*self) + num::RoundToZero if self.is_negative() => f64::ceil(*self as f64) as float, num::RoundToZero => f64::floor(*self as f64) as float, - num::RoundFromZero if is_negative(*self) + num::RoundFromZero if self.is_negative() => f64::floor(*self as f64) as float, num::RoundFromZero => f64::ceil(*self as f64) as float @@ -445,7 +437,7 @@ impl num::Round for float { fn ceil(&self) -> float { f64::ceil(*self as f64) as float} #[inline(always)] fn fract(&self) -> float { - if is_negative(*self) { + if self.is_negative() { (*self) - (f64::ceil(*self as f64) as float) } else { (*self) - (f64::floor(*self as f64) as float) @@ -501,10 +493,76 @@ impl Neg for float { fn neg(&self) -> float { -*self } } +impl Signed for float { + /// Computes the absolute value. Returns `NaN` if the number is `NaN`. + #[inline(always)] + fn abs(&self) -> float { abs(*self) } + + /** + * # Returns + * + * - `1.0` if the number is positive, `+0.0` or `infinity` + * - `-1.0` if the number is negative, `-0.0` or `neg_infinity` + * - `NaN` if the number is NaN + */ + #[inline(always)] + fn signum(&self) -> float { + if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float } + } + + /// Returns `true` if the number is positive, including `+0.0` and `infinity` + #[inline(always)] + fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } + + /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` + #[inline(always)] + fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } +} + #[cfg(test)] mod tests { use super::*; use prelude::*; + + #[test] + pub fn test_signed() { + assert_eq!(infinity.abs(), infinity); + assert_eq!(1f.abs(), 1f); + assert_eq!(0f.abs(), 0f); + assert_eq!((-0f).abs(), 0f); + assert_eq!((-1f).abs(), 1f); + assert_eq!(neg_infinity.abs(), infinity); + assert_eq!((1f/neg_infinity).abs(), 0f); + assert!(is_NaN(NaN.abs())); + + assert_eq!(infinity.signum(), 1f); + assert_eq!(1f.signum(), 1f); + assert_eq!(0f.signum(), 1f); + assert_eq!((-0f).signum(), -1f); + assert_eq!((-1f).signum(), -1f); + assert_eq!(neg_infinity.signum(), -1f); + assert_eq!((1f/neg_infinity).signum(), -1f); + assert!(is_NaN(NaN.signum())); + + assert!(infinity.is_positive()); + assert!(1f.is_positive()); + assert!(0f.is_positive()); + assert!(!(-0f).is_positive()); + assert!(!(-1f).is_positive()); + assert!(!neg_infinity.is_positive()); + assert!(!(1f/neg_infinity).is_positive()); + assert!(!NaN.is_positive()); + + assert!(!infinity.is_negative()); + assert!(!1f.is_negative()); + assert!(!0f.is_negative()); + assert!((-0f).is_negative()); + assert!((-1f).is_negative()); + assert!(neg_infinity.is_negative()); + assert!((1f/neg_infinity).is_negative()); + assert!(!NaN.is_negative()); + } + #[test] pub fn test_to_str_exact_do_decimal() { let s = to_str_exact(5.0, 4u); @@ -538,11 +596,11 @@ mod tests { } // note: -0 == 0, hence these slightly more complex tests match from_str(~"-0") { - Some(v) if is_zero(v) => assert!(is_negative(v)), + Some(v) if is_zero(v) => assert!(v.is_negative()), _ => fail!() } match from_str(~"0") { - Some(v) if is_zero(v) => assert!(is_positive(v)), + Some(v) if is_zero(v) => assert!(v.is_positive()), _ => fail!() } @@ -585,11 +643,11 @@ mod tests { } // note: -0 == 0, hence these slightly more complex tests match from_str_hex(~"-0") { - Some(v) if is_zero(v) => assert!(is_negative(v)), + Some(v) if is_zero(v) => assert!(v.is_negative()), _ => fail!() } match from_str_hex(~"0") { - Some(v) if is_zero(v) => assert!(is_positive(v)), + Some(v) if is_zero(v) => assert!(v.is_positive()), _ => fail!() } assert_eq!(from_str_hex(~"e"), Some(14.)); @@ -641,50 +699,6 @@ mod tests { assert_eq!(from_str_radix(~"1000.001", 2u), Some(8.125)); } - #[test] - pub fn test_positive() { - assert!(is_positive(infinity)); - assert!(is_positive(1.)); - assert!(is_positive(0.)); - assert!(!is_positive(-1.)); - assert!(!is_positive(neg_infinity)); - assert!(!is_positive(1./neg_infinity)); - assert!(!is_positive(NaN)); - } - - #[test] - pub fn test_negative() { - assert!(!is_negative(infinity)); - assert!(!is_negative(1.)); - assert!(!is_negative(0.)); - assert!(is_negative(-1.)); - assert!(is_negative(neg_infinity)); - assert!(is_negative(1./neg_infinity)); - assert!(!is_negative(NaN)); - } - - #[test] - pub fn test_nonpositive() { - assert!(!is_nonpositive(infinity)); - assert!(!is_nonpositive(1.)); - assert!(!is_nonpositive(0.)); - assert!(is_nonpositive(-1.)); - assert!(is_nonpositive(neg_infinity)); - assert!(is_nonpositive(1./neg_infinity)); - assert!(!is_nonpositive(NaN)); - } - - #[test] - pub fn test_nonnegative() { - assert!(is_nonnegative(infinity)); - assert!(is_nonnegative(1.)); - assert!(is_nonnegative(0.)); - assert!(!is_nonnegative(-1.)); - assert!(!is_nonnegative(neg_infinity)); - assert!(!is_nonnegative(1./neg_infinity)); - assert!(!is_nonnegative(NaN)); - } - #[test] pub fn test_to_str_inf() { assert_eq!(to_str_digits(infinity, 10u), ~"inf"); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 684083f53e992..d65cbb4cf9275 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -14,6 +14,7 @@ use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; +use num::Signed; use num; use prelude::*; @@ -70,15 +71,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y } #[inline(always)] pub fn gt(x: T, y: T) -> bool { x > y } -#[inline(always)] -pub fn is_positive(x: T) -> bool { x > 0 as T } -#[inline(always)] -pub fn is_negative(x: T) -> bool { x < 0 as T } -#[inline(always)] -pub fn is_nonpositive(x: T) -> bool { x <= 0 as T } -#[inline(always)] -pub fn is_nonnegative(x: T) -> bool { x >= 0 as T } - /** * Iterate over the range [`lo`..`hi`) * @@ -139,9 +131,7 @@ pub fn compl(i: T) -> T { /// Computes the absolute value #[inline(always)] -pub fn abs(i: T) -> T { - if is_negative(i) { -i } else { i } -} +pub fn abs(i: T) -> T { i.abs() } #[cfg(notest)] impl Ord for T { @@ -225,6 +215,38 @@ impl Neg for T { fn neg(&self) -> T { -*self } } +impl Signed for T { + /// Computes the absolute value + #[inline(always)] + fn abs(&self) -> T { + if self.is_negative() { -*self } else { *self } + } + + /** + * # Returns + * + * - `0` if the number is zero + * - `1` if the number is positive + * - `-1` if the number is negative + */ + #[inline(always)] + fn signum(&self) -> T { + match *self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns true if the number is positive + #[inline(always)] + fn is_positive(&self) -> bool { *self > 0 } + + /// Returns true if the number is negative + #[inline(always)] + fn is_negative(&self) -> bool { *self < 0 } +} + #[cfg(notest)] impl BitOr for T { #[inline(always)] @@ -344,6 +366,28 @@ mod tests { use super::inst::T; use prelude::*; + #[test] + pub fn test_signed() { + assert_eq!((1 as T).abs(), 1 as T); + assert_eq!((0 as T).abs(), 0 as T); + assert_eq!((-1 as T).abs(), 1 as T); + + assert_eq!((1 as T).signum(), 1 as T); + assert_eq!((0 as T).signum(), 0 as T); + assert_eq!((-0 as T).signum(), 0 as T); + assert_eq!((-1 as T).signum(), -1 as T); + + assert!((1 as T).is_positive()); + assert!(!(0 as T).is_positive()); + assert!(!(-0 as T).is_positive()); + assert!(!(-1 as T).is_positive()); + + assert!(!(1 as T).is_negative()); + assert!(!(0 as T).is_negative()); + assert!(!(-0 as T).is_negative()); + assert!((-1 as T).is_negative()); + } + #[test] fn test_bitwise_ops() { assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index a0ff510cde7da..ea0b290aac2ce 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -60,6 +60,17 @@ pub trait One { fn one() -> Self; } +pub trait Signed: Num + + Neg { + fn abs(&self) -> Self; + fn signum(&self) -> Self; + fn is_positive(&self) -> bool; + fn is_negative(&self) -> bool; +} + +pub trait Unsigned: Num {} + +// This should be moved into the default implementation for Signed::abs pub fn abs>(v: T) -> T { if v < Zero::zero() { v.neg() } else { v } } diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 4bb93907a3a50..41205145f1778 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -15,6 +15,7 @@ use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; +use num::Unsigned; use num; use option::Option; use prelude::*; @@ -51,15 +52,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y } #[inline(always)] pub fn gt(x: T, y: T) -> bool { x > y } -#[inline(always)] -pub fn is_positive(x: T) -> bool { x > 0 as T } -#[inline(always)] -pub fn is_negative(x: T) -> bool { x < 0 as T } -#[inline(always)] -pub fn is_nonpositive(x: T) -> bool { x <= 0 as T } -#[inline(always)] -pub fn is_nonnegative(x: T) -> bool { x >= 0 as T } - #[inline(always)] /** * Iterate over the range [`start`,`start`+`step`..`stop`) @@ -190,6 +182,8 @@ impl Neg for T { fn neg(&self) -> T { -*self } } +impl Unsigned for T {} + #[cfg(notest)] impl BitOr for T { #[inline(always)] diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 15aa6c78ed6e0..157a0e3752d77 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -39,7 +39,7 @@ pub use hash::Hash; pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::{Times, ExtendedMutableIter}; -pub use num::{Num, NumCast}; +pub use num::{Num, Signed, Unsigned, NumCast}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index ee9749af5320e..5f0fd76640a30 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -154,6 +154,8 @@ impl One for BigUint { pub fn one() -> BigUint { BigUint::new(~[1]) } } +impl Unsigned for BigUint {} + impl Add for BigUint { fn add(&self, other: &BigUint) -> BigUint { let new_len = uint::max(self.data.len(), other.data.len()); @@ -469,11 +471,8 @@ pub impl BigUint { } fn is_zero(&self) -> bool { self.data.is_empty() } + fn is_not_zero(&self) -> bool { !self.data.is_empty() } - fn is_positive(&self) -> bool { self.is_not_zero() } - fn is_negative(&self) -> bool { false } - fn is_nonpositive(&self) -> bool { self.is_zero() } - fn is_nonnegative(&self) -> bool { true } fn to_uint(&self) -> uint { match self.data.len() { @@ -693,6 +692,27 @@ impl One for BigInt { } } +impl Signed for BigInt { + fn abs(&self) -> BigInt { + match self.sign { + Plus | Zero => copy *self, + Minus => BigInt::from_biguint(Plus, copy self.data) + } + } + + fn signum(&self) -> BigInt { + match self.sign { + Plus => BigInt::from_biguint(Plus, One::one()), + Minus => BigInt::from_biguint(Minus, One::one()), + Zero => Zero::zero(), + } + } + + fn is_positive(&self) -> bool { self.sign == Plus } + + fn is_negative(&self) -> bool { self.sign == Minus } +} + impl Add for BigInt { fn add(&self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { @@ -888,11 +908,8 @@ pub impl BigInt { } fn is_zero(&self) -> bool { self.sign == Zero } + fn is_not_zero(&self) -> bool { self.sign != Zero } - fn is_positive(&self) -> bool { self.sign == Plus } - fn is_negative(&self) -> bool { self.sign == Minus } - fn is_nonpositive(&self) -> bool { self.sign != Plus } - fn is_nonnegative(&self) -> bool { self.sign != Minus } fn to_uint(&self) -> uint { match self.sign { diff --git a/src/test/run-pass/block-arg.rs b/src/test/run-pass/block-arg.rs index 4fecbd4e956b3..93c44b8faa128 100644 --- a/src/test/run-pass/block-arg.rs +++ b/src/test/run-pass/block-arg.rs @@ -18,28 +18,28 @@ pub fn main() { } // Usable at all: - let mut any_negative = do vec::any(v) |e| { float::is_negative(*e) }; + let mut any_negative = do vec::any(v) |e| { e.is_negative() }; assert!(any_negative); // Higher precedence than assignments: - any_negative = do vec::any(v) |e| { float::is_negative(*e) }; + any_negative = do vec::any(v) |e| { e.is_negative() }; assert!(any_negative); // Higher precedence than unary operations: - let abs_v = do vec::map(v) |e| { float::abs(*e) }; - assert!(do vec::all(abs_v) |e| { float::is_nonnegative(*e) }); - assert!(!do vec::any(abs_v) |e| { float::is_negative(*e) }); + let abs_v = do vec::map(v) |e| { e.abs() }; + assert!(do vec::all(abs_v) |e| { e.is_positive() }); + assert!(!do vec::any(abs_v) |e| { e.is_negative() }); // Usable in funny statement-like forms: - if !do vec::any(v) |e| { float::is_positive(*e) } { + if !do vec::any(v) |e| { e.is_positive() } { assert!(false); } - match do vec::all(v) |e| { float::is_negative(*e) } { + match do vec::all(v) |e| { e.is_negative() } { true => { fail!(~"incorrect answer."); } false => { } } match 3 { - _ if do vec::any(v) |e| { float::is_negative(*e) } => { + _ if do vec::any(v) |e| { e.is_negative() } => { } _ => { fail!(~"wrong answer."); @@ -56,7 +56,7 @@ pub fn main() { // In the tail of a block let w = - if true { do vec::any(abs_v) |e| { float::is_nonnegative(*e) } } + if true { do vec::any(abs_v) |e| { e.is_positive() } } else { false }; assert!(w); } From f39152e07baf03fc1ff4c8b2c1678ac857b4a512 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 12:54:11 +1000 Subject: [PATCH 377/403] Implement Natural trait This adds the following methods to ints and uints: - div - modulo - div_mod - quot_rem - gcd - lcm - divisible_by - is_even - is_odd I have not implemented Natural for BigInt and BigUInt because they're a little over my head. --- src/libcore/core.rc | 2 +- src/libcore/num/int-template.rs | 245 +++++++++++++++++++++++++++++++ src/libcore/num/num.rs | 16 ++ src/libcore/num/uint-template.rs | 72 +++++++++ src/libcore/prelude.rs | 2 +- 5 files changed, 335 insertions(+), 2 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 123fbcca9d536..61fbf98a7c61d 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -105,7 +105,7 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use iter::{ExtendedMutableIter}; -pub use num::{Num, Signed, Unsigned, NumCast}; +pub use num::{Num, Signed, Unsigned, Natural, NumCast}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index d65cbb4cf9275..426ed8a8b0f6e 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -191,6 +191,24 @@ impl Div for T { #[cfg(stage2,notest)] #[cfg(stage3,notest)] impl Quot for T { + /** + * Returns the integer quotient, truncated towards 0. As this behaviour reflects + * the underlying machine implementation it is more efficient than `Natural::div`. + * + * # Examples + * + * ~~~ + * assert!( 8 / 3 == 2); + * assert!( 8 / -3 == -2); + * assert!(-8 / 3 == -2); + * assert!(-8 / -3 == 2); + + * assert!( 1 / 2 == 0); + * assert!( 1 / -2 == 0); + * assert!(-1 / 2 == 0); + * assert!(-1 / -2 == 0); + * ~~~ + */ #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } } @@ -205,6 +223,27 @@ impl Modulo for T { #[cfg(stage2,notest)] #[cfg(stage3,notest)] impl Rem for T { + /** + * Returns the integer remainder after division, satisfying: + * + * ~~~ + * assert!((n / d) * d + (n % d) == n) + * ~~~ + * + * # Examples + * + * ~~~ + * assert!( 8 % 3 == 2); + * assert!( 8 % -3 == 2); + * assert!(-8 % 3 == -2); + * assert!(-8 % -3 == -2); + + * assert!( 1 % 2 == 1); + * assert!( 1 % -2 == 1); + * assert!(-1 % 2 == -1); + * assert!(-1 % -2 == -1); + * ~~~ + */ #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } } @@ -247,6 +286,123 @@ impl Signed for T { fn is_negative(&self) -> bool { *self < 0 } } +impl Natural for T { + /** + * Floored integer division + * + * # Examples + * + * ~~~ + * assert!(( 8).div( 3) == 2); + * assert!(( 8).div(-3) == -3); + * assert!((-8).div( 3) == -3); + * assert!((-8).div(-3) == 2); + * + * assert!(( 1).div( 2) == 0); + * assert!(( 1).div(-2) == -1); + * assert!((-1).div( 2) == -1); + * assert!((-1).div(-2) == 0); + * ~~~ + */ + #[inline(always)] + fn div(&self, other: T) -> T { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match self.quot_rem(other) { + (q, r) if (r > 0 && other < 0) + || (r < 0 && other > 0) => q - 1, + (q, _) => q, + } + } + + /** + * Integer modulo, satisfying: + * + * ~~~ + * assert!(n.div(d) * d + n.modulo(d) == n) + * ~~~ + * + * # Examples + * + * ~~~ + * assert!(( 8).modulo( 3) == 2); + * assert!(( 8).modulo(-3) == -1); + * assert!((-8).modulo( 3) == 1); + * assert!((-8).modulo(-3) == -2); + * + * assert!(( 1).modulo( 2) == 1); + * assert!(( 1).modulo(-2) == -1); + * assert!((-1).modulo( 2) == 1); + * assert!((-1).modulo(-2) == -1); + * ~~~ + */ + #[inline(always)] + fn modulo(&self, other: T) -> T { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match *self % other { + r if (r > 0 && other < 0) + || (r < 0 && other > 0) => r + other, + r => r, + } + } + + /// Calculates `div` and `modulo` simultaneously + #[inline(always)] + fn div_mod(&self, other: T) -> (T,T) { + // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, + // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) + match self.quot_rem(other) { + (q, r) if (r > 0 && other < 0) + || (r < 0 && other > 0) => (q - 1, r + other), + (q, r) => (q, r), + } + } + + /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously + #[inline(always)] + fn quot_rem(&self, other: T) -> (T,T) { + (*self / other, *self % other) + } + + /** + * Calculates the Greatest Common Divisor (GCD) of the number and `other` + * + * The result is always positive + */ + #[inline(always)] + fn gcd(&self, other: T) -> T { + // Use Euclid's algorithm + let mut m = *self, n = other; + while m != 0 { + let temp = m; + m = n % temp; + n = temp; + } + n.abs() + } + + /** + * Calculates the Lowest Common Multiple (LCM) of the number and `other` + */ + #[inline(always)] + fn lcm(&self, other: T) -> T { + ((*self * other) / self.gcd(other)).abs() // should not have to recaluculate abs + } + + /// Returns `true` if the number can be divided by `other` without leaving a remainder + #[inline(always)] + fn divisible_by(&self, other: T) -> bool { *self % other == 0 } + + /// Returns `true` if the number is divisible by `2` + #[inline(always)] + fn is_even(&self) -> bool { self.divisible_by(2) } + + /// Returns `true` if the number is not divisible by `2` + #[inline(always)] + fn is_odd(&self) -> bool { !self.is_even() } +} + #[cfg(notest)] impl BitOr for T { #[inline(always)] @@ -388,6 +544,95 @@ mod tests { assert!((-1 as T).is_negative()); } + /** + * Checks that the division rule holds for: + * + * - `n`: numerator (dividend) + * - `d`: denominator (divisor) + * - `qr`: quotient and remainder + */ + #[cfg(test)] + fn test_division_rule(nd: (T,T), qr: (T,T)) { + let (n,d) = nd, + (q,r) = qr; + + assert_eq!(d * q + r, n); + } + + #[test] + fn test_quot_rem() { + fn test_nd_qr(nd: (T,T), qr: (T,T)) { + let (n,d) = nd; + let separate_quot_rem = (n / d, n % d); + let combined_quot_rem = n.quot_rem(d); + + assert_eq!(separate_quot_rem, qr); + assert_eq!(combined_quot_rem, qr); + + test_division_rule(nd, separate_quot_rem); + test_division_rule(nd, combined_quot_rem); + } + + test_nd_qr(( 8, 3), ( 2, 2)); + test_nd_qr(( 8, -3), (-2, 2)); + test_nd_qr((-8, 3), (-2, -2)); + test_nd_qr((-8, -3), ( 2, -2)); + + test_nd_qr(( 1, 2), ( 0, 1)); + test_nd_qr(( 1, -2), ( 0, 1)); + test_nd_qr((-1, 2), ( 0, -1)); + test_nd_qr((-1, -2), ( 0, -1)); + } + + #[test] + fn test_div_mod() { + fn test_nd_dm(nd: (T,T), dm: (T,T)) { + let (n,d) = nd; + let separate_div_mod = (n.div(d), n.modulo(d)); + let combined_div_mod = n.div_mod(d); + + assert_eq!(separate_div_mod, dm); + assert_eq!(combined_div_mod, dm); + + test_division_rule(nd, separate_div_mod); + test_division_rule(nd, combined_div_mod); + } + + test_nd_dm(( 8, 3), ( 2, 2)); + test_nd_dm(( 8, -3), (-3, -1)); + test_nd_dm((-8, 3), (-3, 1)); + test_nd_dm((-8, -3), ( 2, -2)); + + test_nd_dm(( 1, 2), ( 0, 1)); + test_nd_dm(( 1, -2), (-1, -1)); + test_nd_dm((-1, 2), (-1, 1)); + test_nd_dm((-1, -2), ( 0, -1)); + } + + #[test] + fn test_gcd() { + assert_eq!((10 as T).gcd(2), 2 as T); + assert_eq!((10 as T).gcd(3), 1 as T); + assert_eq!((0 as T).gcd(3), 3 as T); + assert_eq!((3 as T).gcd(3), 3 as T); + assert_eq!((56 as T).gcd(42), 14 as T); + assert_eq!((3 as T).gcd(-3), 3 as T); + assert_eq!((-6 as T).gcd(3), 3 as T); + assert_eq!((-4 as T).gcd(-2), 2 as T); + } + + #[test] + fn test_lcm() { + assert_eq!((1 as T).lcm(0), 0 as T); + assert_eq!((0 as T).lcm(1), 0 as T); + assert_eq!((1 as T).lcm(1), 1 as T); + assert_eq!((-1 as T).lcm(1), 1 as T); + assert_eq!((1 as T).lcm(-1), 1 as T); + assert_eq!((-1 as T).lcm(-1), 1 as T); + assert_eq!((8 as T).lcm(9), 72 as T); + assert_eq!((11 as T).lcm(5), 55 as T); + } + #[test] fn test_bitwise_ops() { assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index ea0b290aac2ce..577bb3f0f150a 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -75,6 +75,22 @@ pub fn abs>(v: T) -> T { if v < Zero::zero() { v.neg() } else { v } } +pub trait Natural: Num + + Ord + + Quot + + Rem { + fn div(&self, other: Self) -> Self; + fn modulo(&self, other: Self) -> Self; + fn div_mod(&self, other: Self) -> (Self,Self); + fn quot_rem(&self, other: Self) -> (Self,Self); + + fn gcd(&self, other: Self) -> Self; + fn lcm(&self, other: Self) -> Self; + fn divisible_by(&self, other: Self) -> bool; + fn is_even(&self) -> bool; + fn is_odd(&self) -> bool; +} + pub trait Round { fn round(&self, mode: RoundMode) -> Self; diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 41205145f1778..a0da84a8c5359 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -184,6 +184,59 @@ impl Neg for T { impl Unsigned for T {} +impl Natural for T { + /// Unsigned integer division. Returns the same result as `quot` (`/`). + #[inline(always)] + fn div(&self, other: T) -> T { *self / other } + + /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). + #[inline(always)] + fn modulo(&self, other: T) -> T { *self / other } + + /// Calculates `div` and `modulo` simultaneously + #[inline(always)] + fn div_mod(&self, other: T) -> (T,T) { + (*self / other, *self % other) + } + + /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously + #[inline(always)] + fn quot_rem(&self, other: T) -> (T,T) { + (*self / other, *self % other) + } + + /// Calculates the Greatest Common Divisor (GCD) of the number and `other` + #[inline(always)] + fn gcd(&self, other: T) -> T { + // Use Euclid's algorithm + let mut m = *self, n = other; + while m != 0 { + let temp = m; + m = n % temp; + n = temp; + } + n + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and `other` + #[inline(always)] + fn lcm(&self, other: T) -> T { + (*self * other) / self.gcd(other) + } + + /// Returns `true` if the number can be divided by `other` without leaving a remainder + #[inline(always)] + fn divisible_by(&self, other: T) -> bool { *self % other == 0 } + + /// Returns `true` if the number is divisible by `2` + #[inline(always)] + fn is_even(&self) -> bool { self.divisible_by(2) } + + /// Returns `true` if the number is not divisible by `2` + #[inline(always)] + fn is_odd(&self) -> bool { !self.is_even() } +} + #[cfg(notest)] impl BitOr for T { #[inline(always)] @@ -303,6 +356,25 @@ mod tests { use super::inst::T; use prelude::*; + #[test] + fn test_gcd() { + assert_eq!((10 as T).gcd(2), 2 as T); + assert_eq!((10 as T).gcd(3), 1 as T); + assert_eq!((0 as T).gcd(3), 3 as T); + assert_eq!((3 as T).gcd(3), 3 as T); + assert_eq!((56 as T).gcd(42), 14 as T); + } + + #[test] + fn test_lcm() { + assert_eq!((1 as T).lcm(0), 0 as T); + assert_eq!((0 as T).lcm(1), 0 as T); + assert_eq!((1 as T).lcm(1), 1 as T); + assert_eq!((8 as T).lcm(9), 72 as T); + assert_eq!((11 as T).lcm(5), 55 as T); + assert_eq!((99 as T).lcm(17), 1683 as T); + } + #[test] fn test_bitwise_ops() { assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 157a0e3752d77..03e6065a85caa 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -39,7 +39,7 @@ pub use hash::Hash; pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::{Times, ExtendedMutableIter}; -pub use num::{Num, Signed, Unsigned, NumCast}; +pub use num::{Num, Signed, Unsigned, Natural, NumCast}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From ab8068c9f2cbcce4411020b04dafe2055044f96a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 13:01:38 +1000 Subject: [PATCH 378/403] Improve divide-by-zero error messages --- src/librustc/middle/const_eval.rs | 8 ++++---- src/librustc/middle/trans/base.rs | 4 ++-- src/test/compile-fail/eval-enum.rs | 4 ++-- src/test/run-fail/divide-by-zero.rs | 2 +- src/test/run-fail/mod-zero.rs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index c1cc01ed05a72..d3619a247677d 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -299,9 +299,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_int(a + b)), subtract => Ok(const_int(a - b)), mul => Ok(const_int(a * b)), - quot if b == 0 => Err(~"quotient zero"), + quot if b == 0 => Err(~"attempted quotient with a divisor of zero"), quot => Ok(const_int(a / b)), - rem if b == 0 => Err(~"remainder zero"), + rem if b == 0 => Err(~"attempted remainder with a divisor of zero"), rem => Ok(const_int(a % b)), and | bitand => Ok(const_int(a & b)), or | bitor => Ok(const_int(a | b)), @@ -321,9 +321,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) add => Ok(const_uint(a + b)), subtract => Ok(const_uint(a - b)), mul => Ok(const_uint(a * b)), - quot if b == 0 => Err(~"quotient zero"), + quot if b == 0 => Err(~"attempted quotient with a divisor of zero"), quot => Ok(const_uint(a / b)), - rem if b == 0 => Err(~"remainder zero"), + rem if b == 0 => Err(~"attempted remainder with a divisor of zero"), rem => Ok(const_uint(a % b)), and | bitand => Ok(const_uint(a & b)), or | bitor => Ok(const_uint(a | b)), diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index da87568b3d0c0..de64441fd95bf 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -785,9 +785,9 @@ pub fn cast_shift_rhs(op: ast::binop, pub fn fail_if_zero(cx: block, span: span, quotrem: ast::binop, rhs: ValueRef, rhs_t: ty::t) -> block { let text = if quotrem == ast::quot { - @~"quotient zero" + @~"attempted quotient with a divisor of zero" } else { - @~"remainder zero" + @~"attempted remainder with a divisor of zero" }; let is_zero = match ty::get(rhs_t).sty { ty::ty_int(t) => { diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs index d368f9d6769de..0123341957903 100644 --- a/src/test/compile-fail/eval-enum.rs +++ b/src/test/compile-fail/eval-enum.rs @@ -1,6 +1,6 @@ enum test { - quot_zero = 1/0, //~ERROR expected constant: quotient zero - rem_zero = 1%0 //~ERROR expected constant: remainder zero + quot_zero = 1/0, //~ERROR expected constant: attempted quotient with a divisor of zero + rem_zero = 1%0 //~ERROR expected constant: attempted remainder with a divisor of zero } fn main() {} diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs index 7a17dd024153c..d4f3828ea7174 100644 --- a/src/test/run-fail/divide-by-zero.rs +++ b/src/test/run-fail/divide-by-zero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:quotient zero +// error-pattern:attempted quotient with a divisor of zero fn main() { let y = 0; let z = 1 / y; diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs index c379a8fc65fd7..b3e083c77fb23 100644 --- a/src/test/run-fail/mod-zero.rs +++ b/src/test/run-fail/mod-zero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:remainder zero +// error-pattern:attempted remainder with a divisor of zero fn main() { let y = 0; let z = 1 % y; From 6c0a7c7b7d304157f31189bf34f50ef4027e1d66 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 24 Apr 2013 00:00:43 +1000 Subject: [PATCH 379/403] libcore: remove @Rng from rand, and use traits instead. Also, rename RandRes -> IsaacRng, and make the constructors static methods. --- src/libcore/flate.rs | 2 +- src/libcore/hashmap.rs | 2 +- src/libcore/os.rs | 2 +- src/libcore/rand.rs | 324 ++++++++++++++++--------------- src/libcore/unstable/at_exit.rs | 2 +- src/librustpkg/path_util.rs | 2 +- src/libstd/bitv.rs | 5 +- src/libstd/sort.rs | 10 +- src/libstd/tempfile.rs | 2 +- src/libstd/test.rs | 2 +- src/libstd/timer.rs | 4 +- src/libstd/treemap.rs | 2 +- src/test/bench/core-map.rs | 2 +- src/test/bench/core-set.rs | 14 +- src/test/bench/core-std.rs | 6 +- src/test/bench/graph500-bfs.rs | 8 +- src/test/bench/noise.rs | 6 +- src/test/bench/shootout-fasta.rs | 2 +- src/test/run-pass/morestack6.rs | 3 +- 19 files changed, 205 insertions(+), 195 deletions(-) diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs index 70c96c9c806e4..5c4181c10cf3b 100644 --- a/src/libcore/flate.rs +++ b/src/libcore/flate.rs @@ -85,7 +85,7 @@ pub fn inflate_bytes(bytes: &const [u8]) -> ~[u8] { #[test] #[allow(non_implicitly_copyable_typarams)] fn test_flate_round_trip() { - let r = rand::Rng(); + let r = rand::rng(); let mut words = ~[]; for 20.times { words.push(r.gen_bytes(r.gen_uint_range(1, 10))); diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 1d7cc8515a656..3233207b8bd6a 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -56,7 +56,7 @@ fn resize_at(capacity: uint) -> uint { pub fn linear_map_with_capacity( initial_capacity: uint) -> HashMap { let r = rand::task_rng(); - linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(), + linear_map_with_capacity_and_keys((*r).gen_u64(), (*r).gen_u64(), initial_capacity) } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index fa3ca4577c6d1..1000fd88b5246 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -1259,7 +1259,7 @@ mod tests { } fn make_rand_name() -> ~str { - let rng: @rand::Rng = rand::Rng(); + let rng = rand::rng(); let n = ~"TEST" + rng.gen_str(10u); assert!(getenv(n).is_none()); n diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 919c7bbb036d6..86509c81eb34d 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -22,95 +22,95 @@ use libc::size_t; /// A type that can be randomly generated using an RNG pub trait Rand { - fn rand(rng: @rand::Rng) -> Self; + fn rand(rng: &R) -> Self; } impl Rand for int { - fn rand(rng: @rand::Rng) -> int { + fn rand(rng: &R) -> int { rng.gen_int() } } impl Rand for i8 { - fn rand(rng: @rand::Rng) -> i8 { + fn rand(rng: &R) -> i8 { rng.gen_i8() } } impl Rand for i16 { - fn rand(rng: @rand::Rng) -> i16 { + fn rand(rng: &R) -> i16 { rng.gen_i16() } } impl Rand for i32 { - fn rand(rng: @rand::Rng) -> i32 { + fn rand(rng: &R) -> i32 { rng.gen_i32() } } impl Rand for i64 { - fn rand(rng: @rand::Rng) -> i64 { + fn rand(rng: &R) -> i64 { rng.gen_i64() } } impl Rand for uint { - fn rand(rng: @rand::Rng) -> uint { + fn rand(rng: &R) -> uint { rng.gen_uint() } } impl Rand for u8 { - fn rand(rng: @rand::Rng) -> u8 { + fn rand(rng: &R) -> u8 { rng.gen_u8() } } impl Rand for u16 { - fn rand(rng: @rand::Rng) -> u16 { + fn rand(rng: &R) -> u16 { rng.gen_u16() } } impl Rand for u32 { - fn rand(rng: @rand::Rng) -> u32 { + fn rand(rng: &R) -> u32 { rng.gen_u32() } } impl Rand for u64 { - fn rand(rng: @rand::Rng) -> u64 { + fn rand(rng: &R) -> u64 { rng.gen_u64() } } impl Rand for float { - fn rand(rng: @rand::Rng) -> float { + fn rand(rng: &R) -> float { rng.gen_float() } } impl Rand for f32 { - fn rand(rng: @rand::Rng) -> f32 { + fn rand(rng: &R) -> f32 { rng.gen_f32() } } impl Rand for f64 { - fn rand(rng: @rand::Rng) -> f64 { + fn rand(rng: &R) -> f64 { rng.gen_f64() } } impl Rand for char { - fn rand(rng: @rand::Rng) -> char { + fn rand(rng: &R) -> char { rng.gen_char() } } impl Rand for bool { - fn rand(rng: @rand::Rng) -> bool { + fn rand(rng: &R) -> bool { rng.gen_bool() } } @@ -123,10 +123,10 @@ macro_rules! tuple_impl { $( $tyvar : Rand ),* > Rand for ( $( $tyvar ),* , ) { - fn rand (_rng: @Rng) -> ( $( $tyvar ),* , ) { + fn rand(_rng: &R) -> ( $( $tyvar ),* , ) { ( - // use the $var's to get the appropriate number of repeats - // (they're not actually needed) + // use the $tyvar's to get the appropriate number of + // repeats (they're not actually needed) $( _rng.gen::<$tyvar>() ),* @@ -137,7 +137,7 @@ macro_rules! tuple_impl { } } -impl Rand for () { fn rand(_: @Rng) -> () { () } } +impl Rand for () { fn rand(_: &R) -> () { () } } tuple_impl!{A} tuple_impl!{A, B} tuple_impl!{A, B, C} @@ -150,9 +150,9 @@ tuple_impl!{A, B, C, D, E, F, G, H, I} tuple_impl!{A, B, C, D, E, F, G, H, I, J} impl Rand for Option { - fn rand(rng: @rand::Rng) -> Option { + fn rand(rng: &R) -> Option { if rng.gen_bool() { - Some(Rand::rand(rng)) + Some(rng.gen()) } else { None } @@ -160,11 +160,11 @@ impl Rand for Option { } impl Rand for ~T { - fn rand(rng: @Rng) -> ~T { ~rng.gen() } + fn rand(rng: &R) -> ~T { ~rng.gen() } } impl Rand for @T { - fn rand(rng: @Rng) -> @T { @rng.gen() } + fn rand(rng: &R) -> @T { @rng.gen() } } #[allow(non_camel_case_types)] // runtime type @@ -173,7 +173,7 @@ pub enum rust_rng {} #[abi = "cdecl"] pub mod rustrt { use libc::size_t; - use rand::rust_rng; + use super::rust_rng; pub extern { unsafe fn rand_seed_size() -> size_t; @@ -187,7 +187,7 @@ pub mod rustrt { /// A random number generator pub trait Rng { /// Return the next random integer - fn next(&self) -> u32; + pub fn next(&self) -> u32; } /// A value with a particular weight compared to other values @@ -195,9 +195,10 @@ pub struct Weighted { weight: uint, item: T, } - +// this should be in gen_f64, but it causes an ICE there. +static scale : f64 = (u32::max_value as f64) + 1.0f64; pub trait RngUtil { - /// Return a random value for a Rand type + /// Return a random value of a Rand type fn gen(&self) -> T; /** * Return a random int @@ -209,7 +210,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%d",rng.gen_int())); * } * ~~~ @@ -249,7 +250,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%f",rng.gen_float())); * } * ~~~ @@ -275,7 +276,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%b",rng.gen_bool())); * } * ~~~ @@ -291,7 +292,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%b",rng.gen_weighted_bool(3))); * } * ~~~ @@ -307,7 +308,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(rng.gen_str(8)); * } * ~~~ @@ -323,13 +324,12 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%?",rng.gen_bytes(8))); * } * ~~~ */ fn gen_bytes(&self, len: uint) -> ~[u8]; - /// /** * Choose an item randomly, failing if values is empty * @@ -340,7 +340,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%d",rng.choose([1,2,4,8,16,32]))); * } * ~~~ @@ -359,7 +359,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * let x = [rand::Weighted {weight: 4, item: 'a'}, * rand::Weighted {weight: 2, item: 'b'}, * rand::Weighted {weight: 2, item: 'c'}]; @@ -379,7 +379,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * let x = [rand::Weighted {weight: 4, item: 'a'}, * rand::Weighted {weight: 2, item: 'b'}, * rand::Weighted {weight: 2, item: 'c'}]; @@ -399,7 +399,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * let x = [rand::Weighted {weight: 4, item: 'a'}, * rand::Weighted {weight: 2, item: 'b'}, * rand::Weighted {weight: 2, item: 'c'}]; @@ -418,7 +418,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * println(fmt!("%?",rng.shuffle([1,2,3]))); * } * ~~~ @@ -434,7 +434,7 @@ pub trait RngUtil { * use core::rand::RngUtil; * * fn main() { - * rng = rand::Rng(); + * rng = rand::rng(); * let mut y = [1,2,3]; * rng.shuffle_mut(y); * println(fmt!("%?",y)); @@ -447,10 +447,10 @@ pub trait RngUtil { } /// Extension methods for random number generators -impl RngUtil for @Rng { +impl RngUtil for R { /// Return a random value for a Rand type - fn gen(&self) -> T { - Rand::rand(*self) + fn gen(&self) -> T { + Rand::rand(self) } /// Return a random int @@ -536,7 +536,7 @@ impl RngUtil for @Rng { let u1 = self.next() as f64; let u2 = self.next() as f64; let u3 = self.next() as f64; - static scale : f64 = (u32::max_value as f64) + 1.0f64; + return ((u1 / scale + u2) / scale + u3) / scale; } @@ -605,7 +605,6 @@ impl RngUtil for @Rng { Some(values[self.gen_uint_range(0u, values.len())]) } } - /** * Choose an item respecting the relative weights, failing if the sum of * the weights is 0 @@ -668,14 +667,18 @@ impl RngUtil for @Rng { vec::swap(values, i, self.gen_uint_range(0u, i + 1u)); } } +} +/// Create a random number generator with a default algorithm and seed. +pub fn rng() -> IsaacRng { + IsaacRng::new() } -struct RandRes { - rng: *rust_rng, +pub struct IsaacRng { + priv rng: *rust_rng, } -impl Drop for RandRes { +impl Drop for IsaacRng { fn finalize(&self) { unsafe { rustrt::rand_free(self.rng); @@ -683,21 +686,42 @@ impl Drop for RandRes { } } -fn RandRes(rng: *rust_rng) -> RandRes { - RandRes { - rng: rng +pub impl IsaacRng { + priv fn from_rust_rng(rng: *rust_rng) -> IsaacRng { + IsaacRng { + rng: rng + } + } + + /// Create an ISAAC random number generator with a system specified seed + fn new() -> IsaacRng { + IsaacRng::new_seeded(seed()) + } + + /** + * Create a random number generator using the specified seed. A generator + * constructed with a given seed will generate the same sequence of values as + * all other generators constructed with the same seed. The seed may be any + * length. + */ + fn new_seeded(seed: &[u8]) -> IsaacRng { + unsafe { + do vec::as_imm_buf(seed) |p, sz| { + IsaacRng::from_rust_rng(rustrt::rand_new_seeded(p, sz as size_t)) + } + } } } -impl Rng for @RandRes { - fn next(&self) -> u32 { +impl Rng for IsaacRng { + pub fn next(&self) -> u32 { unsafe { - return rustrt::rand_next((*self).rng); + return rustrt::rand_next(self.rng); } } } -/// Create a new random seed for seeded_rng +/// Create a new random seed for IsaacRng::new_seeded pub fn seed() -> ~[u8] { unsafe { let n = rustrt::rand_seed_size() as uint; @@ -709,38 +733,15 @@ pub fn seed() -> ~[u8] { } } -/// Create a random number generator with a system specified seed -pub fn Rng() -> @Rng { - seeded_rng(seed()) -} - -/** - * Create a random number generator using the specified seed. A generator - * constructed with a given seed will generate the same sequence of values as - * all other generators constructed with the same seed. The seed may be any - * length. - */ -pub fn seeded_rng(seed: &[u8]) -> @Rng { - @seeded_randres(seed) as @Rng -} - -fn seeded_randres(seed: &[u8]) -> @RandRes { - unsafe { - do vec::as_imm_buf(seed) |p, sz| { - @RandRes(rustrt::rand_new_seeded(p, sz as size_t)) - } - } -} - -struct XorShiftState { - mut x: u32, - mut y: u32, - mut z: u32, - mut w: u32, +struct XorShiftRng { + priv mut x: u32, + priv mut y: u32, + priv mut z: u32, + priv mut w: u32, } -impl Rng for XorShiftState { - fn next(&self) -> u32 { +impl Rng for XorShiftRng { + pub fn next(&self) -> u32 { let x = self.x; let t = x ^ (x << 11); self.x = self.y; @@ -752,38 +753,46 @@ impl Rng for XorShiftState { } } -pub fn xorshift() -> @Rng { - // constants taken from http://en.wikipedia.org/wiki/Xorshift - seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32) -} +pub impl XorShiftRng { + /// Create an xor shift random number generator with a default seed. + fn new() -> XorShiftRng { + // constants taken from http://en.wikipedia.org/wiki/Xorshift + XorShiftRng::new_seeded(123456789u32, 362436069u32, 521288629u32, 88675123u32) + } -pub fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> @Rng { - @XorShiftState { x: x, y: y, z: z, w: w } as @Rng -} + /** + * Create a random number generator using the specified seed. A generator + * constructed with a given seed will generate the same sequence of values as + * all other generators constructed with the same seed. + */ + fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng { + XorShiftRng { x: x, y: y, z: z, w: w } + } +} // used to make space in TLS for a random number generator -fn tls_rng_state(_v: @RandRes) {} +fn tls_rng_state(_v: @IsaacRng) {} /** * Gives back a lazily initialized task-local random number generator, * seeded by the system. Intended to be used in method chaining style, ie * task_rng().gen_int(). */ -pub fn task_rng() -> @Rng { - let r : Option<@RandRes>; +pub fn task_rng() -> @IsaacRng { + let r : Option<@IsaacRng>; unsafe { r = task::local_data::local_data_get(tls_rng_state); } match r { None => { unsafe { - let rng = seeded_randres(seed()); + let rng = @IsaacRng::new_seeded(seed()); task::local_data::local_data_set(tls_rng_state, rng); - @rng as @Rng + rng } } - Some(rng) => @rng as @Rng + Some(rng) => rng } } @@ -792,36 +801,35 @@ pub fn task_rng() -> @Rng { * generator. */ pub fn random() -> T { - task_rng().gen() + (*task_rng()).gen() } - #[cfg(test)] mod tests { use option::{Option, Some}; - use rand; + use super::*; #[test] - fn rng_seeded() { - let seed = rand::seed(); - let ra = rand::seeded_rng(seed); - let rb = rand::seeded_rng(seed); + fn test_rng_seeded() { + let seed = seed(); + let ra = IsaacRng::new_seeded(seed); + let rb = IsaacRng::new_seeded(seed); assert!(ra.gen_str(100u) == rb.gen_str(100u)); } #[test] - fn rng_seeded_custom_seed() { + fn test_rng_seeded_custom_seed() { // much shorter than generated seeds which are 1024 bytes let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; - let ra = rand::seeded_rng(seed); - let rb = rand::seeded_rng(seed); + let ra = IsaacRng::new_seeded(seed); + let rb = IsaacRng::new_seeded(seed); assert!(ra.gen_str(100u) == rb.gen_str(100u)); } #[test] - fn rng_seeded_custom_seed2() { + fn test_rng_seeded_custom_seed2() { let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; - let ra = rand::seeded_rng(seed); + let ra = IsaacRng::new_seeded(seed); // Regression test that isaac is actually using the above vector let r = ra.next(); error!("%?", r); @@ -830,8 +838,8 @@ mod tests { } #[test] - fn gen_int_range() { - let r = rand::Rng(); + fn test_gen_int_range() { + let r = rng(); let a = r.gen_int_range(-3, 42); assert!(a >= -3 && a < 42); assert!(r.gen_int_range(0, 1) == 0); @@ -841,13 +849,13 @@ mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - fn gen_int_from_fail() { - rand::Rng().gen_int_range(5, -2); + fn test_gen_int_from_fail() { + rng().gen_int_range(5, -2); } #[test] - fn gen_uint_range() { - let r = rand::Rng(); + fn test_gen_uint_range() { + let r = rng(); let a = r.gen_uint_range(3u, 42u); assert!(a >= 3u && a < 42u); assert!(r.gen_uint_range(0u, 1u) == 0u); @@ -857,28 +865,28 @@ mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - fn gen_uint_range_fail() { - rand::Rng().gen_uint_range(5u, 2u); + fn test_gen_uint_range_fail() { + rng().gen_uint_range(5u, 2u); } #[test] - fn gen_float() { - let r = rand::Rng(); + fn test_gen_float() { + let r = rng(); let a = r.gen_float(); let b = r.gen_float(); debug!((a, b)); } #[test] - fn gen_weighted_bool() { - let r = rand::Rng(); + fn test_gen_weighted_bool() { + let r = rng(); assert!(r.gen_weighted_bool(0u) == true); assert!(r.gen_weighted_bool(1u) == true); } #[test] - fn gen_str() { - let r = rand::Rng(); + fn test_gen_str() { + let r = rng(); debug!(r.gen_str(10u)); debug!(r.gen_str(10u)); debug!(r.gen_str(10u)); @@ -888,91 +896,91 @@ mod tests { } #[test] - fn gen_bytes() { - let r = rand::Rng(); + fn test_gen_bytes() { + let r = rng(); assert!(r.gen_bytes(0u).len() == 0u); assert!(r.gen_bytes(10u).len() == 10u); assert!(r.gen_bytes(16u).len() == 16u); } #[test] - fn choose() { - let r = rand::Rng(); + fn test_choose() { + let r = rng(); assert!(r.choose([1, 1, 1]) == 1); } #[test] - fn choose_option() { - let r = rand::Rng(); + fn test_choose_option() { + let r = rng(); let x: Option = r.choose_option([]); assert!(x.is_none()); assert!(r.choose_option([1, 1, 1]) == Some(1)); } #[test] - fn choose_weighted() { - let r = rand::Rng(); + fn test_choose_weighted() { + let r = rng(); assert!(r.choose_weighted(~[ - rand::Weighted { weight: 1u, item: 42 }, + Weighted { weight: 1u, item: 42 }, ]) == 42); assert!(r.choose_weighted(~[ - rand::Weighted { weight: 0u, item: 42 }, - rand::Weighted { weight: 1u, item: 43 }, + Weighted { weight: 0u, item: 42 }, + Weighted { weight: 1u, item: 43 }, ]) == 43); } #[test] - fn choose_weighted_option() { - let r = rand::Rng(); + fn test_choose_weighted_option() { + let r = rng(); assert!(r.choose_weighted_option(~[ - rand::Weighted { weight: 1u, item: 42 }, + Weighted { weight: 1u, item: 42 }, ]) == Some(42)); assert!(r.choose_weighted_option(~[ - rand::Weighted { weight: 0u, item: 42 }, - rand::Weighted { weight: 1u, item: 43 }, + Weighted { weight: 0u, item: 42 }, + Weighted { weight: 1u, item: 43 }, ]) == Some(43)); let v: Option = r.choose_weighted_option([]); assert!(v.is_none()); } #[test] - fn weighted_vec() { - let r = rand::Rng(); + fn test_weighted_vec() { + let r = rng(); let empty: ~[int] = ~[]; assert!(r.weighted_vec(~[]) == empty); assert!(r.weighted_vec(~[ - rand::Weighted { weight: 0u, item: 3u }, - rand::Weighted { weight: 1u, item: 2u }, - rand::Weighted { weight: 2u, item: 1u }, + Weighted { weight: 0u, item: 3u }, + Weighted { weight: 1u, item: 2u }, + Weighted { weight: 2u, item: 1u }, ]) == ~[2u, 1u, 1u]); } #[test] - fn shuffle() { - let r = rand::Rng(); + fn test_shuffle() { + let r = rng(); let empty: ~[int] = ~[]; assert!(r.shuffle(~[]) == empty); assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); } #[test] - fn task_rng() { - let r = rand::task_rng(); - r.gen_int(); - assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); - assert!(r.gen_uint_range(0u, 1u) == 0u); + fn test_task_rng() { + let r = task_rng(); + (*r).gen_int(); + assert!((*r).shuffle(~[1, 1, 1]) == ~[1, 1, 1]); + assert!((*r).gen_uint_range(0u, 1u) == 0u); } #[test] - fn random() { + fn test_random() { // not sure how to test this aside from just getting some values - let _n : uint = rand::random(); - let _f : f32 = rand::random(); - let _o : Option> = rand::random(); + let _n : uint = random(); + let _f : f32 = random(); + let _o : Option> = random(); let _many : ((), (~uint, @int, ~Option<~(@char, ~(@bool,))>), (u8, i8, u16, i16, u32, i32, u64, i64), - (f32, (f64, (float,)))) = rand::random(); + (f32, (f64, (float,)))) = random(); } } diff --git a/src/libcore/unstable/at_exit.rs b/src/libcore/unstable/at_exit.rs index 83f0c3695e82f..bc4ec620aa86a 100644 --- a/src/libcore/unstable/at_exit.rs +++ b/src/libcore/unstable/at_exit.rs @@ -62,7 +62,7 @@ fn exit_runner(exit_fns: *ExitFunctions) { // give us ownership of the array of functions let mut exit_fns_vec = unsafe { vec::from_buf(start, count as uint) }; // Let's not make any promises about execution order - rand::Rng().shuffle_mut(exit_fns_vec); + rand::rng().shuffle_mut(exit_fns_vec); debug!("running %u exit functions", exit_fns_vec.len()); diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index 140d9ced5808d..b35b9face2a8f 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -78,7 +78,7 @@ mod test { // Helper function to create a directory name that doesn't exist pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { - let r = rand::Rng(); + let r = rand::rng(); for 1000.times { let p = tmpdir.push(r.gen_str(16) + suffix); if !os::path_exists(&p) { diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index d1f6bf982a7ff..5f4d507568a10 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -876,6 +876,7 @@ mod tests { use core::uint; use core::vec; use core::rand; + use core::rand::Rng; static bench_bits : uint = 1 << 14; @@ -1424,9 +1425,9 @@ mod tests { assert!(a.capacity() == uint::bits); } - fn rng() -> @rand::Rng { + fn rng() -> rand::RandRes { let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::seeded_rng(seed) + rand::IsaacRng::new_seeded(seed) } #[bench] diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index febaea637efe1..be32fb2565755 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -915,7 +915,7 @@ mod test_tim_sort { impl Ord for CVal { fn lt(&self, other: &CVal) -> bool { - let rng = rand::Rng(); + let rng = rand::rng(); if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); } (*self).val < other.val } @@ -964,7 +964,7 @@ mod test_tim_sort { #[should_fail] #[cfg(unix)] fn crash_test() { - let rng = rand::Rng(); + let rng = rand::rng(); let mut arr = do vec::from_fn(1000) |_i| { let randVal = rng.gen_float(); CVal { val: randVal } @@ -985,7 +985,7 @@ mod test_tim_sort { #[test] fn test_bad_Ord_impl() { - let rng = rand::Rng(); + let rng = rand::rng(); let mut arr = do vec::from_fn(500) |_i| { let randVal = rng.gen_uint(); DVal { val: randVal } @@ -1045,7 +1045,7 @@ mod big_tests { } } - let rng = rand::Rng(); + let rng = rand::rng(); for uint::range(lo, hi) |i| { let n = 1 << i; @@ -1117,7 +1117,7 @@ mod big_tests { } } - let rng = rand::Rng(); + let rng = rand::rng(); for uint::range(lo, hi) |i| { let n = 1 << i; diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs index 895ccbc820b16..b92e652b7af9b 100644 --- a/src/libstd/tempfile.rs +++ b/src/libstd/tempfile.rs @@ -16,7 +16,7 @@ use core::rand::RngUtil; use core::rand; pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { - let r = rand::Rng(); + let r = rand::rng(); for 1000.times { let p = tmpdir.push(r.gen_str(16) + suffix); if os::make_dir(&p, 0x1c0) { // 700 diff --git a/src/libstd/test.rs b/src/libstd/test.rs index addc1da6394ee..113d66b30204d 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -705,7 +705,7 @@ pub mod bench { // not met, it may run as long as the Go algorithm. pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] { - let rng = rand::Rng(); + let rng = rand::rng(); let mut magnitude = 10; let mut prev_madp = 0.0; diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index e862fe6077cb6..f0daf407073af 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -220,7 +220,7 @@ mod test { let hl_loop_clone = hl_loop.clone(); do task::spawn { use core::rand::*; - let rng = Rng(); + let rng = rng(); for iter::repeat(times) { sleep(&hl_loop_clone, rng.next() as uint % maxms); } @@ -277,7 +277,7 @@ mod test { let hl_loop = uv::global_loop::get(); for iter::repeat(times as uint) { - let expected = rand::Rng().gen_str(16u); + let expected = rand::rng().gen_str(16u); let (test_po, test_ch) = stream::<~str>(); let hl_loop_clone = hl_loop.clone(); do task::spawn() { diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index ac887c7fdc41d..dbb01b6ce397b 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -835,7 +835,7 @@ mod test_treemap { check_equal(ctrl, &map); assert!(map.find(&5).is_none()); - let rng = rand::seeded_rng(&[42]); + let rng = rand::IsaacRng::new_seeded(&[42]); for 3.times { for 90.times { diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index b75aa3c909b96..0c53ccd46e8b7 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -102,7 +102,7 @@ fn main() { let mut rand = vec::with_capacity(n_keys); { - let rng = core::rand::seeded_rng([1, 1, 1, 1, 1, 1, 1]); + let rng = core::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]); let mut set = HashSet::new(); while set.len() != n_keys { let next = rng.next() as uint; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 5f8f13896fb95..2ed3f668684d8 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -32,7 +32,7 @@ fn timed(result: &mut float, op: &fn()) { } pub impl Results { - fn bench_int>(&mut self, rng: @rand::Rng, num_keys: uint, + fn bench_int>(&mut self, rng: &rand::Rng, num_keys: uint, rand_cap: uint, f: &fn() -> T) { { let mut set = f(); @@ -70,7 +70,7 @@ pub impl Results { } } - fn bench_str>(&mut self, rng: @rand::Rng, num_keys: uint, + fn bench_str>(&mut self, rng: &rand::Rng, num_keys: uint, f: &fn() -> T) { { let mut set = f(); @@ -156,15 +156,15 @@ fn main() { let max = 200000; { - let rng = rand::seeded_rng(seed); + let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || HashSet::new::()); - results.bench_str(rng, num_keys, || HashSet::new::<~str>()); + results.bench_int(&rng, num_keys, max, || HashSet::new::()); + results.bench_str(&rng, num_keys, || HashSet::new::<~str>()); write_results("core::hashmap::HashSet", &results); } { - let rng = rand::seeded_rng(seed); + let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); results.bench_int(rng, num_keys, max, || TreeSet::new::()); results.bench_str(rng, num_keys, || TreeSet::new::<~str>()); @@ -172,7 +172,7 @@ fn main() { } { - let rng = rand::seeded_rng(seed); + let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); results.bench_int(rng, num_keys, max, || BitvSet::new()); write_results("std::bitv::BitvSet", &results); diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 0a68d29ac560e..8438759b5c8d3 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -71,7 +71,7 @@ fn read_line() { } fn vec_plus() { - let r = rand::Rng(); + let r = rand::rng(); let mut v = ~[]; let mut i = 0; @@ -88,7 +88,7 @@ fn vec_plus() { } fn vec_append() { - let r = rand::Rng(); + let r = rand::rng(); let mut v = ~[]; let mut i = 0; @@ -105,7 +105,7 @@ fn vec_append() { } fn vec_push_all() { - let r = rand::Rng(); + let r = rand::rng(); let mut v = ~[]; for uint::range(0, 1500) |i| { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index 396ea08136281..e84d8abf9790c 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -34,9 +34,9 @@ type graph = ~[~[node_id]]; type bfs_result = ~[node_id]; fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] { - let r = rand::xorshift(); + let r = rand::XorShiftRng::new(); - fn choose_edge(i: node_id, j: node_id, scale: uint, r: @rand::Rng) + fn choose_edge(i: node_id, j: node_id, scale: uint, r: &R) -> (node_id, node_id) { let A = 0.57; @@ -75,7 +75,7 @@ fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] { } do vec::from_fn((1u << scale) * edgefactor) |_i| { - choose_edge(0i64, 0i64, scale, r) + choose_edge(0i64, 0i64, scale, &r) } } @@ -105,7 +105,7 @@ fn make_graph(N: uint, edges: ~[(node_id, node_id)]) -> graph { fn gen_search_keys(graph: &[~[node_id]], n: uint) -> ~[node_id] { let mut keys = HashSet::new(); - let r = rand::Rng(); + let r = rand::rng(); while keys.len() < n { let k = r.gen_uint_range(0u, graph.len()); diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 4397dcd5247f5..e032274482a02 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -13,7 +13,7 @@ fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } #[inline(always)] fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } -fn random_gradient(r: @Rng) -> Vec2 { +fn random_gradient(r: &Rng) -> Vec2 { let v = r.gen_float() * float::consts::pi * 2.0; Vec2 { x: float::cos(v) as f32, @@ -33,9 +33,9 @@ struct Noise2DContext { pub impl Noise2DContext { fn new() -> Noise2DContext { - let r = rand::Rng(); + let r = rand::rng(); let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; - for int::range(0, 256) |i| { rgradients[i] = random_gradient(r); } + for int::range(0, 256) |i| { rgradients[i] = random_gradient(&r); } let mut permutations = [ 0, ..256 ]; for int::range(0, 256) |i| { permutations[i] = i; } r.shuffle_mut(permutations); diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 8c371150e1ea2..83e1a958d3ca8 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -63,7 +63,7 @@ fn make_random_fasta(wr: @io::Writer, genelist: ~[AminoAcids], n: int) { wr.write_line(~">" + id + ~" " + desc); - let rng = @mut MyRandom {last: rand::Rng().next()}; + let rng = @mut MyRandom {last: rand::rng().next()}; let mut op: ~str = ~""; for uint::range(0u, n as uint) |_i| { str::push_char(&mut op, select_random(myrandom_next(rng, 100u32), diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs index 7e0b4b47846e0..1f908936aef47 100644 --- a/src/test/run-pass/morestack6.rs +++ b/src/test/run-pass/morestack6.rs @@ -54,6 +54,7 @@ fn runtest2(f: extern fn(), frame_backoff: u32, last_stk: *u8) -> u32 { } pub fn main() { + use core::rand::Rng; let fns = ~[ calllink01, calllink02, @@ -61,7 +62,7 @@ pub fn main() { calllink09, calllink10 ]; - let rng = rand::Rng(); + let rng = rand::rng(); for fns.each |f| { let f = *f; let sz = rng.next() % 256u32 + 256u32; From 7b009210c66d6b62ca6be123b752b464f8f178e5 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 24 Apr 2013 00:16:48 +1000 Subject: [PATCH 380/403] libcore: convert the Program @-object to be a plain struct + impl. Removes the dynamic @ indirection, and also converts the functions acting on `ProgRepr`s to methods. --- src/libcore/run.rs | 218 +++++++++++++++++++++------------------------ 1 file changed, 104 insertions(+), 114 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 2455954ebe128..e7df95e20c80b 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -47,28 +47,117 @@ pub struct RunProgramResult { handle: *(), } +struct ProgRepr { + pid: pid_t, + handle: *(), + in_fd: c_int, + out_file: *libc::FILE, + err_file: *libc::FILE, + finished: bool, +} + +impl ProgRepr { + fn close_input(&mut self) { + let invalid_fd = -1i32; + if self.in_fd != invalid_fd { + unsafe { + libc::close(self.in_fd); + } + self.in_fd = invalid_fd; + } + } + + fn close_outputs(&mut self) { + unsafe { + fclose_and_null(&mut self.out_file); + fclose_and_null(&mut self.err_file); + } + } + + fn finish(&mut self) -> int { + if self.finished { return 0; } + self.finished = true; + self.close_input(); + return waitpid(self.pid); + } + + fn destroy(&mut self, force: bool) { + killpid(self.pid, force); + self.finish(); + self.close_outputs(); + + #[cfg(windows)] + fn killpid(pid: pid_t, _force: bool) { + unsafe { + libc::funcs::extra::kernel32::TerminateProcess( + cast::transmute(pid), 1); + } + } + + #[cfg(unix)] + fn killpid(pid: pid_t, force: bool) { + let signal = if force { + libc::consts::os::posix88::SIGKILL + } else { + libc::consts::os::posix88::SIGTERM + }; + + unsafe { + libc::funcs::posix88::signal::kill(pid, signal as c_int); + } + } + } +} + /// A value representing a child process -pub trait Program { +pub struct Program { + priv r: ProgRepr, +} + +impl Drop for Program { + fn finalize(&self) { + // FIXME #4943: transmute is bad. + let selfr: &mut ProgRepr = unsafe { cast::transmute(&self.r) }; + + selfr.finish(); + selfr.close_outputs(); + free_handle(self.r.handle); + } +} + +pub impl Program { + priv fn new(r: ProgRepr) -> Program { + Program { + r: r + } + } + /// Returns the process id of the program - fn get_id(&mut self) -> pid_t; + fn get_id(&mut self) -> pid_t { self.r.pid } /// Returns an io::Writer that can be used to write to stdin - fn input(&mut self) -> @io::Writer; + fn input(&mut self) -> @io::Writer { + io::fd_writer(self.r.in_fd, false) + } /// Returns an io::Reader that can be used to read from stdout - fn output(&mut self) -> @io::Reader; + fn output(&mut self) -> @io::Reader { + io::FILE_reader(self.r.out_file, false) + } /// Returns an io::Reader that can be used to read from stderr - fn err(&mut self) -> @io::Reader; + fn err(&mut self) -> @io::Reader { + io::FILE_reader(self.r.err_file, false) + } /// Closes the handle to the child processes standard input - fn close_input(&mut self); + fn close_input(&mut self) { self.r.close_input(); } /** * Waits for the child process to terminate. Closes the handle * to stdin if necessary. */ - fn finish(&mut self) -> int; + fn finish(&mut self) -> int { self.r.finish() } /** * Terminate the program, giving it a chance to clean itself up if @@ -77,7 +166,7 @@ pub trait Program { * On Posix OSs SIGTERM will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - fn destroy(&mut self); + fn destroy(&mut self) { self.r.destroy(false); } /** * Terminate the program as soon as possible without giving it a @@ -86,7 +175,7 @@ pub trait Program { * On Posix OSs SIGKILL will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - fn force_destroy(&mut self); + fn force_destroy(&mut self) { self.r.destroy(true); } } @@ -248,9 +337,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int { /** * Spawns a process and returns a Program * - * The returned value is a boxed class containing a object that can - * be used for sending and receiving data over the standard file descriptors. - * The class will ensure that file descriptors are closed properly. + * The returned value is a object that can be used for sending and + * receiving data over the standard file descriptors. The class will ensure + * that file descriptors are closed properly. * * # Arguments * @@ -259,9 +348,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int { * * # Return value * - * A class with a field + * A object */ -pub fn start_program(prog: &str, args: &[~str]) -> @Program { +pub fn start_program(prog: &str, args: &[~str]) -> Program { let pipe_input = os::pipe(); let pipe_output = os::pipe(); let pipe_err = os::pipe(); @@ -277,105 +366,6 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { libc::close(pipe_err.out); } - struct ProgRepr { - pid: pid_t, - handle: *(), - in_fd: c_int, - out_file: *libc::FILE, - err_file: *libc::FILE, - finished: bool, - } - - fn close_repr_input(r: &mut ProgRepr) { - let invalid_fd = -1i32; - if r.in_fd != invalid_fd { - unsafe { - libc::close(r.in_fd); - } - r.in_fd = invalid_fd; - } - } - - fn close_repr_outputs(r: &mut ProgRepr) { - unsafe { - fclose_and_null(&mut r.out_file); - fclose_and_null(&mut r.err_file); - } - } - - fn finish_repr(r: &mut ProgRepr) -> int { - if r.finished { return 0; } - r.finished = true; - close_repr_input(&mut *r); - return waitpid(r.pid); - } - - fn destroy_repr(r: &mut ProgRepr, force: bool) { - killpid(r.pid, force); - finish_repr(&mut *r); - close_repr_outputs(&mut *r); - - #[cfg(windows)] - fn killpid(pid: pid_t, _force: bool) { - unsafe { - libc::funcs::extra::kernel32::TerminateProcess( - cast::transmute(pid), 1); - } - } - - #[cfg(unix)] - fn killpid(pid: pid_t, force: bool) { - - let signal = if force { - libc::consts::os::posix88::SIGKILL - } else { - libc::consts::os::posix88::SIGTERM - }; - - unsafe { - libc::funcs::posix88::signal::kill(pid, signal as c_int); - } - } - } - - struct ProgRes { - r: ProgRepr, - } - - impl Drop for ProgRes { - fn finalize(&self) { - unsafe { - // FIXME #4943: transmute is bad. - finish_repr(cast::transmute(&self.r)); - close_repr_outputs(cast::transmute(&self.r)); - } - free_handle(self.r.handle); - } - } - - fn ProgRes(r: ProgRepr) -> ProgRes { - ProgRes { - r: r - } - } - - impl Program for ProgRes { - fn get_id(&mut self) -> pid_t { return self.r.pid; } - fn input(&mut self) -> @io::Writer { - io::fd_writer(self.r.in_fd, false) - } - fn output(&mut self) -> @io::Reader { - io::FILE_reader(self.r.out_file, false) - } - fn err(&mut self) -> @io::Reader { - io::FILE_reader(self.r.err_file, false) - } - fn close_input(&mut self) { close_repr_input(&mut self.r); } - fn finish(&mut self) -> int { finish_repr(&mut self.r) } - fn destroy(&mut self) { destroy_repr(&mut self.r, false); } - fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); } - } - let repr = ProgRepr { pid: res.pid, handle: res.handle, @@ -385,7 +375,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { finished: false, }; - @ProgRes(repr) as @Program + Program::new(repr) } fn read_all(rd: @io::Reader) -> ~str { From 4a24f10ac6f155699f086051ba6a728d9afb5ca6 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 24 Apr 2013 22:29:19 +1000 Subject: [PATCH 381/403] libcore: unify `gen_` methods on `rand::RngUtil` into the generic `gen`. This moves all the basic random value generation into the Rand instances for each type and then removes the `gen_int`, `gen_char` (etc) methods on RngUtil, leaving only the generic `gen` and the more specialised methods. Also, removes some imports that are redundant due to a `use core::prelude::*` statement. --- src/libcore/hashmap.rs | 2 +- src/libcore/rand.rs | 253 +++++++++---------------------- src/librustpkg/path_util.rs | 2 +- src/libstd/bitv.rs | 2 +- src/libstd/sort.rs | 35 ++--- src/libstd/tempfile.rs | 2 - src/libstd/test.rs | 17 +-- src/libstd/timer.rs | 4 - src/libstd/treemap.rs | 5 +- src/test/bench/core-map.rs | 1 + src/test/bench/core-set.rs | 13 +- src/test/bench/core-std.rs | 8 +- src/test/bench/graph500-bfs.rs | 3 +- src/test/bench/noise.rs | 4 +- src/test/bench/shootout-fasta.rs | 2 +- 15 files changed, 106 insertions(+), 247 deletions(-) diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 3233207b8bd6a..d2be0416371be 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -56,7 +56,7 @@ fn resize_at(capacity: uint) -> uint { pub fn linear_map_with_capacity( initial_capacity: uint) -> HashMap { let r = rand::task_rng(); - linear_map_with_capacity_and_keys((*r).gen_u64(), (*r).gen_u64(), + linear_map_with_capacity_and_keys(r.gen(), r.gen(), initial_capacity) } diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 86509c81eb34d..367278f66f321 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -8,7 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Random number generation +/*! +Random number generation. + +The key functions are `random()` and `RngUtil::gen()`. These are polymorphic +and so can be used to generate any type that implements `Rand`. Type inference +means that often a simple call to `rand::random()` or `rng.gen()` will +suffice, but sometimes an annotation is required, e.g. `rand::random::()`. + +# Examples +~~~ +use core::rand::RngUtil; + +fn main() { + let rng = rand::rng(); + if rng.gen() { // bool + println(fmt!("int: %d, uint: %u", rng.gen(), rng.gen())) + } +} +~~~ + +~~~ +fn main () { + let tuple_ptr = rand::random::<~(f64, char)>(); + println(fmt!("%?", tuple_ptr)) +} +~~~ +*/ + use int; use prelude::*; @@ -20,98 +47,111 @@ use util; use vec; use libc::size_t; -/// A type that can be randomly generated using an RNG +/// A type that can be randomly generated using an Rng pub trait Rand { fn rand(rng: &R) -> Self; } impl Rand for int { fn rand(rng: &R) -> int { - rng.gen_int() + if int::bits == 32 { + rng.next() as int + } else { + rng.gen::() as int + } } } impl Rand for i8 { fn rand(rng: &R) -> i8 { - rng.gen_i8() + rng.next() as i8 } } impl Rand for i16 { fn rand(rng: &R) -> i16 { - rng.gen_i16() + rng.next() as i16 } } impl Rand for i32 { fn rand(rng: &R) -> i32 { - rng.gen_i32() + rng.next() as i32 } } impl Rand for i64 { fn rand(rng: &R) -> i64 { - rng.gen_i64() + (rng.next() as i64 << 32) | rng.next() as i64 } } impl Rand for uint { fn rand(rng: &R) -> uint { - rng.gen_uint() + if uint::bits == 32 { + rng.next() as uint + } else { + rng.gen::() as uint + } } } impl Rand for u8 { fn rand(rng: &R) -> u8 { - rng.gen_u8() + rng.next() as u8 } } impl Rand for u16 { fn rand(rng: &R) -> u16 { - rng.gen_u16() + rng.next() as u16 } } impl Rand for u32 { fn rand(rng: &R) -> u32 { - rng.gen_u32() + rng.next() } } impl Rand for u64 { fn rand(rng: &R) -> u64 { - rng.gen_u64() + (rng.next() as u64 << 32) | rng.next() as u64 } } impl Rand for float { fn rand(rng: &R) -> float { - rng.gen_float() + rng.gen::() as float } } impl Rand for f32 { fn rand(rng: &R) -> f32 { - rng.gen_f32() + rng.gen::() as f32 } } +static scale : f64 = (u32::max_value as f64) + 1.0f64; impl Rand for f64 { fn rand(rng: &R) -> f64 { - rng.gen_f64() + let u1 = rng.next() as f64; + let u2 = rng.next() as f64; + let u3 = rng.next() as f64; + + ((u1 / scale + u2) / scale + u3) / scale } } impl Rand for char { fn rand(rng: &R) -> char { - rng.gen_char() + rng.next() as char } } impl Rand for bool { fn rand(rng: &R) -> bool { - rng.gen_bool() + rng.next() & 1u32 == 1u32 } } @@ -151,7 +191,7 @@ tuple_impl!{A, B, C, D, E, F, G, H, I, J} impl Rand for Option { fn rand(rng: &R) -> Option { - if rng.gen_bool() { + if rng.gen() { Some(rng.gen()) } else { None @@ -195,93 +235,24 @@ pub struct Weighted { weight: uint, item: T, } -// this should be in gen_f64, but it causes an ICE there. -static scale : f64 = (u32::max_value as f64) + 1.0f64; + pub trait RngUtil { /// Return a random value of a Rand type fn gen(&self) -> T; /** - * Return a random int - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%d",rng.gen_int())); - * } - * ~~~ + * Return a int randomly chosen from the range [start, end), + * failing if start >= end */ - fn gen_int(&self) -> int; fn gen_int_range(&self, start: int, end: int) -> int; - /// Return a random i8 - fn gen_i8(&self) -> i8; - /// Return a random i16 - fn gen_i16(&self) -> i16; - /// Return a random i32 - fn gen_i32(&self) -> i32; - /// Return a random i64 - fn gen_i64(&self) -> i64; - /// Return a random uint - fn gen_uint(&self) -> uint; /** * Return a uint randomly chosen from the range [start, end), * failing if start >= end */ fn gen_uint_range(&self, start: uint, end: uint) -> uint; - /// Return a random u8 - fn gen_u8(&self) -> u8; - /// Return a random u16 - fn gen_u16(&self) -> u16; - /// Return a random u32 - fn gen_u32(&self) -> u32; - /// Return a random u64 - fn gen_u64(&self) -> u64; - /** - * Return random float in the interval [0,1] - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%f",rng.gen_float())); - * } - * ~~~ - */ - fn gen_float(&self) -> float; - /// Return a random f32 in the interval [0,1] - fn gen_f32(&self) -> f32; - /// Return a random f64 in the interval [0,1] - fn gen_f64(&self) -> f64; - /// Return a random char - fn gen_char(&self) -> char; /** * Return a char randomly chosen from chars, failing if chars is empty */ fn gen_char_from(&self, chars: &str) -> char; - /** - * Return a random bool - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%b",rng.gen_bool())); - * } - * ~~~ - */ - fn gen_bool(&self) -> bool; /** * Return a bool with a 1 in n chance of true * @@ -453,43 +424,13 @@ impl RngUtil for R { Rand::rand(self) } - /// Return a random int - fn gen_int(&self) -> int { - self.gen_i64() as int - } - /** * Return an int randomly chosen from the range [start, end), * failing if start >= end */ fn gen_int_range(&self, start: int, end: int) -> int { assert!(start < end); - start + int::abs(self.gen_int() % (end - start)) - } - - /// Return a random i8 - fn gen_i8(&self) -> i8 { - self.next() as i8 - } - - /// Return a random i16 - fn gen_i16(&self) -> i16 { - self.next() as i16 - } - - /// Return a random i32 - fn gen_i32(&self) -> i32 { - self.next() as i32 - } - - /// Return a random i64 - fn gen_i64(&self) -> i64 { - (self.next() as i64 << 32) | self.next() as i64 - } - - /// Return a random uint - fn gen_uint(&self) -> uint { - self.gen_u64() as uint + start + int::abs(self.gen::() % (end - start)) } /** @@ -498,51 +439,7 @@ impl RngUtil for R { */ fn gen_uint_range(&self, start: uint, end: uint) -> uint { assert!(start < end); - start + (self.gen_uint() % (end - start)) - } - - /// Return a random u8 - fn gen_u8(&self) -> u8 { - self.next() as u8 - } - - /// Return a random u16 - fn gen_u16(&self) -> u16 { - self.next() as u16 - } - - /// Return a random u32 - fn gen_u32(&self) -> u32 { - self.next() - } - - /// Return a random u64 - fn gen_u64(&self) -> u64 { - (self.next() as u64 << 32) | self.next() as u64 - } - - /// Return a random float in the interval [0,1] - fn gen_float(&self) -> float { - self.gen_f64() as float - } - - /// Return a random f32 in the interval [0,1] - fn gen_f32(&self) -> f32 { - self.gen_f64() as f32 - } - - /// Return a random f64 in the interval [0,1] - fn gen_f64(&self) -> f64 { - let u1 = self.next() as f64; - let u2 = self.next() as f64; - let u3 = self.next() as f64; - - return ((u1 / scale + u2) / scale + u3) / scale; - } - - /// Return a random char - fn gen_char(&self) -> char { - self.next() as char + start + (self.gen::() % (end - start)) } /** @@ -555,11 +452,6 @@ impl RngUtil for R { self.choose(cs) } - /// Return a random bool - fn gen_bool(&self) -> bool { - self.next() & 1u32 == 1u32 - } - /// Return a bool with a 1-in-n chance of true fn gen_weighted_bool(&self, n: uint) -> bool { if n == 0u { @@ -588,7 +480,7 @@ impl RngUtil for R { /// Return a random byte string of the specified length fn gen_bytes(&self, len: uint) -> ~[u8] { do vec::from_fn(len) |_i| { - self.gen_u8() + self.gen() } } @@ -777,7 +669,7 @@ fn tls_rng_state(_v: @IsaacRng) {} /** * Gives back a lazily initialized task-local random number generator, * seeded by the system. Intended to be used in method chaining style, ie - * task_rng().gen_int(). + * `task_rng().gen::()`. */ pub fn task_rng() -> @IsaacRng { let r : Option<@IsaacRng>; @@ -796,6 +688,11 @@ pub fn task_rng() -> @IsaacRng { } } +// Allow direct chaining with `task_rng` +impl Rng for @R { + fn next(&self) -> u32 { (*self).next() } +} + /** * Returns a random value of a Rand type, using the task's random number * generator. @@ -872,8 +769,8 @@ mod tests { #[test] fn test_gen_float() { let r = rng(); - let a = r.gen_float(); - let b = r.gen_float(); + let a = r.gen::(); + let b = r.gen::(); debug!((a, b)); } @@ -966,9 +863,9 @@ mod tests { #[test] fn test_task_rng() { let r = task_rng(); - (*r).gen_int(); - assert!((*r).shuffle(~[1, 1, 1]) == ~[1, 1, 1]); - assert!((*r).gen_uint_range(0u, 1u) == 0u); + r.gen::(); + assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); + assert!(r.gen_uint_range(0u, 1u) == 0u); } #[test] diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index b35b9face2a8f..cd9b44c278e46 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -73,8 +73,8 @@ pub fn normalize(p: ~Path) -> ~Path { mod test { use core::{os, rand}; use core::path::Path; - use core::rand::RngUtil; use path_util::*; + use core::rand::RngUtil; // Helper function to create a directory name that doesn't exist pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 5f4d507568a10..8bfa201395069 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -1425,7 +1425,7 @@ mod tests { assert!(a.capacity() == uint::bits); } - fn rng() -> rand::RandRes { + fn rng() -> rand::IsaacRng { let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; rand::IsaacRng::new_seeded(seed) } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index be32fb2565755..db6efdf3f52aa 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -902,12 +902,8 @@ mod tests { #[cfg(test)] mod test_tim_sort { use core::prelude::*; - use sort::tim_sort; - use core::rand::RngUtil; - use core::rand; - use core::vec; struct CVal { val: float, @@ -916,7 +912,7 @@ mod test_tim_sort { impl Ord for CVal { fn lt(&self, other: &CVal) -> bool { let rng = rand::rng(); - if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); } + if rng.gen::() > 0.995 { fail!(~"It's happening!!!"); } (*self).val < other.val } fn le(&self, other: &CVal) -> bool { (*self).val <= other.val } @@ -966,8 +962,7 @@ mod test_tim_sort { fn crash_test() { let rng = rand::rng(); let mut arr = do vec::from_fn(1000) |_i| { - let randVal = rng.gen_float(); - CVal { val: randVal } + CVal { val: rng.gen() } }; tim_sort(arr); @@ -987,8 +982,7 @@ mod test_tim_sort { fn test_bad_Ord_impl() { let rng = rand::rng(); let mut arr = do vec::from_fn(500) |_i| { - let randVal = rng.gen_uint(); - DVal { val: randVal } + DVal { val: rng.gen() } }; tim_sort(arr); @@ -998,14 +992,8 @@ mod test_tim_sort { #[cfg(test)] mod big_tests { use core::prelude::*; - use sort::*; - use core::rand::RngUtil; - use core::rand; - use core::task; - use core::uint; - use core::vec; #[test] fn test_unique() { @@ -1049,10 +1037,9 @@ mod big_tests { for uint::range(lo, hi) |i| { let n = 1 << i; - let arr = do vec::from_fn(n) |_i| { - rng.gen_float() + let mut arr: ~[float] = do vec::from_fn(n) |_i| { + rng.gen() }; - let mut arr = arr; tim_sort(arr); // *sort isSorted(arr); @@ -1076,7 +1063,7 @@ mod big_tests { let size = arr.len(); let mut idx = 1; while idx <= 10 { - arr[size-idx] = rng.gen_float(); + arr[size-idx] = rng.gen(); idx += 1; } } @@ -1085,7 +1072,7 @@ mod big_tests { for (n/100).times { let idx = rng.gen_uint_range(0, n); - arr[idx] = rng.gen_float(); + arr[idx] = rng.gen(); } tim_sort(arr); isSorted(arr); @@ -1121,8 +1108,8 @@ mod big_tests { for uint::range(lo, hi) |i| { let n = 1 << i; - let arr = do vec::from_fn(n) |_i| { - @rng.gen_float() + let arr: ~[@float] = do vec::from_fn(n) |_i| { + @rng.gen() }; let mut arr = arr; @@ -1148,7 +1135,7 @@ mod big_tests { let size = arr.len(); let mut idx = 1; while idx <= 10 { - arr[size-idx] = @rng.gen_float(); + arr[size-idx] = @rng.gen(); idx += 1; } } @@ -1157,7 +1144,7 @@ mod big_tests { for (n/100).times { let idx = rng.gen_uint_range(0, n); - arr[idx] = @rng.gen_float(); + arr[idx] = @rng.gen(); } tim_sort(arr); isSorted(arr); diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs index b92e652b7af9b..c9bcb3b8952be 100644 --- a/src/libstd/tempfile.rs +++ b/src/libstd/tempfile.rs @@ -10,10 +10,8 @@ //! Temporary files and directories -use core::os; use core::prelude::*; use core::rand::RngUtil; -use core::rand; pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { let r = rand::rng(); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 113d66b30204d..f82cc25e0f618 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -19,20 +19,9 @@ use getopts; use sort; use term; -use core::cmp::Eq; - use core::to_str::ToStr; -use core::either::Either; -use core::either; -use core::io::WriterUtil; -use core::io; use core::comm::{stream, SharedChan}; -use core::option; use core::prelude::*; -use core::result; -use core::str; -use core::task; -use core::vec; pub mod rustrt { use core::libc::size_t; @@ -608,12 +597,8 @@ pub mod bench { use time::precise_time_ns; use test::{BenchHarness, BenchSamples}; use stats::Stats; - - use core::num; + use core::prelude::*; use core::rand::RngUtil; - use core::rand; - use core::u64; - use core::vec; pub impl BenchHarness { diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index f0daf407073af..1e48ce5aa6f2e 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -175,11 +175,7 @@ mod test { use timer::*; use uv; - - use core::iter; use core::rand::RngUtil; - use core::rand; - use core::task; use core::pipes::{stream, SharedChan}; #[test] diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index dbb01b6ce397b..020f4daefd9d6 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -698,7 +698,6 @@ mod test_treemap { use core::iterator::*; use super::*; use core::rand::RngUtil; - use core::rand; #[test] fn find_empty() { @@ -839,8 +838,8 @@ mod test_treemap { for 3.times { for 90.times { - let k = rng.gen_int(); - let v = rng.gen_int(); + let k = rng.gen(); + let v = rng.gen(); if !ctrl.contains(&(k, v)) { assert!(map.insert(k, v)); ctrl.push((k, v)); diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 0c53ccd46e8b7..e216215ace7f9 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -15,6 +15,7 @@ use std::time; use std::treemap::TreeMap; use core::hashmap::{HashMap, HashSet}; use core::trie::TrieMap; +use core::rand::Rng; fn timed(label: &str, f: &fn()) { let start = time::precise_time_s(); diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 2ed3f668684d8..b3e3d295c0fad 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -12,7 +12,6 @@ extern mod std; use core::hashmap::HashSet; use std::bitv::BitvSet; use std::treemap::TreeSet; -use core::io::WriterUtil; struct Results { sequential_ints: float, @@ -32,7 +31,7 @@ fn timed(result: &mut float, op: &fn()) { } pub impl Results { - fn bench_int>(&mut self, rng: &rand::Rng, num_keys: uint, + fn bench_int, R: rand::Rng>(&mut self, rng: &R, num_keys: uint, rand_cap: uint, f: &fn() -> T) { { let mut set = f(); @@ -70,8 +69,8 @@ pub impl Results { } } - fn bench_str>(&mut self, rng: &rand::Rng, num_keys: uint, - f: &fn() -> T) { + fn bench_str, R: rand::Rng>(&mut self, rng: &R, num_keys: uint, + f: &fn() -> T) { { let mut set = f(); do timed(&mut self.sequential_strings) { @@ -166,15 +165,15 @@ fn main() { { let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || TreeSet::new::()); - results.bench_str(rng, num_keys, || TreeSet::new::<~str>()); + results.bench_int(&rng, num_keys, max, || TreeSet::new::()); + results.bench_str(&rng, num_keys, || TreeSet::new::<~str>()); write_results("std::treemap::TreeSet", &results); } { let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || BitvSet::new()); + results.bench_int(&rng, num_keys, max, || BitvSet::new()); write_results("std::bitv::BitvSet", &results); } } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 8438759b5c8d3..1af3538a0219d 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -13,8 +13,6 @@ extern mod std; use std::time::precise_time_s; - -use core::io::{Reader, ReaderUtil}; use core::rand::RngUtil; macro_rules! bench ( @@ -77,7 +75,7 @@ fn vec_plus() { let mut i = 0; while i < 1500 { let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v += rv; } else { @@ -94,7 +92,7 @@ fn vec_append() { let mut i = 0; while i < 1500 { let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v = vec::append(v, rv); } else { @@ -110,7 +108,7 @@ fn vec_push_all() { let mut v = ~[]; for uint::range(0, 1500) |i| { let mut rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v.push_all(rv); } else { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index e84d8abf9790c..bd3de4a1b8aba 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -25,7 +25,6 @@ use std::time; use std::deque::Deque; use std::par; use core::hashmap::{HashMap, HashSet}; -use core::io::WriterUtil; use core::int::abs; use core::rand::RngUtil; @@ -51,7 +50,7 @@ fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] { let j = j * 2i64; let scale = scale - 1u; - let x = r.gen_float(); + let x = r.gen::(); if x < A { choose_edge(i, j, scale, r) diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index e032274482a02..0da3a2e5d68d0 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -13,8 +13,8 @@ fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } #[inline(always)] fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } -fn random_gradient(r: &Rng) -> Vec2 { - let v = r.gen_float() * float::consts::pi * 2.0; +fn random_gradient(r: &R) -> Vec2 { + let v = 2.0 * float::consts::pi * r.gen(); Vec2 { x: float::cos(v) as f32, y: float::sin(v) as f32, diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 83e1a958d3ca8..0fcf8341ac852 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -16,7 +16,7 @@ * http://shootout.alioth.debian.org/ */ extern mod std; -use core::io::WriterUtil; +use core::rand::Rng; fn LINE_LENGTH() -> uint { return 60u; } From 9860fe10a19cc4997e58861df905f8dbe4de3c5b Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Wed, 24 Apr 2013 23:03:04 +1000 Subject: [PATCH 382/403] libcore: remove unnecessary deref --- src/libcore/rand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 367278f66f321..cdf6a5bb63ded 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -698,7 +698,7 @@ impl Rng for @R { * generator. */ pub fn random() -> T { - (*task_rng()).gen() + task_rng().gen() } #[cfg(test)] From 345d5b82351f4f8309498aa34b9f0348b898300d Mon Sep 17 00:00:00 2001 From: gareth Date: Wed, 24 Apr 2013 21:06:26 +0100 Subject: [PATCH 383/403] Refactor core::run to remove the ProgRepr struct, which was a legacy from the time when destructors were implemented using resource types. --- src/libcore/run.rs | 117 +++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 67 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index e7df95e20c80b..37401788ca2d1 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -47,16 +47,48 @@ pub struct RunProgramResult { handle: *(), } -struct ProgRepr { - pid: pid_t, - handle: *(), - in_fd: c_int, - out_file: *libc::FILE, - err_file: *libc::FILE, - finished: bool, +/// A value representing a child process +pub struct Program { + priv pid: pid_t, + priv handle: *(), + priv in_fd: c_int, + priv out_file: *libc::FILE, + priv err_file: *libc::FILE, + priv finished: bool, +} + +impl Drop for Program { + fn finalize(&self) { + // FIXME #4943: transmute is bad. + let mut_self: &mut Program = unsafe { cast::transmute(self) }; + + mut_self.finish(); + mut_self.close_outputs(); + free_handle(self.handle); + } } -impl ProgRepr { +pub impl Program { + + /// Returns the process id of the program + fn get_id(&mut self) -> pid_t { self.pid } + + /// Returns an io::Writer that can be used to write to stdin + fn input(&mut self) -> @io::Writer { + io::fd_writer(self.in_fd, false) + } + + /// Returns an io::Reader that can be used to read from stdout + fn output(&mut self) -> @io::Reader { + io::FILE_reader(self.out_file, false) + } + + /// Returns an io::Reader that can be used to read from stderr + fn err(&mut self) -> @io::Reader { + io::FILE_reader(self.err_file, false) + } + + /// Closes the handle to the child processes standard input fn close_input(&mut self) { let invalid_fd = -1i32; if self.in_fd != invalid_fd { @@ -67,13 +99,17 @@ impl ProgRepr { } } - fn close_outputs(&mut self) { + priv fn close_outputs(&mut self) { unsafe { fclose_and_null(&mut self.out_file); fclose_and_null(&mut self.err_file); } } + /** + * Waits for the child process to terminate. Closes the handle + * to stdin if necessary. + */ fn finish(&mut self) -> int { if self.finished { return 0; } self.finished = true; @@ -81,7 +117,7 @@ impl ProgRepr { return waitpid(self.pid); } - fn destroy(&mut self, force: bool) { + priv fn destroy_internal(&mut self, force: bool) { killpid(self.pid, force); self.finish(); self.close_outputs(); @@ -107,57 +143,6 @@ impl ProgRepr { } } } -} - -/// A value representing a child process -pub struct Program { - priv r: ProgRepr, -} - -impl Drop for Program { - fn finalize(&self) { - // FIXME #4943: transmute is bad. - let selfr: &mut ProgRepr = unsafe { cast::transmute(&self.r) }; - - selfr.finish(); - selfr.close_outputs(); - free_handle(self.r.handle); - } -} - -pub impl Program { - priv fn new(r: ProgRepr) -> Program { - Program { - r: r - } - } - - /// Returns the process id of the program - fn get_id(&mut self) -> pid_t { self.r.pid } - - /// Returns an io::Writer that can be used to write to stdin - fn input(&mut self) -> @io::Writer { - io::fd_writer(self.r.in_fd, false) - } - - /// Returns an io::Reader that can be used to read from stdout - fn output(&mut self) -> @io::Reader { - io::FILE_reader(self.r.out_file, false) - } - - /// Returns an io::Reader that can be used to read from stderr - fn err(&mut self) -> @io::Reader { - io::FILE_reader(self.r.err_file, false) - } - - /// Closes the handle to the child processes standard input - fn close_input(&mut self) { self.r.close_input(); } - - /** - * Waits for the child process to terminate. Closes the handle - * to stdin if necessary. - */ - fn finish(&mut self) -> int { self.r.finish() } /** * Terminate the program, giving it a chance to clean itself up if @@ -166,7 +151,7 @@ pub impl Program { * On Posix OSs SIGTERM will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - fn destroy(&mut self) { self.r.destroy(false); } + fn destroy(&mut self) { self.destroy_internal(false); } /** * Terminate the program as soon as possible without giving it a @@ -175,7 +160,7 @@ pub impl Program { * On Posix OSs SIGKILL will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - fn force_destroy(&mut self) { self.r.destroy(true); } + fn force_destroy(&mut self) { self.destroy_internal(true); } } @@ -366,16 +351,14 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program { libc::close(pipe_err.out); } - let repr = ProgRepr { + Program { pid: res.pid, handle: res.handle, in_fd: pipe_input.out, out_file: os::fdopen(pipe_output.in), err_file: os::fdopen(pipe_err.in), finished: false, - }; - - Program::new(repr) + } } fn read_all(rd: @io::Reader) -> ~str { From dd748079574197215da46ac164f16a392df9cc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Tue, 23 Apr 2013 11:08:13 +0200 Subject: [PATCH 384/403] Removed ascii functions from other modules Replaced str::to_lowercase and str::to_uppercase --- src/compiletest/errors.rs | 5 ++- src/libcore/char.rs | 16 +------- src/libcore/num/uint-template/u8.rs | 7 ---- src/libcore/path.rs | 9 +++- src/libcore/str.rs | 59 --------------------------- src/libcore/str/ascii.rs | 12 ++++++ src/libcore/unstable/extfmt.rs | 5 ++- src/librustc/driver/driver.rs | 5 ++- src/librustdoc/markdown_index_pass.rs | 4 +- src/libstd/semver.rs | 2 +- src/libstd/sort.rs | 8 +++- 11 files changed, 43 insertions(+), 89 deletions(-) diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 5a5c091d9570a..bc9d694328b77 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -50,7 +50,10 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { while idx < len && line[idx] == (' ' as u8) { idx += 1u; } let start_kind = idx; while idx < len && line[idx] != (' ' as u8) { idx += 1u; } - let kind = str::to_lower(str::slice(line, start_kind, idx).to_owned()); + + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + let kind = str::slice(line, start_kind, idx).to_ascii().to_lower().to_str_ascii(); // Extract msg: while idx < len && line[idx] == (' ' as u8) { idx += 1u; } diff --git a/src/libcore/char.rs b/src/libcore/char.rs index c07a31490c346..8af61dcb86197 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -100,12 +100,6 @@ pub fn is_alphanumeric(c: char) -> bool { unicode::general_category::No(c); } -/// Indicates whether the character is an ASCII character -#[inline(always)] -pub fn is_ascii(c: char) -> bool { - c - ('\x7F' & c) == '\x00' -} - /// Indicates whether the character is numeric (Nd, Nl, or No) #[inline(always)] pub fn is_digit(c: char) -> bool { @@ -116,7 +110,7 @@ pub fn is_digit(c: char) -> bool { /** * Checks if a character parses as a numeric digit in the given radix. - * Compared to `is_digit()`, this function only recognizes the ascii + * Compared to `is_digit()`, this function only recognizes the * characters `0-9`, `a-z` and `A-Z`. * * Returns `true` if `c` is a valid digit under `radix`, and `false` @@ -163,7 +157,7 @@ pub fn to_digit(c: char, radix: uint) -> Option { } /** - * Converts a number to the ascii character representing it. + * Converts a number to the character representing it. * * Returns `Some(char)` if `num` represents one digit under `radix`, * using one character of `0-9` or `a-z`, or `None` if it doesn't. @@ -316,12 +310,6 @@ fn test_to_digit() { assert!(to_digit('$', 36u).is_none()); } -#[test] -fn test_is_ascii() { - assert!(str::all(~"banana", is_ascii)); - assert!(! str::all(~"ประเทศไทย中华Việt Nam", is_ascii)); -} - #[test] fn test_is_digit() { assert!(is_digit('2')); diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs index ce23bebacdad1..5c548d7209330 100644 --- a/src/libcore/num/uint-template/u8.rs +++ b/src/libcore/num/uint-template/u8.rs @@ -10,16 +10,9 @@ //! Operations and constants for `u8` -pub use self::inst::is_ascii; - mod inst { pub type T = u8; #[allow(non_camel_case_types)] pub type T_SIGNED = i8; pub static bits: uint = 8; - - // Type-specific functions here. These must be reexported by the - // parent module so that they appear in core::u8 and not core::u8::u8; - - pub fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; } } diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 8328d42c35e9a..2c75bf98eb05d 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -753,7 +753,9 @@ impl GenericPath for WindowsPath { fn is_restricted(&self) -> bool { match self.filestem() { Some(stem) => { - match stem.to_lower() { + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + match stem.to_ascii().to_lower().to_str_ascii() { ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" | ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true, _ => false @@ -809,7 +811,10 @@ impl GenericPath for WindowsPath { host: copy self.host, device: match self.device { None => None, - Some(ref device) => Some(device.to_upper()) + + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + Some(ref device) => Some(device.to_ascii().to_upper().to_str_ascii()) }, is_absolute: self.is_absolute, components: normalize(self.components) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 9590f148e3046..9ac36198c6a9d 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -787,22 +787,6 @@ pub fn each_split_within<'a>(ss: &'a str, } } -/// Convert a string to lowercase. ASCII only -pub fn to_lower(s: &str) -> ~str { - do map(s) |c| { - assert!(char::is_ascii(c)); - (unsafe{libc::tolower(c as libc::c_char)}) as char - } -} - -/// Convert a string to uppercase. ASCII only -pub fn to_upper(s: &str) -> ~str { - do map(s) |c| { - assert!(char::is_ascii(c)); - (unsafe{libc::toupper(c as libc::c_char)}) as char - } -} - /** * Replace all occurrences of one string with another * @@ -1610,13 +1594,6 @@ pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { Section: String properties */ -/// Determines if a string contains only ASCII characters -pub fn is_ascii(s: &str) -> bool { - let mut i: uint = len(s); - while i > 0u { i -= 1u; if !u8::is_ascii(s[i]) { return false; } } - return true; -} - /// Returns true if the string has length 0 pub fn is_empty(s: &str) -> bool { len(s) == 0u } @@ -2403,8 +2380,6 @@ pub trait StrSlice<'self> { fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool); fn starts_with<'a>(&self, needle: &'a str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; - fn to_lower(&self) -> ~str; - fn to_upper(&self) -> ~str; fn escape_default(&self) -> ~str; fn escape_unicode(&self) -> ~str; fn trim(&self) -> &'self str; @@ -2565,12 +2540,6 @@ impl<'self> StrSlice<'self> for &'self str { fn substr(&self, begin: uint, n: uint) -> &'self str { substr(*self, begin, n) } - /// Convert a string to lowercase - #[inline] - fn to_lower(&self) -> ~str { to_lower(*self) } - /// Convert a string to uppercase - #[inline] - fn to_upper(&self) -> ~str { to_upper(*self) } /// Escape each char in `s` with char::escape_default. #[inline] fn escape_default(&self) -> ~str { escape_default(*self) } @@ -3084,27 +3053,6 @@ mod tests { assert!(repeat(~"hi", 0) == ~""); } - #[test] - fn test_to_upper() { - // libc::toupper, and hence str::to_upper - // are culturally insensitive: they only work for ASCII - // (see Issue #1347) - let unicode = ~""; //"\u65e5\u672c"; // uncomment once non-ASCII works - let input = ~"abcDEF" + unicode + ~"xyz:.;"; - let expected = ~"ABCDEF" + unicode + ~"XYZ:.;"; - let actual = to_upper(input); - assert!(expected == actual); - } - - #[test] - fn test_to_lower() { - // libc::tolower, and hence str::to_lower - // are culturally insensitive: they only work for ASCII - // (see Issue #1347) - assert!(~"" == to_lower("")); - assert!(~"ymca" == to_lower("YMCA")); - } - #[test] fn test_unsafe_slice() { assert!("ab" == unsafe {raw::slice_bytes("abc", 0, 2)}); @@ -3337,13 +3285,6 @@ mod tests { assert!((!is_whitespace(~" _ "))); } - #[test] - fn test_is_ascii() { - assert!((is_ascii(~""))); - assert!((is_ascii(~"a"))); - assert!((!is_ascii(~"\u2009"))); - } - #[test] fn test_shift_byte() { let mut s = ~"ABC"; diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index f6c0176eafc63..7c7f49fed4717 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -221,6 +221,9 @@ mod tests { assert_eq!('['.to_ascii().to_lower().to_char(), '['); assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); + + assert!(str::all(~"banana", |c| c.is_ascii())); + assert!(! str::all(~"ประเทศไทย中华Việt Nam", |c| c.is_ascii())); } #[test] @@ -234,6 +237,15 @@ mod tests { assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#"); assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#"); + + assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~""); + assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca"); + assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;"); + + assert!("".is_ascii()); + assert!("a".is_ascii()); + assert!(!"\u2009".is_ascii()); + } #[test] diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs index ee33e2ed20bba..aefc527219e07 100644 --- a/src/libcore/unstable/extfmt.rs +++ b/src/libcore/unstable/extfmt.rs @@ -520,7 +520,10 @@ pub mod rt { match cv.ty { TyDefault => uint_to_str_prec(u, 10, prec), TyHexLower => uint_to_str_prec(u, 16, prec), - TyHexUpper => str::to_upper(uint_to_str_prec(u, 16, prec)), + + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + TyHexUpper => uint_to_str_prec(u, 16, prec).to_ascii().to_upper().to_str_ascii(), TyBits => uint_to_str_prec(u, 2, prec), TyOctal => uint_to_str_prec(u, 8, prec) }; diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 7110382bb55ed..3c587b3e9d044 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -546,7 +546,10 @@ pub fn build_session_options(binary: @~str, let lint_dict = lint::get_lint_dict(); for lint_levels.each |level| { let level_name = lint::level_to_str(*level); - let level_short = level_name.substr(0,1).to_upper(); + + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + let level_short = level_name.substr(0,1).to_ascii().to_upper().to_str_ascii(); let flags = vec::append(getopts::opt_strs(matches, level_short), getopts::opt_strs(matches, level_name)); for flags.each |lint_name| { diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 866fbba2be87a..4c86fc0fb6afb 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -157,7 +157,9 @@ pub fn pandoc_header_id(header: &str) -> ~str { let s = str::replace(s, ~" ", ~"-"); return s; } - fn convert_to_lowercase(s: &str) -> ~str { str::to_lower(s) } + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + fn convert_to_lowercase(s: &str) -> ~str { s.to_ascii().to_lower().to_str_ascii() } fn remove_up_to_first_letter(s: &str) -> ~str { s.to_str() } fn maybe_use_section_id(s: &str) -> ~str { s.to_str() } } diff --git a/src/libstd/semver.rs b/src/libstd/semver.rs index 83fab365d8d62..f6d1b1ba2ecd4 100644 --- a/src/libstd/semver.rs +++ b/src/libstd/semver.rs @@ -220,7 +220,7 @@ fn parse_reader(rdr: @io::Reader) -> Version { pub fn parse(s: &str) -> Option { - if ! str::is_ascii(s) { + if !s.is_ascii() { return None; } let s = s.trim(); diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index db6efdf3f52aa..8be3e1e6a6210 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -885,8 +885,12 @@ mod tests { // tjc: funny that we have to use parens fn ile(x: &(&'static str), y: &(&'static str)) -> bool { - let x = x.to_lower(); - let y = y.to_lower(); + // FIXME: 4318 Instead of to_str_ascii, could use + // to_str_consume to not do a unneccessary copy. + // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on + // Ascii) + let x = x.to_ascii().to_lower().to_str_ascii(); + let y = y.to_ascii().to_lower().to_str_ascii(); x <= y } From 3759b5711d1f34a92ef51abd069f074fb55b3b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Tue, 23 Apr 2013 18:20:55 +0200 Subject: [PATCH 385/403] Fixed typo... And a billion other things. --- doc/rust.md | 6 +++--- src/compiletest/errors.rs | 7 ++++--- src/libcore/path.rs | 9 +++++---- src/libcore/str.rs | 1 - src/libcore/str/ascii.rs | 1 + src/libcore/unstable/extfmt.rs | 9 ++++++--- src/librustc/driver/driver.rs | 7 ++++--- src/librustdoc/markdown_index_pass.rs | 4 ++-- src/libstd/sort.rs | 4 ++-- src/test/bench/shootout-k-nucleotide-pipes.rs | 9 +++++++-- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index b1eb5521b398f..0173f61e7307d 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -802,7 +802,7 @@ An example of `use` declarations: ~~~~ use core::float::sin; -use core::str::{slice, to_upper}; +use core::str::{slice, contains}; use core::option::Some; fn main() { @@ -813,8 +813,8 @@ fn main() { info!(Some(1.0)); // Equivalent to - // 'info!(core::str::to_upper(core::str::slice("foo", 0, 1)));' - info!(to_upper(slice("foo", 0, 1))); + // 'info!(core::str::contains(core::str::slice("foo", 0, 1), "oo"));' + info!(contains(slice("foo", 0, 1), "oo")); } ~~~~ diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index bc9d694328b77..3aa88523a873a 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -51,9 +51,10 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { let start_kind = idx; while idx < len && line[idx] != (' ' as u8) { idx += 1u; } - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. - let kind = str::slice(line, start_kind, idx).to_ascii().to_lower().to_str_ascii(); + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. + let kind = str::slice(line, start_kind, idx); + let kind = kind.to_ascii().to_lower().to_str_ascii(); // Extract msg: while idx < len && line[idx] == (' ' as u8) { idx += 1u; } diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 2c75bf98eb05d..edc61299af96d 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -19,6 +19,7 @@ use libc; use option::{None, Option, Some}; use str; use to_str::ToStr; +use ascii::{AsciiCast, AsciiStr}; #[deriving(Clone, Eq)] pub struct WindowsPath { @@ -753,8 +754,8 @@ impl GenericPath for WindowsPath { fn is_restricted(&self) -> bool { match self.filestem() { Some(stem) => { - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. match stem.to_ascii().to_lower().to_str_ascii() { ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" | ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true, @@ -812,8 +813,8 @@ impl GenericPath for WindowsPath { device: match self.device { None => None, - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. Some(ref device) => Some(device.to_ascii().to_upper().to_str_ascii()) }, is_absolute: self.is_absolute, diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 9ac36198c6a9d..92c965256ceaf 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -27,7 +27,6 @@ use option::{None, Option, Some}; use iterator::Iterator; use ptr; use str; -use u8; use uint; use vec; use to_str::ToStr; diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs index 7c7f49fed4717..9180c995ca28c 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libcore/str/ascii.rs @@ -199,6 +199,7 @@ impl ToStrConsume for ~[Ascii] { #[cfg(test)] mod tests { use super::*; + use str; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs index aefc527219e07..b812be5575a4a 100644 --- a/src/libcore/unstable/extfmt.rs +++ b/src/libcore/unstable/extfmt.rs @@ -521,9 +521,12 @@ pub mod rt { TyDefault => uint_to_str_prec(u, 10, prec), TyHexLower => uint_to_str_prec(u, 16, prec), - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. - TyHexUpper => uint_to_str_prec(u, 16, prec).to_ascii().to_upper().to_str_ascii(), + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. + TyHexUpper => { + let s = uint_to_str_prec(u, 16, prec); + s.to_ascii().to_upper().to_str_ascii() + } TyBits => uint_to_str_prec(u, 2, prec), TyOctal => uint_to_str_prec(u, 8, prec) }; diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 3c587b3e9d044..f33bb878ee4ba 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -547,9 +547,10 @@ pub fn build_session_options(binary: @~str, for lint_levels.each |level| { let level_name = lint::level_to_str(*level); - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. - let level_short = level_name.substr(0,1).to_ascii().to_upper().to_str_ascii(); + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. + let level_short = level_name.substr(0,1); + let level_short = level_short.to_ascii().to_upper().to_str_ascii(); let flags = vec::append(getopts::opt_strs(matches, level_short), getopts::opt_strs(matches, level_name)); for flags.each |lint_name| { diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 4c86fc0fb6afb..631c86b74f1e9 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -157,8 +157,8 @@ pub fn pandoc_header_id(header: &str) -> ~str { let s = str::replace(s, ~" ", ~"-"); return s; } - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. fn convert_to_lowercase(s: &str) -> ~str { s.to_ascii().to_lower().to_str_ascii() } fn remove_up_to_first_letter(s: &str) -> ~str { s.to_str() } fn maybe_use_section_id(s: &str) -> ~str { s.to_str() } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 8be3e1e6a6210..cc002bc8305a2 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -885,8 +885,8 @@ mod tests { // tjc: funny that we have to use parens fn ile(x: &(&'static str), y: &(&'static str)) -> bool { - // FIXME: 4318 Instead of to_str_ascii, could use - // to_str_consume to not do a unneccessary copy. + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on // Ascii) let x = x.to_ascii().to_lower().to_str_ascii(); diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index c8b13a6e27fa3..4c8c984cd07c9 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -59,7 +59,10 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { for pairs_sorted.each |kv| { let (k,v) = copy *kv; unsafe { - buffer += (fmt!("%s %0.3f\n", str::to_upper(str::raw::from_bytes(k)), v)); + let b = str::raw::from_bytes(k); + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. + buffer += (fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v)); } } @@ -68,7 +71,9 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { // given a map, search for the frequency of a pattern fn find(mm: &HashMap<~[u8], uint>, key: ~str) -> uint { - match mm.find(&str::to_bytes(str::to_lower(key))) { + // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use + // to_ascii_consume and to_str_consume to not do a unnecessary copy. + match mm.find(&str::to_bytes(key.to_ascii().to_lower().to_str_ascii())) { option::None => { return 0u; } option::Some(&num) => { return num; } } From 593bdd9be3959f166c303e3da0678cc9598bffc4 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 17:25:41 +1000 Subject: [PATCH 386/403] Fix incorrect replacement of `modulo` with `rem` --- src/libstd/base64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index cbdd2b19d276c..e90f0fb3c81d4 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -118,7 +118,7 @@ pub trait FromBase64 { impl FromBase64 for ~[u8] { /** * Convert base64 `u8` vector into u8 byte values. - * Every 4 encoded characters is converted into 3 octets, rem padding. + * Every 4 encoded characters is converted into 3 octets, modulo padding. * * *Example*: * From 03932f0b84e94f0ef96e4a6de6cb16ab436311e4 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 20:08:08 +1000 Subject: [PATCH 387/403] Move impls of `Num` out of core::num and clean up imports --- src/libcore/num/f32.rs | 25 +++++++++++------------ src/libcore/num/f64.rs | 25 +++++++++++------------ src/libcore/num/float.rs | 24 +++++++++------------- src/libcore/num/int-template.rs | 10 ++++++--- src/libcore/num/num.rs | 35 +++++--------------------------- src/libcore/num/uint-template.rs | 11 ++++++---- 6 files changed, 53 insertions(+), 77 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 5d663844e5b79..e72356aa3cbd3 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -10,20 +10,10 @@ //! Operations and constants for `f32` -use num::strconv; -use num::Signed; -use num; -use option::Option; use from_str; -use to_str; - -#[cfg(notest)] use cmp::{Eq, Ord}; -#[cfg(stage0,notest)] -use ops::{Add, Sub, Mul, Div, Modulo, Neg}; -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] -use ops::{Add, Sub, Mul, Quot, Rem, Neg}; +use libc::c_int; +use num::strconv; +use prelude::*; pub use cmath::c_float_targ_consts::*; @@ -233,6 +223,8 @@ pub fn logarithm(n: f32, b: f32) -> f32 { return log2(n) / log2(b); } +impl Num for f32 {} + #[cfg(notest)] impl Eq for f32 { #[inline(always)] @@ -588,6 +580,13 @@ impl num::FromStrRadix for f32 { #[cfg(test)] mod tests { use f32::*; + use super::*; + use prelude::*; + + #[test] + fn test_num() { + num::test_num(10f32, 2f32); + } #[test] pub fn test_signed() { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 48f23fe8ba946..c9867f5e6d40f 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -10,20 +10,10 @@ //! Operations and constants for `f64` -use num::strconv; -use num::Signed; -use num; -use option::Option; -use to_str; use from_str; - -#[cfg(notest)] use cmp::{Eq, Ord}; -#[cfg(stage0,notest)] -use ops::{Add, Sub, Mul, Div, Modulo, Neg}; -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] -use ops::{Add, Sub, Mul, Quot, Rem, Neg}; +use libc::c_int; +use num::strconv; +use prelude::*; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; @@ -254,6 +244,8 @@ pub fn logarithm(n: f64, b: f64) -> f64 { return log2(n) / log2(b); } +impl Num for f64 {} + #[cfg(notest)] impl Eq for f64 { #[inline(always)] @@ -596,6 +588,13 @@ impl num::FromStrRadix for f64 { #[cfg(test)] mod tests { use f64::*; + use super::*; + use prelude::*; + + #[test] + fn test_num() { + num::test_num(10f64, 2f64); + } #[test] pub fn test_signed() { diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 036d295943c7b..e2f3a4cbcdb13 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -20,21 +20,10 @@ // PORT this must match in width according to architecture -use f64; -use num::strconv; -use num::Signed; -use num; -use option::Option; -use to_str; use from_str; - -#[cfg(notest)] use cmp::{Eq, Ord}; -#[cfg(stage0,notest)] -use ops::{Add, Sub, Mul, Div, Modulo, Neg}; -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] -use ops::{Add, Sub, Mul, Quot, Rem, Neg}; +use libc::c_int; +use num::strconv; +use prelude::*; pub use f64::{add, sub, mul, quot, rem, lt, le, eq, ne, ge, gt}; pub use f64::logarithm; @@ -382,6 +371,8 @@ pub fn tan(x: float) -> float { f64::tan(x as f64) as float } +impl Num for float {} + #[cfg(notest)] impl Eq for float { #[inline(always)] @@ -524,6 +515,11 @@ mod tests { use super::*; use prelude::*; + #[test] + fn test_num() { + num::test_num(10f, 2f); + } + #[test] pub fn test_signed() { assert_eq!(infinity.abs(), infinity); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 426ed8a8b0f6e..6598efa759ec2 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -10,12 +10,9 @@ use T = self::inst::T; -use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; -use num::Signed; -use num; use prelude::*; pub use cmp::{min, max}; @@ -133,6 +130,8 @@ pub fn compl(i: T) -> T { #[inline(always)] pub fn abs(i: T) -> T { i.abs() } +impl Num for T {} + #[cfg(notest)] impl Ord for T { #[inline(always)] @@ -522,6 +521,11 @@ mod tests { use super::inst::T; use prelude::*; + #[test] + fn test_num() { + num::test_num(10 as T, 2 as T); + } + #[test] pub fn test_signed() { assert_eq!((1 as T).abs(), 1 as T); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 577bb3f0f150a..62ed80114d345 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -33,30 +33,18 @@ pub trait Num: Eq + Zero + One + Quot + Rem {} -impl Num for u8 {} -impl Num for u16 {} -impl Num for u32 {} -impl Num for u64 {} -impl Num for uint {} -impl Num for i8 {} -impl Num for i16 {} -impl Num for i32 {} -impl Num for i64 {} -impl Num for int {} -impl Num for f32 {} -impl Num for f64 {} -impl Num for float {} - pub trait IntConvertible { fn to_int(&self) -> int; fn from_int(n: int) -> Self; } pub trait Zero { + // FIXME (#5527): These should be associated constants fn zero() -> Self; } pub trait One { + // FIXME (#5527): These should be associated constants fn one() -> Self; } @@ -230,8 +218,9 @@ pub fn pow_with_uint+Mul>( total } +/// Helper function for testing numeric operations #[cfg(stage0,test)] -fn test_num(ten: T, two: T) { +pub fn test_num(ten: T, two: T) { assert_eq!(ten.add(&two), cast(12)); assert_eq!(ten.sub(&two), cast(8)); assert_eq!(ten.mul(&two), cast(20)); @@ -247,7 +236,7 @@ fn test_num(ten: T, two: T) { #[cfg(stage1,test)] #[cfg(stage2,test)] #[cfg(stage3,test)] -fn test_num(ten: T, two: T) { +pub fn test_num(ten: T, two: T) { assert_eq!(ten.add(&two), cast(12)); assert_eq!(ten.sub(&two), cast(8)); assert_eq!(ten.mul(&two), cast(20)); @@ -261,20 +250,6 @@ fn test_num(ten: T, two: T) { assert_eq!(ten.rem(&two), ten % two); } -#[test] fn test_u8_num() { test_num(10u8, 2u8) } -#[test] fn test_u16_num() { test_num(10u16, 2u16) } -#[test] fn test_u32_num() { test_num(10u32, 2u32) } -#[test] fn test_u64_num() { test_num(10u64, 2u64) } -#[test] fn test_uint_num() { test_num(10u, 2u) } -#[test] fn test_i8_num() { test_num(10i8, 2i8) } -#[test] fn test_i16_num() { test_num(10i16, 2i16) } -#[test] fn test_i32_num() { test_num(10i32, 2i32) } -#[test] fn test_i64_num() { test_num(10i64, 2i64) } -#[test] fn test_int_num() { test_num(10i, 2i) } -#[test] fn test_f32_num() { test_num(10f32, 2f32) } -#[test] fn test_f64_num() { test_num(10f64, 2f64) } -#[test] fn test_float_num() { test_num(10f, 2f) } - macro_rules! test_cast_20( ($_20:expr) => ({ let _20 = $_20; diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index a0da84a8c5359..fc0fe2d3a4d28 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -11,13 +11,9 @@ use T = self::inst::T; use T_SIGNED = self::inst::T_SIGNED; -use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; -use num::Unsigned; -use num; -use option::Option; use prelude::*; pub use cmp::{min, max}; @@ -100,6 +96,8 @@ pub fn compl(i: T) -> T { max_value ^ i } +impl Num for T {} + #[cfg(notest)] impl Ord for T { #[inline(always)] @@ -356,6 +354,11 @@ mod tests { use super::inst::T; use prelude::*; + #[test] + fn test_num() { + num::test_num(10 as T, 2 as T); + } + #[test] fn test_gcd() { assert_eq!((10 as T).gcd(2), 2 as T); From d4868ee74085c2dc2943ef9407ced2d06e43abf6 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 22:26:14 +1000 Subject: [PATCH 388/403] Use #[cfg(not(stage0))] to exclude items from stage0 As requested on the mailing list: https://mail.mozilla.org/pipermail/rust-dev/2013-April/003713.html --- src/libcore/core.rc | 4 +--- src/libcore/num/f32.rs | 10 ++-------- src/libcore/num/f64.rs | 8 ++------ src/libcore/num/float.rs | 8 ++------ src/libcore/num/int-template.rs | 10 ++-------- src/libcore/num/num.rs | 4 +--- src/libcore/num/uint-template.rs | 10 ++-------- src/libcore/ops.rs | 8 ++------ src/libcore/prelude.rs | 4 +--- src/libstd/std.rc | 16 ++++------------ 10 files changed, 19 insertions(+), 63 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 61fbf98a7c61d..7890d611e853d 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -77,9 +77,7 @@ pub use kinds::{Const, Copy, Owned, Durable}; pub use ops::{Drop}; #[cfg(stage0)] pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not}; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Shl, Shr, Index}; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index e72356aa3cbd3..9e4140adcd131 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -278,10 +278,7 @@ impl Div for f32 { #[inline(always)] fn div(&self, other: &f32) -> f32 { *self / *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Quot for f32 { #[inline(always)] fn quot(&self, other: &f32) -> f32 { *self / *other } @@ -292,10 +289,7 @@ impl Modulo for f32 { #[inline(always)] fn modulo(&self, other: &f32) -> f32 { *self % *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Rem for f32 { #[inline(always)] fn rem(&self, other: &f32) -> f32 { *self % *other } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index c9867f5e6d40f..12f86337e8500 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -292,9 +292,7 @@ impl Mul for f64 { impl Div for f64 { fn div(&self, other: &f64) -> f64 { *self / *other } } -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Quot for f64 { #[inline(always)] fn quot(&self, other: &f64) -> f64 { *self / *other } @@ -303,9 +301,7 @@ impl Quot for f64 { impl Modulo for f64 { fn modulo(&self, other: &f64) -> f64 { *self % *other } } -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Rem for f64 { #[inline(always)] fn rem(&self, other: &f64) -> f64 { *self % *other } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index e2f3a4cbcdb13..88321e6b8bf0f 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -459,9 +459,7 @@ impl Div for float { #[inline(always)] fn div(&self, other: &float) -> float { *self / *other } } -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Quot for float { #[inline(always)] fn quot(&self, other: &float) -> float { *self / *other } @@ -471,9 +469,7 @@ impl Modulo for float { #[inline(always)] fn modulo(&self, other: &float) -> float { *self % *other } } -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Rem for float { #[inline(always)] fn rem(&self, other: &float) -> float { *self % *other } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 6598efa759ec2..cb29b9e448633 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -185,10 +185,7 @@ impl Div for T { #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Quot for T { /** * Returns the integer quotient, truncated towards 0. As this behaviour reflects @@ -217,10 +214,7 @@ impl Modulo for T { #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Rem for T { /** * Returns the integer remainder after division, satisfying: diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 62ed80114d345..8304179c346ae 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -16,9 +16,7 @@ use ops::{Add, Sub, Mul, Neg}; use Quot = ops::Div; #[cfg(stage0)] use Rem = ops::Modulo; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] use ops::{Add, Sub, Mul, Quot, Rem, Neg}; use option::Option; use kinds::Copy; diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index fc0fe2d3a4d28..2ee64d4e4eaa6 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -151,10 +151,7 @@ impl Div for T { #[inline(always)] fn div(&self, other: &T) -> T { *self / *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Quot for T { #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } @@ -165,10 +162,7 @@ impl Modulo for T { #[inline(always)] fn modulo(&self, other: &T) -> T { *self % *other } } - -#[cfg(stage1,notest)] -#[cfg(stage2,notest)] -#[cfg(stage3,notest)] +#[cfg(not(stage0),notest)] impl Rem for T { #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 465a9330f74c0..1aa7aada05c88 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -36,9 +36,7 @@ pub trait Div { fn div(&self, rhs: &RHS) -> Result; } #[lang="quot"] -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] pub trait Quot { fn quot(&self, rhs: &RHS) -> Result; } @@ -49,9 +47,7 @@ pub trait Modulo { fn modulo(&self, rhs: &RHS) -> Result; } #[lang="rem"] -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] pub trait Rem { fn rem(&self, rhs: &RHS) -> Result; } diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 03e6065a85caa..0af0cdf08c91b 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -16,9 +16,7 @@ pub use either::{Either, Left, Right}; pub use kinds::{Const, Copy, Owned, Durable}; #[cfg(stage0)] pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not}; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 7bedef0f84110..07c679409cf68 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -76,9 +76,7 @@ pub mod rope; pub mod smallintmap; pub mod sort; pub mod dlist; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] pub mod treemap; // And ... other stuff @@ -98,19 +96,13 @@ pub mod cmp; pub mod base64; pub mod rl; pub mod workcache; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] #[path="num/bigint.rs"] pub mod bigint; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] #[path="num/rational.rs"] pub mod rational; -#[cfg(stage1)] -#[cfg(stage2)] -#[cfg(stage3)] +#[cfg(not(stage0))] #[path="num/complex.rs"] pub mod complex; pub mod stats; From 024bf2ec72bdc2428d5c58a59bfed7da1bbc4efd Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 22:45:57 +1000 Subject: [PATCH 389/403] Rename Natural to Integer 'Natural' normally means 'positive integer' in mathematics. It is therefore strange to implement it on signed integer types. 'Integer' is probably a better choice. --- src/libcore/core.rc | 3 ++- src/libcore/num/int-template.rs | 2 +- src/libcore/num/num.rs | 2 +- src/libcore/num/uint-template.rs | 2 +- src/libcore/prelude.rs | 3 ++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 7890d611e853d..2a8de6a80322c 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -103,7 +103,8 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use iter::{ExtendedMutableIter}; -pub use num::{Num, Signed, Unsigned, Natural, NumCast}; +pub use num::{Num, NumCast}; +pub use num::{Signed, Unsigned, Integer}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index cb29b9e448633..e322e5edeb90e 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -279,7 +279,7 @@ impl Signed for T { fn is_negative(&self) -> bool { *self < 0 } } -impl Natural for T { +impl Integer for T { /** * Floored integer division * diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 8304179c346ae..1c3c699603b0d 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -61,7 +61,7 @@ pub fn abs>(v: T) -> T { if v < Zero::zero() { v.neg() } else { v } } -pub trait Natural: Num +pub trait Integer: Num + Ord + Quot + Rem { diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 2ee64d4e4eaa6..69483f33e5281 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -176,7 +176,7 @@ impl Neg for T { impl Unsigned for T {} -impl Natural for T { +impl Integer for T { /// Unsigned integer division. Returns the same result as `quot` (`/`). #[inline(always)] fn div(&self, other: T) -> T { *self / other } diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 0af0cdf08c91b..ec332adb8323b 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -37,7 +37,8 @@ pub use hash::Hash; pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::{Times, ExtendedMutableIter}; -pub use num::{Num, Signed, Unsigned, Natural, NumCast}; +pub use num::{Num, NumCast}; +pub use num::{Signed, Unsigned, Integer}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From 6fa054df968198eff4513e483dee07e1e3612dad Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 24 Apr 2013 22:50:56 +1000 Subject: [PATCH 390/403] Use borrowed pointers for Integer methods This brings them in line with the quot and rem traits, and is be better for large Integer types like BigInt and BigUint because they don't need to be copied unnecessarily. --- src/libcore/num/int-template.rs | 80 ++++++++++++++++---------------- src/libcore/num/num.rs | 16 +++---- src/libcore/num/uint-template.rs | 46 +++++++++--------- 3 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index e322e5edeb90e..f9edf1cefc873 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -298,13 +298,13 @@ impl Integer for T { * ~~~ */ #[inline(always)] - fn div(&self, other: T) -> T { + fn div(&self, other: &T) -> T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) match self.quot_rem(other) { - (q, r) if (r > 0 && other < 0) - || (r < 0 && other > 0) => q - 1, - (q, _) => q, + (q, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => q - 1, + (q, _) => q, } } @@ -330,32 +330,32 @@ impl Integer for T { * ~~~ */ #[inline(always)] - fn modulo(&self, other: T) -> T { + fn modulo(&self, other: &T) -> T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match *self % other { - r if (r > 0 && other < 0) - || (r < 0 && other > 0) => r + other, - r => r, + match *self % *other { + r if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => r + *other, + r => r, } } /// Calculates `div` and `modulo` simultaneously #[inline(always)] - fn div_mod(&self, other: T) -> (T,T) { + fn div_mod(&self, other: &T) -> (T,T) { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) match self.quot_rem(other) { - (q, r) if (r > 0 && other < 0) - || (r < 0 && other > 0) => (q - 1, r + other), - (q, r) => (q, r), + (q, r) if (r > 0 && *other < 0) + || (r < 0 && *other > 0) => (q - 1, r + *other), + (q, r) => (q, r), } } /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously #[inline(always)] - fn quot_rem(&self, other: T) -> (T,T) { - (*self / other, *self % other) + fn quot_rem(&self, other: &T) -> (T,T) { + (*self / *other, *self % *other) } /** @@ -364,9 +364,9 @@ impl Integer for T { * The result is always positive */ #[inline(always)] - fn gcd(&self, other: T) -> T { + fn gcd(&self, other: &T) -> T { // Use Euclid's algorithm - let mut m = *self, n = other; + let mut m = *self, n = *other; while m != 0 { let temp = m; m = n % temp; @@ -379,17 +379,17 @@ impl Integer for T { * Calculates the Lowest Common Multiple (LCM) of the number and `other` */ #[inline(always)] - fn lcm(&self, other: T) -> T { - ((*self * other) / self.gcd(other)).abs() // should not have to recaluculate abs + fn lcm(&self, other: &T) -> T { + ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs } /// Returns `true` if the number can be divided by `other` without leaving a remainder #[inline(always)] - fn divisible_by(&self, other: T) -> bool { *self % other == 0 } + fn divisible_by(&self, other: &T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` #[inline(always)] - fn is_even(&self) -> bool { self.divisible_by(2) } + fn is_even(&self) -> bool { self.divisible_by(&2) } /// Returns `true` if the number is not divisible by `2` #[inline(always)] @@ -562,7 +562,7 @@ mod tests { fn test_nd_qr(nd: (T,T), qr: (T,T)) { let (n,d) = nd; let separate_quot_rem = (n / d, n % d); - let combined_quot_rem = n.quot_rem(d); + let combined_quot_rem = n.quot_rem(&d); assert_eq!(separate_quot_rem, qr); assert_eq!(combined_quot_rem, qr); @@ -586,8 +586,8 @@ mod tests { fn test_div_mod() { fn test_nd_dm(nd: (T,T), dm: (T,T)) { let (n,d) = nd; - let separate_div_mod = (n.div(d), n.modulo(d)); - let combined_div_mod = n.div_mod(d); + let separate_div_mod = (n.div(&d), n.modulo(&d)); + let combined_div_mod = n.div_mod(&d); assert_eq!(separate_div_mod, dm); assert_eq!(combined_div_mod, dm); @@ -609,26 +609,26 @@ mod tests { #[test] fn test_gcd() { - assert_eq!((10 as T).gcd(2), 2 as T); - assert_eq!((10 as T).gcd(3), 1 as T); - assert_eq!((0 as T).gcd(3), 3 as T); - assert_eq!((3 as T).gcd(3), 3 as T); - assert_eq!((56 as T).gcd(42), 14 as T); - assert_eq!((3 as T).gcd(-3), 3 as T); - assert_eq!((-6 as T).gcd(3), 3 as T); - assert_eq!((-4 as T).gcd(-2), 2 as T); + assert_eq!((10 as T).gcd(&2), 2 as T); + assert_eq!((10 as T).gcd(&3), 1 as T); + assert_eq!((0 as T).gcd(&3), 3 as T); + assert_eq!((3 as T).gcd(&3), 3 as T); + assert_eq!((56 as T).gcd(&42), 14 as T); + assert_eq!((3 as T).gcd(&-3), 3 as T); + assert_eq!((-6 as T).gcd(&3), 3 as T); + assert_eq!((-4 as T).gcd(&-2), 2 as T); } #[test] fn test_lcm() { - assert_eq!((1 as T).lcm(0), 0 as T); - assert_eq!((0 as T).lcm(1), 0 as T); - assert_eq!((1 as T).lcm(1), 1 as T); - assert_eq!((-1 as T).lcm(1), 1 as T); - assert_eq!((1 as T).lcm(-1), 1 as T); - assert_eq!((-1 as T).lcm(-1), 1 as T); - assert_eq!((8 as T).lcm(9), 72 as T); - assert_eq!((11 as T).lcm(5), 55 as T); + assert_eq!((1 as T).lcm(&0), 0 as T); + assert_eq!((0 as T).lcm(&1), 0 as T); + assert_eq!((1 as T).lcm(&1), 1 as T); + assert_eq!((-1 as T).lcm(&1), 1 as T); + assert_eq!((1 as T).lcm(&-1), 1 as T); + assert_eq!((-1 as T).lcm(&-1), 1 as T); + assert_eq!((8 as T).lcm(&9), 72 as T); + assert_eq!((11 as T).lcm(&5), 55 as T); } #[test] diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 1c3c699603b0d..076d90707f62e 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -65,14 +65,14 @@ pub trait Integer: Num + Ord + Quot + Rem { - fn div(&self, other: Self) -> Self; - fn modulo(&self, other: Self) -> Self; - fn div_mod(&self, other: Self) -> (Self,Self); - fn quot_rem(&self, other: Self) -> (Self,Self); - - fn gcd(&self, other: Self) -> Self; - fn lcm(&self, other: Self) -> Self; - fn divisible_by(&self, other: Self) -> bool; + fn div(&self, other: &Self) -> Self; + fn modulo(&self, other: &Self) -> Self; + fn div_mod(&self, other: &Self) -> (Self,Self); + fn quot_rem(&self, other: &Self) -> (Self,Self); + + fn gcd(&self, other: &Self) -> Self; + fn lcm(&self, other: &Self) -> Self; + fn divisible_by(&self, other: &Self) -> bool; fn is_even(&self) -> bool; fn is_odd(&self) -> bool; } diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 69483f33e5281..96019ddd564d6 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -179,29 +179,29 @@ impl Unsigned for T {} impl Integer for T { /// Unsigned integer division. Returns the same result as `quot` (`/`). #[inline(always)] - fn div(&self, other: T) -> T { *self / other } + fn div(&self, other: &T) -> T { *self / *other } /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). #[inline(always)] - fn modulo(&self, other: T) -> T { *self / other } + fn modulo(&self, other: &T) -> T { *self / *other } /// Calculates `div` and `modulo` simultaneously #[inline(always)] - fn div_mod(&self, other: T) -> (T,T) { - (*self / other, *self % other) + fn div_mod(&self, other: &T) -> (T,T) { + (*self / *other, *self % *other) } /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously #[inline(always)] - fn quot_rem(&self, other: T) -> (T,T) { - (*self / other, *self % other) + fn quot_rem(&self, other: &T) -> (T,T) { + (*self / *other, *self % *other) } /// Calculates the Greatest Common Divisor (GCD) of the number and `other` #[inline(always)] - fn gcd(&self, other: T) -> T { + fn gcd(&self, other: &T) -> T { // Use Euclid's algorithm - let mut m = *self, n = other; + let mut m = *self, n = *other; while m != 0 { let temp = m; m = n % temp; @@ -212,17 +212,17 @@ impl Integer for T { /// Calculates the Lowest Common Multiple (LCM) of the number and `other` #[inline(always)] - fn lcm(&self, other: T) -> T { - (*self * other) / self.gcd(other) + fn lcm(&self, other: &T) -> T { + (*self * *other) / self.gcd(other) } /// Returns `true` if the number can be divided by `other` without leaving a remainder #[inline(always)] - fn divisible_by(&self, other: T) -> bool { *self % other == 0 } + fn divisible_by(&self, other: &T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` #[inline(always)] - fn is_even(&self) -> bool { self.divisible_by(2) } + fn is_even(&self) -> bool { self.divisible_by(&2) } /// Returns `true` if the number is not divisible by `2` #[inline(always)] @@ -355,21 +355,21 @@ mod tests { #[test] fn test_gcd() { - assert_eq!((10 as T).gcd(2), 2 as T); - assert_eq!((10 as T).gcd(3), 1 as T); - assert_eq!((0 as T).gcd(3), 3 as T); - assert_eq!((3 as T).gcd(3), 3 as T); - assert_eq!((56 as T).gcd(42), 14 as T); + assert_eq!((10 as T).gcd(&2), 2 as T); + assert_eq!((10 as T).gcd(&3), 1 as T); + assert_eq!((0 as T).gcd(&3), 3 as T); + assert_eq!((3 as T).gcd(&3), 3 as T); + assert_eq!((56 as T).gcd(&42), 14 as T); } #[test] fn test_lcm() { - assert_eq!((1 as T).lcm(0), 0 as T); - assert_eq!((0 as T).lcm(1), 0 as T); - assert_eq!((1 as T).lcm(1), 1 as T); - assert_eq!((8 as T).lcm(9), 72 as T); - assert_eq!((11 as T).lcm(5), 55 as T); - assert_eq!((99 as T).lcm(17), 1683 as T); + assert_eq!((1 as T).lcm(&0), 0 as T); + assert_eq!((0 as T).lcm(&1), 0 as T); + assert_eq!((1 as T).lcm(&1), 1 as T); + assert_eq!((8 as T).lcm(&9), 72 as T); + assert_eq!((11 as T).lcm(&5), 55 as T); + assert_eq!((99 as T).lcm(&17), 1683 as T); } #[test] From dcd49ccd0ba5616995da00454389b6454423813c Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 25 Apr 2013 08:12:26 +1000 Subject: [PATCH 391/403] Add Fractional, Real and RealExt traits --- src/libcore/core.rc | 1 + src/libcore/num/f32.rs | 211 ++++++++++++++++++++++++++++++--- src/libcore/num/f64.rs | 239 ++++++++++++++++++++++++++++++++++--- src/libcore/num/float.rs | 249 +++++++++++++++++++++++++++++++++++---- src/libcore/num/num.rs | 94 +++++++++++++-- src/libcore/prelude.rs | 1 + 6 files changed, 724 insertions(+), 71 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 2a8de6a80322c..0a24fba666334 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -105,6 +105,7 @@ pub use iter::{ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; +pub use num::{Fractional, Real, RealExt}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 9e4140adcd131..57ac6c551766b 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -327,31 +327,176 @@ impl Signed for f32 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } -impl num::Round for f32 { - #[inline(always)] - fn round(&self, mode: num::RoundMode) -> f32 { - match mode { - num::RoundDown => floor(*self), - num::RoundUp => ceil(*self), - num::RoundToZero if self.is_negative() => ceil(*self), - num::RoundToZero => floor(*self), - num::RoundFromZero if self.is_negative() => floor(*self), - num::RoundFromZero => ceil(*self) - } - } +impl Fractional for f32 { + /// The reciprocal (multiplicative inverse) of the number + #[inline(always)] + fn recip(&self) -> f32 { 1.0 / *self } +} + +impl Real for f32 { + /// Archimedes' constant + #[inline(always)] + fn pi() -> f32 { 3.14159265358979323846264338327950288 } + + /// 2.0 * pi + #[inline(always)] + fn two_pi() -> f32 { 6.28318530717958647692528676655900576 } + + /// pi / 2.0 + #[inline(always)] + fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 } + + /// pi / 3.0 + #[inline(always)] + fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 } + + /// pi / 4.0 + #[inline(always)] + fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 } + + /// pi / 6.0 + #[inline(always)] + fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 } + + /// pi / 8.0 + #[inline(always)] + fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 } + + /// 1 .0/ pi + #[inline(always)] + fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 } + + /// 2.0 / pi + #[inline(always)] + fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 } + + /// 2.0 / sqrt(pi) + #[inline(always)] + fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 } + + /// sqrt(2.0) + #[inline(always)] + fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 } + + /// 1.0 / sqrt(2.0) + #[inline(always)] + fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 } + + /// Euler's number + #[inline(always)] + fn e() -> f32 { 2.71828182845904523536028747135266250 } + + /// log2(e) + #[inline(always)] + fn log2_e() -> f32 { 1.44269504088896340735992468100189214 } + + /// log10(e) + #[inline(always)] + fn log10_e() -> f32 { 0.434294481903251827651128918916605082 } + + /// log(2.0) + #[inline(always)] + fn log_2() -> f32 { 0.693147180559945309417232121458176568 } + + /// log(10.0) + #[inline(always)] + fn log_10() -> f32 { 2.30258509299404568401799145468436421 } #[inline(always)] fn floor(&self) -> f32 { floor(*self) } + #[inline(always)] fn ceil(&self) -> f32 { ceil(*self) } + #[inline(always)] - fn fract(&self) -> f32 { - if self.is_negative() { - (*self) - ceil(*self) - } else { - (*self) - floor(*self) - } - } + fn round(&self) -> f32 { round(*self) } + + #[inline(always)] + fn trunc(&self) -> f32 { trunc(*self) } + + /// The fractional part of the number, calculated using: `n - floor(n)` + #[inline(always)] + fn fract(&self) -> f32 { *self - self.floor() } + + #[inline(always)] + fn pow(&self, n: f32) -> f32 { pow(*self, n) } + + #[inline(always)] + fn exp(&self) -> f32 { exp(*self) } + + #[inline(always)] + fn exp2(&self) -> f32 { exp2(*self) } + + #[inline(always)] + fn expm1(&self) -> f32 { expm1(*self) } + + #[inline(always)] + fn ldexp(&self, n: int) -> f32 { ldexp(*self, n as c_int) } + + #[inline(always)] + fn log(&self) -> f32 { ln(*self) } + + #[inline(always)] + fn log2(&self) -> f32 { log2(*self) } + + #[inline(always)] + fn log10(&self) -> f32 { log10(*self) } + + #[inline(always)] + fn log_radix(&self) -> f32 { log_radix(*self) as f32 } + + #[inline(always)] + fn ilog_radix(&self) -> int { ilog_radix(*self) as int } + + #[inline(always)] + fn sqrt(&self) -> f32 { sqrt(*self) } + + #[inline(always)] + fn rsqrt(&self) -> f32 { self.sqrt().recip() } + + #[inline(always)] + fn cbrt(&self) -> f32 { cbrt(*self) } + + /// Converts to degrees, assuming the number is in radians + #[inline(always)] + fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::()) } + + /// Converts to radians, assuming the number is in degrees + #[inline(always)] + fn to_radians(&self) -> f32 { *self * (Real::pi::() / 180.0) } + + #[inline(always)] + fn hypot(&self, other: f32) -> f32 { hypot(*self, other) } + + #[inline(always)] + fn sin(&self) -> f32 { sin(*self) } + + #[inline(always)] + fn cos(&self) -> f32 { cos(*self) } + + #[inline(always)] + fn tan(&self) -> f32 { tan(*self) } + + #[inline(always)] + fn asin(&self) -> f32 { asin(*self) } + + #[inline(always)] + fn acos(&self) -> f32 { acos(*self) } + + #[inline(always)] + fn atan(&self) -> f32 { atan(*self) } + + #[inline(always)] + fn atan2(&self, other: f32) -> f32 { atan2(*self, other) } + + #[inline(always)] + fn sinh(&self) -> f32 { sinh(*self) } + + #[inline(always)] + fn cosh(&self) -> f32 { cosh(*self) } + + #[inline(always)] + fn tanh(&self) -> f32 { tanh(*self) } } /** @@ -577,11 +722,39 @@ mod tests { use super::*; use prelude::*; + macro_rules! assert_fuzzy_eq( + ($a:expr, $b:expr) => ({ + let a = $a, b = $b; + if !((a - b).abs() < 1.0e-6) { + fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b)); + } + }) + ) + #[test] fn test_num() { num::test_num(10f32, 2f32); } + #[test] + fn test_real_consts() { + assert_fuzzy_eq!(Real::two_pi::(), 2f32 * Real::pi::()); + assert_fuzzy_eq!(Real::frac_pi_2::(), Real::pi::() / 2f32); + assert_fuzzy_eq!(Real::frac_pi_3::(), Real::pi::() / 3f32); + assert_fuzzy_eq!(Real::frac_pi_4::(), Real::pi::() / 4f32); + assert_fuzzy_eq!(Real::frac_pi_6::(), Real::pi::() / 6f32); + assert_fuzzy_eq!(Real::frac_pi_8::(), Real::pi::() / 8f32); + assert_fuzzy_eq!(Real::frac_1_pi::(), 1f32 / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_pi::(), 2f32 / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_sqrtpi::(), 2f32 / Real::pi::().sqrt()); + assert_fuzzy_eq!(Real::sqrt2::(), 2f32.sqrt()); + assert_fuzzy_eq!(Real::frac_1_sqrt2::(), 1f32 / 2f32.sqrt()); + assert_fuzzy_eq!(Real::log2_e::(), Real::e::().log2()); + assert_fuzzy_eq!(Real::log10_e::(), Real::e::().log10()); + assert_fuzzy_eq!(Real::log_2::(), 2f32.log()); + assert_fuzzy_eq!(Real::log_10::(), 10f32.log()); + } + #[test] pub fn test_signed() { assert_eq!(infinity.abs(), infinity); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 12f86337e8500..53ad78c29f392 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -337,31 +337,206 @@ impl Signed for f64 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } -impl num::Round for f64 { - #[inline(always)] - fn round(&self, mode: num::RoundMode) -> f64 { - match mode { - num::RoundDown => floor(*self), - num::RoundUp => ceil(*self), - num::RoundToZero if self.is_negative() => ceil(*self), - num::RoundToZero => floor(*self), - num::RoundFromZero if self.is_negative() => floor(*self), - num::RoundFromZero => ceil(*self) - } - } +impl Fractional for f64 { + /// The reciprocal (multiplicative inverse) of the number + #[inline(always)] + fn recip(&self) -> f64 { 1.0 / *self } +} + +impl Real for f64 { + /// Archimedes' constant + #[inline(always)] + fn pi() -> f64 { 3.14159265358979323846264338327950288 } + + /// 2.0 * pi + #[inline(always)] + fn two_pi() -> f64 { 6.28318530717958647692528676655900576 } + + /// pi / 2.0 + #[inline(always)] + fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 } + + /// pi / 3.0 + #[inline(always)] + fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 } + + /// pi / 4.0 + #[inline(always)] + fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 } + + /// pi / 6.0 + #[inline(always)] + fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 } + + /// pi / 8.0 + #[inline(always)] + fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 } + + /// 1.0 / pi + #[inline(always)] + fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 } + + /// 2.0 / pi + #[inline(always)] + fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 } + + /// 2.0 / sqrt(pi) + #[inline(always)] + fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 } + + /// sqrt(2.0) + #[inline(always)] + fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 } + + /// 1.0 / sqrt(2.0) + #[inline(always)] + fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 } + + /// Euler's number + #[inline(always)] + fn e() -> f64 { 2.71828182845904523536028747135266250 } + + /// log2(e) + #[inline(always)] + fn log2_e() -> f64 { 1.44269504088896340735992468100189214 } + + /// log10(e) + #[inline(always)] + fn log10_e() -> f64 { 0.434294481903251827651128918916605082 } + + /// log(2.0) + #[inline(always)] + fn log_2() -> f64 { 0.693147180559945309417232121458176568 } + + /// log(10.0) + #[inline(always)] + fn log_10() -> f64 { 2.30258509299404568401799145468436421 } #[inline(always)] fn floor(&self) -> f64 { floor(*self) } + #[inline(always)] fn ceil(&self) -> f64 { ceil(*self) } + #[inline(always)] - fn fract(&self) -> f64 { - if self.is_negative() { - (*self) - ceil(*self) - } else { - (*self) - floor(*self) - } + fn round(&self) -> f64 { round(*self) } + + #[inline(always)] + fn trunc(&self) -> f64 { trunc(*self) } + + /// The fractional part of the number, calculated using: `n - floor(n)` + #[inline(always)] + fn fract(&self) -> f64 { *self - self.floor() } + + #[inline(always)] + fn pow(&self, n: f64) -> f64 { pow(*self, n) } + + #[inline(always)] + fn exp(&self) -> f64 { exp(*self) } + + #[inline(always)] + fn exp2(&self) -> f64 { exp2(*self) } + + #[inline(always)] + fn expm1(&self) -> f64 { expm1(*self) } + + #[inline(always)] + fn ldexp(&self, n: int) -> f64 { ldexp(*self, n as c_int) } + + #[inline(always)] + fn log(&self) -> f64 { ln(*self) } + + #[inline(always)] + fn log2(&self) -> f64 { log2(*self) } + + #[inline(always)] + fn log10(&self) -> f64 { log10(*self) } + + #[inline(always)] + fn log_radix(&self) -> f64 { log_radix(*self) } + + #[inline(always)] + fn ilog_radix(&self) -> int { ilog_radix(*self) as int } + + #[inline(always)] + fn sqrt(&self) -> f64 { sqrt(*self) } + + #[inline(always)] + fn rsqrt(&self) -> f64 { self.sqrt().recip() } + + #[inline(always)] + fn cbrt(&self) -> f64 { cbrt(*self) } + + /// Converts to degrees, assuming the number is in radians + #[inline(always)] + fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::()) } + + /// Converts to radians, assuming the number is in degrees + #[inline(always)] + fn to_radians(&self) -> f64 { *self * (Real::pi::() / 180.0) } + + #[inline(always)] + fn hypot(&self, other: f64) -> f64 { hypot(*self, other) } + + #[inline(always)] + fn sin(&self) -> f64 { sin(*self) } + + #[inline(always)] + fn cos(&self) -> f64 { cos(*self) } + + #[inline(always)] + fn tan(&self) -> f64 { tan(*self) } + + #[inline(always)] + fn asin(&self) -> f64 { asin(*self) } + + #[inline(always)] + fn acos(&self) -> f64 { acos(*self) } + + #[inline(always)] + fn atan(&self) -> f64 { atan(*self) } + + #[inline(always)] + fn atan2(&self, other: f64) -> f64 { atan2(*self, other) } + + #[inline(always)] + fn sinh(&self) -> f64 { sinh(*self) } + + #[inline(always)] + fn cosh(&self) -> f64 { cosh(*self) } + + #[inline(always)] + fn tanh(&self) -> f64 { tanh(*self) } +} + +impl RealExt for f64 { + #[inline(always)] + fn lgamma(&self) -> (int, f64) { + let mut sign = 0; + let result = lgamma(*self, &mut sign); + (sign as int, result) } + + #[inline(always)] + fn tgamma(&self) -> f64 { tgamma(*self) } + + #[inline(always)] + fn j0(&self) -> f64 { j0(*self) } + + #[inline(always)] + fn j1(&self) -> f64 { j1(*self) } + + #[inline(always)] + fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) } + + #[inline(always)] + fn y0(&self) -> f64 { y0(*self) } + + #[inline(always)] + fn y1(&self) -> f64 { y1(*self) } + + #[inline(always)] + fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } /** @@ -587,11 +762,39 @@ mod tests { use super::*; use prelude::*; + macro_rules! assert_fuzzy_eq( + ($a:expr, $b:expr) => ({ + let a = $a, b = $b; + if !((a - b).abs() < 1.0e-6) { + fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b)); + } + }) + ) + #[test] fn test_num() { num::test_num(10f64, 2f64); } + #[test] + fn test_real_consts() { + assert_fuzzy_eq!(Real::two_pi::(), 2.0 * Real::pi::()); + assert_fuzzy_eq!(Real::frac_pi_2::(), Real::pi::() / 2f64); + assert_fuzzy_eq!(Real::frac_pi_3::(), Real::pi::() / 3f64); + assert_fuzzy_eq!(Real::frac_pi_4::(), Real::pi::() / 4f64); + assert_fuzzy_eq!(Real::frac_pi_6::(), Real::pi::() / 6f64); + assert_fuzzy_eq!(Real::frac_pi_8::(), Real::pi::() / 8f64); + assert_fuzzy_eq!(Real::frac_1_pi::(), 1f64 / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_pi::(), 2f64 / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_sqrtpi::(), 2f64 / Real::pi::().sqrt()); + assert_fuzzy_eq!(Real::sqrt2::(), 2f64.sqrt()); + assert_fuzzy_eq!(Real::frac_1_sqrt2::(), 1f64 / 2f64.sqrt()); + assert_fuzzy_eq!(Real::log2_e::(), Real::e::().log2()); + assert_fuzzy_eq!(Real::log10_e::(), Real::e::().log10()); + assert_fuzzy_eq!(Real::log_2::(), 2f64.log()); + assert_fuzzy_eq!(Real::log_10::(), 10f64.log()); + } + #[test] pub fn test_signed() { assert_eq!(infinity.abs(), infinity); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 88321e6b8bf0f..ae2d0ce0d7194 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -403,37 +403,206 @@ impl num::One for float { fn one() -> float { 1.0 } } -impl num::Round for float { - #[inline(always)] - fn round(&self, mode: num::RoundMode) -> float { - match mode { - num::RoundDown - => f64::floor(*self as f64) as float, - num::RoundUp - => f64::ceil(*self as f64) as float, - num::RoundToZero if self.is_negative() - => f64::ceil(*self as f64) as float, - num::RoundToZero - => f64::floor(*self as f64) as float, - num::RoundFromZero if self.is_negative() - => f64::floor(*self as f64) as float, - num::RoundFromZero - => f64::ceil(*self as f64) as float - } - } +impl Fractional for float { + /// The reciprocal (multiplicative inverse) of the number + #[inline(always)] + fn recip(&self) -> float { 1.0 / *self } +} +impl Real for float { + /// Archimedes' constant #[inline(always)] - fn floor(&self) -> float { f64::floor(*self as f64) as float} + fn pi() -> float { 3.14159265358979323846264338327950288 } + + /// 2.0 * pi #[inline(always)] - fn ceil(&self) -> float { f64::ceil(*self as f64) as float} + fn two_pi() -> float { 6.28318530717958647692528676655900576 } + + /// pi / 2.0 #[inline(always)] - fn fract(&self) -> float { - if self.is_negative() { - (*self) - (f64::ceil(*self as f64) as float) - } else { - (*self) - (f64::floor(*self as f64) as float) - } + fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 } + + /// pi / 3.0 + #[inline(always)] + fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 } + + /// pi / 4.0 + #[inline(always)] + fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 } + + /// pi / 6.0 + #[inline(always)] + fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 } + + /// pi / 8.0 + #[inline(always)] + fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 } + + /// 1.0 / pi + #[inline(always)] + fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 } + + /// 2.0 / pi + #[inline(always)] + fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 } + + /// 2 .0/ sqrt(pi) + #[inline(always)] + fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 } + + /// sqrt(2.0) + #[inline(always)] + fn sqrt2() -> float { 1.41421356237309504880168872420969808 } + + /// 1.0 / sqrt(2.0) + #[inline(always)] + fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 } + + /// Euler's number + #[inline(always)] + fn e() -> float { 2.71828182845904523536028747135266250 } + + /// log2(e) + #[inline(always)] + fn log2_e() -> float { 1.44269504088896340735992468100189214 } + + /// log10(e) + #[inline(always)] + fn log10_e() -> float { 0.434294481903251827651128918916605082 } + + /// log(2.0) + #[inline(always)] + fn log_2() -> float { 0.693147180559945309417232121458176568 } + + /// log(10.0) + #[inline(always)] + fn log_10() -> float { 2.30258509299404568401799145468436421 } + + #[inline(always)] + fn floor(&self) -> float { floor(*self as f64) as float } + + #[inline(always)] + fn ceil(&self) -> float { ceil(*self as f64) as float } + + #[inline(always)] + fn round(&self) -> float { round(*self as f64) as float } + + #[inline(always)] + fn trunc(&self) -> float { trunc(*self as f64) as float } + + /// The fractional part of the number, calculated using: `n - floor(n)` + #[inline(always)] + fn fract(&self) -> float { *self - self.floor() } + + #[inline(always)] + fn pow(&self, n: float) -> float { pow(*self as f64, n as f64) as float } + + #[inline(always)] + fn exp(&self) -> float { exp(*self as f64) as float } + + #[inline(always)] + fn exp2(&self) -> float { exp2(*self as f64) as float } + + #[inline(always)] + fn expm1(&self) -> float { expm1(*self as f64) as float } + + #[inline(always)] + fn ldexp(&self, n: int) -> float { ldexp(*self as f64, n as c_int) as float } + + #[inline(always)] + fn log(&self) -> float { ln(*self as f64) as float } + + #[inline(always)] + fn log2(&self) -> float { log2(*self as f64) as float } + + #[inline(always)] + fn log10(&self) -> float { log10(*self as f64) as float } + + #[inline(always)] + fn log_radix(&self) -> float { log_radix(*self as f64) as float } + + #[inline(always)] + fn ilog_radix(&self) -> int { ilog_radix(*self as f64) as int } + + #[inline(always)] + fn sqrt(&self) -> float { sqrt(*self) } + + #[inline(always)] + fn rsqrt(&self) -> float { self.sqrt().recip() } + + #[inline(always)] + fn cbrt(&self) -> float { cbrt(*self as f64) as float } + + /// Converts to degrees, assuming the number is in radians + #[inline(always)] + fn to_degrees(&self) -> float { *self * (180.0 / Real::pi::()) } + + /// Converts to radians, assuming the number is in degrees + #[inline(always)] + fn to_radians(&self) -> float { *self * (Real::pi::() / 180.0) } + + #[inline(always)] + fn hypot(&self, other: float) -> float { hypot(*self as f64, other as f64) as float } + + #[inline(always)] + fn sin(&self) -> float { sin(*self) } + + #[inline(always)] + fn cos(&self) -> float { cos(*self) } + + #[inline(always)] + fn tan(&self) -> float { tan(*self) } + + #[inline(always)] + fn asin(&self) -> float { asin(*self as f64) as float } + + #[inline(always)] + fn acos(&self) -> float { acos(*self as f64) as float } + + #[inline(always)] + fn atan(&self) -> float { atan(*self) } + + #[inline(always)] + fn atan2(&self, other: float) -> float { atan2(*self as f64, other as f64) as float } + + #[inline(always)] + fn sinh(&self) -> float { sinh(*self as f64) as float } + + #[inline(always)] + fn cosh(&self) -> float { cosh(*self as f64) as float } + + #[inline(always)] + fn tanh(&self) -> float { tanh(*self as f64) as float } +} + +impl RealExt for float { + #[inline(always)] + fn lgamma(&self) -> (int, float) { + let mut sign = 0; + let result = lgamma(*self as f64, &mut sign); + (sign as int, result as float) } + + #[inline(always)] + fn tgamma(&self) -> float { tgamma(*self as f64) as float } + + #[inline(always)] + fn j0(&self) -> float { j0(*self as f64) as float } + + #[inline(always)] + fn j1(&self) -> float { j1(*self as f64) as float } + + #[inline(always)] + fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float } + + #[inline(always)] + fn y0(&self) -> float { y0(*self as f64) as float } + + #[inline(always)] + fn y1(&self) -> float { y1(*self as f64) as float } + + #[inline(always)] + fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float } } #[cfg(notest)] @@ -511,11 +680,39 @@ mod tests { use super::*; use prelude::*; + macro_rules! assert_fuzzy_eq( + ($a:expr, $b:expr) => ({ + let a = $a, b = $b; + if !((a - b).abs() < 1.0e-6) { + fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b)); + } + }) + ) + #[test] fn test_num() { num::test_num(10f, 2f); } + #[test] + fn test_real_consts() { + assert_fuzzy_eq!(Real::two_pi::(), 2f * Real::pi::()); + assert_fuzzy_eq!(Real::frac_pi_2::(), Real::pi::() / 2f); + assert_fuzzy_eq!(Real::frac_pi_3::(), Real::pi::() / 3f); + assert_fuzzy_eq!(Real::frac_pi_4::(), Real::pi::() / 4f); + assert_fuzzy_eq!(Real::frac_pi_6::(), Real::pi::() / 6f); + assert_fuzzy_eq!(Real::frac_pi_8::(), Real::pi::() / 8f); + assert_fuzzy_eq!(Real::frac_1_pi::(), 1f / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_pi::(), 2f / Real::pi::()); + assert_fuzzy_eq!(Real::frac_2_sqrtpi::(), 2f / Real::pi::().sqrt()); + assert_fuzzy_eq!(Real::sqrt2::(), 2f.sqrt()); + assert_fuzzy_eq!(Real::frac_1_sqrt2::(), 1f / 2f.sqrt()); + assert_fuzzy_eq!(Real::log2_e::(), Real::e::().log2()); + assert_fuzzy_eq!(Real::log10_e::(), Real::e::().log10()); + assert_fuzzy_eq!(Real::log_2::(), 2f.log()); + assert_fuzzy_eq!(Real::log_10::(), 10f.log()); + } + #[test] pub fn test_signed() { assert_eq!(infinity.abs(), infinity); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 076d90707f62e..733b37e2a4a62 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -77,19 +77,97 @@ pub trait Integer: Num fn is_odd(&self) -> bool; } -pub trait Round { - fn round(&self, mode: RoundMode) -> Self; +pub trait Fractional: Num + + Ord + + Quot { + fn recip(&self) -> Self; +} + +pub trait Real: Signed + + Fractional { + // FIXME (#5527): usages of `int` should be replaced with an associated + // integer type once these are implemented + // Common Constants + // FIXME (#5527): These should be associated constants + fn pi() -> Self; + fn two_pi() -> Self; + fn frac_pi_2() -> Self; + fn frac_pi_3() -> Self; + fn frac_pi_4() -> Self; + fn frac_pi_6() -> Self; + fn frac_pi_8() -> Self; + fn frac_1_pi() -> Self; + fn frac_2_pi() -> Self; + fn frac_2_sqrtpi() -> Self; + fn sqrt2() -> Self; + fn frac_1_sqrt2() -> Self; + fn e() -> Self; + fn log2_e() -> Self; + fn log10_e() -> Self; + fn log_2() -> Self; + fn log_10() -> Self; + + // Rounding operations fn floor(&self) -> Self; - fn ceil(&self) -> Self; + fn ceil(&self) -> Self; + fn round(&self) -> Self; + fn trunc(&self) -> Self; fn fract(&self) -> Self; + + // Exponential functions + fn pow(&self, n: Self) -> Self; + fn exp(&self) -> Self; + fn exp2(&self) -> Self; + fn expm1(&self) -> Self; + fn ldexp(&self, n: int) -> Self; + fn log(&self) -> Self; + fn log2(&self) -> Self; + fn log10(&self) -> Self; + fn log_radix(&self) -> Self; + fn ilog_radix(&self) -> int; + fn sqrt(&self) -> Self; + fn rsqrt(&self) -> Self; + fn cbrt(&self) -> Self; + + // Angular conversions + fn to_degrees(&self) -> Self; + fn to_radians(&self) -> Self; + + // Triganomic functions + fn hypot(&self, other: Self) -> Self; + fn sin(&self) -> Self; + fn cos(&self) -> Self; + fn tan(&self) -> Self; + + // Inverse triganomic functions + fn asin(&self) -> Self; + fn acos(&self) -> Self; + fn atan(&self) -> Self; + fn atan2(&self, other: Self) -> Self; + + // Hyperbolic triganomic functions + fn sinh(&self) -> Self; + fn cosh(&self) -> Self; + fn tanh(&self) -> Self; } -pub enum RoundMode { - RoundDown, - RoundUp, - RoundToZero, - RoundFromZero +/// Methods that are harder to implement and not commonly used. +pub trait RealExt: Real { + // FIXME (#5527): usages of `int` should be replaced with an associated + // integer type once these are implemented + + // Gamma functions + fn lgamma(&self) -> (int, Self); + fn tgamma(&self) -> Self; + + // Bessel functions + fn j0(&self) -> Self; + fn j1(&self) -> Self; + fn jn(&self, n: int) -> Self; + fn y0(&self) -> Self; + fn y1(&self) -> Self; + fn yn(&self, n: int) -> Self; } /** diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index ec332adb8323b..c161bd4cf59e2 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -39,6 +39,7 @@ pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::{Times, ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; +pub use num::{Fractional, Real, RealExt}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From 11d04d452fa8fd8adde10f8de902bfffc59ab704 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 24 Apr 2013 19:54:13 -0400 Subject: [PATCH 392/403] add a Counter iterator --- src/libcore/iterator.rs | 45 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs index 4a3a98df0d0ea..8bbf843085809 100644 --- a/src/libcore/iterator.rs +++ b/src/libcore/iterator.rs @@ -312,6 +312,19 @@ impl> Iterator for TakeIterator { } } +pub struct ScanIterator<'self, A, B, T, St> { + priv iter: T, + priv f: &'self fn(&mut St, A) -> Option, + state: St +} + +impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, T, St> { + #[inline] + fn next(&mut self) -> Option { + self.iter.next().chain(|a| (self.f)(&mut self.state, a)) + } +} + pub struct UnfoldrIterator<'self, A, St> { priv f: &'self fn(&mut St) -> Option, state: St @@ -335,16 +348,25 @@ impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { } } -pub struct ScanIterator<'self, A, B, T, St> { - priv iter: T, - priv f: &'self fn(&mut St, A) -> Option, - state: St +/// An infinite iterator starting at `start` and advancing by `step` with each iteration +pub struct Counter { + state: A, + step: A } -impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, T, St> { - #[inline] - fn next(&mut self) -> Option { - self.iter.next().chain(|a| (self.f)(&mut self.state, a)) +pub impl Counter { + #[inline(always)] + fn new(start: A, step: A) -> Counter { + Counter{state: start, step: step} + } +} + +impl + Clone> Iterator for Counter { + #[inline(always)] + fn next(&mut self) -> Option { + let result = self.state.clone(); + self.state = self.state.add(&self.step); // FIXME: #6050 + Some(result) } } @@ -353,6 +375,13 @@ mod tests { use super::*; use prelude::*; + #[test] + fn test_counter_to_vec() { + let mut it = Counter::new(0, 5).take(10); + let xs = iter::iter_to_vec(|f| it.advance(f)); + assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); + } + #[test] fn test_iterator_chain() { let xs = [0u, 1, 2, 3, 4, 5]; From a74aca54826e19f8f125571cb8d72f6addb65a4c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 24 Apr 2013 20:39:29 -0400 Subject: [PATCH 393/403] Remove needless FIXME. Fixes #2811. --- src/libsyntax/ext/tt/transcribe.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 482e7b80339be..7ac924444b836 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -22,8 +22,6 @@ use core::hashmap::HashMap; use core::option; use core::vec; -/* FIXME #2811: figure out how to have a uniquely linked stack, and change to - `~` */ ///an unzipping of `token_tree`s struct TtFrame { forest: @mut ~[ast::token_tree], From 08109aa0ad3d53ff11202d2846652785ddefb02a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:47:55 -0700 Subject: [PATCH 394/403] core: Comments only -- move FIXME to correct location --- src/libcore/os.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 1000fd88b5246..62633837207f9 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -43,8 +43,6 @@ use vec; pub use libc::fclose; pub use os::consts::*; -// FIXME: move these to str perhaps? #2620 - pub fn close(fd: c_int) -> c_int { unsafe { libc::close(fd) @@ -79,6 +77,8 @@ pub fn getcwd() -> Path { } } +// FIXME: move these to str perhaps? #2620 + pub fn as_c_charp(s: &str, f: &fn(*c_char) -> T) -> T { str::as_c_str(s, |b| f(b as *c_char)) } From c2af1de95b65a0cc2225565f47aa9c08fd072371 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:48:21 -0700 Subject: [PATCH 395/403] rustpkg: update README saying which tests pass --- src/librustpkg/README.txt | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/librustpkg/README.txt b/src/librustpkg/README.txt index eacf07e01ea57..acfbf395e4bcd 100644 --- a/src/librustpkg/README.txt +++ b/src/librustpkg/README.txt @@ -1,4 +1,24 @@ -Right now (2013-04-11), only one package works, the branch of rust-sdl at: -https://github.com/catamorphism/rust-sdl/tree/new-rustpkg +Right now, commands that work are "build" and "clean". -and only one command works, "build". +`rustpkg build` and `rustpkg clean` should work + +for example: +$ cd ~/rust/src/librustpkg/testsuite/pass +$ rustpkg build hello-world +... some output ... +$ rustpkg clean hello-world + +------------- +the following test packages in librustpkg/testsuite/pass: + * hello-world + * install-paths + * simple-lib + * deeply/nested/path + * fancy-lib + + It fails on the following test packages: + * external-crate (no support for `extern mod` inference yet) + +and should fail with proper error messages +on all of the test packages in librustpkg/testsuite/fail + * no-inferred-crates From 6a3e26aa4062019629e144196a7852ef039f8b0a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:54:54 -0700 Subject: [PATCH 396/403] rustpkg: Make path searching work as described in the rustpkg doc rustpkg now searches for package directories in ./src rather than in . . I also added a rudimentary RUST_PATH that's currently hard-wired to the current directory. rustpkg now uses src/, lib/, and build/ directories as described in the manual. Most of the existing test scenarios build now; the README file (in a separate commit) explains which ones. --- src/librustpkg/path_util.rs | 168 +++++++++++++++++++++++++----------- src/librustpkg/rustpkg.rc | 158 +++++++++++++-------------------- src/librustpkg/util.rs | 15 +++- 3 files changed, 190 insertions(+), 151 deletions(-) diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index cd9b44c278e46..a8931e52747d9 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -15,39 +15,43 @@ use core::{os, str}; use core::option::*; use util::PkgId; -/// Returns the output directory to use. -/// Right now is always the default, should -/// support changing it. -pub fn dest_dir(pkgid: PkgId) -> Path { - default_dest_dir(&pkgid.path) +#[deriving(Eq)] +pub enum OutputType { Main, Lib, Bench, Test } + +/// Returns the value of RUST_PATH, as a list +/// of Paths. In general this should be read from the +/// environment; for now, it's hard-wired to just be "." +pub fn rust_path() -> ~[Path] { + ~[Path(".")] } -/// Returns the default output directory for compilation. -/// Creates that directory if it doesn't exist. -pub fn default_dest_dir(pkg_dir: &Path) -> Path { +/// Creates a directory that is readable, writeable, +/// and executable by the user. Returns true iff creation +/// succeeded. +pub fn make_dir_rwx(p: &Path) -> bool { use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; - use conditions::bad_path::cond; - // For now: assumes that pkg_dir exists and is relative - // to the CWD. Change this later when we do path searching. - let rslt = pkg_dir.push("build"); - let is_dir = os::path_is_dir(&rslt); - if os::path_exists(&rslt) { - if is_dir { - rslt - } - else { - cond.raise((rslt, ~"Path names a file that isn't a directory")) - } + os::make_dir(p, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) +} + +/// Creates a directory that is readable, writeable, +/// and executable by the user. Returns true iff creation +/// succeeded. Also creates all intermediate subdirectories +/// if they don't already exist. +pub fn mkdir_recursive(p: &Path) -> bool { + if os::path_is_dir(p) { + return true; + } + let parent = p.dir_path(); + debug!("mkdir_recursive: parent = %s", + parent.to_str()); + if parent.to_str() == ~"." + || parent.to_str() == ~"/" { // !!! + // No parent directories to create + os::path_is_dir(&parent) && make_dir_rwx(p) } else { - // Create it - if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { - rslt - } - else { - cond.raise((rslt, ~"Could not create directory")) - } + mkdir_recursive(&parent) && make_dir_rwx(p) } } @@ -69,34 +73,94 @@ pub fn normalize(p: ~Path) -> ~Path { } } +// n.b. So far this only handles local workspaces +// n.b. The next three functions ignore the package version right +// now. Should fix that. + +/// True if there's a directory in with +/// pkgid's short name +pub fn workspace_contains_package_id(pkgid: PkgId, workspace: &Path) -> bool { + let pkgpath = workspace.push("src").push(pkgid.path.to_str()); + os::path_is_dir(&pkgpath) +} + +/// Return the directory for 's source files in . +/// Doesn't check that it exists. +pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("src"); + result.push(pkgid.path.to_str()) +} + +/// Returns the executable that would be installed for +/// in +pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("bin"); + // should use a target-specific subdirectory + mk_output_path(Main, pkgid.path.to_str(), result) +} + + +/// Returns the executable that would be installed for +/// in +pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("lib"); + mk_output_path(Lib, pkgid.path.to_str(), result) +} + +/// Returns the test executable that would be installed for +/// in +pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("build"); + mk_output_path(Test, pkgid.path.to_str(), result) +} + +/// Returns the bench executable that would be installed for +/// in +pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + let result = workspace.push("build"); + mk_output_path(Bench, pkgid.path.to_str(), result) +} + +/// Return the directory for 's build artifacts in . +/// Creates it if it doesn't exist. +pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { + use conditions::bad_path::cond; + + let mut result = workspace.push("build"); + // n.b. Should actually use a target-specific + // subdirectory of build/ + result = result.push(normalize(~pkgid.path).to_str()); + if os::path_exists(&result) || mkdir_recursive(&result) { + result + } + else { + cond.raise((result, fmt!("Could not create directory for package %s", pkgid.to_str()))) + } +} + +/// Return the output file for a given directory name, +/// given whether we're building a library and whether we're building tests +pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path { + match what { + Lib => dir.push(os::dll_filename(short_name)), + _ => dir.push(fmt!("%s%s%s", short_name, + if what == Test { ~"test" } else { ~"" }, + os::EXE_SUFFIX)) + } +} + #[cfg(test)] mod test { - use core::{os, rand}; - use core::path::Path; - use path_util::*; - use core::rand::RngUtil; - - // Helper function to create a directory name that doesn't exist - pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { - let r = rand::rng(); - for 1000.times { - let p = tmpdir.push(r.gen_str(16) + suffix); - if !os::path_exists(&p) { - return p; - } - } - fail!(~"Couldn't compute a non-existent path name; this is worrisome") - } + use core::os; #[test] - fn default_dir_ok() { - let the_path = os::tmpdir(); - let substitute_path = Path("xyzzy"); - assert!(default_dest_dir(&the_path) == the_path.push(~"build")); - let nonexistent_path = mk_nonexistent(&the_path, "quux"); - let bogus = do ::conditions::bad_path::cond.trap(|_| { - substitute_path - }).in { default_dest_dir(&nonexistent_path) }; - assert!(bogus == substitute_path); + fn recursive_mkdir_ok() { + let root = os::tmpdir(); + let path = "xy/z/zy"; + let nested = root.push(path); + assert!(super::mkdir_recursive(&nested)); + assert!(os::path_is_dir(&root.push("xy"))); + assert!(os::path_is_dir(&root.push("xy/z"))); + assert!(os::path_is_dir(&nested)); } } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 705bcc8242750..8381e6ad816a8 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -36,7 +36,8 @@ use rustc::metadata::filesearch; use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use path_util::{dest_dir, normalize}; +use path_util::{normalize, workspace_contains_package_id}; +use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, rust_path}; use rustc::driver::session::{lib_crate, bin_crate, crate_type}; mod conditions; @@ -70,7 +71,7 @@ impl PkgScript { /// Given the path name for a package script /// and a package ID, parse the package script into /// a PkgScript that we can then execute - fn parse(script: Path, id: PkgId) -> PkgScript { + fn parse(script: Path, workspace: &Path, id: PkgId) -> PkgScript { // Get the executable name that was invoked let binary = os::args()[0]; // Build the rustc session data structures to pass @@ -85,7 +86,7 @@ impl PkgScript { let cfg = driver::build_configuration(sess, @binary, &input); let (crate, _) = driver::compile_upto(sess, cfg, &input, driver::cu_parse, None); - let work_dir = dest_dir(id); + let work_dir = build_pkg_id_in_workspace(id, workspace); debug!("Returning package script with id %?", id); @@ -193,54 +194,60 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - // Should allow the build directory to be configured. - // Right now it's always the "build" subdirectory in - // the package directory - let dst_dir = dest_dir(pkgid); - debug!("Destination dir = %s", dst_dir.to_str()); - // Right now, we assume the pkgid path is a valid dir - // relative to the CWD. In the future, we should search - // paths - let cwd = os::getcwd().normalize(); - debug!("Current working directory = %s", cwd.to_str()); - - // Create the package source - let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid); - debug!("Package src = %?", src); - - // Is there custom build logic? If so, use it - let pkg_src_dir = cwd.push_rel(&pkgid.path); - let mut custom = false;; - debug!("Package source directory = %s", pkg_src_dir.to_str()); - let cfgs = match src.package_script_option(&pkg_src_dir) { - Some(package_script_path) => { - let pscript = PkgScript::parse(package_script_path, - pkgid); - // Limited right now -- we're only running the post_build - // hook and probably fail otherwise - // also post_build should be called pre_build - let (cfgs, hook_result) = pscript.run_custom(~"post_build"); - debug!("Command return code = %?", hook_result); - if hook_result != 0 { - fail!(fmt!("Error running custom build command")) + // Using the RUST_PATH, find workspaces that contain + // this package ID + let workspaces = rust_path().filtered(|ws| + workspace_contains_package_id(pkgid, ws)); + if workspaces.is_empty() { + fail!(fmt!("Package %s not found in any of \ + the following workspaces: %s", + pkgid.path.to_str(), + rust_path().to_str())); + } + for workspaces.each |workspace| { + let src_dir = pkgid_src_in_workspace(pkgid, workspace); + let build_dir = build_pkg_id_in_workspace(pkgid, workspace); + debug!("Destination dir = %s", build_dir.to_str()); + + // Create the package source + let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid); + debug!("Package src = %?", src); + + // Is there custom build logic? If so, use it + let pkg_src_dir = src_dir; + let mut custom = false; + debug!("Package source directory = %s", pkg_src_dir.to_str()); + let cfgs = match src.package_script_option(&pkg_src_dir) { + Some(package_script_path) => { + let pscript = PkgScript::parse(package_script_path, + workspace, + pkgid); + // Limited right now -- we're only running the post_build + // hook and probably fail otherwise + // also post_build should be called pre_build + let (cfgs, hook_result) = pscript.run_custom(~"post_build"); + debug!("Command return code = %?", hook_result); + if hook_result != 0 { + fail!(fmt!("Error running custom build command")) + } + custom = true; + // otherwise, the package script succeeded + cfgs } - custom = true; - // otherwise, the package script succeeded - cfgs - } - None => { - debug!("No package script, continuing"); - ~[] + None => { + debug!("No package script, continuing"); + ~[] + } + }; + + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + // Find crates inside the workspace + src.find_crates(); + // Build it! + src.build(&build_dir, cfgs); } - }; - - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - // Find crates inside the workspace - src.find_crates(); - // Build it! - src.build(&dst_dir, cfgs); } } ~"clean" => { @@ -250,8 +257,8 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - - self.clean(pkgid); + let cwd = os::getcwd(); + self.clean(&cwd, pkgid); // tjc: should use workspace, not cwd } ~"do" => { if args.len() < 2 { @@ -304,57 +311,16 @@ impl Ctx { } fn do_cmd(&self, cmd: ~str, pkgname: ~str) { - match cmd { - ~"build" | ~"test" => { - util::error(~"that command cannot be manually called"); - fail!(~"do_cmd"); - } - _ => {} - } - - let cwd = &os::getcwd(); - let pkgid = PkgId::new(pkgname); - // Always use the "build" subdirectory of the package dir, - // but we should allow this to be configured - let dst_dir = dest_dir(pkgid); - - let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid); - match src.package_script_option(cwd) { - Some(script_path) => { - let script = PkgScript::parse(script_path, pkgid); - let (_, status) = script.run_custom(cmd); // Ignore cfgs? - if status == 42 { - util::error(~"no fns are listening for that cmd"); - fail!(~"do_cmd"); - } - } - None => { - util::error(fmt!("invoked `do`, but there is no package script in %s", - cwd.to_str())); - fail!(~"do_cmd"); - } - } - } - - fn build(&self, _dir: &Path, _verbose: bool, _opt: bool, - _test: bool) -> Option { - // either not needed anymore, - // or needed only when we don't have a package script. Not sure which one. - fail!(); - } - - fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str], - _cfgs: ~[~str], _opt: bool, _test: bool) { - // What's the difference between build and compile? - fail!(~"compile not yet implemented"); + // stub + fail!("`do` not yet implemented"); } - fn clean(&self, id: PkgId) { + fn clean(&self, workspace: &Path, id: PkgId) { // Could also support a custom build hook in the pkg // script for cleaning files rustpkg doesn't know about. // Do something reasonable for now - let dir = dest_dir(id); + let dir = build_pkg_id_in_workspace(id, workspace); util::note(fmt!("Cleaning package %s (removing directory %s)", id.to_str(), dir.to_str())); if os::path_exists(&dir) { diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 2ab1ea1e7d2ea..36d409adcd29c 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -116,7 +116,14 @@ pub impl PkgId { impl ToStr for PkgId { fn to_str(&self) -> ~str { // should probably use the filestem and not the whole path - fmt!("%s-%s", self.path.to_str(), self.version.to_str()) + fmt!("%s-%s", self.path.to_str(), + // Replace dots with -s in the version + // this is because otherwise rustc will think + // that foo-0.1 has .1 as its extension + // (Temporary hack until I figure out how to + // get rustc to not name the object file + // foo-0.o if I pass in foo-0.1 to build_output_filenames) + str::replace(self.version.to_str(), ".", "-")) } } @@ -438,7 +445,9 @@ pub fn compile_input(sysroot: Option, test: bool, crate_type: session::crate_type) -> bool { - let short_name = pkg_id.to_str(); + // Want just the directory component here + let pkg_filename = pkg_id.path.filename().expect(~"Weird pkg id"); + let short_name = fmt!("%s-%s", pkg_filename, pkg_id.version.to_str()); assert!(in_file.components.len() > 1); let input = driver::file_input(copy *in_file); @@ -515,7 +524,7 @@ pub fn compile_crate_from_input(input: driver::input, out_file: Path, binary: ~str, what: driver::compile_upto) -> @ast::crate { - debug!("Calling build_output_filenames with %?", build_dir_opt); + debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str()); let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess); debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); let cfg = driver::build_configuration(sess, @binary, &input); From f945e57bd050227bbf92f151303785991173f2fe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 22 Apr 2013 17:56:15 -0700 Subject: [PATCH 397/403] rustpkg: Correct directory structure in test scenarios --- .../testsuite/pass/src/fancy-lib/{src => }/bar.rs | 0 .../pass/src/fancy-lib/{src => }/fancy-lib.rs | 2 +- .../testsuite/pass/src/fancy-lib/{src => }/foo.rs | 0 .../testsuite/pass/src/fancy-lib/pkg.rs | 15 ++++++++++----- .../pass/src/hello-world/{src => }/main.rs | 0 .../pass/src/install-paths/{src => }/bench.rs | 0 .../pass/src/install-paths/{src => }/lib.rs | 0 .../pass/src/install-paths/{src => }/main.rs | 0 .../pass/src/install-paths/{src => }/test.rs | 0 9 files changed, 11 insertions(+), 6 deletions(-) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/bar.rs (100%) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/fancy-lib.rs (92%) rename src/librustpkg/testsuite/pass/src/fancy-lib/{src => }/foo.rs (100%) rename src/librustpkg/testsuite/pass/src/hello-world/{src => }/main.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/bench.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/lib.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/main.rs (100%) rename src/librustpkg/testsuite/pass/src/install-paths/{src => }/test.rs (100%) diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/bar.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/bar.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/bar.rs diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs similarity index 92% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs index 55261a820981a..dc068eed143ef 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/src/fancy-lib.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/fancy-lib.rs @@ -21,4 +21,4 @@ extern mod std; pub mod foo; pub mod bar; -#[path = "build/generated.rs"] pub mod generated; +#[path = "../../build/fancy_lib/generated.rs"] pub mod generated; diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/foo.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/fancy-lib/src/foo.rs rename to src/librustpkg/testsuite/pass/src/fancy-lib/foo.rs diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs index be3c68d731b23..eeaa0f68ed531 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs @@ -11,13 +11,18 @@ use core::run; pub fn main() { - let cwd = os::getcwd(); - debug!("cwd = %s", cwd.to_str()); - let file = io::file_writer(&Path(~"fancy-lib/build/generated.rs"), + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + let out_path = Path(~"build/fancy_lib"); + if !os::path_exists(&out_path) { + assert!(os::make_dir(&out_path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); + } + + let file = io::file_writer(&out_path.push("generated.rs"), [io::Create]).get(); file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }"); // now compile the crate itself - run::run_program("rustc", ~[~"fancy-lib/fancy-lib.rs", ~"--lib", - ~"-o", ~"fancy-lib/build/fancy_lib"]); + run::run_program("rustc", ~[~"src/fancy-lib/fancy-lib.rs", ~"--lib", + ~"-o", out_path.push(~"fancy_lib").to_str()]); } \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/src/hello-world/src/main.rs b/src/librustpkg/testsuite/pass/src/hello-world/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/hello-world/src/main.rs rename to src/librustpkg/testsuite/pass/src/hello-world/main.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs b/src/librustpkg/testsuite/pass/src/install-paths/bench.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/bench.rs rename to src/librustpkg/testsuite/pass/src/install-paths/bench.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs b/src/librustpkg/testsuite/pass/src/install-paths/lib.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/lib.rs rename to src/librustpkg/testsuite/pass/src/install-paths/lib.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/main.rs b/src/librustpkg/testsuite/pass/src/install-paths/main.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/main.rs rename to src/librustpkg/testsuite/pass/src/install-paths/main.rs diff --git a/src/librustpkg/testsuite/pass/src/install-paths/src/test.rs b/src/librustpkg/testsuite/pass/src/install-paths/test.rs similarity index 100% rename from src/librustpkg/testsuite/pass/src/install-paths/src/test.rs rename to src/librustpkg/testsuite/pass/src/install-paths/test.rs From 4e2c8f422aec1aef910fdfdac57f5f66a7465355 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 24 Apr 2013 17:37:59 -0700 Subject: [PATCH 398/403] rustpkg: Preliminary work on install command Mostly just tests (that are ignored); install command is still stubbed out. --- src/librustpkg/conditions.rs | 5 ++ src/librustpkg/context.rs | 21 ++++++++ src/librustpkg/rustpkg.rc | 50 ++++++++----------- src/librustpkg/tests.rs | 93 ++++++++++++++++++++++++++++++++++++ src/librustpkg/util.rs | 2 +- src/librustpkg/workspace.rs | 34 +++++++++++++ 6 files changed, 175 insertions(+), 30 deletions(-) create mode 100644 src/librustpkg/context.rs create mode 100644 src/librustpkg/workspace.rs diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs index 353995a816e37..35e70af7914c1 100644 --- a/src/librustpkg/conditions.rs +++ b/src/librustpkg/conditions.rs @@ -11,7 +11,12 @@ // Useful conditions pub use core::path::Path; +pub use util::PkgId; condition! { bad_path: (super::Path, ~str) -> super::Path; } + +condition! { + nonexistent_package: (super::PkgId, ~str) -> super::Path; +} diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs new file mode 100644 index 0000000000000..db036f44a185b --- /dev/null +++ b/src/librustpkg/context.rs @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Context data structure used by rustpkg + +use core::hashmap::HashMap; + +pub struct Ctx { + // I'm not sure what this is for + json: bool, + // Cache of hashes of things already installed + // though I'm not sure why the value is a bool + dep_cache: @mut HashMap<~str, bool>, +} diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 8381e6ad816a8..e1edce6ce5b6a 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -36,14 +36,19 @@ use rustc::metadata::filesearch; use std::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use path_util::{normalize, workspace_contains_package_id}; -use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, rust_path}; +use path_util::normalize; +use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace}; +use workspace::pkg_parent_workspaces; use rustc::driver::session::{lib_crate, bin_crate, crate_type}; +use context::Ctx; mod conditions; +mod context; mod usage; mod path_util; +mod tests; mod util; +mod workspace; /// A PkgScript represents user-supplied custom logic for /// special build hooks. This only exists for packages with @@ -154,14 +159,6 @@ impl PkgScript { } -struct Ctx { - // I'm not sure what this is for - json: bool, - // Cache of hashes of things already installed - // though I'm not sure why the value is a bool - dep_cache: @mut HashMap<~str, bool>, -} - impl Ctx { fn run(&self, cmd: ~str, args: ~[~str]) { @@ -194,17 +191,7 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - // Using the RUST_PATH, find workspaces that contain - // this package ID - let workspaces = rust_path().filtered(|ws| - workspace_contains_package_id(pkgid, ws)); - if workspaces.is_empty() { - fail!(fmt!("Package %s not found in any of \ - the following workspaces: %s", - pkgid.path.to_str(), - rust_path().to_str())); - } - for workspaces.each |workspace| { + for pkg_parent_workspaces(pkgid) |workspace| { let src_dir = pkgid_src_in_workspace(pkgid, workspace); let build_dir = build_pkg_id_in_workspace(pkgid, workspace); debug!("Destination dir = %s", build_dir.to_str()); @@ -271,10 +258,16 @@ impl Ctx { self.info(); } ~"install" => { - self.install(if args.len() >= 1 { Some(args[0]) } - else { None }, - if args.len() >= 2 { Some(args[1]) } - else { None }, false); + if args.len() < 1 { + return usage::install(); + } + + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(args[0]); + for pkg_parent_workspaces(pkgid) |workspace| { + self.install(workspace, pkgid); + } } ~"prefer" => { if args.len() < 1 { @@ -310,9 +303,9 @@ impl Ctx { } } - fn do_cmd(&self, cmd: ~str, pkgname: ~str) { + fn do_cmd(&self, _cmd: ~str, _pkgname: ~str) { // stub - fail!("`do` not yet implemented"); + fail!(~"`do` not yet implemented"); } fn clean(&self, workspace: &Path, id: PkgId) { @@ -336,8 +329,7 @@ impl Ctx { fail!(~"info not yet implemented"); } - fn install(&self, _url: Option<~str>, - _target: Option<~str>, _cache: bool) { + fn install(&self, _workspace: &Path, _id: PkgId) { // stub fail!(~"install not yet implemented"); } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index f594860607255..70c03c845ce60 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -9,3 +9,96 @@ // except according to those terms. // rustpkg unit tests + +use context::Ctx; +use core::hashmap::HashMap; +use core::path::Path; +use core::os; +use core::io; +use core::option::*; +use std::tempfile::mkdtemp; +use util::{PkgId, default_version}; +use path_util::{target_executable_in_workspace, target_library_in_workspace, + target_test_in_workspace, target_bench_in_workspace, + make_dir_rwx}; + +fn fake_ctxt() -> Ctx { + Ctx { + json: false, + dep_cache: @mut HashMap::new() + } +} + +fn fake_pkg() -> PkgId { + PkgId { + path: Path(~"bogus"), + version: default_version() + } +} + +fn mk_temp_workspace() -> Path { + mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir") +} + +fn is_rwx(p: &Path) -> bool { + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + match p.get_mode() { + None => return false, + Some(m) => { + ((m & S_IRUSR as uint) == S_IRUSR as uint + && (m & S_IWUSR as uint) == S_IWUSR as uint + && (m & S_IXUSR as uint) == S_IXUSR as uint) + } + } +} + +#[test] +fn test_make_dir_rwx() { + let temp = &os::tmpdir(); + let dir = temp.push(~"quux"); + let _ = os::remove_dir(&dir); + assert!(make_dir_rwx(&dir)); + assert!(os::path_is_dir(&dir)); + assert!(is_rwx(&dir)); + assert!(os::remove_dir(&dir)); +} + +#[test] +#[ignore(reason = "install not yet implemented")] +fn test_install_valid() { + let ctxt = fake_ctxt(); + let temp_pkg_id = fake_pkg(); + let temp_workspace() = mk_temp_workspace(); + // should have test, bench, lib, and main + ctxt.install(&temp_workspace, temp_pkg_id); + // Check that all files exist + let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace); + assert!(os::path_exists(&exec)); + assert!(is_rwx(&exec)); + let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace); + assert!(os::path_exists(&lib)); + assert!(is_rwx(&lib)); + // And that the test and bench executables aren't installed + assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace))); + assert!(!os::path_exists(&target_bench_in_workspace(temp_pkg_id, &temp_workspace))); +} + +#[test] +#[ignore(reason = "install not yet implemented")] +fn test_install_invalid() { + use conditions::nonexistent_package::cond; + + let ctxt = fake_ctxt(); + let pkgid = fake_pkg(); + let temp_workspace = mk_temp_workspace(); + let expected_path = Path(~"quux"); + let substituted: Path = do cond.trap(|_| { + expected_path + }).in { + ctxt.install(&temp_workspace, pkgid); + // ok + fail!(~"test_install_invalid failed, should have raised a condition"); + }; + assert!(substituted == expected_path); +} \ No newline at end of file diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 36d409adcd29c..28198e59f86d4 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -78,7 +78,7 @@ impl ToStr for Version { } /// Placeholder -fn default_version() -> Version { ExactRevision(0.1) } +pub fn default_version() -> Version { ExactRevision(0.1) } // Path-fragment identifier of a package such as // 'github.com/graydon/test'; path must be a relative diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs new file mode 100644 index 0000000000000..15e2166b24abe --- /dev/null +++ b/src/librustpkg/workspace.rs @@ -0,0 +1,34 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg utilities having to do with workspaces + +use path_util::{rust_path, workspace_contains_package_id}; +use util::PkgId; +use core::path::Path; + +pub fn pkg_parent_workspaces(pkgid: PkgId, action: &fn(&Path) -> bool) { + // Using the RUST_PATH, find workspaces that contain + // this package ID + let workspaces = rust_path().filtered(|ws| + workspace_contains_package_id(pkgid, ws)); + if workspaces.is_empty() { + // tjc: make this a condition + fail!(fmt!("Package %s not found in any of \ + the following workspaces: %s", + pkgid.path.to_str(), + rust_path().to_str())); + } + for workspaces.each |ws| { + if action(ws) { + break; + } + } +} \ No newline at end of file From 48c24188f9191888110ebea2bc5193de9a0b26d5 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 25 Apr 2013 11:53:04 +1000 Subject: [PATCH 399/403] Restore Round trait and move appropriate methods out of Real --- src/libcore/core.rc | 2 +- src/libcore/num/f32.rs | 114 +++++++++++++++++++++++++++++++----- src/libcore/num/f64.rs | 117 +++++++++++++++++++++++++++++++------ src/libcore/num/float.rs | 123 +++++++++++++++++++++++++++++++-------- src/libcore/num/num.rs | 16 ++--- src/libcore/prelude.rs | 2 +- 6 files changed, 307 insertions(+), 67 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 0a24fba666334..71bbaf557ce38 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -105,7 +105,7 @@ pub use iter::{ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; -pub use num::{Fractional, Real, RealExt}; +pub use num::{Round, Fractional, Real, RealExt}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 57ac6c551766b..7d5807ba5462c 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -327,6 +327,34 @@ impl Signed for f32 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } +impl Round for f32 { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> f32 { floor(*self) } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> f32 { ceil(*self) } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> f32 { round(*self) } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> f32 { trunc(*self) } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> f32 { *self - self.trunc() } +} + impl Fractional for f32 { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -402,22 +430,6 @@ impl Real for f32 { #[inline(always)] fn log_10() -> f32 { 2.30258509299404568401799145468436421 } - #[inline(always)] - fn floor(&self) -> f32 { floor(*self) } - - #[inline(always)] - fn ceil(&self) -> f32 { ceil(*self) } - - #[inline(always)] - fn round(&self) -> f32 { round(*self) } - - #[inline(always)] - fn trunc(&self) -> f32 { trunc(*self) } - - /// The fractional part of the number, calculated using: `n - floor(n)` - #[inline(always)] - fn fract(&self) -> f32 { *self - self.floor() } - #[inline(always)] fn pow(&self, n: f32) -> f32 { pow(*self, n) } @@ -736,6 +748,76 @@ mod tests { num::test_num(10f32, 2f32); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.3f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.5f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.7f32.floor(), 1.0f32); + assert_fuzzy_eq!(0.0f32.floor(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).floor(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).floor(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).floor(), -2.0f32); + assert_fuzzy_eq!((-1.5f32).floor(), -2.0f32); + assert_fuzzy_eq!((-1.7f32).floor(), -2.0f32); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f32.ceil(), 1.0f32); + assert_fuzzy_eq!(1.3f32.ceil(), 2.0f32); + assert_fuzzy_eq!(1.5f32.ceil(), 2.0f32); + assert_fuzzy_eq!(1.7f32.ceil(), 2.0f32); + assert_fuzzy_eq!(0.0f32.ceil(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).ceil(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.7f32).ceil(), -1.0f32); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f32.round(), 1.0f32); + assert_fuzzy_eq!(1.3f32.round(), 1.0f32); + assert_fuzzy_eq!(1.5f32.round(), 2.0f32); + assert_fuzzy_eq!(1.7f32.round(), 2.0f32); + assert_fuzzy_eq!(0.0f32.round(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).round(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).round(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).round(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).round(), -2.0f32); + assert_fuzzy_eq!((-1.7f32).round(), -2.0f32); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.3f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.5f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.7f32.trunc(), 1.0f32); + assert_fuzzy_eq!(0.0f32.trunc(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).trunc(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.7f32).trunc(), -1.0f32); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f32.fract(), 0.0f32); + assert_fuzzy_eq!(1.3f32.fract(), 0.3f32); + assert_fuzzy_eq!(1.5f32.fract(), 0.5f32); + assert_fuzzy_eq!(1.7f32.fract(), 0.7f32); + assert_fuzzy_eq!(0.0f32.fract(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).fract(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).fract(), -0.0f32); + assert_fuzzy_eq!((-1.3f32).fract(), -0.3f32); + assert_fuzzy_eq!((-1.5f32).fract(), -0.5f32); + assert_fuzzy_eq!((-1.7f32).fract(), -0.7f32); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2f32 * Real::pi::()); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 53ad78c29f392..3b6198bfc472e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -337,6 +337,34 @@ impl Signed for f64 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } +impl Round for f64 { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> f64 { floor(*self) } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> f64 { ceil(*self) } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> f64 { round(*self) } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> f64 { trunc(*self) } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> f64 { *self - self.trunc() } +} + impl Fractional for f64 { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -412,22 +440,6 @@ impl Real for f64 { #[inline(always)] fn log_10() -> f64 { 2.30258509299404568401799145468436421 } - #[inline(always)] - fn floor(&self) -> f64 { floor(*self) } - - #[inline(always)] - fn ceil(&self) -> f64 { ceil(*self) } - - #[inline(always)] - fn round(&self) -> f64 { round(*self) } - - #[inline(always)] - fn trunc(&self) -> f64 { trunc(*self) } - - /// The fractional part of the number, calculated using: `n - floor(n)` - #[inline(always)] - fn fract(&self) -> f64 { *self - self.floor() } - #[inline(always)] fn pow(&self, n: f64) -> f64 { pow(*self, n) } @@ -766,7 +778,8 @@ mod tests { ($a:expr, $b:expr) => ({ let a = $a, b = $b; if !((a - b).abs() < 1.0e-6) { - fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b)); + fail!(fmt!("The values were not approximately equal. \ + Found: %? and expected %?", a, b)); } }) ) @@ -776,6 +789,76 @@ mod tests { num::test_num(10f64, 2f64); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.3f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.5f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.7f64.floor(), 1.0f64); + assert_fuzzy_eq!(0.0f64.floor(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).floor(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).floor(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).floor(), -2.0f64); + assert_fuzzy_eq!((-1.5f64).floor(), -2.0f64); + assert_fuzzy_eq!((-1.7f64).floor(), -2.0f64); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f64.ceil(), 1.0f64); + assert_fuzzy_eq!(1.3f64.ceil(), 2.0f64); + assert_fuzzy_eq!(1.5f64.ceil(), 2.0f64); + assert_fuzzy_eq!(1.7f64.ceil(), 2.0f64); + assert_fuzzy_eq!(0.0f64.ceil(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).ceil(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.7f64).ceil(), -1.0f64); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f64.round(), 1.0f64); + assert_fuzzy_eq!(1.3f64.round(), 1.0f64); + assert_fuzzy_eq!(1.5f64.round(), 2.0f64); + assert_fuzzy_eq!(1.7f64.round(), 2.0f64); + assert_fuzzy_eq!(0.0f64.round(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).round(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).round(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).round(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).round(), -2.0f64); + assert_fuzzy_eq!((-1.7f64).round(), -2.0f64); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.3f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.5f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.7f64.trunc(), 1.0f64); + assert_fuzzy_eq!(0.0f64.trunc(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).trunc(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.7f64).trunc(), -1.0f64); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f64.fract(), 0.0f64); + assert_fuzzy_eq!(1.3f64.fract(), 0.3f64); + assert_fuzzy_eq!(1.5f64.fract(), 0.5f64); + assert_fuzzy_eq!(1.7f64.fract(), 0.7f64); + assert_fuzzy_eq!(0.0f64.fract(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).fract(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).fract(), -0.0f64); + assert_fuzzy_eq!((-1.3f64).fract(), -0.3f64); + assert_fuzzy_eq!((-1.5f64).fract(), -0.5f64); + assert_fuzzy_eq!((-1.7f64).fract(), -0.7f64); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2.0 * Real::pi::()); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index ae2d0ce0d7194..9c0412b422f52 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -403,6 +403,34 @@ impl num::One for float { fn one() -> float { 1.0 } } +impl Round for float { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> float { floor(*self as f64) as float } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> float { ceil(*self as f64) as float } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> float { round(*self as f64) as float } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> float { trunc(*self as f64) as float } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> float { *self - self.trunc() } +} + impl Fractional for float { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -478,22 +506,6 @@ impl Real for float { #[inline(always)] fn log_10() -> float { 2.30258509299404568401799145468436421 } - #[inline(always)] - fn floor(&self) -> float { floor(*self as f64) as float } - - #[inline(always)] - fn ceil(&self) -> float { ceil(*self as f64) as float } - - #[inline(always)] - fn round(&self) -> float { round(*self as f64) as float } - - #[inline(always)] - fn trunc(&self) -> float { trunc(*self as f64) as float } - - /// The fractional part of the number, calculated using: `n - floor(n)` - #[inline(always)] - fn fract(&self) -> float { *self - self.floor() } - #[inline(always)] fn pow(&self, n: float) -> float { pow(*self as f64, n as f64) as float } @@ -694,6 +706,76 @@ mod tests { num::test_num(10f, 2f); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f.floor(), 1.0f); + assert_fuzzy_eq!(1.3f.floor(), 1.0f); + assert_fuzzy_eq!(1.5f.floor(), 1.0f); + assert_fuzzy_eq!(1.7f.floor(), 1.0f); + assert_fuzzy_eq!(0.0f.floor(), 0.0f); + assert_fuzzy_eq!((-0.0f).floor(), -0.0f); + assert_fuzzy_eq!((-1.0f).floor(), -1.0f); + assert_fuzzy_eq!((-1.3f).floor(), -2.0f); + assert_fuzzy_eq!((-1.5f).floor(), -2.0f); + assert_fuzzy_eq!((-1.7f).floor(), -2.0f); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f.ceil(), 1.0f); + assert_fuzzy_eq!(1.3f.ceil(), 2.0f); + assert_fuzzy_eq!(1.5f.ceil(), 2.0f); + assert_fuzzy_eq!(1.7f.ceil(), 2.0f); + assert_fuzzy_eq!(0.0f.ceil(), 0.0f); + assert_fuzzy_eq!((-0.0f).ceil(), -0.0f); + assert_fuzzy_eq!((-1.0f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.3f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.5f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.7f).ceil(), -1.0f); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f.round(), 1.0f); + assert_fuzzy_eq!(1.3f.round(), 1.0f); + assert_fuzzy_eq!(1.5f.round(), 2.0f); + assert_fuzzy_eq!(1.7f.round(), 2.0f); + assert_fuzzy_eq!(0.0f.round(), 0.0f); + assert_fuzzy_eq!((-0.0f).round(), -0.0f); + assert_fuzzy_eq!((-1.0f).round(), -1.0f); + assert_fuzzy_eq!((-1.3f).round(), -1.0f); + assert_fuzzy_eq!((-1.5f).round(), -2.0f); + assert_fuzzy_eq!((-1.7f).round(), -2.0f); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f.trunc(), 1.0f); + assert_fuzzy_eq!(1.3f.trunc(), 1.0f); + assert_fuzzy_eq!(1.5f.trunc(), 1.0f); + assert_fuzzy_eq!(1.7f.trunc(), 1.0f); + assert_fuzzy_eq!(0.0f.trunc(), 0.0f); + assert_fuzzy_eq!((-0.0f).trunc(), -0.0f); + assert_fuzzy_eq!((-1.0f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.3f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.5f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.7f).trunc(), -1.0f); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f.fract(), 0.0f); + assert_fuzzy_eq!(1.3f.fract(), 0.3f); + assert_fuzzy_eq!(1.5f.fract(), 0.5f); + assert_fuzzy_eq!(1.7f.fract(), 0.7f); + assert_fuzzy_eq!(0.0f.fract(), 0.0f); + assert_fuzzy_eq!((-0.0f).fract(), -0.0f); + assert_fuzzy_eq!((-1.0f).fract(), -0.0f); + assert_fuzzy_eq!((-1.3f).fract(), -0.3f); + assert_fuzzy_eq!((-1.5f).fract(), -0.5f); + assert_fuzzy_eq!((-1.7f).fract(), -0.7f); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2f * Real::pi::()); @@ -893,15 +975,6 @@ mod tests { assert_eq!(to_str_digits(infinity, 10u), ~"inf"); assert_eq!(to_str_digits(-infinity, 10u), ~"-inf"); } - - #[test] - pub fn test_round() { - assert_eq!(round(5.8), 6.0); - assert_eq!(round(5.2), 5.0); - assert_eq!(round(3.0), 3.0); - assert_eq!(round(2.5), 3.0); - assert_eq!(round(-3.5), -4.0); - } } // diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 733b37e2a4a62..e19afdc69c32f 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -77,8 +77,17 @@ pub trait Integer: Num fn is_odd(&self) -> bool; } +pub trait Round { + fn floor(&self) -> Self; + fn ceil(&self) -> Self; + fn round(&self) -> Self; + fn trunc(&self) -> Self; + fn fract(&self) -> Self; +} + pub trait Fractional: Num + Ord + + Round + Quot { fn recip(&self) -> Self; } @@ -108,13 +117,6 @@ pub trait Real: Signed fn log_2() -> Self; fn log_10() -> Self; - // Rounding operations - fn floor(&self) -> Self; - fn ceil(&self) -> Self; - fn round(&self) -> Self; - fn trunc(&self) -> Self; - fn fract(&self) -> Self; - // Exponential functions fn pow(&self, n: Self) -> Self; fn exp(&self) -> Self; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index c161bd4cf59e2..553bb8268102b 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -39,7 +39,7 @@ pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter}; pub use iter::{Times, ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; -pub use num::{Fractional, Real, RealExt}; +pub use num::{Round, Fractional, Real, RealExt}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From 225ac216157cf530332cef1c926875e2023e48e6 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 25 Apr 2013 11:53:51 +1000 Subject: [PATCH 400/403] Update impl of Round for Ratio --- src/libstd/num/rational.rs | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs index 36652380bff58..8af1d99fa4719 100644 --- a/src/libstd/num/rational.rs +++ b/src/libstd/num/rational.rs @@ -204,20 +204,6 @@ impl /* Utils */ impl Round for Ratio { - fn round(&self, mode: num::RoundMode) -> Ratio { - match mode { - num::RoundUp => { self.ceil() } - num::RoundDown => { self.floor()} - num::RoundToZero => { Ratio::from_integer(self.numer / self.denom) } - num::RoundFromZero => { - if *self < Zero::zero() { - Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) - } else { - Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) - } - } - } - } fn floor(&self) -> Ratio { if *self < Zero::zero() { @@ -226,6 +212,7 @@ impl Ratio::from_integer(self.numer / self.denom) } } + fn ceil(&self) -> Ratio { if *self < Zero::zero() { Ratio::from_integer(self.numer / self.denom) @@ -233,6 +220,21 @@ impl Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) } } + + #[inline(always)] + fn round(&self) -> Ratio { + if *self < Zero::zero() { + Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) + } else { + Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) + } + } + + #[inline(always)] + fn trunc(&self) -> Ratio { + Ratio::from_integer(self.numer / self.denom) + } + fn fract(&self) -> Ratio { Ratio::new_raw(self.numer % self.denom, self.denom) } @@ -421,18 +423,18 @@ mod test { fn test_round() { assert_eq!(_1_2.ceil(), _1); assert_eq!(_1_2.floor(), _0); - assert_eq!(_1_2.round(num::RoundToZero), _0); - assert_eq!(_1_2.round(num::RoundFromZero), _1); + assert_eq!(_1_2.round(), _1); + assert_eq!(_1_2.trunc(), _0); assert_eq!(_neg1_2.ceil(), _0); assert_eq!(_neg1_2.floor(), -_1); - assert_eq!(_neg1_2.round(num::RoundToZero), _0); - assert_eq!(_neg1_2.round(num::RoundFromZero), -_1); + assert_eq!(_neg1_2.round(), -_1); + assert_eq!(_neg1_2.trunc(), _0); assert_eq!(_1.ceil(), _1); assert_eq!(_1.floor(), _1); - assert_eq!(_1.round(num::RoundToZero), _1); - assert_eq!(_1.round(num::RoundFromZero), _1); + assert_eq!(_1.round(), _1); + assert_eq!(_1.trunc(), _1); } #[test] From 92bf9b68da05504e925e2b66ceb9f3e5f1a5b0ee Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Wed, 24 Apr 2013 22:33:13 -0400 Subject: [PATCH 401/403] Add basic documentation for with_capacity --- src/libcore/vec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index e478936ff65cc..f5ed574527d2d 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -173,6 +173,7 @@ pub fn from_slice(t: &[T]) -> ~[T] { from_fn(t.len(), |i| t[i]) } +/// Creates a new vector with a capacity of `capacity` pub fn with_capacity(capacity: uint) -> ~[T] { let mut vec = ~[]; reserve(&mut vec, capacity); From 91fb7b282de4877e72f22f42b4535e3c76732264 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Wed, 24 Apr 2013 22:33:48 -0400 Subject: [PATCH 402/403] Move documentation for vec::windowed where it will be generated --- src/libcore/vec.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index f5ed574527d2d..a56f69f4ae9ff 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1566,6 +1566,16 @@ pub fn each_permutation(v: &[T], put: &fn(ts: &[T]) -> bool) { } } +// see doc below +#[cfg(stage0)] // XXX: lifetimes! +pub fn windowed(n: uint, v: &[T], it: &fn(&[T]) -> bool) { + assert!(1u <= n); + if n > v.len() { return; } + for uint::range(0, v.len() - n + 1) |i| { + if !it(v.slice(i, i+n)) { return } + } +} + /** * Iterate over all contiguous windows of length `n` of the vector `v`. * @@ -1580,14 +1590,6 @@ pub fn each_permutation(v: &[T], put: &fn(ts: &[T]) -> bool) { * ~~~ * */ -#[cfg(stage0)] // XXX: lifetimes! -pub fn windowed(n: uint, v: &[T], it: &fn(&[T]) -> bool) { - assert!(1u <= n); - if n > v.len() { return; } - for uint::range(0, v.len() - n + 1) |i| { - if !it(v.slice(i, i+n)) { return } - } -} #[cfg(stage1)] #[cfg(stage2)] #[cfg(stage3)] From 2c99e3dc3effce7e33b817aeb3f300e4e1a1c382 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 26 Apr 2013 13:35:01 -0700 Subject: [PATCH 403/403] Suppress all 'cond' errors in valgrind. #5856 --- src/etc/x86.supp | 164 +---------------------------------------------- 1 file changed, 2 insertions(+), 162 deletions(-) diff --git a/src/etc/x86.supp b/src/etc/x86.supp index 1253b5ffc06c9..417f4c9d2c199 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -366,76 +366,6 @@ ... } -{ - enum-instruction-scheduling-1 - Memcheck:Cond - fun:*fold_mod* - ... -} - -{ - enum-instruction-scheduling-2 - Memcheck:Cond - fun:*fold_nmod* - ... -} - -{ - enum-instruction-scheduling-3 - Memcheck:Cond - fun:*fold_crate* - ... -} - -{ - enum-instruction-scheduling-4 - Memcheck:Cond - fun:*fold_enum* - ... -} - -{ - enum-instruction-scheduling-5 - Memcheck:Cond - fun:*write_variant* - ... -} - -{ - enum-instruction-scheduling-6 - Memcheck:Cond - fun:*merge_method_attrs* - ... -} - -{ - enum-instruction-scheduling-7 - Memcheck:Cond - fun:*parse_config_* - ... -} - -{ - enum-instruction-scheduling-8 - Memcheck:Cond - fun:*should_set_output_format_to_markdown_if_requested* - ... -} - -{ - enum-instruction-scheduling-9 - Memcheck:Cond - fun:*get_authority* - ... -} - -{ - enum-instruction-scheduling-10 - Memcheck:Cond - fun:*config_from_opts* - ... -} - { llvm-user-new-leak Memcheck:Leak @@ -567,98 +497,8 @@ } { - llvm-optimization-reads-uninitialized-memory-1 - Memcheck:Cond - fun:_ZN4test17run_tests_console4anon13expr_fn* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-2 - Memcheck:Cond - fun:_ZN4test17run_tests_console* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-3 - Memcheck:Cond - fun:_ZN4test9run_tests* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-4 - Memcheck:Cond - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-5 - Memcheck:Cond - fun:_ZN4fold25noop_fold_item_underscore* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-6 - Memcheck:Cond - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn17* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-9 - Memcheck:Cond - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_foreign_fn* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-11 - Memcheck:Cond - fun:_ZN4fold22noop_fold_foreign_item17_* - ... -} - - -{ - llvm-optimization-reads-uninitialized-memory-12 - Memcheck:Cond - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_struct* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-13 - Memcheck:Cond - fun:_ZN5parse6parser14__extensions__10meth_*parse_item_type* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-14 - Memcheck:Cond - fun:_ZN7ast_map6map_fn16_* - fun:_ZN5visit30visit_struct_dtor_helper_* - obj:* - fun:_ZN8unstable6extfmt2rt14__extensions__10meth_* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-15 - Memcheck:Cond - fun:_ZN7ast_map6map_fn16_* - fun:_ZN5visit30visit_struct_dtor_helper_* - ... -} - -{ - llvm-optimization-reads-uninitialized-memory-16 + goddammit-llvm-why-u-no-valgrind Memcheck:Cond - fun:_ZN7ast_map6map_fn* - fun:_ZN5visit30visit_struct_dtor_helper* + fun:* ... }