Avoid ever constructing cyclic types in the first place, rather than detecting them in resolve. This simplifies logic elsewhere in the compiler, in particular on the trait reform branch.
r? @pnkfelix or @pcwalton
cc #5527
[wiki]: https://github.com/rust-lang/rust/wiki
+## Getting help and getting involved
+
+The Rust community congregates in a few places:
+
+* [StackOverflow] - Get help here.
+* [/r/rust] - General discussion.
+* [discuss.rust-lang.org] - For development of the Rust language itself.
+
+[StackOverflow]: http://stackoverflow.com/questions/tagged/rust
+[/r/rust]: http://reddit.com/r/rust
+[discuss.rust-lang.org]: http://discuss.rust-lang.org/
+
## License
Rust is primarily distributed under the terms of both the MIT license
| cut -d ' ' -f 2)
case $CFG_CLANG_VERSION in
- (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* | 3.5* )
+ (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* | 3.5* | 3.6*)
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
if [ -z "$CC" ]
then
ifdef CFG_ISCC
-PKG_EXE = dist/$(PKG_NAME)-install.exe
+PKG_EXE = dist/$(PKG_NAME)-$(CFG_BUILD).exe
%.iss: $(S)src/etc/pkg/%.iss
cp $< $@
$(PKG_EXE): rust.iss modpath.iss upgrade.iss LICENSE.txt rust-logo.ico \
$(CSREQ3_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
dist-prepare-win
- $(CFG_PYTHON) $(S)src/etc/copy-runtime-deps.py tmp/dist/win/bin
+ $(CFG_PYTHON) $(S)src/etc/copy-runtime-deps.py tmp/dist/win/bin $(CFG_BUILD)
@$(call E, ISCC: $@)
$(Q)"$(CFG_ISCC)" $<
# Check for the various external utilities for the EPUB/PDF docs:
-ifeq ($(CFG_PDFLATEX),)
- $(info cfg: no pdflatex found, deferring to xelatex)
+ifeq ($(CFG_LUALATEX),)
+ $(info cfg: no lualatex found, deferring to xelatex)
ifeq ($(CFG_XELATEX),)
- $(info cfg: no xelatex found, deferring to lualatex)
- ifeq ($(CFG_LUALATEX),)
- $(info cfg: no lualatex found, disabling LaTeX docs)
+ $(info cfg: no xelatex found, deferring to pdflatex)
+ ifeq ($(CFG_PDFLATEX),)
+ $(info cfg: no pdflatex found, disabling LaTeX docs)
NO_PDF_DOCS = 1
else
- CFG_LATEX := $(CFG_LUALATEX)
+ CFG_LATEX := $(CFG_PDFLATEX)
endif
else
CFG_LATEX := $(CFG_XELATEX)
+ XELATEX = 1
endif
else
- CFG_LATEX := $(CFG_PDFLATEX)
+ CFG_LATEX := $(CFG_LUALATEX)
endif
ifneq ($(NO_PDF_DOCS),1)
ifeq ($$(SHOULD_BUILD_PDF_DOC_$(1)),1)
DOC_TARGETS += doc/$(1).pdf
+ifneq ($(XELATEX),1)
doc/$(1).pdf: doc/$(1).tex
@$$(call E, latex compiler: $$@)
$$(Q)$$(CFG_LATEX) \
-interaction=batchmode \
-output-directory=doc \
$$<
+else
+# The version of xelatex on the snap bots seemingly ingores -output-directory
+# So we'll output to . and move to the doc directory manually.
+# This will leave some intermediate files in the build directory.
+doc/$(1).pdf: doc/$(1).tex
+ @$$(call E, latex compiler: $$@)
+ $$(Q)$$(CFG_LATEX) \
+ -interaction=batchmode \
+ -output-directory=. \
+ $$<
+ $$(Q)mv ./$(1).pdf $$@
+endif # XELATEX
endif # SHOULD_BUILD_PDF_DOCS_$(1)
endif # NO_PDF_DOCS
ifndef CFG_DISABLE_MANAGE_SUBMODULES
# This is a pretty expensive operation but I don't see any way to avoid it
-NEED_GIT_RECONFIG=$(shell cd "$(CFG_SRC_DIR)" && "$(CFG_GIT)" submodule status | grep -c '^\(+\|-\)')
+# NB: This only looks for '+' status (wrong commit checked out), not '-' status
+# (nothing checked out at all). `./configure --{llvm,jemalloc,libuv}-root`
+# will explicitly deinitialize the corresponding submodules, and we don't
+# want to force constant rebuilds in that case.
+NEED_GIT_RECONFIG=$(shell cd "$(CFG_SRC_DIR)" && "$(CFG_GIT)" submodule status | grep -c '^+')
else
NEED_GIT_RECONFIG=0
endif
```
If you have good reason. It's not polite to hold on to ownership you don't
-need, and it can make your lifetimes more complex. Furthermore, you can pass
-either kind of string into `foo` by using `.as_slice()` on any `String` you
-need to pass in, so the `&str` version is more flexible.
+need, and it can make your lifetimes more complex.
+
+## Generic functions
+
+To write a function that's generic over types of strings, use [the `Str`
+trait](http://doc.rust-lang.org/std/str/trait.Str.html):
+
+```{rust}
+fn some_string_length<T: Str>(x: T) -> uint {
+ x.as_slice().len()
+}
+
+fn main() {
+ let s = "Hello, world";
+
+ println!("{}", some_string_length(s));
+
+ let s = "Hello, world".to_string();
+
+ println!("{}", some_string_length(s));
+}
+```
+
+Both of these lines will print `12`.
+
+The only method that the `Str` trait has is `as_slice()`, which gives you
+access to a `&str` value from the underlying string.
## Comparisons
Converting a `String` to a `&str` is cheap, but converting the `&str` to a
`String` involves an allocation.
+## Indexing strings
+
+You may be tempted to try to access a certain character of a `String`, like
+this:
+
+```{rust,ignore}
+let s = "hello".to_string();
+
+println!("{}", s[0]);
+```
+
+This does not compile. This is on purpose. In the world of UTF-8, direct
+indexing is basically never what you want to do. The reason is that each
+character can be a variable number of bytes. This means that you have to iterate
+through the characters anyway, which is a O(n) operation.
+
+To iterate over a string, use the `graphemes()` method on `&str`:
+
+```{rust}
+let s = "αἰθήρ";
+
+for l in s.graphemes(true) {
+ println!("{}", l);
+}
+```
+
+Note that `l` has the type `&str` here, since a single grapheme can consist of
+multiple codepoints, so a `char` wouldn't be appropriate.
+
+This will print out each character in turn, as you'd expect: first "α", then
+"ἰ", etc. You can see that this is different than just the individual bytes.
+Here's a version that prints out each byte:
+
+```{rust}
+let s = "αἰθήρ";
+
+for l in s.bytes() {
+ println!("{}", l);
+}
+```
+
+This will print:
+
+```{notrust,ignore}
+206
+177
+225
+188
+176
+206
+184
+206
+174
+207
+129
+```
+
+Many more bytes than graphemes!
+
# Other Documentation
* [the `&str` API documentation](/std/str/index.html)
Now that you've got your file open, type this in:
-```
+```{rust}
fn main() {
println!("Hello, world!");
}
Success! Let's go over what just happened in detail.
-```
+```{rust}
fn main() {
}
Next up is this line:
-```
+```{rust}
println!("Hello, world!");
```
Could not compile `hello_world`.
```
-Rust will not let us use a value that has not been initialized. So why let us
-declare a binding without initializing it? You'd think our first example would
-have errored. Well, Rust is smarter than that. Before we get to that, let's talk
-about this stuff we've added to `println!`.
+Rust will not let us use a value that has not been initialized. Next, let's
+talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort
available](std/fmt/index.html). For now, we'll just stick to the default:
integers aren't very complicated to print.
-So, we've cleared up all of the confusion around bindings, with one exception:
-why does Rust let us declare a variable binding without an initial value if we
-must initialize the binding before we use it? And how does it know that we have
-or have not initialized the binding? For that, we need to learn our next
-concept: `if`.
-
# If
Rust's take on `if` is not particularly complex, but it's much more like the
If you want something to happen in the `false` case, use an `else`:
-```
+```{rust}
let x = 5i;
if x == 5i {
This is all pretty standard. However, you can also do this:
-```
+```{rust}
let x = 5i;
let y = if x == 5i {
Which we can (and probably should) write like this:
-```
+```{rust}
let x = 5i;
let y = if x == 5i { 10i } else { 15i };
What is this exception that makes us say 'almost?' You saw it already, in this
code:
-```
+```{rust}
let x = 5i;
let y: int = if x == 5i { 10i } else { 15i };
The values in structs are immutable, like other bindings in Rust. However, you
can use `mut` to make them mutable:
-```rust
+```{rust}
struct Point {
x: int,
y: int,
don't:
-```
+```{rust}
struct Color(int, int, int);
struct Point(int, int, int);
```
It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:
-```rust
+```{rust}
struct Color {
red: int,
blue: int,
tuple struct with only one element. We call this a 'newtype,' because it lets
you create a new type that's a synonym for another one:
-```
+```{rust}
struct Inches(int);
let length = Inches(10);
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
groupings with something more powerful. Check it out:
-```rust
+```{rust}
let x = 5i;
match x {
`continue` is similar, but instead of ending the loop, goes to the next
iteration: This will only print the odd numbers:
-```
+```{rust}
for x in range(0i, 10i) {
if x % 2 == 0 { continue; }
Here's how it works:
-```
+```{rust}
struct Circle {
x: f64,
y: f64,
You can also define methods that do not take a `self` parameter. Here's a
pattern that's very common in Rust code:
-```
+```{rust}
struct Circle {
x: f64,
y: f64,
which is considered wildly unsafe and will be
obsoleted by language improvements.
+* `tuple_indexing` - Allows use of tuple indexing (expressions like `expr.0`)
+
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about #[feature] directives which enabled
the new feature (because the directive is no longer necessary). However, if
exactly one argument, while the pattern `C(..)` is type-correct for any enum
variant `C`, regardless of how many arguments `C` has.
-Used inside a vector pattern, `..` stands for any number of elements. This
-wildcard can be used at most once for a given vector, which implies that it
-cannot be used to specifically match elements that are at an unknown distance
-from both ends of a vector, like `[.., 42, ..]`. If followed by a variable name,
-it will bind the corresponding slice to the variable. Example:
+Used inside a vector pattern, `..` stands for any number of elements, when the
+`advanced_slice_patterns` feature gate is turned on. This wildcard can be used
+at most once for a given vector, which implies that it cannot be used to
+specifically match elements that are at an unknown distance from both ends of a
+vector, like `[.., 42, ..]`. If followed by a variable name, it will bind the
+corresponding slice to the variable. Example:
~~~~
+# #![feature(advanced_slice_patterns)]
fn is_symmetric(list: &[uint]) -> bool {
match list {
[] | [_] => true,
- [x, ..inside, y] if x == y => is_symmetric(inside),
+ [x, inside.., y] if x == y => is_symmetric(inside),
_ => false
}
}
[] => 0,
[a] => a * 10,
[a, b] => a * 6 + b * 4,
- [a, b, c, ..rest] => a * 5 + b * 3 + c * 2 + rest.len() as int
+ [a, b, c, rest..] => a * 5 + b * 3 + c * 2 + rest.len() as int
};
~~~~
import snapshot, sys, os, shutil
-def copy_runtime_deps(dest_dir):
- for path in snapshot.get_winnt_runtime_deps():
+def copy_runtime_deps(dest_dir, triple):
+ for path in snapshot.get_winnt_runtime_deps(snapshot.get_platform(triple)):
shutil.copy(path, dest_dir)
lic_dest = os.path.join(dest_dir, "third-party")
shutil.rmtree(lic_dest) # copytree() won't overwrite existing files
shutil.copytree(os.path.join(os.path.dirname(__file__), "third-party"), lic_dest)
-copy_runtime_deps(sys.argv[1])
+copy_runtime_deps(sys.argv[1], sys.argv[2])
"libsync/mpmc_bounded_queue.rs", # BSD
"libsync/mpsc_intrusive.rs", # BSD
"test/bench/shootout-binarytrees.rs", # BSD
+ "test/bench/shootout-chameneos-redux.rs", # BSD
"test/bench/shootout-fannkuch-redux.rs", # BSD
"test/bench/shootout-k-nucleotide.rs", # BSD
"test/bench/shootout-mandelbrot.rs", # BSD
"test/bench/shootout-meteor.rs", # BSD
+ "test/bench/shootout-nbody.rs", # BSD
"test/bench/shootout-pidigits.rs", # BSD
"test/bench/shootout-regex-dna.rs", # BSD
+ "test/bench/shootout-reverse-complement.rs", # BSD
"test/bench/shootout-threadring.rs", # BSD
]
#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
#define CFG_RELEASE GetEnv("CFG_RELEASE")
#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME")
+#define CFG_BUILD GetEnv("CFG_BUILD")
[Setup]
OutputDir=.\dist\
SourceDir=.\
-OutputBaseFilename={#CFG_PACKAGE_NAME}-install
+OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD}
DefaultDirName={pf32}\Rust
Compression=lzma2/ultra
"freebsd": ["bin/rustc"],
}
-winnt_runtime_deps = ["libgcc_s_dw2-1.dll",
- "libstdc++-6.dll"]
+winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll",
+ "libstdc++-6.dll"]
+winnt_runtime_deps_64 = ["libgcc_s_seh-1.dll",
+ "libstdc++-6.dll"]
def parse_line(n, line):
global snapshotfile
return scrub(h.hexdigest())
# Returns a list of paths of Rust's system runtime dependencies
-def get_winnt_runtime_deps():
+def get_winnt_runtime_deps(platform):
+ if platform == "winnt-x86_64":
+ deps = winnt_runtime_deps_64
+ else:
+ deps = winnt_runtime_deps_32
runtime_deps = []
- path_dirs = os.environ["PATH"].split(';')
- for name in winnt_runtime_deps:
+ path_dirs = os.environ["PATH"].split(os.pathsep)
+ for name in deps:
for dir in path_dirs:
matches = glob.glob(os.path.join(dir, name))
if matches:
"Please make a clean build." % "\n ".join(matches))
if kernel=="winnt":
- for path in get_winnt_runtime_deps():
+ for path in get_winnt_runtime_deps(platform):
tar.add(path, "rust-stage0/bin/" + os.path.basename(path))
tar.add(os.path.join(os.path.dirname(__file__), "third-party"),
"rust-stage0/bin/third-party")
-Subproject commit 024c67ad651e1a3ca228936c4cfb13a37329baf2
+Subproject commit aae04170ccbfeea620502106b581c3c216cd132a
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
// and `nonnull`
-use core::ptr::RawPtr;
#[cfg(not(test))] use core::raw;
#[cfg(stage0, not(test))] use util;
/// the value returned by `usable_size` for the requested size.
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
- // FIXME(14395) This is only required for DST ~[T], it should be removed once
- // we fix that representation to not use null pointers.
- if ptr.is_null() {
- return;
- }
imp::deallocate(ptr, size, align)
}
alloc as *mut u8
}
+// The minimum alignment guaranteed by the architecture. This value is used to
+// add fast paths for low alignment values. In practice, the alignment is a
+// constant at the call site and the branch will be optimized out.
+#[cfg(target_arch = "arm")]
+#[cfg(target_arch = "mips")]
+#[cfg(target_arch = "mipsel")]
+static MIN_ALIGN: uint = 8;
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "x86_64")]
+static MIN_ALIGN: uint = 16;
+
#[cfg(jemalloc)]
mod imp {
use core::option::{None, Option};
use core::ptr::{RawPtr, mut_null, null};
use core::num::Int;
use libc::{c_char, c_int, c_void, size_t};
+ use super::MIN_ALIGN;
#[link(name = "jemalloc", kind = "static")]
#[cfg(not(test))]
flags: c_int) -> *mut c_void;
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
flags: c_int) -> size_t;
+ #[cfg(stage0)]
fn je_dallocx(ptr: *mut c_void, flags: c_int);
+ #[cfg(not(stage0))]
+ fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
*const c_char)>,
#[inline(always)]
fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }
+ #[inline(always)]
+ fn align_to_flags(align: uint) -> c_int {
+ if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
+ }
+
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
- let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
+ let flags = align_to_flags(align);
+ let ptr = je_mallocx(size as size_t, flags) as *mut u8;
if ptr.is_null() {
::oom()
}
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
_old_size: uint) -> *mut u8 {
- let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
- mallocx_align(align)) as *mut u8;
+ let flags = align_to_flags(align);
+ let ptr = je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8;
if ptr.is_null() {
::oom()
}
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
_old_size: uint) -> bool {
- je_xallocx(ptr as *mut c_void, size as size_t, 0,
- mallocx_align(align)) == size as size_t
+ let flags = align_to_flags(align);
+ je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) == size as size_t
}
#[inline]
+ #[cfg(stage0)]
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
- je_dallocx(ptr as *mut c_void, mallocx_align(align))
+ let flags = align_to_flags(align);
+ je_dallocx(ptr as *mut c_void, flags)
+ }
+
+ #[inline]
+ #[cfg(not(stage0))]
+ pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
+ let flags = align_to_flags(align);
+ je_sdallocx(ptr as *mut c_void, size as size_t, flags)
}
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
- unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
+ let flags = align_to_flags(align);
+ unsafe { je_nallocx(size as size_t, flags) as uint }
}
pub fn stats_print() {
use core::ptr;
use libc;
use libc_heap;
+ use super::MIN_ALIGN;
extern {
fn posix_memalign(memptr: *mut *mut libc::c_void,
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
- // The posix_memalign manpage states
- //
- // alignment [...] must be a power of and a multiple of
- // sizeof(void *)
- //
- // The `align` parameter to this function is the *minimum* alignment for
- // a block of memory, so we special case everything under `*uint` to
- // just pass it to malloc, which is guaranteed to align to at least the
- // size of `*uint`.
- if align < mem::size_of::<uint>() {
+ if align <= MIN_ALIGN {
libc_heap::malloc_raw(size)
} else {
let mut out = 0 as *mut libc::c_void;
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
old_size: uint) -> *mut u8 {
- let new_ptr = allocate(size, align);
- ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
- deallocate(ptr, old_size, align);
- return new_ptr;
+ if align <= MIN_ALIGN {
+ libc_heap::realloc_raw(ptr, size)
+ } else {
+ let new_ptr = allocate(size, align);
+ ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
+ deallocate(ptr, old_size, align);
+ new_ptr
+ }
}
#[inline]
size
}
- pub fn stats_print() {
- }
+ pub fn stats_print() {}
}
#[cfg(not(jemalloc), windows)]
mod imp {
use libc::{c_void, size_t};
+ use libc;
+ use libc_heap;
use core::ptr::RawPtr;
+ use super::MIN_ALIGN;
extern {
fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
- let ptr = _aligned_malloc(size as size_t, align as size_t);
- if ptr.is_null() {
- ::oom();
+ if align <= MIN_ALIGN {
+ libc_heap::malloc_raw(size)
+ } else {
+ let ptr = _aligned_malloc(size as size_t, align as size_t);
+ if ptr.is_null() {
+ ::oom();
+ }
+ ptr as *mut u8
}
- ptr as *mut u8
}
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
_old_size: uint) -> *mut u8 {
- let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
- align as size_t);
- if ptr.is_null() {
- ::oom();
+ if align <= MIN_ALIGN {
+ libc_heap::realloc_raw(ptr, size)
+ } else {
+ let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
+ align as size_t);
+ if ptr.is_null() {
+ ::oom();
+ }
+ ptr as *mut u8
}
- ptr as *mut u8
}
#[inline]
}
#[inline]
- pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
- _aligned_free(ptr as *mut c_void)
+ pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
+ if align <= MIN_ALIGN {
+ libc::free(ptr as *mut libc::c_void)
+ } else {
+ _aligned_free(ptr as *mut c_void)
+ }
}
#[inline]
use self::test::Bencher;
use super::{Arena, TypedArena};
+ #[allow(dead_code)]
struct Point {
x: int,
y: int,
})
}
+ #[allow(dead_code)]
struct Noncopy {
string: String,
array: Vec<int>,
}
#[test]
+ #[allow(deprecated)]
fn test_tailn() {
let mut a = vec![11i, 12, 13];
let b: &[int] = &[11, 12, 13];
#[test]
#[should_fail]
+ #[allow(deprecated)]
fn test_tailn_empty() {
let a: Vec<int> = vec![];
a.tailn(2);
#[test]
#[should_fail]
+ #[allow(deprecated)]
fn test_initn_empty() {
let a: Vec<int> = vec![];
a.as_slice().initn(2);
}
#[test]
+ #[allow(deprecated)]
fn test_unshift() {
let mut x = vec![1i, 2, 3];
x.unshift(0);
}
#[test]
+ #[allow(deprecated)]
fn test_shift_ref() {
let mut x: &[int] = [1, 2, 3, 4, 5];
let h = x.shift_ref();
}
#[test]
+ #[allow(deprecated)]
fn test_pop_ref() {
let mut x: &[int] = [1, 2, 3, 4, 5];
let h = x.pop_ref();
}
#[test]
+ #[allow(deprecated)]
fn test_mut_shift_ref() {
let mut x: &mut [int] = [1, 2, 3, 4, 5];
let h = x.mut_shift_ref();
}
#[test]
+ #[allow(deprecated)]
fn test_mut_pop_ref() {
let mut x: &mut [int] = [1, 2, 3, 4, 5];
let h = x.mut_pop_ref();
b.iter(|| {
v.sort();
});
- b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
+ b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64;
}
type BigSortable = (u64,u64,u64,u64);
b.iter(|| {
v.sort();
});
- b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
+ b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64;
}
}
/// Arguments structure. The compiler inserts an `unsafe` block to call this,
/// which is valid because the compiler performs all necessary validation to
/// ensure that the resulting call to format/write would be safe.
+ #[cfg(not(stage0))]
+ #[doc(hidden)] #[inline]
+ pub unsafe fn new<'a>(pieces: &'static [&'static str],
+ args: &'a [Argument<'a>]) -> Arguments<'a> {
+ Arguments {
+ pieces: mem::transmute(pieces),
+ fmt: None,
+ args: args
+ }
+ }
+
+ /// This function is used to specify nonstandard formatting parameters.
+ /// The `pieces` array must be at least as long as `fmt` to construct
+ /// a valid Arguments structure.
+ #[cfg(not(stage0))]
+ #[doc(hidden)] #[inline]
+ pub unsafe fn with_placeholders<'a>(pieces: &'static [&'static str],
+ fmt: &'static [rt::Argument<'static>],
+ args: &'a [Argument<'a>]) -> Arguments<'a> {
+ Arguments {
+ pieces: mem::transmute(pieces),
+ fmt: Some(mem::transmute(fmt)),
+ args: args
+ }
+ }
+
+ #[cfg(stage0)]
#[doc(hidden)] #[inline]
pub unsafe fn new<'a>(fmt: &'static [rt::Piece<'static>],
args: &'a [Argument<'a>]) -> Arguments<'a> {
/// and pass it to a function or closure, passed as the first argument. The
/// macro validates the format string at compile-time so usage of the `write`
/// and `format` functions can be safely performed.
+#[cfg(not(stage0))]
+pub struct Arguments<'a> {
+ // Format string pieces to print.
+ pieces: &'a [&'a str],
+
+ // Placeholder specs, or `None` if all specs are default (as in "{}{}").
+ fmt: Option<&'a [rt::Argument<'a>]>,
+
+ // Dynamic arguments for interpolation, to be interleaved with string
+ // pieces. (Every argument is preceded by a string piece.)
+ args: &'a [Argument<'a>],
+}
+
+#[cfg(stage0)] #[doc(hidden)]
pub struct Arguments<'a> {
fmt: &'a [rt::Piece<'a>],
args: &'a [Argument<'a>],
secret_upper_exp, UpperExp;
}
+#[cfg(not(stage0))]
+static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument {
+ position: rt::ArgumentNext,
+ format: rt::FormatSpec {
+ fill: ' ',
+ align: rt::AlignUnknown,
+ flags: 0,
+ precision: rt::CountImplied,
+ width: rt::CountImplied,
+ }
+};
+
/// The `write` function takes an output stream, a precompiled format string,
/// and a list of arguments. The arguments will be formatted according to the
/// specified format string into the output stream provided.
///
/// * output - the buffer to write output to
/// * args - the precompiled arguments generated by `format_args!`
+#[cfg(not(stage0))]
+pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
+ let mut formatter = Formatter {
+ flags: 0,
+ width: None,
+ precision: None,
+ buf: output,
+ align: rt::AlignUnknown,
+ fill: ' ',
+ args: args.args,
+ curarg: args.args.iter(),
+ };
+
+ let mut pieces = args.pieces.iter();
+
+ match args.fmt {
+ None => {
+ // We can use default formatting parameters for all arguments.
+ for _ in range(0, args.args.len()) {
+ try!(formatter.buf.write(pieces.next().unwrap().as_bytes()));
+ try!(formatter.run(&DEFAULT_ARGUMENT));
+ }
+ }
+ Some(fmt) => {
+ // Every spec has a corresponding argument that is preceded by
+ // a string piece.
+ for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
+ try!(formatter.buf.write(piece.as_bytes()));
+ try!(formatter.run(arg));
+ }
+ }
+ }
+
+ // There can be only one trailing string piece left.
+ match pieces.next() {
+ Some(piece) => {
+ try!(formatter.buf.write(piece.as_bytes()));
+ }
+ None => {}
+ }
+
+ Ok(())
+}
+
+#[cfg(stage0)] #[doc(hidden)]
pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
let mut formatter = Formatter {
flags: 0,
// First up is the collection of functions used to execute a format string
// at runtime. This consumes all of the compile-time statics generated by
// the format! syntax extension.
+ #[cfg(not(stage0))]
+ fn run(&mut self, arg: &rt::Argument) -> Result {
+ // Fill in the format parameters into the formatter
+ self.fill = arg.format.fill;
+ self.align = arg.format.align;
+ self.flags = arg.format.flags;
+ self.width = self.getcount(&arg.format.width);
+ self.precision = self.getcount(&arg.format.precision);
+
+ // Extract the correct argument
+ let value = match arg.position {
+ rt::ArgumentNext => { *self.curarg.next().unwrap() }
+ rt::ArgumentIs(i) => self.args[i],
+ };
+
+ // Then actually do some printing
+ (value.formatter)(value.value, self)
+ }
+ #[cfg(stage0)] #[doc(hidden)]
fn run(&mut self, piece: &rt::Piece) -> Result {
match *piece {
rt::String(s) => self.buf.write(s.as_bytes()),
//! These definitions are similar to their `ct` equivalents, but differ in that
//! these can be statically allocated and are slightly optimized for the runtime
-
+#[cfg(stage0)]
#[doc(hidden)]
pub enum Piece<'a> {
String(&'a str),
/// Creates a new iterator that produces an infinite sequence of
/// repeated applications of the given function `f`.
#[allow(visible_private_types)]
-pub fn iterate<'a, T: Clone>(f: |T|: 'a -> T, seed: T) -> Iterate<'a, T> {
+pub fn iterate<'a, T: Clone>(seed: T, f: |T|: 'a -> T) -> Iterate<'a, T> {
Unfold::new((f, Some(seed), true), |st| {
let &(ref mut f, ref mut val, ref mut first) = st;
if *first {
*
*/
+use kinds::Sized;
+
/**
*
* The `Drop` trait is used to run some code when a value goes out of scope. This
* ```
*/
#[lang="deref"]
-pub trait Deref<Result> {
+pub trait Deref<Sized? Result> {
/// The method called to dereference a value
fn deref<'a>(&'a self) -> &'a Result;
}
* ```
*/
#[lang="deref_mut"]
-pub trait DerefMut<Result>: Deref<Result> {
+pub trait DerefMut<Sized? Result>: Deref<Result> {
/// The method called to mutably dereference a value
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
}
}
#[test]
-fn any_as_ref() {
+fn any_downcast_ref() {
let a = &5u as &Any;
- match a.as_ref::<uint>() {
+ match a.downcast_ref::<uint>() {
Some(&5) => {}
x => fail!("Unexpected value {}", x)
}
- match a.as_ref::<Test>() {
+ match a.downcast_ref::<Test>() {
None => {}
x => fail!("Unexpected value {}", x)
}
}
#[test]
-fn any_as_mut() {
+fn any_downcast_mut() {
let mut a = 5u;
let mut b = box 7u;
let tmp: &mut uint = &mut *b;
let b_r = tmp as &mut Any;
- match a_r.as_mut::<uint>() {
+ match a_r.downcast_mut::<uint>() {
Some(x) => {
assert_eq!(*x, 5u);
*x = 612;
x => fail!("Unexpected value {}", x)
}
- match b_r.as_mut::<uint>() {
+ match b_r.downcast_mut::<uint>() {
Some(x) => {
assert_eq!(*x, 7u);
*x = 413;
x => fail!("Unexpected value {}", x)
}
- match a_r.as_mut::<Test>() {
+ match a_r.downcast_mut::<Test>() {
None => (),
x => fail!("Unexpected value {}", x)
}
- match b_r.as_mut::<Test>() {
+ match b_r.downcast_mut::<Test>() {
None => (),
x => fail!("Unexpected value {}", x)
}
- match a_r.as_mut::<uint>() {
+ match a_r.downcast_mut::<uint>() {
Some(&612) => {}
x => fail!("Unexpected value {}", x)
}
- match b_r.as_mut::<uint>() {
+ match b_r.downcast_mut::<uint>() {
Some(&413) => {}
x => fail!("Unexpected value {}", x)
}
#[bench]
-fn bench_as_ref(b: &mut Bencher) {
+fn bench_downcast_ref(b: &mut Bencher) {
b.iter(|| {
let mut x = 0i;
let mut y = &mut x as &mut Any;
test::black_box(&mut y);
- test::black_box(y.as_ref::<int>() == Some(&0));
+ test::black_box(y.downcast_ref::<int>() == Some(&0));
});
}
// except according to those terms.
mod num;
+
+#[test]
+fn test_format_flags() {
+ // No residual flags left by pointer formatting
+ let p = "".as_ptr();
+ assert_eq!(format!("{:p} {:x}", p, 16u), format!("{:p} 10", p));
+}
#[test]
fn test_iterate() {
- let mut it = iterate(|x| x * 2, 1u);
+ let mut it = iterate(1u, |x| x * 2);
assert_eq!(it.next(), Some(1u));
assert_eq!(it.next(), Some(2u));
assert_eq!(it.next(), Some(4u));
}
#[test]
+#[allow(deprecated)]
fn test_option_while_some() {
let mut i = 0i;
Some(10i).while_some(|j| {
}
#[test]
+#[allow(deprecated)]
fn test_filtered() {
let some_stuff = Some(42i);
let modified_stuff = some_stuff.filtered(|&x| {x < 10});
}
#[test]
+#[allow(deprecated)]
fn test_collect() {
let v: Option<Vec<int>> = collect(range(0i, 0)
.map(|_| Some(0i)));
}
#[test]
+#[allow(deprecated)]
fn test_collect() {
let v: Result<Vec<int>, ()> = collect(range(0i, 0).map(|_| Ok::<int, ()>(0)));
assert!(v == Ok(vec![]));
}
#[cfg(test)]
+#[allow(dead_code)]
struct P {a: int, b: f64}
#[test]
id_name(n)
}
fn node_label(&'a self, n: &Node) -> LabelText<'a> {
- match self.node_labels.get(*n) {
- &Some(ref l) => LabelStr(str::Slice(l.as_slice())),
- &None => LabelStr(id_name(n).name()),
+ match self.node_labels[*n] {
+ Some(ref l) => LabelStr(str::Slice(l.as_slice())),
+ None => LabelStr(id_name(n).name()),
}
}
fn edge_label(&'a self, e: & &'a Edge) -> LabelText<'a> {
// Regression test that the `start` task entrypoint can
// contain dtors that use task resources
run(proc() {
+ #[allow(dead_code)]
struct S { field: () }
impl Drop for S {
//! Blocking posix-based file I/O
use alloc::arc::Arc;
-use libc::{c_int, c_void};
-use libc;
+use libc::{mod, c_int, c_void};
use std::c_str::CString;
use std::mem;
-use std::rt::rtio;
-use std::rt::rtio::IoResult;
+use std::rt::rtio::{mod, IoResult};
use io::{retry, keep_going};
use io::util;
let ret = retry(|| unsafe {
libc::read(self.fd(),
buf.as_mut_ptr() as *mut libc::c_void,
- buf.len() as libc::size_t) as libc::c_int
+ buf.len() as libc::size_t)
});
if ret == 0 {
Err(util::eof())
match retry(|| unsafe {
libc::pread(self.fd(), buf.as_ptr() as *mut _,
buf.len() as libc::size_t,
- offset as libc::off_t) as libc::c_int
+ offset as libc::off_t)
}) {
-1 => Err(super::last_error()),
n => Ok(n as int)
super::mkerr_libc(retry(|| unsafe {
libc::pwrite(self.fd(), buf.as_ptr() as *const _,
buf.len() as libc::size_t, offset as libc::off_t)
- } as c_int))
+ }))
}
fn seek(&mut self, pos: i64, whence: rtio::SeekStyle) -> IoResult<u64> {
let whence = match whence {
#![allow(non_snake_case)]
-use libc::c_int;
-use libc;
+use libc::{mod, c_int};
use std::c_str::CString;
use std::os;
-use std::rt::rtio;
-use std::rt::rtio::{IoResult, IoError};
+use std::rt::rtio::{mod, IoResult, IoError};
+use std::num;
// Local re-exports
pub use self::file::FileDesc;
}
// unix has nonzero values as errors
-fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
- if ret != 0 {
+fn mkerr_libc <Int: num::Zero>(ret: Int) -> IoResult<()> {
+ if !ret.is_zero() {
Err(last_error())
} else {
Ok(())
#[cfg(windows)]
#[inline]
-fn retry(f: || -> libc::c_int) -> libc::c_int {
- loop {
- match f() {
- -1 if os::errno() as int == libc::WSAEINTR as int => {}
- n => return n,
- }
- }
-}
+fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
#[cfg(unix)]
#[inline]
-fn retry(f: || -> libc::c_int) -> libc::c_int {
+fn retry<I: PartialEq + num::One + Neg<I>> (f: || -> I) -> I {
+ let minus_one = -num::one::<I>();
loop {
- match f() {
- -1 if os::errno() as int == libc::EINTR as int => {}
- n => return n,
- }
+ let n = f();
+ if n == minus_one && os::errno() == libc::EINTR as int { }
+ else { return n }
}
}
+
fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
let origamt = data.len();
let mut data = data.as_ptr();
let mut amt = origamt;
while amt > 0 {
- let ret = retry(|| f(data, amt) as libc::c_int);
+ let ret = retry(|| f(data, amt));
if ret == 0 {
break
} else if ret != -1 {
amt -= ret as uint;
data = unsafe { data.offset(ret as int) };
} else {
- return ret as i64;
+ return ret;
}
}
return (origamt - amt) as i64;
use std::mem;
use std::ptr;
use std::rt::mutex;
-use std::rt::rtio;
-use std::rt::rtio::{IoResult, IoError};
+use std::rt::rtio::{mod, IoResult, IoError};
use std::sync::atomic;
use super::{retry, keep_going};
write(false, inner, len)
});
} else {
- ret = retry(|| {
- write(false, buf.as_ptr(), buf.len()) as libc::c_int
- }) as i64;
+ ret = retry(|| { write(false, buf.as_ptr(), buf.len()) });
if ret > 0 { written = ret as uint; }
}
}
let _guard = lock();
let ptr = buf.slice_from(written).as_ptr();
let len = buf.len() - written;
- match retry(|| write(deadline.is_some(), ptr, len) as libc::c_int) {
+ match retry(|| write(deadline.is_some(), ptr, len)) {
-1 if util::wouldblock() => {}
-1 => return Err(os::last_error()),
n => { written += n as uint; }
#[test]
fn test_checked_add() {
for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigUint::from_slice(a_vec);
+ let b = BigUint::from_slice(b_vec);
+ let c = BigUint::from_slice(c_vec);
assert!(a.checked_add(&b).unwrap() == c);
assert!(b.checked_add(&a).unwrap() == c);
#[test]
fn test_checked_sub() {
for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigUint::from_slice(a_vec);
+ let b = BigUint::from_slice(b_vec);
+ let c = BigUint::from_slice(c_vec);
assert!(c.checked_sub(&a).unwrap() == b);
assert!(c.checked_sub(&b).unwrap() == a);
#[test]
fn test_checked_mul() {
for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigUint::from_slice(a_vec);
+ let b = BigUint::from_slice(b_vec);
+ let c = BigUint::from_slice(c_vec);
assert!(a.checked_mul(&b).unwrap() == c);
assert!(b.checked_mul(&a).unwrap() == c);
}
for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
- let d = BigUint::from_slice(dVec);
+ let (a_vec, b_vec, c_vec, d_vec) = *elm;
+ let a = BigUint::from_slice(a_vec);
+ let b = BigUint::from_slice(b_vec);
+ let c = BigUint::from_slice(c_vec);
+ let d = BigUint::from_slice(d_vec);
assert!(a == b.checked_mul(&c).unwrap() + d);
assert!(a == c.checked_mul(&b).unwrap() + d);
#[test]
fn test_checked_div() {
for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigUint::from_slice(a_vec);
+ let b = BigUint::from_slice(b_vec);
+ let c = BigUint::from_slice(c_vec);
if !a.is_zero() {
assert!(c.checked_div(&a).unwrap() == b);
#[test]
fn test_checked_add() {
for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigInt::from_slice(Plus, a_vec);
+ let b = BigInt::from_slice(Plus, b_vec);
+ let c = BigInt::from_slice(Plus, c_vec);
assert!(a.checked_add(&b).unwrap() == c);
assert!(b.checked_add(&a).unwrap() == c);
#[test]
fn test_checked_sub() {
for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigInt::from_slice(Plus, a_vec);
+ let b = BigInt::from_slice(Plus, b_vec);
+ let c = BigInt::from_slice(Plus, c_vec);
assert!(c.checked_sub(&a).unwrap() == b);
assert!(c.checked_sub(&b).unwrap() == a);
#[test]
fn test_checked_mul() {
for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigInt::from_slice(Plus, a_vec);
+ let b = BigInt::from_slice(Plus, b_vec);
+ let c = BigInt::from_slice(Plus, c_vec);
assert!(a.checked_mul(&b).unwrap() == c);
assert!(b.checked_mul(&a).unwrap() == c);
}
for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
- let d = BigInt::from_slice(Plus, dVec);
+ let (a_vec, b_vec, c_vec, d_vec) = *elm;
+ let a = BigInt::from_slice(Plus, a_vec);
+ let b = BigInt::from_slice(Plus, b_vec);
+ let c = BigInt::from_slice(Plus, c_vec);
+ let d = BigInt::from_slice(Plus, d_vec);
assert!(a == b.checked_mul(&c).unwrap() + d);
assert!(a == c.checked_mul(&b).unwrap() + d);
#[test]
fn test_checked_div() {
for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
+ let (a_vec, b_vec, c_vec) = *elm;
+ let a = BigInt::from_slice(Plus, a_vec);
+ let b = BigInt::from_slice(Plus, b_vec);
+ let c = BigInt::from_slice(Plus, c_vec);
if !a.is_zero() {
assert!(c.checked_div(&a).unwrap() == b);
use serialize::{Encodable, Decodable};
- use std::io::{IoError, IoResult, SeekStyle};
- use std::io;
use std::option::{None, Option, Some};
- use std::slice;
#[test]
fn test_vuint_at() {
#[cfg(test)]
mod test {
- use core::option::{Some, None};
- use core::iter::Iterator;
use core::collections::Collection;
use core::str::StrSlice;
use core::slice::{MutableSlice, ImmutableSlice};
("rustc_diagnostic_macros", Active),
("unboxed_closures", Active),
("import_shadowing", Active),
+ ("advanced_slice_patterns", Active),
+ ("tuple_indexing", Active),
// if you change this list without updating src/doc/rust.md, cmr will be sad
"unboxed closures are a work-in-progress \
feature with known bugs");
}
+ ast::ExprTupField(..) => {
+ self.gate_feature("tuple_indexing",
+ e.span,
+ "tuple indexing is experimental");
+ }
_ => {}
}
visit::walk_expr(self, e, ());
}
}
+ fn visit_pat(&mut self, pattern: &ast::Pat, (): ()) {
+ match pattern.node {
+ ast::PatVec(_, Some(_), ref last) if !last.is_empty() => {
+ self.gate_feature("advanced_slice_patterns",
+ pattern.span,
+ "multiple-element slice matches anywhere \
+ but at the end of a slice (e.g. \
+ `[0, ..xs, 0]` are experimental")
+ }
+ _ => {}
+ }
+ visit::walk_pat(self, pattern, ())
+ }
+
fn visit_fn(&mut self,
fn_kind: &visit::FnKind,
fn_decl: &ast::FnDecl,
self.sess.span_note(e.span, "expression");
visit::walk_expr(self, e, ());
}
+
+ fn visit_mac(&mut self, macro: &ast::Mac, e: ()) {
+ visit::walk_mac(self, macro, e);
+ }
}
pub fn run(sess: &Session, krate: &ast::Crate) {
// Add a special __test module to the crate that will contain code
// generated for the test harness
- let (mod_, reexport) = mk_test_module(&self.cx, &self.cx.reexport_test_harness_main);
+ let (mod_, reexport) = mk_test_module(&mut self.cx);
folded.module.items.push(mod_);
match reexport {
Some(re) => folded.module.view_items.push(re),
}
}
-fn mk_test_module(cx: &TestCtxt, reexport_test_harness_main: &Option<InternedString>)
- -> (Gc<ast::Item>, Option<ast::ViewItem>) {
+fn mk_test_module(cx: &mut TestCtxt) -> (Gc<ast::Item>, Option<ast::ViewItem>) {
// Link to test crate
let view_items = vec!(mk_std(cx));
// The synthesized main function which will call the console test runner
// with our list of tests
- let mainfn = (quote_item!(&cx.ext_cx,
+ let mainfn = (quote_item!(&mut cx.ext_cx,
pub fn main() {
#![main]
use std::slice::Slice;
vis: ast::Public,
span: DUMMY_SP,
};
- let reexport = reexport_test_harness_main.as_ref().map(|s| {
+ let reexport = cx.reexport_test_harness_main.as_ref().map(|s| {
// building `use <ident> = __test::main`
let reexport_ident = token::str_to_ident(s.get());
extern crate getopts;
extern crate graphviz;
extern crate libc;
-extern crate "rustc_llvm" as llvm;
-extern crate "rustc_back" as rustc_back;
+extern crate rustc_llvm;
+extern crate rustc_back;
extern crate serialize;
extern crate rbml;
extern crate time;
#[cfg(test)]
extern crate test;
+pub use rustc_llvm as llvm;
+
mod diagnostics;
pub mod back {
ast::ExprLit(lit) => {
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
ty::ty_int(t) => {
- let int_type = if t == ast::TyI {
- cx.sess().targ_cfg.int_type
- } else { t };
- let (min, max) = int_ty_range(int_type);
- let mut lit_val: i64 = match lit.node {
+ match lit.node {
ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
- if v > i64::MAX as u64{
+ let int_type = if t == ast::TyI {
+ cx.sess().targ_cfg.int_type
+ } else { t };
+ let (min, max) = int_ty_range(int_type);
+ let negative = self.negated_expr_id == e.id;
+
+ if (negative && v > (min.abs() as u64)) ||
+ (!negative && v > (max.abs() as u64)) {
cx.span_lint(TYPE_OVERFLOW, e.span,
"literal out of range for its type");
return;
}
- v as i64
- }
- ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
- ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => {
- -(v as i64)
}
_ => fail!()
};
- if self.negated_expr_id == e.id {
- lit_val *= -1;
- }
- if lit_val < min || lit_val > max {
- cx.span_lint(TYPE_OVERFLOW, e.span,
- "literal out of range for its type");
- }
},
ty::ty_uint(t) => {
let uint_type = if t == ast::TyU {
ast::ExprUnary(_, ref x) |
ast::ExprCast(ref x, _) |
ast::ExprField(ref x, _, _) |
+ ast::ExprTupField(ref x, _, _) |
ast::ExprIndex(ref x, _) => {
// &X { y: 1 }, X { y: 1 }.y
contains_exterior_struct_lit(&**x)
#[test]
fn test_basic() {
let cx = mk_ctxt();
- roundtrip(quote_item!(cx,
+ roundtrip(quote_item!(&cx,
fn foo() {}
));
}
#[test]
fn test_smalltalk() {
let cx = mk_ctxt();
- roundtrip(quote_item!(cx,
+ roundtrip(quote_item!(&cx,
fn foo() -> int { 3 + 4 } // first smalltalk program ever executed.
));
}
#[test]
fn test_more() {
let cx = mk_ctxt();
- roundtrip(quote_item!(cx,
+ roundtrip(quote_item!(&cx,
fn foo(x: uint, y: uint) -> uint {
let z = x + y;
return z;
).unwrap();
let item_in = e::IIItemRef(&*item);
let item_out = simplify_ast(item_in);
- let item_exp = ast::IIItem(quote_item!(cx,
+ let item_exp = ast::IIItem(quote_item!(&cx,
fn new_int_alist<B>() -> alist<int, B> {
return alist {eq_fn: eq_int, data: Vec::new()};
}
out.push_str(token::get_name(fname).get());
}
mc::PositionalField(idx) => {
- out.push_char('#'); // invent a notation here
+ out.push_char('.');
out.push_str(idx.to_string().as_slice());
}
}
ast::ExprCast(e, _) |
ast::ExprUnary(_, e) |
ast::ExprParen(e) |
- ast::ExprField(e, _, _) => {
+ ast::ExprField(e, _, _) |
+ ast::ExprTupField(e, _, _) => {
self.straightline(expr, pred, [e])
}
ExprAddrOf(MutImmutable, _) |
ExprParen(..) |
ExprField(..) |
+ ExprTupField(..) |
ExprIndex(..) |
ExprTup(..) |
ExprRepeat(..) |
}
match e.node {
- ast::ExprField(..) | ast::ExprVec(..) |
+ ast::ExprField(..) | ast::ExprTupField(..) | ast::ExprVec(..) |
ast::ExprBlock(..) | ast::ExprTup(..) => {
visit::walk_expr(self, e, is_const);
}
ast::ExprField(ref base, _, _) => self.classify(&**base),
+ ast::ExprTupField(ref base, _, _) => self.classify(&**base),
+
ast::ExprIndex(ref base, ref idx) =>
join(self.classify(&**base), self.classify(&**idx)),
"target type not found for const cast")
});
- let base = eval_const_expr_partial(tcx, &**base);
- match base {
- Err(_) => base,
- Ok(val) => {
- match ty::get(ety).sty {
- ty::ty_float(_) => {
- match val {
- const_bool(b) => Ok(const_float(b as f64)),
- const_uint(u) => Ok(const_float(u as f64)),
- const_int(i) => Ok(const_float(i as f64)),
- const_float(f) => Ok(const_float(f)),
- _ => Err("can't cast this type to float".to_string()),
- }
- }
- ty::ty_uint(_) => {
- match val {
- const_bool(b) => Ok(const_uint(b as u64)),
- const_uint(u) => Ok(const_uint(u)),
- const_int(i) => Ok(const_uint(i as u64)),
- const_float(f) => Ok(const_uint(f as u64)),
- _ => Err("can't cast this type to uint".to_string()),
- }
- }
- ty::ty_int(_) => {
- match val {
- const_bool(b) => Ok(const_int(b as i64)),
- const_uint(u) => Ok(const_int(u as i64)),
- const_int(i) => Ok(const_int(i)),
- const_float(f) => Ok(const_int(f as i64)),
- _ => Err("can't cast this type to int".to_string()),
- }
+ macro_rules! define_casts(
+ ($val:ident, {
+ $($ty_pat:pat => (
+ $intermediate_ty:ty,
+ $const_type:ident,
+ $target_ty:ty
+ )),*
+ }) => (match ty::get(ety).sty {
+ $($ty_pat => {
+ match $val {
+ const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
+ const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
+ const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
+ const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
+ _ => Err(concat!(
+ "can't cast this type to ", stringify!($const_type)
+ ).to_string())
}
- _ => Err("can't cast this type".to_string())
- }
- }
- }
+ },)*
+ _ => Err("can't cast this type".to_string())
+ })
+ )
+
+ eval_const_expr_partial(tcx, &**base)
+ .and_then(|val| define_casts!(val, {
+ ty::ty_int(ast::TyI) => (int, const_int, i64),
+ ty::ty_int(ast::TyI8) => (i8, const_int, i64),
+ ty::ty_int(ast::TyI16) => (i16, const_int, i64),
+ ty::ty_int(ast::TyI32) => (i32, const_int, i64),
+ ty::ty_int(ast::TyI64) => (i64, const_int, i64),
+ ty::ty_uint(ast::TyU) => (uint, const_uint, u64),
+ ty::ty_uint(ast::TyU8) => (u8, const_uint, u64),
+ ty::ty_uint(ast::TyU16) => (u16, const_uint, u64),
+ ty::ty_uint(ast::TyU32) => (u32, const_uint, u64),
+ ty::ty_uint(ast::TyU64) => (u64, const_uint, u64),
+ ty::ty_float(ast::TyF32) => (f32, const_float, f64),
+ ty::ty_float(ast::TyF64) => (f64, const_float, f64)
+ }))
}
ExprPath(_) => {
match lookup_const(tcx, e) {
}
}
+ fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: uint) {
+ match ty::get(ty::expr_ty_adjusted(self.tcx, lhs)).sty {
+ ty::ty_struct(id, _) => {
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ let field_id = fields[idx].id;
+ self.live_symbols.insert(field_id.node);
+ },
+ _ => ()
+ }
+ }
+
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
let id = match self.tcx.def_map.borrow().get(&lhs.id) {
&def::DefVariant(_, id, _) => id,
ast::ExprField(ref lhs, ref ident, _) => {
self.handle_field_access(&**lhs, &ident.node);
}
+ ast::ExprTupField(ref lhs, idx, _) => {
+ self.handle_tup_field_access(&**lhs, idx.node);
+ }
_ => ()
}
self.select_from_expr(&**base);
}
+ ast::ExprTupField(ref base, _, _) => { // base.<n>
+ self.select_from_expr(&**base);
+ }
+
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
if !self.walk_overloaded_operator(expr, &**lhs, [rhs.clone()]) {
self.select_from_expr(&**lhs);
cx,
item.span,
&*trait_ref);
+
+ let trait_def = ty::lookup_trait_def(cx.tcx, trait_ref.def_id);
+ for (ty, type_param_def) in trait_ref.substs.types
+ .iter()
+ .zip(trait_def.generics
+ .types
+ .iter()) {
+ check_typaram_bounds(cx, item.span, *ty, type_param_def);
+ }
}
}
}
}
// otherwise, live nodes are not required:
- ExprIndex(..) | ExprField(..) | ExprVec(..) |
+ ExprIndex(..) | ExprField(..) | ExprTupField(..) | ExprVec(..) |
ExprCall(..) | ExprMethodCall(..) | ExprTup(..) |
ExprBinary(..) | ExprAddrOf(..) |
ExprCast(..) | ExprUnary(..) | ExprBreak(_) |
self.propagate_through_expr(&**e, succ)
}
+ ExprTupField(ref e, _, _) => {
+ self.propagate_through_expr(&**e, succ)
+ }
+
ExprFnBlock(_, _, ref blk) |
ExprProc(_, ref blk) |
ExprUnboxedFn(_, _, _, ref blk) => {
match expr.node {
ExprPath(_) => succ,
ExprField(ref e, _, _) => self.propagate_through_expr(&**e, succ),
+ ExprTupField(ref e, _, _) => self.propagate_through_expr(&**e, succ),
_ => self.propagate_through_expr(expr, succ)
}
}
// no correctness conditions related to liveness
ExprCall(..) | ExprMethodCall(..) | ExprIf(..) | ExprMatch(..) |
ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
- ExprVec(..) | ExprTup(..) | ExprBinary(..) |
+ ExprTupField(..) | ExprVec(..) | ExprTup(..) | ExprBinary(..) |
ExprCast(..) | ExprUnary(..) | ExprRet(..) | ExprBreak(..) |
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
Ok(self.cat_field(expr, base_cmt, f_name.node, expr_ty))
}
+ ast::ExprTupField(ref base, idx, _) => {
+ let base_cmt = if_ok!(self.cat_expr(&**base));
+ Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
+ }
+
ast::ExprIndex(ref base, _) => {
let method_call = typeck::MethodCall::expr(expr.id());
match self.typer.node_method_ty(method_call) {
})
}
+ pub fn cat_tup_field<N:ast_node>(&self,
+ node: &N,
+ base_cmt: cmt,
+ f_idx: uint,
+ f_ty: ty::t)
+ -> cmt {
+ Rc::new(cmt_ {
+ id: node.id(),
+ span: node.span(),
+ mutbl: base_cmt.mutbl.inherit(),
+ cat: cat_interior(base_cmt, InteriorField(PositionalField(f_idx))),
+ ty: f_ty
+ })
+ }
+
pub fn cat_deref_obj<N:ast_node>(&self, node: &N, base_cmt: cmt) -> cmt {
self.cat_deref_common(node, base_cmt, 0, ty::mk_nil(), false)
}
_ => {}
}
}
+ ast::ExprTupField(ref base, idx, _) => {
+ match ty::get(ty::expr_ty_adjusted(self.tcx, &**base)).sty {
+ ty::ty_struct(id, _) => {
+ self.check_field(expr.span, id, UnnamedField(idx.node));
+ }
+ _ => {}
+ }
+ }
ast::ExprMethodCall(ident, _, _) => {
let method_call = MethodCall::expr(expr.id);
match self.tcx.method_map.borrow().find(&method_call) {
ast::ExprAddrOf(_, ref subexpr) |
ast::ExprUnary(ast::UnDeref, ref subexpr) |
ast::ExprField(ref subexpr, _, _) |
+ ast::ExprTupField(ref subexpr, _, _) |
ast::ExprIndex(ref subexpr, _) |
ast::ExprParen(ref subexpr) => {
let subexpr: &'a Gc<Expr> = subexpr; // FIXME(#11586)
PathListMod { .. } => Some(item.span),
_ => None
}).collect::<Vec<Span>>();
- match mod_spans.as_slice() {
- [first, second, ..other] => {
- self.resolve_error(first,
- "`mod` import can only appear once in the list");
- self.session.span_note(second,
- "another `mod` import appears here");
- for &other_span in other.iter() {
- self.session.span_note(other_span,
- "another `mod` import appears here");
- }
- },
- [_] | [] => ()
+ if mod_spans.len() > 1 {
+ self.resolve_error(mod_spans[0],
+ "`mod` import can only appear once in the list");
+ for other_span in mod_spans.iter().skip(1) {
+ self.session.span_note(*other_span,
+ "another `mod` import appears here");
+ }
}
for source_item in source_items.iter() {
item.id,
ItemRibKind),
|this| {
+ this.resolve_type_parameters(&generics.ty_params);
visit::walk_item(this, item, ());
});
}
"Expected struct type, but not ty_struct"),
}
},
+ ast::ExprTupField(sub_ex, idx, _) => {
+ if generated_code(sub_ex.span) {
+ return
+ }
+
+ self.visit_expr(&*sub_ex, e);
+
+ let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &*sub_ex);
+ let t_box = ty::get(t);
+ match t_box.sty {
+ ty::ty_struct(def_id, _) => {
+ let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, def_id);
+ for (i, f) in fields.iter().enumerate() {
+ if i == idx.node {
+ let sub_span = self.span.span_for_last_ident(ex.span);
+ self.fmt.ref_str(recorder::VarRef,
+ ex.span,
+ sub_span,
+ f.id,
+ e.cur_scope);
+ break;
+ }
+ }
+ },
+ _ => self.sess.span_bug(ex.span,
+ "Expected struct type, but not ty_struct"),
+ }
+ },
ast::ExprFnBlock(_, decl, body) => {
if generated_code(body.span) {
return
(adt::const_get_field(cx, &*brepr, bv, discr, ix), inlineable)
})
}
+ ast::ExprTupField(ref base, idx, _) => {
+ let (bv, inlineable, bt) = const_expr(cx, &**base, is_local);
+ let brepr = adt::represent_type(cx, bt);
+ expr::with_field_tys(cx.tcx(), bt, None, |discr, _| {
+ (adt::const_get_field(cx, &*brepr, bv, discr, idx.node), inlineable)
+ })
+ }
ast::ExprIndex(ref base, ref index) => {
let (bv, inlineable, bt) = const_expr(cx, &**base, is_local);
ast::ExprCast(ref sub_exp, _) |
ast::ExprAddrOf(_, ref sub_exp) |
ast::ExprField(ref sub_exp, _, _) |
+ ast::ExprTupField(ref sub_exp, _, _) |
ast::ExprParen(ref sub_exp) =>
walk_expr(cx, &**sub_exp, scope_stack, scope_map),
use middle::trans::inline;
use middle::trans::tvec;
use middle::trans::type_of;
-use middle::ty::struct_fields;
+use middle::ty::{struct_fields, tup_fields};
use middle::ty::{AutoDerefRef, AutoAddEnv, AutoUnsafe};
use middle::ty::{AutoPtr};
use middle::ty;
let vec_ty = ty::mk_uniq(tcx, ty::mk_vec(tcx, unit_ty, None));
let scratch = rvalue_scratch_datum(bcx, vec_ty, "__unsize_unique");
- if len == 0 {
- Store(bcx,
- C_null(type_of::type_of(bcx.ccx(), unit_ty).ptr_to()),
- get_dataptr(bcx, scratch.val));
- } else {
- // Box<[(), ..n]> will not allocate, but ~[()] expects an
- // allocation of n bytes, so we must allocate here (yuck).
- let llty = type_of::type_of(bcx.ccx(), unit_ty);
- if llsize_of_alloc(bcx.ccx(), llty) == 0 {
- let ptr_unit_ty = type_of::type_of(bcx.ccx(), unit_ty).ptr_to();
- let align = C_uint(bcx.ccx(), 8);
- let alloc_result = malloc_raw_dyn(bcx, ptr_unit_ty, vec_ty, ll_len, align);
- bcx = alloc_result.bcx;
- let base = get_dataptr(bcx, scratch.val);
- Store(bcx, alloc_result.val, base);
- } else {
- let base = get_dataptr(bcx, scratch.val);
- let base = PointerCast(bcx,
- base,
- type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
- bcx = lval.store_to(bcx, base);
- }
- }
+ let base = get_dataptr(bcx, scratch.val);
+ let base = PointerCast(bcx,
+ base,
+ type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
+ bcx = lval.store_to(bcx, base);
Store(bcx, ll_len, get_len(bcx, scratch.val));
DatumBlock::new(bcx, scratch.to_expr_datum())
ast::ExprField(ref base, ident, _) => {
trans_rec_field(bcx, &**base, ident.node)
}
+ ast::ExprTupField(ref base, idx, _) => {
+ trans_rec_tup_field(bcx, &**base, idx.node)
+ }
ast::ExprIndex(ref base, ref idx) => {
trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
}
}
}
-fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
- base: &ast::Expr,
- field: ast::Ident)
- -> DatumBlock<'blk, 'tcx, Expr> {
- //! Translates `base.field`.
-
+fn trans_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+ base: &ast::Expr,
+ get_idx: |&'blk ty::ctxt<'tcx>, &[ty::field]| -> uint)
+ -> DatumBlock<'blk, 'tcx, Expr> {
let mut bcx = bcx;
let _icx = push_ctxt("trans_rec_field");
let bare_ty = ty::unopen_type(base_datum.ty);
let repr = adt::represent_type(bcx.ccx(), bare_ty);
with_field_tys(bcx.tcx(), bare_ty, None, |discr, field_tys| {
- let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
+ let ix = get_idx(bcx.tcx(), field_tys);
let d = base_datum.get_element(
bcx,
field_tys[ix].mt.ty,
}
})
+
+}
+
+/// Translates `base.field`.
+fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+ base: &ast::Expr,
+ field: ast::Ident)
+ -> DatumBlock<'blk, 'tcx, Expr> {
+ trans_field(bcx, base, |tcx, field_tys| ty::field_idx_strict(tcx, field.name, field_tys))
+}
+
+/// Translates `base.<idx>`.
+fn trans_rec_tup_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+ base: &ast::Expr,
+ idx: uint)
+ -> DatumBlock<'blk, 'tcx, Expr> {
+ trans_field(bcx, base, |_, _| idx)
}
fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
op(0, struct_fields(tcx, did, substs).as_slice())
}
+ ty::ty_tup(ref v) => {
+ op(0, tup_fields(v.as_slice()).as_slice())
+ }
+
ty::ty_enum(_, ref substs) => {
// We want the *variant* ID here, not the enum ID.
match node_id_opt {
};
if should_deallocate {
- let not_null = IsNotNull(bcx, dataptr);
- with_cond(bcx, not_null, |bcx| {
- let llty = type_of::type_of(ccx, unit_ty);
- let llsize = machine::llsize_of(ccx, llty);
- let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
- let size = Mul(bcx, llsize, get_len(bcx, vptr));
- glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
- })
+ let llty = type_of::type_of(ccx, unit_ty);
+ let unit_size = llsize_of_alloc(ccx, llty);
+ if unit_size != 0 {
+ let len = get_len(bcx, vptr);
+ let not_empty = ICmp(bcx, llvm::IntNE, len, C_uint(ccx, 0));
+ with_cond(bcx, not_empty, |bcx| {
+ let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
+ let size = Mul(bcx, C_uint(ccx, unit_size as uint), len);
+ glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
+ })
+ } else {
+ bcx
+ }
} else {
bcx
}
ast::ExprUnary(ast::UnDeref, _) |
ast::ExprField(..) |
+ ast::ExprTupField(..) |
ast::ExprIndex(..) => {
LvalueExpr
}
}
}
+pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
+ let fields = lookup_struct_fields(cx, did);
+ !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
+}
+
pub fn lookup_struct_field(cx: &ctxt,
parent: ast::DefId,
field_id: ast::DefId)
}).collect()
}
+// Returns a list of fields corresponding to the tuple's items. trans uses
+// this.
+pub fn tup_fields(v: &[t]) -> Vec<field> {
+ v.iter().enumerate().map(|(i, &f)| {
+ field {
+ // FIXME #6993: change type of field to Name and get rid of new()
+ ident: ast::Ident::new(token::intern(i.to_string().as_slice())),
+ mt: mt {
+ ty: f,
+ mutbl: MutImmutable
+ }
+ }
+ }).collect()
+}
+
pub struct UnboxedClosureUpvar {
pub def: def::Def,
pub span: Span,
o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
}
+pub fn lookup_tup_field_ty(tcx: &ty::ctxt,
+ class_id: ast::DefId,
+ items: &[ty::field_ty],
+ idx: uint,
+ substs: &subst::Substs) -> Option<ty::t> {
+
+ let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
+ o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
+}
+
// Controls whether the arguments are automatically referenced. This is useful
// for overloaded binary and unary operators.
pub enum DerefArgs {
fcx.write_error(expr.id);
}
+ // Check tuple index expressions
+ fn check_tup_field(fcx: &FnCtxt,
+ expr: &ast::Expr,
+ lvalue_pref: LvaluePreference,
+ base: &ast::Expr,
+ idx: codemap::Spanned<uint>,
+ _tys: &[ast::P<ast::Ty>]) {
+ let tcx = fcx.ccx.tcx;
+ check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
+ let expr_t = structurally_resolved_type(fcx, expr.span,
+ fcx.expr_ty(base));
+ let mut tuple_like = false;
+ // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
+ let (_, autoderefs, field_ty) =
+ 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) => {
+ tuple_like = ty::is_tuple_struct(tcx, base_id);
+ if tuple_like {
+ debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
+ let fields = ty::lookup_struct_fields(tcx, base_id);
+ lookup_tup_field_ty(tcx, base_id, fields.as_slice(),
+ idx.node, &(*substs))
+ } else {
+ None
+ }
+ }
+ ty::ty_tup(ref v) => {
+ tuple_like = true;
+ if idx.node < v.len() { Some(v[idx.node]) } else { None }
+ }
+ _ => None
+ }
+ });
+ match field_ty {
+ Some(field_ty) => {
+ fcx.write_ty(expr.id, field_ty);
+ fcx.write_autoderef_adjustment(base.id, autoderefs);
+ return;
+ }
+ None => {}
+ }
+ fcx.type_error_message(
+ expr.span,
+ |actual| {
+ if tuple_like {
+ format!("attempted out-of-bounds tuple index `{}` on \
+ type `{}`",
+ idx.node,
+ actual)
+ } else {
+ format!("attempted tuple index `{}` on type `{}`, but the \
+ type was not a tuple or tuple struct",
+ idx.node,
+ actual)
+ }
+ },
+ expr_t, None);
+
+ fcx.write_error(expr.id);
+ }
+
fn check_struct_or_variant_fields(fcx: &FnCtxt,
struct_ty: ty::t,
span: Span,
ast::ExprField(ref base, ref field, ref tys) => {
check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
}
+ ast::ExprTupField(ref base, idx, ref tys) => {
+ check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
+ }
ast::ExprIndex(ref base, ref idx) => {
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
check_expr(fcx, &**idx);
}
rcx.visit_expr(&**head, ());
+ type_of_node_must_outlive(rcx,
+ infer::AddrOf(expr.span),
+ head.id,
+ ty::ReScope(expr.id));
let repeating_scope = rcx.set_repeating_scope(body.id);
rcx.visit_block(&**body, ());
generics: &ast::Generics,
thing: &'static str) {
for ty_param in generics.ty_params.iter() {
- for bound in ty_param.bounds.iter() {
+ let bounds = ty_param.bounds.iter();
+ let mut bounds = bounds.chain(ty_param.unbound.iter());
+ for bound in bounds {
match *bound {
ast::TraitTyParamBound(..) | ast::UnboxedFnTyParamBound(..) => {
// According to accepted RFC #XXX, we should
desc: &str,
span: Span) {
let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
+
match unbound {
&Some(ast::TraitTyParamBound(ref tpb)) => {
- // #FIXME(8559) currently requires the unbound to be built-in.
+ // 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 => {
SawExprLoop(Option<token::InternedString>),
SawExprField(token::InternedString),
+ SawExprTupField(uint),
SawExprBreak(Option<token::InternedString>),
SawExprAgain(Option<token::InternedString>),
ExprAssign(..) => SawExprAssign,
ExprAssignOp(op, _, _) => SawExprAssignOp(op),
ExprField(_, id, _) => SawExprField(content(id.node)),
+ ExprTupField(_, id, _) => SawExprTupField(id.node),
ExprIndex(..) => SawExprIndex,
ExprPath(..) => SawExprPath,
ExprAddrOf(m, _) => SawExprAddrOf(m),
local_data_key!(pub playground_krate: Option<String>)
pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
- extern fn block(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
+ extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
lang: *const hoedown_buffer, opaque: *mut libc::c_void) {
unsafe {
- if text.is_null() { return }
+ if orig_text.is_null() { return }
let opaque = opaque as *mut hoedown_html_renderer_state;
let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque);
- slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
+ slice::raw::buf_as_slice((*orig_text).data, (*orig_text).size as uint,
+ |text| {
let origtext = str::from_utf8(text).unwrap();
debug!("docblock: ==============\n{}\n=======", text);
- let mut lines = origtext.lines().filter(|l| {
- stripped_filtered_line(*l).is_none()
- });
- let text = lines.collect::<Vec<&str>>().connect("\n");
-
- let buf = hoedown_buffer {
- data: text.as_bytes().as_ptr(),
- size: text.len() as libc::size_t,
- asize: text.len() as libc::size_t,
- unit: 0,
- };
let rendered = if lang.is_null() {
false
} else {
(*lang).size as uint, |rlang| {
let rlang = str::from_utf8(rlang).unwrap();
if LangString::parse(rlang).notrust {
- (my_opaque.dfltblk)(ob, &buf, lang,
+ (my_opaque.dfltblk)(ob, orig_text, lang,
opaque as *mut libc::c_void);
true
} else {
})
};
+ let mut lines = origtext.lines().filter(|l| {
+ stripped_filtered_line(*l).is_none()
+ });
+ let text = lines.collect::<Vec<&str>>().connect("\n");
if !rendered {
let mut s = String::new();
let id = playground_krate.get().map(|krate| {
#[test]
#[should_fail]
fn test_new_fail() {
- let c_str = unsafe { CString::new(ptr::null(), false) };
+ let _c_str = unsafe { CString::new(ptr::null(), false) };
}
#[test]
#[test]
fn block_and_wake() {
let task = box Task::new();
- let mut task = BlockedTask::block(task).wake().unwrap();
+ let task = BlockedTask::block(task).wake().unwrap();
task.drop();
}
}
let mut obj = try!(expect!(self.pop(), Object));
let value = match obj.pop(&name.to_string()) {
- None => return Err(MissingFieldError(name.to_string())),
+ None => {
+ // Add a Null and try to parse it as an Option<_>
+ // to get None as a default value.
+ self.stack.push(Null);
+ match f(self) {
+ Ok(x) => x,
+ Err(_) => return Err(MissingFieldError(name.to_string())),
+ }
+ },
Some(json) => {
self.stack.push(json);
try!(f(self))
}
fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> {
+ debug!("read_option()");
match self.pop() {
Null => f(self, false),
value => { self.stack.push(value); f(self, true) }
use std::{i64, u64, f32, f64, io};
use std::collections::TreeMap;
+ #[deriving(Decodable, Eq, PartialEq, Show)]
+ struct OptionData {
+ opt: Option<uint>,
+ }
+
+ #[test]
+ fn test_decode_option_none() {
+ let s ="{}";
+ let obj: OptionData = super::decode(s).unwrap();
+ assert_eq!(obj, OptionData { opt: None });
+ }
+
+ #[test]
+ fn test_decode_option_some() {
+ let s = "{ \"opt\": 10 }";
+ let obj: OptionData = super::decode(s).unwrap();
+ assert_eq!(obj, OptionData { opt: Some(10u) });
+ }
+
+ #[test]
+ fn test_decode_option_malformed() {
+ check_err::<OptionData>("{ \"opt\": [] }",
+ ExpectedError("Number".to_string(), "[]".to_string()));
+ check_err::<OptionData>("{ \"opt\": false }",
+ ExpectedError("Number".to_string(), "false".to_string()));
+ }
+
#[deriving(PartialEq, Encodable, Decodable, Show)]
enum Animal {
Dog,
use native;
- use super::{queue, Queue};
+ use super::{queue};
#[test]
fn smoke() {
ExprAssign(Gc<Expr>, Gc<Expr>),
ExprAssignOp(BinOp, Gc<Expr>, Gc<Expr>),
ExprField(Gc<Expr>, SpannedIdent, Vec<P<Ty>>),
+ ExprTupField(Gc<Expr>, Spanned<uint>, Vec<P<Ty>>),
ExprIndex(Gc<Expr>, Gc<Expr>),
/// Variable reference, possibly containing `::` and/or
fn expr_mut_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr>;
fn expr_field_access(&self, span: Span, expr: Gc<ast::Expr>,
ident: ast::Ident) -> Gc<ast::Expr>;
+ fn expr_tup_field_access(&self, sp: Span, expr: Gc<ast::Expr>,
+ idx: uint) -> Gc<ast::Expr>;
fn expr_call(&self, span: Span, expr: Gc<ast::Expr>,
args: Vec<Gc<ast::Expr>>) -> Gc<ast::Expr>;
fn expr_call_ident(&self, span: Span, id: ast::Ident,
let id = Spanned { node: ident, span: field_span };
self.expr(sp, ast::ExprField(expr, id, Vec::new()))
}
+ fn expr_tup_field_access(&self, sp: Span, expr: Gc<ast::Expr>, idx: uint) -> Gc<ast::Expr> {
+ let field_span = Span {
+ lo: sp.lo - Pos::from_uint(idx.to_string().len()),
+ hi: sp.hi,
+ expn_info: sp.expn_info,
+ };
+
+ let id = Spanned { node: idx, span: field_span };
+ self.expr(sp, ast::ExprTupField(expr, id, Vec::new()))
+ }
fn expr_addr_of(&self, sp: Span, e: Gc<ast::Expr>) -> Gc<ast::Expr> {
self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e))
}
name_types: HashMap<String, ArgumentType>,
name_ordering: Vec<String>,
- /// The latest consecutive literal strings
- literal: Option<String>,
+ /// The latest consecutive literal strings, or empty if there weren't any.
+ literal: String,
- /// Collection of the compiled `rt::Piece` structures
+ /// Collection of the compiled `rt::Argument` structures
pieces: Vec<Gc<ast::Expr>>,
+ /// Collection of string literals
+ str_pieces: Vec<Gc<ast::Expr>>,
+ /// Stays `true` if all formatting parameters are default (as in "{}{}").
+ all_pieces_simple: bool,
+
name_positions: HashMap<String, uint>,
method_statics: Vec<Gc<ast::Item>>,
}
}
- /// Translate the accumulated string literals to a static `rt::Piece`
- fn trans_literal_string(&mut self) -> Option<Gc<ast::Expr>> {
+ /// Translate the accumulated string literals to a literal expression
+ fn trans_literal_string(&mut self) -> Gc<ast::Expr> {
let sp = self.fmtsp;
- self.literal.take().map(|s| {
- let s = token::intern_and_get_ident(s.as_slice());
- self.ecx.expr_call_global(sp,
- self.rtpath("String"),
- vec!(
- self.ecx.expr_str(sp, s)
- ))
- })
+ let s = token::intern_and_get_ident(self.literal.as_slice());
+ self.literal.clear();
+ self.ecx.expr_str(sp, s)
}
- /// Translate a `parse::Piece` to a static `rt::Piece`
+ /// Translate a `parse::Piece` to a static `rt::Argument` or append
+ /// to the `literal` string.
fn trans_piece(&mut self, piece: &parse::Piece) -> Option<Gc<ast::Expr>> {
let sp = self.fmtsp;
match *piece {
parse::String(s) => {
- match self.literal {
- Some(ref mut sb) => sb.push_str(s),
- ref mut empty => *empty = Some(String::from_str(s)),
- }
+ self.literal.push_str(s);
None
}
parse::Argument(ref arg) => {
}
};
- // Translate the format
+ let simple_arg = parse::Argument {
+ position: parse::ArgumentNext,
+ format: parse::FormatSpec {
+ fill: arg.format.fill,
+ align: parse::AlignUnknown,
+ flags: 0,
+ precision: parse::CountImplied,
+ width: parse::CountImplied,
+ ty: arg.format.ty
+ }
+ };
+
let fill = match arg.format.fill { Some(c) => c, None => ' ' };
+
+ if *arg != simple_arg || fill != ' ' {
+ self.all_pieces_simple = false;
+ }
+
+ // Translate the format
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill));
let align = match arg.format.align {
parse::AlignLeft => {
self.ecx.field_imm(sp, self.ecx.ident_of("width"), width)));
let path = self.ecx.path_global(sp, self.rtpath("Argument"));
- let s = self.ecx.expr_struct(sp, path, vec!(
+ Some(self.ecx.expr_struct(sp, path, vec!(
self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
- self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt)));
- Some(self.ecx.expr_call_global(sp, self.rtpath("Argument"), vec!(s)))
+ self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt))))
}
}
}
+ fn item_static_array(&self,
+ name: ast::Ident,
+ piece_ty: Gc<ast::Ty>,
+ pieces: Vec<Gc<ast::Expr>>)
+ -> ast::Stmt
+ {
+ let pieces_len = self.ecx.expr_uint(self.fmtsp, pieces.len());
+ let fmt = self.ecx.expr_vec(self.fmtsp, pieces);
+ let ty = ast::TyFixedLengthVec(
+ piece_ty,
+ pieces_len
+ );
+ let ty = self.ecx.ty(self.fmtsp, ty);
+ let st = ast::ItemStatic(ty, ast::MutImmutable, fmt);
+ let item = self.ecx.item(self.fmtsp, name,
+ self.static_attrs(), st);
+ let decl = respan(self.fmtsp, ast::DeclItem(item));
+ respan(self.fmtsp, ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))
+ }
+
/// Actually builds the expression which the iformat! block will be expanded
/// to
fn to_expr(&self, invocation: Invocation) -> Gc<ast::Expr> {
// Next, build up the static array which will become our precompiled
// format "string"
- let fmt = self.ecx.expr_vec(self.fmtsp, self.pieces.clone());
- let piece_ty = self.ecx.ty_path(self.ecx.path_all(
+ let static_str_name = self.ecx.ident_of("__STATIC_FMTSTR");
+ let static_lifetime = self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("'static").name);
+ let piece_ty = self.ecx.ty_rptr(
self.fmtsp,
- true, vec!(
- self.ecx.ident_of("std"),
- self.ecx.ident_of("fmt"),
- self.ecx.ident_of("rt"),
- self.ecx.ident_of("Piece")),
- vec!(self.ecx.lifetime(self.fmtsp,
- self.ecx.ident_of("'static").name)),
- Vec::new()
- ), None);
- let ty = ast::TyFixedLengthVec(
- piece_ty,
- self.ecx.expr_uint(self.fmtsp, self.pieces.len())
- );
- let ty = self.ecx.ty(self.fmtsp, ty);
- let st = ast::ItemStatic(ty, ast::MutImmutable, fmt);
- let static_name = self.ecx.ident_of("__STATIC_FMTSTR");
- let item = self.ecx.item(self.fmtsp, static_name,
- self.static_attrs(), st);
- let decl = respan(self.fmtsp, ast::DeclItem(item));
- lets.push(box(GC) respan(self.fmtsp,
- ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID)));
+ self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
+ Some(static_lifetime),
+ ast::MutImmutable);
+ lets.push(box(GC) self.item_static_array(static_str_name,
+ piece_ty,
+ self.str_pieces.clone()));
+
+ // Then, build up the static array which will store our precompiled
+ // nonstandard placeholders, if there are any.
+ let static_args_name = self.ecx.ident_of("__STATIC_FMTARGS");
+ if !self.all_pieces_simple {
+ let piece_ty = self.ecx.ty_path(self.ecx.path_all(
+ self.fmtsp,
+ true, self.rtpath("Argument"),
+ vec![static_lifetime],
+ vec![]
+ ), None);
+ lets.push(box(GC) self.item_static_array(static_args_name,
+ piece_ty,
+ self.pieces.clone()));
+ }
// Right now there is a bug such that for the expression:
// foo(bar(&1))
}
// Now create the fmt::Arguments struct with all our locals we created.
- let fmt = self.ecx.expr_ident(self.fmtsp, static_name);
+ let pieces = self.ecx.expr_ident(self.fmtsp, static_str_name);
let args_slice = self.ecx.expr_ident(self.fmtsp, slicename);
+
+ let (fn_name, fn_args) = if self.all_pieces_simple {
+ ("new", vec![pieces, args_slice])
+ } else {
+ let fmt = self.ecx.expr_ident(self.fmtsp, static_args_name);
+ ("with_placeholders", vec![pieces, fmt, args_slice])
+ };
+
let result = self.ecx.expr_call_global(self.fmtsp, vec!(
self.ecx.ident_of("std"),
self.ecx.ident_of("fmt"),
self.ecx.ident_of("Arguments"),
- self.ecx.ident_of("new")), vec!(fmt, args_slice));
+ self.ecx.ident_of(fn_name)), fn_args);
// We did all the work of making sure that the arguments
// structure is safe, so we can safely have an unsafe block.
name_ordering: name_ordering,
nest_level: 0,
next_arg: 0,
- literal: None,
+ literal: String::new(),
pieces: Vec::new(),
+ str_pieces: Vec::new(),
+ all_pieces_simple: true,
method_statics: Vec::new(),
fmtsp: sp,
};
cx.verify_piece(&piece);
match cx.trans_piece(&piece) {
Some(piece) => {
- cx.trans_literal_string().map(|piece|
- cx.pieces.push(piece));
+ let s = cx.trans_literal_string();
+ cx.str_pieces.push(s);
cx.pieces.push(piece);
}
None => {}
}
None => {}
}
- cx.trans_literal_string().map(|piece| cx.pieces.push(piece));
+ if !cx.literal.is_empty() {
+ let s = cx.trans_literal_string();
+ cx.str_pieces.push(s);
+ }
// Make sure that all arguments were used and all arguments have types.
for (i, ty) in cx.arg_types.iter().enumerate() {
cx.view_use_glob(sp, ast::Inherited, ids_ext(path))
}).collect();
- let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr);
+ // Explicitly borrow to avoid moving from the invoker (#16992)
+ let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr));
+ let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow);
cx.expr_block(cx.block_all(sp, uses, vec!(stmt_let_ext_cx), Some(expr)))
}
noop_fold_ident(i, self)
}
+ fn fold_uint(&mut self, i: uint) -> uint {
+ noop_fold_uint(i, self)
+ }
+
fn fold_path(&mut self, p: &Path) -> Path {
noop_fold_path(p, self)
}
i
}
+pub fn noop_fold_uint<T: Folder>(i: uint, _: &mut T) -> uint {
+ i
+}
+
pub fn noop_fold_path<T: Folder>(p: &Path, fld: &mut T) -> Path {
ast::Path {
span: fld.new_span(p.span),
respan(id.span, folder.fold_ident(id.node)),
tys.iter().map(|&x| folder.fold_ty(x)).collect())
}
+ ExprTupField(el, id, ref tys) => {
+ ExprTupField(folder.fold_expr(el),
+ respan(id.span, folder.fold_uint(id.node)),
+ tys.iter().map(|&x| folder.fold_ty(x)).collect())
+ }
ExprIndex(el, er) => {
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
}
ObsoleteManagedType,
ObsoleteManagedExpr,
ObsoleteImportRenaming,
+ ObsoleteSubsliceMatch,
+ ObsoleteExternCrateRenaming,
}
pub trait ParserObsoleteMethods {
ObsoleteImportRenaming => (
"`use foo = bar` syntax",
"write `use bar as foo` instead"
+ ),
+ ObsoleteSubsliceMatch => (
+ "subslice match syntax",
+ "instead of `..xs`, write `xs..` in a pattern"
+ ),
+ ObsoleteExternCrateRenaming => (
+ "`extern crate foo = bar` syntax",
+ "write `extern crate bar as foo` instead"
)
};
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast};
-use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
+use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex};
use ast::{ExprLit, ExprLoop, ExprMac};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
ExprField(expr, ident, tys)
}
+ pub fn mk_tup_field(&mut self, expr: Gc<Expr>, idx: codemap::Spanned<uint>,
+ tys: Vec<P<Ty>>) -> ast::Expr_ {
+ ExprTupField(expr, idx, tys)
+ }
+
pub fn mk_assign_op(&mut self, binop: ast::BinOp,
lhs: Gc<Expr>, rhs: Gc<Expr>) -> ast::Expr_ {
ExprAssignOp(binop, lhs, rhs)
}
}
}
+ token::LIT_INTEGER(n) => {
+ let index = n.as_str();
+ let dot = self.last_span.hi;
+ hi = self.span.hi;
+ self.bump();
+ let (_, tys) = if self.eat(&token::MOD_SEP) {
+ self.expect_lt();
+ self.parse_generic_values_after_lt()
+ } else {
+ (Vec::new(), Vec::new())
+ };
+
+ let num = from_str::<uint>(index);
+ match num {
+ Some(n) => {
+ let id = spanned(dot, hi, n);
+ let field = self.mk_tup_field(e, id, tys);
+ e = self.mk_expr(lo, hi, field);
+ }
+ None => {
+ let last_span = self.last_span;
+ self.span_err(last_span, "invalid tuple or tuple struct index");
+ }
+ }
+ }
+ token::LIT_FLOAT(n) => {
+ self.bump();
+ let last_span = self.last_span;
+ self.span_err(last_span,
+ format!("unexpected token: `{}`", n.as_str()).as_slice());
+ self.span_note(last_span,
+ "try parenthesizing the first index; e.g., `(foo.0).1`");
+ self.abort_if_errors();
+
+ }
_ => self.unexpected()
}
continue;
let mut before_slice = true;
while self.token != token::RBRACKET {
- if first { first = false; }
- else { self.expect(&token::COMMA); }
+ if first {
+ first = false;
+ } else {
+ self.expect(&token::COMMA);
+ }
- let mut is_slice = false;
if before_slice {
if self.token == token::DOTDOT {
self.bump();
- is_slice = true;
- before_slice = false;
- }
- }
- if is_slice {
- if self.token == token::COMMA || self.token == token::RBRACKET {
- slice = Some(box(GC) ast::Pat {
- id: ast::DUMMY_NODE_ID,
- node: PatWild(PatWildMulti),
- span: self.span,
- })
- } else {
- let subpat = self.parse_pat();
- match *subpat {
- ast::Pat { node: PatIdent(_, _, _), .. } => {
- slice = Some(subpat);
- }
- ast::Pat { span, .. } => self.span_fatal(
- span, "expected an identifier or nothing"
- )
+ if self.token == token::COMMA ||
+ self.token == token::RBRACKET {
+ slice = Some(box(GC) ast::Pat {
+ id: ast::DUMMY_NODE_ID,
+ node: PatWild(PatWildMulti),
+ span: self.span,
+ });
+ before_slice = false;
+ } else {
+ let _ = self.parse_pat();
+ let span = self.span;
+ self.obsolete(span, ObsoleteSubsliceMatch);
}
+ continue
}
+ }
+
+ let subpat = self.parse_pat();
+ if before_slice && self.token == token::DOTDOT {
+ self.bump();
+ slice = Some(subpat);
+ before_slice = false;
+ } else if before_slice {
+ before.push(subpat);
} else {
- let subpat = self.parse_pat();
- if before_slice {
- before.push(subpat);
- } else {
- after.push(subpat);
- }
+ after.push(subpat);
}
}
// These expressions are limited to literals (possibly
// preceded by unary-minus) or identifiers.
let val = self.parse_literal_maybe_minus();
- if self.eat(&token::DOTDOT) {
+ if self.token == token::DOTDOT &&
+ self.look_ahead(1, |t| {
+ *t != token::COMMA && *t != token::RBRACKET
+ }) {
+ self.bump();
let end = if is_ident_or_path(&self.token) {
let path = self.parse_path(LifetimeAndTypesWithColons)
.path;
}
});
- if self.look_ahead(1, |t| *t == token::DOTDOT) {
+ if self.look_ahead(1, |t| *t == token::DOTDOT) &&
+ self.look_ahead(2, |t| {
+ *t != token::COMMA && *t != token::RBRACKET
+ }) {
let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
self.eat(&token::DOTDOT);
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
self.bump();
let path = self.parse_str();
let span = self.span;
- self.span_warn(span,
- format!("this extern crate syntax is deprecated. \
- Use: extern crate \"{}\" as {};",
- path.ref0().get(), the_ident.as_str() ).as_slice()
- );
+ self.obsolete(span, ObsoleteExternCrateRenaming);
Some(path)
} else {None};
try!(word(&mut self.s, ">"));
}
}
+ ast::ExprTupField(ref expr, id, ref tys) => {
+ try!(self.print_expr(&**expr));
+ try!(word(&mut self.s, "."));
+ try!(self.print_uint(id.node));
+ if tys.len() > 0u {
+ try!(word(&mut self.s, "::<"));
+ try!(self.commasep(
+ Inconsistent, tys.as_slice(),
+ |s, ty| s.print_type_ref(ty)));
+ try!(word(&mut self.s, ">"));
+ }
+ }
ast::ExprIndex(ref expr, ref index) => {
try!(self.print_expr(&**expr));
try!(word(&mut self.s, "["));
self.ann.post(self, NodeIdent(&ident))
}
+ pub fn print_uint(&mut self, i: uint) -> IoResult<()> {
+ word(&mut self.s, i.to_string().as_slice())
+ }
+
pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
try!(word(&mut self.s, token::get_name(name).get()));
self.ann.post(self, NodeName(&name))
|s, p| s.print_pat(&**p)));
for p in slice.iter() {
if !before.is_empty() { try!(self.word_space(",")); }
+ try!(self.print_pat(&**p));
match **p {
ast::Pat { node: ast::PatWild(ast::PatWildMulti), .. } => {
// this case is handled by print_pat
}
_ => try!(word(&mut self.s, "..")),
}
- try!(self.print_pat(&**p));
if !after.is_empty() { try!(self.word_space(",")); }
}
try!(self.commasep(Inconsistent,
visitor.visit_ty(&**typ, env.clone())
}
}
+ ExprTupField(ref subexpression, _, ref types) => {
+ visitor.visit_expr(&**subexpression, env.clone());
+ for typ in types.iter() {
+ visitor.visit_ty(&**typ, env.clone())
+ }
+ }
ExprIndex(ref main_expression, ref index_expression) => {
visitor.visit_expr(&**main_expression, env.clone());
visitor.visit_expr(&**index_expression, env.clone())
use super::{Uuid, VariantMicrosoft, VariantNCS, VariantRFC4122,
Version1Mac, Version2Dce, Version3Md5, Version4Random,
Version5Sha1};
- use std::io::MemWriter;
use std::rand;
#[test]
#[test]
fn test_serialize_round_trip() {
use serialize::json;
- use serialize::{Encodable, Decodable};
let u = Uuid::new_v4();
let s = json::encode(&u);
#[test]
fn test_bad_decode() {
use serialize::json;
- use serialize::{Encodable, Decodable};
+ use serialize::{Decodable};
let js_good = json::String("a1a2a3a4a5a6a7a8a1a2a3a4a5a6a7a8".to_string());
let js_bad1 = json::String("a1a2a3a4a5a6a7a8a1a2a3a4a5a6a7ah".to_string());
-// 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.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
//
-// 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.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2012-2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+// the name of "The Computer Language Shootout Benchmarks" nor the
+// names of its contributors may be used to endorse or promote
+// products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
// no-pretty-expanded
-// 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.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
//
-// 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.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2011-2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+// the name of "The Computer Language Shootout Benchmarks" nor the
+// names of its contributors may be used to endorse or promote
+// products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
static PI: f64 = 3.141592653589793;
static SOLAR_MASS: f64 = 4.0 * PI * PI;
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
//
-// 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.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2013-2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+// the name of "The Computer Language Shootout Benchmarks" nor the
+// names of its contributors may be used to endorse or promote
+// products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
// ignore-pretty very bad with line comments
// ignore-android doesn't terminate?
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Foo(Box<int>, int);
+
+struct Bar(int, int);
+
+fn main() {
+ let x = (box 1i, 2i);
+ let r = &x.0;
+ let y = x; //~ ERROR cannot move out of `x` because it is borrowed
+
+ let mut x = (1i, 2i);
+ let a = &x.0;
+ let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
+
+ let mut x = (1i, 2i);
+ let a = &mut x.0;
+ let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
+
+
+ let x = Foo(box 1i, 2i);
+ let r = &x.0;
+ let y = x; //~ ERROR cannot move out of `x` because it is borrowed
+
+ let mut x = Bar(1i, 2i);
+ let a = &x.0;
+ let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
+
+ let mut x = Bar(1i, 2i);
+ let a = &mut x.0;
+ let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
+}
--- /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 mut vector = vec![1u, 2];
+ for &x in vector.iter() {
+ let cap = vector.capacity();
+ vector.grow(cap, &0u); //~ ERROR cannot borrow
+ *vector.get_mut(1u) = 5u; //~ ERROR cannot borrow
+ }
+}
+
);
let x: &[Foo] = x.as_slice();
match x {
- [_, ..tail] => {
+ [_, tail..] => {
match tail {
[Foo { string: a }, //~ ERROR cannot move out of dereference of `&`-pointer
Foo { string: b }] => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn a<'a>() -> &'a [int] {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let tail = match vec {
- [_, ..tail] => tail,
+ [_, tail..] => tail,
_ => fail!("a")
};
tail
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let init = match vec {
- [..init, _] => init,
+ [init.., _] => init,
_ => fail!("b")
};
init
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let slice = match vec {
- [_, ..slice, _] => slice,
+ [_, slice.., _] => slice,
_ => fail!("c")
};
slice
let mut v = vec!(1, 2, 3);
let vb: &mut [int] = v.as_mut_slice();
match vb {
- [_a, ..tail] => {
+ [_a, tail..] => {
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
}
_ => {}
fn main() {
let mut a = [1i, 2, 3, 4];
let t = match a {
- [1, 2, ..tail] => tail,
+ [1, 2, tail..] => tail,
_ => unreachable!()
};
a[0] = 0; //~ ERROR cannot assign to `a[..]` because it is borrowed
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
fn a() {
let mut vec = [box 1i, box 2, box 3];
let mut vec = vec!(box 1i, box 2, box 3);
let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
- [.._b] => {
+ [_b..] => {
vec[0] = box 4; //~ ERROR cannot assign
}
}
let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
[_a, //~ ERROR cannot move out
- .._b] => { //~^ NOTE attempting to move value to here
+ _b..] => { //~^ NOTE attempting to move value to here
// Note: `_a` is *moved* here, but `b` is borrowing,
// hence illegal.
let mut vec = vec!(box 1i, box 2, box 3);
let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
- [.._a, //~ ERROR cannot move out
+ [_a.., //~ ERROR cannot move out
_b] => {} //~ NOTE attempting to move value to here
_ => {}
}
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR `vec` does not live long enough
let tail = match vec {
- [_a, ..tail] => &tail[0],
+ [_a, tail..] => &tail[0],
_ => fail!("foo")
};
tail
--- /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 x = [ 1i, 2, 3, 4, 5 ];
+ match x {
+ [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches
+ [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches
+ [ 1, 2, xs.. ] => {} // OK without feature gate
+ }
+}
+
--- /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.
+
+// This code used to produce an ICE on the definition of trait Bar
+// with the following message:
+//
+// Type parameter out of range when substituting in region 'a (root
+// type=fn(Self) -> 'astr) (space=FnSpace, index=0)
+//
+// Regression test for issue #16218.
+
+trait Bar<'a> {}
+
+trait Foo<'a> {
+ fn bar<'a, T: Bar<'a>>(self) -> &'a str;
+}
+
+impl<'a> Foo<'a> for &'a str {
+ fn bar<T: Bar<'a>>(self) -> &'a str { fail!() } //~ ERROR lifetime
+}
+
+fn main() {
+}
let v: int = match sl.as_slice() {
[] => 0,
[a,b,c] => 3,
- [a, ..rest] => a,
- [10,a, ..rest] => 10 //~ ERROR: unreachable pattern
+ [a, rest..] => a,
+ [10,a, rest..] => 10 //~ ERROR: unreachable pattern
};
}
fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
match (l1, l2) {
([], []) => println!("both empty"),
- ([], [hd, ..tl]) | ([hd, ..tl], []) => println!("one empty"),
+ ([], [hd, tl..]) | ([hd, tl..], []) => println!("one empty"),
//~^ ERROR: cannot move out of dereference
//~^^ ERROR: cannot move out of dereference
- ([hd1, ..tl1], [hd2, ..tl2]) => println!("both nonempty"),
+ ([hd1, tl1..], [hd2, tl2..]) => println!("both nonempty"),
//~^ ERROR: cannot move out of dereference
//~^^ ERROR: cannot move out of dereference
}
let x = -2147483649_i32; //~ error: literal out of range for its type
let x = 9223372036854775808_i64; //~ error: literal out of range for its type
+ let x = -9223372036854775808_i64; // should be OK
let x = 18446744073709551615_i64; //~ error: literal out of range for its type
let x = -3.40282348e+38_f32; //~ error: literal out of range for its type
fn main() {
let a = Vec::new();
match a {
- [1, ..tail, ..tail] => {}, //~ ERROR: unexpected token: `..`
+ [1, tail.., tail..] => {}, //~ ERROR: expected `,`, found `..`
_ => ()
}
}
let x: Vec<char> = vec!('a', 'b', 'c');
let x: &[char] = x.as_slice();
match x {
- ['a', 'b', 'c', .._tail] => {}
+ ['a', 'b', 'c', _tail..] => {}
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
_ => {}
}
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Foo(Box<int>);
+
+fn main() {
+ let x = (box 1i,);
+ let y = x.0;
+ let z = x.0; //~ ERROR use of moved value: `x.0`
+
+ let x = Foo(box 1i);
+ let y = x.0;
+ let z = x.0; //~ ERROR use of moved value: `x.0`
+}
let vec = vec!(Some(42i), None, Some(21i));
let vec: &[Option<int>] = vec.as_slice();
match vec { //~ ERROR non-exhaustive patterns: `[]` not covered
- [Some(..), None, ..tail] => {}
- [Some(..), Some(..), ..tail] => {}
+ [Some(..), None, tail..] => {}
+ [Some(..), Some(..), tail..] => {}
[None] => {}
}
let vec = vec!(1i);
let vec: &[int] = vec.as_slice();
match vec {
- [_, ..tail] => (),
+ [_, tail..] => (),
[] => ()
}
let vec = vec!(0.5f32);
let vec = vec!(Some(42i), None, Some(21i));
let vec: &[Option<int>] = vec.as_slice();
match vec {
- [Some(..), None, ..tail] => {}
- [Some(..), Some(..), ..tail] => {}
- [None, None, ..tail] => {}
- [None, Some(..), ..tail] => {}
+ [Some(..), None, tail..] => {}
+ [Some(..), Some(..), tail..] => {}
+ [None, None, tail..] => {}
+ [None, Some(..), tail..] => {}
[Some(_)] => {}
[None] => {}
[] => {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(struct_variant)]
+#![feature(advanced_slice_patterns, struct_variant)]
struct Foo {
first: bool,
[Second(true), First] => (),
[Second(true), Second(true)] => (),
[Second(false), _] => (),
- [_, _, ..tail, _] => ()
+ [_, _, tail.., _] => ()
}
}
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Point { x: int, y: int }
+struct Empty;
+
+fn main() {
+ let origin = Point { x: 0, y: 0 };
+ origin.0;
+ //~^ ERROR attempted tuple index `0` on type `Point`, but the type was not
+ Empty.0;
+ //~^ ERROR attempted tuple index `0` on type `Empty`, but the type was not
+}
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Point(int, int);
+
+fn main() {
+ let origin = Point(0, 0);
+ origin.0;
+ origin.1;
+ origin.2;
+ //~^ ERROR attempted out-of-bounds tuple index `2` on type `Point`
+ let tuple = (0i, 0i);
+ tuple.0;
+ tuple.1;
+ tuple.2;
+ //~^ ERROR attempted out-of-bounds tuple index `2` on type `(int,int)`
+}
//~^ ERROR instantiating a type parameter with an incompatible type
}
-// I would like these to fail eventually.
-/*
// impl - bounded
trait T1<Z: T> {
}
struct S3<Sized? Y>;
-impl<Sized? X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
+impl<Sized? X: T> T1<X> for S3<X> { //~ ERROR instantiating a type parameter with an incompatible
}
// impl - unbounded
trait T2<Z> {
}
-impl<Sized? 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
+}
// impl - struct
trait T3<Sized? Z> {
--- /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 x = [1i, 2, 3];
+ match x {
+ [a, b, ..c] => { //~ ERROR obsolete syntax
+ assert_eq!(a, 1);
+ assert_eq!(b, 2);
+ let expected: &[_] = &[3];
+ assert_eq!(c, expected);
+ }
+ }
+}
+
() => {
#[inline]
#[allow(dead_code)]
- static __STATIC_FMTSTR:
- [::std::fmt::rt::Piece<'static>, ..(1u as uint)] =
- ([((::std::fmt::rt::String as
- fn(&'static str) -> core::fmt::rt::Piece<'static>)(("test"
- as
- &'static str))
- as core::fmt::rt::Piece<'static>)] as
- [core::fmt::rt::Piece<'static>, .. 1]);
+ static __STATIC_FMTSTR: [&'static str, ..(1u as uint)] =
+ ([("test" as &'static str)] as [&'static str, .. 1]);
let __args_vec =
(&([] as [core::fmt::Argument<'_>, .. 0]) as
&[core::fmt::Argument<'_>, .. 0]);
let __args =
(unsafe {
((::std::fmt::Arguments::new as
- unsafe fn(&'static [core::fmt::rt::Piece<'static>], &'a [core::fmt::Argument<'a>]) -> core::fmt::Arguments<'a>)((__STATIC_FMTSTR
- as
- [core::fmt::rt::Piece<'static>, .. 1]),
- (__args_vec
- as
- &[core::fmt::Argument<'_>, .. 0]))
+ unsafe fn(&'static [&'static str], &'a [core::fmt::Argument<'a>]) -> core::fmt::Arguments<'a>)((__STATIC_FMTSTR
+ as
+ [&'static str, .. 1]),
+ (__args_vec
+ as
+ &[core::fmt::Argument<'_>, .. 0]))
as core::fmt::Arguments<'_>)
} as core::fmt::Arguments<'_>);
--- /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-pretty
+// ignore-android
+
+#![feature(quote)]
+
+extern crate syntax;
+
+use syntax::ext::base::ExtCtxt;
+
+#[allow(dead_code)]
+fn foobar(cx: &mut ExtCtxt) {
+ quote_expr!(cx, 1i);
+ quote_expr!(cx, 2i);
+}
+
+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.
+
+#![feature(tuple_indexing)]
+
+struct Foo(int, int);
+
+fn main() {
+ let x = (1i, 2i);
+ let a = &x.0;
+ let b = &x.0;
+ assert_eq!(*a, 1);
+ assert_eq!(*b, 1);
+
+ let mut x = (1i, 2i);
+ {
+ let a = &x.0;
+ let b = &mut x.1;
+ *b = 5;
+ assert_eq!(*a, 1);
+ }
+ assert_eq!(x.0, 1);
+ assert_eq!(x.1, 5);
+
+
+ let x = Foo(1i, 2i);
+ let a = &x.0;
+ let b = &x.0;
+ assert_eq!(*a, 1);
+ assert_eq!(*b, 1);
+
+ let mut x = Foo(1i, 2i);
+ {
+ let a = &x.0;
+ let b = &mut x.1;
+ *b = 5;
+ assert_eq!(*a, 1);
+ }
+ assert_eq!(x.0, 1);
+ assert_eq!(x.1, 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.
+
+// This test verifies that casting from the same lifetime on a value
+// to the same lifetime on a trait succeeds. See issue #10766.
+
+#![allow(dead_code)]
+fn main() {
+ trait T {}
+
+ fn f<'a, V: T>(v: &'a V) -> &'a T {
+ v as &'a T
+ }
+}
pub fn main() {
assert!(Some(box() ()).is_some());
+ let xs: Box<[()]> = box [];
+ assert!(Some(xs).is_some());
+
struct Foo;
assert!(Some(box Foo).is_some());
+
+ let ys: Box<[Foo]> = box [];
+ assert!(Some(ys).is_some());
}
+++ /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.
-
-
-// The `for` loop use to keep a mutable borrow when executing its body,
-// making it impossible to re-use the iterator as follows.
-// https://github.com/rust-lang/rust/issues/8372
-//
-// This was fixed in https://github.com/rust-lang/rust/pull/15809
-
-pub fn main() {
- let mut for_loop_values = Vec::new();
- let mut explicit_next_call_values = Vec::new();
-
- let mut iter = range(1i, 10);
- for i in iter {
- for_loop_values.push(i);
- explicit_next_call_values.push(iter.next());
- }
-
- assert_eq!(for_loop_values, vec![1, 3, 5, 7, 9]);
- assert_eq!(explicit_next_call_values, vec![Some(2), Some(4), Some(6), Some(8), None]);
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
struct Foo(int, int, int, int);
struct Bar{a: int, b: int, c: int, d: int}
let mut result = vec!();
loop {
x = match x {
- [1, n, 3, ..rest] => {
+ [1, n, 3, rest..] => {
result.push(n);
rest
}
- [n, ..rest] => {
+ [n, rest..] => {
result.push(n);
rest
}
match v {
[] => 0,
[_] => 1,
- [_x, ..xs] => 1 + count_members(xs)
+ [_x, xs..] => 1 + count_members(xs)
}
}
--- /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.
+
+static X: u64 = -1 as u16 as u64;
+static Y: u64 = -1 as u32 as u64;
+
+fn main() {
+ assert_eq!(match 1 {
+ X => unreachable!(),
+ Y => unreachable!(),
+ _ => 1i
+ }, 1);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn foo<T: Add<T, T> + Clone>([x, y, z]: [T, ..3]) -> (T, T, T) {
(x.clone(), x.clone() + y.clone(), x + y + z)
}
assert_eq!(d, "baz");
let out = bar("baz", "foo");
- let [a, ..xs, d] = out;
+ let [a, xs.., d] = out;
assert_eq!(a, "baz");
assert!(xs == ["foo", "foo"]);
assert_eq!(d, "baz");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
match (l1, l2) {
([], []) => "both empty",
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Foo<'a>(&'a [int]);
+
+fn main() {
+ let x: &[int] = &[1i, 2, 3];
+ let y = (x,);
+ assert_eq!(y.0, x);
+
+ let x: &[int] = &[1i, 2, 3];
+ let y = Foo(x);
+ assert_eq!(y.0, x);
+}
--- /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.
+
+#![feature(tuple_indexing)]
+
+struct Point(int, int);
+
+fn main() {
+ let mut x = Point(3, 2);
+ assert_eq!(x.0, 3);
+ assert_eq!(x.1, 2);
+ x.0 += 5;
+ assert_eq!(x.0, 8);
+ {
+ let ry = &mut x.1;
+ *ry -= 2;
+ x.0 += 3;
+ assert_eq!(x.0, 11);
+ }
+ assert_eq!(x.1, 0);
+
+ let mut x = (3i, 2i);
+ assert_eq!(x.0, 3);
+ assert_eq!(x.1, 2);
+ x.0 += 5;
+ assert_eq!(x.0, 8);
+ {
+ let ry = &mut x.1;
+ *ry -= 2;
+ x.0 += 3;
+ assert_eq!(x.0, 11);
+ }
+ assert_eq!(x.1, 0);
+
+}
--- /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.
+//
+// This code used to produce the following ICE:
+//
+// error: internal compiler error: get_unique_type_id_of_type() -
+// unexpected type: closure,
+// ty_unboxed_closure(syntax::ast::DefId{krate: 0u32, node: 66u32},
+// ReScope(63u32))
+//
+// This is a regression test for issue #17021.
+
+#![feature(unboxed_closures, overloaded_calls)]
+
+use std::ptr;
+
+pub fn replace_map<'a, T, F>(src: &mut T, prod: F)
+where F: |: T| -> T {
+ unsafe { *src = prod(ptr::read(src as *mut T as *const T)); }
+}
+
+pub fn main() {
+ let mut a = 7u;
+ let b = &mut a;
+ replace_map(b, |: x: uint| x * 2);
+ assert_eq!(*b, 14u);
+}
enum E<Sized? X> {}
impl <Sized? X> T1 for S1<X> {}
fn f<Sized? X>() {}
+type TT<Sized? T> = T;
pub fn main() {
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn a() {
let x = [1i, 2, 3];
match x {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn foldl<T,U:Clone>(values: &[T],
initial: U,
function: |partial: U, element: &T| -> U)
-> U {
match values {
- [ref head, ..tail] =>
+ [ref head, tail..] =>
foldl(tail, function(initial, head), function),
[] => initial.clone()
}
function: |element: &T, partial: U| -> U)
-> U {
match values {
- [..head, ref tail] =>
+ [head.., ref tail] =>
foldr(head, function(tail, initial), function),
[] => initial.clone()
}
let x: &[int] = &[1, 2, 3, 4, 5];
if !x.is_empty() {
let el = match x {
- [1, ..ref tail] => &tail[0],
+ [1, ref tail..] => &tail[0],
_ => unreachable!()
};
println!("{}", *el);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(advanced_slice_patterns)]
+
fn a() {
let x = [1i];
match x {
fn b() {
let x = [1i, 2, 3];
match x {
- [a, b, ..c] => {
+ [a, b, c..] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
let expected: &[_] = &[3];
}
}
match x {
- [..a, b, c] => {
+ [a.., b, c] => {
let expected: &[_] = &[1];
assert_eq!(a, expected);
assert_eq!(b, 2);
}
}
match x {
- [a, ..b, c] => {
+ [a, b.., c] => {
assert_eq!(a, 1);
let expected: &[_] = &[2];
assert_eq!(b, expected);
Foo { string: "baz".to_string() }
];
match x {
- [ref first, ..tail] => {
+ [ref first, tail..] => {
assert!(first.string == "foo".to_string());
assert_eq!(tail.len(), 2);
assert!(tail[0].string == "bar".to_string());
assert!(tail[1].string == "baz".to_string());
match tail {
- [Foo { .. }, _, Foo { .. }, .. _tail] => {
+ [Foo { .. }, _, Foo { .. }, _tail..] => {
unreachable!();
}
[Foo { string: ref a }, Foo { string: ref b }] => {