I'm not happy about the hand-waving around `cmp`, but I'm not sure how to get around it.
* A new facility for enabling experimental features (feature gating) has
been added, using the crate-level `#[feature(foo)]` attribute.
* Managed boxes (@) are now behind a feature gate
- (`#[feature(managed_boxes)]`) in preperation for future removal. Use the
+ (`#[feature(managed_boxes)]`) in preparation for future removal. Use the
standard library's `Gc` or `Rc` types instead.
* `@mut` has been removed. Use `std::cell::{Cell, RefCell}` instead.
* Jumping back to the top of a loop is now done with `continue` instead of
* std: `fmt::Default` can be implemented for any type to provide default
formatting to the `format!` macro, as in `format!("{}", myfoo)`.
* std: The `rand` API continues to be tweaked.
- * std: The `rust_begin_unwind` function, useful for insterting breakpoints
+ * std: The `rust_begin_unwind` function, useful for inserting breakpoints
on failure in gdb, is now named `rust_fail`.
* std: The `each_key` and `each_value` methods on `HashMap` have been
replaced by the `keys` and `values` iterators.
extensible interfaces and is now implemented by two different crates:
libnative, for native threading and I/O; and libgreen, for green threading
and I/O. This paves the way for using the standard library in more limited
- embeded environments.
+ embedded environments.
* std: The `comm` module has been rewritten to be much faster, have a
simpler, more consistent API, and to work for both native and green
threading.
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
-opt rpath 1 "build rpaths into rustc itself"
+opt rpath 0 "build rpaths into rustc itself"
opt nightly 0 "build nightly packages"
opt verify-install 1 "verify installed binaries work"
opt jemalloc 1 "build liballoc with jemalloc"
If specified, the compiler will save more files (.bc, .o, .no-opt.bc) generated
throughout compilation in the output directory.
.TP
-\fBno-rpath\fR
-If specified, then the rpath value for dynamic libraries will not be set in
+\fBrpath\fR
+If specified, then the rpath value for dynamic libraries will be set in
either dynamic library or executable outputs.
.TP
\fBno-prepopulate-passes\fR
CFG_RELEASE_NUM=0.11.0
CFG_RELEASE_LABEL=
+CFG_FILENAME_EXTRA=4e7c5e5c
+
ifndef CFG_ENABLE_NIGHTLY
# This is the normal version string
CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)
ifdef TRACE
CFG_RUSTC_FLAGS += -Z trace
endif
-ifdef CFG_DISABLE_RPATH
-CFG_RUSTC_FLAGS += -C no-rpath
+ifdef CFG_ENABLE_RPATH
+CFG_RUSTC_FLAGS += -C rpath
endif
# The executables crated during this compilation process have no need to include
# $(4) is the crate name
define RUST_TARGET_STAGE_N
+# NOTE: after a stage0 snap this should be just EXTRA_FILENAME, not with a stage
+# or target bound
+EXTRA_FILENAME_$(1)_$(2) = -C extra-filename=-$$(CFG_FILENAME_EXTRA)
+ifeq ($(1),0)
+ifeq ($$(CFG_BUILD),$(2))
+EXTRA_FILENAME_$(1)_$(2) =
+endif
+endif
+
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2)
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
$$(CRATEFILE_$(4)) \
-L "$$(LLVM_LIBDIR_$(2))" \
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
$$(RUSTFLAGS_$(4)) \
- --out-dir $$(@D) $$<
+ --out-dir $$(@D) \
+ $$(EXTRA_FILENAME_$(1)_$(2)) \
+ $$<
@touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES,\
$$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4)))
# Main test targets
######################################################################
-check: cleantmptestlogs cleantestlibs tidy check-notidy
+check: cleantmptestlogs cleantestlibs check-notidy tidy
check-notidy: cleantmptestlogs cleantestlibs all check-stage2
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
opt_str(&config.filter
.as_ref()
.map(|re| {
- re.to_str().into_string()
+ re.to_string().into_string()
}))));
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
logv(c, format!("host-rustcflags: {}",
fn parse_expected(line_num: uint, line: &str, re: &Regex) -> Option<ExpectedError> {
re.captures(line).and_then(|caps| {
let adjusts = caps.name("adjusts").len();
- let kind = caps.name("kind").to_ascii().to_lower().into_str();
+ let kind = caps.name("kind").to_ascii().to_lower().into_string();
let msg = caps.name("msg").trim().to_string();
debug!("line={} kind={} msg={}", line_num, kind, msg);
Some(curr) => {
format!("{}{}{}", path, path_div(), curr)
}
- None => path.to_str()
+ None => path.to_string()
}
}
let mut value: uint;
loop {
value = channel.recv();
- channel.send(value.to_str());
+ channel.send(value.to_string());
if value == 0 { break; }
}
}
(the second type parameter). The body itself simply loops, reading
from the channel and then sending its response back. The actual
response itself is simply the stringified version of the received value,
-`uint::to_str(value)`.
+`uint::to_string(value)`.
Here is the code for the parent task:
# let mut value: uint;
# loop {
# value = channel.recv();
-# channel.send(value.to_str());
+# channel.send(value.to_string());
# if value == 0u { break; }
# }
# }
```{ignore}
rustc 0.11.0-pre (443a1cd 2014-06-08 14:56:52 -0700)
-host: x86_64-unknown-linux-gnu
```
If you did, Rust has been installed successfully! Congrats!
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
-However, re-assigning to a mutable binding is an expression:
+However, assigning to a variable binding is an expression:
```{rust}
-let mut x = 0i;
+let x;
let y = x = 5i;
```
We would get an error:
```{ignore,notrust}
-note: consider removing this semicolon:
- x + 1;
- ^
error: not all control paths return a value
fn add_one(x: int) -> int {
x + 1;
}
+
+note: consider removing this semicolon:
+ x + 1;
+ ^
```
Remember our earlier discussions about semicolons and `()`? Our function claims
There are some additional ways to define functions, but they involve features
that we haven't learned about yet, so let's just leave it at that for now.
+
## Comments
-return
+Now that we have some functions, it's a good idea to learn about comments.
+Comments are notes that you leave to other programmers to help explain things
+about your code. The compiler mostly ignores them.
+
+Rust has two kinds of comments that you should care about: **line comment**s
+and **doc comment**s.
+
+```{rust}
+// Line comments are anything after '//' and extend to the end of the line.
+
+let x = 5i; // this is also a line comment.
+
+// If you have a long explanation for something, you can put line comments next
+// to each other. Put a space between the // and your comment so that it's
+// more readable.
+```
+
+The other kind of comment is a doc comment. Doc comments use `///` instead of
+`//`, and support Markdown notation inside:
+
+```{rust}
+/// `hello` is a function that prints a greeting that is personalized based on
+/// the name given.
+///
+/// # Arguments
+///
+/// * `name` - The name of the person you'd like to greet.
+///
+/// # Example
+///
+/// ```rust
+/// let name = "Steve";
+/// hello(name); // prints "Hello, Steve!"
+/// ```
+fn hello(name: &str) {
+ println!("Hello, {}!", name);
+}
+```
+
+When writing doc comments, adding sections for any arguments, return values,
+and providing some examples of usage is very, very helpful.
-comments
+You can use the `rustdoc` tool to generate HTML documentation from these doc
+comments. We will talk more about `rustdoc` when we get to modules, as
+generally, you want to export documentation for a full module.
## Compound Data Types
#| "[tarball]: http://static.rust-lang.org/dist/rust-nightly.tar.gz [win-exe]: "
#| "http://static.rust-lang.org/dist/rust-nightly-install.exe"
msgid ""
-"Use [`ToStr`](http://static.rust-lang.org/doc/master/std/to_str/trait.ToStr."
+"Use [`ToString`](http://static.rust-lang.org/doc/master/std/to_str/trait.ToString."
"html)."
msgstr ""
"[tarball]: http://static.rust-lang.org/dist/rust-nightly.tar.gz\n"
#, fuzzy
#| msgid ""
#| "~~~~ let x: f64 = 4.0; let y: uint = x as uint; assert!(y == 4u); ~~~~"
-msgid "~~~ let x: int = 42; let y: String = x.to_str(); ~~~"
+msgid "~~~ let x: int = 42; let y: String = x.to_string(); ~~~"
msgstr ""
"~~~~\n"
"let x: f64 = 4.0;\n"
#| msgid "~~~~ {.ignore} // main.rs extern crate world; fn main() { println(~\"hello \" + world::explore()); } ~~~~"
msgid ""
"impl Printable for int {\n"
-" fn to_string(&self) -> String { self.to_str() }\n"
+" fn to_string(&self) -> String { self.to_string() }\n"
"}\n"
msgstr ""
"~~~~ {.ignore}\n"
#. type: Plain text
#: src/doc/tutorial.md:2528
-msgid "#[deriving(Rand, ToStr)] enum ABC { A, B, C } ~~~"
+msgid "#[deriving(Rand, ToString)] enum ABC { A, B, C } ~~~"
msgstr ""
-"#[deriving(Rand, ToStr)]\n"
+"#[deriving(Rand, ToString)]\n"
"enum ABC { A, B, C }\n"
"~~~"
#| msgid ""
#| "The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
#| "`Encodable` `Decodable`, `Clone`, `DeepClone`, `Hash`, `Rand`, "
-#| "`Zero`, and `ToStr`."
+#| "`Zero`, and `ToString`."
msgid ""
"The full list of derivable traits is `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
"`Encodable` `Decodable`, `Clone`, `DeepClone`, `Hash`, `Rand`, "
-"`Default`, `Zero`, and `ToStr`."
+"`Default`, `Zero`, and `ToString`."
msgstr ""
"実装を自動的に導出可能なトレイトは、 `Eq`, `TotalEq`, `Ord`, `TotalOrd`, "
"`Encodable` `Decodable`, `Clone`, `DeepClone`, `Hash`, `Rand`, `Zero`, "
-"および `ToStr` です。."
+"および `ToString` です。."
#. type: Plain text
#: src/doc/tutorial.md:2534
~~~~
trait Printable {
- fn to_string(&self) -> String;
+ fn stringify(&self) -> String;
}
impl Printable for int {
- fn to_string(&self) -> String { self.to_str() }
+ fn stringify(&self) -> String { self.to_string() }
}
fn print(a: Box<Printable>) {
- println!("{}", a.to_string());
+ println!("{}", a.stringify());
}
fn main() {
An example of an owned box type and value:
~~~~
-
let x: Box<int> = box 10;
~~~~
-Owned box values exist in 1:1 correspondence with their heap allocation
-copying an owned box value makes a shallow copy of the pointer
+Owned box values exist in 1:1 correspondence with their heap allocation,
+copying an owned box value makes a shallow copy of the pointer.
Rust will consider a shallow copy of an owned box to move ownership of the value. After a value has been moved, the source location cannot be used unless it is reinitialized.
~~~~
~~~{.ignore}
// `b/mod.rs`
pub mod c;
-pub fn foo() { println!("Foo!"; }
+pub fn foo() { println!("Foo!"); }
~~~
~~~{.ignore}
" j was only added in 7.3.541, so stop complaints about its nonexistence
silent! setlocal formatoptions+=j
+" smartindent will be overridden by indentexpr if filetype indent is on, but
+" otherwise it's better than nothing.
+setlocal smartindent nocindent
+
+setlocal tabstop=4 shiftwidth=4 expandtab
+
" This includeexpr isn't perfect, but it's a good start
setlocal includeexpr=substitute(v:fname,'::','/','g')
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
syn keyword rustTrait BitAnd BitOr BitXor
syn keyword rustTrait Drop Deref DerefMut
-syn keyword rustTrait Shl Shr Index
+syn keyword rustTrait Shl Shr Index IndexMut
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
syn keyword rustEnum Result
syn keyword rustTrait Buffer Writer Reader Seek
syn keyword rustTrait Str StrVector StrSlice OwnedStr
syn keyword rustTrait IntoMaybeOwned StrAllocating
-syn keyword rustTrait ToStr IntoStr
+syn keyword rustTrait ToString IntoStr
syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4
syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8
syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12
//! by libc malloc/free. The `libc_heap` module is defined to be wired up to
//! the system malloc/free.
-#![crate_id = "alloc#0.11.0"]
+#![crate_id = "alloc#0.11.0"] // NOTE: remove after a stage0 snap
+#![crate_name = "alloc"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![no_std]
#![feature(lang_items, phase, unsafe_destructor)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)]
extern crate core;
//! more complex, slower Arena which can hold objects of any type.
#![crate_id = "arena#0.11.0"]
+#![crate_name = "arena"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(unsafe_destructor)]
#![allow(missing_doc)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::cell::{Cell, RefCell};
use std::cmp;
use core::cmp;
use core::default::Default;
use core::fmt;
-use core::iter::{Enumerate, Repeat, Map, Zip};
-use core::ops;
+use core::iter::Take;
use core::slice;
use core::uint;
use std::hash;
use {Collection, Mutable, Set, MutableSet};
use vec::Vec;
+#[cfg(not(stage0))]
+use core::ops::Index;
+
+#[cfg(not(stage0))]
+static TRUE: bool = true;
+
+#[cfg(not(stage0))]
+static FALSE: bool = false;
+
#[deriving(Clone)]
struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined.
bits: uint
}
-/// a mask that has a 1 for each defined bit in a small_bitv, assuming n bits
-#[inline]
-fn small_mask(nbits: uint) -> uint {
- (1 << nbits) - 1
-}
-
-impl SmallBitv {
- fn new(bits: uint) -> SmallBitv {
- SmallBitv {bits: bits}
- }
-
- #[inline]
- fn bits_op(&mut self,
- right_bits: uint,
- nbits: uint,
- f: |uint, uint| -> uint)
- -> bool {
- let mask = small_mask(nbits);
- let old_b: uint = self.bits;
- let new_b = f(old_b, right_bits);
- self.bits = new_b;
- mask & old_b != mask & new_b
- }
-
- #[inline]
- fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool {
- self.bits_op(s.bits, nbits, |u1, u2| u1 | u2)
- }
-
- #[inline]
- fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool {
- self.bits_op(s.bits, nbits, |u1, u2| u1 & u2)
- }
-
- #[inline]
- fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool {
- self.bits_op(s.bits, nbits, |_u1, u2| u2)
- }
-
- #[inline]
- fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool {
- self.bits_op(s.bits, nbits, |u1, u2| u1 & !u2)
- }
-
- #[inline]
- fn get(&self, i: uint) -> bool {
- (self.bits & (1 << i)) != 0
- }
-
- #[inline]
- fn set(&mut self, i: uint, x: bool) {
- if x {
- self.bits |= 1<<i;
- }
- else {
- self.bits &= !(1<<i);
- }
- }
-
- #[inline]
- fn equals(&self, b: &SmallBitv, nbits: uint) -> bool {
- let mask = small_mask(nbits);
- mask & self.bits == mask & b.bits
- }
-
- #[inline]
- fn clear(&mut self) { self.bits = 0; }
-
- #[inline]
- fn set_all(&mut self) { self.bits = !0; }
-
- #[inline]
- fn all(&self, nbits: uint) -> bool {
- small_mask(nbits) & !self.bits == 0
- }
-
- #[inline]
- fn none(&self, nbits: uint) -> bool {
- small_mask(nbits) & self.bits == 0
- }
-
- #[inline]
- fn negate(&mut self) { self.bits = !self.bits; }
-}
-
#[deriving(Clone)]
struct BigBitv {
storage: Vec<uint>
}
-/**
- * A mask that has a 1 for each defined bit in the n'th element of a `BigBitv`,
- * assuming n bits.
- */
-#[inline]
-fn big_mask(nbits: uint, elem: uint) -> uint {
- let rmd = nbits % uint::BITS;
- let nelems = nbits/uint::BITS + if rmd == 0 {0} else {1};
-
- if elem < nelems - 1 || rmd == 0 {
- !0
- } else {
- (1 << rmd) - 1
- }
-}
-
-impl BigBitv {
- fn new(storage: Vec<uint>) -> BigBitv {
- BigBitv {storage: storage}
- }
-
- #[inline]
- fn process(&mut self,
- b: &BigBitv,
- nbits: uint,
- op: |uint, uint| -> uint)
- -> bool {
- let len = b.storage.len();
- assert_eq!(self.storage.len(), len);
- let mut changed = false;
- for (i, (a, b)) in self.storage.mut_iter()
- .zip(b.storage.iter())
- .enumerate() {
- let mask = big_mask(nbits, i);
- let w0 = *a & mask;
- let w1 = *b & mask;
- let w = op(w0, w1) & mask;
- if w0 != w {
- changed = true;
- *a = w;
- }
- }
- changed
- }
-
- #[inline]
- fn each_storage(&mut self, op: |v: &mut uint| -> bool) -> bool {
- self.storage.mut_iter().advance(|elt| op(elt))
- }
-
- #[inline]
- fn negate(&mut self) {
- self.each_storage(|w| { *w = !*w; true });
- }
-
- #[inline]
- fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
- self.process(b, nbits, |w1, w2| w1 | w2)
- }
-
- #[inline]
- fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool {
- self.process(b, nbits, |w1, w2| w1 & w2)
- }
-
- #[inline]
- fn become(&mut self, b: &BigBitv, nbits: uint) -> bool {
- self.process(b, nbits, |_, w| w)
- }
-
- #[inline]
- fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool {
- self.process(b, nbits, |w1, w2| w1 & !w2)
- }
-
- #[inline]
- fn get(&self, i: uint) -> bool {
- let w = i / uint::BITS;
- let b = i % uint::BITS;
- let x = 1 & self.storage.get(w) >> b;
- x == 1
- }
-
- #[inline]
- fn set(&mut self, i: uint, x: bool) {
- let w = i / uint::BITS;
- let b = i % uint::BITS;
- let flag = 1 << b;
- *self.storage.get_mut(w) = if x { *self.storage.get(w) | flag }
- else { *self.storage.get(w) & !flag };
- }
-
- #[inline]
- fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
- for (i, elt) in b.storage.iter().enumerate() {
- let mask = big_mask(nbits, i);
- if mask & *self.storage.get(i) != mask & *elt {
- return false;
- }
- }
- true
- }
-}
-
#[deriving(Clone)]
enum BitvVariant { Big(BigBitv), Small(SmallBitv) }
-enum Op {Union, Intersect, Assign, Difference}
-
/// The bitvector type
///
/// # Example
/// ```rust
/// use collections::bitv::Bitv;
///
-/// let mut bv = Bitv::new(10, false);
+/// let mut bv = Bitv::with_capacity(10, false);
///
/// // insert all primes less than 10
/// bv.set(2, true);
/// bv.set(3, true);
/// bv.set(5, true);
/// bv.set(7, true);
-/// println!("{}", bv.to_str());
+/// println!("{}", bv.to_string());
/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
///
/// // flip all values in bitvector, producing non-primes less than 10
/// bv.negate();
-/// println!("{}", bv.to_str());
+/// println!("{}", bv.to_string());
/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
///
/// // reset bitvector to empty
/// bv.clear();
-/// println!("{}", bv.to_str());
+/// println!("{}", bv.to_string());
/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
/// ```
-#[deriving(Clone)]
pub struct Bitv {
- /// Internal representation of the bit vector (small or large)
- rep: BitvVariant,
+ /// Internal representation of the bit vector
+ storage: Vec<uint>,
/// The number of valid bits in the internal representation
nbits: uint
}
-fn die() -> ! {
- fail!("Tried to do operation on bit vectors with different sizes");
+#[cfg(not(stage0))]
+impl Index<uint,bool> for Bitv {
+ #[inline]
+ fn index<'a>(&'a self, i: &uint) -> &'a bool {
+ if self.get(*i) {
+ &TRUE
+ } else {
+ &FALSE
+ }
+ }
}
-impl Bitv {
+struct MaskWords<'a> {
+ iter: slice::Items<'a, uint>,
+ next_word: Option<&'a uint>,
+ last_word_mask: uint,
+ offset: uint
+}
+
+impl<'a> Iterator<(uint, uint)> for MaskWords<'a> {
+ /// Returns (offset, word)
#[inline]
- fn do_op(&mut self, op: Op, other: &Bitv) -> bool {
- if self.nbits != other.nbits {
- die();
- }
- match self.rep {
- Small(ref mut s) => match other.rep {
- Small(ref s1) => match op {
- Union => s.union(s1, self.nbits),
- Intersect => s.intersect(s1, self.nbits),
- Assign => s.become(s1, self.nbits),
- Difference => s.difference(s1, self.nbits)
+ fn next<'a>(&'a mut self) -> Option<(uint, uint)> {
+ let ret = self.next_word;
+ match ret {
+ Some(&w) => {
+ self.next_word = self.iter.next();
+ self.offset += 1;
+ // The last word may need to be masked
+ if self.next_word.is_none() {
+ Some((self.offset - 1, w & self.last_word_mask))
+ } else {
+ Some((self.offset - 1, w))
+ }
},
- Big(_) => die()
- },
- Big(ref mut s) => match other.rep {
- Small(_) => die(),
- Big(ref s1) => match op {
- Union => s.union(s1, self.nbits),
- Intersect => s.intersect(s1, self.nbits),
- Assign => s.become(s1, self.nbits),
- Difference => s.difference(s1, self.nbits)
- }
- }
+ None => None
}
}
}
impl Bitv {
- /// Creates an empty Bitv that holds `nbits` elements, setting each element
+ #[inline]
+ fn process(&mut self, other: &Bitv, op: |uint, uint| -> uint) -> bool {
+ let len = other.storage.len();
+ assert_eq!(self.storage.len(), len);
+ let mut changed = false;
+ // Notice: `a` is *not* masked here, which is fine as long as
+ // `op` is a bitwise operation, since any bits that should've
+ // been masked were fine to change anyway. `b` is masked to
+ // make sure its unmasked bits do not cause damage.
+ for (a, (_, b)) in self.storage.mut_iter()
+ .zip(other.mask_words(0)) {
+ let w = op(*a, b);
+ if *a != w {
+ changed = true;
+ *a = w;
+ }
+ }
+ changed
+ }
+
+ #[inline]
+ fn mask_words<'a>(&'a self, mut start: uint) -> MaskWords<'a> {
+ if start > self.storage.len() {
+ start = self.storage.len();
+ }
+ let mut iter = self.storage.slice_from(start).iter();
+ MaskWords {
+ next_word: iter.next(),
+ iter: iter,
+ last_word_mask: {
+ let rem = self.nbits % uint::BITS;
+ if rem > 0 {
+ (1 << rem) - 1
+ } else { !0 }
+ },
+ offset: start
+ }
+ }
+
+ /// Creates an empty Bitv
+ pub fn new() -> Bitv {
+ Bitv { storage: Vec::new(), nbits: 0 }
+ }
+
+ /// Creates a Bitv that holds `nbits` elements, setting each element
/// to `init`.
- pub fn new(nbits: uint, init: bool) -> Bitv {
- let rep = if nbits < uint::BITS {
- Small(SmallBitv::new(if init {(1<<nbits)-1} else {0}))
- } else if nbits == uint::BITS {
- Small(SmallBitv::new(if init {!0} else {0}))
- } else {
- let exact = nbits % uint::BITS == 0;
- let nelems = nbits/uint::BITS + if exact {0} else {1};
- let s =
- if init {
- if exact {
- Vec::from_elem(nelems, !0u)
- } else {
- let mut v = Vec::from_elem(nelems-1, !0u);
- v.push((1<<nbits % uint::BITS)-1);
- v
- }
- } else { Vec::from_elem(nelems, 0u)};
- Big(BigBitv::new(s))
- };
- Bitv {rep: rep, nbits: nbits}
+ pub fn with_capacity(nbits: uint, init: bool) -> Bitv {
+ Bitv {
+ storage: Vec::from_elem((nbits + uint::BITS - 1) / uint::BITS,
+ if init { !0u } else { 0u }),
+ nbits: nbits
+ }
}
/**
* the same length. Returns `true` if `self` changed.
*/
#[inline]
- pub fn union(&mut self, v1: &Bitv) -> bool { self.do_op(Union, v1) }
+ pub fn union(&mut self, other: &Bitv) -> bool {
+ self.process(other, |w1, w2| w1 | w2)
+ }
/**
* Calculates the intersection of two bitvectors
* must be the same length. Returns `true` if `self` changed.
*/
#[inline]
- pub fn intersect(&mut self, v1: &Bitv) -> bool {
- self.do_op(Intersect, v1)
+ pub fn intersect(&mut self, other: &Bitv) -> bool {
+ self.process(other, |w1, w2| w1 & w2)
}
- /**
- * Assigns the value of `v1` to `self`
- *
- * Both bitvectors must be the same length. Returns `true` if `self` was
- * changed
- */
- #[inline]
- pub fn assign(&mut self, v: &Bitv) -> bool { self.do_op(Assign, v) }
-
/// Retrieve the value at index `i`
#[inline]
pub fn get(&self, i: uint) -> bool {
- assert!((i < self.nbits));
- match self.rep {
- Big(ref b) => b.get(i),
- Small(ref s) => s.get(i)
- }
+ assert!(i < self.nbits);
+ let w = i / uint::BITS;
+ let b = i % uint::BITS;
+ let x = self.storage.get(w) & (1 << b);
+ x != 0
}
/**
*/
#[inline]
pub fn set(&mut self, i: uint, x: bool) {
- assert!((i < self.nbits));
- match self.rep {
- Big(ref mut b) => b.set(i, x),
- Small(ref mut s) => s.set(i, x)
- }
- }
-
- /// Set all bits to 0
- #[inline]
- pub fn clear(&mut self) {
- match self.rep {
- Small(ref mut b) => b.clear(),
- Big(ref mut s) => {
- s.each_storage(|w| { *w = 0u; true });
- }
- }
+ assert!(i < self.nbits);
+ let w = i / uint::BITS;
+ let b = i % uint::BITS;
+ let flag = 1 << b;
+ *self.storage.get_mut(w) = if x { *self.storage.get(w) | flag }
+ else { *self.storage.get(w) & !flag };
}
/// Set all bits to 1
#[inline]
pub fn set_all(&mut self) {
- match self.rep {
- Small(ref mut b) => b.set_all(),
- Big(ref mut s) => {
- s.each_storage(|w| { *w = !0u; true });
- }
- }
+ for w in self.storage.mut_iter() { *w = !0u; }
}
/// Flip all bits
#[inline]
pub fn negate(&mut self) {
- match self.rep {
- Small(ref mut s) => s.negate(),
- Big(ref mut b) => b.negate(),
- }
+ for w in self.storage.mut_iter() { *w = !*w; }
}
/**
* Returns `true` if `v0` was changed.
*/
#[inline]
- pub fn difference(&mut self, v: &Bitv) -> bool {
- self.do_op(Difference, v)
+ pub fn difference(&mut self, other: &Bitv) -> bool {
+ self.process(other, |w1, w2| w1 & !w2)
}
/// Returns `true` if all bits are 1
#[inline]
pub fn all(&self) -> bool {
- match self.rep {
- Small(ref b) => b.all(self.nbits),
- _ => self.iter().all(|x| x)
- }
+ let mut last_word = !0u;
+ // Check that every word but the last is all-ones...
+ self.mask_words(0).all(|(_, elem)|
+ { let tmp = last_word; last_word = elem; tmp == !0u }) &&
+ // ...and that the last word is ones as far as it needs to be
+ (last_word == ((1 << self.nbits % uint::BITS) - 1) || last_word == !0u)
}
/// Returns an iterator over the elements of the vector in order.
///
/// ```rust
/// use collections::bitv::Bitv;
- /// let mut bv = Bitv::new(10, false);
+ /// let mut bv = Bitv::with_capacity(10, false);
/// bv.set(1, true);
/// bv.set(2, true);
/// bv.set(3, true);
/// Returns `true` if all bits are 0
pub fn none(&self) -> bool {
- match self.rep {
- Small(ref b) => b.none(self.nbits),
- _ => self.iter().all(|x| !x)
- }
+ self.mask_words(0).all(|(_, w)| w == 0)
}
#[inline]
!self.none()
}
- /**
- * Converts `self` to a vector of `uint` with the same length.
- *
- * Each `uint` in the resulting vector has either value `0u` or `1u`.
- */
- pub fn to_vec(&self) -> Vec<uint> {
- Vec::from_fn(self.nbits, |i| if self.get(i) { 1 } else { 0 })
- }
-
/**
* Organise the bits into bytes, such that the first bit in the
* `Bitv` becomes the high-order bit of the first byte. If the
if offset >= bitv.nbits {
0
} else {
- bitv[offset] as u8 << (7 - bit)
+ bitv.get(offset) as u8 << (7 - bit)
}
}
* Transform `self` into a `Vec<bool>` by turning each bit into a `bool`.
*/
pub fn to_bools(&self) -> Vec<bool> {
- Vec::from_fn(self.nbits, |i| self[i])
+ Vec::from_fn(self.nbits, |i| self.get(i))
}
/**
true
}
- pub fn ones(&self, f: |uint| -> bool) -> bool {
- range(0u, self.nbits).advance(|i| !self.get(i) || f(i))
+ /// Shorten a Bitv, dropping excess elements.
+ ///
+ /// If `len` is greater than the vector's current length, this has no
+ /// effect.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::bitv::Bitv;
+ /// let mut bvec: Bitv = vec![false, true, true, false].iter().map(|n| *n).collect();
+ /// let expected: Bitv = vec![false, true].iter().map(|n| *n).collect();
+ /// bvec.truncate(2);
+ /// assert_eq!(bvec, expected);
+ /// ```
+ pub fn truncate(&mut self, len: uint) {
+ if len < self.len() {
+ self.nbits = len;
+ let word_len = (len + uint::BITS - 1) / uint::BITS;
+ self.storage.truncate(word_len);
+ if len % uint::BITS > 0 {
+ let mask = (1 << len % uint::BITS) - 1;
+ *self.storage.get_mut(word_len - 1) &= mask;
+ }
+ }
+ }
+
+ /// Grows the vector to be able to store `size` bits without resizing
+ pub fn reserve(&mut self, size: uint) {
+ let old_size = self.storage.len();
+ let size = (size + uint::BITS - 1) / uint::BITS;
+ if old_size < size {
+ self.storage.grow(size - old_size, &0);
+ }
+ }
+
+ /// Returns the capacity in bits for this bit vector. Inserting any
+ /// element less than this amount will not trigger a resizing.
+ #[inline]
+ pub fn capacity(&self) -> uint {
+ self.storage.len() * uint::BITS
+ }
+
+ /// Grows the `Bitv` in-place.
+ ///
+ /// Adds `n` copies of `value` to the `Bitv`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::bitv::Bitv;
+ /// let mut bvec: Bitv = vec![false, true, true, false].iter().map(|n| *n).collect();
+ /// bvec.grow(2, true);
+ /// assert_eq!(bvec, vec![false, true, true, false, true, true].iter().map(|n| *n).collect());
+ /// ```
+ pub fn grow(&mut self, n: uint, value: bool) {
+ let new_nbits = self.nbits + n;
+ let new_nwords = (new_nbits + uint::BITS - 1) / uint::BITS;
+ let full_value = if value { !0 } else { 0 };
+ // Correct the old tail word
+ let old_last_word = (self.nbits + uint::BITS - 1) / uint::BITS - 1;
+ if self.nbits % uint::BITS > 0 {
+ let overhang = self.nbits % uint::BITS; // # of already-used bits
+ let mask = !((1 << overhang) - 1); // e.g. 5 unused bits => 111110....0
+ if value {
+ *self.storage.get_mut(old_last_word) |= mask;
+ } else {
+ *self.storage.get_mut(old_last_word) &= !mask;
+ }
+ }
+ // Fill in words after the old tail word
+ let stop_idx = cmp::min(self.storage.len(), new_nwords);
+ for idx in range(old_last_word + 1, stop_idx) {
+ *self.storage.get_mut(idx) = full_value;
+ }
+ // Allocate new words, if needed
+ if new_nwords > self.storage.len() {
+ let to_add = new_nwords - self.storage.len();
+ self.storage.grow(to_add, &full_value);
+ }
+ // Adjust internal bit count
+ self.nbits = new_nbits;
+ }
+
+ /// Shorten a `Bitv` by one, returning the removed element
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::bitv::Bitv;
+ /// let mut bvec: Bitv = vec![false, true, true, false].iter().map(|n| *n).collect();
+ /// let expected: Bitv = vec![false, true, true].iter().map(|n| *n).collect();
+ /// let popped = bvec.pop();
+ /// assert_eq!(popped, false);
+ /// assert_eq!(bvec, expected);
+ /// ```
+ pub fn pop(&mut self) -> bool {
+ let ret = self.get(self.nbits - 1);
+ // If we are unusing a whole word, make sure it is zeroed out
+ if self.nbits % uint::BITS == 1 {
+ *self.storage.get_mut(self.nbits / uint::BITS) = 0;
+ }
+ self.nbits -= 1;
+ ret
}
+ /// Pushes a `bool` onto the `Bitv`
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::bitv::Bitv;
+ /// let prototype: Bitv = vec![false, true, true, false].iter().map(|n| *n).collect();
+ /// let mut bvec: Bitv = vec![false, true].iter().map(|n| *n).collect();
+ /// bvec.push(true);
+ /// bvec.push(false);
+ /// assert_eq!(prototype, bvec);
+ /// ```
+ pub fn push(&mut self, elem: bool) {
+ let insert_pos = self.nbits;
+ self.nbits += 1;
+ if self.storage.len() * uint::BITS < self.nbits {
+ self.storage.push(0);
+ }
+ self.set(insert_pos, elem);
+ }
}
/**
})
}
-/**
- * Transform a `[bool]` into a `Bitv` by converting each `bool` into a bit.
- */
-pub fn from_bools(bools: &[bool]) -> Bitv {
- from_fn(bools.len(), |i| bools[i])
-}
-
/**
* Create a `Bitv` of the specified length where the value at each
* index is `f(index)`.
*/
pub fn from_fn(len: uint, f: |index: uint| -> bool) -> Bitv {
- let mut bitv = Bitv::new(len, false);
+ let mut bitv = Bitv::with_capacity(len, false);
for i in range(0u, len) {
bitv.set(i, f(i));
}
bitv
}
-impl ops::Index<uint,bool> for Bitv {
- fn index(&self, i: &uint) -> bool {
- self.get(*i)
+impl Default for Bitv {
+ #[inline]
+ fn default() -> Bitv { Bitv::new() }
+}
+
+impl Collection for Bitv {
+ #[inline]
+ fn len(&self) -> uint { self.nbits }
+}
+
+impl Mutable for Bitv {
+ #[inline]
+ fn clear(&mut self) {
+ for w in self.storage.mut_iter() { *w = 0u; }
+ }
+}
+
+impl FromIterator<bool> for Bitv {
+ fn from_iter<I:Iterator<bool>>(iterator: I) -> Bitv {
+ let mut ret = Bitv::new();
+ ret.extend(iterator);
+ ret
+ }
+}
+
+impl Extendable<bool> for Bitv {
+ #[inline]
+ fn extend<I: Iterator<bool>>(&mut self, mut iterator: I) {
+ let (min, _) = iterator.size_hint();
+ let nbits = self.nbits;
+ self.reserve(nbits + min);
+ for element in iterator {
+ self.push(element)
+ }
+ }
+}
+
+impl Clone for Bitv {
+ #[inline]
+ fn clone(&self) -> Bitv {
+ Bitv { storage: self.storage.clone(), nbits: self.nbits }
+ }
+
+ #[inline]
+ fn clone_from(&mut self, source: &Bitv) {
+ self.nbits = source.nbits;
+ self.storage.reserve(source.storage.len());
+ for (i, w) in self.storage.mut_iter().enumerate() { *w = *source.storage.get(i); }
}
}
impl<S: hash::Writer> hash::Hash<S> for Bitv {
fn hash(&self, state: &mut S) {
self.nbits.hash(state);
- match self.rep {
- Small(ref s) => (s.bits & small_mask(self.nbits)).hash(state),
- Big(ref b) => {
- for (i, ele) in b.storage.iter().enumerate() {
- (ele & big_mask(self.nbits, i)).hash(state);
- }
- }
+ for (_, elem) in self.mask_words(0) {
+ elem.hash(state);
}
}
}
impl cmp::PartialEq for Bitv {
#[inline]
fn eq(&self, other: &Bitv) -> bool {
- if self.nbits != other.nbits { return false; }
- match self.rep {
- Small(ref b) => match other.rep {
- Small(ref b1) => b.equals(b1, self.nbits),
- _ => false
- },
- Big(ref s) => match other.rep {
- Big(ref s1) => s.equals(s1, self.nbits),
- Small(_) => return false
- }
+ if self.nbits != other.nbits {
+ return false;
}
+ self.mask_words(0).zip(other.mask_words(0)).all(|((_, w1), (_, w2))| w1 == w2)
}
}
impl cmp::Eq for Bitv {}
-#[inline]
-fn iterate_bits(base: uint, bits: uint, f: |uint| -> bool) -> bool {
- if bits == 0 {
- return true;
- }
- for i in range(0u, uint::BITS) {
- if bits & (1 << i) != 0 {
- if !f(base + i) {
- return false;
- }
- }
- }
- return true;
-}
-
/// An iterator for `Bitv`.
pub struct Bits<'a> {
bitv: &'a Bitv,
/// It should also be noted that the amount of storage necessary for holding a
/// set of objects is proportional to the maximum of the objects when viewed
/// as a `uint`.
-#[deriving(Clone)]
-pub struct BitvSet {
- size: uint,
-
- // In theory this is a `Bitv` instead of always a `BigBitv`, but knowing that
- // there's an array of storage makes our lives a whole lot easier when
- // performing union/intersection/etc operations
- bitv: BigBitv
-}
+#[deriving(Clone, PartialEq, Eq)]
+pub struct BitvSet(Bitv);
impl Default for BitvSet {
#[inline]
impl BitvSet {
/// Creates a new bit vector set with initially no contents
+ #[inline]
pub fn new() -> BitvSet {
- BitvSet{ size: 0, bitv: BigBitv::new(vec!(0)) }
+ BitvSet(Bitv::new())
+ }
+
+ /// Creates a new bit vector set with initially no contents, able to
+ /// hold `nbits` elements without resizing
+ #[inline]
+ pub fn with_capacity(nbits: uint) -> BitvSet {
+ BitvSet(Bitv::with_capacity(nbits, false))
}
/// Creates a new bit vector set from the given bit vector
+ #[inline]
pub fn from_bitv(bitv: Bitv) -> BitvSet {
- let mut size = 0;
- bitv.ones(|_| {
- size += 1;
- true
- });
- let Bitv{rep, ..} = bitv;
- match rep {
- Big(b) => BitvSet{ size: size, bitv: b },
- Small(SmallBitv{bits}) =>
- BitvSet{ size: size, bitv: BigBitv{ storage: vec!(bits) } },
- }
+ BitvSet(bitv)
}
/// Returns the capacity in bits for this bit vector. Inserting any
/// element less than this amount will not trigger a resizing.
- pub fn capacity(&self) -> uint { self.bitv.storage.len() * uint::BITS }
+ #[inline]
+ pub fn capacity(&self) -> uint {
+ let &BitvSet(ref bitv) = self;
+ bitv.capacity()
+ }
+
+ /// Grows the underlying vector to be able to store `size` bits
+ pub fn reserve(&mut self, size: uint) {
+ let &BitvSet(ref mut bitv) = self;
+ bitv.reserve(size)
+ }
/// Consumes this set to return the underlying bit vector
+ #[inline]
pub fn unwrap(self) -> Bitv {
- let cap = self.capacity();
- let BitvSet{bitv, ..} = self;
- return Bitv{ nbits:cap, rep: Big(bitv) };
+ let BitvSet(bitv) = self;
+ bitv
+ }
+
+ /// Returns a reference to the underlying bit vector
+ #[inline]
+ pub fn get_ref<'a>(&'a self) -> &'a Bitv {
+ let &BitvSet(ref bitv) = self;
+ bitv
+ }
+
+ /// Returns a mutable reference to the underlying bit vector
+ #[inline]
+ pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut Bitv {
+ let &BitvSet(ref mut bitv) = self;
+ bitv
}
#[inline]
fn other_op(&mut self, other: &BitvSet, f: |uint, uint| -> uint) {
- fn nbits(mut w: uint) -> uint {
- let mut bits = 0;
- for _ in range(0u, uint::BITS) {
- if w == 0 {
- break;
- }
- bits += w & 1;
- w >>= 1;
- }
- return bits;
- }
- if self.capacity() < other.capacity() {
- self.bitv.storage.grow(other.capacity() / uint::BITS, &0);
- }
- for (i, &w) in other.bitv.storage.iter().enumerate() {
- let old = *self.bitv.storage.get(i);
+ // Unwrap Bitvs
+ let &BitvSet(ref mut self_bitv) = self;
+ let &BitvSet(ref other_bitv) = other;
+ // Expand the vector if necessary
+ self_bitv.reserve(other_bitv.capacity());
+ // Apply values
+ for (i, w) in other_bitv.mask_words(0) {
+ let old = *self_bitv.storage.get(i);
let new = f(old, w);
- *self.bitv.storage.get_mut(i) = new;
- self.size += nbits(new) - nbits(old);
+ *self_bitv.storage.get_mut(i) = new;
}
}
+ #[inline]
+ /// Truncate the underlying vector to the least length required
+ pub fn shrink_to_fit(&mut self) {
+ let &BitvSet(ref mut bitv) = self;
+ // Obtain original length
+ let old_len = bitv.storage.len();
+ // Obtain coarse trailing zero length
+ let n = bitv.storage.iter().rev().take_while(|&&n| n == 0).count();
+ // Truncate
+ let trunc_len = cmp::max(old_len - n, 1);
+ bitv.storage.truncate(trunc_len);
+ bitv.nbits = trunc_len * uint::BITS;
+ }
+
/// Union in-place with the specified other bit vector
+ #[inline]
pub fn union_with(&mut self, other: &BitvSet) {
self.other_op(other, |w1, w2| w1 | w2);
}
/// Intersect in-place with the specified other bit vector
+ #[inline]
pub fn intersect_with(&mut self, other: &BitvSet) {
self.other_op(other, |w1, w2| w1 & w2);
}
/// Difference in-place with the specified other bit vector
+ #[inline]
pub fn difference_with(&mut self, other: &BitvSet) {
self.other_op(other, |w1, w2| w1 & !w2);
}
/// Symmetric difference in-place with the specified other bit vector
+ #[inline]
pub fn symmetric_difference_with(&mut self, other: &BitvSet) {
self.other_op(other, |w1, w2| w1 ^ w2);
}
+ /// Iterator over each uint stored in the BitvSet
+ #[inline]
pub fn iter<'a>(&'a self) -> BitPositions<'a> {
BitPositions {set: self, next_idx: 0}
}
- pub fn difference(&self, other: &BitvSet, f: |&uint| -> bool) -> bool {
- for (i, w1, w2) in self.commons(other) {
- if !iterate_bits(i, w1 & !w2, |b| f(&b)) {
- return false
- }
- };
- /* everything we have that they don't also shows up */
- self.outliers(other).advance(|(mine, i, w)|
- !mine || iterate_bits(i, w, |b| f(&b))
- )
- }
-
- pub fn symmetric_difference(&self, other: &BitvSet, f: |&uint| -> bool)
- -> bool {
- for (i, w1, w2) in self.commons(other) {
- if !iterate_bits(i, w1 ^ w2, |b| f(&b)) {
- return false
- }
- };
- self.outliers(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
- }
-
- pub fn intersection(&self, other: &BitvSet, f: |&uint| -> bool) -> bool {
- self.commons(other).advance(|(i, w1, w2)| iterate_bits(i, w1 & w2, |b| f(&b)))
+ /// Iterator over each uint stored in the `self` setminus `other`
+ #[inline]
+ pub fn difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+ TwoBitPositions {
+ set: self,
+ other: other,
+ merge: |w1, w2| w1 & !w2,
+ current_word: 0,
+ next_idx: 0
+ }
}
- pub fn union(&self, other: &BitvSet, f: |&uint| -> bool) -> bool {
- for (i, w1, w2) in self.commons(other) {
- if !iterate_bits(i, w1 | w2, |b| f(&b)) {
- return false
- }
- };
- self.outliers(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
+ /// Iterator over each uint stored in the symmetric difference of `self` and `other`
+ #[inline]
+ pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+ TwoBitPositions {
+ set: self,
+ other: other,
+ merge: |w1, w2| w1 ^ w2,
+ current_word: 0,
+ next_idx: 0
+ }
}
-}
-impl cmp::PartialEq for BitvSet {
- fn eq(&self, other: &BitvSet) -> bool {
- if self.size != other.size {
- return false;
- }
- for (_, w1, w2) in self.commons(other) {
- if w1 != w2 {
- return false;
- }
- }
- for (_, _, w) in self.outliers(other) {
- if w != 0 {
- return false;
- }
+ /// Iterator over each uint stored in `self` intersect `other`
+ #[inline]
+ pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Take<TwoBitPositions<'a>> {
+ let min = cmp::min(self.capacity(), other.capacity());
+ TwoBitPositions {
+ set: self,
+ other: other,
+ merge: |w1, w2| w1 & w2,
+ current_word: 0,
+ next_idx: 0
+ }.take(min)
+ }
+
+ /// Iterator over each uint stored in `self` union `other`
+ #[inline]
+ pub fn union<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+ TwoBitPositions {
+ set: self,
+ other: other,
+ merge: |w1, w2| w1 | w2,
+ current_word: 0,
+ next_idx: 0
}
- return true;
}
-
- fn ne(&self, other: &BitvSet) -> bool { !self.eq(other) }
}
-impl cmp::Eq for BitvSet {}
-
impl fmt::Show for BitvSet {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(write!(fmt, "{{"));
impl Collection for BitvSet {
#[inline]
- fn len(&self) -> uint { self.size }
+ fn len(&self) -> uint {
+ let &BitvSet(ref bitv) = self;
+ bitv.storage.iter().fold(0, |acc, &n| acc + n.count_ones())
+ }
}
impl Mutable for BitvSet {
+ #[inline]
fn clear(&mut self) {
- self.bitv.each_storage(|w| { *w = 0; true });
- self.size = 0;
+ let &BitvSet(ref mut bitv) = self;
+ bitv.clear();
}
}
impl Set<uint> for BitvSet {
+ #[inline]
fn contains(&self, value: &uint) -> bool {
- *value < self.bitv.storage.len() * uint::BITS && self.bitv.get(*value)
+ let &BitvSet(ref bitv) = self;
+ *value < bitv.nbits && bitv.get(*value)
}
+ #[inline]
fn is_disjoint(&self, other: &BitvSet) -> bool {
- self.intersection(other, |_| false)
+ self.intersection(other).count() > 0
}
+ #[inline]
fn is_subset(&self, other: &BitvSet) -> bool {
- for (_, w1, w2) in self.commons(other) {
- if w1 & w2 != w1 {
- return false;
- }
- }
- /* If anything is not ours, then everything is not ours so we're
- definitely a subset in that case. Otherwise if there's any stray
- ones that 'other' doesn't have, we're not a subset. */
- for (mine, _, w) in self.outliers(other) {
- if !mine {
- return true;
- } else if w != 0 {
- return false;
- }
- }
- return true;
+ let &BitvSet(ref self_bitv) = self;
+ let &BitvSet(ref other_bitv) = other;
+
+ // Check that `self` intersect `other` is self
+ self_bitv.mask_words(0).zip(other_bitv.mask_words(0))
+ .all(|((_, w1), (_, w2))| w1 & w2 == w1) &&
+ // Check that `self` setminus `other` is empty
+ self_bitv.mask_words(other_bitv.storage.len()).all(|(_, w)| w == 0)
}
+ #[inline]
fn is_superset(&self, other: &BitvSet) -> bool {
other.is_subset(self)
}
if self.contains(&value) {
return false;
}
- let nbits = self.capacity();
- if value >= nbits {
- let newsize = cmp::max(value, nbits * 2) / uint::BITS + 1;
- assert!(newsize > self.bitv.storage.len());
- self.bitv.storage.grow(newsize, &0);
+ if value >= self.capacity() {
+ let new_cap = cmp::max(value + 1, self.capacity() * 2);
+ self.reserve(new_cap);
+ }
+ let &BitvSet(ref mut bitv) = self;
+ if value >= bitv.nbits {
+ // If we are increasing nbits, make sure we mask out any previously-unconsidered bits
+ let old_rem = bitv.nbits % uint::BITS;
+ if old_rem != 0 {
+ let old_last_word = (bitv.nbits + uint::BITS - 1) / uint::BITS - 1;
+ *bitv.storage.get_mut(old_last_word) &= (1 << old_rem) - 1;
+ }
+ bitv.nbits = value + 1;
}
- self.size += 1;
- self.bitv.set(value, true);
+ bitv.set(value, true);
return true;
}
if !self.contains(value) {
return false;
}
- self.size -= 1;
- self.bitv.set(*value, false);
-
- // Attempt to truncate our storage
- let mut i = self.bitv.storage.len();
- while i > 1 && *self.bitv.storage.get(i - 1) == 0 {
- i -= 1;
- }
- self.bitv.storage.truncate(i);
-
+ let &BitvSet(ref mut bitv) = self;
+ bitv.set(*value, false);
return true;
}
}
-impl BitvSet {
- /// Visits each of the words that the two bit vectors (`self` and `other`)
- /// both have in common. The three yielded arguments are (bit location,
- /// w1, w2) where the bit location is the number of bits offset so far,
- /// and w1/w2 are the words coming from the two vectors self, other.
- fn commons<'a>(&'a self, other: &'a BitvSet)
- -> Map<'static, ((uint, &'a uint), &'a Vec<uint>), (uint, uint, uint),
- Zip<Enumerate<slice::Items<'a, uint>>, Repeat<&'a Vec<uint>>>> {
- let min = cmp::min(self.bitv.storage.len(), other.bitv.storage.len());
- self.bitv.storage.slice(0, min).iter().enumerate()
- .zip(Repeat::new(&other.bitv.storage))
- .map(|((i, &w), o_store)| (i * uint::BITS, w, *o_store.get(i)))
- }
-
- /// Visits each word in `self` or `other` that extends beyond the other. This
- /// will only iterate through one of the vectors, and it only iterates
- /// over the portion that doesn't overlap with the other one.
- ///
- /// The yielded arguments are a `bool`, the bit offset, and a word. The `bool`
- /// is true if the word comes from `self`, and `false` if it comes from
- /// `other`.
- fn outliers<'a>(&'a self, other: &'a BitvSet)
- -> Map<'static, ((uint, &'a uint), uint), (bool, uint, uint),
- Zip<Enumerate<slice::Items<'a, uint>>, Repeat<uint>>> {
- let slen = self.bitv.storage.len();
- let olen = other.bitv.storage.len();
-
- if olen < slen {
- self.bitv.storage.slice_from(olen).iter().enumerate()
- .zip(Repeat::new(olen))
- .map(|((i, &w), min)| (true, (i + min) * uint::BITS, w))
- } else {
- other.bitv.storage.slice_from(slen).iter().enumerate()
- .zip(Repeat::new(slen))
- .map(|((i, &w), min)| (false, (i + min) * uint::BITS, w))
- }
- }
+pub struct BitPositions<'a> {
+ set: &'a BitvSet,
+ next_idx: uint
}
-pub struct BitPositions<'a> {
+pub struct TwoBitPositions<'a> {
set: &'a BitvSet,
+ other: &'a BitvSet,
+ merge: |uint, uint|: 'a -> uint,
+ current_word: uint,
next_idx: uint
}
impl<'a> Iterator<uint> for BitPositions<'a> {
- #[inline]
fn next(&mut self) -> Option<uint> {
while self.next_idx < self.set.capacity() {
let idx = self.next_idx;
return None;
}
+ #[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
(0, Some(self.set.capacity() - self.next_idx))
}
}
+impl<'a> Iterator<uint> for TwoBitPositions<'a> {
+ fn next(&mut self) -> Option<uint> {
+ while self.next_idx < self.set.capacity() ||
+ self.next_idx < self.other.capacity() {
+ let bit_idx = self.next_idx % uint::BITS;
+ if bit_idx == 0 {
+ let &BitvSet(ref s_bitv) = self.set;
+ let &BitvSet(ref o_bitv) = self.other;
+ // Merging the two words is a bit of an awkward dance since
+ // one Bitv might be longer than the other
+ let word_idx = self.next_idx / uint::BITS;
+ let w1 = if word_idx < s_bitv.storage.len() {
+ *s_bitv.storage.get(word_idx)
+ } else { 0 };
+ let w2 = if word_idx < o_bitv.storage.len() {
+ *o_bitv.storage.get(word_idx)
+ } else { 0 };
+ self.current_word = (self.merge)(w1, w2);
+ }
+
+ self.next_idx += 1;
+ if self.current_word & (1 << bit_idx) != 0 {
+ return Some(self.next_idx - 1);
+ }
+ }
+ return None;
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ let cap = cmp::max(self.set.capacity(), self.other.capacity());
+ (0, Some(cap - self.next_idx))
+ }
+}
+
#[cfg(test)]
mod tests {
use std::prelude::*;
use test::Bencher;
use {Set, Mutable, MutableSet};
- use bitv::{Bitv, SmallBitv, BigBitv, BitvSet, from_bools, from_fn,
- from_bytes};
+ use bitv::{Bitv, BitvSet, from_fn, from_bytes};
use bitv;
use vec::Vec;
#[test]
fn test_to_str() {
- let zerolen = Bitv::new(0u, false);
- assert_eq!(zerolen.to_str().as_slice(), "");
+ let zerolen = Bitv::new();
+ assert_eq!(zerolen.to_string().as_slice(), "");
- let eightbits = Bitv::new(8u, false);
- assert_eq!(eightbits.to_str().as_slice(), "00000000")
+ let eightbits = Bitv::with_capacity(8u, false);
+ assert_eq!(eightbits.to_string().as_slice(), "00000000")
}
#[test]
fn test_0_elements() {
- let act = Bitv::new(0u, false);
+ let act = Bitv::new();
let exp = Vec::from_elem(0u, false);
assert!(act.eq_vec(exp.as_slice()));
}
#[test]
fn test_1_element() {
- let mut act = Bitv::new(1u, false);
+ let mut act = Bitv::with_capacity(1u, false);
assert!(act.eq_vec([false]));
- act = Bitv::new(1u, true);
+ act = Bitv::with_capacity(1u, true);
assert!(act.eq_vec([true]));
}
#[test]
fn test_2_elements() {
- let mut b = bitv::Bitv::new(2, false);
+ let mut b = bitv::Bitv::with_capacity(2, false);
b.set(0, true);
b.set(1, false);
- assert_eq!(b.to_str().as_slice(), "10");
+ assert_eq!(b.to_string().as_slice(), "10");
}
#[test]
let mut act;
// all 0
- act = Bitv::new(10u, false);
+ act = Bitv::with_capacity(10u, false);
assert!((act.eq_vec(
[false, false, false, false, false, false, false, false, false, false])));
// all 1
- act = Bitv::new(10u, true);
+ act = Bitv::with_capacity(10u, true);
assert!((act.eq_vec([true, true, true, true, true, true, true, true, true, true])));
// mixed
- act = Bitv::new(10u, false);
+ act = Bitv::with_capacity(10u, false);
act.set(0u, true);
act.set(1u, true);
act.set(2u, true);
assert!((act.eq_vec([true, true, true, true, true, false, false, false, false, false])));
// mixed
- act = Bitv::new(10u, false);
+ act = Bitv::with_capacity(10u, false);
act.set(5u, true);
act.set(6u, true);
act.set(7u, true);
assert!((act.eq_vec([false, false, false, false, false, true, true, true, true, true])));
// mixed
- act = Bitv::new(10u, false);
+ act = Bitv::with_capacity(10u, false);
act.set(0u, true);
act.set(3u, true);
act.set(6u, true);
let mut act;
// all 0
- act = Bitv::new(31u, false);
+ act = Bitv::with_capacity(31u, false);
assert!(act.eq_vec(
[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false]));
// all 1
- act = Bitv::new(31u, true);
+ act = Bitv::with_capacity(31u, true);
assert!(act.eq_vec(
[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true]));
// mixed
- act = Bitv::new(31u, false);
+ act = Bitv::with_capacity(31u, false);
act.set(0u, true);
act.set(1u, true);
act.set(2u, true);
false, false, false, false, false, false]));
// mixed
- act = Bitv::new(31u, false);
+ act = Bitv::with_capacity(31u, false);
act.set(16u, true);
act.set(17u, true);
act.set(18u, true);
false, false, false, false, false, false, false]));
// mixed
- act = Bitv::new(31u, false);
+ act = Bitv::with_capacity(31u, false);
act.set(24u, true);
act.set(25u, true);
act.set(26u, true);
false, true, true, true, true, true, true, true]));
// mixed
- act = Bitv::new(31u, false);
+ act = Bitv::with_capacity(31u, false);
act.set(3u, true);
act.set(17u, true);
act.set(30u, true);
let mut act;
// all 0
- act = Bitv::new(32u, false);
+ act = Bitv::with_capacity(32u, false);
assert!(act.eq_vec(
[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false]));
// all 1
- act = Bitv::new(32u, true);
+ act = Bitv::with_capacity(32u, true);
assert!(act.eq_vec(
[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true]));
// mixed
- act = Bitv::new(32u, false);
+ act = Bitv::with_capacity(32u, false);
act.set(0u, true);
act.set(1u, true);
act.set(2u, true);
false, false, false, false, false, false, false]));
// mixed
- act = Bitv::new(32u, false);
+ act = Bitv::with_capacity(32u, false);
act.set(16u, true);
act.set(17u, true);
act.set(18u, true);
false, false, false, false, false, false, false, false]));
// mixed
- act = Bitv::new(32u, false);
+ act = Bitv::with_capacity(32u, false);
act.set(24u, true);
act.set(25u, true);
act.set(26u, true);
false, true, true, true, true, true, true, true, true]));
// mixed
- act = Bitv::new(32u, false);
+ act = Bitv::with_capacity(32u, false);
act.set(3u, true);
act.set(17u, true);
act.set(30u, true);
let mut act;
// all 0
- act = Bitv::new(33u, false);
+ act = Bitv::with_capacity(33u, false);
assert!(act.eq_vec(
[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false]));
// all 1
- act = Bitv::new(33u, true);
+ act = Bitv::with_capacity(33u, true);
assert!(act.eq_vec(
[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true]));
// mixed
- act = Bitv::new(33u, false);
+ act = Bitv::with_capacity(33u, false);
act.set(0u, true);
act.set(1u, true);
act.set(2u, true);
false, false, false, false, false, false, false, false]));
// mixed
- act = Bitv::new(33u, false);
+ act = Bitv::with_capacity(33u, false);
act.set(16u, true);
act.set(17u, true);
act.set(18u, true);
false, false, false, false, false, false, false, false, false]));
// mixed
- act = Bitv::new(33u, false);
+ act = Bitv::with_capacity(33u, false);
act.set(24u, true);
act.set(25u, true);
act.set(26u, true);
false, true, true, true, true, true, true, true, true, false]));
// mixed
- act = Bitv::new(33u, false);
+ act = Bitv::with_capacity(33u, false);
act.set(3u, true);
act.set(17u, true);
act.set(30u, true);
#[test]
fn test_equal_differing_sizes() {
- let v0 = Bitv::new(10u, false);
- let v1 = Bitv::new(11u, false);
+ let v0 = Bitv::with_capacity(10u, false);
+ let v1 = Bitv::with_capacity(11u, false);
assert!(v0 != v1);
}
#[test]
fn test_equal_greatly_differing_sizes() {
- let v0 = Bitv::new(10u, false);
- let v1 = Bitv::new(110u, false);
+ let v0 = Bitv::with_capacity(10u, false);
+ let v1 = Bitv::with_capacity(110u, false);
assert!(v0 != v1);
}
#[test]
fn test_equal_sneaky_small() {
- let mut a = bitv::Bitv::new(1, false);
+ let mut a = bitv::Bitv::with_capacity(1, false);
a.set(0, true);
- let mut b = bitv::Bitv::new(1, true);
+ let mut b = bitv::Bitv::with_capacity(1, true);
b.set(0, true);
assert_eq!(a, b);
#[test]
fn test_equal_sneaky_big() {
- let mut a = bitv::Bitv::new(100, false);
+ let mut a = bitv::Bitv::with_capacity(100, false);
for i in range(0u, 100) {
a.set(i, true);
}
- let mut b = bitv::Bitv::new(100, true);
+ let mut b = bitv::Bitv::with_capacity(100, true);
for i in range(0u, 100) {
b.set(i, true);
}
fn test_from_bytes() {
let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]);
let str = format!("{}{}{}", "10110110", "00000000", "11111111");
- assert_eq!(bitv.to_str().as_slice(), str.as_slice());
+ assert_eq!(bitv.to_string().as_slice(), str.as_slice());
}
#[test]
fn test_to_bytes() {
- let mut bv = Bitv::new(3, true);
+ let mut bv = Bitv::with_capacity(3, true);
bv.set(1, false);
assert_eq!(bv.to_bytes(), vec!(0b10100000));
- let mut bv = Bitv::new(9, false);
+ let mut bv = Bitv::with_capacity(9, false);
bv.set(2, true);
bv.set(8, true);
assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
#[test]
fn test_from_bools() {
- assert!(from_bools([true, false, true, true]).to_str().as_slice() ==
- "1011");
+ let bools = vec![true, false, true, true];
+ let bitv: Bitv = bools.iter().map(|n| *n).collect();
+ assert_eq!(bitv.to_string().as_slice(), "1011");
}
#[test]
fn test_to_bools() {
let bools = vec!(false, false, true, false, false, true, true, false);
- assert_eq!(from_bytes([0b00100110]).to_bools(), bools);
+ assert_eq!(from_bytes([0b00100110]).iter().collect::<Vec<bool>>(), bools);
}
#[test]
fn test_bitv_iterator() {
let bools = [true, false, true, true];
- let bitv = from_bools(bools);
+ let bitv: Bitv = bools.iter().map(|n| *n).collect();
for (act, &ex) in bitv.iter().zip(bools.iter()) {
assert_eq!(ex, act);
#[test]
fn test_bitv_set_iterator() {
let bools = [true, false, true, true];
- let bitv = BitvSet::from_bitv(from_bools(bools));
+ let bitv = BitvSet::from_bitv(bools.iter().map(|n| *n).collect());
let idxs: Vec<uint> = bitv.iter().collect();
assert_eq!(idxs, vec!(0, 2, 3));
let lengths = [10, 64, 100];
for &b in bools.iter() {
for &l in lengths.iter() {
- let bitset = BitvSet::from_bitv(Bitv::new(l, b));
+ let bitset = BitvSet::from_bitv(Bitv::with_capacity(l, b));
assert_eq!(bitset.contains(&1u), b)
assert_eq!(bitset.contains(&(l-1u)), b)
assert!(!bitset.contains(&l))
#[test]
fn test_small_difference() {
- let mut b1 = Bitv::new(3, false);
- let mut b2 = Bitv::new(3, false);
+ let mut b1 = Bitv::with_capacity(3, false);
+ let mut b2 = Bitv::with_capacity(3, false);
b1.set(0, true);
b1.set(1, true);
b2.set(1, true);
b2.set(2, true);
assert!(b1.difference(&b2));
- assert!(b1[0]);
- assert!(!b1[1]);
- assert!(!b1[2]);
+ assert!(b1.get(0));
+ assert!(!b1.get(1));
+ assert!(!b1.get(2));
}
#[test]
fn test_big_difference() {
- let mut b1 = Bitv::new(100, false);
- let mut b2 = Bitv::new(100, false);
+ let mut b1 = Bitv::with_capacity(100, false);
+ let mut b2 = Bitv::with_capacity(100, false);
b1.set(0, true);
b1.set(40, true);
b2.set(40, true);
b2.set(80, true);
assert!(b1.difference(&b2));
- assert!(b1[0]);
- assert!(!b1[40]);
- assert!(!b1[80]);
+ assert!(b1.get(0));
+ assert!(!b1.get(40));
+ assert!(!b1.get(80));
}
#[test]
fn test_small_clear() {
- let mut b = Bitv::new(14, true);
+ let mut b = Bitv::with_capacity(14, true);
b.clear();
- b.ones(|i| {
+ BitvSet::from_bitv(b).iter().advance(|i| {
fail!("found 1 at {:?}", i)
});
}
#[test]
fn test_big_clear() {
- let mut b = Bitv::new(140, true);
+ let mut b = Bitv::with_capacity(140, true);
b.clear();
- b.ones(|i| {
+ BitvSet::from_bitv(b).iter().advance(|i| {
fail!("found 1 at {:?}", i)
});
}
+ #[test]
+ fn test_bitv_masking() {
+ let b = Bitv::with_capacity(140, true);
+ let mut bs = BitvSet::from_bitv(b);
+ assert!(bs.contains(&139));
+ assert!(!bs.contains(&140));
+ assert!(bs.insert(150));
+ assert!(!bs.contains(&140));
+ assert!(!bs.contains(&149));
+ assert!(bs.contains(&150));
+ assert!(!bs.contains(&151));
+ }
+
#[test]
fn test_bitv_set_basic() {
+ // calculate nbits with uint::BITS granularity
+ fn calc_nbits(bits: uint) -> uint {
+ uint::BITS * ((bits + uint::BITS - 1) / uint::BITS)
+ }
+
let mut b = BitvSet::new();
+ assert_eq!(b.capacity(), calc_nbits(0));
assert!(b.insert(3));
+ assert_eq!(b.capacity(), calc_nbits(3));
assert!(!b.insert(3));
assert!(b.contains(&3));
+ assert!(b.insert(4));
+ assert!(!b.insert(4));
+ assert!(b.contains(&3));
assert!(b.insert(400));
+ assert_eq!(b.capacity(), calc_nbits(400));
assert!(!b.insert(400));
assert!(b.contains(&400));
- assert_eq!(b.len(), 2);
+ assert_eq!(b.len(), 3);
}
#[test]
let mut i = 0;
let expected = [3, 5, 11, 77];
- a.intersection(&b, |x| {
- assert_eq!(*x, expected[i]);
+ a.intersection(&b).advance(|x| {
+ assert_eq!(x, expected[i]);
i += 1;
true
});
let mut i = 0;
let expected = [1, 5, 500];
- a.difference(&b, |x| {
- assert_eq!(*x, expected[i]);
+ a.difference(&b).advance(|x| {
+ assert_eq!(x, expected[i]);
i += 1;
true
});
let mut i = 0;
let expected = [1, 5, 11, 14, 220];
- a.symmetric_difference(&b, |x| {
- assert_eq!(*x, expected[i]);
+ a.symmetric_difference(&b).advance(|x| {
+ assert_eq!(x, expected[i]);
i += 1;
true
});
let mut i = 0;
let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160];
- a.union(&b, |x| {
- assert_eq!(*x, expected[i]);
+ a.union(&b).advance(|x| {
+ assert_eq!(x, expected[i]);
i += 1;
true
});
assert_eq!(i, expected.len());
}
+ #[test]
+ fn test_bitv_set_subset() {
+ let mut set1 = BitvSet::new();
+ let mut set2 = BitvSet::new();
+
+ assert!(set1.is_subset(&set2)); // {} {}
+ set2.insert(100);
+ assert!(set1.is_subset(&set2)); // {} { 1 }
+ set2.insert(200);
+ assert!(set1.is_subset(&set2)); // {} { 1, 2 }
+ set1.insert(200);
+ assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 }
+ set1.insert(300);
+ assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 }
+ set2.insert(300);
+ assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 }
+ set2.insert(400);
+ assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 }
+ set2.remove(&100);
+ assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 }
+ set2.remove(&300);
+ assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 }
+ set1.remove(&300);
+ assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 }
+ }
+
#[test]
fn test_bitv_remove() {
let mut a = BitvSet::new();
assert!(a.insert(1000));
assert!(a.remove(&1000));
+ a.shrink_to_fit();
assert_eq!(a.capacity(), uint::BITS);
}
assert!(!v.none());
}
+ #[test]
+ fn test_bitv_push_pop() {
+ let mut s = Bitv::with_capacity(5 * uint::BITS - 2, false);
+ assert_eq!(s.len(), 5 * uint::BITS - 2);
+ assert_eq!(s.get(5 * uint::BITS - 3), false);
+ s.push(true);
+ s.push(true);
+ assert_eq!(s.get(5 * uint::BITS - 2), true);
+ assert_eq!(s.get(5 * uint::BITS - 1), true);
+ // Here the internal vector will need to be extended
+ s.push(false);
+ assert_eq!(s.get(5 * uint::BITS), false);
+ s.push(false);
+ assert_eq!(s.get(5 * uint::BITS + 1), false);
+ assert_eq!(s.len(), 5 * uint::BITS + 2);
+ // Pop it all off
+ assert_eq!(s.pop(), false);
+ assert_eq!(s.pop(), false);
+ assert_eq!(s.pop(), true);
+ assert_eq!(s.pop(), true);
+ assert_eq!(s.len(), 5 * uint::BITS - 2);
+ }
+
+ #[test]
+ fn test_bitv_truncate() {
+ let mut s = Bitv::with_capacity(5 * uint::BITS, true);
+
+ assert_eq!(s, Bitv::with_capacity(5 * uint::BITS, true));
+ assert_eq!(s.len(), 5 * uint::BITS);
+ s.truncate(4 * uint::BITS);
+ assert_eq!(s, Bitv::with_capacity(4 * uint::BITS, true));
+ assert_eq!(s.len(), 4 * uint::BITS);
+ // Truncating to a size > s.len() should be a noop
+ s.truncate(5 * uint::BITS);
+ assert_eq!(s, Bitv::with_capacity(4 * uint::BITS, true));
+ assert_eq!(s.len(), 4 * uint::BITS);
+ s.truncate(3 * uint::BITS - 10);
+ assert_eq!(s, Bitv::with_capacity(3 * uint::BITS - 10, true));
+ assert_eq!(s.len(), 3 * uint::BITS - 10);
+ s.truncate(0);
+ assert_eq!(s, Bitv::with_capacity(0, true));
+ assert_eq!(s.len(), 0);
+ }
+
+ #[test]
+ fn test_bitv_reserve() {
+ let mut s = Bitv::with_capacity(5 * uint::BITS, true);
+ // Check capacity
+ assert_eq!(s.capacity(), 5 * uint::BITS);
+ s.reserve(2 * uint::BITS);
+ assert_eq!(s.capacity(), 5 * uint::BITS);
+ s.reserve(7 * uint::BITS);
+ assert_eq!(s.capacity(), 7 * uint::BITS);
+ s.reserve(7 * uint::BITS);
+ assert_eq!(s.capacity(), 7 * uint::BITS);
+ s.reserve(7 * uint::BITS + 1);
+ assert_eq!(s.capacity(), 8 * uint::BITS);
+ // Check that length hasn't changed
+ assert_eq!(s.len(), 5 * uint::BITS);
+ s.push(true);
+ s.push(false);
+ s.push(true);
+ assert_eq!(s.get(5 * uint::BITS - 1), true);
+ assert_eq!(s.get(5 * uint::BITS - 0), true);
+ assert_eq!(s.get(5 * uint::BITS + 1), false);
+ assert_eq!(s.get(5 * uint::BITS + 2), true);
+ }
+
+ #[test]
+ fn test_bitv_grow() {
+ let mut bitv = from_bytes([0b10110110, 0b00000000, 0b10101010]);
+ bitv.grow(32, true);
+ assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010,
+ 0xFF, 0xFF, 0xFF, 0xFF]));
+ bitv.grow(64, false);
+ assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0]));
+ bitv.grow(16, true);
+ assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]));
+ }
+
+ #[test]
+ fn test_bitv_extend() {
+ let mut bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]);
+ let ext = from_bytes([0b01001001, 0b10010010, 0b10111101]);
+ bitv.extend(ext.iter());
+ assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b11111111,
+ 0b01001001, 0b10010010, 0b10111101]));
+ }
+
#[test]
fn test_bitv_set_show() {
let mut s = BitvSet::new();
s.insert(10);
s.insert(50);
s.insert(2);
- assert_eq!("{1, 2, 10, 50}".to_string(), s.to_str());
+ assert_eq!("{1, 2, 10, 50}".to_string(), s.to_string());
}
fn rng() -> rand::IsaacRng {
})
}
- #[bench]
- fn bench_small_bitv_small(b: &mut Bencher) {
- let mut r = rng();
- let mut bitv = SmallBitv::new(uint::BITS);
- b.iter(|| {
- bitv.set((r.next_u32() as uint) % uint::BITS, true);
- &bitv
- })
- }
-
- #[bench]
- fn bench_big_bitv_small(b: &mut Bencher) {
- let mut r = rng();
- let mut bitv = BigBitv::new(vec!(0));
- b.iter(|| {
- bitv.set((r.next_u32() as uint) % uint::BITS, true);
- &bitv
- })
- }
-
- #[bench]
- fn bench_big_bitv_big(b: &mut Bencher) {
- let mut r = rng();
- let mut storage = vec!();
- storage.grow(BENCH_BITS / uint::BITS, &0u);
- let mut bitv = BigBitv::new(storage);
- b.iter(|| {
- bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
- &bitv
- })
- }
-
#[bench]
fn bench_bitv_big(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = Bitv::new(BENCH_BITS, false);
+ let mut bitv = Bitv::with_capacity(BENCH_BITS, false);
b.iter(|| {
bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
&bitv
#[bench]
fn bench_bitv_small(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = Bitv::new(uint::BITS, false);
+ let mut bitv = Bitv::with_capacity(uint::BITS, false);
b.iter(|| {
bitv.set((r.next_u32() as uint) % uint::BITS, true);
&bitv
#[bench]
fn bench_bitv_big_union(b: &mut Bencher) {
- let mut b1 = Bitv::new(BENCH_BITS, false);
- let b2 = Bitv::new(BENCH_BITS, false);
+ let mut b1 = Bitv::with_capacity(BENCH_BITS, false);
+ let b2 = Bitv::with_capacity(BENCH_BITS, false);
b.iter(|| {
b1.union(&b2);
})
#[bench]
fn bench_btv_small_iter(b: &mut Bencher) {
- let bitv = Bitv::new(uint::BITS, false);
+ let bitv = Bitv::with_capacity(uint::BITS, false);
b.iter(|| {
let mut _sum = 0;
for pres in bitv.iter() {
#[bench]
fn bench_bitv_big_iter(b: &mut Bencher) {
- let bitv = Bitv::new(BENCH_BITS, false);
+ let bitv = Bitv::with_capacity(BENCH_BITS, false);
b.iter(|| {
let mut _sum = 0;
for pres in bitv.iter() {
fn insert_test_one() {
let b = BTree::new(1i, "abc".to_string(), 2);
let is_insert = b.insert(2i, "xyz".to_string());
- //println!("{}", is_insert.clone().to_str());
assert!(is_insert.root.is_leaf());
}
let leaf_elt_3 = LeafElt::new(3i, "ccc".to_string());
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3));
let b = BTree::new_with_node_len(n, 3, 2);
- //println!("{}", b.clone().insert(4, "ddd".to_string()).to_str());
+ //println!("{}", b.clone().insert(4, "ddd".to_string()).to_string());
assert!(b.insert(4, "ddd".to_string()).root.is_leaf());
}
let leaf_elt_4 = LeafElt::new(4i, "ddd".to_string());
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3, leaf_elt_4));
let b = BTree::new_with_node_len(n, 3, 2);
- //println!("{}", b.clone().insert(5, "eee".to_string()).to_str());
+ //println!("{}", b.clone().insert(5, "eee".to_string()).to_string());
assert!(!b.insert(5, "eee".to_string()).root.is_leaf());
}
b = b.clone().insert(7, "ggg".to_string());
b = b.clone().insert(8, "hhh".to_string());
b = b.clone().insert(0, "omg".to_string());
- //println!("{}", b.clone().to_str());
+ //println!("{}", b.clone().to_string());
assert!(!b.root.is_leaf());
}
assert!(&b2.cmp(&b) == &Greater)
}
- //Tests the BTree's to_str() method.
+ //Tests the BTree's to_string() method.
#[test]
fn btree_tostr_test() {
let b = BTree::new(1i, "abc".to_string(), 2);
- assert_eq!(b.to_str(), "Key: 1, value: abc;".to_string())
+ assert_eq!(b.to_string(), "Key: 1, value: abc;".to_string())
}
}
#[test]
fn test_show() {
let list: DList<int> = range(0i, 10).collect();
- assert!(list.to_str().as_slice() == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+ assert!(list.to_string().as_slice() == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let list: DList<&str> = vec!["just", "one", "test", "more"].iter()
.map(|&s| s)
.collect();
- assert!(list.to_str().as_slice() == "[just, one, test, more]");
+ assert!(list.to_string().as_slice() == "[just, one, test, more]");
}
#[cfg(test)]
* Collection types.
*/
-#![crate_id = "collections#0.11.0"]
+#![crate_id = "collections#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "collections"]
#![experimental]
#![crate_type = "rlib"]
#![license = "MIT/ASL2"]
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![feature(unsafe_destructor)]
#![no_std]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;
map.insert(1, 2i);
map.insert(3, 4i);
- let map_str = map.to_str();
+ let map_str = map.to_string();
let map_str = map_str.as_slice();
assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
assert_eq!(format!("{}", empty), "{}".to_string());
#[inline]
fn into_string(self) -> String {
match self {
- Slice(s) => s.to_string(),
+ Slice(s) => String::from_str(s),
Owned(s) => s
}
}
fn clone(&self) -> MaybeOwned<'a> {
match *self {
Slice(s) => Slice(s),
- Owned(ref s) => Owned(s.to_string())
+ Owned(ref s) => Owned(String::from_str(s.as_slice()))
}
}
}
let a = vec![65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = a.as_ptr();
let c = from_buf_len(b, 3u);
- assert_eq!(c, "AAA".to_string());
+ assert_eq!(c, String::from_str("AAA"));
}
}
}
/// Convert `self` into a `String`, not making a copy if possible.
fn into_string(self) -> String;
- /// Convert `self` into a `String`.
- #[inline]
- fn to_string(&self) -> String {
- String::from_str(self.as_slice())
- }
-
#[allow(missing_doc)]
#[deprecated = "replaced by .into_string()"]
fn into_owned(self) -> String {
impl<'a> StrAllocating for &'a str {
#[inline]
fn into_string(self) -> String {
- self.to_string()
+ String::from_str(self)
}
}
#[cfg(test)]
mod tests {
- use std::prelude::*;
use std::iter::AdditiveIterator;
use std::default::Default;
+ use std::char::Char;
+ use std::clone::Clone;
+ use std::cmp::{Equal, Greater, Less, Ord, Eq, PartialOrd, PartialEq, Equiv};
+ use std::result::{Ok, Err};
+ use std::option::{Some, None};
+ use std::ptr::RawPtr;
+ use std::iter::{Iterator, DoubleEndedIterator};
+ use Collection;
- use str::*;
+ use super::*;
+ use std::slice::{Vector, ImmutableVector};
use string::String;
use vec::Vec;
#[test]
fn test_collect() {
- let empty = "".to_string();
+ let empty = String::from_str("");
let s: String = empty.as_slice().chars().collect();
assert_eq!(empty, s);
- let data = "ประเทศไทย中".to_string();
+ let data = String::from_str("ประเทศไทย中");
let s: String = data.as_slice().chars().collect();
assert_eq!(data, s);
}
#[test]
fn test_into_bytes() {
- let data = "asdf".to_string();
+ let data = String::from_str("asdf");
let buf = data.into_bytes();
assert_eq!(b"asdf", buf.as_slice());
}
assert!(data.slice(2u, 4u).find_str("ab").is_none());
let string = "ประเทศไทย中华Việt Nam";
- let mut data = string.to_string();
+ let mut data = String::from_str(string);
data.push_str(string);
assert!(data.as_slice().find_str("ไท华").is_none());
assert_eq!(data.as_slice().slice(0u, 43u).find_str(""), Some(0u));
fn t(v: &[String], s: &str) {
assert_eq!(v.concat().as_slice(), s);
}
- t(["you".to_string(), "know".to_string(), "I'm".to_string(),
- "no".to_string(), "good".to_string()], "youknowI'mnogood");
+ t([String::from_str("you"), String::from_str("know"),
+ String::from_str("I'm"),
+ String::from_str("no"), String::from_str("good")],
+ "youknowI'mnogood");
let v: &[String] = [];
t(v, "");
- t(["hi".to_string()], "hi");
+ t([String::from_str("hi")], "hi");
}
#[test]
fn t(v: &[String], sep: &str, s: &str) {
assert_eq!(v.connect(sep).as_slice(), s);
}
- t(["you".to_string(), "know".to_string(), "I'm".to_string(),
- "no".to_string(), "good".to_string()],
+ t([String::from_str("you"), String::from_str("know"),
+ String::from_str("I'm"),
+ String::from_str("no"), String::from_str("good")],
" ", "you know I'm no good");
let v: &[String] = [];
t(v, " ", "");
- t(["hi".to_string()], " ", "hi");
+ t([String::from_str("hi")], " ", "hi");
}
#[test]
#[test]
fn test_repeat() {
- assert_eq!("x".repeat(4), "xxxx".to_string());
- assert_eq!("hi".repeat(4), "hihihihi".to_string());
- assert_eq!("ไท华".repeat(3), "ไท华ไท华ไท华".to_string());
- assert_eq!("".repeat(4), "".to_string());
- assert_eq!("hi".repeat(0), "".to_string());
+ assert_eq!("x".repeat(4), String::from_str("xxxx"));
+ assert_eq!("hi".repeat(4), String::from_str("hihihihi"));
+ assert_eq!("ไท华".repeat(3), String::from_str("ไท华ไท华ไท华"));
+ assert_eq!("".repeat(4), String::from_str(""));
+ assert_eq!("hi".repeat(0), String::from_str(""));
}
#[test]
}
let letters = a_million_letter_a();
assert!(half_a_million_letter_a() ==
- unsafe {raw::slice_bytes(letters.as_slice(),
+ unsafe {String::from_str(raw::slice_bytes(letters.as_slice(),
0u,
- 500000)}.to_string());
+ 500000))});
}
#[test]
#[test]
fn test_replace() {
let a = "a";
- assert_eq!("".replace(a, "b"), "".to_string());
- assert_eq!("a".replace(a, "b"), "b".to_string());
- assert_eq!("ab".replace(a, "b"), "bb".to_string());
+ assert_eq!("".replace(a, "b"), String::from_str(""));
+ assert_eq!("a".replace(a, "b"), String::from_str("b"));
+ assert_eq!("ab".replace(a, "b"), String::from_str("bb"));
let test = "test";
assert!(" test test ".replace(test, "toast") ==
- " toast toast ".to_string());
- assert_eq!(" test test ".replace(test, ""), " ".to_string());
+ String::from_str(" toast toast "));
+ assert_eq!(" test test ".replace(test, ""), String::from_str(" "));
}
#[test]
}
let letters = a_million_letter_x();
assert!(half_a_million_letter_x() ==
- letters.as_slice().slice(0u, 3u * 500000u).to_string());
+ String::from_str(letters.as_slice().slice(0u, 3u * 500000u)));
}
#[test]
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = raw::from_c_str(b);
- assert_eq!(c, "AAAAAAA".to_string());
+ assert_eq!(c, String::from_str("AAAAAAA"));
}
}
fn test_as_bytes_fail() {
// Don't double free. (I'm not sure if this exercises the
// original problem code path anymore.)
- let s = "".to_string();
+ let s = String::from_str("");
let _bytes = s.as_bytes();
fail!();
}
#[test]
fn vec_str_conversions() {
- let s1: String = "All mimsy were the borogoves".to_string();
+ let s1: String = String::from_str("All mimsy were the borogoves");
let v: Vec<u8> = Vec::from_slice(s1.as_bytes());
- let s2: String = from_utf8(v.as_slice()).unwrap().to_string();
+ let s2: String = String::from_str(from_utf8(v.as_slice()).unwrap());
let mut i: uint = 0u;
let n1: uint = s1.len();
let n2: uint = v.len();
#[test]
fn test_utf16() {
let pairs =
- [("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n".to_string(),
+ [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
0xd800_u16, 0xdf30_u16, 0x000a_u16]),
- ("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n".to_string(),
+ (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
0x000a_u16]),
- ("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n".to_string(),
+ (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
- ("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n".to_string(),
+ (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
0x000a_u16 ]),
// Issue #12318, even-numbered non-BMP planes
- ("\U00020000".to_string(),
+ (String::from_str("\U00020000"),
vec![0xD840, 0xDC00])];
for p in pairs.iter() {
fn test_utf16_lossy() {
// completely positive cases tested above.
// lead + eof
- assert_eq!(from_utf16_lossy([0xD800]), "\uFFFD".to_string());
+ assert_eq!(from_utf16_lossy([0xD800]), String::from_str("\uFFFD"));
// lead + lead
- assert_eq!(from_utf16_lossy([0xD800, 0xD800]), "\uFFFD\uFFFD".to_string());
+ assert_eq!(from_utf16_lossy([0xD800, 0xD800]), String::from_str("\uFFFD\uFFFD"));
// isolated trail
- assert_eq!(from_utf16_lossy([0x0061, 0xDC00]), "a\uFFFD".to_string());
+ assert_eq!(from_utf16_lossy([0x0061, 0xDC00]), String::from_str("a\uFFFD"));
// general
assert_eq!(from_utf16_lossy([0xD800, 0xd801, 0xdc8b, 0xD800]),
- "\uFFFD𐒋\uFFFD".to_string());
+ String::from_str("\uFFFD𐒋\uFFFD"));
}
#[test]
#[test]
fn test_escape_unicode() {
- assert_eq!("abc".escape_unicode(), "\\x61\\x62\\x63".to_string());
- assert_eq!("a c".escape_unicode(), "\\x61\\x20\\x63".to_string());
- assert_eq!("\r\n\t".escape_unicode(), "\\x0d\\x0a\\x09".to_string());
- assert_eq!("'\"\\".escape_unicode(), "\\x27\\x22\\x5c".to_string());
- assert_eq!("\x00\x01\xfe\xff".escape_unicode(), "\\x00\\x01\\xfe\\xff".to_string());
- assert_eq!("\u0100\uffff".escape_unicode(), "\\u0100\\uffff".to_string());
- assert_eq!("\U00010000\U0010ffff".escape_unicode(), "\\U00010000\\U0010ffff".to_string());
- assert_eq!("ab\ufb00".escape_unicode(), "\\x61\\x62\\ufb00".to_string());
- assert_eq!("\U0001d4ea\r".escape_unicode(), "\\U0001d4ea\\x0d".to_string());
+ assert_eq!("abc".escape_unicode(), String::from_str("\\x61\\x62\\x63"));
+ assert_eq!("a c".escape_unicode(), String::from_str("\\x61\\x20\\x63"));
+ assert_eq!("\r\n\t".escape_unicode(), String::from_str("\\x0d\\x0a\\x09"));
+ assert_eq!("'\"\\".escape_unicode(), String::from_str("\\x27\\x22\\x5c"));
+ assert_eq!("\x00\x01\xfe\xff".escape_unicode(), String::from_str("\\x00\\x01\\xfe\\xff"));
+ assert_eq!("\u0100\uffff".escape_unicode(), String::from_str("\\u0100\\uffff"));
+ assert_eq!("\U00010000\U0010ffff".escape_unicode(),
+ String::from_str("\\U00010000\\U0010ffff"));
+ assert_eq!("ab\ufb00".escape_unicode(), String::from_str("\\x61\\x62\\ufb00"));
+ assert_eq!("\U0001d4ea\r".escape_unicode(), String::from_str("\\U0001d4ea\\x0d"));
}
#[test]
fn test_escape_default() {
- assert_eq!("abc".escape_default(), "abc".to_string());
- assert_eq!("a c".escape_default(), "a c".to_string());
- assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t".to_string());
- assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\".to_string());
- assert_eq!("\u0100\uffff".escape_default(), "\\u0100\\uffff".to_string());
- assert_eq!("\U00010000\U0010ffff".escape_default(), "\\U00010000\\U0010ffff".to_string());
- assert_eq!("ab\ufb00".escape_default(), "ab\\ufb00".to_string());
- assert_eq!("\U0001d4ea\r".escape_default(), "\\U0001d4ea\\r".to_string());
+ assert_eq!("abc".escape_default(), String::from_str("abc"));
+ assert_eq!("a c".escape_default(), String::from_str("a c"));
+ assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t"));
+ assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\"));
+ assert_eq!("\u0100\uffff".escape_default(), String::from_str("\\u0100\\uffff"));
+ assert_eq!("\U00010000\U0010ffff".escape_default(),
+ String::from_str("\\U00010000\\U0010ffff"));
+ assert_eq!("ab\ufb00".escape_default(), String::from_str("ab\\ufb00"));
+ assert_eq!("\U0001d4ea\r".escape_default(), String::from_str("\\U0001d4ea\\r"));
}
#[test]
#[test]
fn test_nfd_chars() {
- assert_eq!("abc".nfd_chars().collect::<String>(), "abc".to_string());
- assert_eq!("\u1e0b\u01c4".nfd_chars().collect::<String>(), "d\u0307\u01c4".to_string());
- assert_eq!("\u2026".nfd_chars().collect::<String>(), "\u2026".to_string());
- assert_eq!("\u2126".nfd_chars().collect::<String>(), "\u03a9".to_string());
- assert_eq!("\u1e0b\u0323".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("\u1e0d\u0307".nfd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("a\u0301".nfd_chars().collect::<String>(), "a\u0301".to_string());
- assert_eq!("\u0301a".nfd_chars().collect::<String>(), "\u0301a".to_string());
- assert_eq!("\ud4db".nfd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
- assert_eq!("\uac1c".nfd_chars().collect::<String>(), "\u1100\u1162".to_string());
+ assert_eq!("abc".nfd_chars().collect::<String>(), String::from_str("abc"));
+ assert_eq!("\u1e0b\u01c4".nfd_chars().collect::<String>(),
+ String::from_str("d\u0307\u01c4"));
+ assert_eq!("\u2026".nfd_chars().collect::<String>(), String::from_str("\u2026"));
+ assert_eq!("\u2126".nfd_chars().collect::<String>(), String::from_str("\u03a9"));
+ assert_eq!("\u1e0b\u0323".nfd_chars().collect::<String>(),
+ String::from_str("d\u0323\u0307"));
+ assert_eq!("\u1e0d\u0307".nfd_chars().collect::<String>(),
+ String::from_str("d\u0323\u0307"));
+ assert_eq!("a\u0301".nfd_chars().collect::<String>(), String::from_str("a\u0301"));
+ assert_eq!("\u0301a".nfd_chars().collect::<String>(), String::from_str("\u0301a"));
+ assert_eq!("\ud4db".nfd_chars().collect::<String>(),
+ String::from_str("\u1111\u1171\u11b6"));
+ assert_eq!("\uac1c".nfd_chars().collect::<String>(), String::from_str("\u1100\u1162"));
}
#[test]
fn test_nfkd_chars() {
- assert_eq!("abc".nfkd_chars().collect::<String>(), "abc".to_string());
- assert_eq!("\u1e0b\u01c4".nfkd_chars().collect::<String>(), "d\u0307DZ\u030c".to_string());
- assert_eq!("\u2026".nfkd_chars().collect::<String>(), "...".to_string());
- assert_eq!("\u2126".nfkd_chars().collect::<String>(), "\u03a9".to_string());
- assert_eq!("\u1e0b\u0323".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("\u1e0d\u0307".nfkd_chars().collect::<String>(), "d\u0323\u0307".to_string());
- assert_eq!("a\u0301".nfkd_chars().collect::<String>(), "a\u0301".to_string());
- assert_eq!("\u0301a".nfkd_chars().collect::<String>(), "\u0301a".to_string());
- assert_eq!("\ud4db".nfkd_chars().collect::<String>(), "\u1111\u1171\u11b6".to_string());
- assert_eq!("\uac1c".nfkd_chars().collect::<String>(), "\u1100\u1162".to_string());
+ assert_eq!("abc".nfkd_chars().collect::<String>(), String::from_str("abc"));
+ assert_eq!("\u1e0b\u01c4".nfkd_chars().collect::<String>(),
+ String::from_str("d\u0307DZ\u030c"));
+ assert_eq!("\u2026".nfkd_chars().collect::<String>(), String::from_str("..."));
+ assert_eq!("\u2126".nfkd_chars().collect::<String>(), String::from_str("\u03a9"));
+ assert_eq!("\u1e0b\u0323".nfkd_chars().collect::<String>(),
+ String::from_str("d\u0323\u0307"));
+ assert_eq!("\u1e0d\u0307".nfkd_chars().collect::<String>(),
+ String::from_str("d\u0323\u0307"));
+ assert_eq!("a\u0301".nfkd_chars().collect::<String>(), String::from_str("a\u0301"));
+ assert_eq!("\u0301a".nfkd_chars().collect::<String>(),
+ String::from_str("\u0301a"));
+ assert_eq!("\ud4db".nfkd_chars().collect::<String>(),
+String::from_str("\u1111\u1171\u11b6"));
+ assert_eq!("\uac1c".nfkd_chars().collect::<String>(), String::from_str("\u1100\u1162"));
}
#[test]
v.iter().map(|x| x.len()).sum()
}
- let s = "01234".to_string();
+ let s = String::from_str("01234");
assert_eq!(5, sum_len(["012", "", "34"]));
- assert_eq!(5, sum_len(["01".to_string(), "2".to_string(),
- "34".to_string(), "".to_string()]));
+ assert_eq!(5, sum_len([String::from_str("01"), String::from_str("2"),
+ String::from_str("34"), String::from_str("")]));
assert_eq!(5, sum_len([s.as_slice()]));
}
#[test]
fn test_str_from_utf8_owned() {
let xs = Vec::from_slice(b"hello");
- assert_eq!(from_utf8_owned(xs), Ok("hello".to_string()));
+ assert_eq!(from_utf8_owned(xs), Ok(String::from_str("hello")));
let xs = Vec::from_slice("ศไทย中华Việt Nam".as_bytes());
- assert_eq!(from_utf8_owned(xs), Ok("ศไทย中华Việt Nam".to_string()));
+ assert_eq!(from_utf8_owned(xs), Ok(String::from_str("ศไทย中华Việt Nam")));
let xs = Vec::from_slice(b"hello\xFF");
assert_eq!(from_utf8_owned(xs),
assert_eq!(from_utf8_lossy(xs), Slice("ศไทย中华Việt Nam"));
let xs = b"Hello\xC2 There\xFF Goodbye";
- assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD There\uFFFD Goodbye".to_string()));
+ assert_eq!(from_utf8_lossy(xs), Owned(String::from_str("Hello\uFFFD There\uFFFD Goodbye")));
let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
- assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD\uFFFD There\uFFFD Goodbye".to_string()));
+ assert_eq!(from_utf8_lossy(xs),
+ Owned(String::from_str("Hello\uFFFD\uFFFD There\uFFFD Goodbye")));
let xs = b"\xF5foo\xF5\x80bar";
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFD\uFFFDbar".to_string()));
+ assert_eq!(from_utf8_lossy(xs), Owned(String::from_str("\uFFFDfoo\uFFFD\uFFFDbar")));
let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFDbaz".to_string()));
+ assert_eq!(from_utf8_lossy(xs), Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFDbaz")));
let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz".to_string()));
+ assert_eq!(from_utf8_lossy(xs),
+ Owned(String::from_str("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz")));
let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFD\uFFFD\
- foo\U00010000bar".to_string()));
+ assert_eq!(from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFD\uFFFD\
+ foo\U00010000bar")));
// surrogates
let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
- assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFDfoo\
- \uFFFD\uFFFD\uFFFDbar".to_string()));
- }
-
- #[test]
- fn test_from_str() {
- let owned: Option<::std::string::String> = from_str("string");
- assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string"));
+ assert_eq!(from_utf8_lossy(xs), Owned(String::from_str("\uFFFD\uFFFD\uFFFDfoo\
+ \uFFFD\uFFFD\uFFFDbar")));
}
#[test]
let s = Slice("abcde");
assert_eq!(s.len(), 5);
assert_eq!(s.as_slice(), "abcde");
- assert_eq!(s.to_str().as_slice(), "abcde");
+ assert_eq!(String::from_str(s.as_slice()).as_slice(), "abcde");
assert_eq!(format!("{}", s).as_slice(), "abcde");
- assert!(s.lt(&Owned("bcdef".to_string())));
+ assert!(s.lt(&Owned(String::from_str("bcdef"))));
assert_eq!(Slice(""), Default::default());
- let o = Owned("abcde".to_string());
+ let o = Owned(String::from_str("abcde"));
assert_eq!(o.len(), 5);
assert_eq!(o.as_slice(), "abcde");
- assert_eq!(o.to_str().as_slice(), "abcde");
+ assert_eq!(String::from_str(o.as_slice()).as_slice(), "abcde");
assert_eq!(format!("{}", o).as_slice(), "abcde");
assert!(o.lt(&Slice("bcdef")));
- assert_eq!(Owned("".to_string()), Default::default());
+ assert_eq!(Owned(String::from_str("")), Default::default());
assert!(s.cmp(&o) == Equal);
assert!(s.equiv(&o));
assert!(s.is_slice());
assert!(!s.is_owned());
- let o = Owned("abcde".to_string());
+ let o = Owned(String::from_str("abcde"));
assert!(!o.is_slice());
assert!(o.is_owned());
}
#[test]
fn test_maybe_owned_clone() {
- assert_eq!(Owned("abcde".to_string()), Slice("abcde").clone());
- assert_eq!(Owned("abcde".to_string()), Owned("abcde".to_string()).clone());
+ assert_eq!(Owned(String::from_str("abcde")), Slice("abcde").clone());
+ assert_eq!(Owned(String::from_str("abcde")), Owned(String::from_str("abcde")).clone());
assert_eq!(Slice("abcde"), Slice("abcde").clone());
- assert_eq!(Slice("abcde"), Owned("abcde".to_string()).clone());
+ assert_eq!(Slice("abcde"), Owned(String::from_str("abcde")).clone());
}
#[test]
fn test_maybe_owned_into_string() {
- assert_eq!(Slice("abcde").into_string(), "abcde".to_string());
- assert_eq!(Owned("abcde".to_string()).into_string(), "abcde".to_string());
+ assert_eq!(Slice("abcde").into_string(), String::from_str("abcde"));
+ assert_eq!(Owned(String::from_str("abcde")).into_string(),
+ String::from_str("abcde"));
}
#[test]
fn test_into_maybe_owned() {
assert_eq!("abcde".into_maybe_owned(), Slice("abcde"));
- assert_eq!(("abcde".to_string()).into_maybe_owned(), Slice("abcde"));
- assert_eq!("abcde".into_maybe_owned(), Owned("abcde".to_string()));
- assert_eq!(("abcde".to_string()).into_maybe_owned(), Owned("abcde".to_string()));
+ assert_eq!((String::from_str("abcde")).into_maybe_owned(), Slice("abcde"));
+ assert_eq!("abcde".into_maybe_owned(), Owned(String::from_str("abcde")));
+ assert_eq!((String::from_str("abcde")).into_maybe_owned(),
+ Owned(String::from_str("abcde")));
}
}
mod bench {
use test::Bencher;
use super::*;
- use std::prelude::*;
+ use vec::Vec;
+ use std::iter::{Iterator, DoubleEndedIterator};
+ use std::collections::Collection;
+ use std::slice::Vector;
#[bench]
fn char_iterator(b: &mut Bencher) {
/// Appends a byte to this string buffer. The caller must preserve the valid UTF-8 property.
#[inline]
pub unsafe fn push_byte(&mut self, byte: u8) {
- self.push_bytes([byte])
+ self.vec.push(byte)
}
/// Removes the last byte from the string buffer and returns it. Returns `None` if this string
impl<S: Str> Add<S, String> for String {
fn add(&self, other: &S) -> String {
- let mut s = self.to_string();
+ let mut s = String::from_str(self.as_slice());
s.push_str(other.as_slice());
return s;
}
use str::{Str, StrSlice};
use super::String;
+ #[test]
+ fn test_from_str() {
+ let owned: Option<::std::string::String> = from_str("string");
+ assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string"));
+ }
+
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| {
use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
use slice::{Items, MutItems};
+
+#[doc(hidden)]
+pub static PTR_MARKER: u8 = 0;
+
/// An owned, growable vector.
///
/// # Examples
/// ```
#[inline]
pub fn new() -> Vec<T> {
- Vec { len: 0, cap: 0, ptr: 0 as *mut T }
+ // We want ptr to never be NULL so instead we set it to some arbitrary
+ // non-null value which is fine since we never call deallocate on the ptr
+ // if cap is 0. The reason for this is because the pointer of a slice
+ // being NULL would break the null pointer optimization for enums.
+ Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T }
}
/// Constructs a new, empty `Vec` with the specified capacity.
#[inline]
pub fn with_capacity(capacity: uint) -> Vec<T> {
if mem::size_of::<T>() == 0 {
- Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
+ Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T }
} else if capacity == 0 {
Vec::new()
} else {
/// would also make any pointers to it invalid.
#[inline]
pub fn as_ptr(&self) -> *const T {
- // If we have a 0-sized vector, then the base pointer should not be NULL
- // because an iterator over the slice will attempt to yield the base
- // pointer as the first element in the vector, but this will end up
- // being Some(NULL) which is optimized to None.
- if mem::size_of::<T>() == 0 {
- 1 as *const T
- } else {
- self.ptr as *const T
- }
+ self.ptr as *const T
}
/// Returns a mutable unsafe pointer to the vector's buffer.
/// would also make any pointers to it invalid.
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
- // see above for the 0-size check
- if mem::size_of::<T>() == 0 {
- 1 as *mut T
- } else {
- self.ptr
- }
+ self.ptr
}
/// Retains only the elements specified by the predicate.
//! ```
use option::{Option, Some};
-#[cfg(stage0)]
-use option::None;
/// Trait for values that can be compared for equality and inequality.
///
pub trait PartialOrd: PartialEq {
/// This method returns an ordering between `self` and `other` values
/// if one exists.
- #[cfg(stage0)]
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- match (!self.lt(other), !other.lt(self)) {
- (false, false) => None,
- (false, true) => Some(Less),
- (true, false) => Some(Greater),
- (true, true) => Some(Equal),
- }
- }
-
- /// This method returns an ordering between `self` and `other` values
- /// if one exists.
- #[cfg(not(stage0))]
fn partial_cmp(&self, other: &Self) -> Option<Ordering>;
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
/**
* Converts a number to its string representation as a byte vector.
* This is meant to be a common base implementation for all numeric string
- * conversion functions like `to_str()` or `to_str_radix()`.
+ * conversion functions like `to_string()` or `to_str_radix()`.
*
* # Arguments
* - `num` - The number to convert. Accepts any number that
// separate crate, libcoretest, to avoid bizarre issues.
#![crate_id = "core#0.11.0"]
+#![crate_name = "core"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![feature(globs, intrinsics, lang_items, macro_rules, managed_boxes, phase)]
#![feature(simd, unsafe_destructor)]
#![deny(missing_doc)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
mod macros;
/**
*
* The `Index` trait is used to specify the functionality of indexing operations
- * like `arr[idx]`.
+ * like `arr[idx]` when used in an immutable context.
*
* # Example
*
* struct Foo;
*
* impl Index<Foo, Foo> for Foo {
- * fn index(&self, _rhs: &Foo) -> Foo {
+ * fn index<'a>(&'a self, _rhs: &Foo) -> &'a Foo {
* println!("Indexing!");
- * *self
+ * self
* }
* }
*
* ```
*/
#[lang="index"]
+#[cfg(not(stage0))]
pub trait Index<Index,Result> {
/// The method for the indexing (`Foo[Bar]`) operation
- fn index(&self, index: &Index) -> Result;
+ fn index<'a>(&'a self, index: &Index) -> &'a Result;
+}
+
+/**
+ *
+ * The `IndexMut` trait is used to specify the functionality of indexing
+ * operations like `arr[idx]`, when used in a mutable context.
+ *
+ * # Example
+ *
+ * A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
+ * calling `index`, and therefore, `main` prints `Indexing!`.
+ *
+ * ```
+ * struct Foo;
+ *
+ * impl IndexMut<Foo, Foo> for Foo {
+ * fn index_mut<'a>(&'a mut self, _rhs: &Foo) -> &'a mut Foo {
+ * println!("Indexing!");
+ * self
+ * }
+ * }
+ *
+ * fn main() {
+ * &mut Foo[Foo];
+ * }
+ * ```
+ */
+#[lang="index_mut"]
+#[cfg(not(stage0))]
+pub trait IndexMut<Index,Result> {
+ /// The method for the indexing (`Foo[Bar]`) operation
+ fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
}
/**
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop, Deref, DerefMut};
-pub use ops::{Shl, Shr, Index};
+pub use ops::{Shl, Shr};
+#[cfg(not(stage0))]
+pub use ops::{Index, IndexMut};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};
//! Error handling with the `Result` type
//!
-//! `Result<T>` is the type used for returning and propagating
+//! `Result<T, E>` is the type used for returning and propagating
//! errors. It is an enum with the variants, `Ok(T)`, representing
//! success and containing a value, and `Err(E)`, representing error
//! and containing an error value.
if self.ptr == self.end {
None
} else {
- let old = self.ptr;
- self.ptr = if mem::size_of::<T>() == 0 {
+ if mem::size_of::<T>() == 0 {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
- transmute(self.ptr as uint + 1)
+ self.ptr = transmute(self.ptr as uint + 1);
+
+ // Use a non-null pointer value
+ Some(transmute(1u))
} else {
- self.ptr.offset(1)
- };
+ let old = self.ptr;
+ self.ptr = self.ptr.offset(1);
- Some(transmute(old))
+ Some(transmute(old))
+ }
}
}
}
if self.end == self.ptr {
None
} else {
- self.end = if mem::size_of::<T>() == 0 {
+ if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
- transmute(self.end as uint - 1)
+ self.end = transmute(self.end as uint - 1);
+
+ // Use a non-null pointer value
+ Some(transmute(1u))
} else {
- self.end.offset(-1)
- };
- Some(transmute(self.end))
+ self.end = self.end.offset(-1);
+
+ Some(transmute(self.end))
+ }
}
}
}
fn idx(&mut self, index: uint) -> Option<&'a T> {
unsafe {
if index < self.indexable() {
- transmute(self.ptr.offset(index as int))
+ if mem::size_of::<T>() == 0 {
+ // Use a non-null pointer value
+ Some(transmute(1u))
+ } else {
+ Some(transmute(self.ptr.offset(index as int)))
+ }
} else {
None
}
assert_eq!(s.as_slice(), "\\U0001d4b6");
}
-#[test]
-fn test_to_str() {
- let s = 't'.to_str();
- assert_eq!(s.as_slice(), "t");
-}
-
#[test]
fn test_encode_utf8() {
fn check(input: char, expect: &[u8]) {
// If we have a specified width for formatting, then we have to make
// this allocation of a new string
_ => {
- let s = repr::repr_to_str(self);
+ let s = repr::repr_to_string(self);
f.pad(s.as_slice())
}
}
//! Additionally, it is not guaranteed that functionality such as reflection
//! will persist into the future.
-#![crate_id = "debug#0.11.0"]
+#![crate_id = "debug#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "debug"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![experimental]
#![feature(managed_boxes, macro_rules)]
#![allow(experimental)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
pub mod fmt;
pub mod reflect;
macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty {
fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> {
- let s = self.to_str();
+ let s = self.to_string();
writer.write(s.as_bytes()).and_then(|()| {
writer.write($suffix)
})
}
}
-pub fn repr_to_str<T>(t: &T) -> String {
+pub fn repr_to_string<T>(t: &T) -> String {
let mut result = io::MemWriter::new();
write_repr(&mut result as &mut io::Writer, t).unwrap();
String::from_utf8(result.unwrap()).unwrap()
*/
-#![crate_id = "flate#0.11.0"]
+#![crate_id = "flate#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "flate"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(phase)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] #[phase(plugin, link)] extern crate log;
//! Parsing does not happen at runtime: structures of `std::fmt::rt` are
//! generated instead.
-#![crate_id = "fmt_macros#0.11.0"]
+#![crate_id = "fmt_macros#0.11.0"] // NOTE: remove after stage0c
+#![crate_name = "fmt_macros"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(macro_rules, globs)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::char;
use std::str;
*/
-#![crate_id = "fourcc#0.11.0"]
+#![crate_id = "fourcc#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "fourcc"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(plugin_registrar, managed_boxes)]
//! ];
//! let matches = match getopts(args.tail(), opts) {
//! Ok(m) => { m }
-//! Err(f) => { fail!(f.to_str()) }
+//! Err(f) => { fail!(f.to_string()) }
//! };
//! if matches.opt_present("h") {
//! print_usage(program.as_slice(), opts);
//! }
//! ~~~
-#![crate_id = "getopts#0.11.0"]
+#![crate_id = "getopts#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "getopts"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_playground_url = "http://play.rust-lang.org/")]
#![feature(globs, phase)]
#![deny(missing_doc)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate debug;
#[cfg(test)] #[phase(plugin, link)] extern crate log;
}
}
- fn to_str(&self) -> String {
+ fn to_string(&self) -> String {
match *self {
- Short(ch) => ch.to_str(),
+ Short(ch) => ch.to_string(),
Long(ref s) => s.to_string()
}
}
/// Convert a `Fail_` enum into an error string.
#[deprecated="use `Show` (`{}` format specifier)"]
pub fn to_err_msg(self) -> String {
- self.to_str()
+ self.to_string()
}
}
name_pos += 1;
let optid = match find_opt(opts.as_slice(), (*nm).clone()) {
Some(id) => id,
- None => return Err(UnrecognizedOption(nm.to_str()))
+ None => return Err(UnrecognizedOption(nm.to_string()))
};
match opts.get(optid).hasarg {
No => {
if !i_arg.is_none() {
- return Err(UnexpectedArgument(nm.to_str()));
+ return Err(UnexpectedArgument(nm.to_string()));
}
vals.get_mut(optid).push(Given);
}
if !i_arg.is_none() {
vals.get_mut(optid).push(Val(i_arg.clone().unwrap()));
} else if i + 1 == l {
- return Err(ArgumentMissing(nm.to_str()));
+ return Err(ArgumentMissing(nm.to_string()));
} else {
i += 1;
vals.get_mut(optid).push(Val(args[i].clone()));
let occ = opts.get(i).occur;
if occ == Req {
if n == 0 {
- return Err(OptionMissing(opts.get(i).name.to_str()));
+ return Err(OptionMissing(opts.get(i).name.to_string()));
}
}
if occ != Multi {
if n > 1 {
- return Err(OptionDuplicated(opts.get(i).name.to_str()));
+ return Err(OptionDuplicated(opts.get(i).name.to_string()));
}
}
i += 1;
* `glob`/`fnmatch` functions.
*/
-#![crate_id = "glob#0.11.0"]
+#![crate_id = "glob#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "glob"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::cell::Cell;
use std::{cmp, os, path};
for &p in pats.iter() {
let pat = Pattern::new(p);
for c in "abcdefghijklmnopqrstuvwxyz".chars() {
- assert!(pat.matches(c.to_str().as_slice()));
+ assert!(pat.matches(c.to_string().as_slice()));
}
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars() {
let options = MatchOptions {case_sensitive: false, .. MatchOptions::new()};
- assert!(pat.matches_with(c.to_str().as_slice(), options));
+ assert!(pat.matches_with(c.to_string().as_slice(), options));
}
assert!(pat.matches("1"));
assert!(pat.matches("2"));
*/
-#![crate_id = "graphviz#0.11.0"]
+#![crate_id = "graphviz#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "graphviz"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
-
-#![experimental]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::io;
use std::str;
let mut writer = MemWriter::new();
render(&g, &mut writer).unwrap();
let mut r = BufReader::new(writer.get_ref());
- match r.read_to_str() {
+ match r.read_to_string() {
Ok(string) => Ok(string.to_string()),
Err(err) => Err(err),
}
render(&g, &mut writer).unwrap();
let mut r = BufReader::new(writer.get_ref());
- let r = r.read_to_str();
+ let r = r.read_to_string();
assert_eq!(r.unwrap().as_slice(),
r#"digraph syntax_tree {
//! pool.shutdown();
//! ```
-#![crate_id = "green#0.11.0"]
+#![crate_id = "green#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "green"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
html_playground_url = "http://play.rust-lang.org/")]
// NB this does *not* include globs, please keep it that way.
-#![feature(macro_rules, phase)]
-#![allow(visible_private_types)]
-#![allow(deprecated)]
-#![feature(default_type_params)]
+#![feature(macro_rules, phase, default_type_params)]
+#![allow(visible_private_types, deprecated)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] #[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
*/
-#![crate_id = "hexfloat#0.11.0"]
+#![crate_id = "hexfloat#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "hexfloat"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(plugin_registrar, managed_boxes)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate syntax;
extern crate rustc;
// except according to those terms.
#![feature(globs)]
-#![crate_id = "libc#0.11.0"]
+#![crate_id = "libc#0.11.0"] // NOTE: remove after a stage0 snap
+#![crate_name = "libc"]
#![experimental]
#![no_std] // we don't need std, and we can't have std, since it doesn't exist
// yet. std depends on us.
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
/*!
* Bindings for the C standard library and other platform libraries
*/
-#![crate_id = "log#0.11.0"]
+#![crate_id = "log#0.11.0"] // NOTE: Remove after stage0
+#![crate_name = "log"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
-
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(macro_rules)]
#![deny(missing_doc)]
None => Err(IoError {
code: libc::ERROR_INVALID_NAME as uint,
extra: 0,
- detail: Some("valid unicode input required".to_str()),
+ detail: Some("valid unicode input required".to_string()),
})
}
}
return Err(IoError {
code: ERROR as uint,
extra: 0,
- detail: Some("path must be smaller than SUN_LEN".to_str()),
+ detail: Some("path must be smaller than SUN_LEN".to_string()),
})
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
Err(IoError {
code: libc::ERROR_OPERATION_ABORTED as uint,
extra: amt,
- detail: Some("short write during write".to_str()),
+ detail: Some("short write during write".to_string()),
})
} else {
Err(util::timeout("write timed out"))
Some(..) => return Err(IoError {
code: ERROR as uint,
extra: 0,
- detail: Some("can't kill an exited process".to_str()),
+ detail: Some("can't kill an exited process".to_string()),
}),
None => {}
}
return Err(IoError {
code: libc::ERROR_CALL_NOT_IMPLEMENTED as uint,
extra: 0,
- detail: Some("unsupported gid/uid requested on windows".to_str()),
+ detail: Some("unsupported gid/uid requested on windows".to_string()),
})
}
IoError {
code: ERROR as uint,
extra: 0,
- detail: Some(desc.to_str()),
+ detail: Some(desc.to_string()),
}
}
IoError {
code: ERROR as uint,
extra: n,
- detail: Some(desc.to_str()),
+ detail: Some(desc.to_string()),
}
}
//! }
//! ```
-#![crate_id = "native#0.11.0"]
+#![crate_id = "native#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "native"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![deny(unused_result, unused_must_use)]
#![allow(non_camel_case_types, deprecated)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(default_type_params, lang_items)]
// NB this crate explicitly does *not* allow glob imports, please seriously
// attempt to allocate a vector of size (-1u) == huge.
let x: BigInt =
from_str(format!("1{}", "0".repeat(36)).as_slice()).unwrap();
- let _y = x.to_str();
+ let _y = x.to_string();
}
#[test]
}
#[bench]
- fn to_str(b: &mut Bencher) {
+ fn to_string(b: &mut Bencher) {
let fac = factorial(100);
let fib = fib(100);
b.iter(|| {
- fac.to_str();
+ fac.to_string();
});
b.iter(|| {
- fib.to_str();
+ fib.to_string();
});
}
}
#[test]
- fn test_to_str() {
+ fn test_to_string() {
fn test(c : Complex64, s: String) {
- assert_eq!(c.to_str(), s);
+ assert_eq!(c.to_string(), s);
}
test(_0_0i, "0+0i".to_string());
test(_1_0i, "1+0i".to_string());
#![feature(macro_rules)]
-#![crate_id = "num#0.11.0"]
+#![crate_id = "num#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "num"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
-
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![allow(deprecated)] // from_str_radix
extern crate rand;
use std::cmp;
use std::fmt;
use std::from_str::FromStr;
+use std::num;
use std::num::{Zero, One, ToStrRadix, FromStrRadix};
+
use bigint::{BigInt, BigUint, Sign, Plus, Minus};
/// Represents the ratio between 2 numbers.
impl<T: Clone + Integer + PartialOrd>
Num for Ratio<T> {}
+impl<T: Clone + Integer + PartialOrd>
+ num::Signed for Ratio<T> {
+ #[inline]
+ fn abs(&self) -> Ratio<T> {
+ if self.is_negative() { -self.clone() } else { self.clone() }
+ }
+
+ #[inline]
+ fn abs_sub(&self, other: &Ratio<T>) -> Ratio<T> {
+ if *self <= *other { Zero::zero() } else { *self - *other }
+ }
+
+ #[inline]
+ fn signum(&self) -> Ratio<T> {
+ if *self > Zero::zero() {
+ num::one()
+ } else if self.is_zero() {
+ num::zero()
+ } else {
+ - num::one::<Ratio<T>>()
+ }
+ }
+
+ #[inline]
+ fn is_positive(&self) -> bool { *self > Zero::zero() }
+
+ #[inline]
+ fn is_negative(&self) -> bool { *self < Zero::zero() }
+}
+
/* String conversions */
impl<T: fmt::Show + Eq + One> fmt::Show for Ratio<T> {
/// Renders as `numer/denom`. If denom=1, renders as numer.
use super::{Ratio, Rational, BigRational};
use std::num::{Zero, One, FromStrRadix, FromPrimitive, ToStrRadix};
use std::from_str::FromStr;
+ use std::num;
pub static _0 : Rational = Ratio { numer: 0, denom: 1};
pub static _1 : Rational = Ratio { numer: 1, denom: 1};
fn test_to_from_str() {
fn test(r: Rational, s: String) {
assert_eq!(FromStr::from_str(s.as_slice()), Some(r));
- assert_eq!(r.to_str(), s);
+ assert_eq!(r.to_string(), s);
}
test(_1, "1".to_string());
test(_0, "0".to_string());
assert_eq!(Ratio::from_float(f64::INFINITY), None);
assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
}
+
+ #[test]
+ fn test_signed() {
+ assert_eq!(_neg1_2.abs(), _1_2);
+ assert_eq!(_3_2.abs_sub(&_1_2), _1);
+ assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero());
+ assert_eq!(_1_2.signum(), One::one());
+ assert_eq!(_neg1_2.signum(), - num::one::<Ratio<int>>());
+ assert!(_neg1_2.is_negative());
+ assert!(! _neg1_2.is_positive());
+ assert!(! _1_2.is_negative());
+ }
}
//! is not recommended to use this library directly, but rather the official
//! interface through `std::rand`.
-#![crate_id = "rand#0.11.0"]
+#![crate_id = "rand#0.11.0"] // NOTE: remove after a stage0 snap
+#![crate_name = "rand"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, phase, globs)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![no_std]
#![experimental]
//! characters in the search text and `m` is the number of instructions in a
//! compiled expression.
-#![crate_id = "regex#0.11.0"]
+#![crate_id = "regex#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "regex"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![experimental]
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, phase)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![deny(missing_doc)]
#[cfg(test)]
//! This crate provides the `regex!` macro. Its use is documented in the
//! `regex` crate.
-#![crate_id = "regex_macros#0.11.0"]
+#![crate_id = "regex_macros#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "regex_macros"]
#![crate_type = "dylib"]
#![experimental]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(plugin_registrar, managed_boxes, quote)]
let re = match Regex::new(regex.as_slice()) {
Ok(re) => re,
Err(err) => {
- cx.span_err(sp, err.to_str().as_slice());
+ cx.span_err(sp, err.to_string().as_slice());
return DummyResult::any(sp)
}
};
#[inline]
fn groups<'r>(&'r mut self, i: uint) -> &'r mut Captures {
- &'r mut self.queue[i].groups
+ &mut self.queue[i].groups
}
}
}
let regex = match entry.node {
ast::ExprLit(lit) => {
match lit.node {
- ast::LitStr(ref s, _) => s.to_str(),
+ ast::LitStr(ref s, _) => s.to_string(),
_ => {
cx.span_err(entry.span, format!(
"expected string literal but got `{}`",
- pprust::lit_to_str(lit)).as_slice());
+ pprust::lit_to_string(lit)).as_slice());
return None
}
}
_ => {
cx.span_err(entry.span, format!(
"expected string literal but got `{}`",
- pprust::expr_to_str(entry)).as_slice());
+ pprust::expr_to_string(entry)).as_slice());
return None
}
};
//! necessary. It is an error to include this library when also linking with
//! the system libc library.
-#![crate_id = "rlibc#0.11.0"]
+#![crate_id = "rlibc#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "rlibc"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(intrinsics)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![no_std]
#![experimental]
use back::archive::{Archive, METADATA_FILENAME};
use back::rpath;
use back::svh::Svh;
-use driver::driver::{CrateTranslation, OutputFilenames};
+use driver::driver::{CrateTranslation, OutputFilenames, Input, FileInput};
use driver::config::NoDebugInfo;
use driver::session::Session;
use driver::config;
use lib::llvm::ModuleRef;
use lib;
use metadata::common::LinkMeta;
-use metadata::{encoder, cstore, filesearch, csearch, loader};
+use metadata::{encoder, cstore, filesearch, csearch, loader, creader};
use middle::trans::context::CrateContext;
use middle::trans::common::gensym_name;
use middle::ty;
use syntax::ast;
use syntax::ast_map::{PathElem, PathElems, PathName};
use syntax::ast_map;
-use syntax::attr;
use syntax::attr::AttrMetaMethods;
-use syntax::crateid::CrateId;
+use syntax::codemap::Span;
use syntax::parse::token;
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
* system linkers understand.
*/
-// FIXME (#9639): This needs to handle non-utf8 `out_filestem` values
-pub fn find_crate_id(attrs: &[ast::Attribute], out_filestem: &str) -> CrateId {
- match attr::find_crateid(attrs) {
- None => from_str(out_filestem).unwrap_or_else(|| {
- let mut s = out_filestem.chars().filter(|c| c.is_XID_continue());
- from_str(s.collect::<String>().as_slice())
- .or(from_str("rust-out")).unwrap()
- }),
- Some(s) => s,
+pub fn find_crate_name(sess: Option<&Session>,
+ attrs: &[ast::Attribute],
+ input: &Input) -> String {
+ use syntax::crateid::CrateId;
+
+ let validate = |s: String, span: Option<Span>| {
+ creader::validate_crate_name(sess, s.as_slice(), span);
+ s
+ };
+
+ match sess {
+ Some(sess) => {
+ match sess.opts.crate_name {
+ Some(ref s) => return validate(s.clone(), None),
+ None => {}
+ }
+ }
+ None => {}
+ }
+
+ let crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
+ .and_then(|at| at.value_str().map(|s| (at, s)));
+ match crate_name {
+ Some((attr, s)) => return validate(s.get().to_string(), Some(attr.span)),
+ None => {}
+ }
+ let crate_id = attrs.iter().find(|at| at.check_name("crate_id"))
+ .and_then(|at| at.value_str().map(|s| (at, s)))
+ .and_then(|(at, s)| {
+ from_str::<CrateId>(s.get()).map(|id| (at, id))
+ });
+ match crate_id {
+ Some((attr, id)) => {
+ match sess {
+ Some(sess) => {
+ sess.span_warn(attr.span, "the #[crate_id] attribute is \
+ deprecated for the \
+ #[crate_name] attribute");
+ }
+ None => {}
+ }
+ return validate(id.name, Some(attr.span))
+ }
+ None => {}
+ }
+ match *input {
+ FileInput(ref path) => {
+ match path.filestem_str() {
+ Some(s) => return validate(s.to_string(), None),
+ None => {}
+ }
+ }
+ _ => {}
}
-}
-pub fn crate_id_hash(crate_id: &CrateId) -> String {
- // This calculates CMH as defined above. Note that we don't use the path of
- // the crate id in the hash because lookups are only done by (name/vers),
- // not by path.
- let mut s = Sha256::new();
- s.input_str(crate_id.short_name_with_version().as_slice());
- truncated_hash_result(&mut s).as_slice().slice_to(8).to_string()
+ "rust-out".to_string()
}
-// FIXME (#9639): This needs to handle non-utf8 `out_filestem` values
-pub fn build_link_meta(krate: &ast::Crate, out_filestem: &str) -> LinkMeta {
+pub fn build_link_meta(sess: &Session, krate: &ast::Crate,
+ name: String) -> LinkMeta {
let r = LinkMeta {
- crateid: find_crate_id(krate.attrs.as_slice(), out_filestem),
- crate_hash: Svh::calculate(krate),
+ crate_name: name,
+ crate_hash: Svh::calculate(sess, krate),
};
info!("{}", r);
return r;
// to be independent of one another in the crate.
symbol_hasher.reset();
- symbol_hasher.input_str(link_meta.crateid.name.as_slice());
+ symbol_hasher.input_str(link_meta.crate_name.as_slice());
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
+ for meta in tcx.sess.crate_metadata.borrow().iter() {
+ symbol_hasher.input_str(meta.as_slice());
+ }
symbol_hasher.input_str("-");
symbol_hasher.input_str(encoder::encoded_ty(tcx, t).as_slice());
// Prefix with 'h' so that it never blends into adjacent digits
}
pub fn mangle<PI: Iterator<PathElem>>(mut path: PI,
- hash: Option<&str>,
- vers: Option<&str>) -> String {
+ hash: Option<&str>) -> String {
// Follow C++ namespace-mangling style, see
// http://en.wikipedia.org/wiki/Name_mangling for more info.
//
Some(s) => push(&mut n, s),
None => {}
}
- match vers {
- Some(s) => push(&mut n, s),
- None => {}
- }
n.push_char('E'); // End name-sequence.
n
}
-pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> String {
- // The version will get mangled to have a leading '_', but it makes more
- // sense to lead with a 'v' b/c this is a version...
- let vers = if vers.len() > 0 && !char::is_XID_start(vers.char_at(0)) {
- format!("v{}", vers)
- } else {
- vers.to_string()
- };
-
- mangle(path, Some(hash), Some(vers.as_slice()))
+pub fn exported_name(path: PathElems, hash: &str) -> String {
+ mangle(path, Some(hash))
}
pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
hash.push_char(EXTRA_CHARS.as_bytes()[extra2] as char);
hash.push_char(EXTRA_CHARS.as_bytes()[extra3] as char);
- exported_name(path,
- hash.as_slice(),
- ccx.link_meta.crateid.version_or_default())
+ exported_name(path, hash.as_slice())
}
pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
t: ty::t,
name: &str) -> String {
- let s = ppaux::ty_to_str(ccx.tcx(), t);
+ let s = ppaux::ty_to_string(ccx.tcx(), t);
let path = [PathName(token::intern(s.as_slice())),
gensym_name(name)];
let hash = get_symbol_hash(ccx, t);
- mangle(ast_map::Values(path.iter()), Some(hash.as_slice()), None)
+ mangle(ast_map::Values(path.iter()), Some(hash.as_slice()))
}
pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> String {
- mangle(path.chain(Some(gensym_name(flav)).move_iter()), None, None)
-}
-
-pub fn output_lib_filename(id: &CrateId) -> String {
- format!("{}-{}-{}", id.name, crate_id_hash(id), id.version_or_default())
+ mangle(path.chain(Some(gensym_name(flav)).move_iter()), None)
}
pub fn get_cc_prog(sess: &Session) -> String {
pub fn link_binary(sess: &Session,
trans: &CrateTranslation,
outputs: &OutputFilenames,
- id: &CrateId) -> Vec<Path> {
+ crate_name: &str) -> Vec<Path> {
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
if invalid_output_for_target(sess, crate_type) {
sess.bug(format!("invalid output type `{}` for target os `{}`",
crate_type, sess.targ_cfg.os).as_slice());
}
- let out_file = link_binary_output(sess, trans, crate_type, outputs, id);
+ let out_file = link_binary_output(sess, trans, crate_type, outputs,
+ crate_name);
out_filenames.push(out_file);
}
}
}
-pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
- id: &CrateId, out_filename: &Path) -> Path {
- let libname = output_lib_filename(id);
+pub fn filename_for_input(sess: &Session,
+ crate_type: config::CrateType,
+ name: &str,
+ out_filename: &Path) -> Path {
+ let libname = format!("{}{}", name, sess.opts.cg.extra_filename);
match crate_type {
config::CrateTypeRlib => {
out_filename.with_filename(format!("lib{}.rlib", libname))
trans: &CrateTranslation,
crate_type: config::CrateType,
outputs: &OutputFilenames,
- id: &CrateId) -> Path {
+ crate_name: &str) -> Path {
let obj_filename = outputs.temp_path(OutputTypeObject);
let out_filename = match outputs.single_output_file {
Some(ref file) => file.clone(),
None => {
let out_filename = outputs.path(OutputTypeExe);
- filename_for_input(sess, crate_type, id, &out_filename)
+ filename_for_input(sess, crate_type, crate_name, &out_filename)
}
};
if sess.targ_cfg.os == abi::OsMacos {
cmd.args(["-dynamiclib", "-Wl,-dylib"]);
- if !sess.opts.cg.no_rpath {
+ if sess.opts.cg.rpath {
let mut v = Vec::from_slice("-Wl,-install_name,@rpath/".as_bytes());
v.push_all(out_filename.filename().unwrap());
cmd.arg(v.as_slice());
// FIXME (#2397): At some point we want to rpath our guesses as to
// where extern libraries might live, based on the
// addl_lib_search_paths
- if !sess.opts.cg.no_rpath {
+ if sess.opts.cg.rpath {
cmd.args(rpath::get_rpath_flags(sess, out_filename).as_slice());
}
use syntax::ast;
use syntax::visit;
+use driver::session::Session;
+
#[deriving(Clone, PartialEq)]
pub struct Svh {
hash: String,
self.hash.as_slice()
}
- pub fn calculate(krate: &ast::Crate) -> Svh {
+ pub fn calculate(sess: &Session, krate: &ast::Crate) -> Svh {
// FIXME (#14132): This is better than it used to be, but it still not
// ideal. We now attempt to hash only the relevant portions of the
// Crate AST as well as the top-level crate attributes. (However,
// avoid collisions.
let mut state = SipState::new();
+ for data in sess.opts.cg.metadata.iter() {
+ data.hash(&mut state);
+ }
+
{
let mut visit = svh_visitor::make(&mut state);
visit::walk_crate(&mut visit, krate, ());
// trees might be faster. Implementing this is far
// easier in short term.
let macro_defn_as_string =
- pprust::to_str(|pp_state| pp_state.print_mac(macro));
+ pprust::to_string(|pp_state| pp_state.print_mac(macro));
macro_defn_as_string.hash(self.st);
} else {
// It is not possible to observe any kind of macro
// invocation at this stage except `macro_rules!`.
fail!("reached macro somehow: {}",
- pprust::to_str(|pp_state| pp_state.print_mac(macro)));
+ pprust::to_string(|pp_state| pp_state.print_mac(macro)));
}
visit::walk_mac(self, macro, e);
//! Contains infrastructure for configuring the compiler, including parsing
//! command line options.
-use driver::early_error;
+use driver::{early_error, early_warn};
use driver::driver;
use driver::session::Session;
use syntax::parse;
use syntax::parse::token::InternedString;
-use std::collections::HashSet;
+use std::collections::{HashSet, HashMap};
use getopts::{optopt, optmulti, optflag, optflagopt};
use getopts;
use lib::llvm::llvm;
pub debugging_opts: u64,
/// Whether to write dependency files. It's (enabled, optional filename).
pub write_dependency_info: (bool, Option<Path>),
- /// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
- pub print_metas: (bool, bool, bool),
+ /// Crate id-related things to maybe print. It's (crate_name, crate_file_name).
+ pub print_metas: (bool, bool),
pub cg: CodegenOptions,
pub color: ColorConfig,
+ pub externs: HashMap<String, Vec<String>>,
+ pub crate_name: Option<String>,
}
/// Some reasonable defaults
no_analysis: false,
debugging_opts: 0,
write_dependency_info: (false, None),
- print_metas: (false, false, false),
+ print_metas: (false, false),
cg: basic_codegen_options(),
color: Auto,
+ externs: HashMap::new(),
+ crate_name: None,
}
}
"a list of arguments to pass to llvm (space separated)"),
save_temps: bool = (false, parse_bool,
"save all temporary output files during compilation"),
- no_rpath: bool = (false, parse_bool,
- "disables setting the rpath in libs/exes"),
+ rpath: bool = (false, parse_bool,
+ "set rpath values in libs/exes"),
no_prepopulate_passes: bool = (false, parse_bool,
"don't pre-populate the pass manager with a list of passes"),
no_vectorize_loops: bool = (false, parse_bool,
"use an external assembler rather than LLVM's integrated one"),
relocation_model: String = ("pic".to_string(), parse_string,
"choose the relocation model to use (llc -relocation-model for details)"),
+ metadata: Vec<String> = (Vec::new(), parse_list,
+ "metadata to mangle symbol names with"),
+ extra_filename: String = ("".to_string(), parse_string,
+ "extra data to put in each output filename"),
)
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
}
None
}
-static os_names : &'static [(&'static str, abi::Os)] = &'static [
+static os_names : &'static [(&'static str, abi::Os)] = &[
("mingw32", abi::OsWin32),
("win32", abi::OsWin32),
("darwin", abi::OsMacos),
}
None
}
-static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
+static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
("i386", abi::X86),
("i486", abi::X86),
("i586", abi::X86),
"[bin|lib|rlib|dylib|staticlib]"),
optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
"[asm|bc|ir|obj|link]"),
- optflag("", "crate-id", "Output the crate id and exit"),
- optflag("", "crate-name", "Output the crate name and exit"),
- optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
+ optopt("", "crate-name", "Specify the name of the crate being built",
+ "NAME"),
+ optflag("", "print-crate-name", "Output the crate name and exit"),
+ optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
continued and exit"),
+ optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
optflag("g", "", "Equivalent to --debuginfo=2"),
optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
0 = no debug info,
optopt("", "color", "Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
- never = never colorize output", "auto|always|never")
+ never = never colorize output", "auto|always|never"),
+ optmulti("", "extern", "Specify where an external rust library is located",
+ "PATH"),
)
}
matches.opt_str("dep-info")
.map(|p| Path::new(p)));
- let print_metas = (matches.opt_present("crate-id"),
- matches.opt_present("crate-name"),
+ let print_metas = (matches.opt_present("print-crate-name"),
+ matches.opt_present("print-file-name") ||
matches.opt_present("crate-file-name"));
+ if matches.opt_present("crate-file-name") {
+ early_warn("the --crate-file-name argument has been renamed to \
+ --print-file-name");
+ }
let cg = build_codegen_options(matches);
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
}
};
+ let mut externs = HashMap::new();
+ for arg in matches.opt_strs("extern").iter() {
+ let mut parts = arg.as_slice().splitn('=', 1);
+ let name = match parts.next() {
+ Some(s) => s,
+ None => early_error("--extern value must not be empty"),
+ };
+ let location = match parts.next() {
+ Some(s) => s,
+ None => early_error("--extern value must be of the format `foo=bar`"),
+ };
+ let locs = externs.find_or_insert(name.to_string(), Vec::new());
+ locs.push(location.to_string());
+ }
+
+ let crate_name = matches.opt_str("crate-name");
+
Options {
crate_types: crate_types,
gc: gc,
write_dependency_info: write_dependency_info,
print_metas: print_metas,
cg: cg,
- color: color
+ color: color,
+ externs: externs,
+ crate_name: crate_name,
}
}
use syntax::ast;
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
-use syntax::crateid::CrateId;
use syntax::parse;
use syntax::parse::token;
use syntax::print::{pp, pprust};
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
let (outputs, trans, sess) = {
- let (outputs, expanded_crate, ast_map) = {
+ let (outputs, expanded_crate, ast_map, id) = {
let krate = phase_1_parse_input(&sess, cfg, input);
if stop_after_phase_1(&sess) { return; }
let outputs = build_output_filenames(input,
output,
krate.attrs.as_slice(),
&sess);
- let id = link::find_crate_id(krate.attrs.as_slice(),
- outputs.out_filestem.as_slice());
+ let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
+ input);
let (expanded_crate, ast_map)
- = match phase_2_configure_and_expand(&sess, krate, &id) {
+ = match phase_2_configure_and_expand(&sess, krate, id.as_slice()) {
None => return,
Some(p) => p,
};
- (outputs, expanded_crate, ast_map)
+ (outputs, expanded_crate, ast_map, id)
};
- write_out_deps(&sess, input, &outputs, &expanded_crate);
+ write_out_deps(&sess, input, &outputs, id.as_slice());
if stop_after_phase_2(&sess) { return; }
- let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
+ let analysis = phase_3_run_analysis_passes(sess, &expanded_crate,
+ ast_map, id);
phase_save_analysis(&analysis.ty_cx.sess, &expanded_crate, &analysis, outdir);
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
- let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
- analysis, &outputs);
+ let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate, analysis);
// Discard interned strings as they are no longer required.
token::get_ident_interner().clear();
/// Returns `None` if we're aborting after handling -W help.
pub fn phase_2_configure_and_expand(sess: &Session,
mut krate: ast::Crate,
- crate_id: &CrateId)
+ crate_name: &str)
-> Option<(ast::Crate, syntax::ast_map::Map)> {
let time_passes = sess.time_passes();
- *sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
+ *sess.crate_types.borrow_mut() =
+ collect_crate_types(sess, krate.attrs.as_slice());
+ *sess.crate_metadata.borrow_mut() =
+ collect_crate_metadata(sess, krate.attrs.as_slice());
time(time_passes, "gated feature checking", (), |_|
front::feature_gate::check_crate(sess, &krate));
}
let cfg = syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: sess.features.default_type_params.get(),
- crate_id: crate_id.clone(),
+ crate_name: crate_name.to_string(),
};
syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
pub public_items: middle::privacy::PublicItems,
pub ty_cx: ty::ctxt,
pub reachable: NodeSet,
+ pub name: String,
}
/// Run the resolution, typechecking, region checking and other
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes(sess: Session,
krate: &ast::Crate,
- ast_map: syntax::ast_map::Map) -> CrateAnalysis {
+ ast_map: syntax::ast_map::Map,
+ name: String) -> CrateAnalysis {
let time_passes = sess.time_passes();
exported_items: exported_items,
public_items: public_items,
reachable: reachable_map,
+ name: name,
}
}
/// Run the translation phase to LLVM, after which the AST and analysis can
/// be discarded.
pub fn phase_4_translate_to_llvm(krate: ast::Crate,
- analysis: CrateAnalysis,
- outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
+ analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
let time_passes = analysis.ty_cx.sess.time_passes();
time(time_passes, "resolving dependency formats", (), |_|
// Option dance to work around the lack of stack once closures.
time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
- trans::base::trans_crate(krate, analysis, outputs))
+ trans::base::trans_crate(krate, analysis))
}
/// Run LLVM itself, producing a bitcode file, assembly file or object file
link::link_binary(sess,
trans,
outputs,
- &trans.link.crateid));
+ trans.link.crate_name.as_slice()));
}
pub fn stop_after_phase_3(sess: &Session) -> bool {
fn write_out_deps(sess: &Session,
input: &Input,
outputs: &OutputFilenames,
- krate: &ast::Crate) {
- let id = link::find_crate_id(krate.attrs.as_slice(),
- outputs.out_filestem.as_slice());
+ id: &str) {
let mut out_filenames = Vec::new();
for output_type in sess.opts.output_types.iter() {
match *output_type {
link::OutputTypeExe => {
for output in sess.crate_types.borrow().iter() {
- let p = link::filename_for_input(sess, *output, &id, &file);
+ let p = link::filename_for_input(sess, *output,
+ id, &file);
out_filenames.push(p);
}
}
match node {
pprust::NodeItem(item) => {
try!(pp::space(&mut s.s));
- s.synth_comment(item.id.to_str())
+ s.synth_comment(item.id.to_string())
}
pprust::NodeBlock(blk) => {
try!(pp::space(&mut s.s));
}
pprust::NodeExpr(expr) => {
try!(pp::space(&mut s.s));
- try!(s.synth_comment(expr.id.to_str()));
+ try!(s.synth_comment(expr.id.to_string()));
s.pclose()
}
pprust::NodePat(pat) => {
try!(pp::word(&mut s.s, "as"));
try!(pp::space(&mut s.s));
try!(pp::word(&mut s.s,
- ppaux::ty_to_str(
+ ppaux::ty_to_string(
tcx,
ty::expr_ty(tcx, expr)).as_slice()));
s.pclose()
ppm: PpMode,
ofile: Option<Path>) {
let krate = phase_1_parse_input(&sess, cfg, input);
- let id = link::find_crate_id(krate.attrs.as_slice(),
- input.filestem().as_slice());
+ let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
let (krate, ast_map)
- = match phase_2_configure_and_expand(&sess, krate, &id) {
+ = match phase_2_configure_and_expand(&sess, krate,
+ id.as_slice()) {
None => return,
Some(p) => p,
};
}
PpmTyped => {
let ast_map = ast_map.expect("--pretty=typed missing ast_map");
- let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
+ let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map, id);
let annotation = TypedAnnotation {
analysis: analysis
};
}
}
};
- let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
+ let analysis = phase_3_run_analysis_passes(sess, &krate,
+ ast_map, id);
print_flowgraph(analysis, block, out)
}
_ => {
}).collect()
}
+pub fn collect_crate_metadata(session: &Session,
+ _attrs: &[ast::Attribute]) -> Vec<String> {
+ session.opts.cg.metadata.clone()
+}
+
pub struct OutputFilenames {
pub out_directory: Path,
pub out_filestem: String,
None => Path::new(".")
};
- let mut stem = input.filestem();
+ // If a crate name is present, we use it as the link name
+ let stem = sess.opts.crate_name.clone().or_else(|| {
+ attr::find_crate_name(attrs).map(|n| n.get().to_string())
+ }).or_else(|| {
+ // NB: this clause can be removed once #[crate_id] is no longer
+ // deprecated.
+ //
+ // Also note that this will be warned about later so we don't
+ // warn about it here.
+ use syntax::crateid::CrateId;
+ attrs.iter().find(|at| at.check_name("crate_id"))
+ .and_then(|at| at.value_str())
+ .and_then(|s| from_str::<CrateId>(s.get()))
+ .map(|id| id.name)
+ }).unwrap_or(input.filestem());
- // If a crateid is present, we use it as the link name
- let crateid = attr::find_crateid(attrs);
- match crateid {
- None => {}
- Some(crateid) => stem = crateid.name.to_string(),
- }
OutputFilenames {
out_directory: dirpath,
out_filestem: stem,
match getopts::getopts(args.as_slice(), config::optgroups().as_slice()) {
Ok(m) => m,
Err(f) => {
- early_error(f.to_str().as_slice());
+ early_error(f.to_string().as_slice());
}
};
odir: &Option<Path>,
ofile: &Option<Path>)
-> bool {
- let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
+ let (crate_name, crate_file_name) = sess.opts.print_metas;
// these nasty nested conditions are to avoid doing extra work
- if crate_id || crate_name || crate_file_name {
+ if crate_name || crate_file_name {
let attrs = parse_crate_attrs(sess, input);
let t_outputs = driver::build_output_filenames(input,
odir,
ofile,
attrs.as_slice(),
sess);
- let id = link::find_crate_id(attrs.as_slice(),
- t_outputs.out_filestem.as_slice());
+ let id = link::find_crate_name(Some(sess), attrs.as_slice(), input);
- if crate_id {
- println!("{}", id.to_str());
- }
if crate_name {
- println!("{}", id.name);
+ println!("{}", id);
}
if crate_file_name {
let crate_types = driver::collect_crate_types(sess, attrs.as_slice());
+ let metadata = driver::collect_crate_metadata(sess, attrs.as_slice());
+ *sess.crate_metadata.borrow_mut() = metadata;
for &style in crate_types.iter() {
- let fname = link::filename_for_input(sess, style, &id,
+ let fname = link::filename_for_input(sess, style, id.as_slice(),
&t_outputs.with_extension(""));
println!("{}", fname.filename_display());
}
fail!(diagnostic::FatalError);
}
+pub fn early_warn(msg: &str) {
+ let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
+ emitter.emit(None, msg, diagnostic::Warning);
+}
+
pub fn list_metadata(sess: &Session, path: &Path,
out: &mut io::Writer) -> io::IoResult<()> {
metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out)
emitter.emit(None, note.as_slice(), diagnostic::Note)
}
- match r.read_to_str() {
+ match r.read_to_string() {
Ok(s) => println!("{}", s),
Err(e) => {
emitter.emit(None,
pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
pub node_id: Cell<ast::NodeId>,
pub crate_types: RefCell<Vec<config::CrateType>>,
+ pub crate_metadata: RefCell<Vec<String>>,
pub features: front::feature_gate::Features,
/// The maximum recursion limit for potentially infinitely recursive
lints: RefCell::new(NodeMap::new()),
node_id: Cell::new(1),
crate_types: RefCell::new(Vec::new()),
+ crate_metadata: RefCell::new(Vec::new()),
features: front::feature_gate::Features::new(),
recursion_limit: Cell::new(64),
};
.map(|x| *x).collect();
ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
}
- ast::ItemTrait(ref a, b, ref c, ref methods) => {
+ ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
let methods = methods.iter()
.filter(|m| trait_method_in_cfg(cx, *m) )
.map(|x| (*x).clone())
.collect();
- ast::ItemTrait((*a).clone(), b, (*c).clone(), methods)
+ ast::ItemTrait((*a).clone(), (*b).clone(), (*c).clone(), methods)
}
ast::ItemStruct(ref def, ref generics) => {
ast::ItemStruct(fold_struct(cx, &**def), generics.clone())
use std::mem;
use std::gc::{Gc, GC};
-pub static VERSION: &'static str = "0.11.0";
-
pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
-> ast::Crate {
if use_std(&krate) {
sess: &'a Session,
}
-pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
- match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
- Some("1") => None,
- _ => {
- Some((token::intern_and_get_ident(format!("{}#{}",
- krate,
- VERSION).as_slice()),
- ast::CookedStr))
- }
- }
-}
-
impl<'a> fold::Folder for StandardLibraryInjector<'a> {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
let mut vis = vec!(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("std"),
- with_version("std"),
- ast::DUMMY_NODE_ID),
+ None,
+ ast::DUMMY_NODE_ID),
attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
InternedString::new("phase"),
if use_start(&krate) && any_exe {
vis.push(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("native"),
- with_version("native"),
- ast::DUMMY_NODE_ID),
+ None,
+ ast::DUMMY_NODE_ID),
attrs: Vec::new(),
vis: ast::Inherited,
span: DUMMY_SP
use driver::session::Session;
use front::config;
-use front::std_inject::with_version;
use std::cell::RefCell;
use std::gc::{Gc, GC};
ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
ExpansionConfig {
deriving_hash_type_parameter: false,
- crate_id: from_str("test").unwrap(),
+ crate_name: "test".to_string(),
}),
path: RefCell::new(Vec::new()),
testfns: RefCell::new(Vec::new()),
ast::DUMMY_NODE_ID))),
ast::Public)
} else {
- (ast::ViewItemExternCrate(id_test,
- with_version("test"),
- ast::DUMMY_NODE_ID),
+ (ast::ViewItemExternCrate(id_test, None, ast::DUMMY_NODE_ID),
ast::Inherited)
};
ast::ViewItem {
span: DUMMY_SP,
};
- debug!("Synthetic test module:\n{}\n", pprust::item_to_str(&item));
+ debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item));
box(GC) item
}
}
fn is_test_crate(krate: &ast::Crate) -> bool {
- match attr::find_crateid(krate.attrs.as_slice()) {
- Some(ref s) if "test" == s.name.as_slice() => true,
+ match attr::find_crate_name(krate.attrs.as_slice()) {
+ Some(ref s) if "test" == s.get().as_slice() => true,
_ => false
}
}
*/
-#![crate_id = "rustc#0.11.0"]
+#![crate_id = "rustc#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "rustc"]
#![experimental]
#![comment = "The Rust compiler"]
#![license = "MIT/ASL2"]
#![allow(deprecated)]
#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
#![feature(default_type_params, phase, unsafe_destructor)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate arena;
extern crate debug;
self.named_types.borrow().find_equiv(&s).map(|x| Type::from_ref(*x))
}
- pub fn type_to_str(&self, ty: Type) -> String {
+ pub fn type_to_string(&self, ty: Type) -> String {
unsafe {
let s = llvm::LLVMTypeToString(ty.to_ref());
let ret = from_c_str(s);
}
pub fn types_to_str(&self, tys: &[Type]) -> String {
- let strs: Vec<String> = tys.iter().map(|t| self.type_to_str(*t)).collect();
+ let strs: Vec<String> = tys.iter().map(|t| self.type_to_string(*t)).collect();
format!("[{}]", strs.connect(","))
}
- pub fn val_to_str(&self, val: ValueRef) -> String {
+ pub fn val_to_string(&self, val: ValueRef) -> String {
unsafe {
let s = llvm::LLVMValueToString(val);
let ret = from_c_str(s);
use middle::typeck::astconv::ast_ty_to_ty;
use middle::typeck::infer;
use middle::{typeck, ty, def, pat_util, stability};
-use util::ppaux::{ty_to_str};
+use util::ppaux::{ty_to_string};
use util::nodemap::NodeSet;
use lint::{Context, LintPass, LintArray};
});
if n_uniq > 0 {
- let s = ty_to_str(cx.tcx, ty);
+ let s = ty_to_string(cx.tcx, ty);
let m = format!("type uses owned (Box type) pointers: {}", s);
cx.span_lint(OWNED_HEAP_MEMORY, span, m.as_slice());
cx.span_lint(HEAP_MEMORY, span, m.as_slice());
}
if n_box > 0 {
- let s = ty_to_str(cx.tcx, ty);
+ let s = ty_to_string(cx.tcx, ty);
let m = format!("type uses managed (@ type) pointers: {}", s);
cx.span_lint(MANAGED_HEAP_MEMORY, span, m.as_slice());
cx.span_lint(HEAP_MEMORY, span, m.as_slice());
}
fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
- static ATTRIBUTE_WHITELIST: &'static [&'static str] = &'static [
+ static ATTRIBUTE_WHITELIST: &'static [&'static str] = &[
// FIXME: #14408 whitelist docs since rustdoc looks at them
"doc",
"unstable",
];
- static CRATE_ATTRS: &'static [&'static str] = &'static [
+ static CRATE_ATTRS: &'static [&'static str] = &[
+ "crate_name",
"crate_type",
"feature",
"no_start",
"no_main",
"no_std",
- "crate_id",
"desc",
"comment",
"license",
for &(lint, span, ref msg) in v.iter() {
tcx.sess.span_bug(span,
format!("unprocessed lint {} at {}: {}",
- lint.as_str(), tcx.map.node_to_str(*id), *msg).as_slice())
+ lint.as_str(), tcx.map.node_to_string(*id), *msg).as_slice())
}
}
#![allow(non_camel_case_types)]
use std::mem;
-use syntax::crateid::CrateId;
use back::svh::Svh;
// EBML enum definitions and utils shared by the encoder and decoder
pub static tag_crate_dep: uint = 0x19;
pub static tag_crate_hash: uint = 0x1a;
-pub static tag_crate_crateid: uint = 0x1b;
+pub static tag_crate_crate_name: uint = 0x1b;
-pub static tag_crate_dep_crateid: uint = 0x1d;
+pub static tag_crate_dep_crate_name: uint = 0x1d;
pub static tag_crate_dep_hash: uint = 0x1e;
pub static tag_mod_impl: uint = 0x1f;
#[deriving(Clone, Show)]
pub struct LinkMeta {
- pub crateid: CrateId,
+ pub crate_name: String,
pub crate_hash: Svh,
}
//! Validates all used crates and extern libraries and loads their metadata
-use back::link;
use back::svh::Svh;
use driver::session::Session;
use driver::{driver, config};
use syntax::diagnostic::SpanHandler;
use syntax::parse::token::InternedString;
use syntax::parse::token;
-use syntax::crateid::CrateId;
use syntax::visit;
struct Env<'a> {
fn dump_crates(cstore: &CStore) {
debug!("resolved crates:");
cstore.iter_crate_data_origins(|_, data, opt_source| {
- debug!("crate_id: {}", data.crate_id());
+ debug!(" name: {}", data.name());
debug!(" cnum: {}", data.cnum);
debug!(" hash: {}", data.hash());
opt_source.map(|cs| {
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
let mut map = HashMap::new();
cstore.iter_crate_data(|cnum, data| {
- let crateid = data.crate_id();
- let key = (crateid.name.clone(), crateid.path.clone());
- map.find_or_insert_with(key, |_| Vec::new()).push(cnum);
+ map.find_or_insert_with(data.name(), |_| Vec::new()).push(cnum);
});
- for ((name, _), dupes) in map.move_iter() {
+ for (name, dupes) in map.move_iter() {
if dupes.len() == 1 { continue }
diag.handler().warn(
- format!("using multiple versions of crate `{}`",
- name).as_slice());
+ format!("using multiple versions of crate `{}`", name).as_slice());
for dupe in dupes.move_iter() {
let data = cstore.get_crate_data(dupe);
diag.span_note(data.span, "used here");
- loader::note_crateid_attr(diag, &data.crate_id());
+ loader::note_crate_name(diag, data.name().as_slice());
}
}
}
let (cnum, _, _) = resolve_crate(e,
&None,
info.ident.as_slice(),
- &info.crate_id,
+ info.name.as_slice(),
None,
i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
struct CrateInfo {
ident: String,
- crate_id: CrateId,
+ name: String,
id: ast::NodeId,
should_link: bool,
}
let ident = token::get_ident(ident);
debug!("resolving extern crate stmt. ident: {:?} path_opt: {:?}",
ident, path_opt);
- let crate_id = match *path_opt {
+ let name = match *path_opt {
Some((ref path_str, _)) => {
- let crateid: Option<CrateId> = from_str(path_str.get());
- match crateid {
- None => {
- e.sess.span_err(i.span, "malformed crate id");
- return None
- }
- Some(id) => id
- }
+ let name = path_str.get().to_string();
+ validate_crate_name(Some(e.sess), name.as_slice(),
+ Some(i.span));
+ name
}
- None => from_str(ident.get().to_str().as_slice()).unwrap()
+ None => ident.get().to_string(),
};
Some(CrateInfo {
ident: ident.get().to_string(),
- crate_id: crate_id,
+ name: name,
id: id,
should_link: should_link(i),
})
}
}
+pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
+ let err = |s: &str| {
+ match (sp, sess) {
+ (_, None) => fail!("{}", s),
+ (Some(sp), Some(sess)) => sess.span_err(sp, s),
+ (None, Some(sess)) => sess.err(s),
+ }
+ };
+ if s.len() == 0 {
+ err("crate name must not be empty");
+ }
+ for c in s.chars() {
+ if c.is_alphanumeric() { continue }
+ if c == '_' || c == '-' { continue }
+ err(format!("invalid character `{}` in crate name: `{}`", c, s).as_slice());
+ }
+ match sess {
+ Some(sess) => sess.abort_if_errors(),
+ None => {}
+ }
+}
+
fn visit_item(e: &Env, i: &ast::Item) {
match i.node {
ast::ItemForeignMod(ref fm) => {
}
}
-fn existing_match(e: &Env, crate_id: &CrateId,
+fn existing_match(e: &Env, name: &str,
hash: Option<&Svh>) -> Option<ast::CrateNum> {
let mut ret = None;
e.sess.cstore.iter_crate_data(|cnum, data| {
- let other_id = data.crate_id();
- if crate_id.matches(&other_id) {
- let other_hash = data.hash();
- match hash {
- Some(hash) if *hash != other_hash => {}
- Some(..) | None => { ret = Some(cnum); }
+ if data.name().as_slice() != name { return }
+
+ match hash {
+ Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
+ Some(..) => return,
+ None => {}
+ }
+
+ // When the hash is None we're dealing with a top-level dependency in
+ // which case we may have a specification on the command line for this
+ // library. Even though an upstream library may have loaded something of
+ // the same name, we have to make sure it was loaded from the exact same
+ // location as well.
+ let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
+ let dylib = source.dylib.as_ref().map(|p| p.as_vec());
+ let rlib = source.rlib.as_ref().map(|p| p.as_vec());
+ match e.sess.opts.externs.find_equiv(&name) {
+ Some(locs) => {
+ let found = locs.iter().any(|l| {
+ Some(l.as_bytes()) == dylib || Some(l.as_bytes()) == rlib
+ });
+ if found {
+ ret = Some(cnum);
+ }
}
+ None => ret = Some(cnum),
}
});
return ret;
fn register_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
- crate_id: &CrateId,
+ name: &str,
span: Span,
lib: loader::Library)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
let loader::Library{ dylib, rlib, metadata } = lib;
let cmeta = Rc::new( cstore::crate_metadata {
- name: crate_id.name.to_string(),
+ name: name.to_string(),
data: metadata,
cnum_map: cnum_map,
cnum: cnum,
fn resolve_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
- crate_id: &CrateId,
+ name: &str,
hash: Option<&Svh>,
span: Span)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) {
- match existing_match(e, crate_id, hash) {
+ match existing_match(e, name, hash) {
None => {
- let id_hash = link::crate_id_hash(crate_id);
let mut load_ctxt = loader::Context {
sess: e.sess,
span: span,
ident: ident,
- crate_id: crate_id,
- id_hash: id_hash.as_slice(),
+ crate_name: name,
hash: hash.map(|a| &*a),
filesearch: e.sess.target_filesearch(),
os: e.sess.targ_cfg.os,
root: root,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
+ should_match_name: true,
};
let library = load_ctxt.load_library_crate();
- register_crate(e, root, ident, crate_id, span, library)
+ register_crate(e, root, ident, name, span, library)
}
Some(cnum) => (cnum,
e.sess.cstore.get_crate_data(cnum),
// The map from crate numbers in the crate we're resolving to local crate
// numbers
decoder::get_crate_deps(cdata).iter().map(|dep| {
- debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
+ debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
let (local_cnum, _, _) = resolve_crate(e, root,
- dep.crate_id.name.as_slice(),
- &dep.crate_id,
+ dep.name.as_slice(),
+ dep.name.as_slice(),
Some(&dep.hash),
span);
(dep.cnum, local_cnum)
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple();
let mut should_link = info.should_link && !is_cross;
- let id_hash = link::crate_id_hash(&info.crate_id);
let os = config::get_os(driver::host_triple()).unwrap();
let mut load_ctxt = loader::Context {
sess: self.env.sess,
span: krate.span,
ident: info.ident.as_slice(),
- crate_id: &info.crate_id,
- id_hash: id_hash.as_slice(),
+ crate_name: info.name.as_slice(),
hash: None,
filesearch: self.env.sess.host_filesearch(),
triple: driver::host_triple(),
root: &None,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
+ should_match_name: true,
};
let library = match load_ctxt.maybe_load_library_crate() {
Some (l) => l,
macros: macros,
registrar_symbol: registrar,
};
- if should_link && existing_match(&self.env, &info.crate_id, None).is_none() {
+ if should_link && existing_match(&self.env, info.name.as_slice(),
+ None).is_none() {
// register crate now to avoid double-reading metadata
register_crate(&mut self.env, &None, info.ident.as_slice(),
- &info.crate_id, krate.span, library);
+ info.name.as_slice(), krate.span, library);
}
pc
}
use std::rc::Rc;
use std::collections::HashMap;
use syntax::ast;
-use syntax::crateid::CrateId;
use syntax::codemap::Span;
use syntax::parse::token::IdentInterner;
}
pub fn add_used_link_args(&self, args: &str) {
- for s in args.split(' ') {
+ for s in args.split(' ').filter(|s| !s.is_empty()) {
self.used_link_args.borrow_mut().push(s.to_string());
}
}
impl crate_metadata {
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
- pub fn crate_id(&self) -> CrateId { decoder::get_crate_id(self.data()) }
+ pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
}
use syntax::print::pprust;
use syntax::ast;
use syntax::codemap;
-use syntax::crateid::CrateId;
pub type Cmd<'a> = &'a crate_metadata;
}
}
-fn item_sized(item: ebml::Doc) -> ast::Sized {
- match reader::maybe_get_doc(item, tag_items_data_item_sized) {
- None => ast::StaticSize,
- Some(sized_doc) => {
- match reader::doc_as_u8(sized_doc) as char {
- 'd' => ast::DynSize,
- 's' => ast::StaticSize,
- _ => fail!("unknown sized-ness character")
- }
- }
- }
-}
-
fn item_method_sort(item: ebml::Doc) -> char {
let mut ret = 'r';
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
tag_items_data_item_ty_param_bounds);
let rp_defs = item_region_param_defs(item_doc, cdata);
- let sized = item_sized(item_doc);
let mut bounds = ty::empty_builtin_bounds();
// Collect the builtin bounds from the encoded supertraits.
// FIXME(#8559): They should be encoded directly.
});
true
});
- // Turn sized into a bound, FIXME(#8559).
- if sized == ast::StaticSize {
- tcx.lang_items.to_builtin_kind(tcx.lang_items.sized_trait().unwrap()).map(|bound| {
- bounds.add(bound);
- });
- }
ty::TraitDef {
generics: ty::Generics {types: tp_defs,
let r = get_attributes(md);
for attr in r.iter() {
- try!(write!(out, "{}\n", pprust::attribute_to_str(attr)));
+ try!(write!(out, "{}\n", pprust::attribute_to_string(attr)));
}
write!(out, "\n\n")
#[deriving(Clone)]
pub struct CrateDep {
pub cnum: ast::CrateNum,
- pub crate_id: CrateId,
+ pub name: String,
pub hash: Svh,
}
d.as_str_slice().to_string()
}
reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| {
- let crate_id =
- from_str(docstr(depdoc,
- tag_crate_dep_crateid).as_slice()).unwrap();
+ let name = docstr(depdoc, tag_crate_dep_crate_name);
let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash).as_slice());
deps.push(CrateDep {
cnum: crate_num,
- crate_id: crate_id,
+ name: name,
hash: hash,
});
crate_num += 1;
fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> {
try!(write!(out, "=External Dependencies=\n"));
for dep in get_crate_deps(data).iter() {
- try!(write!(out, "{} {}-{}\n", dep.cnum, dep.crate_id, dep.hash));
+ try!(write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash));
}
try!(write!(out, "\n"));
Ok(())
Svh::new(hashdoc.as_str_slice())
}
-pub fn maybe_get_crate_id(data: &[u8]) -> Option<CrateId> {
+pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
let cratedoc = ebml::Doc::new(data);
- reader::maybe_get_doc(cratedoc, tag_crate_crateid).map(|doc| {
- from_str(doc.as_str_slice()).unwrap()
+ reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| {
+ doc.as_str_slice().to_string()
})
}
-pub fn get_crate_triple(data: &[u8]) -> String {
+pub fn get_crate_triple(data: &[u8]) -> Option<String> {
let cratedoc = ebml::Doc::new(data);
let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
- triple_doc.expect("No triple in crate").as_str().to_string()
+ triple_doc.map(|s| s.as_str().to_string())
}
-pub fn get_crate_id(data: &[u8]) -> CrateId {
- let cratedoc = ebml::Doc::new(data);
- let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid);
- from_str(hashdoc.as_str_slice()).unwrap()
+pub fn get_crate_name(data: &[u8]) -> String {
+ maybe_get_crate_name(data).expect("no crate name in crate")
}
pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Writer) -> io::IoResult<()> {
use syntax::ast_map;
use syntax::ast_util::*;
use syntax::ast_util;
-use syntax::attr::AttrMetaMethods;
use syntax::attr;
-use syntax::crateid::CrateId;
+use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::SpanHandler;
-use syntax::parse::token::InternedString;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::visit::Visitor;
}
pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
- ebml_w.wr_tagged_str(tag_def_id, def_to_str(id).as_slice());
+ ebml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
}
#[deriving(Clone)]
tag: uint) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
- ds: def_to_str,
+ ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
ebml_w.end_tag();
}
-pub fn def_to_str(did: DefId) -> String {
+pub fn def_to_string(did: DefId) -> String {
format!("{}:{}", did.krate, did.node)
}
tag: uint) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
- ds: def_to_str,
+ ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
ebml_w.end_tag();
ebml_w.wr_tagged_str(tag_region_param_def_def_id,
- def_to_str(param.def_id).as_slice());
+ def_to_string(param.def_id).as_slice());
ebml_w.wr_tagged_u64(tag_region_param_def_space,
param.space.to_uint() as u64);
fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
ebml_w.start_tag(tag_items_data_item_variant);
- let s = def_to_str(vid);
+ let s = def_to_string(vid);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
typ: ty::t) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
- ds: def_to_str,
+ ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
- ds: def_to_str,
+ ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
ebml_w: &mut Encoder,
disr_val: ty::Disr) {
ebml_w.start_tag(tag_disr_val);
- let s = disr_val.to_str();
+ let s = disr_val.to_string();
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
ebml_w.start_tag(tag_items_data_parent_item);
- let s = def_to_str(id);
+ let s = def_to_string(id);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
encode_struct_field_family(ebml_w, f.vis);
encode_def_id(ebml_w, f.id);
ebml_w.start_tag(tag_item_field_origin);
- let s = def_to_str(origin);
+ let s = def_to_string(origin);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
ebml_w.end_tag();
exp.name, token::get_ident(method_ident));
ebml_w.start_tag(tag_items_data_item_reexport);
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
- ebml_w.wr_str(def_to_str(method_def_id).as_slice());
+ ebml_w.wr_str(def_to_string(method_def_id).as_slice());
ebml_w.end_tag();
ebml_w.start_tag(tag_items_data_item_reexport_name);
ebml_w.wr_str(format!("{}::{}",
id);
ebml_w.start_tag(tag_items_data_item_reexport);
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
- ebml_w.wr_str(def_to_str(exp.def_id).as_slice());
+ ebml_w.wr_str(def_to_string(exp.def_id).as_slice());
ebml_w.end_tag();
ebml_w.start_tag(tag_items_data_item_reexport_name);
ebml_w.wr_str(exp.name.as_slice());
// Encode info about all the module children.
for item in md.items.iter() {
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
+ ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
ebml_w.end_tag();
each_auxiliary_node_id(*item, |auxiliary_node_id| {
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(local_def(
+ ebml_w.wr_str(def_to_string(local_def(
auxiliary_node_id)).as_slice());
ebml_w.end_tag();
true
debug!("(encoding info for module) ... encoding impl {} \
({:?}/{:?})",
token::get_ident(ident),
- did, ecx.tcx.map.node_to_str(did));
+ did, ecx.tcx.map.node_to_string(did));
ebml_w.start_tag(tag_mod_impl);
- ebml_w.wr_str(def_to_str(local_def(did)).as_slice());
+ ebml_w.wr_str(def_to_string(local_def(did)).as_slice());
ebml_w.end_tag();
}
_ => {}
source_opt: Option<DefId>) {
for source in source_opt.iter() {
ebml_w.start_tag(tag_item_method_provided_source);
- let s = def_to_str(*source);
+ let s = def_to_string(*source);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
}
}
-fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
- ebml_w.start_tag(tag_items_data_item_sized);
- let ch = match sized {
- DynSize => 'd',
- StaticSize => 's',
- };
- ebml_w.wr_str(str::from_char(ch).as_slice());
- ebml_w.end_tag();
-}
-
fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
stab_opt.map(|stab| {
ebml_w.start_tag(tag_items_data_item_stability);
}
debug!("encoding info for item at {}",
- tcx.sess.codemap().span_to_str(item.span));
+ tcx.sess.codemap().span_to_string(item.span));
let def_id = local_def(item.id);
let stab = stability::lookup(tcx, ast_util::local_def(item.id));
// Encode all the items in this module.
for foreign_item in fm.items.iter() {
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(local_def(foreign_item.id)).as_slice());
+ ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
ebml_w.end_tag();
}
encode_visibility(ebml_w, vis);
}
for &method_def_id in methods.iter() {
ebml_w.start_tag(tag_item_impl_method);
- let s = def_to_str(method_def_id);
+ let s = def_to_string(method_def_id);
ebml_w.writer.write(s.as_bytes());
ebml_w.end_tag();
}
ast_method)
}
}
- ItemTrait(_, sized, ref super_traits, ref ms) => {
+ ItemTrait(_, _, ref super_traits, ref ms) => {
add_to_index(item, ebml_w, index);
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, def_id);
encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
encode_name(ebml_w, item.ident.name);
encode_attributes(ebml_w, item.attrs.as_slice());
- // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
- // should no longer need this ugly little hack either.
- encode_sized(ebml_w, sized);
encode_visibility(ebml_w, vis);
encode_stability(ebml_w, stab);
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
ebml_w.end_tag();
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(method_def_id).as_slice());
+ ebml_w.wr_str(def_to_string(method_def_id).as_slice());
ebml_w.end_tag();
}
encode_path(ebml_w, path.clone());
// See above
let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
debug!("writing foreign item {}::{}",
- ecx.tcx.map.path_to_str(ni.id),
+ ecx.tcx.map.path_to_string(ni.id),
token::get_ident(ni.ident));
let mut ebml_w = unsafe {
ebml_w.end_tag();
}
-// So there's a special crate attribute called 'crate_id' which defines the
-// metadata that Rust cares about for linking crates. If the user didn't
-// provide it we will throw it in anyway with a default value.
-fn synthesize_crate_attrs(ecx: &EncodeContext,
- krate: &Crate) -> Vec<Attribute> {
-
- fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
- assert!(!ecx.link_meta.crateid.name.is_empty());
-
- attr::mk_attr_inner(attr::mk_attr_id(),
- attr::mk_name_value_item_str(
- InternedString::new("crate_id"),
- token::intern_and_get_ident(ecx.link_meta
- .crateid
- .to_str()
- .as_slice())))
- }
-
- let mut attrs = Vec::new();
- for attr in krate.attrs.iter() {
- if !attr.check_name("crate_id") {
- attrs.push(*attr);
- }
- }
- attrs.push(synthesize_crateid_attr(ecx));
-
- attrs
-}
-
fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
// Pull the cnums and name,vers,hash out of cstore
cstore.iter_crate_data(|key, val| {
let dep = decoder::CrateDep {
cnum: key,
- crate_id: decoder::get_crate_id(val.data()),
- hash: decoder::get_crate_hash(val.data())
+ name: decoder::get_crate_name(val.data()),
+ hash: decoder::get_crate_hash(val.data()),
};
deps.push(dep);
});
ebml_w.start_tag(tag_misc_info_crate_items);
for &item in krate.module.items.iter() {
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
+ ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
ebml_w.end_tag();
each_auxiliary_node_id(item, |auxiliary_node_id| {
ebml_w.start_tag(tag_mod_child);
- ebml_w.wr_str(def_to_str(local_def(
+ ebml_w.wr_str(def_to_string(local_def(
auxiliary_node_id)).as_slice());
ebml_w.end_tag();
true
fn encode_crate_dep(ebml_w: &mut Encoder,
dep: decoder::CrateDep) {
ebml_w.start_tag(tag_crate_dep);
- ebml_w.start_tag(tag_crate_dep_crateid);
- ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
+ ebml_w.start_tag(tag_crate_dep_crate_name);
+ ebml_w.writer.write(dep.name.as_bytes());
ebml_w.end_tag();
ebml_w.start_tag(tag_crate_dep_hash);
ebml_w.writer.write(dep.hash.as_str().as_bytes());
ebml_w.end_tag();
}
-fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
- ebml_w.start_tag(tag_crate_crateid);
- ebml_w.writer.write(crate_id.to_str().as_bytes());
+fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
+ ebml_w.start_tag(tag_crate_crate_name);
+ ebml_w.writer.write(crate_name.as_bytes());
ebml_w.end_tag();
}
let mut ebml_w = writer::Encoder::new(wr);
- encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
+ encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
encode_crate_triple(&mut ebml_w,
tcx.sess
.targ_cfg
encode_dylib_dependency_formats(&mut ebml_w, &ecx);
let mut i = ebml_w.writer.tell().unwrap();
- let crate_attrs = synthesize_crate_attrs(&ecx, krate);
- encode_attributes(&mut ebml_w, crate_attrs.as_slice());
+ encode_attributes(&mut ebml_w, krate.attrs.as_slice());
stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
i = ebml_w.writer.tell().unwrap();
let mut wr = MemWriter::new();
tyencode::enc_ty(&mut wr, &tyencode::ctxt {
diag: tcx.sess.diagnostic(),
- ds: def_to_str,
+ ds: def_to_string,
tcx: tcx,
abbrevs: &RefCell::new(HashMap::new())
}, t);
// except according to those terms.
//! Finds crate binaries and loads their metadata
+//!
+//! Might I be the first to welcome you to a world of platform differences,
+//! version requirements, dependency graphs, conficting desires, and fun! This
+//! is the major guts (along with metadata::creader) of the compiler for loading
+//! crates and resolving dependencies. Let's take a tour!
+//!
+//! # The problem
+//!
+//! Each invocation of the compiler is immediately concerned with one primary
+//! problem, to connect a set of crates to resolved crates on the filesystem.
+//! Concretely speaking, the compiler follows roughly these steps to get here:
+//!
+//! 1. Discover a set of `extern crate` statements.
+//! 2. Transform these directives into crate names. If the directive does not
+//! have an explicit name, then the identifier is the name.
+//! 3. For each of these crate names, find a corresponding crate on the
+//! filesystem.
+//!
+//! Sounds easy, right? Let's walk into some of the nuances.
+//!
+//! ## Transitive Dependencies
+//!
+//! Let's say we've got three crates: A, B, and C. A depends on B, and B depends
+//! on C. When we're compiling A, we primarily need to find and locate B, but we
+//! also end up needing to find and locate C as well.
+//!
+//! The reason for this is that any of B's types could be composed of C's types,
+//! any function in B could return a type from C, etc. To be able to guarantee
+//! that we can always typecheck/translate any function, we have to have
+//! complete knowledge of the whole ecosystem, not just our immediate
+//! dependencies.
+//!
+//! So now as part of the "find a corresponding crate on the filesystem" step
+//! above, this involves also finding all crates for *all upstream
+//! dependencies*. This includes all dependencies transitively.
+//!
+//! ## Rlibs and Dylibs
+//!
+//! The compiler has two forms of intermediate dependencies. These are dubbed
+//! rlibs and dylibs for the static and dynamic variants, respectively. An rlib
+//! is a rustc-defined file format (currently just an ar archive) while a dylib
+//! is a platform-defined dynamic library. Each library has a metadata somewhere
+//! inside of it.
+//!
+//! When translating a crate name to a crate on the filesystem, we all of a
+//! sudden need to take into account both rlibs and dylibs! Linkage later on may
+//! use either one of these files, as each has their pros/cons. The job of crate
+//! loading is to discover what's possible by finding all candidates.
+//!
+//! Most parts of this loading systems keep the dylib/rlib as just separate
+//! variables.
+//!
+//! ## Where to look?
+//!
+//! We can't exactly scan your whole hard drive when looking for dependencies,
+//! so we need to places to look. Currently the compiler will implicitly add the
+//! target lib search path ($prefix/lib/rustlib/$target/lib) to any compilation,
+//! and otherwise all -L flags are added to the search paths.
+//!
+//! ## What criterion to select on?
+//!
+//! This a pretty tricky area of loading crates. Given a file, how do we know
+//! whether it's the right crate? Currently, the rules look along these lines:
+//!
+//! 1. Does the filename match an rlib/dylib pattern? That is to say, does the
+//! filename have the right prefix/suffix?
+//! 2. Does the filename have the right prefix for the crate name being queried?
+//! This is filtering for files like `libfoo*.rlib` and such.
+//! 3. Is the file an actual rust library? This is done by loading the metadata
+//! from the library and making sure it's actually there.
+//! 4. Does the name in the metadata agree with the name of the library?
+//! 5. Does the target in the metadata agree with the current target?
+//! 6. Does the SVH match? (more on this later)
+//!
+//! If the file answeres `yes` to all these questions, then the file is
+//! considered as being *candidate* for being accepted. It is illegal to have
+//! more than two candidates as the compiler has no method by which to resolve
+//! this conflict. Additionally, rlib/dylib candidates are considered
+//! separately.
+//!
+//! After all this has happened, we have 1 or two files as candidates. These
+//! represent the rlib/dylib file found for a library, and they're returned as
+//! being found.
+//!
+//! ### What about versions?
+//!
+//! A lot of effort has been put forth to remove versioning from the compiler.
+//! There have been forays in the past to have versioning baked in, but it was
+//! largely always deemed insufficient to the point that it was recognized that
+//! it's probably something the compiler shouldn't do anyway due to its
+//! complicated nature and the state of the half-baked solutions.
+//!
+//! With a departure from versioning, the primary criterion for loading crates
+//! is just the name of a crate. If we stopped here, it would imply that you
+//! could never link two crates of the same name from different sources
+//! together, which is clearly a bad state to be in.
+//!
+//! To resolve this problem, we come to the next section!
+//!
+//! # Expert Mode
+//!
+//! A number of flags have been added to the compiler to solve the "version
+//! problem" in the previous section, as well as generally enabling more
+//! powerful usage of the crate loading system of the compiler. The goal of
+//! these flags and options are to enable third-party tools to drive the
+//! compiler with prior knowledge about how the world should look.
+//!
+//! ## The `--extern` flag
+//!
+//! The compiler accepts a flag of this form a number of times:
+//!
+//! ```notrust
+//! --extern crate-name=path/to/the/crate.rlib
+//! ```
+//!
+//! This flag is basically the following letter to the compiler:
+//!
+//! > Dear rustc,
+//! >
+//! > When you are attempting to load the immediate dependency `crate-name`, I
+//! > would like you too assume that the library is located at
+//! > `path/to/the/crate.rlib`, and look nowhere else. Also, please do not
+//! > assume that the path I specified has the name `crate-name`.
+//!
+//! This flag basically overrides most matching logic except for validating that
+//! the file is indeed a rust library. The same `crate-name` can be specified
+//! twice to specify the rlib/dylib pair.
+//!
+//! ## Enabling "multiple versions"
+//!
+//! This basically boils down to the ability to specify arbitrary packages to
+//! the compiler. For example, if crate A wanted to use Bv1 and Bv2, then it
+//! would look something like:
+//!
+//! ```ignore
+//! extern crate b1;
+//! extern crate b2;
+//!
+//! fn main() {}
+//! ```
+//!
+//! and the compiler would be invoked as:
+//!
+//! ```notrust
+//! rustc a.rs --extern b1=path/to/libb1.rlib --extern b2=path/to/libb2.rlib
+//! ```
+//!
+//! In this scenario there are two crates named `b` and the compiler must be
+//! manually driven to be informed where each crate is.
+//!
+//! ## Frobbing symbols
+//!
+//! One of the immediate problems with linking the same library together twice
+//! in the same problem is dealing with duplicate symbols. The primary way to
+//! deal with this in rustc is to add hashes to the end of each symbol.
+//!
+//! In order to force hashes to change between versions of a library, if
+//! desired, the compiler exposes an option `-C metadata=foo`, which is used to
+//! initially seed each symbol hash. The string `foo` is prepended to each
+//! string-to-hash to ensure that symbols change over time.
+//!
+//! ## Loading transitive dependencies
+//!
+//! Dealing with same-named-but-distinct crates is not just a local problem, but
+//! one that also needs to be dealt with for transitive dependences. Note that
+//! in the letter above `--extern` flags only apply to the *local* set of
+//! dependencies, not the upstream transitive dependencies. Consider this
+//! dependency graph:
+//!
+//! ```notrust
+//! A.1 A.2
+//! | |
+//! | |
+//! B C
+//! \ /
+//! \ /
+//! D
+//! ```
+//!
+//! In this scenario, when we compile `D`, we need to be able to distinctly
+//! resolve `A.1` and `A.2`, but an `--extern` flag cannot apply to these
+//! transitive dependencies.
+//!
+//! Note that the key idea here is that `B` and `C` are both *already compiled*.
+//! That is, they have already resolved their dependencies. Due to unrelated
+//! technical reasons, when a library is compiled, it is only compatible with
+//! the *exact same* version of the upstream libraries it was compiled against.
+//! We use the "Strict Version Hash" to identify the exact copy of an upstream
+//! library.
+//!
+//! With this knowledge, we know that `B` and `C` will depend on `A` with
+//! different SVH values, so we crawl the normal `-L` paths looking for
+//! `liba*.rlib` and filter based on the contained SVH.
+//!
+//! In the end, this ends up not needing `--extern` to specify upstream
+//! transitive dependencies.
+//!
+//! # Wrapping up
+//!
+//! That's the general overview of loading crates in the compiler, but it's by
+//! no means all of the necessary details. Take a look at the rest of
+//! metadata::loader or metadata::creader for all the juicy details!
use back::archive::{ArchiveRO, METADATA_FILENAME};
use back::svh::Svh;
use syntax::abi;
use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler;
-use syntax::crateid::CrateId;
-use syntax::attr::AttrMetaMethods;
use util::fs;
use std::c_str::ToCStr;
pub sess: &'a Session,
pub span: Span,
pub ident: &'a str,
- pub crate_id: &'a CrateId,
- pub id_hash: &'a str,
+ pub crate_name: &'a str,
pub hash: Option<&'a Svh>,
pub triple: &'a str,
pub os: abi::Os,
pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
pub rejected_via_triple: Vec<CrateMismatch>,
+ pub should_match_name: bool,
}
pub struct Library {
}
fn find_library_crate(&mut self) -> Option<Library> {
+ // If an SVH is specified, then this is a transitive dependency that
+ // must be loaded via -L plus some filtering.
+ if self.hash.is_none() {
+ self.should_match_name = false;
+ match self.find_commandline_library() {
+ Some(l) => return Some(l),
+ None => {}
+ }
+ self.should_match_name = true;
+ }
+
let dypair = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let dylib_prefix = dypair.map(|(prefix, _)| {
- format!("{}{}-", prefix, self.crate_id.name)
+ format!("{}{}", prefix, self.crate_name)
});
- let rlib_prefix = format!("lib{}-", self.crate_id.name);
+ let rlib_prefix = format!("lib{}", self.crate_name);
let mut candidates = HashMap::new();
// First, find all possible candidate rlibs and dylibs purely based on
// the name of the files themselves. We're trying to match against an
- // exact crate_id and a possibly an exact hash.
+ // exact crate name and a possibly an exact hash.
//
// During this step, we can filter all found libraries based on the
// name and id found in the crate id (we ignore the path portion for
None => return FileDoesntMatch,
Some(file) => file,
};
- if file.starts_with(rlib_prefix.as_slice()) &&
+ let (hash, rlib) = if file.starts_with(rlib_prefix.as_slice()) &&
file.ends_with(".rlib") {
- info!("rlib candidate: {}", path.display());
- match self.try_match(file, rlib_prefix.as_slice(), ".rlib") {
- Some(hash) => {
- info!("rlib accepted, hash: {}", hash);
- let slot = candidates.find_or_insert_with(hash, |_| {
- (HashSet::new(), HashSet::new())
- });
- let (ref mut rlibs, _) = *slot;
- rlibs.insert(fs::realpath(path).unwrap());
- FileMatches
- }
- None => {
- info!("rlib rejected");
- FileDoesntMatch
- }
- }
+ (file.slice(rlib_prefix.len(), file.len() - ".rlib".len()),
+ true)
} else if dypair.map_or(false, |(_, suffix)| {
file.starts_with(dylib_prefix.get_ref().as_slice()) &&
file.ends_with(suffix)
}) {
let (_, suffix) = dypair.unwrap();
let dylib_prefix = dylib_prefix.get_ref().as_slice();
- info!("dylib candidate: {}", path.display());
- match self.try_match(file, dylib_prefix, suffix) {
- Some(hash) => {
- info!("dylib accepted, hash: {}", hash);
- let slot = candidates.find_or_insert_with(hash, |_| {
- (HashSet::new(), HashSet::new())
- });
- let (_, ref mut dylibs) = *slot;
- dylibs.insert(fs::realpath(path).unwrap());
- FileMatches
- }
- None => {
- info!("dylib rejected");
- FileDoesntMatch
- }
- }
+ (file.slice(dylib_prefix.len(), file.len() - suffix.len()),
+ false)
} else {
- FileDoesntMatch
+ return FileDoesntMatch
+ };
+ info!("lib candidate: {}", path.display());
+ let slot = candidates.find_or_insert_with(hash.to_string(), |_| {
+ (HashSet::new(), HashSet::new())
+ });
+ let (ref mut rlibs, ref mut dylibs) = *slot;
+ if rlib {
+ rlibs.insert(fs::realpath(path).unwrap());
+ } else {
+ dylibs.insert(fs::realpath(path).unwrap());
}
+ FileMatches
});
// We have now collected all known libraries into a set of candidates
_ => {
self.sess.span_err(self.span,
format!("multiple matching crates for `{}`",
- self.crate_id.name).as_slice());
+ self.crate_name).as_slice());
self.sess.note("candidates:");
for lib in libraries.iter() {
match lib.dylib {
None => {}
}
let data = lib.metadata.as_slice();
- let crate_id = decoder::get_crate_id(data);
- note_crateid_attr(self.sess.diagnostic(), &crate_id);
+ let name = decoder::get_crate_name(data);
+ note_crate_name(self.sess.diagnostic(), name.as_slice());
}
None
}
}
}
- // Attempts to match the requested version of a library against the file
- // specified. The prefix/suffix are specified (disambiguates between
- // rlib/dylib).
- //
- // The return value is `None` if `file` doesn't look like a rust-generated
- // library, or if a specific version was requested and it doesn't match the
- // apparent file's version.
- //
- // If everything checks out, then `Some(hash)` is returned where `hash` is
- // the listed hash in the filename itself.
- fn try_match(&self, file: &str, prefix: &str, suffix: &str) -> Option<String>{
- let middle = file.slice(prefix.len(), file.len() - suffix.len());
- debug!("matching -- {}, middle: {}", file, middle);
- let mut parts = middle.splitn('-', 1);
- let hash = match parts.next() { Some(h) => h, None => return None };
- debug!("matching -- {}, hash: {} (want {})", file, hash, self.id_hash);
- let vers = match parts.next() { Some(v) => v, None => return None };
- debug!("matching -- {}, vers: {} (want {})", file, vers,
- self.crate_id.version);
- match self.crate_id.version {
- Some(ref version) if version.as_slice() != vers => return None,
- Some(..) => {} // check the hash
-
- // hash is irrelevant, no version specified
- None => return Some(hash.to_string())
- }
- debug!("matching -- {}, vers ok", file);
- // hashes in filenames are prefixes of the "true hash"
- if self.id_hash == hash.as_slice() {
- debug!("matching -- {}, hash ok", file);
- Some(hash.to_string())
- } else {
- None
- }
- }
-
// Attempts to extract *one* library from the set `m`. If the set has no
// elements, `None` is returned. If the set has more than one element, then
// the errors and notes are emitted about the set of libraries.
format!("multiple {} candidates for `{}` \
found",
flavor,
- self.crate_id.name).as_slice());
+ self.crate_name).as_slice());
self.sess.span_note(self.span,
format!(r"candidate #1: {}",
ret.get_ref()
}
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
- match decoder::maybe_get_crate_id(crate_data) {
- Some(ref id) if self.crate_id.matches(id) => {}
- _ => { info!("Rejecting via crate_id"); return false }
+ if self.should_match_name {
+ match decoder::maybe_get_crate_name(crate_data) {
+ Some(ref name) if self.crate_name == name.as_slice() => {}
+ _ => { info!("Rejecting via crate name"); return false }
+ }
}
let hash = match decoder::maybe_get_crate_hash(crate_data) {
Some(hash) => hash, None => {
}
};
- let triple = decoder::get_crate_triple(crate_data);
+ let triple = match decoder::get_crate_triple(crate_data) {
+ None => { debug!("triple not present"); return false }
+ Some(t) => t,
+ };
if triple.as_slice() != self.triple {
info!("Rejecting via crate triple: expected {} got {}", self.triple, triple);
self.rejected_via_triple.push(CrateMismatch {
}
}
+ fn find_commandline_library(&mut self) -> Option<Library> {
+ let locs = match self.sess.opts.externs.find_equiv(&self.crate_name) {
+ Some(s) => s,
+ None => return None,
+ };
+
+ // First, filter out all libraries that look suspicious. We only accept
+ // files which actually exist that have the correct naming scheme for
+ // rlibs/dylibs.
+ let sess = self.sess;
+ let dylibname = self.dylibname();
+ let mut locs = locs.iter().map(|l| Path::new(l.as_slice())).filter(|loc| {
+ if !loc.exists() {
+ sess.err(format!("extern location does not exist: {}",
+ loc.display()).as_slice());
+ return false;
+ }
+ let file = loc.filename_str().unwrap();
+ if file.starts_with("lib") && file.ends_with(".rlib") {
+ return true
+ } else {
+ match dylibname {
+ Some((prefix, suffix)) => {
+ if file.starts_with(prefix) && file.ends_with(suffix) {
+ return true
+ }
+ }
+ None => {}
+ }
+ }
+ sess.err(format!("extern location is of an unknown type: {}",
+ loc.display()).as_slice());
+ false
+ });
+
+ // Now that we have an itertor of good candidates, make sure there's at
+ // most one rlib and at most one dylib.
+ let mut rlibs = HashSet::new();
+ let mut dylibs = HashSet::new();
+ for loc in locs {
+ if loc.filename_str().unwrap().ends_with(".rlib") {
+ rlibs.insert(loc.clone());
+ } else {
+ dylibs.insert(loc.clone());
+ }
+ }
+
+ // Extract the rlib/dylib pair.
+ let mut metadata = None;
+ let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
+ let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
+
+ if rlib.is_none() && dylib.is_none() { return None }
+ match metadata {
+ Some(metadata) => Some(Library {
+ dylib: dylib,
+ rlib: rlib,
+ metadata: metadata,
+ }),
+ None => None,
+ }
+ }
}
-pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
- diag.handler().note(format!("crate_id: {}", crateid.to_str()).as_slice());
+pub fn note_crate_name(diag: &SpanHandler, name: &str) {
+ diag.handler().note(format!("crate name: {}", name).as_slice());
}
impl ArchiveMetadata {
op: |&mut MemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
- for t in v.get_vec(space).iter() {
+ for t in v.get_slice(space).iter() {
op(w, cx, t);
}
mywrite!(w, "]");
use middle::subst::VecPerParamSpace;
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
use middle::{ty, typeck};
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
use syntax::{ast, ast_map, ast_util, codemap, fold};
use syntax::codemap::Span;
e::IIMethodRef(_, _, m) => m.id,
};
debug!("> Encoding inlined item: {} ({})",
- ecx.tcx.map.path_to_str(id),
+ ecx.tcx.map.path_to_string(id),
ebml_w.writer.tell());
let ii = simplify_ast(ii);
ebml_w.end_tag();
debug!("< Encoded inlined fn: {} ({})",
- ecx.tcx.map.path_to_str(id),
+ ecx.tcx.map.path_to_string(id),
ebml_w.writer.tell());
}
debug!("> Decoding inlined fn: {}::?",
{
// Do an Option dance to use the path after it is moved below.
- let s = ast_map::path_to_str(ast_map::Values(path.iter()));
+ let s = ast_map::path_to_string(ast_map::Values(path.iter()));
path_as_str = Some(s);
path_as_str.as_ref().map(|x| x.as_slice())
});
match ii {
ast::IIItem(i) => {
debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
- syntax::print::pprust::item_to_str(&*i));
+ syntax::print::pprust::item_to_string(&*i));
}
_ => { }
}
v: &subst::VecPerParamSpace<T>,
f: |&mut Encoder, &T|) {
for &space in subst::ParamSpace::all().iter() {
- ebml_w.emit_from_vec(v.get_vec(space).as_slice(),
+ ebml_w.emit_from_vec(v.get_slice(space),
|ebml_w, n| Ok(f(ebml_w, n))).unwrap();
}
}
fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a> {
tyencode::ctxt {
diag: self.tcx.sess.diagnostic(),
- ds: e::def_to_str,
+ ds: e::def_to_string,
tcx: self.tcx,
abbrevs: &self.type_abbrevs
}
c::tag_table_node_type => {
let ty = val_dsr.read_ty(xcx);
debug!("inserting ty for node {:?}: {}",
- id, ty_to_str(dcx.tcx, ty));
+ id, ty_to_string(dcx.tcx, ty));
dcx.tcx.node_types.borrow_mut().insert(id as uint, ty);
}
c::tag_table_item_subst => {
).unwrap());
match (item_out, item_exp) {
(ast::IIItem(item_out), ast::IIItem(item_exp)) => {
- assert!(pprust::item_to_str(item_out) == pprust::item_to_str(item_exp));
+ assert!(pprust::item_to_string(item_out) == pprust::item_to_string(item_exp));
}
_ => fail!()
}
"it".to_string()
} else {
format!("`{}`",
- self.bccx.loan_path_to_str(&*old_loan.loan_path))
+ self.bccx.loan_path_to_string(&*old_loan.loan_path))
};
match (new_loan.kind, old_loan.kind) {
new_loan.span,
format!("cannot borrow `{}` as mutable \
more than once at a time",
- self.bccx.loan_path_to_str(
+ self.bccx.loan_path_to_string(
&*new_loan.loan_path)).as_slice());
}
new_loan.span,
format!("closure requires unique access to `{}` \
but {} is already borrowed",
- self.bccx.loan_path_to_str(&*new_loan.loan_path),
+ self.bccx.loan_path_to_string(&*new_loan.loan_path),
old_pronoun).as_slice());
}
new_loan.span,
format!("cannot borrow `{}` as {} because \
previous closure requires unique access",
- self.bccx.loan_path_to_str(&*new_loan.loan_path),
+ self.bccx.loan_path_to_string(&*new_loan.loan_path),
new_loan.kind.to_user_str()).as_slice());
}
new_loan.span,
format!("cannot borrow `{}` as {} because \
{} is also borrowed as {}",
- self.bccx.loan_path_to_str(&*new_loan.loan_path),
+ self.bccx.loan_path_to_string(&*new_loan.loan_path),
new_loan.kind.to_user_str(),
old_pronoun,
old_loan.kind.to_user_str()).as_slice());
self.bccx.span_note(
span,
format!("borrow occurs due to use of `{}` in closure",
- self.bccx.loan_path_to_str(
+ self.bccx.loan_path_to_string(
&*new_loan.loan_path)).as_slice());
}
_ => { }
format!("the mutable borrow prevents subsequent \
moves, borrows, or modification of `{0}` \
until the borrow ends",
- self.bccx.loan_path_to_str(
+ self.bccx.loan_path_to_string(
&*old_loan.loan_path))
}
format!("the immutable borrow prevents subsequent \
moves or mutable borrows of `{0}` \
until the borrow ends",
- self.bccx.loan_path_to_str(&*old_loan.loan_path))
+ self.bccx.loan_path_to_string(&*old_loan.loan_path))
}
ty::UniqueImmBorrow => {
format!("the unique capture prevents subsequent \
moves or borrows of `{0}` \
until the borrow ends",
- self.bccx.loan_path_to_str(&*old_loan.loan_path))
+ self.bccx.loan_path_to_string(&*old_loan.loan_path))
}
};
euv::ClosureCapture(_) => {
format!("previous borrow of `{}` occurs here due to \
use in closure",
- self.bccx.loan_path_to_str(&*old_loan.loan_path))
+ self.bccx.loan_path_to_string(&*old_loan.loan_path))
}
euv::OverloadedOperator(..) |
euv::ClosureInvocation(..) |
euv::RefBinding(..) => {
format!("previous borrow of `{}` occurs here",
- self.bccx.loan_path_to_str(&*old_loan.loan_path))
+ self.bccx.loan_path_to_string(&*old_loan.loan_path))
}
};
self.bccx.span_err(
span,
format!("cannot use `{}` because it was mutably borrowed",
- self.bccx.loan_path_to_str(copy_path).as_slice())
+ self.bccx.loan_path_to_string(copy_path).as_slice())
.as_slice());
self.bccx.span_note(
loan_span,
format!("borrow of `{}` occurs here",
- self.bccx.loan_path_to_str(&*loan_path).as_slice())
+ self.bccx.loan_path_to_string(&*loan_path).as_slice())
.as_slice());
}
}
let err_message = match move_kind {
move_data::Captured =>
format!("cannot move `{}` into closure because it is borrowed",
- self.bccx.loan_path_to_str(move_path).as_slice()),
+ self.bccx.loan_path_to_string(move_path).as_slice()),
move_data::Declared |
move_data::MoveExpr |
move_data::MovePat =>
format!("cannot move out of `{}` because it is borrowed",
- self.bccx.loan_path_to_str(move_path).as_slice())
+ self.bccx.loan_path_to_string(move_path).as_slice())
};
self.bccx.span_err(span, err_message.as_slice());
self.bccx.span_note(
loan_span,
format!("borrow of `{}` occurs here",
- self.bccx.loan_path_to_str(&*loan_path).as_slice())
+ self.bccx.loan_path_to_string(&*loan_path).as_slice())
.as_slice());
}
}
borrow_kind: ty::BorrowKind)
-> UseError {
debug!("analyze_restrictions_on_use(expr_id={:?}, use_path={})",
- self.tcx().map.node_to_str(expr_id),
+ self.tcx().map.node_to_string(expr_id),
use_path.repr(self.tcx()));
let mut ret = UseOk;
assignment_span,
format!("cannot assign to {} {} `{}`",
assignee_cmt.mutbl.to_user_str(),
- self.bccx.cmt_to_str(&*assignee_cmt),
- self.bccx.loan_path_to_str(&*lp)).as_slice());
+ self.bccx.cmt_to_string(&*assignee_cmt),
+ self.bccx.loan_path_to_string(&*lp)).as_slice());
}
None => {
self.bccx.span_err(
assignment_span,
format!("cannot assign to {} {}",
assignee_cmt.mutbl.to_user_str(),
- self.bccx.cmt_to_str(&*assignee_cmt)).as_slice());
+ self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
}
}
return;
self.bccx.span_err(
span,
format!("cannot assign to `{}` because it is borrowed",
- self.bccx.loan_path_to_str(loan_path)).as_slice());
+ self.bccx.loan_path_to_string(loan_path)).as_slice());
self.bccx.span_note(
loan.span,
format!("borrow of `{}` occurs here",
- self.bccx.loan_path_to_str(loan_path)).as_slice());
+ self.bccx.loan_path_to_string(loan_path)).as_slice());
}
}
bccx.span_err(
move_from.span,
format!("cannot move out of {}",
- bccx.cmt_to_str(&*move_from)).as_slice());
+ bccx.cmt_to_string(&*move_from)).as_slice());
}
mc::cat_downcast(ref b) |
move_to_span: codemap::Span,
pat_ident: &ast::Ident,
is_first_note: bool) {
- let pat_name = pprust::ident_to_str(pat_ident);
+ let pat_name = pprust::ident_to_string(pat_ident);
if is_first_note {
bccx.span_note(
move_to_span,
pub fn report(&self, err: BckError) {
self.span_err(
err.span,
- self.bckerr_to_str(&err).as_slice());
+ self.bckerr_to_string(&err).as_slice());
self.note_and_explain_bckerr(err);
}
use_span,
format!("{} of possibly uninitialized variable: `{}`",
verb,
- self.loan_path_to_str(lp)).as_slice());
+ self.loan_path_to_string(lp)).as_slice());
}
_ => {
let partially = if lp == moved_lp {""} else {"partially "};
format!("{} of {}moved value: `{}`",
verb,
partially,
- self.loan_path_to_str(lp)).as_slice());
+ self.loan_path_to_string(lp)).as_slice());
}
}
self.tcx.sess.span_note(
expr_span,
format!("`{}` moved here because it has type `{}`, which is {}",
- self.loan_path_to_str(moved_lp),
+ self.loan_path_to_string(moved_lp),
expr_ty.user_string(self.tcx),
suggestion).as_slice());
}
format!("`{}` moved here because it has type `{}`, \
which is moved by default (use `ref` to \
override)",
- self.loan_path_to_str(moved_lp),
+ self.loan_path_to_string(moved_lp),
pat_ty.user_string(self.tcx)).as_slice());
}
expr_span,
format!("`{}` moved into closure environment here because it \
has type `{}`, which is {}",
- self.loan_path_to_str(moved_lp),
+ self.loan_path_to_string(moved_lp),
expr_ty.user_string(self.tcx),
suggestion).as_slice());
}
self.tcx.sess.span_err(
span,
format!("re-assignment of immutable variable `{}`",
- self.loan_path_to_str(lp)).as_slice());
+ self.loan_path_to_string(lp)).as_slice());
self.tcx.sess.span_note(assign.span, "prior assignment occurs here");
}
self.tcx.sess.span_end_note(s, m);
}
- pub fn bckerr_to_str(&self, err: &BckError) -> String {
+ pub fn bckerr_to_string(&self, err: &BckError) -> String {
match err.code {
err_mutbl => {
let descr = match opt_loan_path(&err.cmt) {
None => {
format!("{} {}",
err.cmt.mutbl.to_user_str(),
- self.cmt_to_str(&*err.cmt))
+ self.cmt_to_string(&*err.cmt))
}
Some(lp) => {
format!("{} {} `{}`",
err.cmt.mutbl.to_user_str(),
- self.cmt_to_str(&*err.cmt),
- self.loan_path_to_str(&*lp))
+ self.cmt_to_string(&*err.cmt),
+ self.loan_path_to_string(&*lp))
}
};
let msg = match opt_loan_path(&err.cmt) {
None => "borrowed value".to_string(),
Some(lp) => {
- format!("`{}`", self.loan_path_to_str(&*lp))
+ format!("`{}`", self.loan_path_to_string(&*lp))
}
};
format!("{} does not live long enough", msg)
err_borrowed_pointer_too_short(..) => {
let descr = match opt_loan_path(&err.cmt) {
Some(lp) => {
- format!("`{}`", self.loan_path_to_str(&*lp))
+ format!("`{}`", self.loan_path_to_string(&*lp))
}
- None => self.cmt_to_str(&*err.cmt),
+ None => self.cmt_to_string(&*err.cmt),
};
format!("lifetime of {} is too short to guarantee \
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
let descr = match opt_loan_path(&err.cmt) {
Some(lp) => {
- format!("`{}`", self.loan_path_to_str(&*lp))
+ format!("`{}`", self.loan_path_to_string(&*lp))
}
- None => self.cmt_to_str(&*err.cmt),
+ None => self.cmt_to_string(&*err.cmt),
};
note_and_explain_region(
self.tcx,
}
}
- pub fn append_loan_path_to_str(&self,
+ pub fn append_loan_path_to_string(&self,
loan_path: &LoanPath,
out: &mut String) {
match *loan_path {
}
LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
- self.append_autoderefd_loan_path_to_str(&**lp_base, out);
+ self.append_autoderefd_loan_path_to_string(&**lp_base, out);
match fname {
mc::NamedField(fname) => {
out.push_char('.');
}
mc::PositionalField(idx) => {
out.push_char('#'); // invent a notation here
- out.push_str(idx.to_str().as_slice());
+ out.push_str(idx.to_string().as_slice());
}
}
}
LpExtend(ref lp_base, _, LpInterior(mc::InteriorElement(_))) => {
- self.append_autoderefd_loan_path_to_str(&**lp_base, out);
+ self.append_autoderefd_loan_path_to_string(&**lp_base, out);
out.push_str("[..]");
}
LpExtend(ref lp_base, _, LpDeref(_)) => {
out.push_char('*');
- self.append_loan_path_to_str(&**lp_base, out);
+ self.append_loan_path_to_string(&**lp_base, out);
}
}
}
- pub fn append_autoderefd_loan_path_to_str(&self,
+ pub fn append_autoderefd_loan_path_to_string(&self,
loan_path: &LoanPath,
out: &mut String) {
match *loan_path {
// For a path like `(*x).f` or `(*x)[3]`, autoderef
// rules would normally allow users to omit the `*x`.
// So just serialize such paths to `x.f` or x[3]` respectively.
- self.append_autoderefd_loan_path_to_str(&**lp_base, out)
+ self.append_autoderefd_loan_path_to_string(&**lp_base, out)
}
LpVar(..) | LpUpvar(..) | LpExtend(_, _, LpInterior(..)) => {
- self.append_loan_path_to_str(loan_path, out)
+ self.append_loan_path_to_string(loan_path, out)
}
}
}
- pub fn loan_path_to_str(&self, loan_path: &LoanPath) -> String {
+ pub fn loan_path_to_string(&self, loan_path: &LoanPath) -> String {
let mut result = String::new();
- self.append_loan_path_to_str(loan_path, &mut result);
+ self.append_loan_path_to_string(loan_path, &mut result);
result
}
- pub fn cmt_to_str(&self, cmt: &mc::cmt_) -> String {
- self.mc().cmt_to_str(cmt)
+ pub fn cmt_to_string(&self, cmt: &mc::cmt_) -> String {
+ self.mc().cmt_to_string(cmt)
}
}
fn repr(&self, tcx: &ty::ctxt) -> String {
match self {
&LpVar(id) => {
- format!("$({})", tcx.map.node_to_str(id))
+ format!("$({})", tcx.map.node_to_string(id))
}
&LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => {
- let s = tcx.map.node_to_str(var_id);
+ let s = tcx.map.node_to_string(var_id);
format!("$({} captured by id={})", s, closure_expr_id)
}
} else if n.data.id == ast::DUMMY_NODE_ID {
dot::LabelStr("(dummy_node)".into_maybe_owned())
} else {
- let s = self.ast_map.node_to_str(n.data.id);
+ let s = self.ast_map.node_to_string(n.data.id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
dot::EscStr(s.into_maybe_owned())
} else {
put_one = true;
}
- let s = self.ast_map.node_to_str(node_id);
+ let s = self.ast_map.node_to_string(node_id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
label = label.append(format!("exiting scope_{} {}",
.span_err(e.span,
format!("can not cast to `{}` in a constant \
expression",
- ppaux::ty_to_str(v.tcx, ety)).as_slice())
+ ppaux::ty_to_string(v.tcx, ety)).as_slice())
}
}
ExprPath(ref pth) => {
use syntax::ast_util::{is_unguarded, walk_pat};
use syntax::codemap::{Span, Spanned, DUMMY_SP};
use syntax::owned_slice::OwnedSlice;
-use syntax::print::pprust::pat_to_str;
+use syntax::print::pprust::pat_to_string;
use syntax::visit;
use syntax::visit::{Visitor, FnKind};
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
struct Matrix(Vec<Vec<Gc<Pat>>>);
let &Matrix(ref m) = self;
let pretty_printed_matrix: Vec<Vec<String>> = m.iter().map(|row| {
- row.iter().map(|&pat| pat_to_str(pat)).collect::<Vec<String>>()
+ row.iter().map(|&pat| pat_to_string(pat)).collect::<Vec<String>>()
}).collect();
let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0u);
// We know the type is inhabited, so this must be wrong
cx.tcx.sess.span_err(ex.span, format!("non-exhaustive patterns: \
type {} is non-empty",
- ty_to_str(cx.tcx, pat_ty)).as_slice());
+ ty_to_string(cx.tcx, pat_ty)).as_slice());
}
// If the type *is* empty, it's vacuously exhaustive
return;
[] => wild(),
_ => unreachable!()
};
- let msg = format!("non-exhaustive patterns: `{0}` not covered", pat_to_str(&*witness));
+ let msg = format!("non-exhaustive patterns: `{0}` not covered",
+ pat_to_string(&*witness));
cx.tcx.sess.span_err(sp, msg.as_slice());
}
NotUseful => {
};
if is_structure {
let fields = ty::lookup_struct_fields(cx.tcx, vid);
- let field_pats = fields.move_iter()
+ let field_pats: Vec<FieldPat> = fields.move_iter()
.zip(pats.iter())
+ .filter(|&(_, pat)| pat.node != PatWild)
.map(|(field, pat)| FieldPat {
ident: Ident::new(field.name),
pat: pat.clone()
}).collect();
- PatStruct(def_to_path(cx.tcx, vid), field_pats, false)
+ let has_more_fields = field_pats.len() < pats.len();
+ PatStruct(def_to_path(cx.tcx, vid), field_pats, has_more_fields)
} else {
PatEnum(def_to_path(cx.tcx, vid), Some(pats))
}
return NotUseful;
}
let real_pat = match rows.iter().find(|r| r.get(0).id != 0) {
- Some(r) => {
- match r.get(0).node {
- // An arm of the form `ref x @ sub_pat` has type
- // `sub_pat`, not `&sub_pat` as `x` itself does.
- PatIdent(BindByRef(_), _, Some(sub)) => sub,
- _ => *r.get(0)
- }
- }
+ Some(r) => raw_pat(*r.get(0)),
None if v.len() == 0 => return NotUseful,
None => v[0]
};
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => match ty::get(ty).sty {
ty::ty_vec(_, None) => match *ctor {
Slice(length) => length,
+ ConstantValue(_) => 0u,
_ => unreachable!()
},
ty::ty_str => 0u,
} else {
None
},
- DefStruct(struct_id) => Some(struct_id),
- _ => None
+ _ => {
+ // Assume this is a struct.
+ match ty::ty_to_def_id(node_id_to_type(cx.tcx, pat_id)) {
+ None => {
+ cx.tcx.sess.span_bug(pat_span,
+ "struct pattern wasn't of a \
+ type with a def ID?!")
+ }
+ Some(def_id) => Some(def_id),
+ }
+ }
};
class_id.map(|variant_id| {
let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);
Some(pat) => {
let msg = format!(
"refutable pattern in {} binding: `{}` not covered",
- name, pat_to_str(&*pat)
+ name, pat_to_string(&*pat)
);
cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
},
Some(pat) => {
let msg = format!(
"refutable pattern in function argument: `{}` not covered",
- pat_to_str(&*pat)
+ pat_to_string(&*pat)
);
cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
},
impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
fn visit_item(&mut self, i: &ast::Item, _is_const: bool) {
- debug!("visit_item(item={})", pprust::item_to_str(i));
+ debug!("visit_item(item={})", pprust::item_to_string(i));
match i.node {
ast::ItemStatic(_, mutability, ref expr) => {
match mutability {
/// of a static item, this method does nothing but walking
/// down through it.
fn visit_expr(&mut self, e: &ast::Expr, is_const: bool) {
- debug!("visit_expr(expr={})", pprust::expr_to_str(e));
+ debug!("visit_expr(expr={})", pprust::expr_to_string(e));
if !is_const {
return visit::walk_expr(self, e, is_const);
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
let (start, end) = self.compute_id_range_frozen(cfgidx);
let on_entry = self.on_entry.slice(start, end);
- let entry_str = bits_to_str(on_entry);
+ let entry_str = bits_to_string(on_entry);
let gens = self.gens.slice(start, end);
let gens_str = if gens.iter().any(|&u| u != 0) {
- format!(" gen: {}", bits_to_str(gens))
+ format!(" gen: {}", bits_to_string(gens))
} else {
"".to_string()
};
let kills = self.kills.slice(start, end);
let kills_str = if kills.iter().any(|&u| u != 0) {
- format!(" kill: {}", bits_to_str(kills))
+ format!(" kill: {}", bits_to_string(kills))
} else {
"".to_string()
};
fn apply_gen_kill(&mut self, cfgidx: CFGIndex, bits: &mut [uint]) {
//! Applies the gen and kill sets for `id` to `bits`
debug!("{:s} apply_gen_kill(cfgidx={}, bits={}) [before]",
- self.analysis_name, cfgidx, mut_bits_to_str(bits));
+ self.analysis_name, cfgidx, mut_bits_to_string(bits));
let (start, end) = self.compute_id_range(cfgidx);
let gens = self.gens.slice(start, end);
bitwise(bits, gens, &Union);
bitwise(bits, kills, &Subtract);
debug!("{:s} apply_gen_kill(cfgidx={}, bits={}) [after]",
- self.analysis_name, cfgidx, mut_bits_to_str(bits));
+ self.analysis_name, cfgidx, mut_bits_to_string(bits));
}
fn compute_id_range_frozen(&self, cfgidx: CFGIndex) -> (uint, uint) {
let (start, end) = self.compute_id_range_frozen(cfgidx);
let on_entry = self.on_entry.slice(start, end);
debug!("{:s} each_bit_on_entry_frozen(id={:?}, on_entry={})",
- self.analysis_name, id, bits_to_str(on_entry));
+ self.analysis_name, id, bits_to_string(on_entry));
self.each_bit(on_entry, f)
}
let (start, end) = self.compute_id_range_frozen(cfgidx);
let gens = self.gens.slice(start, end);
debug!("{:s} each_gen_bit(id={:?}, gens={})",
- self.analysis_name, id, bits_to_str(gens));
+ self.analysis_name, id, bits_to_string(gens));
self.each_bit(gens, f)
}
if changed {
let bits = self.kills.mut_slice(start, end);
debug!("{:s} add_kills_from_flow_exits flow_exit={} bits={} [before]",
- self.analysis_name, flow_exit, mut_bits_to_str(bits));
+ self.analysis_name, flow_exit, mut_bits_to_string(bits));
bits.copy_from(orig_kills.as_slice());
debug!("{:s} add_kills_from_flow_exits flow_exit={} bits={} [after]",
- self.analysis_name, flow_exit, mut_bits_to_str(bits));
+ self.analysis_name, flow_exit, mut_bits_to_string(bits));
}
true
});
cfg: &cfg::CFG,
in_out: &mut [uint]) {
debug!("DataFlowContext::walk_cfg(in_out={}) {:s}",
- bits_to_str(in_out), self.dfcx.analysis_name);
+ bits_to_string(in_out), self.dfcx.analysis_name);
cfg.graph.each_node(|node_index, node| {
debug!("DataFlowContext::walk_cfg idx={} id={} begin in_out={}",
- node_index, node.data.id, bits_to_str(in_out));
+ node_index, node.data.id, bits_to_string(in_out));
let (start, end) = self.dfcx.compute_id_range(node_index);
let source = edge.source();
let cfgidx = edge.target();
debug!("{:s} propagate_bits_into_entry_set_for(pred_bits={}, {} to {})",
- self.dfcx.analysis_name, bits_to_str(pred_bits), source, cfgidx);
+ self.dfcx.analysis_name, bits_to_string(pred_bits), source, cfgidx);
let (start, end) = self.dfcx.compute_id_range(cfgidx);
let changed = {
// (scoping mutable borrow of self.dfcx.on_entry)
if changed {
debug!("{:s} changed entry set for {:?} to {}",
self.dfcx.analysis_name, cfgidx,
- bits_to_str(self.dfcx.on_entry.slice(start, end)));
+ bits_to_string(self.dfcx.on_entry.slice(start, end)));
self.changed = true;
}
}
}
-fn mut_bits_to_str(words: &mut [uint]) -> String {
- bits_to_str(words)
+fn mut_bits_to_string(words: &mut [uint]) -> String {
+ bits_to_string(words)
}
-fn bits_to_str(words: &[uint]) -> String {
+fn bits_to_string(words: &[uint]) -> String {
let mut result = String::new();
let mut sep = '[';
fn set_bit(words: &mut [uint], bit: uint) -> bool {
debug!("set_bit: words={} bit={}",
- mut_bits_to_str(words), bit_str(bit));
+ mut_bits_to_string(words), bit_str(bit));
let word = bit / uint::BITS;
let bit_in_word = bit % uint::BITS;
let bit_mask = 1 << bit_in_word;
}
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
- match self.tcx.def_map.borrow().get(&lhs.id) {
- &def::DefStruct(id) | &def::DefVariant(_, id, _) => {
- let fields = ty::lookup_struct_fields(self.tcx, id);
- for pat in pats.iter() {
- let field_id = fields.iter()
- .find(|field| field.name == pat.ident.name).unwrap().id;
- self.live_symbols.insert(field_id.node);
+ let id = match self.tcx.def_map.borrow().get(&lhs.id) {
+ &def::DefVariant(_, id, _) => id,
+ _ => {
+ match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
+ lhs.id)) {
+ None => {
+ self.tcx.sess.span_bug(lhs.span,
+ "struct pattern wasn't of a \
+ type with a def ID?!")
+ }
+ Some(def_id) => def_id,
}
}
- _ => ()
+ };
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ for pat in pats.iter() {
+ let field_id = fields.iter()
+ .find(|field| field.name == pat.ident.name).unwrap().id;
+ self.live_symbols.insert(field_id.node);
}
}
_ => return
};
debug!("effect: checking index with base type {}",
- ppaux::ty_to_str(self.tcx, base_type));
+ ppaux::ty_to_string(self.tcx, base_type));
match ty::get(base_type).sty {
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
ty::ty_str => {
let method_call = MethodCall::expr(expr.id);
let base_type = self.tcx.method_map.borrow().get(&method_call).ty;
debug!("effect: method call case, base type is {}",
- ppaux::ty_to_str(self.tcx, base_type));
+ ppaux::ty_to_string(self.tcx, base_type));
if type_is_unsafe_function(base_type) {
self.require_unsafe(expr.span,
"invocation of unsafe method")
ast::ExprCall(base, _) => {
let base_type = ty::node_id_to_type(self.tcx, base.id);
debug!("effect: call case, base type is {}",
- ppaux::ty_to_str(self.tcx, base_type));
+ ppaux::ty_to_string(self.tcx, base_type));
if type_is_unsafe_function(base_type) {
self.require_unsafe(expr.span, "call to unsafe function")
}
ast::ExprUnary(ast::UnDeref, base) => {
let base_type = ty::node_id_to_type(self.tcx, base.id);
debug!("effect: unary case, base type is {}",
- ppaux::ty_to_str(self.tcx, base_type));
+ ppaux::ty_to_string(self.tcx, base_type));
match ty::get(base_type).sty {
ty::ty_ptr(_) => {
self.require_unsafe(expr.span,
use middle::ty;
use middle::typeck::{MethodCall, NoAdjustment};
use middle::typeck;
-use util::ppaux::{Repr, ty_to_str};
+use util::ppaux::{Repr, ty_to_string};
use util::ppaux::UserString;
use syntax::ast::*;
use syntax::attr;
use syntax::codemap::Span;
-use syntax::print::pprust::{expr_to_str, ident_to_str};
+use syntax::print::pprust::{expr_to_string, ident_to_string};
use syntax::{visit};
use syntax::visit::Visitor;
cx.tcx.sess.span_err(self_type.span,
format!("the type `{}', which does not fulfill `{}`, cannot implement this \
trait",
- ty_to_str(cx.tcx, self_ty),
+ ty_to_string(cx.tcx, self_ty),
missing.user_string(cx.tcx)).as_slice());
cx.tcx.sess.span_note(self_type.span,
format!("types implementing this trait must fulfill `{}`",
}
pub fn check_expr(cx: &mut Context, e: &Expr) {
- debug!("kind::check_expr({})", expr_to_str(e));
+ debug!("kind::check_expr({})", expr_to_string(e));
// Handle any kind bounds on type parameters
check_bounds_on_type_parameters(cx, e);
sp,
format!("instantiating a type parameter with an incompatible type \
`{}`, which does not fulfill `{}`",
- ty_to_str(cx.tcx, ty),
+ ty_to_string(cx.tcx, ty),
missing.user_string(cx.tcx)).as_slice());
});
}
format!("cannot implicitly borrow variable of type `{}` in a \
bounded stack closure (implicit reference does not \
fulfill `{}`)",
- ty_to_str(cx.tcx, rty),
+ ty_to_string(cx.tcx, rty),
missing.user_string(cx.tcx)).as_slice())
}
None => {
cx.tcx.sess.span_err(sp,
format!("cannot capture variable of type `{}`, which does \
not fulfill `{}`, in a bounded closure",
- ty_to_str(cx.tcx, ty),
+ ty_to_string(cx.tcx, ty),
missing.user_string(cx.tcx)).as_slice())
}
}
cx.tcx.sess.span_err(sp,
format!("cannot pack type `{}`, which does not fulfill \
`{}`, as a trait bounded by {}",
- ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
+ ty_to_string(cx.tcx, ty), missing.user_string(cx.tcx),
bounds.user_string(cx.tcx)).as_slice());
});
}
fn check_copy(cx: &Context, ty: ty::t, sp: Span, reason: &str) {
debug!("type_contents({})={}",
- ty_to_str(cx.tcx, ty),
- ty::type_contents(cx.tcx, ty).to_str());
+ ty_to_string(cx.tcx, ty),
+ ty::type_contents(cx.tcx, ty).to_string());
if ty::type_moves_by_default(cx.tcx, ty) {
cx.tcx.sess.span_err(
sp,
format!("copying a value of non-copyable type `{}`",
- ty_to_str(cx.tcx, ty)).as_slice());
+ ty_to_string(cx.tcx, ty)).as_slice());
cx.tcx.sess.span_note(sp, format!("{}", reason).as_slice());
}
}
tcx.sess.span_err(sp,
format!("value may contain references; \
add `'static` bound to `{}`",
- ty_to_str(tcx, ty)).as_slice());
+ ty_to_string(tcx, ty)).as_slice());
}
_ => {
tcx.sess.span_err(sp, "value may contain references");
// source_span,
// format!("source contains reference with lifetime \
// not found in the target type `{}`",
- // ty_to_str(cx.tcx, target_ty)));
+ // ty_to_string(cx.tcx, target_ty)));
// note_and_explain_region(
// cx.tcx, "source data is only valid for ", r, "");
// }
format!("variable `{}` has dynamically sized type \
`{}`",
name,
- ty_to_str(tcx, ty)).as_slice());
+ ty_to_string(tcx, ty)).as_slice());
}
}
fn check_pat(cx: &mut Context, pat: &Pat) {
let var_name = match pat.node {
PatWild => Some("_".to_string()),
- PatIdent(_, ref path1, _) => Some(ident_to_str(&path1.node).to_string()),
+ PatIdent(_, ref path1, _) => Some(ident_to_string(&path1.node).to_string()),
_ => None
};
match ty {
Some(ty) => {
debug!("kind: checking sized-ness of variable {}: {}",
- name, ty_to_str(cx.tcx, *ty));
+ name, ty_to_string(cx.tcx, *ty));
check_sized(cx.tcx, *ty, name, pat.span);
}
None => {} // extern fn args
ShlTraitLangItem, "shl", shl_trait;
ShrTraitLangItem, "shr", shr_trait;
IndexTraitLangItem, "index", index_trait;
+ IndexMutTraitLangItem, "index_mut", index_mut_trait;
UnsafeTypeLangItem, "unsafe", unsafe_type;
use syntax::codemap::{BytePos, original_sp, Span};
use syntax::parse::token::special_idents;
use syntax::parse::token;
-use syntax::print::pprust::{expr_to_str, block_to_str};
+use syntax::print::pprust::{expr_to_string, block_to_string};
use syntax::{visit, ast_util};
use syntax::visit::{Visitor, FnKind};
ExitNode
}
-fn live_node_kind_to_str(lnk: LiveNodeKind, cx: &ty::ctxt) -> String {
+fn live_node_kind_to_string(lnk: LiveNodeKind, cx: &ty::ctxt) -> String {
let cm = cx.sess.codemap();
match lnk {
FreeVarNode(s) => {
- format!("Free var node [{}]", cm.span_to_str(s))
+ format!("Free var node [{}]", cm.span_to_string(s))
}
ExprNode(s) => {
- format!("Expr node [{}]", cm.span_to_str(s))
+ format!("Expr node [{}]", cm.span_to_string(s))
}
VarDefNode(s) => {
- format!("Var def node [{}]", cm.span_to_str(s))
+ format!("Var def node [{}]", cm.span_to_string(s))
}
ExitNode => "Exit node".to_string(),
}
self.lnks.push(lnk);
self.num_live_nodes += 1;
- debug!("{} is of kind {}", ln.to_str(),
- live_node_kind_to_str(lnk, self.tcx));
+ debug!("{} is of kind {}", ln.to_string(),
+ live_node_kind_to_string(lnk, self.tcx));
ln
}
let ln = self.add_live_node(lnk);
self.live_node_map.insert(node_id, ln);
- debug!("{} is node {}", ln.to_str(), node_id);
+ debug!("{} is node {}", ln.to_string(), node_id);
}
fn add_variable(&mut self, vk: VarKind) -> Variable {
ImplicitRet => {}
}
- debug!("{} is {:?}", v.to_str(), vk);
+ debug!("{} is {:?}", v.to_string(), vk);
v
}
fn variable_name(&self, var: Variable) -> String {
match self.var_kinds.get(var.get()) {
&Local(LocalInfo { ident: nm, .. }) | &Arg(_, nm) => {
- token::get_ident(nm).get().to_str()
+ token::get_ident(nm).get().to_string()
},
&ImplicitRet => "<implicit-ret>".to_string()
}
for var_idx in range(0u, self.ir.num_vars) {
let idx = node_base_idx + var_idx;
if test(idx).is_valid() {
- try!(write!(wr, " {}", Variable(var_idx).to_str()));
+ try!(write!(wr, " {}", Variable(var_idx).to_string()));
}
}
Ok(())
self.write_vars(wr, ln, |idx| self.users.get(idx).reader);
write!(wr, " writes");
self.write_vars(wr, ln, |idx| self.users.get(idx).writer);
- write!(wr, " precedes {}]", self.successors.get(ln.get()).to_str());
+ write!(wr, " precedes {}]", self.successors.get(ln.get()).to_string());
}
str::from_utf8(wr.unwrap().as_slice()).unwrap().to_string()
}
});
debug!("merge_from_succ(ln={}, succ={}, first_merge={}, changed={})",
- ln.to_str(), self.ln_str(succ_ln), first_merge, changed);
+ ln.to_string(), self.ln_str(succ_ln), first_merge, changed);
return changed;
fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool {
self.users.get_mut(idx).reader = invalid_node();
self.users.get_mut(idx).writer = invalid_node();
- debug!("{} defines {} (idx={}): {}", writer.to_str(), var.to_str(),
+ debug!("{} defines {} (idx={}): {}", writer.to_string(), var.to_string(),
idx, self.ln_str(writer));
}
// Either read, write, or both depending on the acc bitset
fn acc(&mut self, ln: LiveNode, var: Variable, acc: uint) {
debug!("{} accesses[{:x}] {}: {}",
- ln.to_str(), acc, var.to_str(), self.ln_str(ln));
+ ln.to_string(), acc, var.to_string(), self.ln_str(ln));
let idx = self.idx(ln, var);
let user = self.users.get_mut(idx);
// effectively a return---this only occurs in `for` loops,
// where the body is really a closure.
- debug!("compute: using id for block, {}", block_to_str(body));
+ debug!("compute: using id for block, {}", block_to_string(body));
let exit_ln = self.s.exit_ln;
let entry_ln: LiveNode =
}
body.id
},
- entry_ln.to_str());
+ entry_ln.to_string());
entry_ln
}
fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
-> LiveNode {
- debug!("propagate_through_expr: {}", expr_to_str(expr));
+ debug!("propagate_through_expr: {}", expr_to_string(expr));
match expr.node {
// Interesting cases with control flow or which gen/kill
}
ExprFnBlock(_, ref blk) | ExprProc(_, ref blk) => {
- debug!("{} is an ExprFnBlock or ExprProc", expr_to_str(expr));
+ debug!("{} is an ExprFnBlock or ExprProc", expr_to_string(expr));
/*
The next-node for a break is the successor of the entire
first_merge = false;
}
debug!("propagate_through_loop: using id for loop body {} {}",
- expr.id, block_to_str(body));
+ expr.id, block_to_string(body));
let cond_ln = self.propagate_through_opt_expr(cond, ln);
let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| {
},
_ => false
};
+ self.ir.tcx.sess.span_err(
+ sp, "not all control paths return a value");
if ends_with_stmt {
let last_stmt = body.stmts.last().unwrap();
let original_span = original_sp(last_stmt.span, sp);
self.ir.tcx.sess.span_note(
span_semicolon, "consider removing this semicolon:");
}
- self.ir.tcx.sess.span_err(
- sp, "not all control paths return a value");
}
}
}
use middle::ty;
use middle::typeck;
use util::nodemap::NodeMap;
-use util::ppaux::{ty_to_str, Repr};
+use util::ppaux::{ty_to_string, Repr};
use syntax::ast::{MutImmutable, MutMutable};
use syntax::ast;
None => {
tcx.sess.bug(
format!("deref_cat() invoked on non-derefable type {}",
- ty_to_str(tcx, t)).as_slice());
+ ty_to_string(tcx, t)).as_slice());
}
}
}
}
ast::ExprIndex(ref base, _) => {
- if self.typer.is_method_call(expr.id) {
- return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
- }
-
let base_cmt = if_ok!(self.cat_expr(&**base));
Ok(self.cat_index(expr, base_cmt, 0))
}
pub fn cat_index<N:ast_node>(&self,
elt: &N,
- base_cmt: cmt,
+ mut base_cmt: cmt,
derefs: uint)
-> cmt {
//! Creates a cmt for an indexing operation (`[]`); this
//! - `derefs`: the deref number to be used for
//! the implicit index deref, if any (see above)
- let element_ty = match ty::array_element_ty(base_cmt.ty) {
- Some(ref mt) => mt.ty,
- None => {
- self.tcx().sess.span_bug(
- elt.span(),
- format!("Explicit index of non-index type `{}`",
- base_cmt.ty.repr(self.tcx())).as_slice());
- }
+ let method_call = typeck::MethodCall::expr(elt.id());
+ let method_ty = self.typer.node_method_ty(method_call);
+
+ let element_ty = match method_ty {
+ Some(method_ty) => {
+ let ref_ty = ty::ty_fn_ret(method_ty);
+ base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
+ *ty::ty_fn_args(method_ty).get(0)
+ }
+ None => {
+ match ty::array_element_ty(base_cmt.ty) {
+ Some(ref mt) => mt.ty,
+ None => {
+ self.tcx().sess.span_bug(
+ elt.span(),
+ format!("Explicit index of non-index type `{}`",
+ base_cmt.ty.repr(self.tcx())).as_slice());
+ }
+ }
+ }
};
return match deref_kind(self.tcx(), base_cmt.ty) {
// get the type of the *subpattern* and use that.
debug!("cat_pattern: id={} pat={} cmt={}",
- pat.id, pprust::pat_to_str(pat),
+ pat.id, pprust::pat_to_string(pat),
cmt.repr(self.tcx()));
op(self, cmt.clone(), pat);
Ok(())
}
- pub fn cmt_to_str(&self, cmt: &cmt_) -> String {
+ pub fn cmt_to_string(&self, cmt: &cmt_) -> String {
match cmt.cat {
cat_static_item => {
"static item".to_string()
"captured outer variable".to_string()
}
cat_discr(ref cmt, _) => {
- self.cmt_to_str(&**cmt)
+ self.cmt_to_string(&**cmt)
}
cat_downcast(ref cmt) => {
- self.cmt_to_str(&**cmt)
+ self.cmt_to_string(&**cmt)
}
}
}
fn repr(&self, _tcx: &ty::ctxt) -> String {
match *self {
InteriorField(NamedField(fld)) => {
- token::get_name(fld).get().to_str()
+ token::get_name(fld).get().to_string()
}
InteriorField(PositionalField(i)) => format!("#{:?}", i),
InteriorElement(_) => "[]".to_string(),
impl<'a> PrivacyVisitor<'a> {
// used when debugging
fn nodestr(&self, id: ast::NodeId) -> String {
- self.tcx.map.node_to_str(id).to_string()
+ self.tcx.map.node_to_string(id).to_string()
}
// Determines whether the given definition is public from the point of view
}
debug!("privacy - local {} not public all the way down",
- self.tcx.map.node_to_str(did.node));
+ self.tcx.map.node_to_string(did.node));
// return quickly for things in the same module
if self.parents.find(&did.node) == self.parents.find(&self.curitem) {
debug!("privacy - same parent, we're done here");
.bug(format!("found unexpected thingy in worklist: {}",
self.tcx
.map
- .node_to_str(search_item)).as_slice())
+ .node_to_string(search_item)).as_slice())
}
}
}
body.id={}, \
cx.parent={})",
id,
- visitor.sess.codemap().span_to_str(sp),
+ visitor.sess.codemap().span_to_string(sp),
body.id,
cx.parent);
#[deriving(PartialEq)]
enum DuplicateCheckingMode {
ForbidDuplicateModules,
- ForbidDuplicateTypes,
+ ForbidDuplicateTypesAndModules,
ForbidDuplicateValues,
ForbidDuplicateTypesAndValues,
OverwriteDuplicates
}
-fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
+fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
match ns {
- NoError => "",
- ModuleError => "module",
- TypeError => "type",
- ValueError => "value",
+ NoError => "",
+ ModuleError | TypeError => "type or module",
+ ValueError => "value",
}
}
}
Some(TypeNS)
}
- ForbidDuplicateTypes => {
+ ForbidDuplicateTypesAndModules => {
match child.def_for_namespace(TypeNS) {
- Some(DefMod(_)) | None => {}
+ None => {}
+ Some(_) if child.get_module_if_available()
+ .map(|m| m.kind.get()) ==
+ Some(ImplModuleKind) => {}
Some(_) => duplicate_type = TypeError
}
Some(TypeNS)
let ns = ns.unwrap();
self.resolve_error(sp,
format!("duplicate definition of {} `{}`",
- namespace_error_to_str(duplicate_type),
+ namespace_error_to_string(duplicate_type),
token::get_ident(name)).as_slice());
{
let r = child.span_for_namespace(ns);
for sp in r.iter() {
self.session.span_note(*sp,
format!("first definition of {} `{}` here",
- namespace_error_to_str(duplicate_type),
+ namespace_error_to_string(duplicate_type),
token::get_ident(name)).as_slice());
}
}
// These items live in the type namespace.
ItemTy(..) => {
let name_bindings =
- self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
+ self.add_child(ident,
+ parent.clone(),
+ ForbidDuplicateTypesAndModules,
+ sp);
name_bindings.define_type
(DefTy(local_def(item.id)), sp, is_public);
ItemEnum(ref enum_definition, _) => {
let name_bindings =
- self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
+ self.add_child(ident,
+ parent.clone(),
+ ForbidDuplicateTypesAndModules,
+ sp);
name_bindings.define_type
(DefTy(local_def(item.id)), sp, is_public);
// Adding to both Type and Value namespaces or just Type?
let (forbid, ctor_id) = match struct_def.ctor_id {
Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
- None => (ForbidDuplicateTypes, None)
+ None => (ForbidDuplicateTypesAndModules, None)
};
let name_bindings = self.add_child(ident, parent.clone(), forbid, sp);
ItemTrait(_, _, _, ref methods) => {
let name_bindings =
- self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
+ self.add_child(ident,
+ parent.clone(),
+ ForbidDuplicateTypesAndModules,
+ sp);
// Add all the methods within to a new module.
let parent_link = self.get_parent_link(parent.clone(), ident);
false,
true));
debug!("(build reduced graph for item) found extern `{}`",
- self.module_to_str(&*external_module));
+ self.module_to_string(&*external_module));
parent.module().external_module_children.borrow_mut()
.insert(name.name, external_module.clone());
self.build_reduced_graph_for_external_crate(external_module);
/// Builds the reduced graph rooted at the given external module.
fn populate_external_module(&mut self, module: Rc<Module>) {
debug!("(populating external module) attempting to populate {}",
- self.module_to_str(&*module));
+ self.module_to_string(&*module));
let def_id = match module.def_id.get() {
None => {
SingleImport(target, _) => {
debug!("(building import directive) building import \
directive: {}::{}",
- self.idents_to_str(module_.imports.borrow().last().unwrap()
+ self.idents_to_string(module_.imports.borrow().last().unwrap()
.module_path.as_slice()),
token::get_ident(target));
/// submodules.
fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
debug!("(resolving imports for module subtree) resolving {}",
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
let orig_module = replace(&mut self.current_module, module_.clone());
self.resolve_imports_for_module(module_.clone());
self.current_module = orig_module;
if module.all_imports_resolved() {
debug!("(resolving imports for module) all imports resolved for \
{}",
- self.module_to_str(&*module));
+ self.module_to_string(&*module));
return;
}
None => (import_directive.span, String::new())
};
let msg = format!("unresolved import `{}`{}",
- self.import_path_to_str(
+ self.import_path_to_string(
import_directive.module_path
.as_slice(),
import_directive.subclass),
}
}
- fn idents_to_str(&self, idents: &[Ident]) -> String {
+ fn idents_to_string(&self, idents: &[Ident]) -> String {
let mut first = true;
let mut result = String::new();
for ident in idents.iter() {
result
}
- fn path_idents_to_str(&self, path: &Path) -> String {
+ fn path_idents_to_string(&self, path: &Path) -> String {
let identifiers: Vec<ast::Ident> = path.segments
.iter()
.map(|seg| seg.identifier)
.collect();
- self.idents_to_str(identifiers.as_slice())
+ self.idents_to_string(identifiers.as_slice())
}
- fn import_directive_subclass_to_str(&mut self,
+ fn import_directive_subclass_to_string(&mut self,
subclass: ImportDirectiveSubclass)
-> String {
match subclass {
}
}
- fn import_path_to_str(&mut self,
+ fn import_path_to_string(&mut self,
idents: &[Ident],
subclass: ImportDirectiveSubclass)
-> String {
if idents.is_empty() {
- self.import_directive_subclass_to_str(subclass)
+ self.import_directive_subclass_to_string(subclass)
} else {
(format!("{}::{}",
- self.idents_to_str(idents),
- self.import_directive_subclass_to_str(
+ self.idents_to_string(idents),
+ self.import_directive_subclass_to_string(
subclass))).to_string()
}
}
debug!("(resolving import for module) resolving import `{}::...` in \
`{}`",
- self.idents_to_str(module_path.as_slice()),
- self.module_to_str(&*module_));
+ self.idents_to_string(module_path.as_slice()),
+ self.module_to_string(&*module_));
// First, resolve the module path for the directive, if necessary.
let container = if module_path.len() == 0 {
debug!("(resolving single import) resolving `{}` = `{}::{}` from \
`{}` id {}, last private {:?}",
token::get_ident(target),
- self.module_to_str(&*containing_module),
+ self.module_to_string(&*containing_module),
token::get_ident(source),
- self.module_to_str(module_),
+ self.module_to_string(module_),
directive.id,
lp);
if value_result.is_unbound() && type_result.is_unbound() {
let msg = format!("There is no `{}` in `{}`",
token::get_ident(source),
- self.module_to_str(&*containing_module));
+ self.module_to_string(&*containing_module));
return Failed(Some((directive.span, msg)));
}
let value_used_public = value_used_reexport || value_used_public;
debug!("(resolving glob import) writing module resolution \
{:?} into `{}`",
target_import_resolution.type_target.is_none(),
- self.module_to_str(module_));
+ self.module_to_string(module_));
if !target_import_resolution.is_public {
debug!("(resolving glob import) nevermind, just kidding");
debug!("(resolving glob import) writing resolution `{}` in `{}` \
to `{}`",
- token::get_name(name).get().to_str(),
- self.module_to_str(&*containing_module),
- self.module_to_str(module_));
+ token::get_name(name).get().to_string(),
+ self.module_to_string(&*containing_module),
+ self.module_to_string(module_));
// Merge the child item into the import resolution.
if name_bindings.defined_in_public_namespace(ValueNS) {
false) {
Failed(None) => {
let segment_name = token::get_ident(name);
- let module_name = self.module_to_str(&*search_module);
+ let module_name = self.module_to_string(&*search_module);
let mut span = span;
let msg = if "???" == module_name.as_slice() {
span.hi = span.lo + Pos::from_uint(segment_name.get().len());
match search_parent_externals(name.name,
&self.current_module) {
Some(module) => {
- let path_str = self.idents_to_str(module_path);
- let target_mod_str = self.module_to_str(&*module);
+ let path_str = self.idents_to_string(module_path);
+ let target_mod_str = self.module_to_string(&*module);
let current_mod_str =
- self.module_to_str(&*self.current_module);
+ self.module_to_string(&*self.current_module);
let prefix = if target_mod_str == current_mod_str {
"self::".to_string()
debug!("(resolving module path for import) processing `{}` rooted at \
`{}`",
- self.idents_to_str(module_path),
- self.module_to_str(&*module_));
+ self.idents_to_string(module_path),
+ self.module_to_string(&*module_));
// Resolve the module prefix, if any.
let module_prefix_result = self.resolve_module_prefix(module_.clone(),
let last_private;
match module_prefix_result {
Failed(None) => {
- let mpath = self.idents_to_str(module_path);
+ let mpath = self.idents_to_string(module_path);
let mpath = mpath.as_slice();
match mpath.rfind(':') {
Some(idx) => {
namespace {:?} in `{}`",
token::get_ident(name),
namespace,
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
// The current module node is handled specially. First, check for
// its immediate children.
break
}
debug!("(resolving module prefix) resolving `super` at {}",
- self.module_to_str(&*containing_module));
+ self.module_to_string(&*containing_module));
match self.get_nearest_normal_module_parent(containing_module) {
None => return Failed(None),
Some(new_module) => {
}
debug!("(resolving module prefix) finished resolving prefix at {}",
- self.module_to_str(&*containing_module));
+ self.module_to_string(&*containing_module));
return Success(PrefixFound(containing_module, i));
}
-> ResolveResult<(Target, bool)> {
debug!("(resolving name in module) resolving `{}` in `{}`",
token::get_name(name).get(),
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
// First, check the direct children of the module.
self.populate_module_if_necessary(&module_);
// OK. Continue.
debug!("(recording exports for module subtree) recording \
exports for local module `{}`",
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
}
None => {
// Record exports for the root module.
debug!("(recording exports for module subtree) recording \
exports for root module `{}`",
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
}
Some(_) => {
// Bail out.
debug!("(recording exports for module subtree) not recording \
exports for `{}`",
- self.module_to_str(&*module_));
+ self.module_to_string(&*module_));
return;
}
}
None => {
debug!("!!! (with scope) didn't find `{}` in `{}`",
token::get_ident(name),
- self.module_to_str(&*orig_module));
+ self.module_to_string(&*orig_module));
}
Some(name_bindings) => {
match (*name_bindings).get_module_if_available() {
debug!("!!! (with scope) didn't find module \
for `{}` in `{}`",
token::get_ident(name),
- self.module_to_str(&*orig_module));
+ self.module_to_string(&*orig_module));
}
Some(module_) => {
self.current_module = module_;
item.id,
ItemRibKind),
|this| {
+ this.resolve_type_parameters(&generics.ty_params);
visit::walk_item(this, item, ());
});
}
methods.as_slice());
}
- ItemTrait(ref generics, _, ref traits, ref methods) => {
+ ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
// Create a new rib for the self type.
let self_type_rib = Rib::new(ItemRibKind);
for trt in traits.iter() {
this.resolve_trait_reference(item.id, trt, TraitDerivation);
}
+ match unbound {
+ &Some(ast::TraitTyParamBound(ref tpb)) => {
+ this.resolve_trait_reference(item.id, tpb, TraitDerivation);
+ }
+ _ => {}
+ }
for method in (*methods).iter() {
// Create a new rib for the method-specific type
}
fn resolve_type_parameters(&mut self,
- type_parameters: &OwnedSlice<TyParam>) {
+ type_parameters: &OwnedSlice<TyParam>) {
for type_parameter in type_parameters.iter() {
for bound in type_parameter.bounds.iter() {
self.resolve_type_parameter_bound(type_parameter.id, bound);
}
+ match &type_parameter.unbound {
+ &Some(ref unbound) => self.resolve_type_parameter_bound(type_parameter.id, unbound),
+ &None => {}
+ }
match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty),
None => {}
}
fn resolve_trait_reference(&mut self,
- id: NodeId,
- trait_reference: &TraitRef,
- reference_type: TraitReferenceType) {
+ id: NodeId,
+ trait_reference: &TraitRef,
+ reference_type: TraitReferenceType) {
match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
None => {
- let path_str = self.path_idents_to_str(&trait_reference.path);
+ let path_str = self.path_idents_to_string(&trait_reference.path);
let usage_str = match reference_type {
TraitBoundingTypeParameter => "bound type parameter with",
TraitImplementation => "implement",
(def, _) => {
self.resolve_error(trait_reference.path.span,
format!("`{}` is not a trait",
- self.path_idents_to_str(
+ self.path_idents_to_string(
&trait_reference.path)));
// If it's a typedef, give a note
.identifier),
def);
debug!("(resolving struct) writing resolution for `{}` (id {})",
- this.path_idents_to_str(path),
+ this.path_idents_to_string(path),
path_id);
this.record_def(path_id, (def, lp));
}
let method_name = method.ident.name;
if self.method_map.borrow().find(&(method_name, did)).is_none() {
- let path_str = self.path_idents_to_str(&trait_ref.path);
+ let path_str = self.path_idents_to_string(&trait_ref.path);
self.resolve_error(method.span,
format!("method `{}` is not a member of trait `{}`",
token::get_name(method_name),
// Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` \
(id {})",
- self.path_idents_to_str(path),
+ self.path_idents_to_string(path),
path_id);
self.record_def(path_id, def);
}
None => {
let msg = format!("use of undeclared type name `{}`",
- self.path_idents_to_str(path));
+ self.path_idents_to_string(path));
self.resolve_error(ty.span, msg.as_slice());
}
}
PatStruct(ref path, _, _) => {
match self.resolve_path(pat_id, path, TypeNS, false) {
- Some((DefTy(class_id), lp))
- if self.structs.contains_key(&class_id) => {
- let class_def = DefStruct(class_id);
- self.record_def(pattern.id, (class_def, lp));
- }
- Some(definition @ (DefStruct(class_id), _)) => {
- assert!(self.structs.contains_key(&class_id));
- self.record_def(pattern.id, definition);
- }
- Some(definition @ (DefVariant(_, variant_id, _), _))
- if self.structs.contains_key(&variant_id) => {
+ Some(definition) => {
self.record_def(pattern.id, definition);
}
result => {
debug!("(resolving pattern) didn't find struct \
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
- self.path_idents_to_str(path));
+ self.path_idents_to_string(path));
self.resolve_error(path.span, msg.as_slice());
}
}
Some((span, msg)) => (span, msg),
None => {
let msg = format!("Use of undeclared module `{}`",
- self.idents_to_str(
+ self.idents_to_string(
module_path_idents.as_slice()));
(path.span, msg)
}
Some((span, msg)) => (span, msg),
None => {
let msg = format!("Use of undeclared module `::{}`",
- self.idents_to_str(
+ self.idents_to_string(
module_path_idents.as_slice()));
(path.span, msg)
}
match get_module(self, path.span, ident_path.as_slice()) {
Some(module) => match module.children.borrow().find(&name) {
Some(binding) => {
- let p_str = self.path_idents_to_str(&path);
+ let p_str = self.path_idents_to_string(&path);
match binding.def_for_namespace(ValueNS) {
Some(DefStaticMethod(_, provenance, _)) => {
match provenance {
let method_map = self.method_map.borrow();
match self.current_trait_ref {
Some((did, ref trait_ref)) => {
- let path_str = self.path_idents_to_str(&trait_ref.path);
+ let path_str = self.path_idents_to_string(&trait_ref.path);
match method_map.find(&(name, did)) {
Some(&SelfStatic) => return StaticTraitMethod(path_str),
Some(def) => {
// Write the result into the def map.
debug!("(resolving expr) resolved `{}`",
- self.path_idents_to_str(path));
+ self.path_idents_to_string(path));
// First-class methods are not supported yet; error
// out here.
self.record_def(expr.id, def);
}
None => {
- let wrong_name = self.path_idents_to_str(path);
+ let wrong_name = self.path_idents_to_string(path);
// Be helpful if the name refers to a struct
// (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and enum-like
}
ExprStruct(ref path, _, _) => {
- // Resolve the path to the structure it goes to.
+ // Resolve the path to the structure it goes to. We don't
+ // check to ensure that the path is actually a structure; that
+ // is checked later during typeck.
match self.resolve_path(expr.id, path, TypeNS, false) {
- Some((DefTy(class_id), lp)) | Some((DefStruct(class_id), lp))
- if self.structs.contains_key(&class_id) => {
- let class_def = DefStruct(class_id);
- self.record_def(expr.id, (class_def, lp));
- }
- Some(definition @ (DefVariant(_, class_id, _), _))
- if self.structs.contains_key(&class_id) => {
- self.record_def(expr.id, definition);
- }
+ Some(definition) => self.record_def(expr.id, definition),
result => {
debug!("(resolving expression) didn't find struct \
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
- self.path_idents_to_str(path));
+ self.path_idents_to_string(path));
self.resolve_error(path.span, msg.as_slice());
}
}
//
/// A somewhat inefficient routine to obtain the name of a module.
- fn module_to_str(&self, module: &Module) -> String {
+ fn module_to_string(&self, module: &Module) -> String {
let mut idents = Vec::new();
fn collect_mod(idents: &mut Vec<ast::Ident>, module: &Module) {
if idents.len() == 0 {
return "???".to_string();
}
- self.idents_to_str(idents.move_iter().rev()
+ self.idents_to_string(idents.move_iter().rev()
.collect::<Vec<ast::Ident>>()
.as_slice())
}
#[allow(dead_code)] // useful for debugging
fn dump_module(&mut self, module_: Rc<Module>) {
- debug!("Dump of module `{}`:", self.module_to_str(&*module_));
+ debug!("Dump of module `{}`:", self.module_to_string(&*module_));
debug!("Children:");
self.populate_module_if_necessary(&module_);
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
-use syntax::print::pprust::{lifetime_to_str};
+use syntax::print::pprust::{lifetime_to_string};
use syntax::visit;
use syntax::visit::Visitor;
use util::nodemap::NodeMap;
}
debug!("lifetime_ref={} id={} resolved to {:?}",
- lifetime_to_str(lifetime_ref),
+ lifetime_to_string(lifetime_ref),
lifetime_ref.id,
def);
self.named_region_map.insert(lifetime_ref.id, def);
use syntax::parse::token::{get_ident,keywords};
use syntax::visit;
use syntax::visit::Visitor;
-use syntax::print::pprust::{path_to_str,ty_to_str};
+use syntax::print::pprust::{path_to_string,ty_to_string};
use middle::save::span_utils::SpanUtils;
use middle::save::recorder::Recorder;
if spans.len() < path.segments.len() {
error!("Mis-calculated spans for path '{}'. \
Found {} spans, expected {}. Found spans:",
- path_to_str(path), spans.len(), path.segments.len());
+ path_to_string(path), spans.len(), path.segments.len());
for s in spans.iter() {
let loc = self.sess.codemap().lookup_char_pos(s.lo);
error!(" '{}' in {}, line {}",
let sub_path = ast::Path{span: *span, // span for the last segment
global: path.global,
segments: segs};
- let qualname = path_to_str(&sub_path);
+ let qualname = path_to_string(&sub_path);
result.push((*span, qualname));
segs = sub_path.segments;
}
self.collecting = false;
let span_utils = self.span;
for &(id, ref p, _, _) in self.collected_paths.iter() {
- let typ = ppaux::ty_to_str(&self.analysis.ty_cx,
+ let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
*self.analysis.ty_cx.node_types.borrow().get(&(id as uint)));
// get the span only for the name of the variable (I hope the path is only ever a
// variable name, but who knows?)
span_utils.span_for_last_ident(p.span),
id,
qualname,
- path_to_str(p).as_slice(),
+ path_to_string(p).as_slice(),
typ.as_slice());
}
self.collected_paths.clear();
match item.node {
ast::ItemImpl(_, _, ty, _) => {
let mut result = String::from_str("<");
- result.push_str(ty_to_str(&*ty).as_slice());
+ result.push_str(ty_to_string(&*ty).as_slice());
match ty::trait_of_method(&self.analysis.ty_cx,
ast_util::local_def(method.id)) {
ast::NamedField(ident, _) => {
let name = get_ident(ident);
let qualname = format!("{}::{}", qualname, name);
- let typ = ppaux::ty_to_str(&self.analysis.ty_cx,
+ let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
*self.analysis.ty_cx.node_types.borrow().get(&(field.node.id as uint)));
match self.span.sub_span_before_token(field.span, token::COLON) {
Some(sub_span) => self.fmt.field_str(field.span,
decl: ast::P<ast::FnDecl>,
ty_params: &ast::Generics,
body: ast::P<ast::Block>) {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Fn);
self.fmt.fn_str(item.span,
mt: ast::Mutability,
expr: &ast::Expr)
{
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
// If the variable is immutable, save the initialising expression.
let value = match mt {
get_ident(item.ident).get(),
qualname.as_slice(),
value.as_slice(),
- ty_to_str(&*typ).as_slice(),
+ ty_to_string(&*typ).as_slice(),
e.cur_scope);
// walk type and init value
e: DxrVisitorEnv,
def: &ast::StructDef,
ty_params: &ast::Generics) {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
let ctor_id = match def.ctor_id {
Some(node_id) => node_id,
e: DxrVisitorEnv,
enum_definition: &ast::EnumDef,
ty_params: &ast::Generics) {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
match self.span.sub_span_after_keyword(item.span, keywords::Enum) {
Some(sub_span) => self.fmt.enum_str(item.span,
Some(sub_span),
generics: &ast::Generics,
trait_refs: &Vec<ast::TraitRef>,
methods: &Vec<ast::TraitMethod>) {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
self.fmt.trait_str(item.span,
item: &ast::Item, // The module in question, represented as an item.
e: DxrVisitorEnv,
m: &ast::Mod) {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
let cm = self.sess.codemap();
let filename = cm.span_to_filename(m.inner);
self.process_trait(item, e, generics, trait_refs, methods),
ast::ItemMod(ref m) => self.process_mod(item, e, m),
ast::ItemTy(ty, ref ty_params) => {
- let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
- let value = ty_to_str(&*ty);
+ let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
+ let value = ty_to_string(&*ty);
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
self.fmt.typedef_str(item.span,
sub_span,
return
}
- let id = String::from_str("$").append(ex.id.to_str().as_slice());
+ let id = String::from_str("$").append(ex.id.to_string().as_slice());
self.process_formals(&decl.inputs, id.as_slice(), e);
// walk arg and return types
def::DefBinding(id, _) => self.fmt.variable_str(p.span,
sub_span,
id,
- path_to_str(p).as_slice(),
+ path_to_string(p).as_slice(),
value.as_slice(),
""),
def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind,
for &(id, ref p, ref immut, _) in self.collected_paths.iter() {
let value = if *immut { value.to_owned() } else { "<mutable>".to_owned() };
let types = self.analysis.ty_cx.node_types.borrow();
- let typ = ppaux::ty_to_str(&self.analysis.ty_cx, *types.get(&(id as uint)));
+ let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&(id as uint)));
// Get the span only for the name of the variable (I hope the path
// is only ever a variable name, but who knows?).
let sub_span = self.span.span_for_last_ident(p.span);
self.fmt.variable_str(p.span,
sub_span,
id,
- path_to_str(p).as_slice(),
+ path_to_string(p).as_slice(),
value.as_slice(),
typ.as_slice());
}
return;
}
- let (cratename, crateid) = match attr::find_crateid(krate.attrs.as_slice()) {
- Some(crateid) => (crateid.name.clone(), crateid.to_str()),
+ let cratename = match attr::find_crate_name(krate.attrs.as_slice()) {
+ Some(name) => name.get().to_string(),
None => {
info!("Could not find crate name, using 'unknown_crate'");
- (String::from_str("unknown_crate"),"unknown_crate".to_owned())
+ String::from_str("unknown_crate")
},
};
- info!("Dumping crate {} ({})", cratename, crateid);
+ info!("Dumping crate {}", cratename);
// find a path to dump our data to
let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {
// the local case they can be overridden in one block and there is no nice way
// to refer to such a scope in english, so we just hack it by appending the
// variable def's node id
- let qualname = String::from_str(name).append("$").append(id.to_str().as_slice());
+ let qualname = String::from_str(name).append("$").append(id.to_string().as_slice());
self.check_and_record(Variable,
span,
sub_span,
use middle::ty_fold::{TypeFoldable, TypeFolder};
use util::ppaux::Repr;
-use std::iter::Chain;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
}
pub fn with_method_from(self, substs: &Substs) -> Substs {
- self.with_method((*substs.types.get_vec(FnSpace)).clone(),
- (*substs.regions().get_vec(FnSpace)).clone())
+ self.with_method(Vec::from_slice(substs.types.get_slice(FnSpace)),
+ Vec::from_slice(substs.regions().get_slice(FnSpace)))
}
pub fn with_method(self,
*/
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
pub struct VecPerParamSpace<T> {
- vecs: (Vec<T>, Vec<T>, Vec<T>)
+ // This was originally represented as a tuple with one Vec<T> for
+ // each variant of ParamSpace, and that remains the abstraction
+ // that it provides to its clients.
+ //
+ // Here is how the representation corresponds to the abstraction
+ // i.e. the "abstraction function" AF:
+ //
+ // AF(self) = (self.content.slice_to(self.type_limit),
+ // self.content.slice(self.type_limit, self.self_limit),
+ // self.content.slice_from(self.self_limit))
+ type_limit: uint,
+ self_limit: uint,
+ content: Vec<T>,
+}
+
+impl<T:Clone> VecPerParamSpace<T> {
+ pub fn push_all(&mut self, space: ParamSpace, values: &[T]) {
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
+ for t in values.iter() {
+ self.push(space, t.clone());
+ }
+ }
}
impl<T> VecPerParamSpace<T> {
+ fn limits(&self, space: ParamSpace) -> (uint, uint) {
+ match space {
+ TypeSpace => (0, self.type_limit),
+ SelfSpace => (self.type_limit, self.self_limit),
+ FnSpace => (self.self_limit, self.content.len()),
+ }
+ }
+
pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace {
- vecs: (Vec::new(), Vec::new(), Vec::new())
+ type_limit: 0,
+ self_limit: 0,
+ content: Vec::new()
}
}
}
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
+ let type_limit = t.len();
+ let self_limit = t.len() + s.len();
+ let mut content = t;
+ content.push_all_move(s);
+ content.push_all_move(f);
VecPerParamSpace {
- vecs: (t, s, f)
+ type_limit: type_limit,
+ self_limit: self_limit,
+ content: content,
}
}
result
}
+ /// Appends `value` to the vector associated with `space`.
+ ///
+ /// Unlike the `push` method in `Vec`, this should not be assumed
+ /// to be a cheap operation (even when amortized over many calls).
pub fn push(&mut self, space: ParamSpace, value: T) {
- self.get_mut_vec(space).push(value);
+ let (_, limit) = self.limits(space);
+ match space {
+ TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
+ SelfSpace => { self.self_limit += 1; }
+ FnSpace => {}
+ }
+ self.content.insert(limit, value);
+ }
+
+ pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
+ let (start, limit) = self.limits(space);
+ if start == limit {
+ None
+ } else {
+ match space {
+ TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
+ SelfSpace => { self.self_limit -= 1; }
+ FnSpace => {}
+ }
+ self.content.remove(limit - 1)
+ }
+ }
+
+ pub fn truncate(&mut self, space: ParamSpace, len: uint) {
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
+ while self.len(space) > len {
+ self.pop(space);
+ }
+ }
+
+ pub fn replace(&mut self, space: ParamSpace, elems: Vec<T>) {
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
+ self.truncate(space, 0);
+ for t in elems.move_iter() {
+ self.push(space, t);
+ }
}
pub fn get_self<'a>(&'a self) -> Option<&'a T> {
- let v = self.get_vec(SelfSpace);
+ let v = self.get_slice(SelfSpace);
assert!(v.len() <= 1);
- if v.len() == 0 { None } else { Some(v.get(0)) }
+ if v.len() == 0 { None } else { Some(&v[0]) }
}
pub fn len(&self, space: ParamSpace) -> uint {
- self.get_vec(space).len()
+ self.get_slice(space).len()
+ }
+
+ pub fn is_empty_in(&self, space: ParamSpace) -> bool {
+ self.len(space) == 0
}
- pub fn get_vec<'a>(&'a self, space: ParamSpace) -> &'a Vec<T> {
- self.vecs.get(space as uint).unwrap()
+ pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] {
+ let (start, limit) = self.limits(space);
+ self.content.slice(start, limit)
}
- pub fn get_mut_vec<'a>(&'a mut self, space: ParamSpace) -> &'a mut Vec<T> {
- self.vecs.get_mut(space as uint).unwrap()
+ fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] {
+ let (start, limit) = self.limits(space);
+ self.content.mut_slice(start, limit)
}
pub fn opt_get<'a>(&'a self,
space: ParamSpace,
index: uint)
-> Option<&'a T> {
- let v = self.get_vec(space);
- if index < v.len() { Some(v.get(index)) } else { None }
+ let v = self.get_slice(space);
+ if index < v.len() { Some(&v[index]) } else { None }
}
pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
- self.get_vec(space).get(index)
+ &self.get_slice(space)[index]
}
pub fn get_mut<'a>(&'a mut self,
space: ParamSpace,
index: uint) -> &'a mut T {
- self.get_mut_vec(space).get_mut(index)
+ &mut self.get_mut_slice(space)[index]
}
- pub fn iter<'a>(&'a self) -> Chain<Items<'a,T>,
- Chain<Items<'a,T>,
- Items<'a,T>>> {
- let (ref r, ref s, ref f) = self.vecs;
- r.iter().chain(s.iter().chain(f.iter()))
+ pub fn iter<'a>(&'a self) -> Items<'a,T> {
+ self.content.iter()
}
- pub fn all_vecs(&self, pred: |&Vec<T>| -> bool) -> bool {
- self.vecs.iter().all(pred)
+ pub fn all_vecs(&self, pred: |&[T]| -> bool) -> bool {
+ let spaces = [TypeSpace, SelfSpace, FnSpace];
+ spaces.iter().all(|&space| { pred(self.get_slice(space)) })
}
pub fn all(&self, pred: |&T| -> bool) -> bool {
}
pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
- VecPerParamSpace::new(self.vecs.ref0().iter().map(|p| pred(p)).collect(),
- self.vecs.ref1().iter().map(|p| pred(p)).collect(),
- self.vecs.ref2().iter().map(|p| pred(p)).collect())
+ // FIXME (#15418): this could avoid allocating the intermediate
+ // Vec's, but note that the values of type_limit and self_limit
+ // also need to be kept in sync during construction.
+ VecPerParamSpace::new(
+ self.get_slice(TypeSpace).iter().map(|p| pred(p)).collect(),
+ self.get_slice(SelfSpace).iter().map(|p| pred(p)).collect(),
+ self.get_slice(FnSpace).iter().map(|p| pred(p)).collect())
}
pub fn map_rev<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
* can be run to a fixed point
*/
- let mut fns: Vec<U> = self.vecs.ref2().iter().rev().map(|p| pred(p)).collect();
+ let mut fns: Vec<U> = self.get_slice(FnSpace).iter().rev().map(|p| pred(p)).collect();
// NB: Calling foo.rev().map().rev() causes the calls to map
// to occur in the wrong order. This was somewhat surprising
// to me, though it makes total sense.
fns.reverse();
- let mut selfs: Vec<U> = self.vecs.ref1().iter().rev().map(|p| pred(p)).collect();
+ let mut selfs: Vec<U> = self.get_slice(SelfSpace).iter().rev().map(|p| pred(p)).collect();
selfs.reverse();
- let mut tys: Vec<U> = self.vecs.ref0().iter().rev().map(|p| pred(p)).collect();
+ let mut tys: Vec<U> = self.get_slice(TypeSpace).iter().rev().map(|p| pred(p)).collect();
tys.reverse();
VecPerParamSpace::new(tys, selfs, fns)
}
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
- self.vecs
+ // FIXME (#15418): this does two traversals when in principle
+ // one would suffice. i.e. change to use `move_iter`.
+ let VecPerParamSpace { type_limit, self_limit, content } = self;
+ let mut i = 0;
+ let (prefix, fn_vec) = content.partition(|_| {
+ let on_left = i < self_limit;
+ i += 1;
+ on_left
+ });
+
+ let mut i = 0;
+ let (type_vec, self_vec) = prefix.partition(|_| {
+ let on_left = i < type_limit;
+ i += 1;
+ on_left
+ });
+
+ (type_vec, self_vec, fn_vec)
}
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
-> VecPerParamSpace<T>
{
- assert!(self.get_vec(space).is_empty());
- *self.get_mut_vec(space) = vec;
+ assert!(self.is_empty_in(space));
+ self.replace(space, vec);
self
}
}
use middle::trans::debuginfo;
use middle::ty;
use util::common::indenter;
-use util::ppaux::{Repr, vec_map_to_str};
+use util::ppaux::{Repr, vec_map_to_string};
use std;
use std::collections::HashMap;
bcx.to_str(),
m.repr(bcx.tcx()),
col,
- bcx.val_to_str(val));
+ bcx.val_to_string(val));
let _indenter = indenter();
m.iter().map(|br| {
- match br.pats.get(col).node {
- ast::PatIdent(_, ref path1, Some(inner)) => {
- let pats = Vec::from_slice(br.pats.slice(0u, col))
- .append((vec!(inner))
- .append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
-
- let mut bound_ptrs = br.bound_ptrs.clone();
- bound_ptrs.push((path1.node, val));
- Match {
- pats: pats,
- data: &*br.data,
- bound_ptrs: bound_ptrs
- }
- }
- _ => Match {
- pats: br.pats.clone(),
- data: &*br.data,
- bound_ptrs: br.bound_ptrs.clone()
+ let mut bound_ptrs = br.bound_ptrs.clone();
+ let mut pat = *br.pats.get(col);
+ loop {
+ pat = match pat.node {
+ ast::PatIdent(_, ref path, Some(inner)) => {
+ bound_ptrs.push((path.node, val));
+ inner.clone()
+ },
+ _ => break
}
}
+
+ let mut pats = br.pats.clone();
+ *pats.get_mut(col) = pat;
+ Match {
+ pats: pats,
+ data: &*br.data,
+ bound_ptrs: bound_ptrs
+ }
}).collect()
}
bcx.to_str(),
m.repr(bcx.tcx()),
col,
- bcx.val_to_str(val));
+ bcx.val_to_string(val));
let _indenter = indenter();
m.iter().filter_map(|br| {
bcx.to_str(),
m.repr(bcx.tcx()),
col,
- bcx.val_to_str(val));
+ bcx.val_to_string(val));
let _indenter = indenter();
// Collect all of the matches that can match against anything.
m.repr(bcx.tcx()),
*opt,
col,
- bcx.val_to_str(val));
+ bcx.val_to_string(val));
let _indenter = indenter();
let ctor = match opt {
// matches should fit that sort of pattern or NONE (however, some of the
// matches may be wildcards like _ or identifiers).
macro_rules! any_pat (
- ($m:expr, $pattern:pat) => (
+ ($m:expr, $col:expr, $pattern:pat) => (
($m).iter().any(|br| {
- match br.pats.get(col).node {
+ match br.pats.get($col).node {
$pattern => true,
_ => false
}
)
fn any_uniq_pat(m: &[Match], col: uint) -> bool {
- any_pat!(m, ast::PatBox(_))
+ any_pat!(m, col, ast::PatBox(_))
}
fn any_region_pat(m: &[Match], col: uint) -> bool {
- any_pat!(m, ast::PatRegion(_))
+ any_pat!(m, col, ast::PatRegion(_))
}
fn any_irrefutable_adt_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
let pat = *br.pats.get(col);
match pat.node {
ast::PatTup(_) => true,
- ast::PatEnum(..) | ast::PatIdent(_, _, None) | ast::PatStruct(..) =>
+ ast::PatStruct(..) => {
+ match bcx.tcx().def_map.borrow().find(&pat.id) {
+ Some(&def::DefVariant(..)) => false,
+ _ => true,
+ }
+ }
+ ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
match bcx.tcx().def_map.borrow().find(&pat.id) {
Some(&def::DefFn(..)) |
Some(&def::DefStruct(..)) => true,
_ => false
- },
+ }
+ }
_ => false
}
})
let did = langcall(cx,
None,
format!("comparison of `{}`",
- cx.ty_to_str(rhs_t)).as_slice(),
+ cx.ty_to_string(rhs_t)).as_slice(),
StrEqFnLangItem);
callee::trans_lang_call(cx, did, [lhs, rhs], None)
}
}
}
-fn insert_lllocals<'a>(mut bcx: &'a Block<'a>,
- bindings_map: &BindingsMap)
+fn insert_lllocals<'a>(mut bcx: &'a Block<'a>, bindings_map: &BindingsMap,
+ cs: Option<cleanup::ScopeId>)
-> &'a Block<'a> {
/*!
* For each binding in `data.bindings_map`, adds an appropriate entry into
};
let datum = Datum::new(llval, binding_info.ty, Lvalue);
+ match cs {
+ Some(cs) => bcx.fcx.schedule_drop_and_zero_mem(cs, llval, binding_info.ty),
+ _ => {}
+ }
debug!("binding {:?} to {}",
binding_info.id,
- bcx.val_to_str(llval));
+ bcx.val_to_string(llval));
bcx.fcx.lllocals.borrow_mut().insert(binding_info.id, datum);
if bcx.sess().opts.debuginfo == FullDebugInfo {
-> &'b Block<'b> {
debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
bcx.to_str(),
- bcx.expr_to_str(guard_expr),
+ bcx.expr_to_string(guard_expr),
m.repr(bcx.tcx()),
- vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
+ vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
let _indenter = indenter();
- let mut bcx = insert_lllocals(bcx, &data.bindings_map);
+ let mut bcx = insert_lllocals(bcx, &data.bindings_map, None);
let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
let val = val.to_llbool(bcx);
debug!("compile_submatch(bcx={}, m={}, vals={})",
bcx.to_str(),
m.repr(bcx.tcx()),
- vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
+ vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
let _indenter = indenter();
let _icx = push_ctxt("match::compile_submatch");
let mut bcx = bcx;
debug!("options={:?}", opts);
let mut kind = no_branch;
let mut test_val = val;
- debug!("test_val={}", bcx.val_to_str(test_val));
+ debug!("test_val={}", bcx.val_to_string(test_val));
if opts.len() > 0u {
match *opts.get(0) {
var(_, ref repr, _) => {
for arm_data in arm_datas.iter() {
let mut bcx = arm_data.bodycx;
- // insert bindings into the lllocals map
- bcx = insert_lllocals(bcx, &arm_data.bindings_map);
+ // insert bindings into the lllocals map and add cleanups
+ let cs = fcx.push_custom_cleanup_scope();
+ bcx = insert_lllocals(bcx, &arm_data.bindings_map, Some(cleanup::CustomScope(cs)));
bcx = expr::trans_into(bcx, &*arm_data.arm.body, dest);
+ bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cs);
arm_cxs.push(bcx);
}
use syntax::ast;
use syntax::attr;
use syntax::attr::IntType;
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
type Hint = attr::ReprAttr;
StructWrappedNullablePointer {
pub nonnull: Struct,
pub nndiscr: Disr,
- pub ptrfield: uint,
+ pub ptrfield: PointerField,
pub nullfields: Vec<ty::t>,
}
}
/// Decides how to represent a given type.
pub fn represent_type(cx: &CrateContext, t: ty::t) -> Rc<Repr> {
- debug!("Representing: {}", ty_to_str(cx.tcx(), t));
+ debug!("Representing: {}", ty_to_string(cx.tcx(), t));
match cx.adt_reprs.borrow().find(&t) {
Some(repr) => return repr.clone(),
None => {}
let mut discr = 0;
while discr < 2 {
if cases.get(1 - discr).is_zerolen(cx) {
+ let st = mk_struct(cx, cases.get(discr).tys.as_slice(), false);
match cases.get(discr).find_ptr() {
+ Some(ThinPointer(_)) if st.fields.len() == 1 => {
+ return RawNullablePointer {
+ nndiscr: discr as Disr,
+ nnty: *st.fields.get(0),
+ nullfields: cases.get(1 - discr).tys.clone()
+ };
+ }
Some(ptrfield) => {
- let st = mk_struct(cx, cases.get(discr).tys.as_slice(),
- false);
-
- return if st.fields.len() == 1 {
- RawNullablePointer {
- nndiscr: discr as Disr,
- nnty: *st.fields.get(0),
- nullfields: cases.get(1 - discr).tys.clone()
- }
- } else {
- StructWrappedNullablePointer {
- nndiscr: discr as Disr,
- nonnull: st,
- ptrfield: ptrfield,
- nullfields: cases.get(1 - discr).tys.clone()
- }
+ return StructWrappedNullablePointer {
+ nndiscr: discr as Disr,
+ nonnull: st,
+ ptrfield: ptrfield,
+ nullfields: cases.get(1 - discr).tys.clone()
};
}
None => { }
}
// this should probably all be in ty
-struct Case { discr: Disr, tys: Vec<ty::t> }
+struct Case {
+ discr: Disr,
+ tys: Vec<ty::t>
+}
+
+
+#[deriving(Show)]
+pub enum PointerField {
+ ThinPointer(uint),
+ FatPointer(uint, uint)
+}
+
impl Case {
fn is_zerolen(&self, cx: &CrateContext) -> bool {
mk_struct(cx, self.tys.as_slice(), false).size == 0
}
- fn find_ptr(&self) -> Option<uint> {
- self.tys.iter().position(|&ty| {
+ fn find_ptr(&self) -> Option<PointerField> {
+ use back::abi::{fn_field_code, slice_elt_base, trt_field_box};
+
+ for (i, &ty) in self.tys.iter().enumerate() {
match ty::get(ty).sty {
- ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
- ty::ty_vec(_, None) | ty::ty_str| ty::ty_trait(..) => false,
- _ => true,
+ // &T/&mut T could either be a thin or fat pointer depending on T
+ ty::ty_rptr(_, ty::mt { ty, .. }) => match ty::get(ty).sty {
+ // &[T] and &str are a pointer and length pair
+ ty::ty_vec(_, None) | ty::ty_str => return Some(FatPointer(i, slice_elt_base)),
+
+ // &Trait/&mut Trait are a pair of pointers: the actual object and a vtable
+ ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)),
+
+ // Any other &T/&mut T is just a pointer
+ _ => return Some(ThinPointer(i))
+ },
+
+ // Box<T> could either be a thin or fat pointer depending on T
+ ty::ty_uniq(t) => match ty::get(t).sty {
+ // Box<[T]>/Box<str> might be FatPointer in a post DST world
+ ty::ty_vec(_, None) | ty::ty_str => continue,
+
+ // Box<Trait> is a pair of pointers: the actual object and a vtable
+ ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)),
+
+ // Any other Box<T> is just a pointer
+ _ => return Some(ThinPointer(i))
},
- ty::ty_box(..) | ty::ty_bare_fn(..) => true,
- // Is that everything? Would closures or slices qualify?
- _ => false
+
+ // Gc<T> is just a pointer
+ ty::ty_box(..) => return Some(ThinPointer(i)),
+
+ // Functions are just pointers
+ ty::ty_bare_fn(..) => return Some(ThinPointer(i)),
+
+ // Closures are a pair of pointers: the code and environment
+ ty::ty_closure(..) => return Some(FatPointer(i, fn_field_code)),
+
+ // Anything else is not a pointer
+ _ => continue
+
}
- })
+ }
+
+ None
}
}
val = ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty));
signed = false;
}
- StructWrappedNullablePointer { nonnull: ref nonnull, nndiscr, ptrfield, .. } => {
- val = struct_wrapped_nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee);
+ StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
+ val = struct_wrapped_nullable_bitdiscr(bcx, nndiscr, ptrfield, scrutinee);
signed = false;
}
}
}
}
-fn struct_wrapped_nullable_bitdiscr(bcx: &Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uint,
+fn struct_wrapped_nullable_bitdiscr(bcx: &Block, nndiscr: Disr, ptrfield: PointerField,
scrutinee: ValueRef) -> ValueRef {
- let llptr = Load(bcx, GEPi(bcx, scrutinee, [0, ptrfield]));
+ let llptrptr = match ptrfield {
+ ThinPointer(field) => GEPi(bcx, scrutinee, [0, field]),
+ FatPointer(field, pair) => GEPi(bcx, scrutinee, [0, field, pair])
+ };
+ let llptr = Load(bcx, llptrptr);
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
- let llptrty = type_of::type_of(bcx.ccx(), *nonnull.fields.get(ptrfield));
- ICmp(bcx, cmp, llptr, C_null(llptrty))
+ ICmp(bcx, cmp, llptr, C_null(val_ty(llptr)))
}
/// Helper for cases where the discriminant is simply loaded.
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => {
assert!(discr == 0 || discr == 1);
- _match::single_result(Result::new(bcx, C_i1(bcx.ccx(), discr != 0)))
+ _match::single_result(Result::new(bcx, C_bool(bcx.ccx(), discr != 0)))
}
}
}
}
Univariant(ref st, true) => {
assert_eq!(discr, 0);
- Store(bcx, C_bool(bcx.ccx(), true),
+ Store(bcx, C_u8(bcx.ccx(), 1),
GEPi(bcx, val, [0, st.fields.len() - 1]))
}
Univariant(..) => {
}
StructWrappedNullablePointer { 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.get(ptrfield));
+ let (llptrptr, llptrty) = match ptrfield {
+ ThinPointer(field) =>
+ (GEPi(bcx, val, [0, field]),
+ type_of::type_of(bcx.ccx(), *nonnull.fields.get(field))),
+ FatPointer(field, pair) => {
+ let v = GEPi(bcx, val, [0, field, pair]);
+ (v, val_ty(v).element_type())
+ }
+ };
Store(bcx, C_null(llptrty), llptrptr)
}
}
}
}
StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
- if is_null(const_struct_field(ccx, val, ptrfield)) {
+ let (idx, sub_idx) = match ptrfield {
+ ThinPointer(field) => (field, None),
+ FatPointer(field, pair) => (field, Some(pair))
+ };
+ if is_null(const_struct_field(ccx, val, idx, sub_idx)) {
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
(1 - nndiscr) as Disr
} else {
_discr: Disr, ix: uint) -> 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),
+ Univariant(..) => const_struct_field(ccx, val, ix, None),
+ General(..) => const_struct_field(ccx, val, ix + 1, None),
RawNullablePointer { .. } => {
assert_eq!(ix, 0);
val
}
- StructWrappedNullablePointer{ .. } => const_struct_field(ccx, val, ix)
+ StructWrappedNullablePointer{ .. } => const_struct_field(ccx, val, ix, None)
}
}
/// Extract field of struct-like const, skipping our alignment padding.
-fn const_struct_field(ccx: &CrateContext, val: ValueRef, ix: uint)
+fn const_struct_field(ccx: &CrateContext, val: ValueRef, ix: uint, sub_idx: Option<uint>)
-> ValueRef {
// Get the ix-th non-undef element of the struct.
let mut real_ix = 0; // actual position in the struct
let mut field;
loop {
loop {
- field = const_get_elt(ccx, val, [real_ix]);
+ field = match sub_idx {
+ Some(si) => const_get_elt(ccx, val, [real_ix, si as u32]),
+ None => const_get_elt(ccx, val, [real_ix])
+ };
if !is_undef(field) {
break;
}
use driver::config;
use driver::config::{NoDebugInfo, FullDebugInfo};
use driver::session::Session;
-use driver::driver::OutputFilenames;
use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
use lib::llvm::{llvm, Vector};
use middle::ty;
use middle::typeck;
use util::common::indenter;
-use util::ppaux::{Repr, ty_to_str};
+use util::ppaux::{Repr, ty_to_string};
use util::sha2::Sha256;
use util::nodemap::NodeMap;
Ok(id) => id,
Err(s) => {
bcx.sess().fatal(format!("allocation of `{}` {}",
- bcx.ty_to_str(info_ty),
+ bcx.ty_to_string(info_ty),
s).as_slice());
}
}
// We don't need to do actual comparisons for nil.
// () == () holds but () < () does not.
match op {
- ast::BiEq | ast::BiLe | ast::BiGe => return C_i1(cx.ccx(), true),
- ast::BiNe | ast::BiLt | ast::BiGt => return C_i1(cx.ccx(), false),
+ ast::BiEq | ast::BiLe | ast::BiGe => return C_bool(cx.ccx(), true),
+ ast::BiNe | ast::BiLt | ast::BiGt => return C_bool(cx.ccx(), false),
// refinements would be nice
_ => die(cx)
}
let variant_cx =
fcx.new_temp_block(
format!("enum-iter-variant-{}",
- variant.disr_val.to_str().as_slice())
+ variant.disr_val.to_string().as_slice())
.as_slice());
match adt::trans_case(cx, &*repr, variant.disr_val) {
_match::single_result(r) => {
}
_ => {
cx.sess().bug(format!("fail-if-zero on unexpected type: {}",
- ty_to_str(cx.tcx(), rhs_t)).as_slice());
+ ty_to_string(cx.tcx(), rhs_t)).as_slice());
}
};
let bcx = with_cond(cx, is_zero, |bcx| {
debug!("invoke at ???");
}
Some(id) => {
- debug!("invoke at {}", bcx.tcx().map.node_to_str(id));
+ debug!("invoke at {}", bcx.tcx().map.node_to_string(id));
}
}
pub fn load_if_immediate(cx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = push_ctxt("load_if_immediate");
- if type_is_immediate(cx.ccx(), t) { return Load(cx, v); }
+ if type_is_immediate(cx.ccx(), t) { return load_ty(cx, v, t); }
return v;
}
+pub fn load_ty(cx: &Block, ptr: ValueRef, t: ty::t) -> ValueRef {
+ /*!
+ * Helper for loading values from memory. Does the necessary conversion if
+ * the in-memory type differs from the type used for SSA values. Also
+ * handles various special cases where the type gives us better information
+ * about what we are loading.
+ */
+ if type_is_zero_size(cx.ccx(), t) {
+ C_undef(type_of::type_of(cx.ccx(), t))
+ } else if ty::type_is_bool(t) {
+ Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, lib::llvm::False), Type::i1(cx.ccx()))
+ } else if ty::type_is_char(t) {
+ // a char is a unicode codepoint, and so takes values from 0
+ // to 0x10FFFF inclusive only.
+ LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, lib::llvm::False)
+ } else {
+ Load(cx, ptr)
+ }
+}
+
+pub fn store_ty(cx: &Block, v: ValueRef, dst: ValueRef, t: ty::t) {
+ /*!
+ * Helper for storing values in memory. Does the necessary conversion if
+ * the in-memory type differs from the type used for SSA values.
+ */
+ if ty::type_is_bool(t) {
+ Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
+ } else {
+ Store(cx, v, dst);
+ };
+}
+
pub fn ignore_lhs(_bcx: &Block, local: &ast::Local) -> bool {
match local.pat.node {
ast::PatWild => true, _ => false
let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
let size = IntCast(cx, n_bytes, ccx.int_type);
let align = C_i32(ccx, align as i32);
- let volatile = C_i1(ccx, false);
+ let volatile = C_bool(ccx, false);
Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []);
}
let llzeroval = C_u8(ccx, 0);
let size = machine::llsize_of(ccx, ty);
let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32);
- let volatile = C_i1(ccx, false);
+ let volatile = C_bool(ccx, false);
b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []);
}
llvm::LLVMGetParam(fcx.llfn, 0)
} else {
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
- let bcx = fcx.entry_bcx.borrow().clone().unwrap();
- Alloca(bcx, lloutputtype, "__make_return_pointer")
+ AllocaFcx(fcx, lloutputtype, "__make_return_pointer")
}
}
}
if id == -1 {
"".to_string()
} else {
- ccx.tcx.map.path_to_str(id).to_string()
+ ccx.tcx.map.path_to_string(id).to_string()
},
id, param_substs.repr(ccx.tcx()));
llfn: llfndecl,
llenv: None,
llretptr: Cell::new(None),
- entry_bcx: RefCell::new(None),
alloca_insert_pt: Cell::new(None),
llreturn: Cell::new(None),
personality: Cell::new(None),
/// and allocating space for the return pointer.
pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
skip_retptr: bool,
- output_type: ty::t) {
+ output_type: ty::t) -> &'a Block<'a> {
let entry_bcx = fcx.new_temp_block("entry-block");
- *fcx.entry_bcx.borrow_mut() = Some(entry_bcx);
-
// Use a dummy instruction as the insertion point for all allocas.
// This is later removed in FunctionContext::cleanup.
fcx.alloca_insert_pt.set(Some(unsafe {
fcx.llretptr.set(Some(make_return_pointer(fcx, substd_output_type)));
}
}
+
+ entry_bcx
}
// NB: must keep 4 fns in sync:
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
// and builds the return block.
pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
- last_bcx: &'a Block<'a>) {
+ last_bcx: &'a Block<'a>,
+ retty: ty::t) {
let _icx = push_ctxt("finish_fn");
+ // This shouldn't need to recompute the return type,
+ // as new_fn_ctxt did it already.
+ let substd_retty = retty.substp(fcx.ccx.tcx(), fcx.param_substs);
+
let ret_cx = match fcx.llreturn.get() {
Some(llreturn) => {
if !last_bcx.terminated.get() {
}
None => last_bcx
};
- build_return_block(fcx, ret_cx);
+ build_return_block(fcx, ret_cx, substd_retty);
debuginfo::clear_source_location(fcx);
fcx.cleanup();
}
// Builds the return block for a function.
-pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
+pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
// Return the value if this function immediate; otherwise, return void.
if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer {
return RetVoid(ret_cx);
retptr.erase_from_parent();
}
- retval
+ if ty::type_is_bool(retty) {
+ Trunc(ret_cx, retval, Type::i1(fcx.ccx))
+ } else {
+ retval
+ }
}
// Otherwise, load the return value from the ret slot
- None => Load(ret_cx, fcx.llretptr.get().unwrap())
+ None => load_ty(ret_cx, fcx.llretptr.get().unwrap(), retty)
};
-
Ret(ret_cx, retval);
}
param_substs,
Some(body.span),
&arena);
- init_function(&fcx, false, output_type);
+ let mut bcx = init_function(&fcx, false, output_type);
// cleanup scope for the incoming arguments
let arg_scope = fcx.push_custom_cleanup_scope();
- // Create the first basic block in the function and keep a handle on it to
- // pass to finish_fn later.
- let bcx_top = fcx.entry_bcx.borrow().clone().unwrap();
- let mut bcx = bcx_top;
let block_ty = node_id_type(bcx, body.id);
// Set up arguments to the function.
}
// Insert the mandatory first few basic blocks before lltop.
- finish_fn(&fcx, bcx);
+ finish_fn(&fcx, bcx, output_type);
}
// trans_fn: creates an LLVM function corresponding to a source language
param_substs: ¶m_substs,
id: ast::NodeId,
attrs: &[ast::Attribute]) {
- let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id).to_string());
+ let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_string(id).to_string());
debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
let _icx = push_ctxt("trans_fn");
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
_ => ccx.sess().bug(
format!("trans_enum_variant_or_tuple_like_struct: \
unexpected ctor return type {}",
- ty_to_str(ccx.tcx(), ctor_ty)).as_slice())
+ ty_to_string(ccx.tcx(), ctor_ty)).as_slice())
};
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
param_substs, None, &arena);
- init_function(&fcx, false, result_ty);
+ let bcx = init_function(&fcx, false, result_ty);
let arg_tys = ty::ty_fn_args(ctor_ty);
let arg_datums = create_datums_for_fn_args(&fcx, arg_tys.as_slice());
- let bcx = fcx.entry_bcx.borrow().clone().unwrap();
-
if !type_is_zero_size(fcx.ccx, result_ty) {
let repr = adt::represent_type(ccx, result_ty);
adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
}
}
- finish_fn(&fcx, bcx);
+ finish_fn(&fcx, bcx, result_ty);
}
fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
_ => ccx.tcx.map.with_path(id, |mut path| {
if attr::contains_name(attrs, "no_mangle") {
// Don't mangle
- path.last().unwrap().to_str()
+ path.last().unwrap().to_string()
} else {
match weak_lang_items::link_name(attrs) {
Some(name) => name.get().to_string(),
}.as_slice());
let llmeta = C_bytes(cx, compressed.as_slice());
let llconst = C_struct(cx, [llmeta], false);
- let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,
- cx.link_meta.crateid.version_or_default(), cx.link_meta.crate_hash);
+ let name = format!("rust_metadata_{}_{}",
+ cx.link_meta.crate_name,
+ cx.link_meta.crate_hash);
let llglobal = name.with_c_str(|buf| {
unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod, val_ty(llconst).to_ref(), buf)
}
pub fn trans_crate(krate: ast::Crate,
- analysis: CrateAnalysis,
- output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
- let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
+ analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
+ let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, name, .. } = analysis;
// Before we touch LLVM, make sure that multithreading is enabled.
unsafe {
}
}
- let link_meta = link::build_link_meta(&krate,
- output.out_filestem.as_slice());
+ let link_meta = link::build_link_meta(&tcx.sess, &krate, name);
// Append ".rs" to crate name as LLVM module identifier.
//
// crashes if the module identifier is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
- let mut llmod_id = link_meta.crateid.name.clone();
+ let mut llmod_id = link_meta.crate_name.clone();
llmod_id.push_str(".rs");
let ccx = CrateContext::new(llmod_id.as_slice(), tcx, exp_map2,
check_not_terminated(cx);
terminate(cx, "Invoke");
debug!("Invoke({} with arguments ({}))",
- cx.val_to_str(fn_),
- args.iter().map(|a| cx.val_to_str(*a)).collect::<Vec<String>>().connect(", "));
+ cx.val_to_string(fn_),
+ args.iter().map(|a| cx.val_to_string(*a)).collect::<Vec<String>>().connect(", "));
B(cx).invoke(fn_, args, then, catch, attributes)
}
self.count_insn("invoke");
debug!("Invoke {} with args ({})",
- self.ccx.tn.val_to_str(llfn),
+ self.ccx.tn.val_to_string(llfn),
args.iter()
- .map(|&v| self.ccx.tn.val_to_str(v))
+ .map(|&v| self.ccx.tn.val_to_string(v))
.collect::<Vec<String>>()
.connect(", "));
pub fn store(&self, val: ValueRef, ptr: ValueRef) {
debug!("Store {} -> {}",
- self.ccx.tn.val_to_str(val),
- self.ccx.tn.val_to_str(ptr));
+ self.ccx.tn.val_to_string(val),
+ self.ccx.tn.val_to_string(ptr));
assert!(self.llbuilder.is_not_null());
self.count_insn("store");
unsafe {
pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) {
debug!("Store {} -> {}",
- self.ccx.tn.val_to_str(val),
- self.ccx.tn.val_to_str(ptr));
+ self.ccx.tn.val_to_string(val),
+ self.ccx.tn.val_to_string(ptr));
assert!(self.llbuilder.is_not_null());
self.count_insn("store.volatile");
unsafe {
pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
debug!("Store {} -> {}",
- self.ccx.tn.val_to_str(val),
- self.ccx.tn.val_to_str(ptr));
+ self.ccx.tn.val_to_string(val),
+ self.ccx.tn.val_to_string(ptr));
self.count_insn("store.atomic");
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
if self.ccx.sess().asm_comments() {
let s = format!("{} ({})",
text,
- self.ccx.sess().codemap().span_to_str(sp));
+ self.ccx.sess().codemap().span_to_string(sp));
debug!("{}", s.as_slice());
self.add_comment(s.as_slice());
}
else { lib::llvm::False };
let argtys = inputs.iter().map(|v| {
- debug!("Asm Input Type: {:?}", self.ccx.tn.val_to_str(*v));
+ debug!("Asm Input Type: {:?}", self.ccx.tn.val_to_string(*v));
val_ty(*v)
}).collect::<Vec<_>>();
- debug!("Asm Output Type: {:?}", self.ccx.tn.type_to_str(output));
+ debug!("Asm Output Type: {:?}", self.ccx.tn.type_to_string(output));
let fty = Type::func(argtys.as_slice(), &output);
unsafe {
let v = llvm::LLVMInlineAsm(
self.count_insn("call");
debug!("Call {} with args ({})",
- self.ccx.tn.val_to_str(llfn),
+ self.ccx.tn.val_to_string(llfn),
args.iter()
- .map(|&v| self.ccx.tn.val_to_str(v))
+ .map(|&v| self.ccx.tn.val_to_string(v))
.collect::<Vec<String>>()
.connect(", "));
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let size = ty_size(ty);
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let align = ty_align(ty);
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
- let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::indirect(ty, Some(StructRetAttribute))
*offset += align_up_to(size, align * 8) / 8;
if is_reg_ty(ty) {
- let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::direct(
}
}
} else {
- let attr = if rty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ret_ty = ArgType::direct(rty, None, None, attr);
}
}
}
_ => {
- let attr = if t == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(t, None, None, attr)
}
};
None)
}
} else {
- let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None };
+ let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
}
}
expr.span,
format!("type of callee is neither bare-fn nor closure: \
{}",
- bcx.ty_to_str(datum.ty)).as_slice());
+ bcx.ty_to_string(datum.ty)).as_slice());
}
}
}
bcx.tcx(), ¶m_substs, &impl_res);
// Now we pull any vtables for parameters on the actual method.
- param_vtables
- .get_mut_vec(subst::FnSpace)
- .push_all(
- impl_vtables.get_vec(subst::FnSpace).as_slice());
+ param_vtables.push_all(subst::FnSpace,
+ impl_vtables.get_slice(subst::FnSpace));
param_vtables
}
&empty_param_substs,
None,
&block_arena);
- init_function(&fcx, false, return_type);
+ let mut bcx = init_function(&fcx, false, return_type);
// Create the substituted versions of the self type.
- let mut bcx = fcx.entry_bcx.borrow().clone().unwrap();
let arg_scope = fcx.push_custom_cleanup_scope();
let arg_scope_id = cleanup::CustomScope(arg_scope);
let boxed_arg_types = ty::ty_fn_args(boxed_function_type);
}).bcx;
bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope);
- finish_fn(&fcx, bcx);
+ finish_fn(&fcx, bcx, return_type);
llfn
}
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
!type_is_zero_size(bcx.ccx(), ret_ty)
{
- Store(bcx, llret, llretslot);
+ store_ty(bcx, llret, llretslot, ret_ty)
}
}
None => {}
let arg_datum_ty = arg_datum.ty;
- debug!(" arg datum: {}", arg_datum.to_str(bcx.ccx()));
+ debug!(" arg datum: {}", arg_datum.to_string(bcx.ccx()));
let mut val;
if ty::type_is_bot(arg_datum_ty) {
// this could happen due to e.g. subtyping
let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
debug!("casting actual type ({}) to match formal ({})",
- bcx.val_to_str(val), bcx.llty_str(llformal_arg_ty));
+ bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
val = PointerCast(bcx, val, llformal_arg_ty);
}
}
- debug!("--- trans_arg_datum passing {}", bcx.val_to_str(val));
+ debug!("--- trans_arg_datum passing {}", bcx.val_to_string(val));
Result::new(bcx, val)
}
*/
debug!("push_ast_cleanup_scope({})",
- self.ccx.tcx.map.node_to_str(id));
+ self.ccx.tcx.map.node_to_string(id));
// FIXME(#2202) -- currently closure bodies have a parent
// region, which messes up the assertion below, since there
id: ast::NodeId,
exits: [&'a Block<'a>, ..EXIT_MAX]) {
debug!("push_loop_cleanup_scope({})",
- self.ccx.tcx.map.node_to_str(id));
+ self.ccx.tcx.map.node_to_string(id));
assert_eq!(Some(id), self.top_ast_scope());
self.push_scope(CleanupScope::new(LoopScopeKind(id, exits)));
*/
debug!("pop_and_trans_ast_cleanup_scope({})",
- self.ccx.tcx.map.node_to_str(cleanup_scope));
+ self.ccx.tcx.map.node_to_string(cleanup_scope));
assert!(self.top_scope(|s| s.kind.is_ast_with_id(cleanup_scope)));
*/
debug!("pop_loop_cleanup_scope({})",
- self.ccx.tcx.map.node_to_str(cleanup_scope));
+ self.ccx.tcx.map.node_to_string(cleanup_scope));
assert!(self.top_scope(|s| s.kind.is_loop_with_id(cleanup_scope)));
is_immediate: false,
on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
val: val,
- ty: ty
+ ty: ty,
+ zero: false
};
debug!("schedule_drop_mem({:?}, val={}, ty={})",
cleanup_scope,
- self.ccx.tn.val_to_str(val),
+ self.ccx.tn.val_to_string(val),
ty.repr(self.ccx.tcx()));
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
}
+ fn schedule_drop_and_zero_mem(&self,
+ cleanup_scope: ScopeId,
+ val: ValueRef,
+ ty: ty::t) {
+ /*!
+ * Schedules a (deep) drop and zero-ing of `val`, which is a pointer
+ * to an instance of `ty`
+ */
+
+ if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
+ let drop = box DropValue {
+ is_immediate: false,
+ on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+ val: val,
+ ty: ty,
+ zero: true
+ };
+
+ debug!("schedule_drop_and_zero_mem({:?}, val={}, ty={}, zero={})",
+ cleanup_scope,
+ self.ccx.tn.val_to_string(val),
+ ty.repr(self.ccx.tcx()),
+ true);
+
+ self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
+ }
+
fn schedule_drop_immediate(&self,
cleanup_scope: ScopeId,
val: ValueRef,
is_immediate: true,
on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
val: val,
- ty: ty
+ ty: ty,
+ zero: false
};
debug!("schedule_drop_immediate({:?}, val={}, ty={})",
cleanup_scope,
- self.ccx.tn.val_to_str(val),
+ self.ccx.tn.val_to_string(val),
ty.repr(self.ccx.tcx()));
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
debug!("schedule_free_value({:?}, val={}, heap={:?})",
cleanup_scope,
- self.ccx.tn.val_to_str(val),
+ self.ccx.tn.val_to_string(val),
heap);
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
self.ccx.sess().bug(
format!("no cleanup scope {} found",
- self.ccx.tcx.map.node_to_str(cleanup_scope)).as_slice());
+ self.ccx.tcx.map.node_to_string(cleanup_scope)).as_slice());
}
fn schedule_clean_in_custom_scope(&self,
on_unwind: bool,
val: ValueRef,
ty: ty::t,
+ zero: bool
}
impl Cleanup for DropValue {
}
fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
- if self.is_immediate {
+ let bcx = if self.is_immediate {
glue::drop_ty_immediate(bcx, self.val, self.ty)
} else {
glue::drop_ty(bcx, self.val, self.ty)
+ };
+ if self.zero {
+ base::zero_mem(bcx, self.val, self.ty);
}
+ bcx
}
}
cleanup_scope: ScopeId,
val: ValueRef,
ty: ty::t);
+ fn schedule_drop_and_zero_mem(&self,
+ cleanup_scope: ScopeId,
+ val: ValueRef,
+ ty: ty::t);
fn schedule_drop_immediate(&self,
cleanup_scope: ScopeId,
val: ValueRef,
use middle::trans::type_::Type;
use middle::ty;
use util::ppaux::Repr;
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
use arena::TypedArena;
use syntax::ast;
}
impl EnvValue {
- pub fn to_str(&self, ccx: &CrateContext) -> String {
- format!("{}({})", self.action, self.datum.to_str(ccx))
+ pub fn to_string(&self, ccx: &CrateContext) -> String {
+ format!("{}({})", self.action, self.datum.to_string(ccx))
}
}
}
}).collect();
let cdata_ty = ty::mk_tup(tcx, bound_tys);
- debug!("cdata_ty={}", ty_to_str(tcx, cdata_ty));
+ debug!("cdata_ty={}", ty_to_string(tcx, cdata_ty));
return cdata_ty;
}
let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, store, cdata_ty);
let llbox = PointerCast(bcx, llbox, llboxptr_ty);
- debug!("tuplify_box_ty = {}", ty_to_str(tcx, cbox_ty));
+ debug!("tuplify_box_ty = {}", ty_to_string(tcx, cbox_ty));
// Copy expr values into boxed bindings.
let mut bcx = bcx;
for (i, bv) in bound_values.move_iter().enumerate() {
- debug!("Copy {} into closure", bv.to_str(ccx));
+ debug!("Copy {} into closure", bv.to_string(ccx));
if ccx.sess().asm_comments() {
add_comment(bcx, format!("Copy {} into closure",
- bv.to_str(ccx)).as_slice());
+ bv.to_string(ccx)).as_slice());
}
let bound_data = GEPi(bcx, llbox, [0u, abi::box_field_body, i]);
let empty_param_substs = param_substs::empty();
let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output,
&empty_param_substs, None, &arena);
- init_function(&fcx, true, f.sig.output);
- let bcx = fcx.entry_bcx.borrow().clone().unwrap();
+ let bcx = init_function(&fcx, true, f.sig.output);
let args = create_datums_for_fn_args(&fcx,
ty::ty_fn_args(closure_ty)
}
}
-fn param_substs_to_str(this: ¶m_substs, tcx: &ty::ctxt) -> String {
+fn param_substs_to_string(this: ¶m_substs, tcx: &ty::ctxt) -> String {
format!("param_substs({})", this.substs.repr(tcx))
}
impl Repr for param_substs {
fn repr(&self, tcx: &ty::ctxt) -> String {
- param_substs_to_str(self, tcx)
+ param_substs_to_string(self, tcx)
}
}
// always be Some.
pub llretptr: Cell<Option<ValueRef>>,
- pub entry_bcx: RefCell<Option<&'a Block<'a>>>,
-
// These pub elements: "hoisted basic blocks" containing
// administrative activities that have to happen in only one place in
// the function, due to LLVM's quirks.
.get()
.unwrap());
}
- // Remove the cycle between fcx and bcx, so memory can be freed
- *self.entry_bcx.borrow_mut() = None;
}
pub fn get_llreturn(&self) -> BasicBlockRef {
token::get_ident(ident).get().to_string()
}
- pub fn node_id_to_str(&self, id: ast::NodeId) -> String {
- self.tcx().map.node_to_str(id).to_string()
+ pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
+ self.tcx().map.node_to_string(id).to_string()
}
- pub fn expr_to_str(&self, e: &ast::Expr) -> String {
+ pub fn expr_to_string(&self, e: &ast::Expr) -> String {
e.repr(self.tcx())
}
}
}
- pub fn val_to_str(&self, val: ValueRef) -> String {
- self.ccx().tn.val_to_str(val)
+ pub fn val_to_string(&self, val: ValueRef) -> String {
+ self.ccx().tn.val_to_string(val)
}
pub fn llty_str(&self, ty: Type) -> String {
- self.ccx().tn.type_to_str(ty)
+ self.ccx().tn.type_to_string(ty)
}
- pub fn ty_to_str(&self, t: ty::t) -> String {
+ pub fn ty_to_string(&self, t: ty::t) -> String {
t.repr(self.tcx())
}
}
pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
- C_integral(Type::bool(ccx), val as u64, false)
-}
-
-pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
C_integral(Type::i1(ccx), val as u64, false)
}
let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
debug!("const_get_elt(v={}, us={:?}, r={})",
- cx.tn.val_to_str(v), us, cx.tn.val_to_str(r));
+ cx.tn.val_to_string(v), us, cx.tn.val_to_string(r));
return r;
}
use middle::trans::type_of;
use middle::trans::debuginfo;
use middle::ty;
-use util::ppaux::{Repr, ty_to_str};
+use util::ppaux::{Repr, ty_to_string};
use std::c_str::ToCStr;
use std::gc::Gc;
_ => cx.sess().span_bug(lit.span,
format!("integer literal has type {} (expected int \
or uint)",
- ty_to_str(cx.tcx(), lit_int_ty)).as_slice())
+ ty_to_string(cx.tcx(), lit_int_ty)).as_slice())
}
}
ast::LitFloat(ref fs, t) => {
}
_ => {
cx.sess().bug(format!("unexpected dereferenceable type {}",
- ty_to_str(cx.tcx(), t)).as_slice())
+ ty_to_string(cx.tcx(), t)).as_slice())
}
};
(dv, mt.ty)
}
None => {
cx.sess().bug(format!("can't dereference const of type {}",
- ty_to_str(cx.tcx(), t)).as_slice())
+ ty_to_string(cx.tcx(), t)).as_slice())
}
}
}
llvm::LLVMDumpValue(C_undef(llty));
}
cx.sess().bug(format!("const {} of type {} has size {} instead of {}",
- e.repr(cx.tcx()), ty_to_str(cx.tcx(), ety),
+ e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety),
csize, tsize).as_slice());
}
(llconst, inlineable)
if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
}
- (expr::cast_enum, expr::cast_integral) |
- (expr::cast_enum, expr::cast_float) => {
+ (expr::cast_enum, expr::cast_integral) => {
let repr = adt::represent_type(cx, basety);
let discr = adt::const_get_discrim(cx, &*repr, v);
let iv = C_integral(cx.int_type, discr, false);
dest: expr::Dest)
-> &'a Block<'a> {
debug!("trans_if(bcx={}, if_id={}, cond={}, thn={:?}, dest={})",
- bcx.to_str(), if_id, bcx.expr_to_str(cond), thn.id,
- dest.to_str(bcx.ccx()));
+ bcx.to_str(), if_id, bcx.expr_to_string(cond), thn.id,
+ dest.to_string(bcx.ccx()));
let _icx = push_ctxt("trans_if");
let mut bcx = bcx;
* Datums are and how they are intended to be used.
*/
-use lib;
use lib::llvm::ValueRef;
use middle::trans::base::*;
-use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::cleanup;
use middle::trans::cleanup::CleanupMethods;
use middle::trans::tvec;
use middle::trans::type_of;
use middle::ty;
-use util::ppaux::{ty_to_str};
+use util::ppaux::{ty_to_string};
use syntax::ast;
match self.kind.mode {
ByValue => DatumBlock::new(bcx, self),
ByRef => {
- let llval = load(bcx, self.val, self.ty);
+ let llval = load_ty(bcx, self.val, self.ty);
DatumBlock::new(bcx, Datum::new(llval, self.ty, Rvalue::new(ByValue)))
}
}
DatumBlock::new(bcx, scratch)
}
ByValue => {
- let v = load(bcx, l.val, l.ty);
+ let v = load_ty(bcx, l.val, l.ty);
bcx = l.kind.post_store(bcx, l.val, l.ty);
DatumBlock::new(bcx, Datum::new(v, l.ty, Rvalue::new(ByValue)))
}
}
}
-fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
- /*!
- * Private helper for loading from a by-ref datum. Handles various
- * special cases where the type gives us better information about
- * what we are loading.
- */
-
- if type_is_zero_size(bcx.ccx(), ty) {
- C_undef(type_of::type_of(bcx.ccx(), ty))
- } else if ty::type_is_char(ty) {
- // a char is a unicode codepoint, and so takes values from 0
- // to 0x10FFFF inclusive only.
- LoadRangeAssert(bcx, llptr, 0, 0x10FFFF + 1, lib::llvm::False)
- } else {
- Load(bcx, llptr)
- }
-}
-
/**
* Generic methods applicable to any sort of datum.
*/
if self.kind.is_by_ref() {
memcpy_ty(bcx, dst, self.val, self.ty);
} else {
- Store(bcx, self.val, dst);
+ store_ty(bcx, self.val, dst, self.ty);
}
return bcx;
}
#[allow(dead_code)] // useful for debugging
- pub fn to_str(&self, ccx: &CrateContext) -> String {
+ pub fn to_string(&self, ccx: &CrateContext) -> String {
format!("Datum({}, {}, {:?})",
- ccx.tn.val_to_str(self.val),
- ty_to_str(ccx.tcx(), self.ty),
+ ccx.tn.val_to_string(self.val),
+ ty_to_string(ccx.tcx(), self.ty),
self.kind)
}
assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
if self.kind.is_by_ref() {
- load(bcx, self.val, self.ty)
+ load_ty(bcx, self.val, self.ty)
} else {
self.val
}
metadata: DIType) {
if !self.type_to_metadata.insert(ty::type_id(type_), metadata) {
cx.sess().bug(format!("Type metadata for ty::t '{}' is already in the TypeMap!",
- ppaux::ty_to_str(cx.tcx(), type_)).as_slice());
+ ppaux::ty_to_string(cx.tcx(), type_)).as_slice());
}
}
},
_ => {
cx.sess().bug(format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
- ppaux::ty_to_str(cx.tcx(), type_).as_slice(),
+ ppaux::ty_to_string(cx.tcx(), type_).as_slice(),
ty::get(type_).sty).as_slice())
}
};
// Maybe check that there is no self type here.
- let tps = substs.types.get_vec(subst::TypeSpace);
+ let tps = substs.types.get_slice(subst::TypeSpace);
if tps.len() > 0 {
output.push_char('<');
let type_metadata = type_metadata(cx, variable_type, span);
let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
- let var_name = token::get_ident(ident).get().to_str();
+ let var_name = token::get_ident(ident).get().to_string();
let linkage_name =
namespace_node.mangled_name_of_contained_item(var_name.as_slice());
let var_scope = namespace_node.scope;
FunctionDebugContext(box ref function_debug_context) => {
let cx = fcx.ccx;
- debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
+ debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
if function_debug_context.source_locations_enabled.get() {
let loc = span_start(cx, span);
}
// Handle other generic parameters
- let actual_types = param_substs.substs.types.get_vec(subst::FnSpace);
+ let actual_types = param_substs.substs.types.get_slice(subst::FnSpace);
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
- let actual_type = *actual_types.get(index);
+ let actual_type = actual_types[index];
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,
});
fn fallback_path(cx: &CrateContext) -> CString {
- cx.link_meta.crateid.name.as_slice().to_c_str()
+ cx.link_meta.crate_name.as_slice().to_c_str()
}
}
type_map.find_metadata_for_type(unfinished_type).is_none() {
cx.sess().bug(format!("Forward declaration of potentially recursive type \
'{}' was not found in TypeMap!",
- ppaux::ty_to_str(cx.tcx(), unfinished_type))
+ ppaux::ty_to_string(cx.tcx(), unfinished_type))
.as_slice());
}
}
let null_variant_index = (1 - nndiscr) as uint;
let null_variant_ident = self.variants.get(null_variant_index).name;
let null_variant_name = token::get_ident(null_variant_ident);
+ let discrfield = match ptrfield {
+ adt::ThinPointer(field) => format!("{}", field),
+ adt::FatPointer(field, pair) => format!("{}${}", field, pair)
+ };
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
- ptrfield,
+ discrfield,
null_variant_name);
// Create the (singleton) list of descriptions of union members.
enum EnumDiscriminantInfo {
RegularDiscriminant(DIType),
- OptimizedDiscriminant(uint),
+ OptimizedDiscriminant(adt::PointerField),
NoDiscriminant
}
Some(ref names) => {
names.iter()
.map(|ident| {
- token::get_ident(*ident).get().to_str().into_string()
+ token::get_ident(*ident).get().to_string().into_string()
}).collect()
}
None => variant_info.args.iter().map(|_| "".to_string()).collect()
ty::ty_uniq(pointee_type) => pointee_type,
ty::ty_rptr(_, ty::mt { ty, .. }) => ty,
_ => {
- let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_pointer_type);
+ let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_pointer_type);
cx.sess().bug(format!("debuginfo: Unexpected trait-pointer type in \
trait_pointer_metadata(): {}",
pp_type_name.as_slice()).as_slice());
let def_id = match ty::get(trait_object_type).sty {
ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id,
_ => {
- let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_object_type);
+ let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_object_type);
cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {}",
pp_type_name.as_slice()).as_slice());
the debuginfo::TypeMap but it \
was not. (ty::t = {})",
unique_type_id_str.as_slice(),
- ppaux::ty_to_str(cx.tcx(), t));
+ ppaux::ty_to_string(cx.tcx(), t));
cx.sess().span_bug(usage_site_span, error_message.as_slice());
}
};
debuginfo::TypeMap. \
UniqueTypeId={}, ty::t={}",
unique_type_id_str.as_slice(),
- ppaux::ty_to_str(cx.tcx(), t));
+ ppaux::ty_to_string(cx.tcx(), t));
cx.sess().span_bug(usage_site_span, error_message.as_slice());
}
}
ty::ty_infer(_) |
ty::ty_param(_) => {
cx.sess().bug(format!("debuginfo: Trying to create type name for \
- unexpected type: {}", ppaux::ty_to_str(cx.tcx(), t)).as_slice());
+ unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)).as_slice());
}
}
}
fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
- cx.link_meta.crateid.name.as_slice()
+ cx.link_meta.crate_name.as_slice()
}
fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
use syntax::ast;
use syntax::codemap;
-use syntax::print::pprust::{expr_to_str};
+use syntax::print::pprust::{expr_to_string};
use std::gc::Gc;
}
impl Dest {
- pub fn to_str(&self, ccx: &CrateContext) -> String {
+ pub fn to_string(&self, ccx: &CrateContext) -> String {
match *self {
- SaveIn(v) => format!("SaveIn({})", ccx.tn.val_to_str(v)),
+ SaveIn(v) => format!("SaveIn({})", ccx.tn.val_to_string(v)),
Ignore => "Ignore".to_string()
}
}
* the stack.
*/
- debug!("trans(expr={})", bcx.expr_to_str(expr));
+ debug!("trans(expr={})", bcx.expr_to_string(expr));
let mut bcx = bcx;
let fcx = bcx.fcx;
Some(adj) => { adj }
};
debug!("unadjusted datum for expr {}: {}",
- expr.id, datum.to_str(bcx.ccx()));
+ expr.id, datum.to_string(bcx.ccx()));
match adjustment {
AutoAddEnv(..) => {
datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
datum = scratch.to_expr_datum();
}
}
- debug!("after adjustments, datum={}", datum.to_str(bcx.ccx()));
+ debug!("after adjustments, datum={}", datum.to_string(bcx.ccx()));
return DatumBlock {bcx: bcx, datum: datum};
fn auto_slice<'a>(
let mut bcx = bcx;
- debug!("trans_unadjusted(expr={})", bcx.expr_to_str(expr));
+ debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr));
let _indenter = indenter();
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
trans_rec_field(bcx, &**base, ident.node)
}
ast::ExprIndex(ref base, ref idx) => {
- trans_index(bcx, expr, &**base, &**idx)
+ trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
}
ast::ExprVstore(ref contents, ast::ExprVstoreUniq) => {
fcx.push_ast_cleanup_scope(contents.id);
fn trans_index<'a>(bcx: &'a Block<'a>,
index_expr: &ast::Expr,
base: &ast::Expr,
- idx: &ast::Expr)
+ idx: &ast::Expr,
+ method_call: MethodCall)
-> DatumBlock<'a, Expr> {
//! Translates `base[idx]`.
let ccx = bcx.ccx();
let mut bcx = bcx;
- let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "index"));
-
- // Translate index expression and cast to a suitable LLVM integer.
- // Rust is less strict than LLVM in this regard.
- let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
- let ix_val = ix_datum.to_llscalarish(bcx);
- let ix_size = machine::llbitsize_of_real(bcx.ccx(), val_ty(ix_val));
- let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type);
- let ix_val = {
- if ix_size < int_size {
- if ty::type_is_signed(expr_ty(bcx, idx)) {
- SExt(bcx, ix_val, ccx.int_type)
- } else { ZExt(bcx, ix_val, ccx.int_type) }
- } else if ix_size > int_size {
- Trunc(bcx, ix_val, ccx.int_type)
- } else {
- ix_val
- }
- };
+ // Check for overloaded index.
+ let method_ty = ccx.tcx
+ .method_map
+ .borrow()
+ .find(&method_call)
+ .map(|method| method.ty);
+ let elt_datum = match method_ty {
+ Some(method_ty) => {
+ let base_datum = unpack_datum!(bcx, trans(bcx, base));
- let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), base_datum.ty));
- base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
+ // Translate index expression.
+ let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
- let (base, len) = base_datum.get_vec_base_and_len(bcx);
+ // Overloaded. Evaluate `trans_overloaded_op`, which will
+ // invoke the user's index() method, which basically yields
+ // a `&T` pointer. We can then proceed down the normal
+ // path (below) to dereference that `&T`.
+ let val =
+ unpack_result!(bcx,
+ trans_overloaded_op(bcx,
+ index_expr,
+ method_call,
+ base_datum,
+ Some((ix_datum, idx.id)),
+ None));
+ let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
+ let elt_ty = match ty::deref(ref_ty, true) {
+ None => {
+ bcx.tcx().sess.span_bug(index_expr.span,
+ "index method didn't return a \
+ dereferenceable type?!")
+ }
+ Some(elt_tm) => elt_tm.ty,
+ };
+ Datum::new(val, elt_ty, LvalueExpr)
+ }
+ None => {
+ let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx,
+ base,
+ "index"));
+
+ // Translate index expression and cast to a suitable LLVM integer.
+ // Rust is less strict than LLVM in this regard.
+ let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
+ let ix_val = ix_datum.to_llscalarish(bcx);
+ let ix_size = machine::llbitsize_of_real(bcx.ccx(),
+ val_ty(ix_val));
+ let int_size = machine::llbitsize_of_real(bcx.ccx(),
+ ccx.int_type);
+ let ix_val = {
+ if ix_size < int_size {
+ if ty::type_is_signed(expr_ty(bcx, idx)) {
+ SExt(bcx, ix_val, ccx.int_type)
+ } else { ZExt(bcx, ix_val, ccx.int_type) }
+ } else if ix_size > int_size {
+ Trunc(bcx, ix_val, ccx.int_type)
+ } else {
+ ix_val
+ }
+ };
- debug!("trans_index: base {}", bcx.val_to_str(base));
- debug!("trans_index: len {}", bcx.val_to_str(len));
+ let vt =
+ tvec::vec_types(bcx,
+ ty::sequence_element_type(bcx.tcx(),
+ base_datum.ty));
+ base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
+
+ let (base, len) = base_datum.get_vec_base_and_len(bcx);
+
+ debug!("trans_index: base {}", bcx.val_to_string(base));
+ debug!("trans_index: len {}", bcx.val_to_string(len));
+
+ let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
+ let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
+ let expected = Call(bcx,
+ expect,
+ [bounds_check, C_bool(ccx, false)],
+ []);
+ bcx = with_cond(bcx, expected, |bcx| {
+ controlflow::trans_fail_bounds_check(bcx,
+ index_expr.span,
+ ix_val,
+ len)
+ });
+ let elt = InBoundsGEP(bcx, base, [ix_val]);
+ let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
+ Datum::new(elt, vt.unit_ty, LvalueExpr)
+ }
+ };
- let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
- let expect = ccx.get_intrinsic(&("llvm.expect.i1"));
- let expected = Call(bcx, expect, [bounds_check, C_i1(ccx, false)], []);
- let bcx = with_cond(bcx, expected, |bcx| {
- controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
- });
- let elt = InBoundsGEP(bcx, base, [ix_val]);
- let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
- DatumBlock::new(bcx, Datum::new(elt, vt.unit_ty, LvalueExpr))
+ DatumBlock::new(bcx, elt_datum)
}
fn trans_def<'a>(bcx: &'a Block<'a>,
let expr_ty = expr_ty(bcx, expr);
let store = ty::ty_closure_store(expr_ty);
debug!("translating block function {} with type {}",
- expr_to_str(expr), expr_ty.repr(tcx));
+ expr_to_string(expr), expr_ty.repr(tcx));
closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
}
ast::ExprCall(ref f, ref args) => {
_ => {
bcx.tcx().sess.span_bug(ref_expr.span, format!(
"Non-DPS def {:?} referened by {}",
- def, bcx.node_id_to_str(ref_expr.id)).as_slice());
+ def, bcx.node_id_to_string(ref_expr.id)).as_slice());
}
}
}
}
};
debug!("take_local(nid={:?}, v={}, ty={})",
- nid, bcx.val_to_str(datum.val), bcx.ty_to_str(datum.ty));
+ nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty));
datum
}
}
match op {
ast::UnNot => {
let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
- let llresult = if ty::type_is_bool(un_ty) {
- let val = datum.to_llscalarish(bcx);
- Xor(bcx, val, C_bool(ccx, true))
- } else {
- // Note: `Not` is bitwise, not suitable for logical not.
- Not(bcx, datum.to_llscalarish(bcx))
- };
+ let llresult = Not(bcx, datum.to_llscalarish(bcx));
immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock()
}
ast::UnNeg => {
}
Br(past_rhs, join.llbb);
- let phi = Phi(join, Type::bool(bcx.ccx()), [lhs, rhs],
+ let phi = Phi(join, Type::i1(bcx.ccx()), [lhs, rhs],
[past_lhs.llbb, past_rhs.llbb]);
return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock();
debug!("trans_binary (expr {}): lhs_datum={}",
expr.id,
- lhs_datum.to_str(ccx));
+ lhs_datum.to_string(ccx));
let lhs_ty = lhs_datum.ty;
let lhs = lhs_datum.to_llscalarish(bcx);
debug!("trans_binary (expr {}): rhs_datum={}",
expr.id,
- rhs_datum.to_str(ccx));
+ rhs_datum.to_string(ccx));
let rhs_ty = rhs_datum.ty;
let rhs = rhs_datum.to_llscalarish(bcx);
trans_eager_binop(bcx, expr, binop_ty, op,
let k_in = cast_type_kind(t_in);
let k_out = cast_type_kind(t_out);
let s_in = k_in == cast_integral && ty::type_is_signed(t_in);
- let ll_t_in = type_of::type_of(ccx, t_in);
- let ll_t_out = type_of::type_of(ccx, t_out);
+ let ll_t_in = type_of::arg_type_of(ccx, t_in);
+ let ll_t_out = type_of::arg_type_of(ccx, t_out);
// Convert the value to be cast into a ValueRef, either by-ref or
// by-value as appropriate given its type:
let _icx = push_ctxt("trans_assign_op");
let mut bcx = bcx;
- debug!("trans_assign_op(expr={})", bcx.expr_to_str(expr));
+ debug!("trans_assign_op(expr={})", bcx.expr_to_string(expr));
// User-defined operator methods cannot be used with `+=` etc right now
assert!(!bcx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty));
let dst_ty = dst_datum.ty;
- let dst = Load(bcx, dst_datum.val);
+ let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);
// Evaluate RHS
let rhs_datum = unpack_datum!(bcx, trans(bcx, &*src));
debug!("deref_once(expr={}, datum={}, method_call={})",
expr.repr(bcx.tcx()),
- datum.to_str(ccx),
+ datum.to_string(ccx),
method_call);
let mut bcx = bcx;
Some(method_ty) => {
// Overloaded. Evaluate `trans_overloaded_op`, which will
// invoke the user's deref() method, which basically
- // converts from the `Shaht<T>` pointer that we have into
+ // converts from the `Smaht<T>` pointer that we have into
// a `&T` pointer. We can then proceed down the normal
// path (below) to dereference that `&T`.
let datum = match method_call.adjustment {
};
debug!("deref_once(expr={}, method_call={}, result={})",
- expr.id, method_call, r.datum.to_str(ccx));
+ expr.id, method_call, r.datum.to_string(ccx));
return r;
use middle::trans::base::push_ctxt;
use middle::trans::base;
use middle::trans::build::*;
-use middle::trans::builder::noname;
use middle::trans::cabi;
use middle::trans::common::*;
use middle::trans::machine;
llfn={}, \
llretptr={})",
callee_ty.repr(tcx),
- ccx.tn.val_to_str(llfn),
- ccx.tn.val_to_str(llretptr));
+ ccx.tn.val_to_string(llfn),
+ ccx.tn.val_to_string(llretptr));
let (fn_abi, fn_sig) = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()),
debug!("argument {}, llarg_rust={}, rust_indirect={}, arg_ty={}",
i,
- ccx.tn.val_to_str(llarg_rust),
+ ccx.tn.val_to_string(llarg_rust),
rust_indirect,
- ccx.tn.type_to_str(arg_tys[i].ty));
+ ccx.tn.type_to_string(arg_tys[i].ty));
// Ensure that we always have the Rust value indirectly,
// because it makes bitcasting easier.
base::alloca(bcx,
type_of::type_of(ccx, *passed_arg_tys.get(i)),
"__arg");
- Store(bcx, llarg_rust, scratch);
+ base::store_ty(bcx, llarg_rust, scratch, *passed_arg_tys.get(i));
llarg_rust = scratch;
}
debug!("llarg_rust={} (after indirection)",
- ccx.tn.val_to_str(llarg_rust));
+ ccx.tn.val_to_string(llarg_rust));
// Check whether we need to do any casting
match arg_tys[i].cast {
}
debug!("llarg_rust={} (after casting)",
- ccx.tn.val_to_str(llarg_rust));
+ ccx.tn.val_to_string(llarg_rust));
// Finally, load the value if needed for the foreign ABI
let foreign_indirect = arg_tys[i].is_indirect();
let llarg_foreign = if foreign_indirect {
llarg_rust
} else {
- Load(bcx, llarg_rust)
+ if ty::type_is_bool(*passed_arg_tys.get(i)) {
+ let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, lib::llvm::False);
+ Trunc(bcx, val, Type::i1(bcx.ccx()))
+ } else {
+ Load(bcx, llarg_rust)
+ }
};
debug!("argument {}, llarg_foreign={}",
- i, ccx.tn.val_to_str(llarg_foreign));
+ i, ccx.tn.val_to_string(llarg_foreign));
// fill padding with undef value
match arg_tys[i].pad {
None => fn_type.ret_ty.ty
};
- debug!("llretptr={}", ccx.tn.val_to_str(llretptr));
- debug!("llforeign_retval={}", ccx.tn.val_to_str(llforeign_retval));
- debug!("llrust_ret_ty={}", ccx.tn.type_to_str(llrust_ret_ty));
- debug!("llforeign_ret_ty={}", ccx.tn.type_to_str(llforeign_ret_ty));
+ debug!("llretptr={}", ccx.tn.val_to_string(llretptr));
+ debug!("llforeign_retval={}", ccx.tn.val_to_string(llforeign_retval));
+ debug!("llrust_ret_ty={}", ccx.tn.type_to_string(llrust_ret_ty));
+ debug!("llforeign_ret_ty={}", ccx.tn.type_to_string(llforeign_ret_ty));
if llrust_ret_ty == llforeign_ret_ty {
- Store(bcx, llforeign_retval, llretptr);
+ base::store_ty(bcx, llforeign_retval, llretptr, fn_sig.output)
} else {
// The actual return type is a struct, but the ABI
// adaptation code has cast it into some scalar type. The
let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
add_argument_attributes(&tys, llfn);
debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})",
- node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn));
+ node_id, ccx.tn.type_to_string(llfn_ty), ccx.tn.val_to_string(llfn));
llfn
}
let ps = ccx.tcx.map.with_path(id, |path| {
let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
- link::mangle(path.chain(abi.move_iter()), None, None)
+ link::mangle(path.chain(abi.move_iter()), None)
});
// Compute the type that the function would have if it were just a
_ => {
ccx.sess().bug(format!("build_rust_fn: extern fn {} has ty {}, \
expected a bare fn ty",
- ccx.tcx.map.path_to_str(id),
+ ccx.tcx.map.path_to_string(id),
t.repr(tcx)).as_slice());
}
};
debug!("build_rust_fn: path={} id={} t={}",
- ccx.tcx.map.path_to_str(id),
+ ccx.tcx.map.path_to_string(id),
id, t.repr(tcx));
let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
let t = ty::node_id_to_type(tcx, id);
debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
- ccx.tn.val_to_str(llrustfn),
- ccx.tn.val_to_str(llwrapfn),
+ ccx.tn.val_to_string(llrustfn),
+ ccx.tn.val_to_string(llwrapfn),
t.repr(ccx.tcx()));
// Avoid all the Rust generation stuff and just generate raw
"the block".with_c_str(
|s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llwrapfn, s));
- let builder = ccx.builder.b;
- llvm::LLVMPositionBuilderAtEnd(builder, the_block);
+ let builder = ccx.builder();
+ builder.position_at_end(the_block);
// Array for the arguments we will pass to the rust function.
let mut llrust_args = Vec::new();
match foreign_outptr {
Some(llforeign_outptr) => {
debug!("out pointer, foreign={}",
- ccx.tn.val_to_str(llforeign_outptr));
+ ccx.tn.val_to_string(llforeign_outptr));
let llrust_retptr =
- llvm::LLVMBuildBitCast(builder,
- llforeign_outptr,
- llrust_ret_ty.ptr_to().to_ref(),
- noname());
+ builder.bitcast(llforeign_outptr, llrust_ret_ty.ptr_to());
debug!("out pointer, foreign={} (casted)",
- ccx.tn.val_to_str(llrust_retptr));
+ ccx.tn.val_to_string(llrust_retptr));
llrust_args.push(llrust_retptr);
return_alloca = None;
}
None => {
- let slot = {
- "return_alloca".with_c_str(
- |s| llvm::LLVMBuildAlloca(builder,
- llrust_ret_ty.to_ref(),
- s))
- };
+ let slot = builder.alloca(llrust_ret_ty, "return_alloca");
debug!("out pointer, \
allocad={}, \
llrust_ret_ty={}, \
return_ty={}",
- ccx.tn.val_to_str(slot),
- ccx.tn.type_to_str(llrust_ret_ty),
+ ccx.tn.val_to_string(slot),
+ ccx.tn.type_to_string(llrust_ret_ty),
tys.fn_sig.output.repr(tcx));
llrust_args.push(slot);
return_alloca = Some(slot);
let mut llforeign_arg = llvm::LLVMGetParam(llwrapfn, foreign_index);
debug!("llforeign_arg {}{}: {}", "#",
- i, ccx.tn.val_to_str(llforeign_arg));
+ i, ccx.tn.val_to_string(llforeign_arg));
debug!("rust_indirect = {}, foreign_indirect = {}",
rust_indirect, foreign_indirect);
// pointer). It makes adapting types easier, since we can
// always just bitcast pointers.
if !foreign_indirect {
- let lltemp =
- llvm::LLVMBuildAlloca(
- builder, val_ty(llforeign_arg).to_ref(), noname());
- llvm::LLVMBuildStore(
- builder, llforeign_arg, lltemp);
- llforeign_arg = lltemp;
+ llforeign_arg = if ty::type_is_bool(rust_ty) {
+ let lltemp = builder.alloca(Type::bool(ccx), "");
+ builder.store(builder.zext(llforeign_arg, Type::bool(ccx)), lltemp);
+ lltemp
+ } else {
+ let lltemp = builder.alloca(val_ty(llforeign_arg), "");
+ builder.store(llforeign_arg, lltemp);
+ lltemp
+ }
}
// If the types in the ABI and the Rust types don't match,
// Rust expects.
if llforeign_arg_ty.cast.is_some() {
assert!(!foreign_indirect);
- llforeign_arg = llvm::LLVMBuildBitCast(
- builder, llforeign_arg,
- llrust_ty.ptr_to().to_ref(), noname());
+ llforeign_arg = builder.bitcast(llforeign_arg, llrust_ty.ptr_to());
}
let llrust_arg = if rust_indirect {
llforeign_arg
} else {
- llvm::LLVMBuildLoad(builder, llforeign_arg, noname())
+ if ty::type_is_bool(rust_ty) {
+ let tmp = builder.load_range_assert(llforeign_arg, 0, 2, lib::llvm::False);
+ builder.trunc(tmp, Type::i1(ccx))
+ } else {
+ builder.load(llforeign_arg)
+ }
};
debug!("llrust_arg {}{}: {}", "#",
- i, ccx.tn.val_to_str(llrust_arg));
+ i, ccx.tn.val_to_string(llrust_arg));
llrust_args.push(llrust_arg);
}
// Perform the call itself
- debug!("calling llrustfn = {}, t = {}", ccx.tn.val_to_str(llrustfn), t.repr(ccx.tcx()));
- let llrust_ret_val = llvm::LLVMBuildCall(builder, llrustfn, llrust_args.as_ptr(),
- llrust_args.len() as c_uint, noname());
-
+ debug!("calling llrustfn = {}, t = {}", ccx.tn.val_to_string(llrustfn), t.repr(ccx.tcx()));
let attributes = base::get_fn_llvm_attributes(ccx, t);
- for &(idx, attr) in attributes.iter() {
- llvm::LLVMAddCallSiteAttribute(llrust_ret_val, idx as c_uint, attr);
- }
+ let llrust_ret_val = builder.call(llrustfn, llrust_args.as_slice(), attributes.as_slice());
// Get the return value where the foreign fn expects it.
let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast {
None if !tys.ret_def => {
// Function returns `()` or `bot`, which in Rust is the LLVM
// type "{}" but in foreign ABIs is "Void".
- llvm::LLVMBuildRetVoid(builder);
+ builder.ret_void();
}
None if rust_uses_outptr => {
// Rust uses an outpointer, but the foreign ABI does not. Load.
let llrust_outptr = return_alloca.unwrap();
let llforeign_outptr_casted =
- llvm::LLVMBuildBitCast(builder,
- llrust_outptr,
- llforeign_ret_ty.ptr_to().to_ref(),
- noname());
- let llforeign_retval =
- llvm::LLVMBuildLoad(builder, llforeign_outptr_casted, noname());
- llvm::LLVMBuildRet(builder, llforeign_retval);
+ builder.bitcast(llrust_outptr, llforeign_ret_ty.ptr_to());
+ let llforeign_retval = builder.load(llforeign_outptr_casted);
+ builder.ret(llforeign_retval);
}
None if llforeign_ret_ty != llrust_ret_ty => {
// right now we just use a temp memory location and
// bitcast the pointer, which is the same thing the
// old wrappers used to do.
- let lltemp =
- llvm::LLVMBuildAlloca(
- builder, llforeign_ret_ty.to_ref(), noname());
- let lltemp_casted =
- llvm::LLVMBuildBitCast(builder,
- lltemp,
- llrust_ret_ty.ptr_to().to_ref(),
- noname());
- llvm::LLVMBuildStore(
- builder, llrust_ret_val, lltemp_casted);
- let llforeign_retval =
- llvm::LLVMBuildLoad(builder, lltemp, noname());
- llvm::LLVMBuildRet(builder, llforeign_retval);
+ let lltemp = builder.alloca(llforeign_ret_ty, "");
+ let lltemp_casted = builder.bitcast(lltemp, llrust_ret_ty.ptr_to());
+ builder.store(llrust_ret_val, lltemp_casted);
+ let llforeign_retval = builder.load(lltemp);
+ builder.ret(llforeign_retval);
}
None => {
// Neither ABI uses an outpointer, and the types
// match. Easy peasy.
- llvm::LLVMBuildRet(builder, llrust_ret_val);
+ builder.ret(llrust_ret_val);
}
Some(llforeign_outptr) if !rust_uses_outptr => {
// Foreign ABI requires an out pointer, but Rust doesn't.
// Store Rust return value.
let llforeign_outptr_casted =
- llvm::LLVMBuildBitCast(builder,
- llforeign_outptr,
- llrust_retptr_ty.to_ref(),
- noname());
- llvm::LLVMBuildStore(
- builder, llrust_ret_val, llforeign_outptr_casted);
- llvm::LLVMBuildRetVoid(builder);
+ builder.bitcast(llforeign_outptr, llrust_retptr_ty);
+ builder.store(llrust_ret_val, llforeign_outptr_casted);
+ builder.ret_void();
}
Some(_) => {
// Both ABIs use outpointers. Easy peasy.
- llvm::LLVMBuildRetVoid(builder);
+ builder.ret_void();
}
}
}
* values by pointer like we do.
*/
- let llarg_tys = arg_tys.iter().map(|&arg| type_of(ccx, arg)).collect();
- let llret_ty = type_of::type_of(ccx, fn_sig.output);
+ let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect();
+ let llret_ty = type_of::arg_type_of(ccx, fn_sig.output);
LlvmSignature {
llarg_tys: llarg_tys,
llret_ty: llret_ty
ret_def={}",
ty.repr(ccx.tcx()),
ccx.tn.types_to_str(llsig.llarg_tys.as_slice()),
- ccx.tn.type_to_str(llsig.llret_ty),
+ ccx.tn.type_to_string(llsig.llret_ty),
ccx.tn.types_to_str(fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>().as_slice()),
- ccx.tn.type_to_str(fn_ty.ret_ty.ty),
+ ccx.tn.type_to_string(fn_ty.ret_ty.ty),
ret_def);
ForeignTypes {
match ti.visit_glue.get() {
Some(visit_glue) => visit_glue,
None => {
- debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
+ debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_string(ccx.tcx(), ti.ty));
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
ti.visit_glue.set(Some(glue_fn));
make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
- debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
+ debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_string(ccx.tcx(), ti.ty));
glue_fn
}
}
-> &'a Block<'a> {
let repr = adt::represent_type(bcx.ccx(), t);
let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0);
- with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| {
+ with_cond(bcx, load_ty(bcx, drop_flag, ty::mk_bool()), |cx| {
trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
})
}
if ccx.sess().count_type_sizes() {
println!("{}\t{}", llsize_of_real(ccx, llty),
- ppaux::ty_to_str(ccx.tcx(), t));
+ ppaux::ty_to_string(ccx.tcx(), t));
}
let llsize = llsize_of(ccx, llty);
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
- debug!("+++ declare_tydesc {} {}", ppaux::ty_to_str(ccx.tcx(), t), name);
+ debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
let gvar = name.as_slice().with_c_str(|buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type().to_ref(), buf)
note_unique_llvm_symbol(ccx, name);
let ty_name = token::intern_and_get_ident(
- ppaux::ty_to_str(ccx.tcx(), t).as_slice());
+ ppaux::ty_to_string(ccx.tcx(), t).as_slice());
let ty_name = C_str_slice(ccx, ty_name);
- debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
+ debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t));
tydesc_info {
ty: t,
tydesc: gvar,
ccx,
t,
format!("glue_{}", name).as_slice());
- debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t));
+ debug!("{} is for type {}", fn_nm, ppaux::ty_to_string(ccx.tcx(), t));
let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil());
note_unique_llvm_symbol(ccx, fn_nm);
return llfn;
let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(),
&empty_param_substs, None, &arena);
- init_function(&fcx, false, ty::mk_nil());
+ let bcx = init_function(&fcx, false, ty::mk_nil());
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
// llfn is expected be declared to take a parameter of the appropriate
// type, so we don't need to explicitly cast the function parameter.
- let bcx = fcx.entry_bcx.borrow().clone().unwrap();
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, fcx.arg_pos(0) as c_uint) };
let bcx = helper(bcx, llrawptr0, t);
- finish_fn(&fcx, bcx);
+ finish_fn(&fcx, bcx, ty::mk_nil());
llfn
}
use syntax::ast;
use syntax::ast_map;
use syntax::parse::token;
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
let name = match token::get_ident(item.ident).get() {
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
let llfn = bcx.ccx().get_intrinsic(&name);
+ // convert `i1` to a `bool`, and write to the out parameter
let val = Call(bcx, llfn, [a, b], []);
+ let result = ExtractValue(bcx, val, 0);
+ let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
+ let ret = C_undef(type_of::type_of(bcx.ccx(), t));
+ let ret = InsertValue(bcx, ret, result, 0);
+ let ret = InsertValue(bcx, ret, overflow, 1);
if type_is_immediate(bcx.ccx(), t) {
- Ret(bcx, val);
+ Ret(bcx, ret);
} else {
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
- Store(bcx, val, retptr);
+ Store(bcx, ret, retptr);
RetVoid(bcx);
}
}
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p(ccx));
let count = get_param(decl, first_real_arg + 2);
let llfn = ccx.get_intrinsic(&name);
- Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, C_i1(ccx, volatile)], []);
+ Call(bcx, llfn,
+ [dst_ptr, src_ptr, Mul(bcx, size, count), align, C_bool(ccx, volatile)], []);
RetVoid(bcx);
}
let val = get_param(decl, first_real_arg + 1);
let count = get_param(decl, first_real_arg + 2);
let llfn = ccx.get_intrinsic(&name);
- Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, C_i1(ccx, volatile)], []);
+ Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, C_bool(ccx, volatile)], []);
RetVoid(bcx);
}
fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u));
- let y = C_i1(bcx.ccx(), false);
+ let y = C_bool(bcx.ccx(), false);
let llfn = bcx.ccx().get_intrinsic(&name);
let llcall = Call(bcx, llfn, [x, y], []);
Ret(bcx, llcall);
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, decl, item.id, false, output_type,
substs, Some(item.span), &arena);
- init_function(&fcx, true, output_type);
+ let mut bcx = init_function(&fcx, true, output_type);
set_always_inline(fcx.llfn);
- let mut bcx = fcx.entry_bcx.borrow().clone().unwrap();
let first_real_arg = fcx.arg_pos(0u);
let name = token::get_ident(item.ident);
let retty = *substs.substs.types.get(FnSpace, 0);
if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) {
unsafe {
- Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
+ Ret(bcx, lib::llvm::llvm::LLVMGetUndef(arg_type_of(ccx, retty).to_ref()));
}
} else {
RetVoid(bcx)
format!("transmute called on types with different sizes: \
{} ({} bit{}) to \
{} ({} bit{})",
- ty_to_str(ccx.tcx(), in_type),
+ ty_to_string(ccx.tcx(), in_type),
in_type_size,
if in_type_size == 1 {""} else {"s"},
- ty_to_str(ccx.tcx(), out_type),
+ ty_to_string(ccx.tcx(), out_type),
out_type_size,
if out_type_size == 1 {""} else {"s"}).as_slice());
}
.span_err(transmute_restriction.span,
format!("transmute called on types with different sizes: \
{} ({} bit{}) to {} ({} bit{})",
- ty_to_str(ccx.tcx(), transmute_restriction.from),
+ ty_to_string(ccx.tcx(), transmute_restriction.from),
from_type_size as uint,
if from_type_size == 1 {
""
} else {
"s"
},
- ty_to_str(ccx.tcx(), transmute_restriction.to),
+ ty_to_string(ccx.tcx(), transmute_restriction.to),
to_type_size as uint,
if to_type_size == 1 {
""
impl LlvmRepr for Type {
fn llrepr(&self, ccx: &CrateContext) -> String {
- ccx.tn.type_to_str(*self)
+ ccx.tn.type_to_string(*self)
}
}
impl LlvmRepr for ValueRef {
fn llrepr(&self, ccx: &CrateContext) -> String {
- ccx.tn.val_to_str(*self)
+ ccx.tn.val_to_string(*self)
}
}
hash_id.hash(&mut state);
mono_ty.hash(&mut state);
- exported_name(path,
- format!("h{}", state.result()).as_slice(),
- ccx.link_meta.crateid.version_or_default())
+ exported_name(path, format!("h{}", state.result()).as_slice())
});
debug!("monomorphize_fn mangled to {}", s);
use middle::trans::type_::Type;
use middle::trans::type_of::*;
use middle::ty;
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
use std::rc::Rc;
use arena::TypedArena;
debug!("passing {} args:", args.len());
let mut bcx = self.bcx;
for (i, a) in args.iter().enumerate() {
- debug!("arg {}: {}", i, bcx.val_to_str(*a));
+ debug!("arg {}: {}", i, bcx.val_to_string(*a));
}
let result = unpack_result!(bcx, callee::trans_call_inner(
self.bcx, None, mth_ty,
pub fn visit_ty(&mut self, t: ty::t) {
let bcx = self.bcx;
let tcx = bcx.tcx();
- debug!("reflect::visit_ty {}", ty_to_str(bcx.tcx(), t));
+ debug!("reflect::visit_ty {}", ty_to_string(bcx.tcx(), t));
match ty::get(t).sty {
ty::ty_bot => self.leaf("bot"),
ty::ty_trait(..) => {
let extra = [
self.c_slice(token::intern_and_get_ident(
- ty_to_str(tcx, t).as_slice()))
+ ty_to_string(tcx, t).as_slice()))
];
self.visit("trait", extra);
}
ty::ty_trait(..) => {
let extra = [
self.c_slice(token::intern_and_get_ident(
- ty_to_str(tcx, t).as_slice()))
+ ty_to_string(tcx, t).as_slice()))
];
self.visit("trait", extra);
}
let extra = (vec!(
self.c_slice(
- token::intern_and_get_ident(ty_to_str(tcx,
+ token::intern_and_get_ident(ty_to_string(tcx,
t).as_slice())),
self.c_bool(named_fields),
self.c_uint(fields.len())
let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
ty::mk_u64(), &empty_param_substs,
None, &arena);
- init_function(&fcx, false, ty::mk_u64());
+ let bcx = init_function(&fcx, false, ty::mk_u64());
let arg = unsafe {
//
//
llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint)
};
- let bcx = fcx.entry_bcx.borrow().clone().unwrap();
let arg = BitCast(bcx, arg, llptrty);
let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx)));
Store(bcx, ret, fcx.llretptr.get().unwrap());
Some(llreturn) => Br(bcx, llreturn),
None => {}
};
- finish_fn(&fcx, bcx);
+ finish_fn(&fcx, bcx, ty::mk_u64());
llfdecl
};
use middle::trans::type_::Type;
use middle::trans::type_of;
use middle::ty;
-use util::ppaux::ty_to_str;
+use util::ppaux::ty_to_string;
use syntax::ast;
use syntax::parse::token::InternedString;
}
impl VecTypes {
- pub fn to_str(&self, ccx: &CrateContext) -> String {
+ pub fn to_string(&self, ccx: &CrateContext) -> String {
format!("VecTypes {{unit_ty={}, llunit_ty={}, \
llunit_size={}, llunit_alloc_size={}}}",
- ty_to_str(ccx.tcx(), self.unit_ty),
- ccx.tn.type_to_str(self.llunit_ty),
- ccx.tn.val_to_str(self.llunit_size),
+ ty_to_string(ccx.tcx(), self.unit_ty),
+ ccx.tn.type_to_string(self.llunit_ty),
+ ccx.tn.val_to_string(self.llunit_size),
self.llunit_alloc_size)
}
}
// generate the content.
debug!("trans_fixed_vstore(vstore_expr={}, dest={:?})",
- bcx.expr_to_str(vstore_expr), dest.to_str(bcx.ccx()));
+ bcx.expr_to_string(vstore_expr), dest.to_string(bcx.ccx()));
let vt = vec_types_from_expr(bcx, vstore_expr);
let mut bcx = bcx;
debug!("trans_slice_vstore(vstore_expr={}, dest={})",
- bcx.expr_to_str(vstore_expr), dest.to_str(ccx));
+ bcx.expr_to_string(vstore_expr), dest.to_string(ccx));
// Handle the &"..." case:
match content_expr.node {
// Handle the &[...] case:
let vt = vec_types_from_expr(bcx, vstore_expr);
let count = elements_required(bcx, content_expr);
- debug!("vt={}, count={:?}", vt.to_str(ccx), count);
+ debug!("vt={}, count={:?}", vt.to_string(ccx), count);
let llcount = C_uint(ccx, count);
let llfixed;
if count == 0 {
- // Zero-length array: just use NULL as the data pointer
- llfixed = C_null(vt.llunit_ty.ptr_to());
+ // Just create a zero-sized alloca to preserve
+ // the non-null invariant of the inner slice ptr
+ llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
} else {
// Make a fixed-length backing array and allocate it on the stack.
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
*/
debug!("trans_lit_str(lit_expr={}, dest={})",
- bcx.expr_to_str(lit_expr),
- dest.to_str(bcx.ccx()));
+ bcx.expr_to_string(lit_expr),
+ dest.to_string(bcx.ccx()));
match dest {
Ignore => bcx,
* the array elements into them.
*/
- debug!("trans_uniq_vstore(vstore_expr={})", bcx.expr_to_str(vstore_expr));
+ debug!("trans_uniq_vstore(vstore_expr={})", bcx.expr_to_string(vstore_expr));
let fcx = bcx.fcx;
let ccx = fcx.ccx;
let dataptr = get_dataptr(bcx, val);
debug!("alloc_uniq_vec() returned val={}, dataptr={}",
- bcx.val_to_str(val), bcx.val_to_str(dataptr));
+ bcx.val_to_string(val), bcx.val_to_string(dataptr));
let bcx = write_content(bcx, &vt, vstore_expr,
content_expr, SaveIn(dataptr));
let mut bcx = bcx;
debug!("write_content(vt={}, dest={}, vstore_expr={:?})",
- vt.to_str(bcx.ccx()),
- dest.to_str(bcx.ccx()),
- bcx.expr_to_str(vstore_expr));
+ vt.to_string(bcx.ccx()),
+ dest.to_string(bcx.ccx()),
+ bcx.expr_to_string(vstore_expr));
match content_expr.node {
ast::ExprLit(lit) => {
for (i, element) in elements.iter().enumerate() {
let lleltptr = GEPi(bcx, lldest, [i]);
debug!("writing index {:?} with lleltptr={:?}",
- i, bcx.val_to_str(lleltptr));
+ i, bcx.val_to_string(lleltptr));
bcx = expr::trans_into(bcx, &**element,
SaveIn(lleltptr));
fcx.schedule_drop_mem(
}
pub fn bool(ccx: &CrateContext) -> Type {
- Type::i1(ccx)
+ Type::i8(ccx)
}
pub fn char(ccx: &CrateContext) -> Type {
}
pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type {
- let llty = type_of(ccx, arg_ty);
+ let llty = arg_type_of(ccx, arg_ty);
if arg_is_indirect(ccx, arg_ty) {
llty.ptr_to()
} else {
// Arg 0: Output pointer.
// (if the output type is non-immediate)
let use_out_pointer = return_uses_outptr(cx, output);
- let lloutputtype = type_of(cx, output);
+ let lloutputtype = arg_type_of(cx, output);
if use_out_pointer {
atys.push(lloutputtype.ptr_to());
}
llsizingty
}
+pub fn arg_type_of(cx: &CrateContext, t: ty::t) -> Type {
+ if ty::type_is_bool(t) {
+ Type::i1(cx)
+ } else {
+ type_of(cx, t)
+ }
+}
+
// NB: If you update this, be sure to update `sizing_type_of()` as well.
pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// Check the cache.
t,
t_norm.repr(cx.tcx()),
t_norm,
- cx.tn.type_to_str(llty));
+ cx.tn.type_to_string(llty));
cx.lltypes.borrow_mut().insert(t, llty);
return llty;
}
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
- let tps = substs.types.get_vec(subst::TypeSpace);
+ let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
- let tps = substs.types.get_vec(subst::TypeSpace);
+ let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
debug!("--> mapped t={} {:?} to llty={}",
t.repr(cx.tcx()),
t,
- cx.tn.type_to_str(llty));
+ cx.tn.type_to_string(llty));
cx.lltypes.borrow_mut().insert(t, llty);
pub fn llvm_type_name(cx: &CrateContext,
what: named_ty,
did: ast::DefId,
- tps: &Vec<ty::t>)
+ tps: &[ty::t])
-> String
{
let name = match what {
use middle::ty_fold;
use middle::ty_fold::{TypeFoldable,TypeFolder};
use middle;
-use util::ppaux::{note_and_explain_region, bound_region_ptr_to_str};
-use util::ppaux::{trait_store_to_str, ty_to_str};
+use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
+use util::ppaux::{trait_store_to_string, ty_to_string};
use util::ppaux::{Repr, UserString};
use util::common::{indenter};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet, FnvHashMap};
}
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
- !self.types.get_vec(space).is_empty()
+ !self.types.is_empty_in(space)
}
}
fn type_requires(cx: &ctxt, seen: &mut Vec<DefId>,
r_ty: t, ty: t) -> bool {
debug!("type_requires({}, {})?",
- ::util::ppaux::ty_to_str(cx, r_ty),
- ::util::ppaux::ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_string(cx, r_ty),
+ ::util::ppaux::ty_to_string(cx, ty));
let r = {
get(r_ty).sty == get(ty).sty ||
};
debug!("type_requires({}, {})? {}",
- ::util::ppaux::ty_to_str(cx, r_ty),
- ::util::ppaux::ty_to_str(cx, ty),
+ ::util::ppaux::ty_to_string(cx, r_ty),
+ ::util::ppaux::ty_to_string(cx, ty),
r);
return r;
}
fn subtypes_require(cx: &ctxt, seen: &mut Vec<DefId>,
r_ty: t, ty: t) -> bool {
debug!("subtypes_require({}, {})?",
- ::util::ppaux::ty_to_str(cx, r_ty),
- ::util::ppaux::ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_string(cx, r_ty),
+ ::util::ppaux::ty_to_string(cx, ty));
let r = match get(ty).sty {
// fixed length vectors need special treatment compared to
};
debug!("subtypes_require({}, {})? {}",
- ::util::ppaux::ty_to_str(cx, r_ty),
- ::util::ppaux::ty_to_str(cx, ty),
+ ::util::ppaux::ty_to_string(cx, r_ty),
+ ::util::ppaux::ty_to_string(cx, ty),
r);
return r;
fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
ty: t) -> Representability {
debug!("type_structurally_recursive: {}",
- ::util::ppaux::ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_string(cx, ty));
// Compare current type to previously seen types
match get(ty).sty {
}
debug!("is_type_representable: {}",
- ::util::ppaux::ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_string(cx, ty));
// To avoid a stack overflow when checking an enum variant or struct that
// contains a different, structurally recursive type, maintain a stack
Some(t) => t.clone(),
None => cx.sess.bug(
format!("node_id_to_trait_ref: no trait ref for node `{}`",
- cx.map.node_to_str(id)).as_slice())
+ cx.map.node_to_string(id)).as_slice())
}
}
Some(t) => t,
None => cx.sess.bug(
format!("node_id_to_type: no type for node `{}`",
- cx.map.node_to_str(id)).as_slice())
+ cx.map.node_to_string(id)).as_slice())
}
}
format!("the {}th autoderef failed: \
{}",
i,
- ty_to_str(cx, adjusted_ty))
+ ty_to_string(cx, adjusted_ty))
.as_slice());
}
}
// the deref method invoked for `*a` always yields an `&T`
ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
+ // the index method invoked for `a[i]` always yields an `&T`
+ ast::ExprIndex(..) => LvalueExpr,
+
// in the general case, result could be any type, use DPS
_ => RvalueDpsExpr
};
rslt
}
-pub fn ty_sort_str(cx: &ctxt, t: t) -> String {
+pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
match get(t).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str => {
- ::util::ppaux::ty_to_str(cx, t)
+ ::util::ppaux::ty_to_string(cx, t)
}
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
terr_mismatch => "types differ".to_string(),
terr_fn_style_mismatch(values) => {
format!("expected {} fn but found {} fn",
- values.expected.to_str(),
- values.found.to_str())
+ values.expected.to_string(),
+ values.found.to_string())
}
terr_abi_mismatch(values) => {
format!("expected {} fn but found {} fn",
- values.expected.to_str(),
- values.found.to_str())
+ values.expected.to_string(),
+ values.found.to_string())
}
terr_onceness_mismatch(values) => {
format!("expected {} fn but found {} fn",
- values.expected.to_str(),
- values.found.to_str())
+ values.expected.to_string(),
+ values.found.to_string())
}
terr_sigil_mismatch(values) => {
format!("expected {}, found {}",
terr_regions_insufficiently_polymorphic(br, _) => {
format!("expected bound lifetime parameter {}, \
but found concrete lifetime",
- bound_region_ptr_to_str(cx, br))
+ bound_region_ptr_to_string(cx, br))
}
terr_regions_overly_polymorphic(br, _) => {
format!("expected concrete lifetime, \
but found bound lifetime parameter {}",
- bound_region_ptr_to_str(cx, br))
+ bound_region_ptr_to_string(cx, br))
}
terr_trait_stores_differ(_, ref values) => {
format!("trait storage differs: expected `{}` but found `{}`",
- trait_store_to_str(cx, (*values).expected),
- trait_store_to_str(cx, (*values).found))
+ trait_store_to_string(cx, (*values).expected),
+ trait_store_to_string(cx, (*values).found))
}
terr_sorts(values) => {
format!("expected {} but found {}",
- ty_sort_str(cx, values.expected),
- ty_sort_str(cx, values.found))
+ ty_sort_string(cx, values.expected),
+ ty_sort_string(cx, values.found))
}
terr_traits(values) => {
format!("expected trait `{}` but found trait `{}`",
}
terr_int_mismatch(ref values) => {
format!("expected `{}` but found `{}`",
- values.expected.to_str(),
- values.found.to_str())
+ values.expected.to_string(),
+ values.found.to_string())
}
terr_float_mismatch(ref values) => {
format!("expected `{}` but found `{}`",
- values.expected.to_str(),
- values.found.to_str())
+ values.expected.to_string(),
+ values.found.to_string())
}
terr_variadic_mismatch(ref values) => {
format!("expected {} fn but found {} function",
}
pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
- with_path(cx, id, |path| ast_map::path_to_str(path)).to_string()
+ with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
}
pub enum DtorKind {
None => {
cx.sess.bug(
format!("ID not mapped to super-struct: {}",
- cx.map.node_to_str(did.node)).as_slice());
+ cx.map.node_to_string(did.node)).as_slice());
}
}
}
_ => {
cx.sess.bug(
format!("ID not mapped to struct fields: {}",
- cx.map.node_to_str(did.node)).as_slice());
+ cx.map.node_to_string(did.node)).as_slice());
}
}
});
}
impl Variance {
- pub fn to_str(self) -> &'static str {
+ pub fn to_string(self) -> &'static str {
match self {
Covariant => "+",
Contravariant => "-",
let mut types = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_types_from_defs(tcx, &mut types, space,
- generics.types.get_vec(space));
+ generics.types.get_slice(space));
}
// map bound 'a => free 'a
let mut regions = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_region_params(&mut regions, space, free_id,
- generics.regions.get_vec(space));
+ generics.regions.get_slice(space));
}
let free_substs = Substs {
let mut bounds = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_bounds_from_defs(tcx, &mut bounds, space, &free_substs,
- generics.types.get_vec(space));
+ generics.types.get_slice(space));
}
debug!("construct_parameter_environment: free_id={} \
fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
space: subst::ParamSpace,
free_id: ast::NodeId,
- region_params: &Vec<RegionParameterDef>)
+ region_params: &[RegionParameterDef])
{
for r in region_params.iter() {
regions.push(space, ty::free_region_from_def(free_id, r));
fn push_types_from_defs(tcx: &ty::ctxt,
types: &mut subst::VecPerParamSpace<ty::t>,
space: subst::ParamSpace,
- defs: &Vec<TypeParameterDef>) {
+ defs: &[TypeParameterDef]) {
for (i, def) in defs.iter().enumerate() {
let ty = ty::mk_param(tcx, space, i, def.def_id);
types.push(space, ty);
bounds: &mut subst::VecPerParamSpace<ParamBounds>,
space: subst::ParamSpace,
free_substs: &subst::Substs,
- defs: &Vec<TypeParameterDef>) {
+ defs: &[TypeParameterDef]) {
for def in defs.iter() {
let b = (*def.bounds).subst(tcx, free_substs);
bounds.push(space, b);
use syntax::{ast, ast_util};
use syntax::codemap::Span;
use syntax::owned_slice::OwnedSlice;
-use syntax::print::pprust::{lifetime_to_str, path_to_str};
+use syntax::print::pprust::{lifetime_to_string, path_to_string};
pub trait AstConv {
fn tcx<'a>(&'a self) -> &'a ty::ctxt;
};
debug!("ast_region_to_region(lifetime={} id={}) yields {}",
- lifetime_to_str(lifetime),
+ lifetime_to_string(lifetime),
lifetime.id, r.repr(tcx));
r
};
debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {}",
- opt_lifetime.as_ref().map(|e| lifetime_to_str(e)),
+ opt_lifetime.as_ref().map(|e| lifetime_to_string(e)),
r.repr(this.tcx()));
r
};
// Convert the type parameters supplied by the user.
- let ty_param_defs = decl_generics.types.get_vec(TypeSpace);
+ let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count();
let formal_ty_param_count = ty_param_defs.len();
let required_ty_param_count = ty_param_defs.iter()
None => {
tcx.sess.span_bug(ast_ty.span,
format!("unbound path {}",
- path_to_str(path)).as_slice())
+ path_to_string(path)).as_slice())
}
Some(&d) => d
};
.sess
.span_bug(ast_ty.span,
format!("unbound path {}",
- path_to_str(path)).as_slice())
+ path_to_string(path)).as_slice())
}
Some(&d) => d
};
tcx.sess
.span_bug(ast_ty.span,
format!("unbound path {}",
- path_to_str(path)).as_slice())
+ path_to_string(path)).as_slice())
}
Some(&d) => d
};
}
match a_def {
def::DefTrait(_) => {
- let path_str = path_to_str(path);
+ let path_str = path_to_string(path);
tcx.sess.span_err(
ast_ty.span,
format!("reference to trait `{name}` where a \
def::DefMod(id) => {
tcx.sess.span_fatal(ast_ty.span,
format!("found module name used as a type: {}",
- tcx.map.node_to_str(id.node)).as_slice());
+ tcx.map.node_to_string(id.node)).as_slice());
}
def::DefPrimTy(_) => {
fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
}
}
-pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::NodeId, span: Span,
- expected: ty::t, path: &ast::Path,
+pub fn check_struct_pat(pcx: &pat_ctxt, _pat_id: ast::NodeId, span: Span,
+ _expected: ty::t, _path: &ast::Path,
fields: &[ast::FieldPat], etc: bool,
struct_id: ast::DefId,
substitutions: &subst::Substs) {
- let fcx = pcx.fcx;
+ let _fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
let class_fields = ty::lookup_struct_fields(tcx, struct_id);
- // Check to ensure that the struct is the one specified.
- match tcx.def_map.borrow().find(&pat_id) {
- Some(&def::DefStruct(supplied_def_id))
- if supplied_def_id == struct_id => {
- // OK.
- }
- Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => {
- let name = pprust::path_to_str(path);
- tcx.sess
- .span_err(span,
- format!("mismatched types: expected `{}` but found \
- `{}`",
- fcx.infcx().ty_to_str(expected),
- name).as_slice());
- }
- _ => {
- tcx.sess.span_bug(span, "resolve didn't write in struct ID");
- }
- }
-
check_struct_pat_fields(pcx, span, fields, class_fields, struct_id,
substitutions, etc);
}
variant_id, substitutions, etc);
}
Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => {
- let name = pprust::path_to_str(path);
+ let name = pprust::path_to_string(path);
tcx.sess.span_err(span,
format!("mismatched types: expected `{}` but \
found `{}`",
- fcx.infcx().ty_to_str(expected),
+ fcx.infcx().ty_to_string(expected),
name).as_slice());
}
_ => {
let mut error_happened = false;
match *structure {
ty::ty_struct(cid, ref substs) => {
+ // Verify that the pattern named the right structure.
+ let item_did = tcx.def_map.borrow().get(&pat.id).def_id();
+ let struct_did =
+ ty::ty_to_def_id(
+ ty::lookup_item_type(tcx, item_did).ty).unwrap();
+ if struct_did != cid {
+ tcx.sess
+ .span_err(path.span,
+ format!("`{}` does not name the \
+ structure `{}`",
+ pprust::path_to_string(path),
+ fcx.infcx()
+ .ty_to_string(expected)).as_slice())
+ }
+
check_struct_pat(pcx, pat.id, pat.span, expected, path,
fields.as_slice(), etc, cid, substs);
}
"a structure pattern".to_string(),
None);
match tcx.def_map.borrow().find(&pat.id) {
- Some(&def::DefStruct(supplied_def_id)) => {
+ Some(def) => {
check_struct_pat(pcx,
pat.id,
pat.span,
path,
fields.as_slice(),
etc,
- supplied_def_id,
+ def.def_id(),
&subst::Substs::empty());
}
- _ => () // Error, but we're already in an error case
+ None => {
+ tcx.sess.span_bug(pat.span,
+ "whoops, looks like resolve didn't \
+ write a def in here")
+ }
}
error_happened = true;
}
tcx.sess.span_err(
span,
format!("type `{}` cannot be dereferenced",
- fcx.infcx().ty_to_str(expected)).as_slice());
+ fcx.infcx().ty_to_string(expected)).as_slice());
fcx.write_error(pat_id);
}
_ => {
module as the type itself).
Inherent candidates are not always derived from impls. If you have a
-trait instance, such as a value of type `Box<ToStr>`, then the trait
-methods (`to_str()`, in this case) are inherently associated with it.
+trait instance, such as a value of type `Box<ToString>`, then the trait
+methods (`to_string()`, in this case) are inherently associated with it.
Another case is type parameters, in which case the methods of their
bounds are inherent.
Extension candidates are derived from imported traits. If I have the
-trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
-then we will go off to find out whether there is an impl of `ToStr`
+trait `ToString` imported, and I call `to_string()` on a value of type `T`,
+then we will go off to find out whether there is an impl of `ToString`
for `T`. These kinds of method calls are called "extension methods".
They can be defined in any module, not only the one that defined `T`.
Furthermore, you must import the trait to call such a method.
// The subst we get in has Err as the "Self" type. For an object
// type, we don't put any type into the Self paramspace, so let's
// make a copy of rcvr_substs that has the Self paramspace empty.
- obj_substs.types.get_mut_vec(subst::SelfSpace).pop().unwrap();
+ obj_substs.types.pop(subst::SelfSpace).unwrap();
match method_ty.explicit_self {
ast::SelfStatic => {
autoderefs: uint)
-> Option<Option<MethodCallee>> {
debug!("search_step: self_ty={} autoderefs={}",
- self.ty_to_str(self_ty), autoderefs);
+ self.ty_to_string(self_ty), autoderefs);
match self.deref_args {
check::DontDerefArgs => {
did: DefId,
substs: &subst::Substs) {
debug!("push_inherent_candidates_from_object(did={}, substs={})",
- self.did_to_str(did),
+ self.did_to_string(did),
substs.repr(self.tcx()));
let _indenter = indenter();
let tcx = self.tcx();
None => None,
Some(method) => {
debug!("(searching for autoderef'd method) writing \
- adjustment {:?} for {}", adjustment, self.ty_to_str( self_ty));
+ adjustment {:?} for {}", adjustment, self.ty_to_string( self_ty));
match adjustment {
Some((self_expr_id, adj)) => {
self.fcx.write_adjustment(self_expr_id, adj);
fn auto_slice_vec(&self, mt: ty::mt, autoderefs: uint) -> Option<MethodCallee> {
let tcx = self.tcx();
- debug!("auto_slice_vec {}", ppaux::ty_to_str(tcx, mt.ty));
+ debug!("auto_slice_vec {}", ppaux::ty_to_string(tcx, mt.ty));
// First try to borrow to a slice
let entry = self.search_for_some_kind_of_autorefd_method(
* `~[]` to `&[]`.
*/
- debug!("search_for_autosliced_method {}", ppaux::ty_to_str(self.tcx(), self_ty));
+ debug!("search_for_autosliced_method {}", ppaux::ty_to_string(self.tcx(), self_ty));
let sty = ty::get(self_ty).sty.clone();
match sty {
ty_infer(TyVar(_)) => {
self.bug(format!("unexpected type: {}",
- self.ty_to_str(self_ty)).as_slice());
+ self.ty_to_string(self_ty)).as_slice());
}
}
}
}
fn search_for_method(&self, rcvr_ty: ty::t) -> Option<MethodCallee> {
- debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
+ debug!("search_for_method(rcvr_ty={})", self.ty_to_string(rcvr_ty));
let _indenter = indenter();
// I am not sure that inherent methods should have higher
let tcx = self.tcx();
debug!("confirm_candidate(rcvr_ty={}, candidate={})",
- self.ty_to_str(rcvr_ty),
+ self.ty_to_string(rcvr_ty),
candidate.repr(self.tcx()));
self.enforce_object_limitations(candidate);
let m_regions =
self.fcx.infcx().region_vars_for_defs(
self.span,
- candidate.method_ty.generics.regions.get_vec(subst::FnSpace));
+ candidate.method_ty.generics.regions.get_slice(subst::FnSpace));
let all_substs = candidate.rcvr_substs.clone().with_method(m_types, m_regions);
fn_style: bare_fn_ty.fn_style,
abi: bare_fn_ty.abi.clone(),
});
- debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
+ debug!("after replacing bound regions, fty={}", self.ty_to_string(fty));
// Before, we only checked whether self_ty could be a subtype
// of rcvr_ty; now we actually make it so (this may cause
Err(_) => {
self.bug(format!(
"{} was a subtype of {} but now is not?",
- self.ty_to_str(rcvr_ty),
- self.ty_to_str(transformed_self_ty)).as_slice());
+ self.ty_to_string(rcvr_ty),
+ self.ty_to_string(transformed_self_ty)).as_slice());
}
}
// candidate method's `self_ty`.
fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
debug!("is_relevant(rcvr_ty={}, candidate={})",
- self.ty_to_str(rcvr_ty), candidate.repr(self.tcx()));
+ self.ty_to_string(rcvr_ty), candidate.repr(self.tcx()));
return match candidate.method_ty.explicit_self {
SelfStatic => {
self.fcx.tcx()
}
- fn ty_to_str(&self, t: ty::t) -> String {
- self.fcx.infcx().ty_to_str(t)
+ fn ty_to_string(&self, t: ty::t) -> String {
+ self.fcx.infcx().ty_to_string(t)
}
- fn did_to_str(&self, did: DefId) -> String {
+ fn did_to_string(&self, did: DefId) -> String {
ty::item_path_str(self.tcx(), did)
}
};
self.assign(local.id, o_ty);
debug!("Local variable {} is assigned type {}",
- self.fcx.pat_to_str(&*local.pat),
- self.fcx.infcx().ty_to_str(
+ self.fcx.pat_to_string(&*local.pat),
+ self.fcx.infcx().ty_to_string(
self.fcx.inh.locals.borrow().get_copy(&local.id)));
visit::walk_local(self, local, ());
}
self.assign(p.id, None);
debug!("Pattern binding {} is assigned to {}",
token::get_ident(path1.node),
- self.fcx.infcx().ty_to_str(
+ self.fcx.infcx().ty_to_string(
self.fcx.inh.locals.borrow().get_copy(&p.id)));
}
_ => {}
let item = match tcx.map.find(struct_id.node) {
Some(ast_map::NodeItem(item)) => item,
None => fail!("node not in ast map: {}", struct_id.node),
- _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
+ _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
};
match item.node {
format!(
"method `{}` is not a member of trait `{}`",
token::get_ident(impl_method_ty.ident),
- pprust::path_to_str(&ast_trait_ref.path)).as_slice());
+ pprust::path_to_string(&ast_trait_ref.path)).as_slice());
}
}
}
format!("method `{}` has a `{}` declaration in the impl, \
but not in the trait",
token::get_ident(trait_m.ident),
- pprust::explicit_self_to_str(
+ pprust::explicit_self_to_string(
impl_m.explicit_self)).as_slice());
return;
}
format!("method `{}` has a `{}` declaration in the trait, \
but not in the impl",
token::get_ident(trait_m.ident),
- pprust::explicit_self_to_str(
+ pprust::explicit_self_to_string(
trait_m.explicit_self)).as_slice());
return;
}
return;
}
- let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
- .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
+ let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
+ .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
// This code is best explained by example. Consider a trait:
//
let trait_to_skol_substs =
trait_to_impl_substs
.subst(tcx, &impl_to_skol_substs)
- .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
- skol_regions.get_vec(subst::FnSpace).clone());
+ .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
+ Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
declaration",
token::get_ident(trait_m.ident),
i,
- ppaux::trait_ref_to_str(
+ ppaux::trait_ref_to_string(
tcx,
&*impl_trait_bound)).as_slice())
}
let t_e = fcx.expr_ty(e);
- debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
- debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
+ debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
+ debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
if ty::type_is_error(t_e) {
fcx.write_error(id);
fcx.type_error_message(span, |actual| {
format!("cast from nil: `{}` as `{}`",
actual,
- fcx.infcx().ty_to_str(t_1))
+ fcx.infcx().ty_to_string(t_1))
}, t_e, None);
} else if ty::type_is_nil(t_1) {
fcx.type_error_message(span, |actual| {
format!("cast to nil: `{}` as `{}`",
actual,
- fcx.infcx().ty_to_str(t_1))
+ fcx.infcx().ty_to_string(t_1))
}, t_e, None);
}
format!("illegal cast; cast through an \
integer first: `{}` as `{}`",
actual,
- fcx.infcx().ty_to_str(t_1))
+ fcx.infcx().ty_to_string(t_1))
}, t_e, None);
}
// casts from C-like enums are allowed
fcx.type_error_message(span, |actual| {
format!("non-scalar cast: `{}` as `{}`",
actual,
- fcx.infcx().ty_to_str(t_1))
+ fcx.infcx().ty_to_string(t_1))
}, t_e, None);
}
#[inline]
pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
debug!("write_ty({}, {}) in fcx {}",
- node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
+ node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
self.inh.node_types.borrow_mut().insert(node_id, ty);
}
ast_ty_to_ty(self, self.infcx(), ast_t)
}
- pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
+ pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
pat.repr(self.tcx())
}
None => {
self.tcx().sess.bug(
format!("no type for node {}: {} in fcx {}",
- id, self.tcx().map.node_to_str(id),
+ id, self.tcx().map.node_to_string(id),
self.tag()).as_slice());
}
}
None => {
self.tcx().sess.bug(
format!("no method entry for node {}: {} in fcx {}",
- id, self.tcx().map.node_to_str(id),
+ id, self.tcx().map.node_to_string(id),
self.tag()).as_slice());
}
}
}
}
+fn try_overloaded_index(fcx: &FnCtxt,
+ method_call: Option<MethodCall>,
+ expr: &ast::Expr,
+ base_expr: Gc<ast::Expr>,
+ base_ty: ty::t,
+ index_expr: Gc<ast::Expr>,
+ lvalue_pref: LvaluePreference)
+ -> Option<ty::mt> {
+ // Try `IndexMut` first, if preferred.
+ let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
+ (PreferMutLvalue, Some(trait_did)) => {
+ method::lookup_in_trait(fcx,
+ expr.span,
+ Some(&*base_expr),
+ token::intern("index_mut"),
+ trait_did,
+ base_ty,
+ [],
+ DontAutoderefReceiver,
+ IgnoreStaticMethods)
+ }
+ _ => None,
+ };
+
+ // Otherwise, fall back to `Index`.
+ let method = match (method, fcx.tcx().lang_items.index_trait()) {
+ (None, Some(trait_did)) => {
+ method::lookup_in_trait(fcx,
+ expr.span,
+ Some(&*base_expr),
+ token::intern("index"),
+ trait_did,
+ base_ty,
+ [],
+ DontAutoderefReceiver,
+ IgnoreStaticMethods)
+ }
+ (method, _) => method,
+ };
+
+ // Regardless of whether the lookup succeeds, check the method arguments
+ // so that we have *some* type for each argument.
+ let method_type = match method {
+ Some(ref method) => method.ty,
+ None => ty::mk_err()
+ };
+ check_method_argument_types(fcx,
+ expr.span,
+ method_type,
+ expr,
+ [base_expr, index_expr],
+ DoDerefArgs,
+ DontTupleArguments);
+
+ match method {
+ Some(method) => {
+ let ref_ty = ty::ty_fn_ret(method.ty);
+ match method_call {
+ Some(method_call) => {
+ fcx.inh.method_map.borrow_mut().insert(method_call,
+ method);
+ }
+ None => {}
+ }
+ ty::deref(ref_ty, true)
+ }
+ None => None,
+ }
+}
+
fn check_method_argument_types(fcx: &FnCtxt,
sp: Span,
method_fn_ty: ty::t,
};
debug!("check_argument_types: formal_tys={:?}",
- formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
+ formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
// Check the arguments.
// We do this in a pretty awful way: first we typecheck any arguments
let ity = ty::lookup_item_type(tcx, did);
let (n_tps, rps, raw_ty) =
(ity.generics.types.len(subst::TypeSpace),
- ity.generics.regions.get_vec(subst::TypeSpace),
+ ity.generics.regions.get_slice(subst::TypeSpace),
ity.ty);
let rps = vcx.infcx.region_vars_for_defs(span, rps);
operation `{}` not \
supported for floating \
point SIMD vector `{}`",
- ast_util::binop_to_str(op),
+ ast_util::binop_to_string(op),
actual)
},
lhs_t,
|actual| {
format!("binary operation `{}` cannot be applied \
to type `{}`",
- ast_util::binop_to_str(op),
+ ast_util::binop_to_string(op),
actual)
},
lhs_t,
operation `{}=` \
cannot be applied to \
type `{}`",
- ast_util::binop_to_str(op),
+ ast_util::binop_to_string(op),
actual)
},
lhs_t,
trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
fcx.type_error_message(ex.span, |actual| {
format!("binary operation `{}` cannot be applied to type `{}`",
- ast_util::binop_to_str(op),
+ ast_util::binop_to_string(op),
actual)
}, lhs_resolved_t, None)
})
expected_sig);
let fty_sig = fn_ty.sig.clone();
let fty = ty::mk_closure(tcx, fn_ty);
- debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
+ debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
fcx.write_ty(expr.id, fty);
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
match ty::get(base_t).sty {
ty::ty_struct(base_id, ref substs) => {
- debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
+ debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
let fields = ty::lookup_struct_fields(tcx, base_id);
lookup_field_ty(tcx, base_id, fields.as_slice(),
field.node.name, &(*substs))
// Resolve the path.
let def = tcx.def_map.borrow().find(&id).map(|i| *i);
match def {
- Some(def::DefStruct(type_def_id)) => {
- check_struct_constructor(fcx, id, expr.span, type_def_id,
- fields.as_slice(), base_expr);
- }
Some(def::DefVariant(enum_id, variant_id, _)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
variant_id, fields.as_slice());
}
+ Some(def) => {
+ // Verify that this was actually a struct.
+ let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
+ match ty::get(typ.ty).sty {
+ ty::ty_struct(struct_did, _) => {
+ check_struct_constructor(fcx,
+ id,
+ expr.span,
+ struct_did,
+ fields.as_slice(),
+ base_expr);
+ }
+ _ => {
+ tcx.sess
+ .span_err(path.span,
+ format!("`{}` does not name a structure",
+ pprust::path_to_string(
+ path)).as_slice())
+ }
+ }
+ }
_ => {
tcx.sess.span_bug(path.span,
- "structure constructor does not name a structure type");
+ "structure constructor wasn't resolved")
}
}
}
} else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
fcx.write_ty(id, idx_t);
} else {
- let (base_t, autoderefs, field_ty) =
+ let (_, autoderefs, field_ty) =
autoderef(fcx, expr.span, raw_base_t, Some(base.id),
lvalue_pref, |base_t, _| ty::index(base_t));
match field_ty {
fcx.write_autoderef_adjustment(base.id, autoderefs);
}
None => {
- let resolved = structurally_resolved_type(fcx,
- expr.span,
- raw_base_t);
- let ret_ty = lookup_op_method(fcx,
- expr,
- resolved,
- token::intern("index"),
- tcx.lang_items.index_trait(),
- [base.clone(), idx.clone()],
- AutoderefReceiver,
- || {
- fcx.type_error_message(expr.span,
- |actual| {
- format!("cannot index a \
- value of type \
- `{}`", actual)
- },
- base_t,
- None);
- });
- fcx.write_ty(id, ret_ty);
+ // This is an overloaded method.
+ let base_t = structurally_resolved_type(fcx,
+ expr.span,
+ raw_base_t);
+ let method_call = MethodCall::expr(expr.id);
+ match try_overloaded_index(fcx,
+ Some(method_call),
+ expr,
+ *base,
+ base_t,
+ *idx,
+ lvalue_pref) {
+ Some(mt) => fcx.write_ty(id, mt.ty),
+ None => {
+ fcx.type_error_message(expr.span,
+ |actual| {
+ format!("cannot \
+ index a \
+ value of \
+ type `{}`",
+ actual)
+ },
+ base_t,
+ None);
+ fcx.write_ty(id, ty::mk_err())
+ }
+ }
}
}
}
}
debug!("type of expr({}) {} is...", expr.id,
- syntax::print::pprust::expr_to_str(expr));
+ syntax::print::pprust::expr_to_string(expr));
debug!("... {}, expected is {}",
- ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
- expected.repr(tcx))
+ ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
+ expected.repr(tcx));
unifier();
}
format!("this type cannot be instantiated without an \
instance of itself; consider using \
`Option<{}>`",
- ppaux::ty_to_str(tcx, item_ty)).as_slice());
+ ppaux::ty_to_string(tcx, item_ty)).as_slice());
false
} else {
true
dynamically sized types may only \
appear as the final type in a \
variant",
- ppaux::ty_to_str(ccx.tcx,
+ ppaux::ty_to_string(ccx.tcx,
*t)).as_slice());
}
}
match v.node.disr_expr {
Some(e) => {
- debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
+ debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
let inh = blank_inherited_fields(ccx);
let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
// a problem.
for &space in ParamSpace::all().iter() {
adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
- assert_eq!(substs.types.get_vec(space).len(),
- type_defs.get_vec(space).len());
+ assert_eq!(substs.types.len(space), type_defs.len(space));
adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
- assert_eq!(substs.regions().get_vec(space).len(),
- region_defs.get_vec(space).len());
+ assert_eq!(substs.regions().len(space), region_defs.len(space));
}
fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
*/
{
- let type_count = type_defs.get_vec(space).len();
- assert_eq!(substs.types.get_vec(space).len(), 0);
+ let type_count = type_defs.len(space);
+ assert_eq!(substs.types.len(space), 0);
for (i, &typ) in segment.types.iter().enumerate() {
let t = fcx.to_ty(&*typ);
if i < type_count {
but found {} parameter(s)",
type_count,
segment.types.len()).as_slice());
- substs.types.get_mut_vec(space).truncate(0);
+ substs.types.truncate(space, 0);
}
}
}
{
- let region_count = region_defs.get_vec(space).len();
- assert_eq!(substs.regions().get_vec(space).len(), 0);
+ let region_count = region_defs.len(space);
+ assert_eq!(substs.regions().len(space), 0);
for (i, lifetime) in segment.lifetimes.iter().enumerate() {
let r = ast_region_to_region(fcx.tcx(), lifetime);
if i < region_count {
expected {} parameter(s) but found {} parameter(s)",
region_count,
segment.lifetimes.len()).as_slice());
- substs.mut_regions().get_mut_vec(space).truncate(0);
+ substs.mut_regions().truncate(space, 0);
}
}
}
defs: &VecPerParamSpace<ty::TypeParameterDef>,
substs: &mut Substs)
{
- let provided_len = substs.types.get_vec(space).len();
- let desired = defs.get_vec(space).as_slice();
+ let provided_len = substs.types.len(space);
+ let desired = defs.get_slice(space);
let required_len = desired.iter()
.take_while(|d| d.default.is_none())
.count();
// Nothing specified at all: supply inference variables for
// everything.
if provided_len == 0 {
- let provided = substs.types.get_mut_vec(space);
- *provided = fcx.infcx().next_ty_vars(desired.len());
+ substs.types.replace(space,
+ fcx.infcx().next_ty_vars(desired.len()));
return;
}
qualifier,
required_len,
provided_len).as_slice());
- let provided = substs.types.get_mut_vec(space);
- *provided = Vec::from_elem(desired.len(), ty::mk_err());
+ substs.types.replace(space,
+ Vec::from_elem(desired.len(), ty::mk_err()));
return;
}
let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
substs.types.push(space, default);
}
- assert_eq!(substs.types.get_vec(space).len(), desired.len());
+ assert_eq!(substs.types.len(space), desired.len());
debug!("Final substs: {}", substs.repr(fcx.tcx()));
}
defs: &VecPerParamSpace<ty::RegionParameterDef>,
substs: &mut Substs)
{
- let provided = substs.mut_regions().get_mut_vec(space);
- let desired = defs.get_vec(space);
+ let provided_len = substs.mut_regions().len(space);
+ let desired = defs.get_slice(space);
// Enforced by `push_explicit_parameters_from_segment_to_substs()`.
- assert!(provided.len() <= desired.len());
+ assert!(provided_len <= desired.len());
// If nothing was provided, just use inference variables.
- if provided.len() == 0 {
- *provided = fcx.infcx().region_vars_for_defs(span, desired);
+ if provided_len == 0 {
+ substs.mut_regions().replace(
+ space,
+ fcx.infcx().region_vars_for_defs(span, desired));
return;
}
// If just the right number were provided, everybody is happy.
- if provided.len() == desired.len() {
+ if provided_len == desired.len() {
return;
}
expected {} parameter(s) \
but found {} parameter(s)",
desired.len(),
- provided.len()).as_slice());
+ provided_len).as_slice());
- *provided = fcx.infcx().region_vars_for_defs(span, desired);
+ substs.mut_regions().replace(
+ space,
+ fcx.infcx().region_vars_for_defs(span, desired));
}
}
tps: &OwnedSlice<ast::TyParam>,
ty: ty::t) {
debug!("check_bounds_are_used(n_tps={}, ty={})",
- tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
+ tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
// make a vector of booleans initially false, set to true when used
if tps.len() == 0u { return; }
fty,
|| {
format!("intrinsic has wrong type: expected `{}`",
- ppaux::ty_to_str(ccx.tcx, fty))
+ ppaux::ty_to_string(ccx.tcx, fty))
});
}
}
use middle::typeck::MethodCall;
use middle::pat_util;
use util::nodemap::NodeMap;
-use util::ppaux::{ty_to_str, region_to_str, Repr};
+use util::ppaux::{ty_to_string, region_to_string, Repr};
use syntax::ast;
use syntax::codemap::Span;
let r_deref_expr = ty::ReScope(deref_expr.id);
for i in range(0u, derefs) {
debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
- rcx.fcx.infcx().ty_to_str(derefd_ty),
+ rcx.fcx.infcx().ty_to_string(derefd_ty),
i, derefs);
let method_call = MethodCall::autoderef(deref_expr.id, i);
*/
debug!("constrain_index(index_expr=?, indexed_ty={}",
- rcx.fcx.infcx().ty_to_str(indexed_ty));
+ rcx.fcx.infcx().ty_to_string(indexed_ty));
let r_index_expr = ty::ReScope(index_expr.id);
match ty::get(indexed_ty).sty {
|method_call| rcx.resolve_method_type(method_call));
debug!("constrain_regions_in_type_of_node(\
ty={}, ty0={}, id={}, minimum_lifetime={:?})",
- ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
+ ty_to_string(tcx, ty), ty_to_string(tcx, ty0),
id, minimum_lifetime);
constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
}
let tcx = rcx.fcx.ccx.tcx;
debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
- region_to_str(tcx, "", false, minimum_lifetime),
- ty_to_str(tcx, ty));
+ region_to_string(tcx, "", false, minimum_lifetime),
+ ty_to_string(tcx, ty));
relate_nested_regions(tcx, Some(minimum_lifetime), ty, |r_sub, r_sup| {
debug!("relate_nested_regions(r_sub={}, r_sup={})",
let rptr_ty = rcx.resolve_node_type(id);
if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
let tcx = rcx.fcx.ccx.tcx;
- debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty));
+ debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
let r = ty::ty_region(tcx, span, rptr_ty);
link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
cmt_borrowed);
let mut map = HashMap::new();
let fn_sig = {
let mut f = ty_fold::RegionFolder::regions(tcx, |r| {
- debug!("region r={}", r.to_str());
+ debug!("region r={}", r.to_string());
match r {
ty::ReLateBound(s, br) if s == fn_sig.binder_id => {
*map.find_or_insert_with(br, |_| mapf(br))
}
for &t in all_tys.iter() {
- debug!("relate_free_regions(t={})", ppaux::ty_to_str(tcx, t));
+ debug!("relate_free_regions(t={})", ppaux::ty_to_string(tcx, t));
relate_nested_regions(tcx, None, t, |a, b| {
match (&a, &b) {
(&ty::ReFree(free_a), &ty::ReFree(free_b)) => {
use middle::typeck::check::{FnCtxt, impl_self_ty};
use middle::typeck::check::{structurally_resolved_type};
use middle::typeck::check::writeback;
-use middle::typeck::infer::fixup_err_to_str;
+use middle::typeck::infer::fixup_err_to_string;
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer;
use middle::typeck::{vtable_origin, vtable_res, vtable_param_res};
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::Span;
-use syntax::print::pprust::expr_to_str;
+use syntax::print::pprust::expr_to_string;
use syntax::visit;
use syntax::visit::Visitor;
vcx.tcx().sess.span_fatal(span,
format!("failed to find an implementation of \
trait {} for {}",
- vcx.infcx.trait_ref_to_str(&*trait_ref),
- vcx.infcx.ty_to_str(ty)).as_slice());
+ vcx.infcx.trait_ref_to_string(&*trait_ref),
+ vcx.infcx.ty_to_string(ty)).as_slice());
}
}
true
let tcx = vcx.tcx();
tcx.sess.span_err(span,
format!("expected {}, but found {} ({})",
- ppaux::trait_ref_to_str(tcx, &r_exp_trait_ref),
- ppaux::trait_ref_to_str(tcx, &r_act_trait_ref),
+ ppaux::trait_ref_to_string(tcx, &r_exp_trait_ref),
+ ppaux::trait_ref_to_string(tcx, &r_act_trait_ref),
ty::type_err_to_str(tcx, err)).as_slice());
}
}
debug!("(checking vtable) num 2 relating trait \
ty {} to of_trait_ref {}",
- vcx.infcx.trait_ref_to_str(&*trait_ref),
- vcx.infcx.trait_ref_to_str(&*of_trait_ref));
+ vcx.infcx.trait_ref_to_string(&*trait_ref),
+ vcx.infcx.trait_ref_to_string(&*of_trait_ref));
relate_trait_refs(vcx, span, of_trait_ref, trait_ref.clone());
tcx.sess.span_fatal(span,
format!("cannot determine a type for this bounded type \
parameter: {}",
- fixup_err_to_str(e)).as_slice())
+ fixup_err_to_string(e)).as_slice())
}
Err(_) => {
None
}
debug!("vtable: early_resolve_expr() ex with id {:?} (early: {}): {}",
- ex.id, is_early, expr_to_str(ex));
+ ex.id, is_early, expr_to_string(ex));
let _indent = indenter();
let cx = fcx.ccx;
ex.span,
format!("can only cast an boxed pointer \
to a boxed object, not a {}",
- ty::ty_sort_str(fcx.tcx(), src_ty)).as_slice());
+ ty::ty_sort_string(fcx.tcx(), src_ty)).as_slice());
}
_ => {}
}
ex.span,
format!("can only cast an &-pointer \
to an &-object, not a {}",
- ty::ty_sort_str(fcx.tcx(), src_ty)).as_slice());
+ ty::ty_sort_string(fcx.tcx(), src_ty)).as_slice());
}
_ => {}
}
let did = def.def_id();
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));
+ fcx.infcx().ty_to_string(item_ty.ty));
debug!("early_resolve_expr: looking up vtables for type params {}",
item_ty.generics.types.repr(fcx.tcx()));
let vcx = fcx.vtable_context();
use syntax::ast;
use syntax::codemap::Span;
-use syntax::print::pprust::pat_to_str;
+use syntax::print::pprust::pat_to_string;
use syntax::visit;
use syntax::visit::Visitor;
self.visit_node_id(ResolvingPattern(p.span), p.id);
debug!("Type for pattern binding {} (id {}) resolved to {}",
- pat_to_str(p),
+ pat_to_string(p),
p.id,
ty::node_id_to_type(self.tcx(), p.id).repr(self.tcx()));
span,
format!("cannot determine a type for \
this expression: {}",
- infer::fixup_err_to_str(e)).as_slice())
+ infer::fixup_err_to_string(e)).as_slice())
}
ResolvingLocal(span) => {
span,
format!("cannot determine a type for \
this local variable: {}",
- infer::fixup_err_to_str(e)).as_slice())
+ infer::fixup_err_to_string(e)).as_slice())
}
ResolvingPattern(span) => {
span,
format!("cannot determine a type for \
this pattern binding: {}",
- infer::fixup_err_to_str(e)).as_slice())
+ infer::fixup_err_to_string(e)).as_slice())
}
ResolvingUpvar(upvar_id) => {
captured variable `{}`: {}",
ty::local_var_name_str(
self.tcx,
- upvar_id.var_id).get().to_str(),
- infer::fixup_err_to_str(e)).as_slice());
+ upvar_id.var_id).get().to_string(),
+ infer::fixup_err_to_string(e)).as_slice());
}
ResolvingImplRes(span) => {
*/
let meth_tps: Vec<ty::t> =
- method.generics.types.get_vec(subst::FnSpace)
+ method.generics.types.get_slice(subst::FnSpace)
.iter()
.map(|def| ty::mk_param_from_def(tcx, def))
.collect();
let meth_regions: Vec<ty::Region> =
- method.generics.regions.get_vec(subst::FnSpace)
+ method.generics.regions.get_slice(subst::FnSpace)
.iter()
.map(|def| ty::ReEarlyBound(def.def_id.node, def.space,
def.index, def.name))
// replace the type parameters declared on the trait with those
// from the impl
for &space in [subst::TypeSpace, subst::SelfSpace].iter() {
- *method_generics.types.get_mut_vec(space) =
- impl_poly_type.generics.types.get_vec(space).clone();
- *method_generics.regions.get_mut_vec(space) =
- impl_poly_type.generics.regions.get_vec(space).clone();
+ method_generics.types.replace(
+ space,
+ Vec::from_slice(impl_poly_type.generics.types.get_slice(space)));
+ method_generics.regions.replace(
+ space,
+ Vec::from_slice(impl_poly_type.generics.regions.get_slice(space)));
}
debug!("subst_receiver_types_in_method_ty: method_generics={}",
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
-use syntax::print::pprust::{path_to_str};
+use syntax::print::pprust::{path_to_string};
use syntax::visit;
struct CollectItemTypesVisitor<'a> {
ccx.tcx.sess.span_fatal(
ast_trait_ref.path.span,
format!("`{}` is not a trait",
- path_to_str(&ast_trait_ref.path)).as_slice());
+ path_to_string(&ast_trait_ref.path)).as_slice());
}
}
}
_ => {}
}
- let (generics, sized, supertraits) = match it.node {
- ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
- (generics, sized, supertraits)
+ let (generics, unbound, supertraits) = match it.node {
+ ast::ItemTrait(ref generics, ref unbound, ref supertraits, _) => {
+ (generics, unbound, supertraits)
}
ref s => {
tcx.sess.span_bug(
generics);
let builtin_bounds =
- ensure_supertraits(ccx, it.id, it.span, supertraits, sized);
+ ensure_supertraits(ccx, it.id, it.span, supertraits, unbound);
let substs = mk_item_substs(ccx, &ty_generics);
let trait_def = Rc::new(ty::TraitDef {
id: ast::NodeId,
sp: codemap::Span,
ast_trait_refs: &Vec<ast::TraitRef>,
- sized: ast::Sized)
+ unbound: &Option<ast::TyParamBound>)
-> ty::BuiltinBounds
{
let tcx = ccx.tcx;
}
}
- if sized == ast::StaticSize {
- match tcx.lang_items.require(SizedTraitLangItem) {
- Ok(def_id) => {
- ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
- }
- Err(s) => tcx.sess.err(s.as_slice()),
- };
- }
-
+ add_unsized_bound(ccx, unbound, &mut bounds, "trait", sp);
tcx.supertraits.borrow_mut().insert(local_def(id),
Rc::new(ty_trait_refs));
bounds
debug!("type of {} (id {}) is {}",
token::get_ident(it.ident),
it.id,
- ppaux::ty_to_str(tcx, pty.ty));
+ ppaux::ty_to_string(tcx, pty.ty));
ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
return pty;
&generics.ty_params, base_generics)
}
+// Add the Sized bound, unless the type parameter is marked as `Sized?`.
+fn add_unsized_bound(ccx: &CrateCtxt,
+ unbound: &Option<ast::TyParamBound>,
+ bounds: &mut ty::BuiltinBounds,
+ desc: &str,
+ span: Span) {
+ let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
+ match unbound {
+ &Some(TraitTyParamBound(ref tpb)) => {
+ // #FIXME(8559) currently requires the unbound to be built-in.
+ let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
+ match kind_id {
+ Ok(kind_id) if trait_def_id != kind_id => {
+ ccx.tcx.sess.span_warn(span,
+ format!("default bound relaxed \
+ for a {}, but this does \
+ nothing because the given \
+ bound is not a default. \
+ Only `Sized?` is supported.",
+ desc).as_slice());
+ ty::try_add_builtin_trait(ccx.tcx,
+ kind_id,
+ bounds);
+ }
+ _ => {}
+ }
+ }
+ _ if kind_id.is_ok() => {
+ ty::try_add_builtin_trait(ccx.tcx,
+ kind_id.unwrap(),
+ bounds);
+ }
+ // No lang item for Sized, so we can't add it as a bound.
+ _ => {}
+ }
+}
+
fn ty_generics(ccx: &CrateCtxt,
space: subst::ParamSpace,
lifetimes: &Vec<ast::Lifetime>,
let bounds = Rc::new(compute_bounds(ccx,
param_ty,
¶m.bounds,
- param.sized,
+ ¶m.unbound,
param.ident,
param.span));
let default = param.default.map(|path| {
ccx: &CrateCtxt,
param_ty: ty::ParamTy,
ast_bounds: &OwnedSlice<ast::TyParamBound>,
- sized: ast::Sized,
+ unbound: &Option<ast::TyParamBound>,
ident: ast::Ident,
span: Span) -> ty::ParamBounds
{
}
}
- if sized == ast::StaticSize {
- match ccx.tcx.lang_items.require(SizedTraitLangItem) {
- Ok(def_id) => { ty::try_add_builtin_trait(ccx.tcx,
- def_id,
- &mut param_bounds.builtin_bounds); },
- // Fixme(13367) after `type` makes it into the snapshot, we can check this properly
- Err(_s) => {}, //ccx.tcx.sess.err(s),
- }
- }
+ add_unsized_bound(ccx,
+ unbound,
+ &mut param_bounds.builtin_bounds,
+ "type parameter",
+ span);
check_bounds_compatible(ccx.tcx, ¶m_bounds, ident, span);
format!("incompatible bounds on type parameter {}, \
bound {} does not allow unsized type",
token::get_ident(ident),
- ppaux::trait_ref_to_str(tcx,
+ ppaux::trait_ref_to_string(tcx,
&*trait_ref)).as_slice());
}
true
let mut substs = subst::Substs::empty();
for &space in subst::ParamSpace::all().iter() {
- let a_tps = a_subst.types.get_vec(space);
- let b_tps = b_subst.types.get_vec(space);
- let tps = if_ok!(self.tps(space,
- a_tps.as_slice(),
- b_tps.as_slice()));
-
- let a_regions = a_subst.regions().get_vec(space);
- let b_regions = b_subst.regions().get_vec(space);
- let r_variances = variances.regions.get_vec(space);
+ let a_tps = a_subst.types.get_slice(space);
+ let b_tps = b_subst.types.get_slice(space);
+ let tps = if_ok!(self.tps(space, a_tps, b_tps));
+
+ let a_regions = a_subst.regions().get_slice(space);
+ let b_regions = b_subst.regions().get_slice(space);
+ let r_variances = variances.regions.get_slice(space);
let regions = if_ok!(relate_region_params(self,
item_def_id,
r_variances,
a_regions,
b_regions));
- *substs.types.get_mut_vec(space) = tps;
- *substs.mut_regions().get_mut_vec(space) = regions;
+ substs.types.replace(space, tps);
+ substs.mut_regions().replace(space, regions);
}
return Ok(substs);
fn relate_region_params<C:Combine>(this: &C,
item_def_id: ast::DefId,
- variances: &Vec<ty::Variance>,
- a_rs: &Vec<ty::Region>,
- b_rs: &Vec<ty::Region>)
+ variances: &[ty::Variance],
+ a_rs: &[ty::Region],
+ b_rs: &[ty::Region])
-> cres<Vec<ty::Region>>
{
let tcx = this.infcx().tcx;
assert_eq!(num_region_params, b_rs.len());
let mut rs = vec!();
for i in range(0, num_region_params) {
- let a_r = *a_rs.get(i);
- let b_r = *b_rs.get(i);
- let variance = *variances.get(i);
+ let a_r = a_rs[i];
+ let b_r = b_rs[i];
+ let variance = variances[i];
let r = match variance {
ty::Invariant => {
eq_regions(this, a_r, b_r)
use syntax::parse::token;
use syntax::print::pprust;
use util::ppaux::UserString;
-use util::ppaux::bound_region_to_str;
+use util::ppaux::bound_region_to_string;
use util::ppaux::note_and_explain_region;
pub trait ErrorReporting {
ty::local_var_name_str(self.tcx,
upvar_id.var_id)
.get()
- .to_str()).as_slice());
+ .to_string()).as_slice());
note_and_explain_region(
self.tcx,
"...the borrowed pointer is valid for ",
ty::local_var_name_str(self.tcx,
upvar_id.var_id)
.get()
- .to_str()).as_slice(),
+ .to_string()).as_slice(),
sup,
"");
}
outlive the enclosing closure",
ty::local_var_name_str(self.tcx,
id).get()
- .to_str()).as_slice());
+ .to_string()).as_slice());
note_and_explain_region(
self.tcx,
"captured variable is valid for ",
var_origins: &[RegionVariableOrigin],
trace_origins: &[(TypeTrace, ty::type_err)],
same_regions: &[SameRegions]) {
- self.give_suggestion(same_regions);
for vo in var_origins.iter() {
self.report_inference_failure(vo.clone());
}
+ self.give_suggestion(same_regions);
for &(ref trace, terr) in trace_origins.iter() {
self.report_type_error(trace.clone(), &terr);
}
ident: ty_param.ident,
id: ty_param.id,
bounds: bounds,
+ unbound: ty_param.unbound.clone(),
default: ty_param.default,
span: ty_param.span,
- sized: ty_param.sized,
}
})
}
.sess
.fatal(format!(
"unbound path {}",
- pprust::path_to_str(path)).as_slice())
+ pprust::path_to_string(path)).as_slice())
}
Some(&d) => d
};
opt_explicit_self: Option<ast::ExplicitSelf_>,
generics: &ast::Generics,
span: codemap::Span) {
- let suggested_fn = pprust::fun_to_str(decl, fn_style, ident,
+ let suggested_fn = pprust::fun_to_string(decl, fn_style, ident,
opt_explicit_self, generics);
let msg = format!("consider using an explicit lifetime \
parameter as shown: {}", suggested_fn);
infer::Coercion(_) => " for automatic coercion".to_string(),
infer::LateBoundRegion(_, br) => {
format!(" for {}in function call",
- bound_region_to_str(self.tcx, "lifetime parameter ", true, br))
+ bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
}
infer::BoundRegionInFnType(_, br) => {
format!(" for {}in function type",
- bound_region_to_str(self.tcx, "lifetime parameter ", true, br))
+ bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
}
infer::EarlyBoundRegion(_, name) => {
format!(" for lifetime parameter `{}",
}
infer::UpvarRegion(ref upvar_id, _) => {
format!(" for capture of `{}` by closure",
- ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_str())
+ ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_string())
}
};
"...so that closure can access `{}`",
ty::local_var_name_str(self.tcx, upvar_id.var_id)
.get()
- .to_str()).as_slice())
+ .to_string()).as_slice())
}
infer::InfStackClosure(span) => {
self.tcx.sess.span_note(
does not outlive the enclosing closure",
ty::local_var_name_str(
self.tcx,
- id).get().to_str()).as_slice());
+ id).get().to_string()).as_slice());
}
infer::IndexSlice(span) => {
self.tcx.sess.span_note(
let mut lifetime;
loop {
let mut s = String::from_str("'");
- s.push_str(num_to_str(self.counter.get()).as_slice());
+ s.push_str(num_to_string(self.counter.get()).as_slice());
if !self.taken.contains(&s) {
lifetime = name_to_dummy_lifetime(
token::str_to_ident(s.as_slice()).name);
return lifetime;
// 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
- fn num_to_str(counter: uint) -> String {
+ fn num_to_string(counter: uint) -> String {
let mut s = String::new();
let (n, r) = (counter/26 + 1, counter % 26);
let letter: char = from_u32((r+97) as u32).unwrap();
use syntax::ast::{Onceness, FnStyle};
use std::collections::HashMap;
use util::common::{indenter};
-use util::ppaux::mt_to_str;
+use util::ppaux::mt_to_string;
use util::ppaux::Repr;
pub struct Glb<'f>(pub CombineFields<'f>); // "greatest lower bound" (common subtype)
debug!("{}.mts({}, {})",
self.tag(),
- mt_to_str(tcx, a),
- mt_to_str(tcx, b));
+ mt_to_string(tcx, a),
+ mt_to_string(tcx, b));
match (a.mutbl, b.mutbl) {
// If one side or both is mut, then the GLB must use
use middle::typeck::infer::combine::*;
use middle::typeck::infer::glb::Glb;
use middle::typeck::infer::lub::Lub;
-use middle::typeck::infer::unify::{Root, UnifyKey};
+use middle::typeck::infer::unify::*;
use middle::typeck::infer::sub::Sub;
use util::ppaux::Repr;
* - If the variables do not both have an upper bound, we will unify
* the variables and return the unified variable, in which case the
* result is a variable. This is indicated with a `VarResult`
- * return.
- */
+ * return. */
pub fn lattice_vars<L:LatticeDir+Combine,
T:LatticeValue,
K:UnifyKey<Bounds<T>>>(
use syntax::ast::{NormalFn, UnsafeFn};
use syntax::ast::{Onceness, FnStyle};
use syntax::ast::{MutMutable, MutImmutable};
-use util::ppaux::mt_to_str;
+use util::ppaux::mt_to_string;
use util::ppaux::Repr;
pub struct Lub<'f>(pub CombineFields<'f>); // least-upper-bound: common supertype
debug!("{}.mts({}, {})",
self.tag(),
- mt_to_str(tcx, a),
- mt_to_str(tcx, b));
+ mt_to_string(tcx, a),
+ mt_to_string(tcx, b));
if a.mutbl != b.mutbl {
return Err(ty::terr_mutability)
use syntax::codemap;
use syntax::codemap::Span;
use util::common::indent;
-use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr};
+use util::ppaux::{bound_region_to_string, ty_to_string, trait_ref_to_string, Repr};
pub mod doc;
pub mod macros;
region_var_bound_by_region_var(RegionVid, RegionVid)
}
-pub fn fixup_err_to_str(f: fixup_err) -> String {
+pub fn fixup_err_to_string(f: fixup_err) -> String {
match f {
unresolved_int_ty(_) => {
"cannot determine the type of this integer; add a suffix to \
pub fn region_vars_for_defs(&self,
span: Span,
- defs: &Vec<ty::RegionParameterDef>)
+ defs: &[ty::RegionParameterDef])
-> Vec<ty::Region> {
defs.iter()
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
assert!(generics.regions.len(subst::FnSpace) == 0);
let type_parameter_count = generics.types.len(subst::TypeSpace);
- let region_param_defs = generics.regions.get_vec(subst::TypeSpace);
+ let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
let regions = self.region_vars_for_defs(span, region_param_defs);
let type_parameters = self.next_ty_vars(type_parameter_count);
subst::Substs::new_type(type_parameters, regions)
self.report_region_errors(&errors); // see error_reporting.rs
}
- pub fn ty_to_str(&self, t: ty::t) -> String {
- ty_to_str(self.tcx,
+ pub fn ty_to_string(&self, t: ty::t) -> String {
+ ty_to_string(self.tcx,
self.resolve_type_vars_if_possible(t))
}
- pub fn tys_to_str(&self, ts: &[ty::t]) -> String {
- let tstrs: Vec<String> = ts.iter().map(|t| self.ty_to_str(*t)).collect();
+ pub fn tys_to_string(&self, ts: &[ty::t]) -> String {
+ let tstrs: Vec<String> = ts.iter().map(|t| self.ty_to_string(*t)).collect();
format!("({})", tstrs.connect(", "))
}
- pub fn trait_ref_to_str(&self, t: &ty::TraitRef) -> String {
+ pub fn trait_ref_to_string(&self, t: &ty::TraitRef) -> String {
let t = self.resolve_type_vars_in_trait_ref_if_possible(t);
- trait_ref_to_str(self.tcx, &t)
+ trait_ref_to_string(self.tcx, &t)
}
pub fn resolve_type_vars_if_possible(&self, typ: ty::t) -> ty::t {
self.tcx.sess.bug(
format!("resolve_type_vars_if_possible() yielded {} \
when supplied with {}",
- self.ty_to_str(dummy0),
- self.ty_to_str(dummy1)).as_slice());
+ self.ty_to_string(dummy0),
+ self.ty_to_string(dummy1)).as_slice());
}
}
}
Some(e) => {
self.tcx.sess.span_err(sp,
format!("{}{}",
- mk_msg(Some(self.ty_to_str(e)), actual_ty),
+ mk_msg(Some(self.ty_to_string(e)), actual_ty),
error_str).as_slice());
}
}
return;
}
- self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_str(actual_ty), err);
+ self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_string(actual_ty), err);
}
pub fn report_mismatched_types(&self,
// if I leave out : String, it infers &str and complains
|actual: String| {
format!("mismatched types: expected `{}` but found `{}`",
- self.ty_to_str(resolved_expected),
+ self.ty_to_string(resolved_expected),
actual)
}
}
let rvar = self.next_region_var(
BoundRegionInFnType(trace.origin.span(), br));
debug!("Bound region {} maps to {:?}",
- bound_region_to_str(self.tcx, "", false, br),
+ bound_region_to_string(self.tcx, "", false, br),
rvar);
rvar
});
use middle::typeck::infer::{unresolved_ty};
use syntax::codemap::Span;
use util::common::indent;
-use util::ppaux::{Repr, ty_to_str};
+use util::ppaux::{Repr, ty_to_string};
pub static resolve_nested_tvar: uint = 0b0000000001;
pub static resolve_rvar: uint = 0b0000000010;
self.err = None;
debug!("Resolving {} (modes={:x})",
- ty_to_str(self.infcx.tcx, typ),
+ ty_to_string(self.infcx.tcx, typ),
self.modes);
// n.b. This is a hokey mess because the current fold doesn't
match self.err {
None => {
debug!("Resolved to {} + {} (modes={:x})",
- ty_to_str(self.infcx.tcx, rty),
- ty_to_str(self.infcx.tcx, rty),
+ ty_to_string(self.infcx.tcx, rty),
+ ty_to_string(self.infcx.tcx, rty),
self.modes);
return Ok(rty);
}
use middle::typeck::infer::then;
use middle::typeck::infer::{TypeTrace, Subtype};
use util::common::{indenter};
-use util::ppaux::{bound_region_to_str, Repr};
+use util::ppaux::{bound_region_to_string, Repr};
use syntax::ast::{Onceness, FnStyle, MutImmutable, MutMutable};
replace_late_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
let skol = self.get_ref().infcx.region_vars.new_skolemized(br);
debug!("Bound region {} skolemized to {:?}",
- bound_region_to_str(self.get_ref().infcx.tcx, "", false, br),
+ bound_region_to_string(self.get_ref().infcx.tcx, "", false, br),
skol);
skol
})
use syntax::codemap::{Span, CodeMap, DUMMY_SP};
use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note};
use syntax::ast;
-use syntax::crateid::CrateId;
-use util::ppaux::{ty_to_str, UserString};
+use util::ppaux::{ty_to_string, UserString};
struct Env<'a> {
krate: ast::Crate,
let krate_config = Vec::new();
let input = driver::StrInput(source_string.to_owned());
let krate = driver::phase_1_parse_input(&sess, krate_config, &input);
- let krate_id = CrateId { path: "test".to_owned(),
- name: "test".to_owned(),
- version: None };
let (krate, ast_map) =
- driver::phase_2_configure_and_expand(&sess, krate, &krate_id)
+ driver::phase_2_configure_and_expand(&sess, krate, "test")
.expect("phase 2 aborted");
// run just enough stuff to build a tcx:
pub fn assert_subtype(&self, a: ty::t, b: ty::t) {
if !self.is_subtype(a, b) {
fail!("{} is not a subtype of {}, but it should be",
- self.ty_to_str(a),
- self.ty_to_str(b));
+ self.ty_to_string(a),
+ self.ty_to_string(b));
}
}
pub fn assert_not_subtype(&self, a: ty::t, b: ty::t) {
if self.is_subtype(a, b) {
fail!("{} is a subtype of {}, but it shouldn't be",
- self.ty_to_str(a),
- self.ty_to_str(b));
+ self.ty_to_string(a),
+ self.ty_to_string(b));
}
}
self.assert_subtype(b, a);
}
- pub fn ty_to_str(&self, a: ty::t) -> String {
- ty_to_str(self.tcx, a)
+ pub fn ty_to_string(&self, a: ty::t) -> String {
+ ty_to_string(self.tcx, a)
}
pub fn t_fn(&self,
/// Checks that `GLB(t1,t2) == t_glb`
pub fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) {
debug!("check_glb(t1={}, t2={}, t_glb={})",
- self.ty_to_str(t1),
- self.ty_to_str(t2),
- self.ty_to_str(t_glb));
+ self.ty_to_string(t1),
+ self.ty_to_string(t2),
+ self.ty_to_string(t_glb));
match self.glb().tys(t1, t2) {
Err(e) => {
fail!("unexpected error computing LUB: {:?}", e)
match self.lub().tys(t1, t2) {
Err(_) => {}
Ok(t) => {
- fail!("unexpected success computing LUB: {}", self.ty_to_str(t))
+ fail!("unexpected success computing LUB: {}", self.ty_to_string(t))
}
}
}
match self.glb().tys(t1, t2) {
Err(_) => {}
Ok(t) => {
- fail!("unexpected success computing GLB: {}", self.ty_to_str(t))
+ fail!("unexpected success computing GLB: {}", self.ty_to_string(t))
}
}
}
// Functions that write types into the node type table
pub fn write_ty_to_tcx(tcx: &ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
- debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_str(tcx, ty));
+ debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty));
assert!(!ty::type_needs_infer(ty));
tcx.node_types.borrow_mut().insert(node_id as uint, ty);
}
require_same_types(tcx, None, false, main_span, main_t, se_ty,
|| {
format!("main function expects type: `{}`",
- ppaux::ty_to_str(ccx.tcx, se_ty))
+ ppaux::ty_to_string(ccx.tcx, se_ty))
});
}
_ => {
tcx.sess.span_bug(main_span,
format!("main has a non-function type: found \
`{}`",
- ppaux::ty_to_str(tcx,
+ ppaux::ty_to_string(tcx,
main_t)).as_slice());
}
}
require_same_types(tcx, None, false, start_span, start_t, se_ty,
|| {
format!("start function expects type: `{}`",
- ppaux::ty_to_str(ccx.tcx, se_ty))
+ ppaux::ty_to_string(ccx.tcx, se_ty))
});
}
tcx.sess.span_bug(start_span,
format!("start has a non-function type: found \
`{}`",
- ppaux::ty_to_str(tcx,
+ ppaux::ty_to_string(tcx,
start_t)).as_slice());
}
}
None => {
self.tcx().sess.bug(format!(
"no inferred index entry for {}",
- self.tcx().map.node_to_str(param_id)).as_slice());
+ self.tcx().map.node_to_string(param_id)).as_slice());
}
}
}
let is_inferred;
macro_rules! cannot_happen { () => { {
fail!("invalid parent: {:s} for {:s}",
- tcx.map.node_to_str(parent_id),
- tcx.map.node_to_str(param_id));
+ tcx.map.node_to_string(parent_id),
+ tcx.map.node_to_string(param_id));
} } }
match parent {
InferredIndex(index): InferredIndex,
variance: VarianceTermPtr<'a>) {
debug!("add_constraint(index={}, variance={})",
- index, variance.to_str());
+ index, variance.to_string());
self.constraints.push(Constraint { inferred: InferredIndex(index),
variance: variance });
}
// All type parameters on enums and structs should be
// in the TypeSpace.
- assert!(generics.types.get_vec(subst::SelfSpace).is_empty());
- assert!(generics.types.get_vec(subst::FnSpace).is_empty());
- assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
- assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
+ assert!(generics.types.is_empty_in(subst::SelfSpace));
+ assert!(generics.types.is_empty_in(subst::FnSpace));
+ assert!(generics.regions.is_empty_in(subst::SelfSpace));
+ assert!(generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs(
def_id,
- generics.types.get_vec(subst::TypeSpace),
- generics.regions.get_vec(subst::TypeSpace),
+ generics.types.get_slice(subst::TypeSpace),
+ generics.regions.get_slice(subst::TypeSpace),
substs,
variance);
}
// Traits DO have a Self type parameter, but it is
// erased from object types.
- assert!(!generics.types.get_vec(subst::SelfSpace).is_empty() &&
- substs.types.get_vec(subst::SelfSpace).is_empty());
+ assert!(!generics.types.is_empty_in(subst::SelfSpace) &&
+ substs.types.is_empty_in(subst::SelfSpace));
// Traits never declare region parameters in the self
// space.
- assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
+ assert!(generics.regions.is_empty_in(subst::SelfSpace));
// Traits never declare type/region parameters in the
// fn space.
- assert!(generics.types.get_vec(subst::FnSpace).is_empty());
- assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
+ assert!(generics.types.is_empty_in(subst::FnSpace));
+ assert!(generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs(
def_id,
- generics.types.get_vec(subst::TypeSpace),
- generics.regions.get_vec(subst::TypeSpace),
+ generics.types.get_slice(subst::TypeSpace),
+ generics.regions.get_slice(subst::TypeSpace),
substs,
variance);
}
/// object, etc) appearing in a context with ambient variance `variance`
fn add_constraints_from_substs(&mut self,
def_id: ast::DefId,
- type_param_defs: &Vec<ty::TypeParameterDef>,
- region_param_defs: &Vec<ty::RegionParameterDef>,
+ type_param_defs: &[ty::TypeParameterDef],
+ region_param_defs: &[ty::RegionParameterDef],
substs: &subst::Substs,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?})", def_id);
.param_id,
old_value,
new_value,
- term.to_str());
+ term.to_string());
*self.solutions.get_mut(inferred) = new_value;
changed = true;
use middle::ty::{BoundRegion, BrAnon, BrNamed};
use middle::ty::{BrFresh, ctxt};
use middle::ty::{mt, t, ParamTy};
-use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
- ReEmpty};
+use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup};
BrFresh(_) => "an anonymous lifetime defined on".to_string(),
_ => {
format!("the lifetime {} as defined on",
- bound_region_ptr_to_str(cx, fr.bound_region))
+ bound_region_ptr_to_string(cx, fr.bound_region))
}
};
}
}
-pub fn bound_region_ptr_to_str(cx: &ctxt, br: BoundRegion) -> String {
- bound_region_to_str(cx, "", false, br)
+pub fn bound_region_ptr_to_string(cx: &ctxt, br: BoundRegion) -> String {
+ bound_region_to_string(cx, "", false, br)
}
-pub fn bound_region_to_str(cx: &ctxt,
+pub fn bound_region_to_string(cx: &ctxt,
prefix: &str, space: bool,
br: BoundRegion) -> String {
let space_str = if space { " " } else { "" };
// In general, if you are giving a region error message,
// you should use `explain_region()` or, better yet,
// `note_and_explain_region()`
-pub fn region_ptr_to_str(cx: &ctxt, region: Region) -> String {
- region_to_str(cx, "&", true, region)
+pub fn region_ptr_to_string(cx: &ctxt, region: Region) -> String {
+ region_to_string(cx, "&", true, region)
}
-pub fn region_to_str(cx: &ctxt, prefix: &str, space: bool, region: Region) -> String {
+pub fn region_to_string(cx: &ctxt, prefix: &str, space: bool, region: Region) -> String {
let space_str = if space { " " } else { "" };
if cx.sess.verbose() {
ty::ReEarlyBound(_, _, _, name) => {
token::get_name(name).get().to_string()
}
- ty::ReLateBound(_, br) => bound_region_to_str(cx, prefix, space, br),
- ty::ReFree(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
+ ty::ReLateBound(_, br) => bound_region_to_string(cx, prefix, space, br),
+ ty::ReFree(ref fr) => bound_region_to_string(cx, prefix, space, fr.bound_region),
ty::ReInfer(ReSkolemized(_, br)) => {
- bound_region_to_str(cx, prefix, space, br)
+ bound_region_to_string(cx, prefix, space, br)
}
ty::ReInfer(ReVar(_)) => prefix.to_string(),
ty::ReStatic => format!("{}'static{}", prefix, space_str),
}
}
-pub fn mutability_to_str(m: ast::Mutability) -> String {
+pub fn mutability_to_string(m: ast::Mutability) -> String {
match m {
ast::MutMutable => "mut ".to_string(),
ast::MutImmutable => "".to_string(),
}
}
-pub fn mt_to_str(cx: &ctxt, m: &mt) -> String {
- format!("{}{}", mutability_to_str(m.mutbl), ty_to_str(cx, m.ty))
+pub fn mt_to_string(cx: &ctxt, m: &mt) -> String {
+ format!("{}{}", mutability_to_string(m.mutbl), ty_to_string(cx, m.ty))
}
+#[cfg(stage0)]
pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> String {
+ trait_store_to_string(cx, s)
+}
+
+pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String {
match s {
ty::UniqTraitStore => "Box ".to_string(),
ty::RegionTraitStore(r, m) => {
- format!("{}{}", region_ptr_to_str(cx, r), mutability_to_str(m))
+ format!("{}{}", region_ptr_to_string(cx, r), mutability_to_string(m))
}
}
}
-pub fn vec_map_to_str<T>(ts: &[T], f: |t: &T| -> String) -> String {
+pub fn vec_map_to_string<T>(ts: &[T], f: |t: &T| -> String) -> String {
let tstrs = ts.iter().map(f).collect::<Vec<String>>();
format!("[{}]", tstrs.connect(", "))
}
-pub fn fn_sig_to_str(cx: &ctxt, typ: &ty::FnSig) -> String {
+pub fn fn_sig_to_string(cx: &ctxt, typ: &ty::FnSig) -> String {
format!("fn{}{} -> {}", typ.binder_id, typ.inputs.repr(cx),
typ.output.repr(cx))
}
-pub fn trait_ref_to_str(cx: &ctxt, trait_ref: &ty::TraitRef) -> String {
+pub fn trait_ref_to_string(cx: &ctxt, trait_ref: &ty::TraitRef) -> String {
trait_ref.user_string(cx).to_string()
}
+#[cfg(stage0)]
pub fn ty_to_str(cx: &ctxt, typ: t) -> String {
- fn fn_input_to_str(cx: &ctxt, input: ty::t) -> String {
- ty_to_str(cx, input).to_string()
+ ty_to_string(cx, typ)
+}
+
+pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
+ fn fn_input_to_string(cx: &ctxt, input: ty::t) -> String {
+ ty_to_string(cx, input).to_string()
}
- fn bare_fn_to_str(cx: &ctxt,
+ fn bare_fn_to_string(cx: &ctxt,
fn_style: ast::FnStyle,
abi: abi::Abi,
ident: Option<ast::Ident>,
match fn_style {
ast::NormalFn => {}
_ => {
- s.push_str(fn_style.to_str().as_slice());
+ s.push_str(fn_style.to_string().as_slice());
s.push_char(' ');
}
};
if abi != abi::Rust {
- s.push_str(format!("extern {} ", abi.to_str()).as_slice());
+ s.push_str(format!("extern {} ", abi.to_string()).as_slice());
};
s.push_str("fn");
_ => { }
}
- push_sig_to_str(cx, &mut s, '(', ')', sig);
+ push_sig_to_string(cx, &mut s, '(', ')', sig);
s
}
- fn closure_to_str(cx: &ctxt, cty: &ty::ClosureTy) -> String {
+ fn closure_to_string(cx: &ctxt, cty: &ty::ClosureTy) -> String {
let mut s = String::new();
match cty.store {
ty::UniqTraitStore => {}
ty::RegionTraitStore(region, _) => {
- s.push_str(region_to_str(cx, "", true, region).as_slice());
+ s.push_str(region_to_string(cx, "", true, region).as_slice());
}
}
match cty.fn_style {
ast::NormalFn => {}
_ => {
- s.push_str(cty.fn_style.to_str().as_slice());
+ s.push_str(cty.fn_style.to_string().as_slice());
s.push_char(' ');
}
};
ty::UniqTraitStore => {
assert_eq!(cty.onceness, ast::Once);
s.push_str("proc");
- push_sig_to_str(cx, &mut s, '(', ')', &cty.sig);
+ push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
}
ty::RegionTraitStore(..) => {
match cty.onceness {
ast::Many => {}
ast::Once => s.push_str("once ")
}
- push_sig_to_str(cx, &mut s, '|', '|', &cty.sig);
+ push_sig_to_string(cx, &mut s, '|', '|', &cty.sig);
}
}
s
}
- fn push_sig_to_str(cx: &ctxt,
+ fn push_sig_to_string(cx: &ctxt,
s: &mut String,
bra: char,
ket: char,
sig: &ty::FnSig) {
s.push_char(bra);
- let strs: Vec<String> = sig.inputs.iter().map(|a| fn_input_to_str(cx, *a)).collect();
+ let strs: Vec<String> = sig.inputs.iter().map(|a| fn_input_to_string(cx, *a)).collect();
s.push_str(strs.connect(", ").as_slice());
if sig.variadic {
s.push_str(", ...");
if ty::type_is_bot(sig.output) {
s.push_char('!');
} else {
- s.push_str(ty_to_str(cx, sig.output).as_slice());
+ s.push_str(ty_to_string(cx, sig.output).as_slice());
}
}
}
ty_bot => "!".to_string(),
ty_bool => "bool".to_string(),
ty_char => "char".to_string(),
- ty_int(t) => ast_util::int_ty_to_str(t, None).to_string(),
- ty_uint(t) => ast_util::uint_ty_to_str(t, None).to_string(),
- ty_float(t) => ast_util::float_ty_to_str(t).to_string(),
- ty_box(typ) => format!("Gc<{}>", ty_to_str(cx, typ)),
- ty_uniq(typ) => format!("Box<{}>", ty_to_str(cx, typ)),
+ ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
+ ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
+ ty_float(t) => ast_util::float_ty_to_string(t).to_string(),
+ ty_box(typ) => format!("Gc<{}>", ty_to_string(cx, typ)),
+ ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)),
ty_ptr(ref tm) => {
format!("*{} {}", match tm.mutbl {
ast::MutMutable => "mut",
ast::MutImmutable => "const",
- }, ty_to_str(cx, tm.ty))
+ }, ty_to_string(cx, tm.ty))
}
ty_rptr(r, ref tm) => {
- let mut buf = region_ptr_to_str(cx, r);
- buf.push_str(mt_to_str(cx, tm).as_slice());
+ let mut buf = region_ptr_to_string(cx, r);
+ buf.push_str(mt_to_string(cx, tm).as_slice());
buf
}
ty_tup(ref elems) => {
- let strs: Vec<String> = elems.iter().map(|elem| ty_to_str(cx, *elem)).collect();
+ let strs: Vec<String> = elems.iter().map(|elem| ty_to_string(cx, *elem)).collect();
format!("({})", strs.connect(","))
}
ty_closure(ref f) => {
- closure_to_str(cx, *f)
+ closure_to_string(cx, *f)
}
ty_bare_fn(ref f) => {
- bare_fn_to_str(cx, f.fn_style, f.abi, None, &f.sig)
+ bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig)
}
- ty_infer(infer_ty) => infer_ty.to_str(),
+ ty_infer(infer_ty) => infer_ty.to_string(),
ty_err => "[type error]".to_string(),
ty_param(ParamTy {idx: id, def_id: did, ..}) => {
let ident = match cx.ty_param_defs.borrow().find(&did.node) {
ty_vec(ref mt, sz) => {
match sz {
Some(n) => {
- format!("[{}, .. {}]", mt_to_str(cx, mt), n)
+ format!("[{}, .. {}]", mt_to_string(cx, mt), n)
}
- None => format!("[{}]", ty_to_str(cx, mt.ty)),
+ None => format!("[{}]", ty_to_string(cx, mt.ty)),
}
}
}
subst::ErasedRegions => { }
subst::NonerasedRegions(ref regions) => {
for &r in regions.iter() {
- let s = region_to_str(cx, "", false, r);
+ let s = region_to_string(cx, "", false, r);
if !s.is_empty() {
strs.push(s)
} else {
}
}
- let tps = substs.types.get_vec(subst::TypeSpace);
- let ty_params = generics.types.get_vec(subst::TypeSpace);
+ let tps = substs.types.get_slice(subst::TypeSpace);
+ let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults && !cx.sess.verbose() {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
};
for t in tps.slice_to(tps.len() - num_defaults).iter() {
- strs.push(ty_to_str(cx, *t))
+ strs.push(ty_to_string(cx, *t))
}
if cx.sess.verbose() {
- for t in substs.types.get_vec(subst::SelfSpace).iter() {
+ for t in substs.types.get_slice(subst::SelfSpace).iter() {
strs.push(format!("for {}", t.repr(cx)));
}
}
}
fn repr_vec<T:Repr>(tcx: &ctxt, v: &[T]) -> String {
- vec_map_to_str(v, |t| t.repr(tcx))
+ vec_map_to_string(v, |t| t.repr(tcx))
}
impl<'a, T:Repr> Repr for &'a [T] {
impl Repr for ty::t {
fn repr(&self, tcx: &ctxt) -> String {
- ty_to_str(tcx, *self)
+ ty_to_string(tcx, *self)
}
}
impl Repr for ty::mt {
fn repr(&self, tcx: &ctxt) -> String {
- mt_to_str(tcx, self)
+ mt_to_string(tcx, self)
}
}
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
fn repr(&self, tcx: &ctxt) -> String {
format!("[{};{};{}]",
- self.get_vec(subst::TypeSpace).repr(tcx),
- self.get_vec(subst::SelfSpace).repr(tcx),
- self.get_vec(subst::FnSpace).repr(tcx))
+ self.get_slice(subst::TypeSpace).repr(tcx),
+ self.get_slice(subst::SelfSpace).repr(tcx),
+ self.get_slice(subst::FnSpace).repr(tcx))
}
}
impl Repr for ty::TraitRef {
fn repr(&self, tcx: &ctxt) -> String {
- trait_ref_to_str(tcx, self)
+ trait_ref_to_string(tcx, self)
}
}
impl Repr for ast::Expr {
fn repr(&self, _tcx: &ctxt) -> String {
- format!("expr({}: {})", self.id, pprust::expr_to_str(self))
+ format!("expr({}: {})", self.id, pprust::expr_to_string(self))
}
}
impl Repr for ast::Path {
fn repr(&self, _tcx: &ctxt) -> String {
- format!("path({})", pprust::path_to_str(self))
+ format!("path({})", pprust::path_to_string(self))
}
}
impl Repr for ast::Item {
fn repr(&self, tcx: &ctxt) -> String {
- format!("item({})", tcx.map.node_to_str(self.id))
+ format!("item({})", tcx.map.node_to_string(self.id))
}
}
fn repr(&self, _tcx: &ctxt) -> String {
format!("stmt({}: {})",
ast_util::stmt_id(self),
- pprust::stmt_to_str(self))
+ pprust::stmt_to_string(self))
}
}
impl Repr for ast::Pat {
fn repr(&self, _tcx: &ctxt) -> String {
- format!("pat({}: {})", self.id, pprust::pat_to_str(self))
+ format!("pat({}: {})", self.id, pprust::pat_to_string(self))
}
}
impl Repr for ty::Variance {
fn repr(&self, _: &ctxt) -> String {
- // The first `.to_str()` returns a &'static str (it is not an implementation
- // of the ToStr trait). Because of that, we need to call `.to_str()` again
+ // The first `.to_string()` returns a &'static str (it is not an implementation
+ // of the ToString trait). Because of that, we need to call `.to_string()` again
// if we want to have a `String`.
- self.to_str().to_str()
+ self.to_string().to_string()
}
}
fn repr(&self, tcx: &ctxt) -> String {
format!("BareFnTy {{fn_style: {:?}, abi: {}, sig: {}}}",
self.fn_style,
- self.abi.to_str(),
+ self.abi.to_string(),
self.sig.repr(tcx))
}
}
impl Repr for ty::FnSig {
fn repr(&self, tcx: &ctxt) -> String {
- fn_sig_to_str(tcx, self)
+ fn_sig_to_string(tcx, self)
}
}
impl Repr for ty::TraitStore {
fn repr(&self, tcx: &ctxt) -> String {
- trait_store_to_str(tcx, *self)
+ trait_store_to_string(tcx, *self)
}
}
impl Repr for Span {
fn repr(&self, tcx: &ctxt) -> String {
- tcx.sess.codemap().span_to_str(*self).to_string()
+ tcx.sess.codemap().span_to_string(*self).to_string()
}
}
impl UserString for ty::t {
fn user_string(&self, tcx: &ctxt) -> String {
- ty_to_str(tcx, *self)
+ ty_to_string(tcx, *self)
}
}
impl Repr for abi::Abi {
fn repr(&self, _tcx: &ctxt) -> String {
- self.to_str()
+ self.to_string()
}
}
impl UserString for abi::Abi {
fn user_string(&self, _tcx: &ctxt) -> String {
- self.to_str()
+ self.to_string()
}
}
cx.inlined.borrow_mut().get_mut_ref().insert(did);
ret.push(clean::Item {
source: clean::Span::empty(),
- name: Some(fqn.last().unwrap().to_str()),
+ name: Some(fqn.last().unwrap().to_string()),
attrs: load_attrs(tcx, did),
inner: inner,
visibility: Some(ast::Public),
match cx.maybe_typed {
core::Typed(ref tcx) => {
let fqn = csearch::get_item_path(tcx, did);
- let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
+ let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
}
core::NotTyped(..) => {}
// Figure out the name of this crate
let input = driver::FileInput(cx.src.clone());
- let t_outputs = driver::build_output_filenames(&input,
- &None,
- &None,
- self.attrs.as_slice(),
- cx.sess());
- let id = link::find_crate_id(self.attrs.as_slice(),
- t_outputs.out_filestem.as_slice());
+ let name = link::find_crate_name(None, self.attrs.as_slice(), &input);
// Clean the crate, translating the entire libsyntax AST to one that is
// understood by rustdoc.
}
Crate {
- name: id.name.to_string(),
+ name: name.to_string(),
module: Some(module),
externs: externs,
primitives: primitives,
List(s.get().to_string(), l.clean().move_iter().collect())
}
ast::MetaNameValue(ref s, ref v) => {
- NameValue(s.get().to_string(), lit_to_str(v))
+ NameValue(s.get().to_string(), lit_to_string(v))
}
}
}
}
fn external_path(name: &str, substs: &subst::Substs) -> Path {
- let lifetimes = substs.regions().get_vec(subst::TypeSpace)
+ let lifetimes = substs.regions().get_slice(subst::TypeSpace)
.iter()
.filter_map(|v| v.clean())
.collect();
- let types = substs.types.get_vec(subst::TypeSpace).clean();
+ let types = Vec::from_slice(substs.types.get_slice(subst::TypeSpace));
+ let types = types.clean();
Path {
global: false,
segments: vec![PathSegment {
external_path("Share", &empty)),
};
let fqn = csearch::get_item_path(tcx, did);
- let fqn = fqn.move_iter().map(|i| i.to_str()).collect();
+ let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
cx.external_paths.borrow_mut().get_mut_ref().insert(did,
(fqn, TypeTrait));
TraitBound(ResolvedPath {
core::NotTyped(_) => return RegionBound,
};
let fqn = csearch::get_item_path(tcx, self.def_id);
- let fqn = fqn.move_iter().map(|i| i.to_str())
+ let fqn = fqn.move_iter().map(|i| i.to_string())
.collect::<Vec<String>>();
let path = external_path(fqn.last().unwrap().as_slice(),
&self.substs);
// is implicit.
let space = {
- if !self.types.get_vec(subst::FnSpace).is_empty() ||
- !self.regions.get_vec(subst::FnSpace).is_empty()
+ if !self.types.is_empty_in(subst::FnSpace) ||
+ !self.regions.is_empty_in(subst::FnSpace)
{
subst::FnSpace
} else {
};
Generics {
- type_params: self.types.get_vec(space).clean(),
- lifetimes: self.regions.get_vec(space).clean(),
+ type_params: Vec::from_slice(self.types.get_slice(space)).clean(),
+ lifetimes: Vec::from_slice(self.regions.get_slice(space)).clean(),
}
}
}
return None
}
- pub fn to_str(&self) -> &'static str {
+ pub fn to_string(&self) -> &'static str {
match *self {
Int => "int",
I8 => "i8",
pub fn to_url_str(&self) -> &'static str {
match *self {
Unit => "unit",
- other => other.to_str(),
+ other => other.to_string(),
}
}
lifetimes: Vec::new(), type_params: Vec::new()
},
decl: (ast_util::local_def(0), &fty.sig).clean(),
- abi: fty.abi.to_str(),
+ abi: fty.abi.to_string(),
}),
ty::ty_closure(ref fty) => {
let decl = box ClosureDecl {
ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
let fqn = csearch::get_item_path(get_cx().tcx(), did);
let fqn: Vec<String> = fqn.move_iter().map(|i| {
- i.to_str()
+ i.to_string()
}).collect();
let kind = match ty::get(*self).sty {
ty::ty_struct(..) => TypeStruct,
ty::ty_trait(..) => TypeTrait,
_ => TypeEnum,
};
- let path = external_path(fqn.last().unwrap().to_str().as_slice(),
+ let path = external_path(fqn.last().unwrap().to_string().as_slice(),
substs);
get_cx().external_paths.borrow_mut().get_mut_ref()
.insert(did, (fqn, kind));
}
}
-fn path_to_str(p: &ast::Path) -> String {
+fn path_to_string(p: &ast::Path) -> String {
let mut s = String::new();
let mut first = true;
for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
type_params: Vec::new(),
},
decl: self.decl.clean(),
- abi: self.abi.to_str(),
+ abi: self.abi.to_string(),
}
}
}
}
}
-fn lit_to_str(lit: &ast::Lit) -> String {
+fn lit_to_string(lit: &ast::Lit) -> String {
match lit.node {
ast::LitStr(ref st, _) => st.get().to_string(),
ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
res
},
ast::LitChar(c) => format!("'{}'", c),
- ast::LitInt(i, _t) => i.to_str(),
- ast::LitUint(u, _t) => u.to_str(),
- ast::LitIntUnsuffixed(i) => i.to_str(),
+ ast::LitInt(i, _t) => i.to_string(),
+ ast::LitUint(u, _t) => u.to_string(),
+ ast::LitIntUnsuffixed(i) => i.to_string(),
ast::LitFloat(ref f, _t) => f.get().to_string(),
ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
- ast::LitBool(b) => b.to_str(),
+ ast::LitBool(b) => b.to_string(),
ast::LitNil => "".to_string(),
}
}
PatWild => "_".to_string(),
PatWildMulti => "..".to_string(),
PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
- PatEnum(ref p, _) => path_to_str(p),
+ PatEnum(ref p, _) => path_to_string(p),
PatStruct(..) => fail!("tried to get argument name from pat_struct, \
which is not allowed in function arguments"),
PatTup(..) => "(tuple arg NYI)".to_string(),
use rustc::{driver, middle};
use rustc::middle::{privacy, ty};
use rustc::lint;
+use rustc::back::link;
use syntax::ast;
use syntax::parse::token;
}
let krate = phase_1_parse_input(&sess, cfg, &input);
+
+ let name = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
+ &input);
+
let (krate, ast_map)
- = phase_2_configure_and_expand(&sess, krate, &from_str("rustdoc").unwrap())
+ = phase_2_configure_and_expand(&sess, krate, name.as_slice())
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let driver::driver::CrateAnalysis {
exported_items, public_items, ty_cx, ..
- } = phase_3_run_analysis_passes(sess, &krate, ast_map);
+ } = phase_3_run_analysis_passes(sess, &krate, ast_map, name);
debug!("crate: {:?}", krate);
(DocContext {
tybounds(f, typarams)
}
clean::Self(..) => f.write("Self".as_bytes()),
- clean::Primitive(prim) => primitive_link(f, prim, prim.to_str()),
+ clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
clean::Closure(ref decl, ref region) => {
write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}",
style = FnStyleSpace(decl.fn_style),
} else {
let mut m = decl.bounds
.iter()
- .map(|s| s.to_str());
+ .map(|s| s.to_string());
format!(
": {}",
m.collect::<Vec<String>>().connect(" + "))
match *stab {
Some(ref stability) => {
write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
- lvl = stability.level.to_str(),
+ lvl = stability.level.to_string(),
reason = stability.text)
}
None => Ok(())
match *stab {
Some(ref stability) => {
write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
- lvl = stability.level.to_str(),
+ lvl = stability.level.to_string(),
colon = if stability.text.len() > 0 { ": " } else { "" },
reason = stability.text)
}
// miscellaneous, no highlighting
t::DOT | t::DOTDOT | t::DOTDOTDOT | t::COMMA | t::SEMI |
t::COLON | t::MOD_SEP | t::LARROW | t::LPAREN |
- t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE => "",
+ t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE | t::QUESTION => "",
t::DOLLAR => {
if t::is_ident(&lexer.peek().tok) {
is_macro_nonterminal = true;
// Transform the contents of the header into a hyphenated string
let id = s.as_slice().words().map(|s| {
match s.to_ascii_opt() {
- Some(s) => s.to_lower().into_str(),
+ Some(s) => s.to_lower().into_string(),
None => s.to_string()
}
}).collect::<Vec<String>>().connect("-");
}
try!(write!(&mut w, r#"[{:u},"{}","{}",{}"#,
item.ty, item.name, path,
- item.desc.to_json().to_str()));
+ item.desc.to_json().to_string()));
match item.parent {
Some(nodeid) => {
let pathid = *nodeid_to_pathid.find(&nodeid).unwrap();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "rustdoc#0.11.0"]
+#![crate_id = "rustdoc#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "rustdoc"]
#![experimental]
#![desc = "rustdoc, the Rust documentation extractor"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(globs, struct_variant, managed_boxes, macro_rules, phase)]
}
};
match json::from_reader(&mut input) {
- Err(s) => Err(s.to_str()),
+ Err(s) => Err(s.to_string()),
Ok(json::Object(obj)) => {
let mut obj = obj;
// Make sure the schema is what we expect
}));
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
- &from_str("rustdoc-test").unwrap())
+ "rustdoc-test")
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let ctx = box(GC) core::DocContext {
Mary had a little lamb, Little lamb
Mary had a little lamb, Little lamb";
- fn bench_to_str(b: &mut Bencher, s: &str) {
+ fn bench_to_string(b: &mut Bencher, s: &str) {
b.iter(|| {
let c_str = s.to_c_str();
check(s, c_str.as_ptr());
#[bench]
fn bench_to_c_str_short(b: &mut Bencher) {
- bench_to_str(b, s_short)
+ bench_to_string(b, s_short)
}
#[bench]
fn bench_to_c_str_medium(b: &mut Bencher) {
- bench_to_str(b, s_medium)
+ bench_to_string(b, s_medium)
}
#[bench]
fn bench_to_c_str_long(b: &mut Bencher) {
- bench_to_str(b, s_long)
+ bench_to_string(b, s_long)
}
fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "rustrt#0.11.0"]
+#![crate_id = "rustrt#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "rustrt"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(linkage, lang_items, unsafe_destructor)]
#![no_std]
#![experimental]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;
*/
-#![crate_id = "rustuv#0.11.0"]
+#![crate_id = "rustuv#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "rustuv"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![feature(macro_rules, unsafe_destructor)]
#![deny(unused_result, unused_must_use)]
#![allow(visible_private_types)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate green;
#[cfg(test)] extern crate debug;
#[test]
fn error_smoke_test() {
let err: UvError = UvError(uvll::EOF);
- assert_eq!(err.to_str(), "EOF: end of file".to_string());
+ assert_eq!(err.to_string(), "EOF: end of file".to_string());
}
#[cfg(unix)]
fn join_multicast(&mut self, multi: rtio::IpAddr) -> Result<(), IoError> {
let _m = self.fire_homing_missile();
status_to_io_result(unsafe {
- multi.to_str().with_c_str(|m_addr| {
+ multi.to_string().with_c_str(|m_addr| {
uvll::uv_udp_set_membership(self.handle,
m_addr, ptr::null(),
uvll::UV_JOIN_GROUP)
fn leave_multicast(&mut self, multi: rtio::IpAddr) -> Result<(), IoError> {
let _m = self.fire_homing_missile();
status_to_io_result(unsafe {
- multi.to_str().with_c_str(|m_addr| {
+ multi.to_string().with_c_str(|m_addr| {
uvll::uv_udp_set_membership(self.handle,
m_addr, ptr::null(),
uvll::UV_LEAVE_GROUP)
//! An example version number with all five components is
//! `0.8.1-rc.3.0+20130922.linux`.
-#![crate_id = "semver#0.11.0"]
+#![crate_id = "semver#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "semver"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::char;
use std::cmp;
let v = parse_iter(&mut s.chars());
match v {
Some(v) => {
- if v.to_str().equiv(&s) {
+ if v.to_string().equiv(&s) {
Some(v)
} else {
None
}
#[test]
-fn test_to_str() {
- assert_eq!(parse("1.2.3").unwrap().to_str(), "1.2.3".to_string());
- assert_eq!(parse("1.2.3-alpha1").unwrap().to_str(), "1.2.3-alpha1".to_string());
- assert_eq!(parse("1.2.3+build.42").unwrap().to_str(), "1.2.3+build.42".to_string());
- assert_eq!(parse("1.2.3-alpha1+42").unwrap().to_str(), "1.2.3-alpha1+42".to_string());
+fn test_to_string() {
+ assert_eq!(parse("1.2.3").unwrap().to_string(), "1.2.3".to_string());
+ assert_eq!(parse("1.2.3-alpha1").unwrap().to_string(), "1.2.3-alpha1".to_string());
+ assert_eq!(parse("1.2.3+build.42").unwrap().to_string(), "1.2.3+build.42".to_string());
+ assert_eq!(parse("1.2.3-alpha1+42").unwrap().to_string(), "1.2.3-alpha1+42".to_string());
}
#[test]
// Serialize using `ToJson`
let test2 = TestStruct1 {data_int: 1, data_str:"toto".to_string(), data_vector:vec![2,3,4,5]};
let tjson: json::Json = test2.to_json();
- let json_str: String = tjson.to_str();
+ let json_str: String = tjson.to_string();
// Deserialize like before
let decoded: TestStruct1 = json::decode(json_str.as_slice()).unwrap();
pub type EncodeResult = io::IoResult<()>;
pub type DecodeResult<T> = Result<T, DecoderError>;
-fn escape_str(s: &str) -> String {
- let mut escaped = String::from_str("\"");
- for c in s.chars() {
- match c {
- '"' => escaped.push_str("\\\""),
- '\\' => escaped.push_str("\\\\"),
- '\x08' => escaped.push_str("\\b"),
- '\x0c' => escaped.push_str("\\f"),
- '\n' => escaped.push_str("\\n"),
- '\r' => escaped.push_str("\\r"),
- '\t' => escaped.push_str("\\t"),
- _ => escaped.push_char(c),
+pub fn escape_bytes(wr: &mut io::Writer, bytes: &[u8]) -> Result<(), io::IoError> {
+ try!(wr.write_str("\""));
+
+ let mut start = 0;
+
+ for (i, byte) in bytes.iter().enumerate() {
+ let escaped = match *byte {
+ b'"' => "\\\"",
+ b'\\' => "\\\\",
+ b'\x08' => "\\b",
+ b'\x0c' => "\\f",
+ b'\n' => "\\n",
+ b'\r' => "\\r",
+ b'\t' => "\\t",
+ _ => { continue; }
+ };
+
+ if start < i {
+ try!(wr.write(bytes.slice(start, i)));
}
- };
- escaped.push_char('"');
- escaped
+
+ try!(wr.write_str(escaped));
+
+ start = i + 1;
+ }
+
+ if start != bytes.len() {
+ try!(wr.write(bytes.slice_from(start)));
+ }
+
+ wr.write_str("\"")
+}
+
+fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> {
+ escape_bytes(writer, v.as_bytes())
+}
+
+fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> {
+ let mut buf = [0, .. 4];
+ v.encode_utf8(buf);
+ escape_bytes(writer, buf)
+}
+
+fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> {
+ static len: uint = 16;
+ static buf: [u8, ..len] = [b' ', ..len];
+
+ while n >= len {
+ try!(wr.write(buf));
+ n -= len;
+ }
+
+ if n > 0 {
+ wr.write(buf.slice_to(n))
+ } else {
+ Ok(())
+ }
}
fn fmt_number_or_null(v: f64) -> String {
}
}
-fn spaces(n: uint) -> String {
- String::from_char(n, ' ')
-}
-
/// A structure for implementing serialization to JSON.
pub struct Encoder<'a> {
writer: &'a mut io::Writer,
fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
fn emit_char(&mut self, v: char) -> EncodeResult {
- self.emit_str(str::from_char(v).as_slice())
+ escape_char(self.writer, v)
}
fn emit_str(&mut self, v: &str) -> EncodeResult {
- write!(self.writer, "{}", escape_str(v))
+ escape_str(self.writer, v)
}
fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
// Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
if cnt == 0 {
- write!(self.writer, "{}", escape_str(name))
+ escape_str(self.writer, name)
} else {
try!(write!(self.writer, "{{\"variant\":"));
- try!(write!(self.writer, "{}", escape_str(name)));
+ try!(escape_str(self.writer, name));
try!(write!(self.writer, ",\"fields\":["));
try!(f(self));
write!(self.writer, "]}}")
idx: uint,
f: |&mut Encoder<'a>| -> EncodeResult) -> EncodeResult {
if idx != 0 { try!(write!(self.writer, ",")); }
- try!(write!(self.writer, "{}:", escape_str(name)));
+ try!(escape_str(self.writer, name));
+ try!(write!(self.writer, ":"));
f(self)
}
}
fn emit_char(&mut self, v: char) -> EncodeResult {
- self.emit_str(str::from_char(v).as_slice())
+ escape_char(self.writer, v)
}
fn emit_str(&mut self, v: &str) -> EncodeResult {
- write!(self.writer, "{}", escape_str(v))
+ escape_str(self.writer, v)
}
fn emit_enum(&mut self,
cnt: uint,
f: |&mut PrettyEncoder<'a>| -> EncodeResult) -> EncodeResult {
if cnt == 0 {
- write!(self.writer, "{}", escape_str(name))
+ escape_str(self.writer, name)
} else {
self.indent += 2;
- try!(write!(self.writer, "[\n{}{},\n", spaces(self.indent),
- escape_str(name)));
+ try!(write!(self.writer, "[\n"));
+ try!(spaces(self.writer, self.indent));
+ try!(escape_str(self.writer, name));
+ try!(write!(self.writer, ",\n"));
try!(f(self));
self.indent -= 2;
- write!(self.writer, "\n{}]", spaces(self.indent))
+ try!(write!(self.writer, "\n"));
+ try!(spaces(self.writer, self.indent));
+ write!(self.writer, "]")
}
}
if idx != 0 {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}", spaces(self.indent)));
+ try!(spaces(self.writer, self.indent));
f(self)
}
self.indent += 2;
try!(f(self));
self.indent -= 2;
- write!(self.writer, "\n{}}}", spaces(self.indent))
+ try!(write!(self.writer, "\n"));
+ try!(spaces(self.writer, self.indent));
+ write!(self.writer, "}}")
}
}
} else {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}{}: ", spaces(self.indent), escape_str(name)));
+ try!(spaces(self.writer, self.indent));
+ try!(escape_str(self.writer, name));
+ try!(write!(self.writer, ": "));
f(self)
}
self.indent += 2;
try!(f(self));
self.indent -= 2;
- write!(self.writer, "\n{}]", spaces(self.indent))
+ try!(write!(self.writer, "\n"));
+ try!(spaces(self.writer, self.indent));
+ write!(self.writer, "]")
}
}
} else {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}", spaces(self.indent)));
+ try!(spaces(self.writer, self.indent));
f(self)
}
self.indent += 2;
try!(f(self));
self.indent -= 2;
- write!(self.writer, "\n{}}}", spaces(self.indent))
+ try!(write!(self.writer, "\n"));
+ try!(spaces(self.writer, self.indent));
+ write!(self.writer, "}}")
}
}
} else {
try!(write!(self.writer, ",\n"));
}
- try!(write!(self.writer, "{}", spaces(self.indent)));
+ try!(spaces(self.writer, self.indent));
// ref #12967, make sure to wrap a key in double quotes,
// in the event that its of a type that omits them (eg numbers)
let mut buf = MemWriter::new();
/// Provides access to the current position in the logical structure of the
/// JSON stream.
pub fn stack<'l>(&'l self) -> &'l Stack {
- return &'l self.stack;
+ return &self.stack;
}
fn eof(&self) -> bool { self.ch.is_none() }
#[test]
fn test_write_null() {
- assert_eq!(Null.to_str().into_string(), "null".to_string());
+ assert_eq!(Null.to_string().into_string(), "null".to_string());
assert_eq!(Null.to_pretty_str().into_string(), "null".to_string());
}
#[test]
fn test_write_number() {
- assert_eq!(Number(3.0).to_str().into_string(), "3".to_string());
+ assert_eq!(Number(3.0).to_string().into_string(), "3".to_string());
assert_eq!(Number(3.0).to_pretty_str().into_string(), "3".to_string());
- assert_eq!(Number(3.1).to_str().into_string(), "3.1".to_string());
+ assert_eq!(Number(3.1).to_string().into_string(), "3.1".to_string());
assert_eq!(Number(3.1).to_pretty_str().into_string(), "3.1".to_string());
- assert_eq!(Number(-1.5).to_str().into_string(), "-1.5".to_string());
+ assert_eq!(Number(-1.5).to_string().into_string(), "-1.5".to_string());
assert_eq!(Number(-1.5).to_pretty_str().into_string(), "-1.5".to_string());
- assert_eq!(Number(0.5).to_str().into_string(), "0.5".to_string());
+ assert_eq!(Number(0.5).to_string().into_string(), "0.5".to_string());
assert_eq!(Number(0.5).to_pretty_str().into_string(), "0.5".to_string());
- assert_eq!(Number(f64::NAN).to_str().into_string(), "null".to_string());
+ assert_eq!(Number(f64::NAN).to_string().into_string(), "null".to_string());
assert_eq!(Number(f64::NAN).to_pretty_str().into_string(), "null".to_string());
- assert_eq!(Number(f64::INFINITY).to_str().into_string(), "null".to_string());
+ assert_eq!(Number(f64::INFINITY).to_string().into_string(), "null".to_string());
assert_eq!(Number(f64::INFINITY).to_pretty_str().into_string(), "null".to_string());
- assert_eq!(Number(f64::NEG_INFINITY).to_str().into_string(), "null".to_string());
+ assert_eq!(Number(f64::NEG_INFINITY).to_string().into_string(), "null".to_string());
assert_eq!(Number(f64::NEG_INFINITY).to_pretty_str().into_string(), "null".to_string());
}
#[test]
fn test_write_str() {
- assert_eq!(String("".to_string()).to_str().into_string(), "\"\"".to_string());
+ assert_eq!(String("".to_string()).to_string().into_string(), "\"\"".to_string());
assert_eq!(String("".to_string()).to_pretty_str().into_string(), "\"\"".to_string());
- assert_eq!(String("foo".to_string()).to_str().into_string(), "\"foo\"".to_string());
+ assert_eq!(String("foo".to_string()).to_string().into_string(), "\"foo\"".to_string());
assert_eq!(String("foo".to_string()).to_pretty_str().into_string(), "\"foo\"".to_string());
}
#[test]
fn test_write_bool() {
- assert_eq!(Boolean(true).to_str().into_string(), "true".to_string());
+ assert_eq!(Boolean(true).to_string().into_string(), "true".to_string());
assert_eq!(Boolean(true).to_pretty_str().into_string(), "true".to_string());
- assert_eq!(Boolean(false).to_str().into_string(), "false".to_string());
+ assert_eq!(Boolean(false).to_string().into_string(), "false".to_string());
assert_eq!(Boolean(false).to_pretty_str().into_string(), "false".to_string());
}
#[test]
fn test_write_list() {
- assert_eq!(List(vec![]).to_str().into_string(), "[]".to_string());
+ assert_eq!(List(vec![]).to_string().into_string(), "[]".to_string());
assert_eq!(List(vec![]).to_pretty_str().into_string(), "[]".to_string());
- assert_eq!(List(vec![Boolean(true)]).to_str().into_string(), "[true]".to_string());
+ assert_eq!(List(vec![Boolean(true)]).to_string().into_string(), "[true]".to_string());
assert_eq!(
List(vec![Boolean(true)]).to_pretty_str().into_string(),
"\
Null,
List(vec![String("foo\nbar".to_string()), Number(3.5)])]);
- assert_eq!(long_test_list.to_str().into_string(),
+ assert_eq!(long_test_list.to_string().into_string(),
"[false,null,[\"foo\\nbar\",3.5]]".to_string());
assert_eq!(
long_test_list.to_pretty_str().into_string(),
#[test]
fn test_write_object() {
- assert_eq!(mk_object([]).to_str().into_string(), "{}".to_string());
+ assert_eq!(mk_object([]).to_string().into_string(), "{}".to_string());
assert_eq!(mk_object([]).to_pretty_str().into_string(), "{}".to_string());
assert_eq!(
mk_object([
("a".to_string(), Boolean(true))
- ]).to_str().into_string(),
+ ]).to_string().into_string(),
"{\"a\":true}".to_string()
);
assert_eq!(
]);
assert_eq!(
- complex_obj.to_str().into_string(),
+ complex_obj.to_string().into_string(),
"{\
\"b\":[\
{\"c\":\"\\f\\r\"},\
// We can't compare the strings directly because the object fields be
// printed in a different order.
- assert_eq!(a.clone(), from_str(a.to_str().as_slice()).unwrap());
+ assert_eq!(a.clone(), from_str(a.to_string().as_slice()).unwrap());
assert_eq!(a.clone(),
from_str(a.to_pretty_str().as_slice()).unwrap());
}
Core encoding and decoding interfaces.
*/
-#![crate_id = "serialize#0.11.0"]
+#![crate_id = "serialize#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "serialize"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, managed_boxes, default_type_params, phase)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
// test harness access
#[cfg(test)]
use std::path;
use std::rc::Rc;
use std::gc::{Gc, GC};
+use std::cell::{Cell, RefCell};
pub trait Encoder<E> {
// Primitive types:
}
}
+impl<E, S: Encoder<E>, T: Encodable<S, E> + Copy> Encodable<S, E> for Cell<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ self.get().encode(s)
+ }
+}
+
+impl<E, D: Decoder<E>, T: Decodable<D, E> + Copy> Decodable<D, E> for Cell<T> {
+ fn decode(d: &mut D) -> Result<Cell<T>, E> {
+ Ok(Cell::new(try!(Decodable::decode(d))))
+ }
+}
+
+// FIXME: #15036
+// Should use `try_borrow`, returning a
+// `encoder.error("attempting to Encode borrowed RefCell")`
+// from `encode` when `try_borrow` returns `None`.
+
+impl<E, S: Encoder<E>, T: Encodable<S, E>> Encodable<S, E> for RefCell<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ self.borrow().encode(s)
+ }
+}
+
+impl<E, D: Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for RefCell<T> {
+ fn decode(d: &mut D) -> Result<RefCell<T>, E> {
+ Ok(RefCell::new(try!(Decodable::decode(d))))
+ }
+}
+
// ___________________________________________________________________________
// Helper routines
//
impl IntoStr for Vec<Ascii> {
#[inline]
- fn into_str(self) -> String {
+ fn into_string(self) -> String {
unsafe {
let s: &str = mem::transmute(self.as_slice());
- s.to_string()
+ String::from_str(s)
}
}
}
*b = map[*b as uint];
}
- str::from_utf8(bytes.as_slice()).unwrap().to_string()
+ String::from_str(str::from_utf8(bytes.as_slice()).unwrap())
}
#[inline]
unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> String {
- let mut s = string.to_string();
+ let mut s = String::from_str(string);
for b in s.as_mut_bytes().mut_iter() {
*b = map[*b as uint];
}
assert_eq!(v.as_slice().to_ascii(), v2ascii!([40, 32, 59]));
assert_eq!("( ;".to_string().as_slice().to_ascii(), v2ascii!([40, 32, 59]));
- assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_string());
- assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_string());
+ assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
+ assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
- assert_eq!("".to_ascii().to_lower().into_str(), "".to_string());
- assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_string());
- assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_string());
+ assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
+ assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
+ assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
#[test]
fn test_ascii_vec_ng() {
- assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_string());
- assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_string());
- assert_eq!("".to_ascii().to_lower().into_str(), "".to_string());
- assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_string());
- assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_string());
+ assert_eq!("abCDef&?#".to_ascii().to_lower().into_string(), "abcdef&?#".to_string());
+ assert_eq!("abCDef&?#".to_ascii().to_upper().into_string(), "ABCDEF&?#".to_string());
+ assert_eq!("".to_ascii().to_lower().into_string(), "".to_string());
+ assert_eq!("YMCA".to_ascii().to_lower().into_string(), "ymca".to_string());
+ assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_string(), "ABCDEFXYZ:.;".to_string());
}
#[test]
}
#[test]
- fn test_ascii_into_str() {
- assert_eq!(vec2ascii![40, 32, 59].into_str(), "( ;".to_string());
- assert_eq!(vec2ascii!(40, 32, 59).into_str(), "( ;".to_string());
+ fn test_ascii_into_string() {
+ assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
+ assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
}
#[test]
}
#[test]
- fn test_to_str() {
- let s = Ascii{ chr: 't' as u8 }.to_str();
+ fn test_to_string() {
+ let s = Ascii{ chr: 't' as u8 }.to_string();
assert_eq!(s, "t".to_string());
}
unsafe {
debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
- (&'a *self.keys.offset(idx),
- &'a *self.vals.offset(idx))
+ (&*self.keys.offset(idx), &*self.vals.offset(idx))
}
}
unsafe {
debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
- (&'a *self.keys.offset(idx),
- &'a mut *self.vals.offset(idx))
+ (&*self.keys.offset(idx), &mut *self.vals.offset(idx))
}
}
unsafe {
debug_assert!(*self.hashes.offset(idx) != EMPTY_BUCKET);
(transmute(self.hashes.offset(idx)),
- &'a mut *self.keys.offset(idx),
- &'a mut *self.vals.offset(idx))
+ &mut *self.keys.offset(idx), &mut *self.vals.offset(idx))
}
}
}
#[test]
- fn test_to_str() {
+ fn test_to_string() {
let mut cache: LruCache<int, int> = LruCache::new(3);
cache.put(1, 10);
cache.put(2, 20);
cache.put(3, 30);
- assert_eq!(cache.to_str(), "{3: 30, 2: 20, 1: 10}".to_string());
+ assert_eq!(cache.to_string(), "{3: 30, 2: 20, 1: 10}".to_string());
cache.put(2, 22);
- assert_eq!(cache.to_str(), "{2: 22, 3: 30, 1: 10}".to_string());
+ assert_eq!(cache.to_string(), "{2: 22, 3: 30, 1: 10}".to_string());
cache.put(6, 60);
- assert_eq!(cache.to_str(), "{6: 60, 2: 22, 3: 30}".to_string());
+ assert_eq!(cache.to_string(), "{6: 60, 2: 22, 3: 30}".to_string());
cache.get(&3);
- assert_eq!(cache.to_str(), "{3: 30, 6: 60, 2: 22}".to_string());
+ assert_eq!(cache.to_string(), "{3: 30, 6: 60, 2: 22}".to_string());
cache.change_capacity(2);
- assert_eq!(cache.to_str(), "{3: 30, 6: 60}".to_string());
+ assert_eq!(cache.to_string(), "{3: 30, 6: 60}".to_string());
}
#[test]
cache.clear();
assert!(cache.get(&1).is_none());
assert!(cache.get(&2).is_none());
- assert_eq!(cache.to_str(), "{}".to_string());
+ assert_eq!(cache.to_string(), "{}".to_string());
}
}
#[cfg(target_os = "ios")]
#[cfg(target_os = "freebsd")]
pub mod dl {
- use prelude::*;
use c_str::{CString, ToCStr};
use libc;
use ptr;
use result::*;
- use str::StrAllocating;
use string::String;
pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
let ret = if ptr::null() == last_error {
Ok(result)
} else {
- Err(CString::new(last_error, false).as_str()
- .unwrap()
- .to_string())
+ Err(String::from_str(CString::new(last_error, false).as_str()
+ .unwrap()))
};
ret
use option::{Option, Some, None};
use string::String;
-use str::StrAllocating;
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
impl FromStr for String {
#[inline]
fn from_str(s: &str) -> Option<String> {
- Some(s.to_string())
+ Some(String::from_str(s))
}
}
use prelude::*;
use self::test::Bencher;
+ // why is this a macro? wouldn't an inlined function work just as well?
macro_rules! u64_from_be_bytes_bench_impl(
- ($size:expr, $stride:expr, $start_index:expr) =>
+ ($b:expr, $size:expr, $stride:expr, $start_index:expr) =>
({
use super::u64_from_be_bytes;
let data = Vec::from_fn($stride*100+$start_index, |i| i as u8);
let mut sum = 0u64;
- b.iter(|| {
+ $b.iter(|| {
let mut i = $start_index;
while i < data.len() {
sum += u64_from_be_bytes(data.as_slice(), i, $size);
#[bench]
fn u64_from_be_bytes_4_aligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(4, 4, 0);
+ u64_from_be_bytes_bench_impl!(b, 4, 4, 0);
}
#[bench]
fn u64_from_be_bytes_4_unaligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(4, 4, 1);
+ u64_from_be_bytes_bench_impl!(b, 4, 4, 1);
}
#[bench]
fn u64_from_be_bytes_7_aligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(7, 8, 0);
+ u64_from_be_bytes_bench_impl!(b, 7, 8, 0);
}
#[bench]
fn u64_from_be_bytes_7_unaligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(7, 8, 1);
+ u64_from_be_bytes_bench_impl!(b, 7, 8, 1);
}
#[bench]
fn u64_from_be_bytes_8_aligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(8, 8, 0);
+ u64_from_be_bytes_bench_impl!(b, 8, 8, 0);
}
#[bench]
fn u64_from_be_bytes_8_unaligned(b: &mut Bencher) {
- u64_from_be_bytes_bench_impl!(8, 8, 1);
+ u64_from_be_bytes_bench_impl!(b, 8, 8, 1);
}
}
macro_rules! error( ($e:expr, $s:expr) => (
match $e {
Ok(val) => fail!("Should have been an error, was {:?}", val),
- Err(ref err) => assert!(err.to_str().as_slice().contains($s.as_slice()),
+ Err(ref err) => assert!(err.to_string().as_slice().contains($s.as_slice()),
format!("`{}` did not contain `{}`", err, $s))
}
) )
for n in range(0i,3) {
let f = dir.join(format!("{}.txt", n));
let mut w = check!(File::create(&f));
- let msg_str = format!("{}{}", prefix, n.to_str());
+ let msg_str = format!("{}{}", prefix, n.to_string());
let msg = msg_str.as_slice().as_bytes();
check!(w.write(msg));
}
writer.write_line("testing").unwrap();
writer.write_str("testing").unwrap();
let mut r = BufReader::new(writer.get_ref());
- assert_eq!(r.read_to_str().unwrap(), "testingtesting\ntesting".to_string());
+ assert_eq!(r.read_to_string().unwrap(), "testingtesting\ntesting".to_string());
}
#[test]
writer.write_char('\n').unwrap();
writer.write_char('ệ').unwrap();
let mut r = BufReader::new(writer.get_ref());
- assert_eq!(r.read_to_str().unwrap(), "a\nệ".to_string());
+ assert_eq!(r.read_to_string().unwrap(), "a\nệ".to_string());
}
#[test]
fn test_read_whole_string_bad() {
let buf = [0xff];
let mut r = BufReader::new(buf);
- match r.read_to_str() {
+ match r.read_to_string() {
Ok(..) => fail!(),
Err(..) => {}
}
use result::{Ok, Err, Result};
use rt::rtio;
use slice::{Vector, MutableVector, ImmutableVector};
-use str::{Str, StrSlice, StrAllocating};
+use str::{Str, StrSlice};
use str;
use string::String;
use uint;
fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
if min > buf.len() {
return Err(IoError {
- detail: Some("the buffer is too short".to_string()),
+ detail: Some(String::from_str("the buffer is too short")),
..standard_error(InvalidInput)
});
}
fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
if min > len {
return Err(IoError {
- detail: Some("the buffer is too short".to_string()),
+ detail: Some(String::from_str("the buffer is too short")),
..standard_error(InvalidInput)
});
}
/// This function returns all of the same errors as `read_to_end` with an
/// additional error if the reader's contents are not a valid sequence of
/// UTF-8 bytes.
- fn read_to_str(&mut self) -> IoResult<String> {
+ fn read_to_string(&mut self) -> IoResult<String> {
self.read_to_end().and_then(|s| {
match str::from_utf8(s.as_slice()) {
- Some(s) => Ok(s.to_string()),
+ Some(s) => Ok(String::from_str(s)),
None => Err(standard_error(InvalidInput)),
}
})
fn read_line(&mut self) -> IoResult<String> {
self.read_until('\n' as u8).and_then(|line|
match str::from_utf8(line.as_slice()) {
- Some(s) => Ok(s.to_string()),
+ Some(s) => Ok(String::from_str(s)),
None => Err(standard_error(InvalidInput)),
}
)
}
#[test]
- fn ipv6_addr_to_str() {
+ fn ipv6_addr_to_string() {
let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
- assert!(a1.to_str() == "::ffff:192.0.2.128".to_string() ||
- a1.to_str() == "::FFFF:192.0.2.128".to_string());
- assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_str(), "8:9:a:b:c:d:e:f".to_string());
+ assert!(a1.to_string() == "::ffff:192.0.2.128".to_string() ||
+ a1.to_string() == "::FFFF:192.0.2.128".to_string());
+ assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
+ "8:9:a:b:c:d:e:f".to_string());
}
}
iotest!(fn listen_ip4_localhost() {
let socket_addr = next_test_ip4();
- let ip_str = socket_addr.ip.to_str();
+ let ip_str = socket_addr.ip.to_string();
let port = socket_addr.port;
let listener = TcpListener::bind(ip_str.as_slice(), port);
let mut acceptor = listener.listen();
iotest!(fn connect_localhost() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn connect_ip4_loopback() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn connect_ip6_loopback() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn smoke_test_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn smoke_test_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn read_eof_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn read_eof_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn read_eof_twice_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn read_eof_twice_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn write_close_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn write_close_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn multiple_connect_serial_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let max = 10u;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn multiple_connect_serial_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let max = 10u;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn multiple_connect_interleaved_greedy_schedule_ip4() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
static MAX: int = 10;
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
connect(0, addr);
fn connect(i: int, addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
if i == MAX { return }
iotest!(fn multiple_connect_interleaved_greedy_schedule_ip6() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
static MAX: int = 10;
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
connect(0, addr);
fn connect(i: int, addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
if i == MAX { return }
iotest!(fn multiple_connect_interleaved_lazy_schedule_ip4() {
static MAX: int = 10;
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
connect(0, addr);
fn connect(i: int, addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
if i == MAX { return }
iotest!(fn multiple_connect_interleaved_lazy_schedule_ip6() {
static MAX: int = 10;
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
connect(0, addr);
fn connect(i: int, addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
if i == MAX { return }
})
pub fn socket_name(addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut listener = TcpListener::bind(ip_str.as_slice(), port).unwrap();
}
pub fn peer_name(addr: SocketAddr) {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
spawn(proc() {
let port = addr.port;
let (tx, rx) = channel();
spawn(proc() {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let mut srv = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
tx.send(());
let mut cl = srv.accept().unwrap();
});
rx.recv();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let mut c = TcpStream::connect(ip_str.as_slice(), port).unwrap();
let mut b = [0, ..10];
assert_eq!(c.read(b), Ok(1));
iotest!(fn double_bind() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let listener = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen();
assert!(listener.is_ok());
let (tx, rx) = channel();
spawn(proc() {
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
rx.recv();
let _stream = TcpStream::connect(ip_str.as_slice(), port).unwrap();
// Close
});
{
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
tx.send(());
{
}
// Close listener
}
- let _listener = TcpListener::bind(addr.ip.to_str().as_slice(), port);
+ let _listener = TcpListener::bind(addr.ip.to_string().as_slice(), port);
})
iotest!(fn tcp_clone_smoke() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
iotest!(fn tcp_clone_two_read() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
let (tx1, rx) = channel();
iotest!(fn tcp_clone_two_write() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
use rt::rtio::RtioTcpStream;
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let a = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen();
spawn(proc() {
iotest!(fn accept_timeout() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut a = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen().unwrap();
if !cfg!(target_os = "freebsd") {
let (tx, rx) = channel();
spawn(proc() {
- tx.send(TcpStream::connect(addr.ip.to_str().as_slice(),
+ tx.send(TcpStream::connect(addr.ip.to_string().as_slice(),
port).unwrap());
});
let _l = rx.recv();
// Unset the timeout and make sure that this always blocks.
a.set_timeout(None);
spawn(proc() {
- drop(TcpStream::connect(addr.ip.to_str().as_slice(),
+ drop(TcpStream::connect(addr.ip.to_string().as_slice(),
port).unwrap());
});
a.accept().unwrap();
iotest!(fn close_readwrite_smoke() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (_tx, rx) = channel::<()>();
iotest!(fn close_read_wakes_up() {
let addr = next_test_ip4();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (_tx, rx) = channel::<()>();
iotest!(fn readwrite_timeouts() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (tx, rx) = channel::<()>();
iotest!(fn read_timeouts() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (tx, rx) = channel::<()>();
iotest!(fn write_timeouts() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (tx, rx) = channel::<()>();
iotest!(fn timeout_concurrent_read() {
let addr = next_test_ip6();
- let ip_str = addr.ip.to_str();
+ let ip_str = addr.ip.to_string();
let port = addr.port;
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
let (tx, rx) = channel::<()>();
iotest!(fn clone_while_reading() {
let addr = next_test_ip6();
- let listen = TcpListener::bind(addr.ip.to_str().as_slice(), addr.port);
+ let listen = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
let mut accept = listen.listen().unwrap();
// Enqueue a task to write to a socket
let (txdone, rxdone) = channel();
let txdone2 = txdone.clone();
spawn(proc() {
- let mut tcp = TcpStream::connect(addr.ip.to_str().as_slice(),
+ let mut tcp = TcpStream::connect(addr.ip.to_string().as_slice(),
addr.port).unwrap();
rx.recv();
tcp.write_u8(0).unwrap();
})
pub fn read_all(input: &mut Reader) -> String {
- input.read_to_str().unwrap()
+ input.read_to_string().unwrap()
}
pub fn run_output(cmd: Command) -> String {
set_stdout(box w);
println!("hello!");
});
- assert_eq!(r.read_to_str().unwrap(), "hello!\n".to_string());
+ assert_eq!(r.read_to_string().unwrap(), "hello!\n".to_string());
})
iotest!(fn capture_stderr() {
::realstd::io::stdio::set_stderr(box w);
fail!("my special message");
});
- let s = r.read_to_str().unwrap();
+ let s = r.read_to_string().unwrap();
assert!(s.as_slice().contains("my special message"));
})
}
let mut r = BufReader::new(data.as_bytes());
{
let mut r = LimitReader::new(r.by_ref(), 3);
- assert_eq!(r.read_line(), Ok("012".to_str()));
+ assert_eq!(r.read_line(), Ok("012".to_string()));
assert_eq!(r.limit(), 0);
assert_eq!(r.read_line().err().unwrap().kind, io::EndOfFile);
}
{
let mut r = LimitReader::new(r.by_ref(), 9);
- assert_eq!(r.read_line(), Ok("3456789\n".to_str()));
+ assert_eq!(r.read_line(), Ok("3456789\n".to_string()));
assert_eq!(r.limit(), 1);
- assert_eq!(r.read_line(), Ok("0".to_str()));
+ assert_eq!(r.read_line(), Ok("0".to_string()));
}
{
let mut r = LimitReader::new(r.by_ref(), 100);
assert_eq!(r.read_char(), Ok('1'));
assert_eq!(r.limit(), 99);
- assert_eq!(r.read_line(), Ok("23456789\n".to_str()));
+ assert_eq!(r.read_line(), Ok("23456789\n".to_string()));
}
}
//! all the standard macros, such as `assert!`, `fail!`, `println!`,
//! and `format!`, also available to all Rust code.
-#![crate_id = "std#0.11.0"]
+#![crate_id = "std#0.11.0"] // NOTE: remove after stage0 snap
+#![crate_name = "std"]
#![unstable]
#![comment = "The Rust standard library"]
#![license = "MIT/ASL2"]
#![feature(macro_rules, globs, managed_boxes, linkage)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
// Don't link to std. We are std.
#![no_std]
///
/// * num - The float value
#[inline]
-pub fn to_str(num: f32) -> String {
+pub fn to_string(num: f32) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
r
///
/// * num - The float value
#[inline]
-pub fn to_str(num: f64) -> String {
+pub fn to_string(num: f64) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
r
/// Convert to a string as a byte slice in a given base.
///
-/// Use in place of x.to_str() when you do not need to store the string permanently
+/// Use in place of x.to_string() when you do not need to store the string permanently
///
/// # Examples
///
}
#[test]
- fn test_to_str() {
+ fn test_to_string() {
assert_eq!((0 as $T).to_str_radix(10u), "0".to_string());
assert_eq!((1 as $T).to_str_radix(10u), "1".to_string());
assert_eq!((-1 as $T).to_str_radix(10u), "-1".to_string());
#[test]
fn test_int_to_str_overflow() {
let mut i8_val: i8 = 127_i8;
- assert_eq!(i8_val.to_str(), "127".to_string());
+ assert_eq!(i8_val.to_string(), "127".to_string());
i8_val += 1 as i8;
- assert_eq!(i8_val.to_str(), "-128".to_string());
+ assert_eq!(i8_val.to_string(), "-128".to_string());
let mut i16_val: i16 = 32_767_i16;
- assert_eq!(i16_val.to_str(), "32767".to_string());
+ assert_eq!(i16_val.to_string(), "32767".to_string());
i16_val += 1 as i16;
- assert_eq!(i16_val.to_str(), "-32768".to_string());
+ assert_eq!(i16_val.to_string(), "-32768".to_string());
let mut i32_val: i32 = 2_147_483_647_i32;
- assert_eq!(i32_val.to_str(), "2147483647".to_string());
+ assert_eq!(i32_val.to_string(), "2147483647".to_string());
i32_val += 1 as i32;
- assert_eq!(i32_val.to_str(), "-2147483648".to_string());
+ assert_eq!(i32_val.to_string(), "-2147483648".to_string());
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
- assert_eq!(i64_val.to_str(), "9223372036854775807".to_string());
+ assert_eq!(i64_val.to_string(), "9223372036854775807".to_string());
i64_val += 1 as i64;
- assert_eq!(i64_val.to_str(), "-9223372036854775808".to_string());
+ assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string());
}
#[test]
/**
* Converts an integral number to its string representation as a byte vector.
* This is meant to be a common base implementation for all integral string
- * conversion functions like `to_str()` or `to_str_radix()`.
+ * conversion functions like `to_string()` or `to_str_radix()`.
*
* # Arguments
* - `num` - The number to convert. Accepts any number that
/**
* Converts a number to its string representation as a byte vector.
* This is meant to be a common base implementation for all numeric string
- * conversion functions like `to_str()` or `to_str_radix()`.
+ * conversion functions like `to_string()` or `to_str_radix()`.
*
* # Arguments
* - `num` - The number to convert. Accepts any number that
use f64;
#[bench]
- fn float_to_str(b: &mut Bencher) {
+ fn float_to_string(b: &mut Bencher) {
let mut rng = weak_rng();
- b.iter(|| { f64::to_str(rng.gen()); })
+ b.iter(|| { f64::to_string(rng.gen()); })
}
}
}
/// Convert to a string as a byte slice in a given base.
///
-/// Use in place of x.to_str() when you do not need to store the string permanently
+/// Use in place of x.to_string() when you do not need to store the string permanently
///
/// # Examples
///
use u16;
#[test]
- pub fn test_to_str() {
+ pub fn test_to_string() {
assert_eq!((0 as $T).to_str_radix(10u), "0".to_string());
assert_eq!((1 as $T).to_str_radix(10u), "1".to_string());
assert_eq!((2 as $T).to_str_radix(10u), "2".to_string());
#[test]
fn test_uint_to_str_overflow() {
let mut u8_val: u8 = 255_u8;
- assert_eq!(u8_val.to_str(), "255".to_string());
+ assert_eq!(u8_val.to_string(), "255".to_string());
u8_val += 1 as u8;
- assert_eq!(u8_val.to_str(), "0".to_string());
+ assert_eq!(u8_val.to_string(), "0".to_string());
let mut u16_val: u16 = 65_535_u16;
- assert_eq!(u16_val.to_str(), "65535".to_string());
+ assert_eq!(u16_val.to_string(), "65535".to_string());
u16_val += 1 as u16;
- assert_eq!(u16_val.to_str(), "0".to_string());
+ assert_eq!(u16_val.to_string(), "0".to_string());
let mut u32_val: u32 = 4_294_967_295_u32;
- assert_eq!(u32_val.to_str(), "4294967295".to_string());
+ assert_eq!(u32_val.to_string(), "4294967295".to_string());
u32_val += 1 as u32;
- assert_eq!(u32_val.to_str(), "0".to_string());
+ assert_eq!(u32_val.to_string(), "0".to_string());
let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
- assert_eq!(u64_val.to_str(), "18446744073709551615".to_string());
+ assert_eq!(u64_val.to_string(), "18446744073709551615".to_string());
u64_val += 1 as u64;
- assert_eq!(u64_val.to_str(), "0".to_string());
+ assert_eq!(u64_val.to_string(), "0".to_string());
}
#[test]
/// ```
pub fn env() -> Vec<(String,String)> {
env_as_bytes().move_iter().map(|(k,v)| {
- let k = str::from_utf8_lossy(k.as_slice()).to_string();
- let v = str::from_utf8_lossy(v.as_slice()).to_string();
+ let k = String::from_str(str::from_utf8_lossy(k.as_slice()).as_slice());
+ let v = String::from_str(str::from_utf8_lossy(v.as_slice()).as_slice());
(k,v)
}).collect()
}
/// }
/// ```
pub fn getenv(n: &str) -> Option<String> {
- getenv_as_bytes(n).map(|v| str::from_utf8_lossy(v.as_slice()).to_string())
+ getenv_as_bytes(n).map(|v| String::from_str(str::from_utf8_lossy(v.as_slice()).as_slice()))
}
#[cfg(unix)]
($path:expr, $disp:ident, $exp:expr) => (
{
let path = Path::new($path);
- assert!(path.$disp().to_str().as_slice() == $exp);
+ assert!(path.$disp().to_string().as_slice() == $exp);
}
)
)
#[test]
fn test_display_str() {
let path = Path::new("foo");
- assert_eq!(path.display().to_str(), "foo".to_string());
+ assert_eq!(path.display().to_string(), "foo".to_string());
let path = Path::new(b"\\");
- assert_eq!(path.filename_display().to_str(), "".to_string());
+ assert_eq!(path.filename_display().to_string(), "".to_string());
let path = Path::new("foo");
let mo = path.display().as_maybe_owned();
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
-#[doc(no_inline)] pub use ops::{Shl, Shr, Index};
+#[doc(no_inline)] pub use ops::{Shl, Shr};
+#[doc(no_inline)] #[cfg(not(stage0))] pub use ops::{Index, IndexMut};
#[doc(no_inline)] pub use option::{Option, Some, None};
#[doc(no_inline)] pub use result::{Result, Ok, Err};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice, OwnedStr};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating};
-#[doc(no_inline)] pub use to_str::{ToStr, IntoStr};
+#[doc(no_inline)] pub use to_str::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
use slice::{MutableVector};
extern {
- fn backtrace(buf: *mut *const libc::c_void,
+ fn backtrace(buf: *mut *mut libc::c_void,
sz: libc::c_int) -> libc::c_int;
}
try!(writeln!(w, "stack backtrace:"));
// 100 lines should be enough
static SIZE: libc::c_int = 100;
- let mut buf: [*const libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
+ let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE) as uint};
// skipping the first one as it is write itself
});
assert!(r.is_ok());
- let output = reader.read_to_str().unwrap();
+ let output = reader.read_to_string().unwrap();
assert_eq!(output, "Hello, world!".to_string());
}
/*!
-The `ToStr` trait for converting to strings
+The `ToString` trait for converting to strings
*/
use string::String;
/// A generic trait for converting a value to a string
-pub trait ToStr {
+pub trait ToString {
/// Converts the value of `self` to an owned string
- fn to_str(&self) -> String;
+ fn to_string(&self) -> String;
}
/// Trait for converting a type to a string, consuming it in the process.
pub trait IntoStr {
/// Consume and convert to a string.
- fn into_str(self) -> String;
+ fn into_string(self) -> String;
}
-impl<T: fmt::Show> ToStr for T {
- fn to_str(&self) -> String {
+impl<T: fmt::Show> ToString for T {
+ fn to_string(&self) -> String {
format!("{}", *self)
}
}
#[test]
fn test_simple_types() {
- assert_eq!(1i.to_str(), "1".to_string());
- assert_eq!((-1i).to_str(), "-1".to_string());
- assert_eq!(200u.to_str(), "200".to_string());
- assert_eq!(2u8.to_str(), "2".to_string());
- assert_eq!(true.to_str(), "true".to_string());
- assert_eq!(false.to_str(), "false".to_string());
- assert_eq!(().to_str(), "()".to_string());
- assert_eq!(("hi".to_string()).to_str(), "hi".to_string());
+ assert_eq!(1i.to_string(), "1".to_string());
+ assert_eq!((-1i).to_string(), "-1".to_string());
+ assert_eq!(200u.to_string(), "200".to_string());
+ assert_eq!(2u8.to_string(), "2".to_string());
+ assert_eq!(true.to_string(), "true".to_string());
+ assert_eq!(false.to_string(), "false".to_string());
+ assert_eq!(().to_string(), "()".to_string());
+ assert_eq!(("hi".to_string()).to_string(), "hi".to_string());
}
#[test]
fn test_vectors() {
let x: Vec<int> = vec![];
- assert_eq!(x.to_str(), "[]".to_string());
- assert_eq!((vec![1i]).to_str(), "[1]".to_string());
- assert_eq!((vec![1i, 2, 3]).to_str(), "[1, 2, 3]".to_string());
- assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_str() ==
+ assert_eq!(x.to_string(), "[]".to_string());
+ assert_eq!((vec![1i]).to_string(), "[1]".to_string());
+ assert_eq!((vec![1i, 2, 3]).to_string(), "[1, 2, 3]".to_string());
+ assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_string() ==
"[[], [1], [1, 1]]".to_string());
}
}
//! use this crate specifically. Instead, its functionality is reexported
//! through `std::sync`.
-#![crate_id = "sync#0.11.0"]
+#![crate_id = "sync#0.11.0"] // NOTE: remove after stage0 snap
+#![crate_name = "sync"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(phase, globs, macro_rules, unsafe_destructor)]
#![deny(missing_doc)]
#![no_std]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;
pub struct TyParam {
pub ident: Ident,
pub id: NodeId,
- pub sized: Sized,
pub bounds: OwnedSlice<TyParamBound>,
+ pub unbound: Option<TyParamBound>,
pub default: Option<P<Ty>>,
pub span: Span
}
+/// Represents lifetimes and type parameters attached to a declaration
+/// of a function, enum, trait, etc.
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,
PatWild,
PatWildMulti,
// A PatIdent may either be a new bound variable,
- // or a nullary enum (in which case the second field
+ // or a nullary enum (in which case the third field
// is None).
// In the nullary enum case, the parser can't determine
// which it is. The resolver determines this, and
ExprCast(Gc<Expr>, P<Ty>),
ExprIf(Gc<Expr>, P<Block>, Option<Gc<Expr>>),
ExprWhile(Gc<Expr>, P<Block>),
- // FIXME #6993: change to Option<Name>
+ // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprForLoop(Gc<Pat>, Gc<Expr>, P<Block>, Option<Ident>),
// Conditionless loop (can be exited with break, cont, or ret)
- // FIXME #6993: change to Option<Name>
+ // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>),
ExprMatch(Gc<Expr>, Vec<Arm>),
ExprFnBlock(P<FnDecl>, P<Block>),
ExprField(Gc<Expr>, SpannedIdent, Vec<P<Ty>>),
ExprIndex(Gc<Expr>, Gc<Expr>),
- /// Expression that looks like a "name". For example,
- /// `std::slice::from_elem::<uint>` is an ExprPath that's the "name" part
- /// of a function call.
+ /// Variable reference, possibly containing `::` and/or
+ /// type parameters, e.g. foo::bar::<baz>
ExprPath(Path),
ExprAddrOf(Mutability, Gc<Expr>),
pub span: Span,
}
+/// Represents a required method in a trait declaration,
+/// one without a default implementation
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct TypeMethod {
pub ident: Ident,
pub vis: Visibility,
}
+/// Represents a method declaration in a trait declaration, possibly
+/// including a default implementation
// A trait method is either required (meaning it doesn't have an
// implementation, just a signature) or provided (meaning it has a default
// implementation).
impl fmt::Show for IntTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", ast_util::int_ty_to_str(*self, None))
+ write!(f, "{}", ast_util::int_ty_to_string(*self, None))
}
}
impl fmt::Show for UintTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", ast_util::uint_ty_to_str(*self, None))
+ write!(f, "{}", ast_util::uint_ty_to_string(*self, None))
}
}
impl fmt::Show for FloatTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", ast_util::float_ty_to_str(*self))
+ write!(f, "{}", ast_util::float_ty_to_string(*self))
}
}
}
}
+/// Represents the type of a closure
#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct ClosureTy {
pub lifetimes: Vec<Lifetime>,
pub dialect: AsmDialect
}
+/// represents an argument in a function header
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct Arg {
pub ty: P<Ty>,
}
}
-// represents the header (not the body) of a function declaration
+/// represents the header (not the body) of a function declaration
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct FnDecl {
pub inputs: Vec<Arg>,
}
}
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
-pub enum Sized {
- DynSize,
- StaticSize,
-}
-
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub struct StructField_ {
pub kind: StructFieldKind,
ItemTy(P<Ty>, Generics),
ItemEnum(EnumDef, Generics),
ItemStruct(Gc<StructDef>, Generics),
- ItemTrait(Generics, Sized, Vec<TraitRef> , Vec<TraitMethod> ),
+ /// Represents a Trait Declaration
+ ItemTrait(Generics,
+ Option<TyParamBound>, // (optional) default bound not required for Self.
+ // Currently, only Sized makes sense here.
+ Vec<TraitRef> ,
+ Vec<TraitMethod>),
ItemImpl(Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
/// The type of the iterator used by with_path.
pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
-pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> String {
+pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String {
let itr = token::get_ident_interner();
path.fold(String::new(), |mut s, e| {
match abi {
Some(abi) => abi,
None => fail!("expected foreign mod or inlined parent, found {}",
- self.node_to_str(parent))
+ self.node_to_string(parent))
}
}
pub fn expect_item(&self, id: NodeId) -> Gc<Item> {
match self.find(id) {
Some(NodeItem(item)) => item,
- _ => fail!("expected item, found {}", self.node_to_str(id))
+ _ => fail!("expected item, found {}", self.node_to_string(id))
}
}
_ => fail!("struct ID bound to enum variant that isn't struct-like"),
}
}
- _ => fail!(format!("expected struct, found {}", self.node_to_str(id))),
+ _ => fail!(format!("expected struct, found {}", self.node_to_string(id))),
}
}
pub fn expect_variant(&self, id: NodeId) -> P<Variant> {
match self.find(id) {
Some(NodeVariant(variant)) => variant,
- _ => fail!(format!("expected variant, found {}", self.node_to_str(id))),
+ _ => fail!(format!("expected variant, found {}", self.node_to_string(id))),
}
}
pub fn expect_foreign_item(&self, id: NodeId) -> Gc<ForeignItem> {
match self.find(id) {
Some(NodeForeignItem(item)) => item,
- _ => fail!("expected foreign item, found {}", self.node_to_str(id))
+ _ => fail!("expected foreign item, found {}", self.node_to_string(id))
}
}
self.with_path_next(id, None, f)
}
- pub fn path_to_str(&self, id: NodeId) -> String {
- self.with_path(id, |path| path_to_str(path))
+ pub fn path_to_string(&self, id: NodeId) -> String {
+ self.with_path(id, |path| path_to_string(path))
}
fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String {
self.with_path(id, |path| {
- path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
+ path_to_string(path.chain(Some(PathName(i.name)).move_iter()))
})
}
.unwrap_or_else(|| fail!("AstMap.span: could not find span for id {}", id))
}
- pub fn node_to_str(&self, id: NodeId) -> String {
- node_id_to_str(self, id)
+ pub fn node_to_string(&self, id: NodeId) -> String {
+ node_id_to_string(self, id)
}
}
ii
}
-fn node_id_to_str(map: &Map, id: NodeId) -> String {
+fn node_id_to_string(map: &Map, id: NodeId) -> String {
match map.find(id) {
Some(NodeItem(item)) => {
let path_str = map.path_to_str_with_ident(id, item.ident);
Some(NodeMethod(m)) => {
format!("method {} in {} (id={})",
token::get_ident(m.ident),
- map.path_to_str(id), id)
+ map.path_to_string(id), id)
}
Some(NodeTraitMethod(ref tm)) => {
let m = ast_util::trait_method_to_ty_method(&**tm);
format!("method {} in {} (id={})",
token::get_ident(m.ident),
- map.path_to_str(id), id)
+ map.path_to_string(id), id)
}
Some(NodeVariant(ref variant)) => {
format!("variant {} in {} (id={})",
token::get_ident(variant.node.name),
- map.path_to_str(id), id)
+ map.path_to_string(id), id)
}
Some(NodeExpr(ref expr)) => {
- format!("expr {} (id={})", pprust::expr_to_str(&**expr), id)
+ format!("expr {} (id={})", pprust::expr_to_string(&**expr), id)
}
Some(NodeStmt(ref stmt)) => {
- format!("stmt {} (id={})", pprust::stmt_to_str(&**stmt), id)
+ format!("stmt {} (id={})", pprust::stmt_to_string(&**stmt), id)
}
Some(NodeArg(ref pat)) => {
- format!("arg {} (id={})", pprust::pat_to_str(&**pat), id)
+ format!("arg {} (id={})", pprust::pat_to_string(&**pat), id)
}
Some(NodeLocal(ref pat)) => {
- format!("local {} (id={})", pprust::pat_to_str(&**pat), id)
+ format!("local {} (id={})", pprust::pat_to_string(&**pat), id)
}
Some(NodePat(ref pat)) => {
- format!("pat {} (id={})", pprust::pat_to_str(&**pat), id)
+ format!("pat {} (id={})", pprust::pat_to_string(&**pat), id)
}
Some(NodeBlock(ref block)) => {
- format!("block {} (id={})", pprust::block_to_str(&**block), id)
+ format!("block {} (id={})", pprust::block_to_string(&**block), id)
}
Some(NodeStructCtor(_)) => {
- format!("struct_ctor {} (id={})", map.path_to_str(id), id)
+ format!("struct_ctor {} (id={})", map.path_to_string(id), id)
}
Some(NodeLifetime(ref l)) => {
format!("lifetime {} (id={})",
- pprust::lifetime_to_str(&**l), id)
+ pprust::lifetime_to_string(&**l), id)
}
None => {
format!("unknown node (id={})", id)
}
}
-pub fn binop_to_str(op: BinOp) -> &'static str {
+pub fn binop_to_string(op: BinOp) -> &'static str {
match op {
BiAdd => "+",
BiSub => "-",
}
}
-pub fn unop_to_str(op: UnOp) -> &'static str {
+pub fn unop_to_string(op: UnOp) -> &'static str {
match op {
UnBox => "box(GC) ",
UnUniq => "box() ",
// Get a string representation of a signed int type, with its value.
// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
-pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> String {
+pub fn int_ty_to_string(t: IntTy, val: Option<i64>) -> String {
let s = match t {
TyI if val.is_some() => "i",
TyI => "int",
// Get a string representation of an unsigned int type, with its value.
// We want to avoid "42uint" in favor of "42u"
-pub fn uint_ty_to_str(t: UintTy, val: Option<u64>) -> String {
+pub fn uint_ty_to_string(t: UintTy, val: Option<u64>) -> String {
let s = match t {
TyU if val.is_some() => "u",
TyU => "uint",
}
}
-pub fn float_ty_to_str(t: FloatTy) -> String {
+pub fn float_ty_to_string(t: FloatTy) -> String {
match t {
TyF32 => "f32".to_string(),
TyF64 => "f64".to_string(),
/// listed as `__extensions__::method_name::hash`, with no indication
/// of the type).
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
- let mut pretty = pprust::ty_to_str(ty);
+ let mut pretty = pprust::ty_to_string(ty);
match *trait_ref {
Some(ref trait_ref) => {
pretty.push_char('.');
- pretty.push_str(pprust::path_to_str(&trait_ref.path).as_slice());
+ pretty.push_str(pprust::path_to_string(&trait_ref.path).as_slice());
}
None => {}
}
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use parse::token::InternedString;
use parse::token;
-use crateid::CrateId;
use std::collections::HashSet;
use std::collections::BitvSet;
}).collect()
}
-pub fn find_crateid(attrs: &[Attribute]) -> Option<CrateId> {
- match first_attr_value_str_by_name(attrs, "crate_id") {
- None => None,
- Some(id) => from_str::<CrateId>(id.get()),
- }
+pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
+ first_attr_value_str_by_name(attrs, "crate_name")
}
#[deriving(PartialEq)]
}
}
- pub fn span_to_str(&self, sp: Span) -> String {
+ pub fn span_to_string(&self, sp: Span) -> String {
if self.files.borrow().len() == 0 && sp == DUMMY_SP {
return "no-location".to_string();
}
// Test span_to_str for a span ending at the end of filemap
let cm = init_code_map();
let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
- let sstr = cm.span_to_str(span);
+ let sstr = cm.span_to_string(span);
assert_eq!(sstr, "blork.rs:2:1: 2:12".to_string());
}
}
try!(print_maybe_styled(dst,
- format!("{}: ", lvl.to_str()).as_slice(),
+ format!("{}: ", lvl.to_string()).as_slice(),
term::attr::ForegroundColor(lvl.color())));
try!(print_maybe_styled(dst,
format!("{}\n", msg).as_slice(),
fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
msg: &str, lvl: Level, custom: bool) -> io::IoResult<()> {
let sp = rsp.span();
- let ss = cm.span_to_str(sp);
+ let ss = cm.span_to_string(sp);
let lines = cm.span_to_lines(sp);
if custom {
// we want to tell compiletest/runtest to look at the last line of the
// span (since `custom_highlight_lines` displays an arrow to the end of
// the span)
let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info};
- let ses = cm.span_to_str(span_end);
+ let ses = cm.span_to_string(span_end);
try!(print_diagnostic(dst, ses.as_slice(), lvl, msg));
if rsp.is_full_span() {
try!(custom_highlight_lines(dst, cm, sp, lvl, lines));
let ss = ei.callee
.span
.as_ref()
- .map_or("".to_string(), |span| cm.span_to_str(*span));
+ .map_or("".to_string(), |span| cm.span_to_string(*span));
let (pre, post) = match ei.callee.format {
codemap::MacroAttribute => ("#[", "]"),
codemap::MacroBang => ("", "!")
format!("in expansion of {}{}{}", pre,
ei.callee.name,
post).as_slice()));
- let ss = cm.span_to_str(ei.call_site);
+ let ss = cm.span_to_string(ei.call_site);
try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site"));
try!(print_macro_backtrace(w, cm, ei.call_site));
}
'statement: loop {
match state {
Asm => {
- let (s, style) = match expr_to_str(cx, p.parse_expr(),
+ let (s, style) = match expr_to_string(cx, p.parse_expr(),
"inline assembly must be a string literal.") {
Some((s, st)) => (s, st),
// let compilation continue
// Append an input operand, with the form of ("0", expr)
// that links to an output operand.
for &(i, out) in read_write_operands.iter() {
- inputs.push((token::intern_and_get_ident(i.to_str().as_slice()),
+ inputs.push((token::intern_and_get_ident(i.to_string().as_slice()),
out));
}
use parse::token;
use parse::token::{InternedString, intern, str_to_ident};
use util::small_vector::SmallVector;
+use ext::mtwt;
use std::collections::HashMap;
use std::gc::{Gc, GC};
// should macros escape from this scope?
pub macros_escape: bool,
// what are the pending renames?
- pub pending_renames: RenameList,
+ pub pending_renames: mtwt::RenameList,
}
impl BlockInfo {
}
}
-// a list of ident->name renamings
-pub type RenameList = Vec<(ast::Ident, Name)>;
-
// The base map of methods for expanding syntax extension
// AST nodes into full ASTs
pub fn syntax_expander_table() -> SyntaxEnv {
pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
pub fn mod_path(&self) -> Vec<ast::Ident> {
let mut v = Vec::new();
- v.push(token::str_to_ident(self.ecfg.crate_id.name.as_slice()));
+ v.push(token::str_to_ident(self.ecfg.crate_name.as_slice()));
v.extend(self.mod_path.iter().map(|a| *a));
return v;
}
/// Extract a string literal from the macro expanded version of `expr`,
/// emitting `err_msg` if `expr` is not a string literal. This does not stop
/// compilation on error, merely emits a non-fatal error and returns None.
-pub fn expr_to_str(cx: &mut ExtCtxt, expr: Gc<ast::Expr>, err_msg: &str)
+pub fn expr_to_string(cx: &mut ExtCtxt, expr: Gc<ast::Expr>, err_msg: &str)
-> Option<(InternedString, ast::StrStyle)> {
// we want to be able to handle e.g. concat("foo", "bar")
let expr = cx.expand_expr(expr);
fn typaram(&self,
span: Span,
id: ast::Ident,
- sized: ast::Sized,
bounds: OwnedSlice<ast::TyParamBound>,
+ unbound: Option<ast::TyParamBound>,
default: Option<P<ast::Ty>>) -> ast::TyParam;
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
fn typaram(&self,
span: Span,
id: ast::Ident,
- sized: ast::Sized,
bounds: OwnedSlice<ast::TyParamBound>,
+ unbound: Option<ast::TyParamBound>,
default: Option<P<ast::Ty>>) -> ast::TyParam {
ast::TyParam {
ident: id,
id: ast::DUMMY_NODE_ID,
- sized: sized,
bounds: bounds,
+ unbound: unbound,
default: default,
span: span
}
fn strip_bounds(&self, generics: &Generics) -> Generics {
let new_params = generics.ty_params.map(|ty_param| {
- ast::TyParam { bounds: OwnedSlice::empty(), ..*ty_param }
+ ast::TyParam { bounds: OwnedSlice::empty(), unbound: None, ..*ty_param }
});
Generics {
ty_params: new_params,
encodable.rs for more.
*/
-use ast;
use ast::{MetaItem, Item, Expr, MutMutable, Ident};
use codemap::Span;
use ext::base::ExtCtxt;
additional_bounds: Vec::new(),
generics: LifetimeBounds {
lifetimes: Vec::new(),
- bounds: vec!(("__D", ast::StaticSize, vec!(Path::new_(
+ bounds: vec!(("__D", None, vec!(Path::new_(
vec!("serialize", "Decoder"), None,
vec!(box Literal(Path::new_local("__E"))), true))),
- ("__E", ast::StaticSize, vec!()))
+ ("__E", None, vec!()))
},
methods: vec!(
MethodDef {
```
*/
-use ast;
use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
use codemap::Span;
use ext::base::ExtCtxt;
additional_bounds: Vec::new(),
generics: LifetimeBounds {
lifetimes: Vec::new(),
- bounds: vec!(("__S", ast::StaticSize, vec!(Path::new_(
+ bounds: vec!(("__S", None, vec!(Path::new_(
vec!("serialize", "Encoder"), None,
vec!(box Literal(Path::new_local("__E"))), true))),
- ("__E", ast::StaticSize, vec!()))
+ ("__E", None, vec!()))
},
methods: vec!(
MethodDef {
cx.typaram(self.span,
ty_param.ident,
- ty_param.sized,
OwnedSlice::from_vec(bounds),
+ ty_param.unbound.clone(),
None)
}));
let trait_generics = Generics {
}
-fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, sized: ast::Sized, bounds: &[Path],
+fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
+ bounds: &[Path], unbound: Option<ast::TyParamBound>,
self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
let bounds =
bounds.iter().map(|b| {
let path = b.to_path(cx, span, self_ident, self_generics);
cx.typarambound(path)
}).collect();
- cx.typaram(span, cx.ident_of(name), sized, bounds, None)
+ cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}
-fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) -> Generics {
+fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
Generics {
lifetimes: lifetimes,
ty_params: OwnedSlice::from_vec(ty_params)
/// Lifetimes and bounds on type parameters
pub struct LifetimeBounds<'a> {
pub lifetimes: Vec<&'a str>,
- pub bounds: Vec<(&'a str, ast::Sized, Vec<Path<'a>>)>,
+ pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}
impl<'a> LifetimeBounds<'a> {
}).collect();
let ty_params = self.bounds.iter().map(|t| {
match t {
- &(ref name, sized, ref bounds) => {
+ &(ref name, ref unbound, ref bounds) => {
mk_ty_param(cx,
span,
*name,
- sized,
bounds.as_slice(),
+ unbound.clone(),
self_ty,
self_generics)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast;
use ast::{MetaItem, Item, Expr, MutMutable};
use codemap::Span;
use ext::base::ExtCtxt;
vec!(box Literal(Path::new_local("__S"))), true),
LifetimeBounds {
lifetimes: Vec::new(),
- bounds: vec!(("__S", ast::StaticSize,
+ bounds: vec!(("__S", None,
vec!(Path::new(vec!("std", "hash", "Writer"))))),
},
Path::new_local("__S"))
generics: LifetimeBounds {
lifetimes: Vec::new(),
bounds: vec!(("R",
- ast::StaticSize,
+ None,
vec!( Path::new(vec!("std", "rand", "Rng")) )))
},
explicit_self: None,
Some(exprs) => exprs
};
- let var = match expr_to_str(cx,
+ let var = match expr_to_string(cx,
*exprs.get(0),
"expected string literal") {
None => return DummyResult::expr(sp),
var).as_slice())
}
2 => {
- match expr_to_str(cx, *exprs.get(1), "expected string literal") {
+ match expr_to_string(cx, *exprs.get(1), "expected string literal") {
None => return DummyResult::expr(sp),
Some((s, _style)) => s
}
use attr::AttrMetaMethods;
use codemap;
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
-use crateid::CrateId;
use ext::base::*;
+use fold;
use fold::*;
use parse;
use parse::token::{fresh_mark, fresh_name, intern};
fld.cx.expr(e.span, ast::ExprLoop(loop_block, opt_ident))
}
+ ast::ExprFnBlock(fn_decl, block) => {
+ let (rewritten_fn_decl, rewritten_block)
+ = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
+ let new_node = ast::ExprFnBlock(rewritten_fn_decl, rewritten_block);
+ box(GC) ast::Expr{id:e.id, node: new_node, span: fld.new_span(e.span)}
+ }
+
+ ast::ExprProc(fn_decl, block) => {
+ let (rewritten_fn_decl, rewritten_block)
+ = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
+ let new_node = ast::ExprProc(rewritten_fn_decl, rewritten_block);
+ box(GC) ast::Expr{id:e.id, node: new_node, span: fld.new_span(e.span)}
+ }
+
_ => noop_fold_expr(e, fld)
}
}
}
}
-// eval $e with a new exts frame:
+// eval $e with a new exts frame.
+// must be a macro so that $e isn't evaluated too early.
macro_rules! with_exts_frame (
($extsboxexpr:expr,$macros_escape:expr,$e:expr) =>
({$extsboxexpr.push_frame();
fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
-> Gc<ast::Item> {
- let (modifiers, attrs) = it.attrs.partitioned(|attr| {
+ // partition the attributes into ItemModifiers and others
+ let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
match fld.extsbox.find(&intern(attr.name().get())) {
Some(&ItemModifier(_)) => true,
_ => false
}
});
-
+ // update the attrs, leave everything else alone. Is this mutation really a good idea?
it = box(GC) ast::Item {
- attrs: attrs,
+ attrs: other_attrs,
..(*it).clone()
};
expand_item_modifiers(it, fld)
}
+/// Expand item_underscore
+fn expand_item_underscore(item: &ast::Item_, fld: &mut MacroExpander) -> ast::Item_ {
+ match *item {
+ ast::ItemFn(decl, fn_style, abi, ref generics, body) => {
+ let (rewritten_fn_decl, rewritten_body)
+ = expand_and_rename_fn_decl_and_block(decl,body,fld);
+ let expanded_generics = fold::fold_generics(generics,fld);
+ ast::ItemFn(rewritten_fn_decl, fn_style, abi, expanded_generics, rewritten_body)
+ }
+ _ => noop_fold_item_underscore(&*item, fld)
+ }
+}
+
// does this attribute list contain "macro_escape" ?
fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
attr::contains_name(attrs, "macro_escape")
} = **local;
// expand the pat (it might contain macro uses):
let expanded_pat = fld.fold_pat(pat);
- // find the pat_idents in the pattern:
+ // find the PatIdents in the pattern:
// oh dear heaven... this is going to include the enum
// names, as well... but that should be okay, as long as
// the new names are gensyms for the old ones.
}
}
+// expand the arm of a 'match', renaming for macro hygiene
fn expand_arm(arm: &ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
// expand pats... they might contain macro uses:
let expanded_pats : Vec<Gc<ast::Pat>> = arm.pats.iter().map(|pat| fld.fold_pat(*pat)).collect();
// all of the pats must have the same set of bindings, so use the
// first one to extract them and generate new names:
let first_pat = expanded_pats.get(0);
- // code duplicated from 'let', above. Perhaps this can be lifted
- // into a separate function:
let idents = pattern_bindings(*first_pat);
- let mut new_pending_renames =
+ let new_renames =
idents.iter().map(|id| (*id,fresh_name(id))).collect();
- // rewrite all of the patterns using the new names (the old
- // ones have already been applied). Note that we depend here
- // on the guarantee that after expansion, there can't be any
- // Path expressions (a.k.a. varrefs) left in the pattern. If
- // this were false, we'd need to apply this renaming only to
- // the bindings, and not to the varrefs, using a more targeted
- // fold-er.
- let mut rename_fld = IdentRenamer{renames:&mut new_pending_renames};
+ // apply the renaming, but only to the PatIdents:
+ let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
let rewritten_pats =
- expanded_pats.iter().map(|pat| rename_fld.fold_pat(*pat)).collect();
+ expanded_pats.iter().map(|pat| rename_pats_fld.fold_pat(*pat)).collect();
// apply renaming and then expansion to the guard and the body:
+ let mut rename_fld = IdentRenamer{renames:&new_renames};
let rewritten_guard =
arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body));
}
}
-
-
-// a visitor that extracts the pat_ident (binding) paths
-// from a given thingy and puts them in a mutable
-// array
+/// A visitor that extracts the PatIdent (binding) paths
+/// from a given thingy and puts them in a mutable
+/// array
#[deriving(Clone)]
-struct NameFinderContext {
+struct PatIdentFinder {
ident_accumulator: Vec<ast::Ident> ,
}
-impl Visitor<()> for NameFinderContext {
+impl Visitor<()> for PatIdentFinder {
fn visit_pat(&mut self, pattern: &ast::Pat, _: ()) {
match *pattern {
- // we found a pat_ident!
- ast::Pat {
- id: _,
- node: ast::PatIdent(_, ref path1, ref inner),
- span: _
- } => {
+ ast::Pat { id: _, node: ast::PatIdent(_, ref path1, ref inner), span: _ } => {
self.ident_accumulator.push(path1.node);
- // visit optional subpattern of pat_ident:
+ // visit optional subpattern of PatIdent:
for subpat in inner.iter() {
self.visit_pat(&**subpat, ())
}
}
- // use the default traversal for non-pat_idents
+ // use the default traversal for non-PatIdents
_ => visit::walk_pat(self, pattern, ())
}
}
}
-// find the pat_ident paths in a pattern
+/// find the PatIdent paths in a pattern
fn pattern_bindings(pat : &ast::Pat) -> Vec<ast::Ident> {
- let mut name_finder = NameFinderContext{ident_accumulator:Vec::new()};
+ let mut name_finder = PatIdentFinder{ident_accumulator:Vec::new()};
name_finder.visit_pat(pat,());
name_finder.ident_accumulator
}
+/// find the PatIdent paths in a
+fn fn_decl_arg_bindings(fn_decl: &ast::FnDecl) -> Vec<ast::Ident> {
+ let mut pat_idents = PatIdentFinder{ident_accumulator:Vec::new()};
+ for arg in fn_decl.inputs.iter() {
+ pat_idents.visit_pat(arg.pat,());
+ }
+ pat_idents.ident_accumulator
+}
+
// expand a block. pushes a new exts_frame, then calls expand_block_elts
fn expand_block(blk: &Block, fld: &mut MacroExpander) -> P<Block> {
// see note below about treatment of exts table
}
}
-// a tree-folder that applies every rename in its (mutable) list
-// to every identifier, including both bindings and varrefs
-// (and lots of things that will turn out to be neither)
+/// A tree-folder that applies every rename in its (mutable) list
+/// to every identifier, including both bindings and varrefs
+/// (and lots of things that will turn out to be neither)
pub struct IdentRenamer<'a> {
- renames: &'a mut RenameList,
+ renames: &'a mtwt::RenameList,
}
impl<'a> Folder for IdentRenamer<'a> {
fn fold_ident(&mut self, id: Ident) -> Ident {
- let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| {
- mtwt::new_rename(from, to, ctxt)
- });
Ident {
name: id.name,
- ctxt: new_ctxt,
+ ctxt: mtwt::apply_renames(self.renames, id.ctxt),
}
}
}
-fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
- /* this discards information in the case of macro-defining macros */
- Span {
- lo: sp.lo,
- hi: sp.hi,
- expn_info: cx.backtrace(),
+/// A tree-folder that applies every rename in its list to
+/// the idents that are in PatIdent patterns. This is more narrowly
+/// focused than IdentRenamer, and is needed for FnDecl,
+/// where we want to rename the args but not the fn name or the generics etc.
+pub struct PatIdentRenamer<'a> {
+ renames: &'a mtwt::RenameList,
+}
+
+impl<'a> Folder for PatIdentRenamer<'a> {
+ fn fold_pat(&mut self, pat: Gc<ast::Pat>) -> Gc<ast::Pat> {
+ match pat.node {
+ ast::PatIdent(binding_mode, Spanned{span: ref sp, node: id}, ref sub) => {
+ let new_ident = Ident{name: id.name,
+ ctxt: mtwt::apply_renames(self.renames, id.ctxt)};
+ let new_node =
+ ast::PatIdent(binding_mode,
+ Spanned{span: self.new_span(*sp), node: new_ident},
+ sub.map(|p| self.fold_pat(p)));
+ box(GC) ast::Pat {
+ id: pat.id,
+ span: self.new_span(pat.span),
+ node: new_node,
+ }
+ },
+ _ => noop_fold_pat(pat, self)
+ }
}
}
+/// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the
+/// PatIdents in its arguments to perform renaming in the FnDecl and
+/// the block, returning both the new FnDecl and the new Block.
+fn expand_and_rename_fn_decl_and_block(fn_decl: &ast::FnDecl, block: Gc<ast::Block>,
+ fld: &mut MacroExpander)
+ -> (Gc<ast::FnDecl>, Gc<ast::Block>) {
+ let expanded_decl = fld.fold_fn_decl(fn_decl);
+ let idents = fn_decl_arg_bindings(expanded_decl);
+ let renames =
+ idents.iter().map(|id : &ast::Ident| (*id,fresh_name(id))).collect();
+ // first, a renamer for the PatIdents, for the fn_decl:
+ let mut rename_pat_fld = PatIdentRenamer{renames: &renames};
+ let rewritten_fn_decl = rename_pat_fld.fold_fn_decl(expanded_decl);
+ // now, a renamer for *all* idents, for the body:
+ let mut rename_fld = IdentRenamer{renames: &renames};
+ let rewritten_body = fld.fold_block(rename_fld.fold_block(block));
+ (rewritten_fn_decl,rewritten_body)
+}
+
+/// A tree-folder that performs macro expansion
pub struct MacroExpander<'a, 'b> {
pub extsbox: SyntaxEnv,
pub cx: &'a mut ExtCtxt<'b>,
expand_item(item, self)
}
+ fn fold_item_underscore(&mut self, item: &ast::Item_) -> ast::Item_ {
+ expand_item_underscore(item, self)
+ }
+
fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<Gc<ast::Stmt>> {
expand_stmt(stmt, self)
}
}
}
+fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
+ /* this discards information in the case of macro-defining macros */
+ Span {
+ lo: sp.lo,
+ hi: sp.hi,
+ expn_info: cx.backtrace(),
+ }
+}
+
pub struct ExpansionConfig {
pub deriving_hash_type_parameter: bool,
- pub crate_id: CrateId,
+ pub crate_name: String,
}
pub struct ExportedMacros {
fn fold_ident(&mut self, id: Ident) -> Ident {
ast::Ident {
name: id.name,
- ctxt: mtwt::new_mark(self.mark, id.ctxt)
+ ctxt: mtwt::apply_mark(self.mark, id.ctxt)
}
}
fn fold_mac(&mut self, m: &ast::Mac) -> ast::Mac {
MacInvocTT(ref path, ref tts, ctxt) => {
MacInvocTT(self.fold_path(path),
fold_tts(tts.as_slice(), self),
- mtwt::new_mark(self.mark, ctxt))
+ mtwt::apply_mark(self.mark, ctxt))
}
};
Spanned {
#[cfg(test)]
mod test {
use super::{pattern_bindings, expand_crate, contains_macro_escape};
- use super::{NameFinderContext};
+ use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer};
use ast;
use ast::{Attribute_, AttrOuter, MetaWord};
use attr;
use codemap;
use codemap::Spanned;
use ext::mtwt;
+ use fold::Folder;
use parse;
use parse::token;
use util::parser_testing::{string_to_parser};
path_finder.path_accumulator
}
+ /// A Visitor that extracts the identifiers from a thingy.
+ // as a side note, I'm starting to want to abstract over these....
+ struct IdentFinder{
+ ident_accumulator: Vec<ast::Ident>
+ }
+
+ impl Visitor<()> for IdentFinder {
+ fn visit_ident(&mut self, _: codemap::Span, id: ast::Ident, _: ()){
+ self.ident_accumulator.push(id);
+ }
+ }
+ /// Find the idents in a crate
+ fn crate_idents(the_crate: &ast::Crate) -> Vec<ast::Ident> {
+ let mut ident_finder = IdentFinder{ident_accumulator: Vec::new()};
+ visit::walk_crate(&mut ident_finder, the_crate, ());
+ ident_finder.ident_accumulator
+ }
// these following tests are quite fragile, in that they don't test what
// *kind* of failure occurs.
// should fail:
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
- crate_id: from_str("test").unwrap(),
+ crate_name: "test".to_string(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
- crate_id: from_str("test").unwrap(),
+ crate_name: "test".to_string(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
- crate_id: from_str("test").unwrap(),
+ crate_name: "test".to_string(),
};
expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
}
// the cfg argument actually does matter, here...
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
- crate_id: from_str("test").unwrap(),
+ crate_name: "test".to_string(),
};
expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
}
// find the pat_ident paths in a crate
fn crate_bindings(the_crate : &ast::Crate) -> Vec<ast::Ident> {
- let mut name_finder = NameFinderContext{ident_accumulator:Vec::new()};
+ let mut name_finder = PatIdentFinder{ident_accumulator:Vec::new()};
visit::walk_crate(&mut name_finder, the_crate, ());
name_finder.ident_accumulator
}
-
//fn expand_and_resolve(crate_str: @str) -> ast::crate {
//let expanded_ast = expand_crate_str(crate_str);
// println!("expanded: {:?}\n",expanded_ast);
//}
//fn expand_and_resolve_and_pretty_print (crate_str: @str) -> String {
//let resolved_ast = expand_and_resolve(crate_str);
- //pprust::to_str(&resolved_ast,fake_print_crate,get_ident_interner())
+ //pprust::to_string(&resolved_ast,fake_print_crate,get_ident_interner())
//}
#[test] fn macro_tokens_should_match(){
// but *shouldn't* bind because it was inserted by a different macro....
// can't write this test case until we have macro-generating macros.
- // FIXME #9383 : lambda var hygiene
- // interesting... can't even write this test, yet, because the name-finder
- // only finds pattern vars. Time to upgrade test framework.
- /*#[test]
- fn issue_9383(){
+ // item fn hygiene
+ // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};}
+ #[test] fn issue_9383(){
run_renaming_test(
- &("macro_rules! bad_macro (($ex:expr) => ({(|_x| { $ex }) (9) }))
- fn takes_x(_x : int) { assert_eq!(bad_macro!(_x),8); }
- fn main() { takes_x(8); }",
- vec!(vec!()),false),
+ &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex }))
+ fn q(x:int) { bad_macro!(x); }",
+ vec!(vec!(1),vec!(0)),true),
0)
- }*/
+ }
+
+ // closure arg hygiene (ExprFnBlock)
+ // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);}
+ #[test] fn closure_arg_hygiene(){
+ run_renaming_test(
+ &("macro_rules! inject_x (()=>(x))
+ fn f(){(|x : int| {(inject_x!() + x)})(3);}",
+ vec!(vec!(1)),
+ true),
+ 0)
+ }
+
+ // closure arg hygiene (ExprProc)
+ // expands to fn f(){(proc(x_1 : int) {(x_2 + x_1)})(3);}
+ #[test] fn closure_arg_hygiene_2(){
+ run_renaming_test(
+ &("macro_rules! inject_x (()=>(x))
+ fn f(){ (proc(x : int){(inject_x!() + x)})(3); }",
+ vec!(vec!(1)),
+ true),
+ 0)
+ }
// run one of the renaming tests
fn run_renaming_test(t: &RenamingTest, test_idx: uint) {
assert_eq!(varref_marks,binding_marks.clone());
}
} else {
+ let varref_name = mtwt::resolve(varref.segments.get(0).identifier);
let fail = (varref.segments.len() == 1)
- && (mtwt::resolve(varref.segments.get(0).identifier)
- == binding_name);
+ && (varref_name == binding_name);
// temp debugging:
if fail {
let varref_idents : Vec<ast::Ident>
println!("text of test case: \"{}\"", teststr);
println!("");
println!("uh oh, matches but shouldn't:");
- println!("varref: {}",varref_idents);
+ println!("varref #{}: {}, resolves to {}",idx, varref_idents,
+ varref_name);
// good lord, you can't make a path with 0 segments, can you?
let string = token::get_ident(varref.segments
.get(0)
println!("varref's first segment's uint: {}, and string: \"{}\"",
varref.segments.get(0).identifier.name,
string.get());
- println!("binding: {}", *bindings.get(binding_idx));
+ println!("binding #{}: {}, resolves to {}",
+ binding_idx, *bindings.get(binding_idx),
+ binding_name);
mtwt::with_sctable(|x| mtwt::display_sctable(x));
}
assert!(!fail);
}
#[test] fn fmt_in_macro_used_inside_module_macro() {
- let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_str()))
+ let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()))
macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}}))
foo_module!()
".to_string();
// 'None' is listed as an identifier pattern because we don't yet know that
// it's the name of a 0-ary variant, and that 'i' appears twice in succession.
#[test]
- fn crate_idents(){
+ fn crate_bindings_test(){
let the_crate = string_to_crate("fn main (a : int) -> int {|b| {
match 34 {None => 3, Some(i) | i => j, Foo{k:z,l:y} => \"banana\"}} }".to_string());
let idents = crate_bindings(&the_crate);
assert_eq!(idents, strs_to_idents(vec!("a","b","None","i","i","z","y")));
}
- //
+ // test the IdentRenamer directly
+ #[test]
+ fn ident_renamer_test () {
+ let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string());
+ let f_ident = token::str_to_ident("f");
+ let x_ident = token::str_to_ident("x");
+ let int_ident = token::str_to_ident("int");
+ let renames = vec!((x_ident,16));
+ let mut renamer = IdentRenamer{renames: &renames};
+ let renamed_crate = renamer.fold_crate(the_crate);
+ let idents = crate_idents(&renamed_crate);
+ let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
+ assert_eq!(resolved,vec!(f_ident.name,16,int_ident.name,16,16,16));
+ }
+
+ // test the PatIdentRenamer; only PatIdents get renamed
+ #[test]
+ fn pat_ident_renamer_test () {
+ let the_crate = string_to_crate("fn f(x : int){let x = x; x}".to_string());
+ let f_ident = token::str_to_ident("f");
+ let x_ident = token::str_to_ident("x");
+ let int_ident = token::str_to_ident("int");
+ let renames = vec!((x_ident,16));
+ let mut renamer = PatIdentRenamer{renames: &renames};
+ let renamed_crate = renamer.fold_crate(the_crate);
+ let idents = crate_idents(&renamed_crate);
+ let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
+ let x_name = x_ident.name;
+ assert_eq!(resolved,vec!(f_ident.name,16,int_ident.name,16,x_name,x_name));
+ }
+
}
_ => {
ecx.span_err(p.span,
format!("expected ident for named argument, but found `{}`",
- p.this_token_to_str()).as_slice());
+ p.this_token_to_string()).as_slice());
return (invocation, None);
}
};
fmtsp: sp,
};
cx.fmtsp = efmt.span;
- let fmt = match expr_to_str(cx.ecx,
+ let fmt = match expr_to_string(cx.ecx,
efmt,
"format argument must be a string literal.") {
Some((fmt, _)) => fmt,
-> Box<base::MacResult> {
cx.print_backtrace();
- println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
+ println!("{}", print::pprust::tt_to_string(&ast::TTDelim(
Rc::new(tt.iter().map(|x| (*x).clone()).collect()))));
// any so that `log_syntax` can be invoked as an expression and item.
IllegalCtxt
}
+/// A list of ident->name renamings
+pub type RenameList = Vec<(Ident, Name)>;
+
/// Extend a syntax context with a given mark
-pub fn new_mark(m: Mrk, tail: SyntaxContext) -> SyntaxContext {
- with_sctable(|table| new_mark_internal(m, tail, table))
+pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext {
+ with_sctable(|table| apply_mark_internal(m, ctxt, table))
}
-// Extend a syntax context with a given mark and table
-fn new_mark_internal(m: Mrk, tail: SyntaxContext, table: &SCTable) -> SyntaxContext {
- let key = (tail, m);
+// Extend a syntax context with a given mark and sctable (explicit memoization)
+fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext {
+ let key = (ctxt, m);
let new_ctxt = |_: &(SyntaxContext, Mrk)|
- idx_push(&mut *table.table.borrow_mut(), Mark(m, tail));
+ idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt));
*table.mark_memo.borrow_mut().find_or_insert_with(key, new_ctxt)
}
/// Extend a syntax context with a given rename
-pub fn new_rename(id: Ident, to:Name,
- tail: SyntaxContext) -> SyntaxContext {
- with_sctable(|table| new_rename_internal(id, to, tail, table))
+pub fn apply_rename(id: Ident, to:Name,
+ ctxt: SyntaxContext) -> SyntaxContext {
+ with_sctable(|table| apply_rename_internal(id, to, ctxt, table))
}
-// Extend a syntax context with a given rename and sctable
-fn new_rename_internal(id: Ident,
+// Extend a syntax context with a given rename and sctable (explicit memoization)
+fn apply_rename_internal(id: Ident,
to: Name,
- tail: SyntaxContext,
+ ctxt: SyntaxContext,
table: &SCTable) -> SyntaxContext {
- let key = (tail,id,to);
+ let key = (ctxt,id,to);
let new_ctxt = |_: &(SyntaxContext, Ident, Mrk)|
- idx_push(&mut *table.table.borrow_mut(), Rename(id, to, tail));
+ idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt));
*table.rename_memo.borrow_mut().find_or_insert_with(key, new_ctxt)
}
+/// Apply a list of renamings to a context
+// if these rename lists get long, it would make sense
+// to consider memoizing this fold. This may come up
+// when we add hygiene to item names.
+pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext {
+ renames.iter().fold(ctxt, |ctxt, &(from, to)| {
+ apply_rename(from, to, ctxt)
+ })
+}
+
/// Fetch the SCTable from TLS, create one if it doesn't yet exist.
pub fn with_sctable<T>(op: |&SCTable| -> T) -> T {
local_data_key!(sctable_key: Rc<SCTable>)
#[cfg(test)]
mod tests {
- use ast::*;
- use super::{resolve, xor_push, new_mark_internal, new_sctable_internal};
- use super::{new_rename_internal, marksof_internal, resolve_internal};
+ use ast::{EMPTY_CTXT, Ident, Mrk, Name, SyntaxContext};
+ use super::{resolve, xor_push, apply_mark_internal, new_sctable_internal};
+ use super::{apply_rename_internal, apply_renames, marksof_internal, resolve_internal};
use super::{SCTable, EmptyCtxt, Mark, Rename, IllegalCtxt};
use std::collections::HashMap;
-> SyntaxContext {
tscs.iter().rev().fold(tail, |tail : SyntaxContext, tsc : &TestSC|
{match *tsc {
- M(mrk) => new_mark_internal(mrk,tail,table),
- R(ident,name) => new_rename_internal(ident,name,tail,table)}})
+ M(mrk) => apply_mark_internal(mrk,tail,table),
+ R(ident,name) => apply_rename_internal(ident,name,tail,table)}})
}
// gather a SyntaxContext back into a vector of TestSCs
fn unfold_marks(mrks: Vec<Mrk> , tail: SyntaxContext, table: &SCTable)
-> SyntaxContext {
mrks.iter().rev().fold(tail, |tail:SyntaxContext, mrk:&Mrk|
- {new_mark_internal(*mrk,tail,table)})
+ {apply_mark_internal(*mrk,tail,table)})
}
#[test] fn unfold_marks_test() {
// rename where stop doesn't match:
{ let chain = vec!(M(9),
R(id(name1,
- new_mark_internal (4, EMPTY_CTXT,&mut t)),
+ apply_mark_internal (4, EMPTY_CTXT,&mut t)),
100101102),
M(14));
let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
assert_eq! (marksof_internal (ans, stopname, &t), vec!(9,14));}
// rename where stop does match
- { let name1sc = new_mark_internal(4, EMPTY_CTXT, &mut t);
+ { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t);
let chain = vec!(M(9),
R(id(name1, name1sc),
stopname),
{ let sc = unfold_test_sc(vec!(R(id(50,EMPTY_CTXT),51),M(12)),EMPTY_CTXT,&mut t);
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt),a);}
// - rename where names do match, but marks don't
- { let sc1 = new_mark_internal(1,EMPTY_CTXT,&mut t);
+ { let sc1 = apply_mark_internal(1,EMPTY_CTXT,&mut t);
let sc = unfold_test_sc(vec!(R(id(a,sc1),50),
M(1),
M(2)),
EMPTY_CTXT,&mut t);
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt), 51); }
// the simplest double-rename:
- { let a_to_a50 = new_rename_internal(id(a,EMPTY_CTXT),50,EMPTY_CTXT,&mut t);
- let a50_to_a51 = new_rename_internal(id(a,a_to_a50),51,a_to_a50,&mut t);
+ { let a_to_a50 = apply_rename_internal(id(a,EMPTY_CTXT),50,EMPTY_CTXT,&mut t);
+ let a50_to_a51 = apply_rename_internal(id(a,a_to_a50),51,a_to_a50,&mut t);
assert_eq!(resolve_internal(id(a,a50_to_a51),&mut t, &mut rt),51);
// mark on the outside doesn't stop rename:
- let sc = new_mark_internal(9,a50_to_a51,&mut t);
+ let sc = apply_mark_internal(9,a50_to_a51,&mut t);
assert_eq!(resolve_internal(id(a,sc),&mut t, &mut rt),51);
// but mark on the inside does:
let a50_to_a51_b = unfold_test_sc(vec!(R(id(a,a_to_a50),51),
#[test]
fn hashing_tests () {
let mut t = new_sctable_internal();
- assert_eq!(new_mark_internal(12,EMPTY_CTXT,&mut t),2);
- assert_eq!(new_mark_internal(13,EMPTY_CTXT,&mut t),3);
+ assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
+ assert_eq!(apply_mark_internal(13,EMPTY_CTXT,&mut t),3);
// using the same one again should result in the same index:
- assert_eq!(new_mark_internal(12,EMPTY_CTXT,&mut t),2);
+ assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
// I'm assuming that the rename table will behave the same....
}
resolve_internal(id(30,EMPTY_CTXT),&mut t, &mut rt);
assert_eq!(rt.len(),2);
}
+
+ #[test]
+ fn new_resolves_test() {
+ let renames = vec!((Ident{name:23,ctxt:EMPTY_CTXT},24),
+ (Ident{name:29,ctxt:EMPTY_CTXT},29));
+ let new_ctxt1 = apply_renames(&renames,EMPTY_CTXT);
+ assert_eq!(resolve(Ident{name:23,ctxt:new_ctxt1}),24);
+ assert_eq!(resolve(Ident{name:29,ctxt:new_ctxt1}),29);
+ }
}
}
}
- impl_to_source!(ast::Ty, ty_to_str)
- impl_to_source!(ast::Block, block_to_str)
- impl_to_source!(ast::Arg, arg_to_str)
- impl_to_source!(Generics, generics_to_str)
- impl_to_source!(Gc<ast::Item>, item_to_str)
- impl_to_source!(Gc<ast::Expr>, expr_to_str)
- impl_to_source!(Gc<ast::Pat>, pat_to_str)
+ impl_to_source!(ast::Ty, ty_to_string)
+ impl_to_source!(ast::Block, block_to_string)
+ impl_to_source!(ast::Arg, arg_to_string)
+ impl_to_source!(Generics, generics_to_string)
+ impl_to_source!(Gc<ast::Item>, item_to_string)
+ impl_to_source!(Gc<ast::Expr>, expr_to_string)
+ impl_to_source!(Gc<ast::Pat>, pat_to_string)
impl_to_source_slice!(ast::Ty, ", ")
impl_to_source_slice!(Gc<ast::Item>, "\n\n")
fn to_source(&self) -> String {
let lit = dummy_spanned(ast::LitStr(
token::intern_and_get_ident(*self), ast::CookedStr));
- pprust::lit_to_str(&lit)
+ pprust::lit_to_string(&lit)
}
}
impl ToSource for bool {
fn to_source(&self) -> String {
let lit = dummy_spanned(ast::LitBool(*self));
- pprust::lit_to_str(&lit)
+ pprust::lit_to_string(&lit)
}
}
impl ToSource for char {
fn to_source(&self) -> String {
let lit = dummy_spanned(ast::LitChar(*self));
- pprust::lit_to_str(&lit)
+ pprust::lit_to_string(&lit)
}
}
impl ToSource for $t {
fn to_source(&self) -> String {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::$tag));
- pprust::lit_to_str(&lit)
+ pprust::lit_to_string(&lit)
}
}
);
impl ToSource for $t {
fn to_source(&self) -> String {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::$tag));
- pprust::lit_to_str(&lit)
+ pprust::lit_to_string(&lit)
}
}
);
pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult> {
- let s = pprust::tts_to_str(tts);
+ let s = pprust::tts_to_string(tts);
base::MacExpr::new(cx.expr_str(sp,
token::intern_and_get_ident(s.as_slice())))
}
Some(src) => {
// Add this input file to the code map to make it available as
// dependency information
- let filename = file.display().to_str();
+ let filename = file.display().to_string();
let interned = token::intern_and_get_ident(src);
cx.codemap().new_filemap(filename, src.to_string());
nts, next_eis.len()).to_string());
} else if bb_eis.len() == 0u && next_eis.len() == 0u {
return Failure(sp, format!("no rules expected the token `{}`",
- token::to_str(&tok)).to_string());
+ token::to_string(&tok)).to_string());
} else if next_eis.len() > 0u {
/* Now process the next token */
while next_eis.len() > 0u {
"ident" => match p.token {
token::IDENT(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
_ => {
- let token_str = token::to_str(&p.token);
+ let token_str = token::to_string(&p.token);
p.fatal((format!("expected ident, found {}",
token_str.as_slice())).as_slice())
}
parser.bump()
}
if parser.token != EOF {
- let token_str = parser.this_token_to_str();
+ let token_str = parser.this_token_to_string();
let msg = format!("macro expansion ignores token `{}` and any \
following",
token_str);
println!("{}! {} {} {}",
token::get_ident(name),
"{",
- print::pprust::tt_to_str(&TTDelim(Rc::new(arg.iter()
+ print::pprust::tt_to_string(&TTDelim(Rc::new(arg.iter()
.map(|x| (*x).clone())
.collect()))),
"}");
box MacroRulesDefiner {
def: RefCell::new(Some(MacroDef {
- name: token::get_ident(name).to_str(),
+ name: token::get_ident(name).to_string(),
ext: NormalTT(exp, Some(sp))
}))
} as Box<MacResult>
TyParam {
ident: tp.ident,
id: id,
- sized: tp.sized,
bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)),
+ unbound: tp.unbound.as_ref().map(|x| fold_ty_param_bound(x, fld)),
default: tp.default.map(|x| fld.fold_ty(x)),
span: tp.span
}
methods.iter().map(|x| folder.fold_method(*x)).collect()
)
}
- ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
+ ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
let methods = methods.iter().map(|method| {
match *method {
Required(ref m) => Required(folder.fold_type_method(m)),
}
}).collect();
ItemTrait(fold_generics(generics, folder),
- *sized,
+ unbound.clone(),
traits.iter().map(|p| fold_trait_ref(p, folder)).collect(),
methods)
}
PatIdent(binding_mode, ref pth1, ref sub) => {
PatIdent(binding_mode,
Spanned{span: folder.new_span(pth1.span),
- node: folder.fold_ident(pth1.node)},
+ node: folder.fold_ident(pth1.node)},
sub.map(|x| folder.fold_pat(x)))
}
PatLit(e) => PatLit(folder.fold_expr(e)),
assert_pred!(
matches_codepattern,
"matches_codepattern",
- pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
+ pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
"#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string());
}
assert_pred!(
matches_codepattern,
"matches_codepattern",
- pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
+ pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_string());
}
}
*/
-#![crate_id = "syntax#0.11.0"]
+#![crate_id = "syntax#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "syntax"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
#![feature(quote, unsafe_destructor)]
#![allow(deprecated)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate serialize;
extern crate term;
(mk_sp(lo, hi), meta_item, style)
}
_ => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `#` but found `{}`",
token_str).as_slice());
}
literals.push(Literal {lit: s.to_string(), pos: sp.lo});
})
} else {
- debug!("tok: {}", token::to_str(&tok));
+ debug!("tok: {}", token::to_string(&tok));
}
first_read = false;
}
'@' => { self.bump(); return token::AT; }
'#' => { self.bump(); return token::POUND; }
'~' => { self.bump(); return token::TILDE; }
+ '?' => { self.bump(); return token::QUESTION; }
':' => {
self.bump();
if self.curr_is(':') {
#[cfg(test)]
mod test {
use super::*;
- use serialize::{json, Encodable};
- use std::io;
- use std::io::MemWriter;
- use std::mem::transmute;
- use std::str;
+ use serialize::json;
use std::gc::GC;
use codemap::{Span, BytePos, Spanned};
use owned_slice::OwnedSlice;
use util::parser_testing::{string_to_expr, string_to_item};
use util::parser_testing::string_to_stmt;
- fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> String {
- let mut writer = MemWriter::new();
- // FIXME(14302) remove the transmute and unsafe block.
- unsafe {
- let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
- let _ = val.encode(transmute(&mut encoder));
- }
- str::from_utf8(writer.unwrap().as_slice()).unwrap().to_string()
- }
-
// produce a codemap::span
fn sp(a: u32, b: u32) -> Span {
Span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
#[test] fn string_to_tts_1 () {
let tts = string_to_tts("fn a (b : int) { b; }".to_string());
- assert_eq!(to_json_str(&tts),
+ assert_eq!(json::encode(&tts),
"[\
{\
\"variant\":\"TTTok\",\
use ast::{PatTup, PatBox, PatWild, PatWildMulti};
use ast::{BiRem, Required};
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
-use ast::{Sized, DynSize, StaticSize};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
}
}
// convert a token to a string using self's reader
- pub fn token_to_str(token: &token::Token) -> String {
- token::to_str(token)
+ pub fn token_to_string(token: &token::Token) -> String {
+ token::to_string(token)
}
// convert the current token to a string using self's reader
- pub fn this_token_to_str(&mut self) -> String {
- Parser::token_to_str(&self.token)
+ pub fn this_token_to_string(&mut self) -> String {
+ Parser::token_to_string(&self.token)
}
pub fn unexpected_last(&mut self, t: &token::Token) -> ! {
- let token_str = Parser::token_to_str(t);
+ let token_str = Parser::token_to_string(t);
let last_span = self.last_span;
self.span_fatal(last_span, format!("unexpected token: `{}`",
token_str).as_slice());
}
pub fn unexpected(&mut self) -> ! {
- let this_token = self.this_token_to_str();
+ let this_token = self.this_token_to_string();
self.fatal(format!("unexpected token: `{}`", this_token).as_slice());
}
if self.token == *t {
self.bump();
} else {
- let token_str = Parser::token_to_str(t);
- let this_token_str = self.this_token_to_str();
+ let token_str = Parser::token_to_string(t);
+ let this_token_str = self.this_token_to_string();
self.fatal(format!("expected `{}` but found `{}`",
token_str,
this_token_str).as_slice())
pub fn expect_one_of(&mut self,
edible: &[token::Token],
inedible: &[token::Token]) {
- fn tokens_to_str(tokens: &[token::Token]) -> String {
+ fn tokens_to_string(tokens: &[token::Token]) -> String {
let mut i = tokens.iter();
// This might be a sign we need a connect method on Iterator.
let b = i.next()
- .map_or("".to_string(), |t| Parser::token_to_str(t));
+ .map_or("".to_string(), |t| Parser::token_to_string(t));
i.fold(b, |b,a| {
let mut b = b;
b.push_str("`, `");
- b.push_str(Parser::token_to_str(a).as_slice());
+ b.push_str(Parser::token_to_string(a).as_slice());
b
})
}
// leave it in the input
} else {
let expected = edible.iter().map(|x| (*x).clone()).collect::<Vec<_>>().append(inedible);
- let expect = tokens_to_str(expected.as_slice());
- let actual = self.this_token_to_str();
+ let expect = tokens_to_string(expected.as_slice());
+ let actual = self.this_token_to_string();
self.fatal(
(if expected.len() != 1 {
(format!("expected one of `{}` but found `{}`",
self.bug("ident interpolation not converted to real token");
}
_ => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal((format!("expected ident, found `{}`",
token_str)).as_slice())
}
pub fn expect_keyword(&mut self, kw: keywords::Keyword) {
if !self.eat_keyword(kw) {
let id_interned_str = token::get_ident(kw.to_ident());
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, found `{}`",
id_interned_str, token_str).as_slice())
}
// signal an error if the given string is a strict keyword
pub fn check_strict_keywords(&mut self) {
if token::is_strict_keyword(&self.token) {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
let span = self.span;
self.span_err(span,
format!("found `{}` in ident position",
// signal an error if the current token is a reserved keyword
pub fn check_reserved_keywords(&mut self) {
if token::is_reserved_keyword(&self.token) {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("`{}` is a reserved keyword",
token_str).as_slice())
}
self.replace_token(token::BINOP(token::AND), lo, span.hi)
}
_ => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
let found_token =
- Parser::token_to_str(&token::BINOP(token::AND));
+ Parser::token_to_string(&token::BINOP(token::AND));
self.fatal(format!("expected `{}`, found `{}`",
found_token,
token_str).as_slice())
self.replace_token(token::BINOP(token::OR), lo, span.hi)
}
_ => {
- let found_token = self.this_token_to_str();
+ let found_token = self.this_token_to_string();
let token_str =
- Parser::token_to_str(&token::BINOP(token::OR));
+ Parser::token_to_string(&token::BINOP(token::OR));
self.fatal(format!("expected `{}`, found `{}`",
token_str,
found_token).as_slice())
fn expect_lt(&mut self) {
if !self.eat_lt(true) {
- let found_token = self.this_token_to_str();
- let token_str = Parser::token_to_str(&token::LT);
+ let found_token = self.this_token_to_string();
+ let token_str = Parser::token_to_string(&token::LT);
self.fatal(format!("expected `{}`, found `{}`",
token_str,
found_token).as_slice())
self.replace_token(token::EQ, lo, span.hi)
}
_ => {
- let gt_str = Parser::token_to_str(&token::GT);
- let this_token_str = self.this_token_to_str();
+ let gt_str = Parser::token_to_string(&token::GT);
+ let this_token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, found `{}`",
gt_str,
this_token_str).as_slice())
}
_ => {
- let token_str = p.this_token_to_str();
+ let token_str = p.this_token_to_string();
p.fatal((format!("expected `;` or `{{` but found `{}`",
token_str)).as_slice())
}
None => {}
Some(&sp) => p.span_note(sp, "unclosed delimiter"),
};
- let token_str = p.this_token_to_str();
+ let token_str = p.this_token_to_string();
p.fatal(format!("incorrect close delimiter: `{}`",
token_str).as_slice())
},
}
token::BINOP(token::AND) | token::ANDAND => {
self.expect_and();
- let _lt = self.parse_opt_lifetime();
let m = self.parse_mutability();
let e = self.parse_prefix_expr();
hi = e.span.hi;
if self.token == token::DOTDOT {
self.bump();
if self.token != token::RBRACE {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, found `{}`", "}",
token_str).as_slice())
}
let subpat = if self.token == token::COLON {
match bind_type {
BindByRef(..) | BindByValue(MutMutable) => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("unexpected `{}`",
token_str).as_slice())
}
self.span_fatal(last_span,
"expected identifier, found path");
}
- // why a path here, and not just an identifier?
- let name = codemap::Spanned{span: self.last_span, node: self.parse_ident()};
+ let ident = self.parse_ident();
+ let last_span = self.last_span;
+ let name = codemap::Spanned{span: last_span, node: ident};
let sub = if self.eat(&token::AT) {
Some(self.parse_pat())
} else {
} else {
""
};
- let tok_str = self.this_token_to_str();
+ let tok_str = self.this_token_to_string();
self.fatal(format!("expected {}`(` or `{{`, but found `{}`",
ident_str,
tok_str).as_slice())
return (ret_lifetime, OwnedSlice::from_vec(result));
}
- // matches typaram = type? IDENT optbounds ( EQ ty )?
+ fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
+ let segment = ast::PathSegment {
+ identifier: ident,
+ lifetimes: Vec::new(),
+ types: OwnedSlice::empty(),
+ };
+ let path = ast::Path {
+ span: span,
+ global: false,
+ segments: vec![segment],
+ };
+ ast::TraitRef {
+ path: path,
+ ref_id: ast::DUMMY_NODE_ID,
+ }
+ }
+
+ // matches typaram = (unbound`?`)? IDENT optbounds ( EQ ty )?
fn parse_ty_param(&mut self) -> TyParam {
- let sized = self.parse_sized();
- let span = self.span;
- let ident = self.parse_ident();
+ // This is a bit hacky. Currently we are only interested in a single
+ // unbound, and it may only be `Sized`. To avoid backtracking and other
+ // complications, we parse an ident, then check for `?`. If we find it,
+ // we use the ident as the unbound, otherwise, we use it as the name of
+ // type param.
+ let mut span = self.span;
+ let mut ident = self.parse_ident();
+ let mut unbound = None;
+ if self.eat(&token::QUESTION) {
+ let tref = Parser::trait_ref_from_ident(ident, span);
+ unbound = Some(TraitTyParamBound(tref));
+ span = self.span;
+ ident = self.parse_ident();
+ }
+
let opt_bounds = {
if self.eat(&token::COLON) {
let (_, bounds) = self.parse_ty_param_bounds(false);
TyParam {
ident: ident,
id: ast::DUMMY_NODE_ID,
- sized: sized,
bounds: bounds,
+ unbound: unbound,
default: default,
span: span,
}
fn expect_self_ident(&mut self) {
if !self.is_self_ident() {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `self` but found `{}`",
token_str).as_slice())
}
vec!(Arg::new_self(explicit_self_sp, mutbl_self))
}
_ => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `,` or `)`, found `{}`",
token_str).as_slice())
}
// Parses two variants (with the region/type params always optional):
// impl<T> Foo { ... }
- // impl<T> ToStr for ~[T] { ... }
+ // impl<T> ToString for ~[T] { ... }
fn parse_item_impl(&mut self) -> ItemInfo {
// First, parse type parameters if necessary.
let generics = self.parse_generics();
is_tuple_like = true;
fields = Vec::new();
} else {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, `(`, or `;` after struct \
name but found `{}`", "{",
token_str).as_slice())
token::RBRACE => {}
_ => {
let span = self.span;
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.span_fatal(span,
format!("expected `,`, or `}}` but found `{}`",
token_str).as_slice())
else { Inherited }
}
- fn parse_sized(&mut self) -> Sized {
- if self.eat_keyword(keywords::Type) { DynSize }
- else { StaticSize }
- }
-
- fn parse_for_sized(&mut self) -> Sized {
+ fn parse_for_sized(&mut self) -> Option<ast::TyParamBound> {
if self.eat_keyword(keywords::For) {
- if !self.eat_keyword(keywords::Type) {
- let last_span = self.last_span;
- self.span_err(last_span,
- "expected 'type' after for in trait item");
+ let span = self.span;
+ let ident = self.parse_ident();
+ if !self.eat(&token::QUESTION) {
+ self.span_err(span,
+ "expected 'Sized?' after `for` in trait item");
+ return None;
}
- DynSize
+ let tref = Parser::trait_ref_from_ident(ident, span);
+ Some(TraitTyParamBound(tref))
} else {
- StaticSize
+ None
}
}
the module");
}
_ => {
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.fatal(format!("expected item but found `{}`",
token_str).as_slice())
}
}
_ => {
let span = self.span;
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.span_fatal(span,
format!("expected extern crate name but \
found `{}`",
}
let span = self.span;
- let token_str = self.this_token_to_str();
+ let token_str = self.this_token_to_string();
self.span_fatal(span,
format!("expected `{}` or `fn` but found `{}`", "{",
token_str).as_slice());
RBRACE,
POUND,
DOLLAR,
+ QUESTION,
/* Literals */
LIT_BYTE(u8),
}
}
-pub fn binop_to_str(o: BinOp) -> &'static str {
+pub fn binop_to_string(o: BinOp) -> &'static str {
match o {
PLUS => "+",
MINUS => "-",
}
}
-pub fn to_str(t: &Token) -> String {
+pub fn to_string(t: &Token) -> String {
match *t {
EQ => "=".to_string(),
LT => "<".to_string(),
TILDE => "~".to_string(),
OROR => "||".to_string(),
ANDAND => "&&".to_string(),
- BINOP(op) => binop_to_str(op).to_string(),
+ BINOP(op) => binop_to_string(op).to_string(),
BINOPEQ(op) => {
- let mut s = binop_to_str(op).to_string();
+ let mut s = binop_to_string(op).to_string();
s.push_str("=");
s
}
RBRACE => "}".to_string(),
POUND => "#".to_string(),
DOLLAR => "$".to_string(),
+ QUESTION => "?".to_string(),
/* Literals */
LIT_BYTE(b) => {
res.push_char('\'');
res
}
- LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
- LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
- LIT_INT_UNSUFFIXED(i) => { (i as u64).to_str() }
+ LIT_INT(i, t) => ast_util::int_ty_to_string(t, Some(i)),
+ LIT_UINT(u, t) => ast_util::uint_ty_to_string(t, Some(u)),
+ LIT_INT_UNSUFFIXED(i) => { (i as u64).to_string() }
LIT_FLOAT(s, t) => {
let mut body = String::from_str(get_ident(s).get());
if body.as_slice().ends_with(".") {
body.push_char('0'); // `10.f` is not a float literal
}
- body.push_str(ast_util::float_ty_to_str(t).as_slice());
+ body.push_str(ast_util::float_ty_to_string(t).as_slice());
body
}
LIT_FLOAT_UNSUFFIXED(s) => {
EOF => "<eof>".to_string(),
INTERPOLATED(ref nt) => {
match nt {
- &NtExpr(ref e) => ::print::pprust::expr_to_str(&**e),
- &NtMeta(ref e) => ::print::pprust::meta_item_to_str(&**e),
+ &NtExpr(ref e) => ::print::pprust::expr_to_string(&**e),
+ &NtMeta(ref e) => ::print::pprust::meta_item_to_string(&**e),
_ => {
let mut s = "an interpolated ".to_string();
match *nt {
}
// create a fresh name that maps to the same string as the old one.
-// note that this guarantees that str_ptr_eq(ident_to_str(src),interner_get(fresh_name(src)));
+// note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
// that is, that the new name and the old one are connected to ptr_eq strings.
pub fn fresh_name(src: &ast::Ident) -> Name {
let interner = get_ident_interner();
// good error messages and uses of struct names in ambiguous could-be-binding
// locations. Also definitely destroys the guarantee given above about ptr_eq.
/*let num = rand::task_rng().gen_uint_range(0,0xffff);
- gensym(format!("{}_{}",ident_to_str(src),num))*/
+ gensym(format!("{}_{}",ident_to_string(src),num))*/
}
// create a fresh mark.
use ext::mtwt;
fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
- ast::Ident{name:id.name,ctxt:mtwt::new_mark(m,id.ctxt)}
+ ast::Ident{name:id.name,ctxt:mtwt::apply_mark(m,id.ctxt)}
}
#[test] fn mtwt_token_eq_test() {
eof(&mut s.s)
}
+pub fn to_string(f: |&mut State| -> IoResult<()>) -> String {
+ let mut s = rust_printer(box MemWriter::new());
+ f(&mut s).unwrap();
+ eof(&mut s.s).unwrap();
+ unsafe {
+ // FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
+ // that we "know" to be a `MemWriter` that works around the lack of checked
+ // downcasts.
+ let (_, wr): (uint, Box<MemWriter>) = mem::transmute_copy(&s.s.out);
+ let result =
+ str::from_utf8_owned(Vec::from_slice(wr.get_ref())).unwrap();
+ mem::forget(wr);
+ result.to_string()
+ }
+}
+
+pub fn ty_to_string(ty: &ast::Ty) -> String {
+ to_string(|s| s.print_type(ty))
+}
+
+pub fn pat_to_string(pat: &ast::Pat) -> String {
+ to_string(|s| s.print_pat(pat))
+}
+
+pub fn expr_to_string(e: &ast::Expr) -> String {
+ to_string(|s| s.print_expr(e))
+}
+
+pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
+ to_string(|s| s.print_lifetime(e))
+}
+
+pub fn tt_to_string(tt: &ast::TokenTree) -> String {
+ to_string(|s| s.print_tt(tt))
+}
+
+pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
+ to_string(|s| s.print_tts(tts))
+}
+
+pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
+ to_string(|s| s.print_stmt(stmt))
+}
+
+pub fn item_to_string(i: &ast::Item) -> String {
+ to_string(|s| s.print_item(i))
+}
+
+pub fn generics_to_string(generics: &ast::Generics) -> String {
+ to_string(|s| s.print_generics(generics))
+}
+
+pub fn ty_method_to_string(p: &ast::TypeMethod) -> String {
+ to_string(|s| s.print_ty_method(p))
+}
+
+pub fn method_to_string(p: &ast::Method) -> String {
+ to_string(|s| s.print_method(p))
+}
+
+pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
+ to_string(|s| s.print_fn_block_args(p))
+}
+
+pub fn path_to_string(p: &ast::Path) -> String {
+ to_string(|s| s.print_path(p, false))
+}
+
+pub fn ident_to_string(id: &ast::Ident) -> String {
+ to_string(|s| s.print_ident(*id))
+}
+
+pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
+ opt_explicit_self: Option<ast::ExplicitSelf_>,
+ generics: &ast::Generics) -> String {
+ to_string(|s| {
+ try!(s.print_fn(decl, Some(fn_style), abi::Rust,
+ name, generics, opt_explicit_self, ast::Inherited));
+ try!(s.end()); // Close the head box
+ s.end() // Close the outer box
+ })
+}
+
+pub fn block_to_string(blk: &ast::Block) -> String {
+ to_string(|s| {
+ // containing cbox, will be closed by print-block at }
+ try!(s.cbox(indent_unit));
+ // head-ibox, will be closed by print-block after {
+ try!(s.ibox(0u));
+ s.print_block(blk)
+ })
+}
+
+pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
+ to_string(|s| s.print_meta_item(mi))
+}
+
+pub fn attribute_to_string(attr: &ast::Attribute) -> String {
+ to_string(|s| s.print_attribute(attr))
+}
+
+pub fn lit_to_string(l: &ast::Lit) -> String {
+ to_string(|s| s.print_literal(l))
+}
+
+pub fn explicit_self_to_string(explicit_self: ast::ExplicitSelf_) -> String {
+ to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
+}
+
+pub fn variant_to_string(var: &ast::Variant) -> String {
+ to_string(|s| s.print_variant(var))
+}
+
+pub fn arg_to_string(arg: &ast::Arg) -> String {
+ to_string(|s| s.print_arg(arg))
+}
+
+
+
+#[cfg(stage0)]
pub fn to_str(f: |&mut State| -> IoResult<()>) -> String {
let mut s = rust_printer(box MemWriter::new());
f(&mut s).unwrap();
}
}
+#[cfg(stage0)]
pub fn ty_to_str(ty: &ast::Ty) -> String {
to_str(|s| s.print_type(ty))
}
+#[cfg(stage0)]
pub fn pat_to_str(pat: &ast::Pat) -> String {
to_str(|s| s.print_pat(pat))
}
+#[cfg(stage0)]
pub fn expr_to_str(e: &ast::Expr) -> String {
to_str(|s| s.print_expr(e))
}
+#[cfg(stage0)]
pub fn lifetime_to_str(e: &ast::Lifetime) -> String {
to_str(|s| s.print_lifetime(e))
}
+#[cfg(stage0)]
pub fn tt_to_str(tt: &ast::TokenTree) -> String {
to_str(|s| s.print_tt(tt))
}
+#[cfg(stage0)]
pub fn tts_to_str(tts: &[ast::TokenTree]) -> String {
to_str(|s| s.print_tts(tts))
}
+#[cfg(stage0)]
pub fn stmt_to_str(stmt: &ast::Stmt) -> String {
to_str(|s| s.print_stmt(stmt))
}
+#[cfg(stage0)]
pub fn item_to_str(i: &ast::Item) -> String {
to_str(|s| s.print_item(i))
}
+#[cfg(stage0)]
pub fn generics_to_str(generics: &ast::Generics) -> String {
to_str(|s| s.print_generics(generics))
}
+#[cfg(stage0)]
pub fn ty_method_to_str(p: &ast::TypeMethod) -> String {
to_str(|s| s.print_ty_method(p))
}
+#[cfg(stage0)]
pub fn method_to_str(p: &ast::Method) -> String {
to_str(|s| s.print_method(p))
}
+#[cfg(stage0)]
pub fn fn_block_to_str(p: &ast::FnDecl) -> String {
to_str(|s| s.print_fn_block_args(p))
}
+#[cfg(stage0)]
pub fn path_to_str(p: &ast::Path) -> String {
to_str(|s| s.print_path(p, false))
}
-pub fn ident_to_str(id: &ast::Ident) -> String {
- to_str(|s| s.print_ident(*id))
-}
-
+#[cfg(stage0)]
pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
opt_explicit_self: Option<ast::ExplicitSelf_>,
generics: &ast::Generics) -> String {
})
}
+#[cfg(stage0)]
pub fn block_to_str(blk: &ast::Block) -> String {
to_str(|s| {
// containing cbox, will be closed by print-block at }
})
}
+#[cfg(stage0)]
pub fn meta_item_to_str(mi: &ast::MetaItem) -> String {
to_str(|s| s.print_meta_item(mi))
}
+#[cfg(stage0)]
pub fn attribute_to_str(attr: &ast::Attribute) -> String {
to_str(|s| s.print_attribute(attr))
}
+#[cfg(stage0)]
pub fn lit_to_str(l: &ast::Lit) -> String {
to_str(|s| s.print_literal(l))
}
+#[cfg(stage0)]
pub fn explicit_self_to_str(explicit_self: ast::ExplicitSelf_) -> String {
to_str(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
}
+#[cfg(stage0)]
pub fn variant_to_str(var: &ast::Variant) -> String {
to_str(|s| s.print_variant(var))
}
+#[cfg(stage0)]
pub fn arg_to_str(arg: &ast::Arg) -> String {
to_str(|s| s.print_arg(arg))
}
+
+
+
pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
match vis {
ast::Public => format!("pub {}", s),
}
ast::ItemForeignMod(ref nmod) => {
try!(self.head("extern"));
- try!(self.word_nbsp(nmod.abi.to_str().as_slice()));
+ try!(self.word_nbsp(nmod.abi.to_string().as_slice()));
try!(self.bopen());
try!(self.print_foreign_mod(nmod, item.attrs.as_slice()));
try!(self.bclose(item.span));
}
try!(self.bclose(item.span));
}
- ast::ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
+ ast::ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
try!(self.head(visibility_qualified(item.vis,
"trait").as_slice()));
try!(self.print_ident(item.ident));
try!(self.print_generics(generics));
- if *sized == ast::DynSize {
- try!(space(&mut self.s));
- try!(word(&mut self.s, "for type"));
+ match unbound {
+ &Some(TraitTyParamBound(ref tref)) => {
+ try!(space(&mut self.s));
+ try!(self.word_space("for"));
+ try!(self.print_trait_ref(tref));
+ try!(word(&mut self.s, "?"));
+ }
+ _ => {}
}
if traits.len() != 0u {
try!(word(&mut self.s, ":"));
match *tt {
ast::TTDelim(ref tts) => self.print_tts(tts.as_slice()),
ast::TTTok(_, ref tk) => {
- try!(word(&mut self.s, parse::token::to_str(tk).as_slice()));
+ try!(word(&mut self.s, parse::token::to_string(tk).as_slice()));
match *tk {
parse::token::DOC_COMMENT(..) => {
hardbreak(&mut self.s)
match *sep {
Some(ref tk) => {
try!(word(&mut self.s,
- parse::token::to_str(tk).as_slice()));
+ parse::token::to_string(tk).as_slice()));
}
None => ()
}
ast::ExprBinary(op, ref lhs, ref rhs) => {
try!(self.print_expr(&**lhs));
try!(space(&mut self.s));
- try!(self.word_space(ast_util::binop_to_str(op)));
+ try!(self.word_space(ast_util::binop_to_string(op)));
try!(self.print_expr(&**rhs));
}
ast::ExprUnary(op, ref expr) => {
- try!(word(&mut self.s, ast_util::unop_to_str(op)));
+ try!(word(&mut self.s, ast_util::unop_to_string(op)));
try!(self.print_expr_maybe_paren(&**expr));
}
ast::ExprAddrOf(m, ref expr) => {
ast::ExprAssignOp(op, ref lhs, ref rhs) => {
try!(self.print_expr(&**lhs));
try!(space(&mut self.s));
- try!(word(&mut self.s, ast_util::binop_to_str(op)));
+ try!(word(&mut self.s, ast_util::binop_to_string(op)));
try!(self.word_space("="));
try!(self.print_expr(&**rhs));
}
}
ast::PatStruct(ref path, ref fields, etc) => {
try!(self.print_path(path, true));
- try!(word(&mut self.s, "{"));
+ try!(self.nbsp());
+ try!(self.word_space("{"));
try!(self.commasep_cmnt(
Consistent, fields.as_slice(),
|s, f| {
try!(s.cbox(indent_unit));
try!(s.print_ident(f.ident));
- try!(s.word_space(":"));
+ try!(s.word_nbsp(":"));
try!(s.print_pat(&*f.pat));
s.end()
},
if fields.len() != 0u { try!(self.word_space(",")); }
try!(word(&mut self.s, ".."));
}
+ try!(space(&mut self.s));
try!(word(&mut self.s, "}"));
}
ast::PatTup(ref elts) => {
} else {
let idx = idx - generics.lifetimes.len();
let param = generics.ty_params.get(idx);
- if param.sized == ast::DynSize {
- try!(s.word_space("type"));
+ match param.unbound {
+ Some(TraitTyParamBound(ref tref)) => {
+ try!(s.print_trait_ref(tref));
+ try!(s.word_space("?"));
+ }
+ _ => {}
}
try!(s.print_ident(param.ident));
try!(s.print_bounds(&None,
}
ast::LitInt(i, t) => {
word(&mut self.s,
- ast_util::int_ty_to_str(t, Some(i)).as_slice())
+ ast_util::int_ty_to_string(t, Some(i)).as_slice())
}
ast::LitUint(u, t) => {
word(&mut self.s,
- ast_util::uint_ty_to_str(t, Some(u)).as_slice())
+ ast_util::uint_ty_to_string(t, Some(u)).as_slice())
}
ast::LitIntUnsuffixed(i) => {
word(&mut self.s, format!("{}", i).as_slice())
format!(
"{}{}",
f.get(),
- ast_util::float_ty_to_str(t).as_slice()).as_slice())
+ ast_util::float_ty_to_string(t).as_slice()).as_slice())
}
ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()),
ast::LitNil => word(&mut self.s, "()"),
Some(abi::Rust) => Ok(()),
Some(abi) => {
try!(self.word_nbsp("extern"));
- self.word_nbsp(abi.to_str().as_slice())
+ self.word_nbsp(abi.to_string().as_slice())
}
None => Ok(())
}
match opt_abi {
Some(abi) => {
try!(self.word_nbsp("extern"));
- self.word_nbsp(abi.to_str().as_slice())
+ self.word_nbsp(abi.to_string().as_slice())
}
None => Ok(())
}
if abi != abi::Rust {
try!(self.word_nbsp("extern"));
- try!(self.word_nbsp(abi.to_str().as_slice()));
+ try!(self.word_nbsp(abi.to_string().as_slice()));
}
word(&mut self.s, "fn")
use parse::token;
#[test]
- fn test_fun_to_str() {
+ fn test_fun_to_string() {
let abba_ident = token::str_to_ident("abba");
let decl = ast::FnDecl {
variadic: false
};
let generics = ast_util::empty_generics();
- assert_eq!(&fun_to_str(&decl, ast::NormalFn, abba_ident,
+ assert_eq!(&fun_to_string(&decl, ast::NormalFn, abba_ident,
None, &generics),
&"fn abba()".to_string());
}
#[test]
- fn test_variant_to_str() {
+ fn test_variant_to_string() {
let ident = token::str_to_ident("principal_skinner");
let var = codemap::respan(codemap::DUMMY_SP, ast::Variant_ {
vis: ast::Public,
});
- let varstr = variant_to_str(&var);
+ let varstr = variant_to_string(&var);
assert_eq!(&varstr,&"pub principal_skinner".to_string());
}
}
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
-#![crate_id = "term#0.11.0"]
+#![crate_id = "term#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "term"]
#![experimental]
#![comment = "Simple ANSI color library"]
#![license = "MIT/ASL2"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(macro_rules, phase)]
// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
-pub static boolfnames: &'static[&'static str] = &'static["auto_left_margin", "auto_right_margin",
+pub static boolfnames: &'static[&'static str] = &["auto_left_margin", "auto_right_margin",
"no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type",
"hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above",
"memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok",
"no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs",
"return_does_clr_eol"];
-pub static boolnames: &'static[&'static str] = &'static["bw", "am", "xsb", "xhp", "xenl", "eo",
+pub static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo",
"gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon",
"nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy",
"xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"];
-pub static numfnames: &'static[&'static str] = &'static[ "columns", "init_tabs", "lines",
+pub static numfnames: &'static[&'static str] = &[ "columns", "init_tabs", "lines",
"lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal",
"width_status_line", "num_labels", "label_height", "label_width", "max_attributes",
"maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity",
"bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay",
"new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"];
-pub static numnames: &'static[&'static str] = &'static[ "cols", "it", "lines", "lm", "xmc", "pb",
+pub static numnames: &'static[&'static str] = &[ "cols", "it", "lines", "lm", "xmc", "pb",
"vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv",
"spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs",
"btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"];
-pub static stringfnames: &'static[&'static str] = &'static[ "back_tab", "bell", "carriage_return",
+pub static stringfnames: &'static[&'static str] = &[ "back_tab", "bell", "carriage_return",
"change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos",
"column_address", "command_character", "cursor_address", "cursor_down", "cursor_home",
"cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right",
"acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline",
"acs_plus", "memory_lock", "memory_unlock", "box_chars_1"];
-pub static stringnames: &'static[&'static str] = &'static[ "cbt", "_", "cr", "csr", "tbc", "clear",
+pub static stringnames: &'static[&'static str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear",
"_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1",
"ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc",
"dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc",
// running tests while providing a base that other test frameworks may
// build off of.
-#![crate_id = "test#0.11.0"]
+#![crate_id = "test#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "test"] // NOTE: remove after stage0
#![experimental]
#![comment = "Rust internal test library only used by rustc"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(asm, macro_rules, phase)]
let matches =
match getopts::getopts(args_.as_slice(), optgroups().as_slice()) {
Ok(m) => m,
- Err(f) => return Some(Err(f.to_str()))
+ Err(f) => return Some(Err(f.to_string()))
};
if matches.opt_present("h") { usage(args[0].as_slice()); return None; }
let mut failures = Vec::new();
let mut fail_out = String::new();
for &(ref f, ref stdout) in self.failures.iter() {
- failures.push(f.name.to_str());
+ failures.push(f.name.to_string());
if stdout.len() > 0 {
fail_out.push_str(format!("---- {} stdout ----\n\t",
f.name.as_slice()).as_slice());
let filtered = filter_tests(&opts, tests);
assert_eq!(filtered.len(), 1);
- assert_eq!(filtered.get(0).desc.name.to_str(),
+ assert_eq!(filtered.get(0).desc.name.to_string(),
"1".to_string());
assert!(filtered.get(0).desc.ignore == false);
}
"test::sort_tests".to_string());
for (a, b) in expected.iter().zip(filtered.iter()) {
- assert!(*a == b.desc.name.to_str());
+ assert!(*a == b.desc.name.to_string());
}
}
let range = hi - lo;
- let lostr = lo.to_str();
- let histr = hi.to_str();
+ let lostr = lo.to_string();
+ let histr = hi.to_string();
let overhead_width = lostr.len() + histr.len() + 4;
let range_width = width_hint - overhead_width;
//! Simple time handling.
-#![crate_id = "time#0.11.0"]
+#![crate_id = "time#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "time"]
#![experimental]
#![crate_type = "rlib"]
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(phase)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate debug;
#[cfg(test)] #[phase(plugin, link)] extern crate log;
'U' => format!("{:02d}", (tm.tm_yday - tm.tm_wday + 7) / 7),
'u' => {
let i = tm.tm_wday as int;
- (if i == 0 { 7 } else { i }).to_str()
+ (if i == 0 { 7 } else { i }).to_string()
}
'V' => iso_week('V', tm),
'v' => {
format!("{:02d}",
(tm.tm_yday - (tm.tm_wday - 1 + 7) % 7 + 7) / 7)
}
- 'w' => (tm.tm_wday as int).to_str(),
- 'Y' => (tm.tm_year as int + 1900).to_str(),
+ 'w' => (tm.tm_wday as int).to_string(),
+ 'Y' => (tm.tm_year as int + 1900).to_string(),
'y' => format!("{:02d}", (tm.tm_year as int + 1900) % 100),
'Z' => "".to_string(), // FIXME(pcwalton): Implement this.
'z' => {
//! Types/fns concerning URLs (see RFC 3986)
-#![crate_id = "url#0.11.0"]
+#![crate_id = "url#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "url"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(default_type_params)]
+#![allow(unused_attribute)] // NOTE: remove after stage0
use std::collections::HashMap;
use std::fmt;
use std::from_str::FromStr;
use std::hash;
-use std::io::BufReader;
-use std::string::String;
use std::uint;
+use std::path::BytesContainer;
/// A Uniform Resource Locator (URL). A URL is a form of URI (Uniform Resource
/// Identifier) that includes network location information, such as hostname or
/// # Example
///
/// ```rust
-/// use url::{Url, UserInfo};
+/// use url::Url;
///
-/// let url = Url { scheme: "https".to_string(),
-/// user: Some(UserInfo { user: "username".to_string(), pass: None }),
-/// host: "example.com".to_string(),
-/// port: Some("8080".to_string()),
-/// path: "/foo/bar".to_string(),
-/// query: vec!(("baz".to_string(), "qux".to_string())),
-/// fragment: Some("quz".to_string()) };
-/// // https://username@example.com:8080/foo/bar?baz=qux#quz
+/// let raw = "https://username@example.com:8080/foo/bar?baz=qux#quz";
+/// match Url::parse(raw) {
+/// Ok(u) => println!("Parsed '{}'", u),
+/// Err(e) => println!("Couldn't parse '{}': {}", raw, e),
+/// }
/// ```
#[deriving(Clone, PartialEq, Eq)]
pub struct Url {
/// A domain name or IP address. For example, `example.com`.
pub host: String,
/// A TCP port number, for example `8080`.
- pub port: Option<String>,
- /// The path component of a URL, for example `/foo/bar`.
- pub path: String,
- /// The query component of a URL.
- /// `vec!(("baz".to_string(), "qux".to_string()))` represents the fragment
- /// `baz=qux` in the above example.
- pub query: Query,
- /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
- pub fragment: Option<String>
+ pub port: Option<u16>,
+ /// The path component of a URL, for example `/foo/bar?baz=qux#quz`.
+ pub path: Path,
}
-#[deriving(Clone, PartialEq)]
+#[deriving(Clone, PartialEq, Eq)]
pub struct Path {
/// The path component of a URL, for example `/foo/bar`.
pub path: String,
/// The query component of a URL.
- /// `vec!(("baz".to_string(), "qux".to_string()))` represents the fragment
+ /// `vec![("baz".to_string(), "qux".to_string())]` represents the fragment
/// `baz=qux` in the above example.
pub query: Query,
- /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
+ /// The fragment component, such as `quz`. Not including the leading `#` character.
pub fragment: Option<String>
}
pub fn new(scheme: String,
user: Option<UserInfo>,
host: String,
- port: Option<String>,
+ port: Option<u16>,
path: String,
query: Query,
fragment: Option<String>)
user: user,
host: host,
port: port,
- path: path,
- query: query,
- fragment: fragment,
+ path: Path::new(path, query, fragment)
}
}
+
+ /// Parses a URL, converting it from a string to a `Url` representation.
+ ///
+ /// # Arguments
+ /// * rawurl - a string representing the full URL, including scheme.
+ ///
+ /// # Return value
+ ///
+ /// `Err(e)` if the string did not represent a valid URL, where `e` is a
+ /// `String` error message. Otherwise, `Ok(u)` where `u` is a `Url` struct
+ /// representing the URL.
+ pub fn parse(rawurl: &str) -> DecodeResult<Url> {
+ // scheme
+ let (scheme, rest) = try!(get_scheme(rawurl));
+
+ // authority
+ let (userinfo, host, port, rest) = try!(get_authority(rest));
+
+ // path
+ let has_authority = host.len() > 0;
+ let (path, rest) = try!(get_path(rest, has_authority));
+
+ // query and fragment
+ let (query, fragment) = try!(get_query_fragment(rest));
+
+ let url = Url::new(scheme.to_string(),
+ userinfo,
+ host.to_string(),
+ port,
+ path,
+ query,
+ fragment);
+ Ok(url)
+ }
+}
+
+#[deprecated="use `Url::parse`"]
+pub fn from_str(s: &str) -> Result<Url, String> {
+ Url::parse(s)
}
impl Path {
fragment: fragment,
}
}
+
+ /// Parses a URL path, converting it from a string to a `Path` representation.
+ ///
+ /// # Arguments
+ /// * rawpath - a string representing the path component of a URL.
+ ///
+ /// # Return value
+ ///
+ /// `Err(e)` if the string did not represent a valid URL path, where `e` is a
+ /// `String` error message. Otherwise, `Ok(p)` where `p` is a `Path` struct
+ /// representing the URL path.
+ pub fn parse(rawpath: &str) -> DecodeResult<Path> {
+ let (path, rest) = try!(get_path(rawpath, false));
+
+ // query and fragment
+ let (query, fragment) = try!(get_query_fragment(rest.as_slice()));
+
+ Ok(Path{ path: path, query: query, fragment: fragment })
+ }
+}
+
+#[deprecated="use `Path::parse`"]
+pub fn path_from_str(s: &str) -> Result<Path, String> {
+ Path::parse(s)
}
impl UserInfo {
}
}
-fn encode_inner(s: &str, full_url: bool) -> String {
- let mut rdr = BufReader::new(s.as_bytes());
- let mut out = String::new();
-
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Err(..) => break,
- Ok(..) => buf[0] as char,
+fn encode_inner<T: BytesContainer>(c: T, full_url: bool) -> String {
+ c.container_as_bytes().iter().fold(String::new(), |mut out, &b| {
+ match b as char {
+ // unreserved:
+ 'A' .. 'Z'
+ | 'a' .. 'z'
+ | '0' .. '9'
+ | '-' | '.' | '_' | '~' => out.push_char(b as char),
+
+ // gen-delims:
+ ':' | '/' | '?' | '#' | '[' | ']' | '@' |
+ // sub-delims:
+ '!' | '$' | '&' | '"' | '(' | ')' | '*' |
+ '+' | ',' | ';' | '='
+ if full_url => out.push_char(b as char),
+
+ ch => out.push_str(format!("%{:02X}", ch as uint).as_slice()),
};
- match ch {
- // unreserved:
- 'A' .. 'Z' |
- 'a' .. 'z' |
- '0' .. '9' |
- '-' | '.' | '_' | '~' => {
- out.push_char(ch);
- }
- _ => {
- if full_url {
- match ch {
- // gen-delims:
- ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
- // sub-delims:
- '!' | '$' | '&' | '"' | '(' | ')' | '*' |
- '+' | ',' | ';' | '=' => {
- out.push_char(ch);
- }
-
- _ => out.push_str(format!("%{:02X}", ch as uint).as_slice())
- }
- } else {
- out.push_str(format!("%{:02X}", ch as uint).as_slice());
- }
- }
- }
- }
-
- out
+ out
+ })
}
-/**
- * Encodes a URI by replacing reserved characters with percent-encoded
- * character sequences.
- *
- * This function is compliant with RFC 3986.
- *
- * # Example
- *
- * ```rust
- * use url::encode;
- *
- * let url = encode("https://example.com/Rust (programming language)");
- * println!("{}", url); // https://example.com/Rust%20(programming%20language)
- * ```
- */
-pub fn encode(s: &str) -> String {
- encode_inner(s, true)
+/// Encodes a URI by replacing reserved characters with percent-encoded
+/// character sequences.
+///
+/// This function is compliant with RFC 3986.
+///
+/// # Example
+///
+/// ```rust
+/// use url::encode;
+///
+/// let url = encode("https://example.com/Rust (programming language)");
+/// println!("{}", url); // https://example.com/Rust%20(programming%20language)
+/// ```
+pub fn encode<T: BytesContainer>(container: T) -> String {
+ encode_inner(container, true)
}
-/**
- * Encodes a URI component by replacing reserved characters with percent-
- * encoded character sequences.
- *
- * This function is compliant with RFC 3986.
- */
-pub fn encode_component(s: &str) -> String {
- encode_inner(s, false)
+/// Encodes a URI component by replacing reserved characters with percent-
+/// encoded character sequences.
+///
+/// This function is compliant with RFC 3986.
+pub fn encode_component<T: BytesContainer>(container: T) -> String {
+ encode_inner(container, false)
}
-fn decode_inner(s: &str, full_url: bool) -> String {
- let mut rdr = BufReader::new(s.as_bytes());
- let mut out = String::new();
+pub type DecodeResult<T> = Result<T, String>;
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Err(..) => break,
- Ok(..) => buf[0] as char
- };
- match ch {
- '%' => {
- let mut bytes = [0, 0];
- match rdr.read(bytes) {
- Ok(2) => {}
- _ => fail!() // FIXME: malformed url?
- }
- let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
-
- if full_url {
- // Only decode some characters:
- match ch {
- // gen-delims:
- ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
- // sub-delims:
- '!' | '$' | '&' | '"' | '(' | ')' | '*' |
- '+' | ',' | ';' | '=' => {
- out.push_char('%');
- out.push_char(bytes[0u] as char);
- out.push_char(bytes[1u] as char);
- }
-
- ch => out.push_char(ch)
- }
- } else {
- out.push_char(ch);
- }
- }
- ch => out.push_char(ch)
- }
- }
-
- out
-}
-
-/**
- * Decodes a percent-encoded string representing a URI.
- *
- * This will only decode escape sequences generated by `encode`.
- *
- * # Example
- *
- * ```rust
- * use url::decode;
- *
- * let url = decode("https://example.com/Rust%20(programming%20language)");
- * println!("{}", url); // https://example.com/Rust (programming language)
- * ```
- */
-pub fn decode(s: &str) -> String {
- decode_inner(s, true)
+/// Decodes a percent-encoded string representing a URI.
+///
+/// This will only decode escape sequences generated by `encode`.
+///
+/// # Example
+///
+/// ```rust
+/// use url::decode;
+///
+/// let url = decode("https://example.com/Rust%20(programming%20language)");
+/// println!("{}", url); // https://example.com/Rust (programming language)
+/// ```
+pub fn decode<T: BytesContainer>(container: T) -> DecodeResult<String> {
+ decode_inner(container, true)
}
-/**
- * Decode a string encoded with percent encoding.
- */
-pub fn decode_component(s: &str) -> String {
- decode_inner(s, false)
+/// Decode a string encoded with percent encoding.
+pub fn decode_component<T: BytesContainer>(container: T) -> DecodeResult<String> {
+ decode_inner(container, false)
}
-fn encode_plus(s: &str) -> String {
- let mut rdr = BufReader::new(s.as_bytes());
+fn decode_inner<T: BytesContainer>(c: T, full_url: bool) -> DecodeResult<String> {
let mut out = String::new();
+ let mut iter = c.container_as_bytes().iter().map(|&b| b);
loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- match ch {
- 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
- out.push_char(ch);
- }
- ' ' => out.push_char('+'),
- _ => out.push_str(format!("%{:X}", ch as uint).as_slice())
+ match iter.next() {
+ Some(b) => match b as char {
+ '%' => {
+ let bytes = match (iter.next(), iter.next()) {
+ (Some(one), Some(two)) => [one as u8, two as u8],
+ _ => return Err(format!("Malformed input: found '%' \
+ without two trailing bytes")),
+ };
+
+ // Only decode some characters if full_url:
+ match uint::parse_bytes(bytes, 16u).unwrap() as u8 as char {
+ // gen-delims:
+ ':' | '/' | '?' | '#' | '[' | ']' | '@' |
+
+ // sub-delims:
+ '!' | '$' | '&' | '"' | '(' | ')' | '*' |
+ '+' | ',' | ';' | '='
+ if full_url => {
+ out.push_char('%');
+ out.push_char(bytes[0u] as char);
+ out.push_char(bytes[1u] as char);
+ }
+
+ ch => out.push_char(ch)
+ }
+ }
+ ch => out.push_char(ch)
+ },
+ None => return Ok(out),
}
}
-
- out
}
-/**
- * Encode a hashmap to the 'application/x-www-form-urlencoded' media type.
- */
+/// Encode a hashmap to the 'application/x-www-form-urlencoded' media type.
pub fn encode_form_urlencoded(m: &HashMap<String, Vec<String>>) -> String {
- let mut out = String::new();
- let mut first = true;
+ fn encode_plus<T: Str>(s: &T) -> String {
+ s.as_slice().bytes().fold(String::new(), |mut out, b| {
+ match b as char {
+ 'A' .. 'Z'
+ | 'a' .. 'z'
+ | '0' .. '9'
+ | '_' | '.' | '-' => out.push_char(b as char),
+ ' ' => out.push_char('+'),
+ ch => out.push_str(format!("%{:X}", ch as uint).as_slice())
+ }
+
+ out
+ })
+ }
- for (key, values) in m.iter() {
- let key = encode_plus(key.as_slice());
+ let mut first = true;
+ m.iter().fold(String::new(), |mut out, (key, values)| {
+ let key = encode_plus(key);
for value in values.iter() {
if first {
first = false;
} else {
out.push_char('&');
- first = false;
}
- out.push_str(format!("{}={}",
- key,
- encode_plus(value.as_slice())).as_slice());
+ out.push_str(key.as_slice());
+ out.push_char('=');
+ out.push_str(encode_plus(value).as_slice());
}
- }
- out
+ out
+ })
}
-/**
- * Decode a string encoded with the 'application/x-www-form-urlencoded' media
- * type into a hashmap.
- */
-#[allow(experimental)]
-pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<String, Vec<String>> {
- let mut rdr = BufReader::new(s);
- let mut m: HashMap<String,Vec<String>> = HashMap::new();
+/// Decode a string encoded with the 'application/x-www-form-urlencoded' media
+/// type into a hashmap.
+pub fn decode_form_urlencoded(s: &[u8])
+ -> DecodeResult<HashMap<String, Vec<String>>> {
+ fn maybe_push_value(map: &mut HashMap<String, Vec<String>>,
+ key: String,
+ value: String) {
+ if key.len() > 0 && value.len() > 0 {
+ let values = map.find_or_insert_with(key, |_| vec!());
+ values.push(value);
+ }
+ }
+
+ let mut out = HashMap::new();
+ let mut iter = s.iter().map(|&x| x);
+
let mut key = String::new();
let mut value = String::new();
let mut parsing_key = true;
loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- match ch {
- '&' | ';' => {
- if key.len() > 0 && value.len() > 0 {
- let mut values = match m.pop_equiv(&key.as_slice()) {
- Some(values) => values,
- None => vec!(),
- };
-
- values.push(value);
- m.insert(key, values);
+ match iter.next() {
+ Some(b) => match b as char {
+ '&' | ';' => {
+ maybe_push_value(&mut out, key, value);
+
+ parsing_key = true;
+ key = String::new();
+ value = String::new();
}
-
- parsing_key = true;
- key = String::new();
- value = String::new();
- }
- '=' => parsing_key = false,
- ch => {
- let ch = match ch {
- '%' => {
- let mut bytes = [0, 0];
- match rdr.read(bytes) {
- Ok(2) => {}
- _ => fail!() // FIXME: malformed?
+ '=' => parsing_key = false,
+ ch => {
+ let ch = match ch {
+ '%' => {
+ let bytes = match (iter.next(), iter.next()) {
+ (Some(one), Some(two)) => [one as u8, two as u8],
+ _ => return Err(format!("Malformed input: found \
+ '%' without two trailing bytes"))
+ };
+
+ uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
}
- uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
- }
- '+' => ' ',
- ch => ch
- };
+ '+' => ' ',
+ ch => ch
+ };
- if parsing_key {
- key.push_char(ch)
- } else {
- value.push_char(ch)
+ if parsing_key {
+ key.push_char(ch)
+ } else {
+ value.push_char(ch)
+ }
}
+ },
+ None => {
+ maybe_push_value(&mut out, key, value);
+ return Ok(out)
}
}
}
-
- if key.len() > 0 && value.len() > 0 {
- let mut values = match m.pop_equiv(&key.as_slice()) {
- Some(values) => values,
- None => vec!(),
- };
-
- values.push(value);
- m.insert(key, values);
- }
-
- m
}
+fn split_char_first<'a>(s: &'a str, c: char) -> (&'a str, &'a str) {
+ let mut iter = s.splitn(c, 1);
-fn split_char_first(s: &str, c: char) -> (String, String) {
- let len = s.len();
- let mut index = len;
- let mut mat = 0;
- let mut rdr = BufReader::new(s.as_bytes());
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- if ch == c {
- // found a match, adjust markers
- index = (rdr.tell().unwrap() as uint) - 1;
- mat = 1;
- break;
- }
- }
- if index+mat == len {
- return (s.slice(0, index).to_string(), "".to_string());
- } else {
- return (s.slice(0, index).to_string(),
- s.slice(index + mat, s.len()).to_string());
+ match (iter.next(), iter.next()) {
+ (Some(a), Some(b)) => (a, b),
+ (Some(a), None) => (a, ""),
+ (None, _) => unreachable!(),
}
}
}
}
-fn query_from_str(rawquery: &str) -> Query {
+fn query_from_str(rawquery: &str) -> DecodeResult<Query> {
let mut query: Query = vec!();
if !rawquery.is_empty() {
for p in rawquery.split('&') {
let (k, v) = split_char_first(p, '=');
- query.push((decode_component(k.as_slice()),
- decode_component(v.as_slice())));
- };
+ query.push((try!(decode_component(k)),
+ try!(decode_component(v))));
+ }
}
- return query;
+
+ Ok(query)
}
-/**
- * Converts an instance of a URI `Query` type to a string.
- *
- * # Example
- *
- * ```rust
- * let query = vec!(("title".to_string(), "The Village".to_string()),
- * ("north".to_string(), "52.91".to_string()),
- * ("west".to_string(), "4.10".to_string()));
- * println!("{}", url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
- * ```
- */
-#[allow(unused_must_use)]
+/// Converts an instance of a URI `Query` type to a string.
+///
+/// # Example
+///
+/// ```rust
+/// let query = vec![("title".to_string(), "The Village".to_string()),
+/// ("north".to_string(), "52.91".to_string()),
+/// ("west".to_string(), "4.10".to_string())];
+/// println!("{}", url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
+/// ```
pub fn query_to_str(query: &Query) -> String {
- use std::io::MemWriter;
- use std::str;
-
- let mut writer = MemWriter::new();
- for (i, &(ref k, ref v)) in query.iter().enumerate() {
- if i != 0 { write!(&mut writer, "&"); }
- write!(&mut writer, "{}={}", encode_component(k.as_slice()),
- encode_component(v.as_slice()));
- }
- str::from_utf8_lossy(writer.unwrap().as_slice()).to_string()
+ query.iter().enumerate().fold(String::new(), |mut out, (i, &(ref k, ref v))| {
+ if i != 0 {
+ out.push_char('&');
+ }
+
+ out.push_str(encode_component(k.as_slice()).as_slice());
+ out.push_char('=');
+ out.push_str(encode_component(v.as_slice()).as_slice());
+ out
+ })
}
-/**
- * Returns a tuple of the URI scheme and the rest of the URI, or a parsing error.
- *
- * Does not include the separating `:` character.
- *
- * # Example
- *
- * ```rust
- * use url::get_scheme;
- *
- * let scheme = match get_scheme("https://example.com/") {
- * Ok((sch, _)) => sch,
- * Err(_) => "(None)".to_string(),
- * };
- * println!("Scheme in use: {}.", scheme); // Scheme in use: https.
- * ```
- */
-pub fn get_scheme(rawurl: &str) -> Result<(String, String), String> {
+/// Returns a tuple of the URI scheme and the rest of the URI, or a parsing error.
+///
+/// Does not include the separating `:` character.
+///
+/// # Example
+///
+/// ```rust
+/// use url::get_scheme;
+///
+/// let scheme = match get_scheme("https://example.com/") {
+/// Ok((sch, _)) => sch,
+/// Err(_) => "(None)",
+/// };
+/// println!("Scheme in use: {}.", scheme); // Scheme in use: https.
+/// ```
+pub fn get_scheme<'a>(rawurl: &'a str) -> DecodeResult<(&'a str, &'a str)> {
for (i,c) in rawurl.chars().enumerate() {
- match c {
- 'A' .. 'Z' | 'a' .. 'z' => continue,
- '0' .. '9' | '+' | '-' | '.' => {
- if i == 0 {
- return Err("url: Scheme must begin with a \
- letter.".to_string());
+ let result = match c {
+ 'A' .. 'Z'
+ | 'a' .. 'z' => continue,
+ '0' .. '9' | '+' | '-' | '.' => {
+ if i != 0 { continue }
+
+ Err("url: Scheme must begin with a letter.".to_string())
}
- continue;
- }
- ':' => {
- if i == 0 {
- return Err("url: Scheme cannot be empty.".to_string());
- } else {
- return Ok((rawurl.slice(0,i).to_string(),
- rawurl.slice(i+1,rawurl.len()).to_string()));
+ ':' => {
+ if i == 0 {
+ Err("url: Scheme cannot be empty.".to_string())
+ } else {
+ Ok((rawurl.slice(0,i), rawurl.slice(i+1,rawurl.len())))
+ }
}
- }
- _ => {
- return Err("url: Invalid character in scheme.".to_string());
- }
- }
- };
- return Err("url: Scheme must be terminated with a colon.".to_string());
-}
+ _ => Err("url: Invalid character in scheme.".to_string()),
+ };
-#[deriving(Clone, PartialEq)]
-enum Input {
- Digit, // all digits
- Hex, // digits and letters a-f
- Unreserved // all other legal characters
+ return result;
+ }
+
+ Err("url: Scheme must be terminated with a colon.".to_string())
}
// returns userinfo, host, port, and unparsed part, or an error
-fn get_authority(rawurl: &str) ->
- Result<(Option<UserInfo>, String, Option<String>, String), String> {
- if !rawurl.starts_with("//") {
- // there is no authority.
- return Ok((None, "".to_string(), None, rawurl.to_str()));
- }
-
+fn get_authority<'a>(rawurl: &'a str) ->
+ DecodeResult<(Option<UserInfo>, &'a str, Option<u16>, &'a str)> {
enum State {
Start, // starting state
PassHostPort, // could be in user or port
InPort // are in port
}
+ #[deriving(Clone, PartialEq)]
+ enum Input {
+ Digit, // all digits
+ Hex, // digits and letters a-f
+ Unreserved // all other legal characters
+ }
+
+ if !rawurl.starts_with("//") {
+ // there is no authority.
+ return Ok((None, "", None, rawurl));
+ }
+
let len = rawurl.len();
let mut st = Start;
let mut input = Digit; // most restricted, start here.
let mut userinfo = None;
- let mut host = "".to_string();
+ let mut host = "";
let mut port = None;
let mut colon_count = 0u;
let mut begin = 2;
let mut end = len;
- for (i,c) in rawurl.chars().enumerate() {
- if i < 2 { continue; } // ignore the leading //
-
+ for (i,c) in rawurl.chars().enumerate()
+ // ignore the leading '//' handled by early return
+ .skip(2) {
// deal with input class first
match c {
- '0' .. '9' => (),
- 'A' .. 'F' | 'a' .. 'f' => {
- if input == Digit {
- input = Hex;
+ '0' .. '9' => (),
+ 'A' .. 'F'
+ | 'a' .. 'f' => {
+ if input == Digit {
+ input = Hex;
+ }
}
- }
- 'G' .. 'Z' | 'g' .. 'z' | '-' | '.' | '_' | '~' | '%' |
- '&' |'\'' | '(' | ')' | '+' | '!' | '*' | ',' | ';' | '=' => {
- input = Unreserved;
- }
- ':' | '@' | '?' | '#' | '/' => {
- // separators, don't change anything
- }
- _ => {
- return Err("Illegal character in authority".to_string());
- }
+ 'G' .. 'Z'
+ | 'g' .. 'z'
+ | '-' | '.' | '_' | '~' | '%'
+ | '&' |'\'' | '(' | ')' | '+'
+ | '!' | '*' | ',' | ';' | '=' => input = Unreserved,
+ ':' | '@' | '?' | '#' | '/' => {
+ // separators, don't change anything
+ }
+ _ => return Err("Illegal character in authority".to_string()),
}
// now process states
pos = i;
if input == Unreserved {
// must be port
- host = rawurl.slice(begin, i).to_string();
+ host = rawurl.slice(begin, i);
st = InPort;
} else {
// can't be sure whether this is an ipv6 address or a port
}
Ip6Port => {
if input == Unreserved {
- return Err("Illegal characters in \
- authority.".to_string());
+ return Err("Illegal characters in authority.".to_string());
}
st = Ip6Host;
}
Ip6Host => {
if colon_count > 7 {
- host = rawurl.slice(begin, i).to_string();
+ host = rawurl.slice(begin, i);
pos = i;
st = InPort;
}
}
- _ => {
- return Err("Invalid ':' in authority.".to_string());
- }
+ _ => return Err("Invalid ':' in authority.".to_string()),
}
input = Digit; // reset input class
}
userinfo = Some(UserInfo::new(user, Some(pass)));
st = InHost;
}
- _ => {
- return Err("Invalid '@' in authority.".to_string());
- }
+ _ => return Err("Invalid '@' in authority.".to_string()),
}
begin = i+1;
}
// finish up
match st {
- Start => {
- host = rawurl.slice(begin, end).to_string();
- }
- PassHostPort | Ip6Port => {
+ Start => host = rawurl.slice(begin, end),
+ PassHostPort
+ | Ip6Port => {
if input != Digit {
return Err("Non-digit characters in port.".to_string());
}
- host = rawurl.slice(begin, pos).to_string();
- port = Some(rawurl.slice(pos+1, end).to_string());
- }
- Ip6Host | InHost => {
- host = rawurl.slice(begin, end).to_string();
+ host = rawurl.slice(begin, pos);
+ port = Some(rawurl.slice(pos+1, end));
}
+ Ip6Host
+ | InHost => host = rawurl.slice(begin, end),
InPort => {
if input != Digit {
return Err("Non-digit characters in port.".to_string());
}
- port = Some(rawurl.slice(pos+1, end).to_string());
+ port = Some(rawurl.slice(pos+1, end));
}
}
- let rest = rawurl.slice(end, len).to_string();
- return Ok((userinfo, host, port, rest));
+ let rest = rawurl.slice(end, len);
+ // If we have a port string, ensure it parses to u16.
+ let port = match port {
+ None => None,
+ opt => match opt.and_then(|p| FromStr::from_str(p)) {
+ None => return Err(format!("Failed to parse port: {}", port)),
+ opt => opt
+ }
+ };
+
+ Ok((userinfo, host, port, rest))
}
// returns the path and unparsed part of url, or an error
-fn get_path(rawurl: &str, authority: bool) ->
- Result<(String, String), String> {
+fn get_path<'a>(rawurl: &'a str, is_authority: bool)
+ -> DecodeResult<(String, &'a str)> {
let len = rawurl.len();
let mut end = len;
for (i,c) in rawurl.chars().enumerate() {
match c {
- 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '&' |'\'' | '(' | ')' | '.'
- | '@' | ':' | '%' | '/' | '+' | '!' | '*' | ',' | ';' | '='
- | '_' | '-' | '~' => {
- continue;
- }
+ 'A' .. 'Z'
+ | 'a' .. 'z'
+ | '0' .. '9'
+ | '&' |'\'' | '(' | ')' | '.'
+ | '@' | ':' | '%' | '/' | '+'
+ | '!' | '*' | ',' | ';' | '='
+ | '_' | '-' | '~' => continue,
'?' | '#' => {
end = i;
break;
}
}
- if authority {
- if end != 0 && !rawurl.starts_with("/") {
- return Err("Non-empty path must begin with\
- '/' in presence of authority.".to_string());
- }
+ if is_authority && end != 0 && !rawurl.starts_with("/") {
+ Err("Non-empty path must begin with \
+ '/' in presence of authority.".to_string())
+ } else {
+ Ok((try!(decode_component(rawurl.slice(0, end))),
+ rawurl.slice(end, len)))
}
-
- return Ok((decode_component(rawurl.slice(0, end)),
- rawurl.slice(end, len).to_string()));
}
// returns the parsed query and the fragment, if present
-fn get_query_fragment(rawurl: &str) ->
- Result<(Query, Option<String>), String> {
- if !rawurl.starts_with("?") {
- if rawurl.starts_with("#") {
- let f = decode_component(rawurl.slice(
- 1,
- rawurl.len()));
- return Ok((vec!(), Some(f)));
- } else {
- return Ok((vec!(), None));
- }
- }
- let (q, r) = split_char_first(rawurl.slice(1, rawurl.len()), '#');
- let f = if r.len() != 0 {
- Some(decode_component(r.as_slice()))
- } else {
- None
- };
- return Ok((query_from_str(q.as_slice()), f));
-}
-
-/**
- * Parses a URL, converting it from a string to `Url` representation.
- *
- * # Arguments
- *
- * `rawurl` - a string representing the full URL, including scheme.
- *
- * # Returns
- *
- * A `Url` struct type representing the URL.
- */
-pub fn from_str(rawurl: &str) -> Result<Url, String> {
- // scheme
- let (scheme, rest) = match get_scheme(rawurl) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // authority
- let (userinfo, host, port, rest) = match get_authority(rest.as_slice()) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // path
- let has_authority = host.len() > 0;
- let (path, rest) = match get_path(rest.as_slice(), has_authority) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // query and fragment
- let (query, fragment) = match get_query_fragment(rest.as_slice()) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- Ok(Url::new(scheme, userinfo, host, port, path, query, fragment))
-}
-
-pub fn path_from_str(rawpath: &str) -> Result<Path, String> {
- let (path, rest) = match get_path(rawpath, false) {
- Ok(val) => val,
- Err(e) => return Err(e)
- };
+fn get_query_fragment(rawurl: &str) -> DecodeResult<(Query, Option<String>)> {
+ let (before_fragment, raw_fragment) = split_char_first(rawurl, '#');
- // query and fragment
- let (query, fragment) = match get_query_fragment(rest.as_slice()) {
- Ok(val) => val,
- Err(e) => return Err(e),
+ // Parse the fragment if available
+ let fragment = match raw_fragment {
+ "" => None,
+ raw => Some(try!(decode_component(raw)))
};
- Ok(Path{ path: path, query: query, fragment: fragment })
+ match before_fragment.slice_shift_char() {
+ (Some('?'), rest) => Ok((try!(query_from_str(rest)), fragment)),
+ (None, "") => Ok((vec!(), fragment)),
+ _ => Err(format!("Query didn't start with '?': '{}..'", before_fragment)),
+ }
}
impl FromStr for Url {
fn from_str(s: &str) -> Option<Url> {
- match from_str(s) {
- Ok(url) => Some(url),
- Err(_) => None
- }
+ Url::parse(s).ok()
}
}
impl FromStr for Path {
fn from_str(s: &str) -> Option<Path> {
- match path_from_str(s) {
- Ok(path) => Some(path),
- Err(_) => None
- }
+ Path::parse(s).ok()
}
}
impl fmt::Show for Url {
- /**
- * Converts a URL from `Url` to string representation.
- *
- * # Arguments
- *
- * `url` - a URL.
- *
- * # Returns
- *
- * A string that contains the formatted URL. Note that this will usually
- * be an inverse of `from_str` but might strip out unneeded separators;
- * for example, "http://somehost.com?", when parsed and formatted, will
- * result in just "http://somehost.com".
- */
+ /// Converts a URL from `Url` to string representation.
+ ///
+ /// # Returns
+ ///
+ /// A string that contains the formatted URL. Note that this will usually
+ /// be an inverse of `from_str` but might strip out unneeded separators;
+ /// for example, "http://somehost.com?", when parsed and formatted, will
+ /// result in just "http://somehost.com".
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}:", self.scheme));
}
}
- try!(write!(f, "{}", self.path));
-
- if !self.query.is_empty() {
- try!(write!(f, "?{}", query_to_str(&self.query)));
- }
-
- match self.fragment {
- Some(ref fragment) => {
- write!(f, "#{}", encode_component(fragment.as_slice()))
- }
- None => Ok(()),
- }
+ write!(f, "{}", self.path)
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}", self.path));
if !self.query.is_empty() {
- try!(write!(f, "?{}", self.query))
+ try!(write!(f, "?{}", query_to_str(&self.query)))
}
match self.fragment {
impl<S: hash::Writer> hash::Hash<S> for Url {
fn hash(&self, state: &mut S) {
- self.to_str().hash(state)
+ self.to_string().hash(state)
}
}
impl<S: hash::Writer> hash::Hash<S> for Path {
fn hash(&self, state: &mut S) {
- self.to_str().hash(state)
+ self.to_string().hash(state)
}
}
#[test]
fn test_split_char_first() {
let (u,v) = split_char_first("hello, sweet world", ',');
- assert_eq!(u, "hello".to_string());
- assert_eq!(v, " sweet world".to_string());
+ assert_eq!(u, "hello");
+ assert_eq!(v, " sweet world");
let (u,v) = split_char_first("hello sweet world", ',');
- assert_eq!(u, "hello sweet world".to_string());
- assert_eq!(v, "".to_string());
+ assert_eq!(u, "hello sweet world");
+ assert_eq!(v, "");
}
#[test]
let (u, h, p, r) = get_authority(
"//user:pass@rust-lang.org/something").unwrap();
assert_eq!(u, Some(UserInfo::new("user".to_string(), Some("pass".to_string()))));
- assert_eq!(h, "rust-lang.org".to_string());
+ assert_eq!(h, "rust-lang.org");
assert!(p.is_none());
- assert_eq!(r, "/something".to_string());
+ assert_eq!(r, "/something");
let (u, h, p, r) = get_authority(
"//rust-lang.org:8000?something").unwrap();
assert!(u.is_none());
- assert_eq!(h, "rust-lang.org".to_string());
- assert_eq!(p, Some("8000".to_string()));
- assert_eq!(r, "?something".to_string());
+ assert_eq!(h, "rust-lang.org");
+ assert_eq!(p, Some(8000));
+ assert_eq!(r, "?something");
- let (u, h, p, r) = get_authority(
- "//rust-lang.org#blah").unwrap();
+ let (u, h, p, r) = get_authority("//rust-lang.org#blah").unwrap();
assert!(u.is_none());
- assert_eq!(h, "rust-lang.org".to_string());
+ assert_eq!(h, "rust-lang.org");
assert!(p.is_none());
- assert_eq!(r, "#blah".to_string());
+ assert_eq!(r, "#blah");
// ipv6 tests
let (_, h, _, _) = get_authority(
"//2001:0db8:85a3:0042:0000:8a2e:0370:7334#blah").unwrap();
- assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334".to_string());
+ assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334");
let (_, h, p, _) = get_authority(
"//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah").unwrap();
- assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334".to_string());
- assert_eq!(p, Some("8000".to_string()));
+ assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334");
+ assert_eq!(p, Some(8000));
let (u, h, p, _) = get_authority(
"//us:p@2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah"
).unwrap();
assert_eq!(u, Some(UserInfo::new("us".to_string(), Some("p".to_string()))));
- assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334".to_string());
- assert_eq!(p, Some("8000".to_string()));
+ assert_eq!(h, "2001:0db8:85a3:0042:0000:8a2e:0370:7334");
+ assert_eq!(p, Some(8000));
// invalid authorities;
assert!(get_authority("//user:pass@rust-lang:something").is_err());
"//2001:0db8:85a3:0042:0000:8a2e:0370:7334:800a").is_err());
assert!(get_authority(
"//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000:00").is_err());
+ // outside u16 range
+ assert!(get_authority("//user:pass@rust-lang:65536").is_err());
// these parse as empty, because they don't start with '//'
let (_, h, _, _) = get_authority("user:pass@rust-lang").unwrap();
- assert_eq!(h, "".to_string());
+ assert_eq!(h, "");
let (_, h, _, _) = get_authority("rust-lang.org").unwrap();
- assert_eq!(h, "".to_string());
+ assert_eq!(h, "");
}
#[test]
fn test_get_path() {
let (p, r) = get_path("/something+%20orother", true).unwrap();
assert_eq!(p, "/something+ orother".to_string());
- assert_eq!(r, "".to_string());
+ assert_eq!(r, "");
let (p, r) = get_path("test@email.com#fragment", false).unwrap();
assert_eq!(p, "test@email.com".to_string());
- assert_eq!(r, "#fragment".to_string());
+ assert_eq!(r, "#fragment");
let (p, r) = get_path("/gen/:addr=?q=v", false).unwrap();
assert_eq!(p, "/gen/:addr=".to_string());
- assert_eq!(r, "?q=v".to_string());
+ assert_eq!(r, "?q=v");
//failure cases
assert!(get_path("something?q", true).is_err());
#[cfg(test)]
mod tests {
- use {encode_form_urlencoded, decode_form_urlencoded,
- decode, encode, from_str, encode_component, decode_component,
- path_from_str, UserInfo, get_scheme};
+ use {encode_form_urlencoded, decode_form_urlencoded, decode, encode,
+ encode_component, decode_component, UserInfo, get_scheme, Url, Path};
use std::collections::HashMap;
+ use std::path::BytesContainer;
#[test]
fn test_url_parse() {
let url = "http://user:pass@rust-lang.org:8080/doc/~u?s=v#something";
-
- let up = from_str(url);
- let u = up.unwrap();
- assert_eq!(&u.scheme, &"http".to_string());
- assert_eq!(&u.user, &Some(UserInfo::new("user".to_string(), Some("pass".to_string()))));
- assert_eq!(&u.host, &"rust-lang.org".to_string());
- assert_eq!(&u.port, &Some("8080".to_string()));
- assert_eq!(&u.path, &"/doc/~u".to_string());
- assert_eq!(&u.query, &vec!(("s".to_string(), "v".to_string())));
- assert_eq!(&u.fragment, &Some("something".to_string()));
+ let u = from_str::<Url>(url).unwrap();
+
+ assert_eq!(u.scheme, "http".to_string());
+ assert_eq!(u.user, Some(UserInfo::new("user".to_string(), Some("pass".to_string()))));
+ assert_eq!(u.host, "rust-lang.org".to_string());
+ assert_eq!(u.port, Some(8080));
+ assert_eq!(u.path.path, "/doc/~u".to_string());
+ assert_eq!(u.path.query, vec!(("s".to_string(), "v".to_string())));
+ assert_eq!(u.path.fragment, Some("something".to_string()));
}
#[test]
fn test_path_parse() {
let path = "/doc/~u?s=v#something";
+ let u = from_str::<Path>(path).unwrap();
- let up = path_from_str(path);
- let u = up.unwrap();
- assert_eq!(&u.path, &"/doc/~u".to_string());
- assert_eq!(&u.query, &vec!(("s".to_string(), "v".to_string())));
- assert_eq!(&u.fragment, &Some("something".to_string()));
+ assert_eq!(u.path, "/doc/~u".to_string());
+ assert_eq!(u.query, vec!(("s".to_string(), "v".to_string())));
+ assert_eq!(u.fragment, Some("something".to_string()));
}
#[test]
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".to_string());
- assert!(url.path == "/".to_string());
+ let url = from_str::<Url>(urlstr).unwrap();
+ assert_eq!(url.host, "0.42.42.42".to_string());
+ assert_eq!(url.path.path, "/".to_string());
}
#[test]
fn test_path_parse_host_slash() {
let pathstr = "/";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == "/".to_string());
+ let path = from_str::<Path>(pathstr).unwrap();
+ assert_eq!(path.path, "/".to_string());
}
#[test]
fn test_url_host_with_port() {
let urlstr = "scheme://host:1234";
- let url = from_str(urlstr).unwrap();
- assert_eq!(&url.scheme, &"scheme".to_string());
- assert_eq!(&url.host, &"host".to_string());
- assert_eq!(&url.port, &Some("1234".to_string()));
+ let url = from_str::<Url>(urlstr).unwrap();
+ assert_eq!(url.scheme, "scheme".to_string());
+ assert_eq!(url.host, "host".to_string());
+ assert_eq!(url.port, Some(1234));
// is empty path really correct? Other tests think so
- assert_eq!(&url.path, &"".to_string());
+ assert_eq!(url.path.path, "".to_string());
+
let urlstr = "scheme://host:1234/";
- let url = from_str(urlstr).unwrap();
- assert_eq!(&url.scheme, &"scheme".to_string());
- assert_eq!(&url.host, &"host".to_string());
- assert_eq!(&url.port, &Some("1234".to_string()));
- assert_eq!(&url.path, &"/".to_string());
+ let url = from_str::<Url>(urlstr).unwrap();
+ assert_eq!(url.scheme, "scheme".to_string());
+ assert_eq!(url.host, "host".to_string());
+ assert_eq!(url.port, Some(1234));
+ assert_eq!(url.path.path, "/".to_string());
}
#[test]
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".to_string());
+ let url = from_str::<Url>(urlstr).unwrap();
+ assert_eq!(url.path.path, "/file_name.html".to_string());
}
#[test]
fn test_path_with_underscores() {
let pathstr = "/file_name.html";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == "/file_name.html".to_string());
+ let path = from_str::<Path>(pathstr).unwrap();
+ assert_eq!(path.path, "/file_name.html".to_string());
}
#[test]
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".to_string());
+ let url = from_str::<Url>(urlstr).unwrap();
+ assert_eq!(url.path.path, "/file-name.html".to_string());
}
#[test]
fn test_path_with_dashes() {
let pathstr = "/file-name.html";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == "/file-name.html".to_string());
+ let path = from_str::<Path>(pathstr).unwrap();
+ assert_eq!(path.path, "/file-name.html".to_string());
}
#[test]
#[test]
fn test_invalid_scheme_errors() {
- assert!(from_str("99://something").is_err());
- assert!(from_str("://something").is_err());
+ assert!(Url::parse("99://something").is_err());
+ assert!(Url::parse("://something").is_err());
}
#[test]
fn test_full_url_parse_and_format() {
let url = "http://user:pass@rust-lang.org/doc?s=v#something";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_userless_url_parse_and_format() {
let url = "http://rust-lang.org/doc?s=v#something";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_queryless_url_parse_and_format() {
let url = "http://user:pass@rust-lang.org/doc#something";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
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_eq!(from_str(url).unwrap().to_str().as_slice(), should_be);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), should_be);
}
#[test]
fn test_fragmentless_url_parse_and_format() {
let url = "http://user:pass@rust-lang.org/doc?q=v";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_minimal_url_parse_and_format() {
let url = "http://rust-lang.org/doc";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_url_with_port_parse_and_format() {
let url = "http://rust-lang.org:80/doc";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_scheme_host_only_url_parse_and_format() {
let url = "http://rust-lang.org";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_pathless_url_parse_and_format() {
let url = "http://user:pass@rust-lang.org?q=v#something";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_scheme_host_fragment_only_url_parse_and_format() {
let url = "http://rust-lang.org#something";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
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".to_string());
- assert!(u.query == vec!(("ba%d ".to_string(), "#&+".to_string())));
+ let u = from_str::<Url>(url).unwrap();
+ assert!(u.path.path == "/doc uments".to_string());
+ assert!(u.path.query == vec!(("ba%d ".to_string(), "#&+".to_string())));
}
#[test]
fn test_path_component_encoding() {
let path = "/doc%20uments?ba%25d%20=%23%26%2B";
- let p = path_from_str(path).unwrap();
+ let p = from_str::<Path>(path).unwrap();
assert!(p.path == "/doc uments".to_string());
assert!(p.query == vec!(("ba%d ".to_string(), "#&+".to_string())));
}
#[test]
fn test_url_without_authority() {
let url = "mailto:test@email.com";
- assert_eq!(from_str(url).unwrap().to_str().as_slice(), url);
+ let u = from_str::<Url>(url).unwrap();
+ assert_eq!(format!("{}", u).as_slice(), url);
}
#[test]
fn test_encode() {
- assert_eq!(encode(""), "".to_string());
- assert_eq!(encode("http://example.com"), "http://example.com".to_string());
- assert_eq!(encode("foo bar% baz"), "foo%20bar%25%20baz".to_string());
- assert_eq!(encode(" "), "%20".to_string());
- assert_eq!(encode("!"), "!".to_string());
- assert_eq!(encode("\""), "\"".to_string());
- assert_eq!(encode("#"), "#".to_string());
- assert_eq!(encode("$"), "$".to_string());
- assert_eq!(encode("%"), "%25".to_string());
- assert_eq!(encode("&"), "&".to_string());
- assert_eq!(encode("'"), "%27".to_string());
- assert_eq!(encode("("), "(".to_string());
- assert_eq!(encode(")"), ")".to_string());
- assert_eq!(encode("*"), "*".to_string());
- assert_eq!(encode("+"), "+".to_string());
- assert_eq!(encode(","), ",".to_string());
- assert_eq!(encode("/"), "/".to_string());
- assert_eq!(encode(":"), ":".to_string());
- assert_eq!(encode(";"), ";".to_string());
- assert_eq!(encode("="), "=".to_string());
- assert_eq!(encode("?"), "?".to_string());
- assert_eq!(encode("@"), "@".to_string());
- assert_eq!(encode("["), "[".to_string());
- assert_eq!(encode("]"), "]".to_string());
- assert_eq!(encode("\0"), "%00".to_string());
- assert_eq!(encode("\n"), "%0A".to_string());
+ fn t<T: BytesContainer>(input: T, expected: &str) {
+ assert_eq!(encode(input), expected.to_string())
+ }
+
+ t("", "");
+ t("http://example.com", "http://example.com");
+ t("foo bar% baz", "foo%20bar%25%20baz");
+ t(" ", "%20");
+ t("!", "!");
+ t("\"", "\"");
+ t("#", "#");
+ t("$", "$");
+ t("%", "%25");
+ t("&", "&");
+ t("'", "%27");
+ t("(", "(");
+ t(")", ")");
+ t("*", "*");
+ t("+", "+");
+ t(",", ",");
+ t("/", "/");
+ t(":", ":");
+ t(";", ";");
+ t("=", "=");
+ t("?", "?");
+ t("@", "@");
+ t("[", "[");
+ t("]", "]");
+ t("\0", "%00");
+ t("\n", "%0A");
+
+ t(&[0u8, 10, 37], "%00%0A%25");
}
#[test]
fn test_encode_component() {
- assert_eq!(encode_component(""), "".to_string());
- assert!(encode_component("http://example.com") ==
- "http%3A%2F%2Fexample.com".to_string());
- assert!(encode_component("foo bar% baz") ==
- "foo%20bar%25%20baz".to_string());
- assert_eq!(encode_component(" "), "%20".to_string());
- assert_eq!(encode_component("!"), "%21".to_string());
- assert_eq!(encode_component("#"), "%23".to_string());
- assert_eq!(encode_component("$"), "%24".to_string());
- assert_eq!(encode_component("%"), "%25".to_string());
- assert_eq!(encode_component("&"), "%26".to_string());
- assert_eq!(encode_component("'"), "%27".to_string());
- assert_eq!(encode_component("("), "%28".to_string());
- assert_eq!(encode_component(")"), "%29".to_string());
- assert_eq!(encode_component("*"), "%2A".to_string());
- assert_eq!(encode_component("+"), "%2B".to_string());
- assert_eq!(encode_component(","), "%2C".to_string());
- assert_eq!(encode_component("/"), "%2F".to_string());
- assert_eq!(encode_component(":"), "%3A".to_string());
- assert_eq!(encode_component(";"), "%3B".to_string());
- assert_eq!(encode_component("="), "%3D".to_string());
- assert_eq!(encode_component("?"), "%3F".to_string());
- assert_eq!(encode_component("@"), "%40".to_string());
- assert_eq!(encode_component("["), "%5B".to_string());
- assert_eq!(encode_component("]"), "%5D".to_string());
- assert_eq!(encode_component("\0"), "%00".to_string());
- assert_eq!(encode_component("\n"), "%0A".to_string());
+ fn t<T: BytesContainer>(input: T, expected: &str) {
+ assert_eq!(encode_component(input), expected.to_string())
+ }
+
+ t("", "");
+ t("http://example.com", "http%3A%2F%2Fexample.com");
+ t("foo bar% baz", "foo%20bar%25%20baz");
+ t(" ", "%20");
+ t("!", "%21");
+ t("#", "%23");
+ t("$", "%24");
+ t("%", "%25");
+ t("&", "%26");
+ t("'", "%27");
+ t("(", "%28");
+ t(")", "%29");
+ t("*", "%2A");
+ t("+", "%2B");
+ t(",", "%2C");
+ t("/", "%2F");
+ t(":", "%3A");
+ t(";", "%3B");
+ t("=", "%3D");
+ t("?", "%3F");
+ t("@", "%40");
+ t("[", "%5B");
+ t("]", "%5D");
+ t("\0", "%00");
+ t("\n", "%0A");
+
+ t(&[0u8, 10, 37], "%00%0A%25");
}
#[test]
fn test_decode() {
- assert_eq!(decode(""), "".to_string());
- assert_eq!(decode("abc/def 123"), "abc/def 123".to_string());
- assert_eq!(decode("abc%2Fdef%20123"), "abc%2Fdef 123".to_string());
- assert_eq!(decode("%20"), " ".to_string());
- assert_eq!(decode("%21"), "%21".to_string());
- assert_eq!(decode("%22"), "%22".to_string());
- assert_eq!(decode("%23"), "%23".to_string());
- assert_eq!(decode("%24"), "%24".to_string());
- assert_eq!(decode("%25"), "%".to_string());
- assert_eq!(decode("%26"), "%26".to_string());
- assert_eq!(decode("%27"), "'".to_string());
- assert_eq!(decode("%28"), "%28".to_string());
- assert_eq!(decode("%29"), "%29".to_string());
- assert_eq!(decode("%2A"), "%2A".to_string());
- assert_eq!(decode("%2B"), "%2B".to_string());
- assert_eq!(decode("%2C"), "%2C".to_string());
- assert_eq!(decode("%2F"), "%2F".to_string());
- assert_eq!(decode("%3A"), "%3A".to_string());
- assert_eq!(decode("%3B"), "%3B".to_string());
- assert_eq!(decode("%3D"), "%3D".to_string());
- assert_eq!(decode("%3F"), "%3F".to_string());
- assert_eq!(decode("%40"), "%40".to_string());
- assert_eq!(decode("%5B"), "%5B".to_string());
- assert_eq!(decode("%5D"), "%5D".to_string());
+ fn t<T: BytesContainer>(input: T, expected: &str) {
+ assert_eq!(decode(input), Ok(expected.to_string()))
+ }
+
+ assert!(decode("sadsadsda%").is_err());
+ assert!(decode("waeasd%4").is_err());
+ t("", "");
+ t("abc/def 123", "abc/def 123");
+ t("abc%2Fdef%20123", "abc%2Fdef 123");
+ t("%20", " ");
+ t("%21", "%21");
+ t("%22", "%22");
+ t("%23", "%23");
+ t("%24", "%24");
+ t("%25", "%");
+ t("%26", "%26");
+ t("%27", "'");
+ t("%28", "%28");
+ t("%29", "%29");
+ t("%2A", "%2A");
+ t("%2B", "%2B");
+ t("%2C", "%2C");
+ t("%2F", "%2F");
+ t("%3A", "%3A");
+ t("%3B", "%3B");
+ t("%3D", "%3D");
+ t("%3F", "%3F");
+ t("%40", "%40");
+ t("%5B", "%5B");
+ t("%5D", "%5D");
+
+ t("%00%0A%25".as_bytes(), "\0\n%");
}
#[test]
fn test_decode_component() {
- assert_eq!(decode_component(""), "".to_string());
- assert_eq!(decode_component("abc/def 123"), "abc/def 123".to_string());
- assert_eq!(decode_component("abc%2Fdef%20123"), "abc/def 123".to_string());
- assert_eq!(decode_component("%20"), " ".to_string());
- assert_eq!(decode_component("%21"), "!".to_string());
- assert_eq!(decode_component("%22"), "\"".to_string());
- assert_eq!(decode_component("%23"), "#".to_string());
- assert_eq!(decode_component("%24"), "$".to_string());
- assert_eq!(decode_component("%25"), "%".to_string());
- assert_eq!(decode_component("%26"), "&".to_string());
- assert_eq!(decode_component("%27"), "'".to_string());
- assert_eq!(decode_component("%28"), "(".to_string());
- assert_eq!(decode_component("%29"), ")".to_string());
- assert_eq!(decode_component("%2A"), "*".to_string());
- assert_eq!(decode_component("%2B"), "+".to_string());
- assert_eq!(decode_component("%2C"), ",".to_string());
- assert_eq!(decode_component("%2F"), "/".to_string());
- assert_eq!(decode_component("%3A"), ":".to_string());
- assert_eq!(decode_component("%3B"), ";".to_string());
- assert_eq!(decode_component("%3D"), "=".to_string());
- assert_eq!(decode_component("%3F"), "?".to_string());
- assert_eq!(decode_component("%40"), "@".to_string());
- assert_eq!(decode_component("%5B"), "[".to_string());
- assert_eq!(decode_component("%5D"), "]".to_string());
+ fn t<T: BytesContainer>(input: T, expected: &str) {
+ assert_eq!(decode_component(input), Ok(expected.to_string()))
+ }
+
+ assert!(decode_component("asacsa%").is_err());
+ assert!(decode_component("acsas%4").is_err());
+ t("", "");
+ t("abc/def 123", "abc/def 123");
+ t("abc%2Fdef%20123", "abc/def 123");
+ t("%20", " ");
+ t("%21", "!");
+ t("%22", "\"");
+ t("%23", "#");
+ t("%24", "$");
+ t("%25", "%");
+ t("%26", "&");
+ t("%27", "'");
+ t("%28", "(");
+ t("%29", ")");
+ t("%2A", "*");
+ t("%2B", "+");
+ t("%2C", ",");
+ t("%2F", "/");
+ t("%3A", ":");
+ t("%3B", ";");
+ t("%3D", "=");
+ t("%3F", "?");
+ t("%40", "@");
+ t("%5B", "[");
+ t("%5D", "]");
+
+ t("%00%0A%25".as_bytes(), "\0\n%");
}
#[test]
let mut m = HashMap::new();
m.insert("foo bar".to_string(), vec!("abc".to_string(), "12 = 34".to_string()));
- assert!(encode_form_urlencoded(&m) ==
- "foo+bar=abc&foo+bar=12+%3D+34".to_string());
+ assert_eq!(encode_form_urlencoded(&m),
+ "foo+bar=abc&foo+bar=12+%3D+34".to_string());
}
#[test]
fn test_decode_form_urlencoded() {
- assert_eq!(decode_form_urlencoded([]).len(), 0);
+ assert_eq!(decode_form_urlencoded([]).unwrap().len(), 0);
let s = "a=1&foo+bar=abc&foo+bar=12+%3D+34".as_bytes();
- let form = decode_form_urlencoded(s);
+ let form = decode_form_urlencoded(s).unwrap();
assert_eq!(form.len(), 2);
assert_eq!(form.get(&"a".to_string()), &vec!("1".to_string()));
assert_eq!(form.get(&"foo bar".to_string()),
fn main() {
let uuid1 = Uuid::new_v4();
- println!("{}", uuid1.to_str());
+ println!("{}", uuid1.to_string());
}
```
*/
-#![crate_id = "uuid#0.11.0"]
+#![crate_id = "uuid#0.11.0"] // NOTE: remove after stage0
+#![crate_name = "uuid"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
+#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(default_type_params)]
// Round-trip
let uuid_orig = Uuid::new_v4();
- let orig_str = uuid_orig.to_str();
+ let orig_str = uuid_orig.to_string();
let uuid_out = Uuid::parse_string(orig_str.as_slice()).unwrap();
assert!(uuid_orig == uuid_out);
}
#[test]
- fn test_to_str() {
+ fn test_to_string() {
let uuid1 = Uuid::new_v4();
- let s = uuid1.to_str();
+ let s = uuid1.to_string();
assert!(s.len() == 32);
assert!(s.as_slice().chars().all(|c| c.is_digit_radix(16)));
let uuid1 = Uuid::new_v4();
let hs = uuid1.to_hyphenated_str();
- let ss = uuid1.to_str();
+ let ss = uuid1.to_string();
let hsn = str::from_chars(hs.as_slice()
.chars()
let uuid_hs = Uuid::parse_string(hs.as_slice()).unwrap();
assert!(uuid_hs == uuid);
- let ss = uuid.to_str();
+ let ss = uuid.to_string();
let uuid_ss = Uuid::parse_string(ss.as_slice()).unwrap();
assert!(uuid_ss == uuid);
}
}
#[bench]
- pub fn uuid_to_str(b: &mut Bencher) {
+ pub fn uuid_to_string(b: &mut Bencher) {
let u = Uuid::new_v4();
b.iter(|| {
- u.to_str();
+ u.to_string();
})
}
+S 2014-07-05 aaff4e0
+ freebsd-x86_64 10272ca9eb17e1be4a4b172aacfb4b33fffcc8fb
+ linux-i386 72ba9f6e0d096c30f128cb3736ffac0b57530a20
+ linux-x86_64 e5621f84934a7d76002ab95a354fbbb9ae6ebbb1
+ macos-i386 a88fd84ee959e59265de12b8f551ed56c0e943df
+ macos-x86_64 f19d479e5a0d2a6067a05b1910e4a6a544836b0a
+ winnt-i386 0c5a91e422409b89ac22f8c265af66f759d476c8
+
S 2014-06-25 bab614f
freebsd-x86_64 14cb361c8fdefa2534bb6776a04815c08680ecd6
linux-i386 8fec4845626c557431a4aa7bfb2b5cfc65ad9eda
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="crateresolve1#0.1"]
-
+// compile-flags:-C extra-filename=-1
+#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 10 }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="crateresolve1#0.2"]
-
+// compile-flags:-C extra-filename=-2
+#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 20 }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="crateresolve1#0.3"]
-
+// compile-flags:-C extra-filename=-3
+#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 30 }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_id="crateresolve2#0.1"]
-
-#![crate_type = "lib"]
-
-pub fn f() -> int { 10 }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_id="crateresolve2#0.2"]
-
-#![crate_type = "lib"]
-
-pub fn f() -> int { 20 }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_id="crateresolve2#0.3"]
-
-#![crate_type = "lib"]
-
-pub fn f() -> int { 30 }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="externcallback#0.1"]
+#![crate_name="externcallback"]
#![crate_type = "lib"]
extern crate libc;
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// no-prefer-dynamic
-
-#![crate_id = "url#0.11.0"]
-#![crate_type = "dylib"]
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// no-prefer-dynamic
-
-#![crate_id = "url#0.11.0"]
-#![crate_type = "rlib"]
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type = "lib"]
-
-pub enum maybe<T> { just(T), nothing }
-
-impl <T:Clone> Index<uint,T> for maybe<T> {
- fn index(&self, _idx: &uint) -> T {
- match self {
- &just(ref t) => (*t).clone(),
- ¬hing => { fail!(); }
- }
- }
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type = "lib"]
-
-extern crate issue2378a;
-
-use issue2378a::maybe;
-
-pub struct two_maybes<T> {pub a: maybe<T>, pub b: maybe<T>}
-
-impl<T:Clone> Index<uint,(T,T)> for two_maybes<T> {
- fn index(&self, idx: &uint) -> (T, T) {
- (self.a[*idx], self.b[*idx])
- }
-}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct S {
+ pub x: int,
+ pub y: int,
+}
+
+pub type S2 = S;
+
let mut set = f();
timed(&mut self.sequential_strings, || {
for i in range(0u, num_keys) {
- set.insert(i.to_str());
+ set.insert(i.to_string());
}
for i in range(0u, num_keys) {
- assert!(set.contains(&i.to_str()));
+ assert!(set.contains(&i.to_string()));
}
})
}
let mut set = f();
timed(&mut self.random_strings, || {
for _ in range(0, num_keys) {
- let s = rng.gen::<uint>().to_str();
+ let s = rng.gen::<uint>().to_string();
set.insert(s);
}
})
{
let mut set = f();
for i in range(0u, num_keys) {
- set.insert(i.to_str());
+ set.insert(i.to_string());
}
timed(&mut self.delete_strings, || {
for i in range(0u, num_keys) {
- assert!(set.remove(&i.to_str()));
+ assert!(set.remove(&i.to_string()));
}
})
}
let n = from_str::<uint>(args.get(1).as_slice()).unwrap();
for i in range(0u, n) {
- let x = i.to_str();
+ let x = i.to_string();
println!("{}", x);
}
}
let mut out = String::new();
for col in set.iter() {
out.push_char(' ');
- out.push_str(col.to_str().as_slice());
+ out.push_str(col.to_string().as_slice());
}
out
}
k.as_slice()
.to_ascii()
.to_upper()
- .into_str(), v).as_slice());
+ .into_string(), v).as_slice());
}
return buffer
// given a map, search for the frequency of a pattern
fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint {
- let key = key.to_owned().into_ascii().as_slice().to_lower().into_str();
+ let key = key.to_owned().into_ascii().as_slice().to_lower().into_string();
match mm.find_equiv(&key.as_bytes()) {
option::None => { return 0u; }
option::Some(&num) => { return num; }
let elapsed = stop - start;
- println!("{}\t{}\t{}", n, fibn, elapsed.to_str());
+ println!("{}\t{}\t{}", n, fibn, elapsed.to_string());
}
}
}
} else {
box io::stdin() as Box<io::Reader>
};
- let mut seq = rdr.read_to_str().unwrap();
+ let mut seq = rdr.read_to_string().unwrap();
let ilen = seq.len();
seq = regex!(">[^\n]*\n|\n").replace_all(seq.as_slice(), NoExpand(""));
let (mut variant_strs, mut counts) = (vec!(), vec!());
for variant in variants.move_iter() {
let seq_arc_copy = seq_arc.clone();
- variant_strs.push(variant.to_str().to_owned());
+ variant_strs.push(variant.to_string().to_owned());
counts.push(Future::spawn(proc() {
count_matches(seq_arc_copy.as_slice(), &variant)
}));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate foo = ""; //~ ERROR: malformed crate id
-extern crate bar = "#a"; //~ ERROR: malformed crate id
+extern crate foo = ""; //~ ERROR: crate name must not be empty
fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate bar = "#a"; //~ ERROR: invalid character `#` in crate name: `#a`
+
+fn main() {}
+
static STATIC2: Unsafe<int> = Unsafe{value: 1, marker1: marker::InvariantType};
static STATIC3: MyUnsafe<int> = MyUnsafe{value: STATIC2};
-static STATIC4: &'static Unsafe<int> = &'static STATIC2;
+static STATIC4: &'static Unsafe<int> = &STATIC2;
//~^ ERROR borrow of immutable static items with unsafe interior is not allowed
struct Wrap<T> {
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+ x: int,
+ y: int,
+}
+
+impl Index<String,int> for Foo {
+ fn index<'a>(&'a self, z: &String) -> &'a int {
+ if z.as_slice() == "x" {
+ &self.x
+ } else {
+ &self.y
+ }
+ }
+}
+
+impl IndexMut<String,int> for Foo {
+ fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut int {
+ if z.as_slice() == "x" {
+ &mut self.x
+ } else {
+ &mut self.y
+ }
+ }
+}
+
+struct Bar {
+ x: int,
+}
+
+impl Index<int,int> for Bar {
+ fn index<'a>(&'a self, z: &int) -> &'a int {
+ &self.x
+ }
+}
+
+fn main() {
+ let mut f = Foo {
+ x: 1,
+ y: 2,
+ };
+ let mut s = "hello".to_string();
+ let rs = &mut s;
+ println!("{}", f[s]);
+ //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+ f[s] = 10;
+ //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+ let s = Bar {
+ x: 1,
+ };
+ s[2] = 20;
+ //~^ ERROR cannot assign to immutable indexed content
+}
+
+
field2: Variant4("str".to_string())
};
-static STATIC15: &'static [Box<MyOwned>] = &'static [box MyOwned, box MyOwned];
+static STATIC15: &'static [Box<MyOwned>] = &[box MyOwned, box MyOwned];
//~^ ERROR static items are not allowed to have custom pointers
//~^^ ERROR static items are not allowed to have custom pointers
static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) =
- (&'static box MyOwned, &'static box MyOwned);
+ (&box MyOwned, &box MyOwned);
//~^ ERROR static items are not allowed to have custom pointers
//~^^ ERROR static items are not allowed to have custom pointers
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve2-1.rs
-// aux-build:crateresolve2-2.rs
-// aux-build:crateresolve2-3.rs
-// error-pattern:using multiple versions of crate `crateresolve2`
-
-extern crate crateresolve2 = "crateresolve2#0.1";
-
-mod m {
- pub extern crate crateresolve2 = "crateresolve2#0.2";
-}
-
-fn main() {
- let x: int = false;
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve5-1.rs
-// aux-build:crateresolve5-2.rs
-
-extern crate cr5_1 = "crateresolve5#0.1";
-extern crate cr5_2 = "crateresolve5#0.2";
-
-
-fn main() {
- // Nominal types from two multiple versions of a crate are different types
- assert!(cr5_1::nominal() == cr5_2::nominal()); //~ ERROR mismatched types: expected
-}
#![feature(struct_variant)]
enum Foo { C { a: int, b: int } }
-struct C { a: int, b: int } //~ ERROR error: duplicate definition of type `C`
+struct C { a: int, b: int } //~ ERROR error: duplicate definition of type or module `C`
struct A { x: int }
-enum Bar { A { x: int } } //~ ERROR error: duplicate definition of type `A`
+enum Bar { A { x: int } } //~ ERROR error: duplicate definition of type or module `A`
fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod Foo {
+ pub static X: int = 42;
+}
+
+enum Foo { //~ ERROR duplicate definition of type or module `Foo`
+ X
+}
+
+fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:issue-11908-1.rs
-// ignore-android this test is incompatible with the android test runner
-// error-pattern: multiple dylib candidates for `url` found
-
-// This test ensures that if you have the same rlib or dylib at two locations
-// in the same path that you don't hit an assertion in the compiler.
-//
-// Note that this relies on `liburl` to be in the path somewhere else,
-// and then our aux-built libraries will collide with liburl (they have
-// the same version listed)
-
-extern crate url;
-
-fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:issue-11908-2.rs
-// no-prefer-dynamic
-// ignore-android this test is incompatible with the android test runner
-// error-pattern: multiple rlib candidates for `url` found
-
-// see comments in issue-11908-1 for what's going on here
-
-extern crate url;
-
-fn main() {}
-
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn new<T>() -> &'static T {
+ fail!()
+}
+
+fn main() {
+ let &v = new();
+ //~^ ERROR cannot determine a type for this local variable: unconstrained type
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn new<'r, T>() -> &'r T {
+ fail!()
+}
+
+fn main() {
+ let &v = new();
+ //~^ ERROR cannot determine a type for this local variable: unconstrained type
+}
fn make(v: vec2) {
let vec3 { y: _, z: _ } = v;
- //~^ ERROR mismatched types: expected `vec2` but found `vec3`
+ //~^ ERROR `vec3` does not name the structure `vec2`
//~^^ ERROR struct `vec2` does not have a field named `z`
}
-fn main() { }
\ No newline at end of file
+fn main() { }
struct t(Box<t>); //~ ERROR this type cannot be instantiated
trait to_str_2 {
- fn my_to_str() -> String;
+ fn my_to_string() -> String;
}
// I use an impl here because it will cause
// the compiler to attempt autoderef and then
// try to resolve the method.
impl to_str_2 for t {
- fn my_to_str() -> String { "t".to_string() }
+ fn my_to_string() -> String { "t".to_string() }
}
fn new_t(x: t) {
- x.my_to_str(); //~ ERROR does not implement
+ x.my_to_string(); //~ ERROR does not implement
}
fn main() {
enum a { b, c }
-enum a { d, e } //~ ERROR duplicate definition of type `a`
+enum a { d, e } //~ ERROR duplicate definition of type or module `a`
fn main() {}
pub mod a {}
-pub mod a {} //~ ERROR duplicate definition of module `a`
+pub mod a {} //~ ERROR duplicate definition of type or module `a`
fn main() {}
y: f64,
}
-trait NewTrait {
- fn a(&self) -> String;
+trait ToString_ {
+ fn to_string(&self) -> String;
}
-impl NewTrait for Point {
+impl ToString_ for Point {
fn new(x: f64, y: f64) -> Point {
- //~^ ERROR method `new` is not a member of trait `NewTrait`
+ //~^ ERROR method `new` is not a member of trait `ToString_`
Point { x: x, y: y }
}
- fn a(&self) -> String {
+ fn to_string(&self) -> String {
format!("({}, {})", self.x, self.y)
}
}
let p = Point::new(0.0, 0.0);
//~^ ERROR unresolved name `Point::new`
//~^^ ERROR failed to resolve. Use of undeclared module `Point`
- println!("{}", p.a());
+ println!("{}", p.to_string());
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-tidy-linelength
+
#![allow(dead_code)]
#![deny(uppercase_variables)]
let mut buff = [0u8, ..16];
match f.read(buff) {
Ok(cnt) => println!("read this many bytes: {}", cnt),
- Err(IoError{ kind: EndOfFile, .. }) => println!("Got end of file: {}", EndOfFile.to_str()),
+ Err(IoError{ kind: EndOfFile, .. }) => println!("Got end of file: {}", EndOfFile.to_string()),
//~^ ERROR variable names should start with a lowercase character
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-tidy-linelength
struct S {
x: Box<E>
f(&s, |hellothere| {
match hellothere.x { //~ ERROR cannot move out
box Foo(_) => {}
- box Bar(x) => println!("{}", x.to_str()), //~ NOTE attempting to move value to here
+ box Bar(x) => println!("{}", x.to_string()), //~ NOTE attempting to move value to here
box Baz => {}
}
})
y: int
}
-impl Cmp, ToStr for S { //~ ERROR: expected `{` but found `,`
+impl Cmp, ToString for S { //~ ERROR: expected `{` but found `,`
fn eq(&&other: S) { false }
- fn to_str(&self) -> String { "hi".to_string() }
+ fn to_string(&self) -> String { "hi".to_string() }
}
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
- impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+ impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
fn foo() {
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
- impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+ impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
fn foo() {
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
- impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+ impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
fn foo() {
impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
fn main() {
fn struct_with_a_nested_enum_and_vector() {
match (Foo { first: true, second: None }) {
- //~^ ERROR non-exhaustive patterns: `Foo{first: false, second: Some([_, _, _, _])}` not covered
+//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
Foo { first: true, second: None } => (),
Foo { first: true, second: Some(_) } => (),
Foo { first: false, second: None } => (),
fn enum_struct_variant() {
match Red {
- //~^ ERROR non-exhaustive patterns: `CustomRGBA{a: true, r: _, g: _, b: _}` not covered
+ //~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
Red => (),
Green => (),
CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
enum E {}
fn f(e: E) {
- println!("{}", (e as int).to_str()); //~ ERROR non-scalar cast
+ println!("{}", (e as int).to_string()); //~ ERROR non-scalar cast
}
fn main() {}
// error-pattern: instantiating a type parameter with an incompatible type
fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<T>() }
+fn foo<Sized? T>() { bar::<T>() }
fn main() { }
// error-pattern: instantiating a type parameter with an incompatible type
fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<Option<T>>() }
+fn foo<Sized? T>() { bar::<Option<T>>() }
fn main() { }
struct Foo<T> { data: T }
fn bar<T: Sized>() { }
-fn foo<type T>() { bar::<Foo<T>>() }
+fn foo<Sized? T>() { bar::<Foo<T>>() }
fn main() { }
// Unbounded.
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
f2::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
}
fn f2<X>(x: &X) {
}
// Bounded.
-trait T for type {}
-fn f3<type X: T>(x: &X) {
+trait T for Sized? {}
+fn f3<Sized? X: T>(x: &X) {
f4::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
}
fn f4<X: T>(x: &X) {
}
// Test with unsized enum.
-enum E<type X> {
+enum E<Sized? X> {
V(X),
}
fn f5<Y>(x: &Y) {}
-fn f6<type X>(x: &X) {}
-fn f7<type X>(x1: &E<X>, x2: &E<X>) {
+fn f6<Sized? X>(x: &X) {}
+fn f7<Sized? X>(x1: &E<X>, x2: &E<X>) {
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `E<X>`, which does not
f6(x2); // ok
}
// Test with unsized struct.
-struct S<type X> {
+struct S<Sized? X> {
x: X,
}
-fn f8<type X>(x1: &S<X>, x2: &S<X>) {
+fn f8<Sized? X>(x1: &S<X>, x2: &S<X>) {
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `S<X>`, which does not
f6(x2); // ok
}
// Test some tuples.
-fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
+fn f9<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(*x1, 34i)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
f5(&(32i, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
}
// impl - bounded
trait T1<Z: T> {
}
-struct S3<type Y>;
-impl<type X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
+struct S3<Sized? Y>;
+impl<Sized? X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
}
// impl - unbounded
trait T2<Z> {
}
-impl<type X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X`
+impl<Sized? X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X
// impl - struct
-trait T3<type Z> {
+trait T3<Sized? Z> {
}
struct S4<Y>;
-impl<type X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X`
+impl<Sized? X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X
}
*/
// Test that bounds are sized-compatible.
trait T {}
-fn f<type Y: T>() {
+fn f<Sized? Y: T>() {
//~^ERROR incompatible bounds on type parameter Y, bound T does not allow unsized type
}
// except according to those terms.
#![feature(struct_variant)]
-// Test `type` types not allowed in fields.
+// Test `Sized?` types not allowed in fields.
-struct S1<type X> {
+struct S1<Sized? X> {
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
f2: int,
}
-struct S2<type X> {
+struct S2<Sized? X> {
f: int,
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
h: int,
}
-enum E<type X> {
+enum E<Sized? X> {
V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test `type` local variables.
+// Test `Sized?` local variables.
-trait T for type {}
+trait T for Sized? {}
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
let _: X; //~ERROR variable `_` has dynamically sized type `X`
let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
let y: X; //~ERROR variable `y` has dynamically sized type `X`
let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
}
-fn f2<type X: T>(x: &X) {
+fn f2<Sized? X: T>(x: &X) {
let _: X; //~ERROR variable `_` has dynamically sized type `X`
let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
let y: X; //~ERROR variable `y` has dynamically sized type `X`
let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
}
-fn f3<type X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f3<Sized? X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
}
-fn f4<type X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f4<Sized? X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
}
-fn g1<type X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
-fn g2<type X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+fn g1<Sized? X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
+fn g2<Sized? X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
pub fn main() {
}
}
struct List {
- list: Vec<Box<ToStr>> }
+ list: Vec<Box<ToString>> }
impl List {
- fn push(&mut self, n: Box<ToStr>) {
+ fn push(&mut self, n: Box<ToString>) {
self.list.push(n);
}
}
let n = box Number { n: 42 };
let mut l = box List { list: Vec::new() };
l.push(n);
- let x = n.to_str();
+ let x = n.to_string();
//~^ ERROR: use of moved value: `n`
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:can't find crate for `std`
-
-extern crate std = "std#bogus";
C
}
-fn main() { }
\ No newline at end of file
+fn main() { }
all:
$(RUSTC) lib.rs
- ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN_BINFILE,main) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -lboot
$(call RUN,main)
$(call REMOVE_DYLIBS,boot)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="boot#0.1"]
+#![crate_name="boot"]
#![crate_type="dylib"]
extern crate rustuv;
all:
$(RUSTC) lib.rs
- ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN_BINFILE,main) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -lboot
$(call RUN,main)
$(call REMOVE_DYLIBS,boot)
all:
$(RUSTC) foo.rs
- ln -s $(call DYLIB,foo-*) $(call DYLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -Wl,-rpath,$(TMPDIR)
$(call RUN,bar)
$(call REMOVE_DYLIBS,foo)
ifneq ($(shell uname),FreeBSD)
all:
$(RUSTC) foo.rs
- ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRAFLAGS) -lstdc++
$(call RUN,bar)
rm $(call STATICLIB,foo*)
-include ../tools.mk
all:
- [ `$(RUSTC) --crate-id crate.rs` = "foo#0.11.0" ]
- [ `$(RUSTC) --crate-name crate.rs` = "foo" ]
- [ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
- [ `$(RUSTC) --crate-file-name --crate-type=lib --test crate.rs` = "foo" ]
- [ `$(RUSTC) --crate-file-name --test lib.rs` = "mylib" ]
- $(RUSTC) --crate-file-name lib.rs
- $(RUSTC) --crate-file-name rlib.rs
+ [ `$(RUSTC) --print-crate-name crate.rs` = "foo" ]
+ [ `$(RUSTC) --print-file-name crate.rs` = "foo" ]
+ [ `$(RUSTC) --print-file-name --crate-type=lib --test crate.rs` = "foo" ]
+ [ `$(RUSTC) --print-file-name --test lib.rs` = "mylib" ]
+ $(RUSTC) --print-file-name lib.rs
+ $(RUSTC) --print-file-name rlib.rs
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "foo#0.11.0"]
+#![crate_name = "foo"]
// Querying about the crate metadata should *not* parse the entire crate, it
// only needs the crate attributes (which are guaranteed to be at the top) be
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "mylib"]
+#![crate_name = "mylib"]
#![crate_type = "lib"]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "mylib"]
+#![crate_name = "mylib"]
#![crate_type = "rlib"]
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) foo.rs
+ rm $(TMPDIR)/$(call BIN,foo)
+ $(RUSTC) foo.rs --crate-name bar
+ rm $(TMPDIR)/$(call BIN,bar)
+ $(RUSTC) foo1.rs
+ rm $(TMPDIR)/$(call BIN,foo)
+ $(RUSTC) foo1.rs --crate-name bar
+ rm $(TMPDIR)/$(call BIN,bar)
+ $(RUSTC) foo1.rs --crate-name bar -o $(TMPDIR)/bar1
+ rm $(TMPDIR)/$(call BIN,bar1)
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+fn main() {}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id="foo#0.1"]
+#![crate_name = "foo"]
pub mod foo;
pub mod bar;
--- /dev/null
+-include ../tools.mk
+
+# Attempt to build this dependency tree:
+#
+# A.1 A.2
+# |\ |
+# | \ |
+# B \ C
+# \ | /
+# \|/
+# D
+#
+# Note that A.1 and A.2 are crates with the same name.
+
+all:
+ $(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs
+ $(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
+ $(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
+ $(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
+ $(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
+ $(call RUN,d)
+ $(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib
+ $(call RUN,d)
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "a"]
+#![crate_type = "rlib"]
+
+static FOO: uint = 3;
+
+pub fn token() -> &'static uint { &FOO }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "b"]
+#![crate_type = "rlib"]
+
+extern crate a;
+
+static FOO: uint = 3;
+
+pub fn token() -> &'static uint { &FOO }
+pub fn a_token() -> &'static uint { a::token() }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "c"]
+#![crate_type = "rlib"]
+
+extern crate a;
+
+static FOO: uint = 3;
+
+pub fn token() -> &'static uint { &FOO }
+pub fn a_token() -> &'static uint { a::token() }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(before)] extern crate a;
+extern crate b;
+extern crate c;
+#[cfg(after)] extern crate a;
+
+fn t(a: &'static uint) -> uint { a as *const _ as uint }
+
+fn main() {
+ assert!(t(a::token()) == t(b::a_token()));
+ assert!(t(a::token()) != t(c::a_token()));
+}
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) bar.rs --crate-type=rlib
+ $(RUSTC) bar.rs --crate-type=rlib -C extra-filename=-a
+ $(RUSTC) foo.rs --extern hello && exit 1 || exit 0
+ $(RUSTC) foo.rs --extern bar=no-exist && exit 1 || exit 0
+ $(RUSTC) foo.rs --extern bar=foo.rs && exit 1 || exit 0
+ $(RUSTC) foo.rs \
+ --extern bar=$(TMPDIR)/libbar.rlib \
+ --extern bar=$(TMPDIR)/libbar-a.rlib \
+ && exit 1 || exit 0
+ $(RUSTC) foo.rs \
+ --extern bar=$(TMPDIR)/libbar.rlib \
+ --extern bar=$(TMPDIR)/libbar.rlib
+ $(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate bar;
+
+fn main() {}
N2[label="expr 6"];
N3[label="expr S6{val: 6,}"];
N4[label="local _x"];
- N5[label="pat S6{val: _x}"];
- N6[label="block { let S6{val: _x} = S6{val: 6,}; }"];
+ N5[label="pat S6 { val: _x }"];
+ N6[label="block { let S6 { val: _x } = S6{val: 6,}; }"];
N0 -> N2;
N2 -> N3;
N3 -> N4;
--- /dev/null
+# This test ensures that if you have the same rlib or dylib at two locations
+# in the same path that you don't hit an assertion in the compiler.
+#
+# Note that this relies on `liburl` to be in the path somewhere else,
+# and then our aux-built libraries will collide with liburl (they have
+# the same version listed)
+
+-include ../tools.mk
+
+all:
+ mkdir $(TMPDIR)/other
+ $(RUSTC) foo.rs --crate-type=dylib
+ mv $(call DYLIB,foo) $(TMPDIR)/other
+ $(RUSTC) foo.rs --crate-type=dylib
+ $(RUSTC) bar.rs -L $(TMPDIR)/other 2>&1 | \
+ grep "multiple dylib candidates"
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)/other
+ $(RUSTC) foo.rs --crate-type=rlib
+ mv $(TMPDIR)/libfoo.rlib $(TMPDIR)/other
+ $(RUSTC) foo.rs --crate-type=rlib
+ $(RUSTC) bar.rs -L $(TMPDIR)/other 2>&1 | \
+ grep "multiple rlib candidates"
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate foo;
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
all:
$(RUSTC) foo.rs -Z lto
- ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRACFLAGS) -lstdc++
$(call RUN,bar)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[crate_type = "rlib"];
+#![crate_type = "rlib"]
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) --crate-name foo bar.rs
+ rm $(TMPDIR)/libfoo.rlib
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) foo.rs -C metadata=a -C extra-filename=-a
+ $(RUSTC) foo.rs -C metadata=b -C extra-filename=-b
+ $(RUSTC) bar.rs \
+ --extern foo1=$(TMPDIR)/libfoo-a.rlib \
+ --extern foo2=$(TMPDIR)/libfoo-b.rlib \
+ -Z print-link-args
+ $(call RUN,bar)
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate foo1;
+extern crate foo2;
+
+fn main() {
+ let a = foo1::foo();
+ let b = foo2::foo();
+ assert!(a as *const _ != b as *const _);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+#![crate_type = "rlib"]
+
+static FOO: uint = 3;
+
+pub fn foo() -> &'static uint { &FOO }
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) foo.rs -C metadata=a -C extra-filename=-1 --crate-type=rlib
+ $(RUSTC) foo.rs -C metadata=b -C extra-filename=-2 --crate-type=rlib
+ $(RUSTC) bar.rs \
+ --extern foo1=$(TMPDIR)/libfoo-1.rlib \
+ --extern foo2=$(TMPDIR)/libfoo-2.rlib \
+ 2>&1 | grep "using multiple versions of crate .foo."
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate foo1;
+extern crate foo2;
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn foo() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![crate_id = "bar"]
+#![crate_name = "bar"]
fn main() {}
-include ../tools.mk
all:
- $(RUSTC) foo.rs -o $(TMPDIR)/.foo
- rm $(TMPDIR)/.foo
- $(RUSTC) foo.rs -o $(TMPDIR)/.foo.bar
- rm $(TMPDIR)/.foo.bar
- $(RUSTC) foo.rs -o $(TMPDIR)/+foo+bar
- rm $(TMPDIR)/$(call BIN,+foo+bar)
+ cp foo.rs $(TMPDIR)/.foo.rs
+ $(RUSTC) $(TMPDIR)/.foo.rs 2>&1 \
+ | grep "invalid character.*in crate name:"
+ cp foo.rs $(TMPDIR)/.foo.bar
+ $(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \
+ | grep "invalid character.*in crate name:"
+ cp foo.rs $(TMPDIR)/+foo+bar
+ $(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \
+ | grep "invalid character.*in crate name:"
use std::collections::Bitv;
fn bitv_test() {
- let mut v1 = box Bitv::new(31, false);
- let v2 = box Bitv::new(31, true);
+ let mut v1 = box Bitv::with_capacity(31, false);
+ let v2 = box Bitv::with_capacity(31, true);
v1.union(v2);
}
assert_eq!(!true, false);
assert_eq!(!false, true);
- let s = false.to_str();
+ let s = false.to_string();
assert_eq!(s.as_slice(), "false");
- let s = true.to_str();
+ let s = true.to_string();
assert_eq!(s.as_slice(), "true");
assert!(true > false);
_ => fail!(),
}
+ let buf = vec!(97u8, 98, 99, 100);
+ assert_eq!(match buf.slice(0, 3) {
+ b"def" => 1u,
+ b"abc" => 2u,
+ _ => 3u
+ }, 2);
+
assert_eq!(BAZ, &[97u8, 92u8, 110u8]);
assert_eq!(br"a\n", &[97u8, 92u8, 110u8]);
assert_eq!(br"a\n", b"a\\n");
debug!("debug");
info!("info");
});
- let s = r.read_to_str().unwrap();
+ let s = r.read_to_string().unwrap();
assert!(s.as_slice().contains("info"));
assert!(!s.as_slice().contains("debug"));
}
// aux-build:cci_class_cast.rs
extern crate cci_class_cast;
-use std::to_str::ToStr;
+use std::to_str::ToString;
use cci_class_cast::kitty::cat;
-fn print_out(thing: Box<ToStr>, expected: String) {
- let actual = thing.to_str();
+fn print_out(thing: Box<ToString>, expected: String) {
+ let actual = thing.to_string();
println!("{}", actual);
assert_eq!(actual.to_string(), expected);
}
pub fn main() {
- let nyan: Box<ToStr> = box cat(0u, 2, "nyan".to_string()) as Box<ToStr>;
+ let nyan: Box<ToString> = box cat(0u, 2, "nyan".to_string()) as Box<ToString>;
print_out(nyan, "nyan".to_string());
}
}
}
-fn print_out(thing: Box<ToStr>, expected: String) {
- let actual = thing.to_str();
+fn print_out(thing: Box<ToString>, expected: String) {
+ let actual = thing.to_string();
println!("{}", actual);
assert_eq!(actual.to_string(), expected);
}
pub fn main() {
- let nyan: Box<ToStr> = box cat(0u, 2, "nyan".to_string()) as Box<ToStr>;
+ let nyan: Box<ToString> = box cat(0u, 2, "nyan".to_string()) as Box<ToString>;
print_out(nyan, "nyan".to_string());
}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve1-1.rs
-// aux-build:crateresolve1-2.rs
-// aux-build:crateresolve1-3.rs
-
-extern crate crateresolve1 = "crateresolve1#0.2";
-
-pub fn main() {
- assert_eq!(crateresolve1::f(), 20);
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve2-1.rs
-// aux-build:crateresolve2-2.rs
-// aux-build:crateresolve2-3.rs
-
-mod a {
- extern crate crateresolve2 = "crateresolve2#0.1";
- pub fn f() { assert!(crateresolve2::f() == 10); }
-}
-
-mod b {
- extern crate crateresolve2 = "crateresolve2#0.2";
- pub fn f() { assert!(crateresolve2::f() == 20); }
-}
-
-mod c {
- extern crate crateresolve2 = "crateresolve2#0.3";
- pub fn f() { assert!(crateresolve2::f() == 30); }
-}
-
-pub fn main() {
- a::f();
- b::f();
- c::f();
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve3-1.rs
-// aux-build:crateresolve3-2.rs
-
-// verify able to link with crates with same name but different versions
-// as long as no name collision on invoked functions.
-
-mod a {
- extern crate crateresolve3 = "crateresolve3#0.1";
- pub fn f() { assert!(crateresolve3::f() == 10); }
-}
-
-mod b {
- extern crate crateresolve3 = "crateresolve3#0.2";
- pub fn f() { assert!(crateresolve3::g() == 20); }
-}
-
-pub fn main() {
- a::f();
- b::f();
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve4a-1.rs
-// aux-build:crateresolve4a-2.rs
-// aux-build:crateresolve4b-1.rs
-// aux-build:crateresolve4b-2.rs
-
-pub mod a {
- extern crate crateresolve4b = "crateresolve4b#0.1";
- pub fn f() { assert!(crateresolve4b::f() == 20); }
-}
-
-pub mod b {
- extern crate crateresolve4b = "crateresolve4b#0.2";
- pub fn f() { assert!(crateresolve4b::g() == 10); }
-}
-
-pub fn main() {
- a::f();
- b::f();
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve5-1.rs
-// aux-build:crateresolve5-2.rs
-
-extern crate cr5_1 = "crateresolve5#0.1";
-extern crate cr5_2 = "crateresolve5#0.2";
-
-pub fn main() {
- // Structural types can be used between two versions of the same crate
- assert!(cr5_1::struct_nameval().name == cr5_2::struct_nameval().name);
- assert!(cr5_1::struct_nameval().val == cr5_2::struct_nameval().val);
- // Make sure these are actually two different crates
- assert!(cr5_1::f() == 10 && cr5_2::f() == 20);
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:crateresolve8-1.rs
-
-#![crate_id="crateresolve8#0.1"]
-
-extern crate crateresolve8 = "crateresolve8#0.1";
-//extern crate crateresolve8(vers = "0.1");
-
-pub fn main() {
- assert_eq!(crateresolve8::f(), 20);
-}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This briefuly tests the capability of `Cell` and `RefCell` to implement the
+// `Encodable` and `Decodable` traits via `#[deriving(Encodable, Decodable)]`
+
+extern crate serialize;
+
+use std::cell::{Cell, RefCell};
+use std::io::MemWriter;
+use serialize::{Encodable, Decodable};
+use serialize::ebml;
+use serialize::ebml::writer::Encoder;
+use serialize::ebml::reader::Decoder;
+
+#[deriving(Encodable, Decodable)]
+struct A {
+ baz: int
+}
+
+#[deriving(Encodable, Decodable)]
+struct B {
+ foo: Cell<bool>,
+ bar: RefCell<A>,
+}
+
+fn main() {
+ let obj = B {
+ foo: Cell::new(true),
+ bar: RefCell::new( A { baz: 2 } )
+ };
+ let mut w = MemWriter::new();
+ {
+ let mut e = Encoder::new(&mut w);
+ match obj.encode(&mut e) {
+ Ok(()) => (),
+ Err(e) => fail!("Failed to encode: {}", e)
+ };
+ }
+ let doc = ebml::Doc::new(w.get_ref());
+ let mut dec = Decoder::new(doc);
+ let obj2: B = match Decodable::decode(&mut dec) {
+ Ok(v) => v,
+ Err(e) => fail!("Failed to decode: {}", e)
+ };
+ assert!(obj.foo.get() == obj2.foo.get());
+ assert!(obj.bar.borrow().baz == obj2.bar.borrow().baz);
+}
}
pub fn main() {
- assert_eq!(B1.to_str(), "B1".to_string());
- assert_eq!(B2.to_str(), "B2".to_string());
- assert_eq!(C1(3).to_str(), "C1(3)".to_string());
- assert_eq!(C2(B2).to_str(), "C2(B2)".to_string());
- assert_eq!(D1{ a: 2 }.to_str(), "D1 { a: 2 }".to_string());
- assert_eq!(E.to_str(), "E".to_string());
- assert_eq!(F(3).to_str(), "F(3)".to_string());
- assert_eq!(G(3, 4).to_str(), "G(3, 4)".to_string());
- assert_eq!(G(3, 4).to_str(), "G(3, 4)".to_string());
- assert_eq!(I{ a: 2, b: 4 }.to_str(), "I { a: 2, b: 4 }".to_string());
- assert_eq!(J(Custom).to_str(), "J(yay)".to_string());
+ assert_eq!(B1.to_string(), "B1".to_string());
+ assert_eq!(B2.to_string(), "B2".to_string());
+ assert_eq!(C1(3).to_string(), "C1(3)".to_string());
+ assert_eq!(C2(B2).to_string(), "C2(B2)".to_string());
+ assert_eq!(D1{ a: 2 }.to_string(), "D1 { a: 2 }".to_string());
+ assert_eq!(E.to_string(), "E".to_string());
+ assert_eq!(F(3).to_string(), "F(3)".to_string());
+ assert_eq!(G(3, 4).to_string(), "G(3, 4)".to_string());
+ assert_eq!(G(3, 4).to_string(), "G(3, 4)".to_string());
+ assert_eq!(I{ a: 2, b: 4 }.to_string(), "I { a: 2, b: 4 }".to_string());
+ assert_eq!(J(Custom).to_string(), "J(yay)".to_string());
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use std::gc::Gc;
+use std::mem::size_of;
+
+trait Trait {}
+
+fn main() {
+ // Closures - || / proc()
+ assert_eq!(size_of::<proc()>(), size_of::<Option<proc()>>());
+ assert_eq!(size_of::<||>(), size_of::<Option<||>>());
+
+ // Functions
+ assert_eq!(size_of::<fn(int)>(), size_of::<Option<fn(int)>>());
+ assert_eq!(size_of::<extern "C" fn(int)>(), size_of::<Option<extern "C" fn(int)>>());
+
+ // Slices - &str / &[T] / &mut [T]
+ assert_eq!(size_of::<&str>(), size_of::<Option<&str>>());
+ assert_eq!(size_of::<&[int]>(), size_of::<Option<&[int]>>());
+ assert_eq!(size_of::<&mut [int]>(), size_of::<Option<&mut [int]>>());
+
+ // Traits - Box<Trait> / &Trait / &mut Trait
+ assert_eq!(size_of::<Box<Trait>>(), size_of::<Option<Box<Trait>>>());
+ assert_eq!(size_of::<&Trait>(), size_of::<Option<&Trait>>());
+ assert_eq!(size_of::<&mut Trait>(), size_of::<Option<&mut Trait>>());
+
+ // Pointers - Box<T> / Gc<T>
+ assert_eq!(size_of::<Box<int>>(), size_of::<Option<Box<int>>>());
+ assert_eq!(size_of::<Gc<int>>(), size_of::<Option<Gc<int>>>());
+
+}
#![feature(macro_rules)]
use s = std::num::strconv;
-use to_str = std::num::strconv::float_to_str_common;
+use to_string = std::num::strconv::float_to_str_common;
macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()) } })
pub fn main() {
// Basic usage
- t!(to_str(1.2345678e-5f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpDec, false),
+ t!(to_string(1.2345678e-5f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpDec, false),
"1.234568e-5")
// Hexadecimal output
- t!(to_str(7.281738281250e+01f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false),
+ t!(to_string(7.281738281250e+01f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false),
"+1.2345p+6")
- t!(to_str(-1.777768135071e-02f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false),
+ t!(to_string(-1.777768135071e-02f64, 16u, true, s::SignAll, s::DigMax(6), s::ExpBin, false),
"-1.2345p-6")
// Some denormals
- t!(to_str(4.9406564584124654e-324f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false),
+ t!(to_string(4.9406564584124654e-324f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false),
"1p-1074")
- t!(to_str(2.2250738585072009e-308f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false),
+ t!(to_string(2.2250738585072009e-308f64, 10u, true, s::SignNeg, s::DigMax(6), s::ExpBin, false),
"1p-1022")
}
//aux-build:extern-crosscrate-source.rs
-extern crate externcallback = "externcallback#0.1";
+extern crate externcallback;
fn fact(n: uint) -> uint {
unsafe {
pub fn main() {
let arr = [1,2,3];
let struc = Struc {a: 13u8, b: arr, c: 42};
- let s = repr::repr_to_str(&struc);
+ let s = repr::repr_to_string(&struc);
assert_eq!(s, "Struc{a: 13u8, b: [1, 2, 3], c: 42}".to_string());
}
fn main() {
// Generate sieve of Eratosthenes for n up to 1e6
let n = 1000000u;
- let sieve = Bitv::new(n+1, true);
+ let mut sieve = Bitv::with_capacity(n+1, true);
let limit: uint = (n as f32).sqrt() as uint;
for i in range(2, limit+1) {
if sieve[i] {
let mut j = 0;
while i*i + j*i <= n {
- sieve[i*i+j*i] = false;
+ sieve.set(i*i+j*i, false);
j += 1;
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32
+
+#![feature(link_args)]
+
+#[link_args="-lc -lm"]
+#[link_args=" -lc"]
+#[link_args="-lc "]
+extern {}
+
+fn main() {}
mod test {
#[test]
- pub fn trivial_to_str() {
- assert!(lambda.to_str() == "\\")
+ pub fn trivial_to_string() {
+ assert!(lambda.to_string() == "\\")
}
}
enum what { }
-fn what_to_str(x: what) -> String
+fn what_to_string(x: what) -> String
{
match x {
}
let mut table = HashMap::new();
table.insert("one".to_string(), 1i);
table.insert("two".to_string(), 2i);
- assert!(check_strs(table.to_str().as_slice(), "{one: 1, two: 2}") ||
- check_strs(table.to_str().as_slice(), "{two: 2, one: 1}"));
+ assert!(check_strs(table.to_string().as_slice(), "{one: 1, two: 2}") ||
+ check_strs(table.to_string().as_slice(), "{two: 2, one: 1}"));
}
}
}
-// Allows AsciiArt to be converted to a string using the libcore ToStr trait.
+// Allows AsciiArt to be converted to a string using the libcore ToString trait.
// Note that the %s fmt! specifier will not call this automatically.
impl fmt::Show for AsciiArt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn test_ascii_art_ctor() {
let art = AsciiArt(3, 3, '*');
- assert!(check_strs(art.to_str().as_slice(), "...\n...\n..."));
+ assert!(check_strs(art.to_string().as_slice(), "...\n...\n..."));
}
art.add_pt(0, 0);
art.add_pt(0, -10);
art.add_pt(1, 2);
- assert!(check_strs(art.to_str().as_slice(), "*..\n...\n.*."));
+ assert!(check_strs(art.to_string().as_slice(), "*..\n...\n.*."));
}
let mut art = AsciiArt(4, 4, '*');
art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}});
art.add_point(Point {x: 2, y: 2});
- assert!(check_strs(art.to_str().as_slice(), "****\n*..*\n*.**\n****"));
+ assert!(check_strs(art.to_string().as_slice(), "****\n*..*\n*.**\n****"));
}
pub fn main() {
pub fn main() {
trait Text {
- fn to_str(&self) -> String;
+ fn to_string(&self) -> String;
}
fn to_string(t: Box<Text>) {
- println!("{}", t.to_str());
+ println!("{}", t.to_string());
}
}
}
}
-priv fn cmd_to_str(cmd: ~[String]) -> String {
+priv fn cmd_to_string(cmd: ~[String]) -> String {
let mut res = "*".to_string();
- res.push_str(cmd.len().to_str());
+ res.push_str(cmd.len().to_string());
res.push_str("\r\n");
for s in cmd.iter() {
- res.push_str(["$".to_string(), s.len().to_str(), "\r\n".to_string(),
+ res.push_str(["$".to_string(), s.len().to_string(), "\r\n".to_string(),
(*s).clone(), "\r\n".to_string()].concat() );
}
res
}
fn query(cmd: ~[String], sb: TcpSocketBuf) -> Result {
- let cmd = cmd_to_str(cmd);
+ let cmd = cmd_to_string(cmd);
//println!("{}", cmd);
sb.write_str(cmd);
let res = parse_response(@sb as @io::Reader);
}
fn query2(cmd: ~[String]) -> Result {
- let _cmd = cmd_to_str(cmd);
+ let _cmd = cmd_to_string(cmd);
io::with_str_reader("$3\r\nXXX\r\n".to_string())(|sb| {
let res = parse_response(@sb as @io::Reader);
println!("{:?}", res);
type FontTableTag = u32;
trait FontTableTagConversions {
- fn tag_to_str(self);
+ fn tag_to_string(self);
}
impl FontTableTagConversions for FontTableTag {
- fn tag_to_str(self) {
+ fn tag_to_string(self) {
&self;
}
}
pub fn main() {
- 5.tag_to_str();
+ 5.tag_to_string();
}
// except according to those terms.
struct T (&'static [int]);
-static t : T = T (&'static [5, 4, 3]);
+static t : T = T (&[5, 4, 3]);
pub fn main () {
let T(ref v) = t;
assert_eq!(v[0], 5);
static instance: UninterpretedOption_NamePart = UninterpretedOption_NamePart {
name_part: None,
};
- &'static instance
+ &instance
}
}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:issue2378a.rs
-// aux-build:issue2378b.rs
-
-extern crate issue2378a;
-extern crate issue2378b;
-
-use issue2378a::{just};
-use issue2378b::{two_maybes};
-
-pub fn main() {
- let x = two_maybes{a: just(3i), b: just(5i)};
- assert_eq!(x[0u], (3, 5));
-}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let value = Some(1i);
+ assert_eq!(match value {
+ ref a @ Some(_) => a,
+ ref b @ None => b
+ }, &Some(1i));
+ assert_eq!(match value {
+ ref a @ ref _c @ Some(_) => a,
+ ref b @ None => b
+ }, &Some(1i));
+ assert_eq!(match value {
+ _a @ ref c @ Some(_) => c,
+ ref b @ None => b
+ }, &Some(1i));
+ assert_eq!(match "foobarbaz" {
+ _a @ b @ _ => b
+ }, "foobarbaz");
+
+ let a @ b @ c = "foobarbaz";
+ assert_eq!(a, "foobarbaz");
+ assert_eq!(b, "foobarbaz");
+ assert_eq!(c, "foobarbaz");
+ let value = Some(true);
+ let ref a @ b @ ref c = value;
+ assert_eq!(a, &Some(true));
+ assert_eq!(b, Some(true));
+ assert_eq!(c, &Some(true));
+}
}
fn transform(x: Option<int>) -> Option<String> {
- x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_str()) )
+ x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_string()) )
}
pub fn main() {
}
}
-fn to_str(sb: StringBuffer) -> String {
+fn to_string(sb: StringBuffer) -> String {
sb.s
}
};
sb.append("Hello, ");
sb.append("World!");
- let str = to_str(sb);
+ let str = to_string(sb);
assert_eq!(str.as_slice(), "Hello, World!");
}
}
pub fn main() {
- println!("{}", Thingy { x: 1, y: 2 }.to_str());
- println!("{}", PolymorphicThingy { x: Thingy { x: 1, y: 2 } }.to_str());
+ println!("{}", Thingy { x: 1, y: 2 }.to_string());
+ println!("{}", PolymorphicThingy { x: Thingy { x: 1, y: 2 } }.to_string());
}
}
impl ops::Index<bool,int> for Point {
- fn index(&self, x: &bool) -> int {
- if *x { self.x } else { self.y }
+ fn index<'a>(&'a self, x: &bool) -> &'a int {
+ if *x {
+ &self.x
+ } else {
+ &self.y
+ }
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// Test to make sure the destructors run in the right order.
+// Each destructor sets it's tag in the corresponding entry
+// in ORDER matching up to when it ran.
+// Correct order is: matched, inner, outer
+
+static mut ORDER: [uint, ..3] = [0, 0, 0];
+static mut INDEX: uint = 0;
+
+struct A;
+impl Drop for A {
+ fn drop(&mut self) {
+ unsafe {
+ ORDER[INDEX] = 1;
+ INDEX = INDEX + 1;
+ }
+ }
+}
+
+struct B;
+impl Drop for B {
+ fn drop(&mut self) {
+ unsafe {
+ ORDER[INDEX] = 2;
+ INDEX = INDEX + 1;
+ }
+ }
+}
+
+struct C;
+impl Drop for C {
+ fn drop(&mut self) {
+ unsafe {
+ ORDER[INDEX] = 3;
+ INDEX = INDEX + 1;
+ }
+ }
+}
+
+fn main() {
+ {
+ let matched = A;
+ let _outer = C;
+ {
+ match matched {
+ _s => {}
+ }
+ let _inner = B;
+ }
+ }
+ unsafe {
+ assert_eq!(&[1, 2, 3], ORDER.as_slice());
+ }
+}
}
impl<K:PartialEq,V:Clone> Index<K,V> for AssociationList<K,V> {
- fn index(&self, index: &K) -> V {
+ fn index<'a>(&'a self, index: &K) -> &'a V {
for pair in self.pairs.iter() {
if pair.key == *index {
- return pair.value.clone();
+ return &pair.value
}
}
fail!("No value found for key: {:?}", index);
// N.B. This is required because method lookup hasn't been performed so
// we don't know whether the called method takes mutable self, before
// the dereference itself is type-checked (a chicken-and-egg problem).
- (*n).to_str();
+ (*n).to_string();
assert_eq!(n.counts(), (2, 4));
// Mutable deref used for calling a method taking &mut self.
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+ x: int,
+ y: int,
+}
+
+impl Index<int,int> for Foo {
+ fn index<'a>(&'a self, z: &int) -> &'a int {
+ if *z == 0 {
+ &self.x
+ } else {
+ &self.y
+ }
+ }
+}
+
+impl IndexMut<int,int> for Foo {
+ fn index_mut<'a>(&'a mut self, z: &int) -> &'a mut int {
+ if *z == 0 {
+ &mut self.x
+ } else {
+ &mut self.y
+ }
+ }
+}
+
+fn main() {
+ let mut f = Foo {
+ x: 1,
+ y: 2,
+ };
+ assert_eq!(f[1], 2);
+ f[0] = 3;
+ assert_eq!(f[0], 3);
+ {
+ let p = &mut f[1];
+ *p = 4;
+ }
+ {
+ let p = &f[1];
+ assert_eq!(*p, 4);
+ }
+}
+
use std::collections::{ Map, MutableMap};
use std::str::{SendStr, Owned, Slice};
-use std::to_str::ToStr;
+use std::to_str::ToString;
use self::collections::TreeMap;
use std::option::Some;
impl uint_utils for uint {
fn str(&self) -> String {
- self.to_str()
+ self.to_string()
}
fn multi(&self, f: |uint|) {
let mut c = 0u;
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:xcrate_struct_aliases.rs
+extern crate xcrate_struct_aliases;
+
+use xcrate_struct_aliases::{S, S2};
+
+fn main() {
+ let s = S2 {
+ x: 1,
+ y: 2,
+ };
+ match s {
+ S2 {
+ x: x,
+ y: y
+ } => {
+ assert_eq!(x, 1);
+ assert_eq!(y, 2);
+ }
+ }
+}
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S {
+ x: int,
+ y: int,
+}
+
+type S2 = S;
+
+fn main() {
+ let s = S2 {
+ x: 1,
+ y: 2,
+ };
+ match s {
+ S2 {
+ x: x,
+ y: y
+ } => {
+ assert_eq!(x, 1);
+ assert_eq!(y, 2);
+ }
+ }
+}
+
});
assert!(res.is_err());
- let output = reader.read_to_str().unwrap();
+ let output = reader.read_to_string().unwrap();
assert!(output.as_slice().contains("Hello, world!"));
}
iotest!(fn eventual_timeout() {
use native;
let addr = next_test_ip4();
- let host = addr.ip.to_str();
+ let host = addr.ip.to_string();
let port = addr.port;
// Use a native task to receive connections because it turns out libuv is
iotest!(fn timeout_success() {
let addr = next_test_ip4();
- let host = addr.ip.to_str();
+ let host = addr.ip.to_string();
let port = addr.port;
let _l = TcpListener::bind(host.as_slice(), port).unwrap().listen();
for _ in range(0u, 1000) {
let tx = tx.clone();
TaskBuilder::new().stack_size(64 * 1024).spawn(proc() {
- let host = addr.ip.to_str();
+ let host = addr.ip.to_string();
let port = addr.port;
match TcpStream::connect(host.as_slice(), port) {
Ok(stream) => {
let tests = __test::TESTS;
assert!(
- tests.iter().any(|t| t.desc.name.to_str().as_slice() == "shouldignore" &&
+ tests.iter().any(|t| t.desc.name.to_string().as_slice() == "shouldignore" &&
t.desc.ignore));
assert!(
- tests.iter().any(|t| t.desc.name.to_str().as_slice() == "shouldnotignore" &&
+ tests.iter().any(|t| t.desc.name.to_string().as_slice() == "shouldnotignore" &&
!t.desc.ignore));
}
impl to_str for int {
fn to_str_(&self) -> String {
- self.to_str()
+ self.to_string()
}
}
trait to_str {
- fn to_string(&self) -> String;
+ fn to_string_(&self) -> String;
}
impl to_str for int {
- fn to_string(&self) -> String { self.to_str() }
+ fn to_string_(&self) -> String { self.to_string() }
}
impl to_str for String {
- fn to_string(&self) -> String { self.clone() }
+ fn to_string_(&self) -> String { self.clone() }
}
impl to_str for () {
- fn to_string(&self) -> String { "()".to_string() }
+ fn to_string_(&self) -> String { "()".to_string() }
}
trait map<T> {
x.map(|_e| "hi".to_string() )
}
fn bar<U:to_str,T:map<U>>(x: T) -> Vec<String> {
- x.map(|_e| _e.to_string() )
+ x.map(|_e| _e.to_string_() )
}
pub fn main() {
trait to_str {
- fn to_string(&self) -> String;
+ fn to_string_(&self) -> String;
}
impl to_str for int {
- fn to_string(&self) -> String { self.to_str() }
+ fn to_string_(&self) -> String { self.to_string() }
}
impl<T:to_str> to_str for Vec<T> {
- fn to_string(&self) -> String {
+ fn to_string_(&self) -> String {
format!("[{}]",
self.iter()
- .map(|e| e.to_string())
+ .map(|e| e.to_string_())
.collect::<Vec<String>>()
.connect(", "))
}
}
pub fn main() {
- assert!(1.to_string() == "1".to_string());
- assert!((vec!(2i, 3, 4)).to_string() == "[2, 3, 4]".to_string());
+ assert!(1.to_string_() == "1".to_string());
+ assert!((vec!(2i, 3, 4)).to_string_() == "[2, 3, 4]".to_string());
fn indirect<T:to_str>(x: T) -> String {
- format!("{}!", x.to_string())
+ format!("{}!", x.to_string_())
}
assert!(indirect(vec!(10i, 20)) == "[10, 20]!".to_string());
// size of struct may be not equal to size of struct, and
// compiler crashes in internal assertion check.
};
- &'static instance
+ &instance
}
fn non_default_instance() -> &'static Request {
foo: TestSome(0x1020304050607080),
bar: 19,
};
- &'static instance
+ &instance
}
pub fn main() {
// This test checks that the `_` type placeholder works
// correctly for enabling type inference.
-static CONSTEXPR: *const int = &'static 413 as *const _;
+static CONSTEXPR: *const int = &413 as *const _;
pub fn main() {
let x: Vec<_> = range(0u, 5).collect();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test syntax checks for `type` keyword.
+// Test syntax checks for `Sized?` syntax.
-trait T1 for type {}
-pub trait T2 for type {}
-trait T3<X: T1> for type: T2 {}
-trait T4<type X> {}
-trait T5<type X, Y> {}
-trait T6<Y, type X> {}
-trait T7<type X, type Y> {}
-trait T8<type X: T2> {}
-struct S1<type X>;
-enum E<type X> {}
-impl <type X> T1 for S1<X> {}
-fn f<type X>() {}
+trait T1 for Sized? {}
+pub trait T2 for Sized? {}
+trait T3<X: T1> for Sized?: T2 {}
+trait T4<Sized? X> {}
+trait T5<Sized? X, Y> {}
+trait T6<Y, Sized? X> {}
+trait T7<Sized? X, Sized? Y> {}
+trait T8<Sized? X: T2> {}
+struct S1<Sized? X>;
+enum E<Sized? X> {}
+impl <Sized? X> T1 for S1<X> {}
+fn f<Sized? X>() {}
pub fn main() {
}
// Test sized-ness checking in substitution.
// Unbounded.
-fn f1<type X>(x: &X) {
+fn f1<Sized? X>(x: &X) {
f1::<X>(x);
}
fn f2<X>(x: &X) {
}
// Bounded.
-trait T for type {}
-fn f3<type X: T>(x: &X) {
+trait T for Sized? {}
+fn f3<Sized? X: T>(x: &X) {
f3::<X>(x);
}
fn f4<X: T>(x: &X) {
}
// Self type.
-trait T2 for type {
+trait T2 for Sized? {
fn f() -> Box<Self>;
}
struct S;
box S
}
}
-fn f5<type X: T2>(x: &X) {
+fn f5<Sized? X: T2>(x: &X) {
let _: Box<X> = T2::f();
}
fn f6<X: T2>(x: &X) {
let _: Box<X> = T2::f();
}
-trait T3 for type {
+trait T3 for Sized? {
fn f() -> Box<Self>;
}
impl T3 for S {
box S
}
}
-fn f7<type X: T3>(x: &X) {
+fn f7<Sized? X: T3>(x: &X) {
// This is valid, but the unsized bound on X is irrelevant because any type
// which implements T3 must have statically known size.
let _: Box<X> = T3::f();
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
-trait T5<type X> {
+trait T5<Sized? X> {
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
-trait T7<type X: T> {
+trait T7<Sized? X: T> {
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
// The last field in a struct or variant may be unsized
-struct S2<type X> {
+struct S2<Sized? X> {
f: X,
}
-struct S3<type X> {
+struct S3<Sized? X> {
f1: int,
f2: X,
}
-enum E<type X> {
+enum E<Sized? X> {
V1(X),
V2{x: X},
V3(int, X),
#![no_std]
extern crate std;
extern crate zed = "std";
-extern crate bar = "std#0.11.0";
use std::str;
use x = zed::str;
mod baz {
- pub use bar::str;
pub use x = std::str;
}
// except according to those terms.
pub fn main() {
- assert_eq!((vec!(0i, 1)).to_str(), "[0, 1]".to_string());
- assert_eq!((&[1i, 2]).to_str(), "[1, 2]".to_string());
+ assert_eq!((vec!(0i, 1)).to_string(), "[0, 1]".to_string());
+ assert_eq!((&[1i, 2]).to_string(), "[1, 2]".to_string());
let foo = vec!(3i, 4);
let bar = &[4i, 5];
- assert_eq!(foo.to_str(), "[3, 4]".to_string());
- assert_eq!(bar.to_str(), "[4, 5]".to_string());
+ assert_eq!(foo.to_string(), "[3, 4]".to_string());
+ assert_eq!(bar.to_string(), "[4, 5]".to_string());
}