auto merge of #17629 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2014-09-29 17:18:07 +00:00
commit 1f3cda8bd8
74 changed files with 727 additions and 279 deletions

8
configure vendored
View File

@ -453,12 +453,12 @@ valopt datadir "${CFG_PREFIX}/share" "install data"
valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
valopt release-channel "source" "the name of the release channel to build"
valopt release-channel "dev" "the name of the release channel to build"
# On windows we just store the libraries in the bin directory because
# there's no rpath. This is where the build system itself puts libraries;
# --libdir is used to configure the installation directory.
# FIXME: Thise needs to parameterized over target triples. Do it in platform.mk
# FIXME: This needs to parameterized over target triples. Do it in platform.mk
CFG_LIBDIR_RELATIVE=lib
if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
then
@ -479,10 +479,10 @@ validate_opt
# Validate the release channel
case "$CFG_RELEASE_CHANNEL" in
(source | nightly | beta | stable)
(dev | nightly | beta | stable)
;;
(*)
err "release channel must be 'source', 'nightly', 'beta' or 'stable'"
err "release channel must be 'dev', 'nightly', 'beta' or 'stable'"
;;
esac

View File

@ -71,7 +71,7 @@ DEPS_graphviz := std
DEPS_green := std native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
DEPS_syntax := std term serialize log fmt_macros debug arena
DEPS_syntax := std term serialize log fmt_macros debug arena libc
DEPS_rustc := syntax flate arena serialize getopts rbml \
time log graphviz debug rustc_llvm rustc_back
DEPS_rustc_llvm := native:rustllvm libc std

View File

@ -35,9 +35,9 @@ ifeq ($(CFG_RELEASE_CHANNEL),nightly)
CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
CFG_PACKAGE_VERS=nightly
endif
ifeq ($(CFG_RELEASE_CHANNEL),source)
CFG_RELEASE=$(CFG_RELEASE_NUM)-pre
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-pre
ifeq ($(CFG_RELEASE_CHANNEL),dev)
CFG_RELEASE=$(CFG_RELEASE_NUM)-dev
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-dev
endif
# The name of the package to use for creating tarballs, installers etc.

View File

@ -4325,8 +4325,6 @@ and so we tell it that we want a vector of integers.
is one:
```{rust}
let one_to_one_hundred = range(0i, 100i);
let greater_than_forty_two = range(0i, 100i)
.find(|x| *x >= 42);

View File

@ -8,7 +8,7 @@
SetupIconFile=rust-logo.ico
AppName=Rust
AppVersion={#CFG_RELEASE}
AppCopyright=Copyright (C) 2006-2013 Mozilla Foundation, MIT license
AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license
AppPublisher=Mozilla Foundation
AppPublisherURL=http://www.rust-lang.org
VersionInfoVersion={#CFG_VERSION_WIN}
@ -43,7 +43,7 @@ Source: "tmp/dist/win/*.*" ; DestDir: "{app}"; Flags: ignoreversion recursesubdi
[Code]
const
ModPathName = 'modifypath';
ModPathType = 'user';
ModPathType = 'system';
function ModPathDir(): TArrayOfString;
begin

View File

@ -120,10 +120,9 @@ LIT_INTEGER
| '0x' [0-9a-fA-F][0-9a-fA-F_]* INT_SUFFIX?
;
FLOAT_SUFFIX
fragment FLOAT_SUFFIX
: 'f32'
| 'f64'
| 'f128'
;
LIT_FLOAT

View File

@ -96,12 +96,6 @@ pub trait BoxAny {
/// `Err(Self)` if it isn't.
#[unstable = "naming conventions around accessing innards may change"]
fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
/// Deprecated; this method has been renamed to `downcast`.
#[deprecated = "use downcast instead"]
fn move<T: 'static>(self) -> Result<Box<T>, Self> {
self.downcast::<T>()
}
}
#[stable]

View File

@ -16,7 +16,7 @@ use core::raw;
#[inline]
#[deprecated]
pub fn get_box_size(body_size: uint, body_align: uint) -> uint {
let header_size = mem::size_of::<raw::Box<()>>();
let header_size = mem::size_of::<raw::GcBox<()>>();
let total_size = align_to(header_size, body_align) + body_size;
total_size
}

View File

@ -16,7 +16,7 @@
use core::prelude::*;
use core::fmt;
#[deriving(Clone, PartialEq, Eq, Hash)]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// A specialized `Set` implementation to use enum types.
pub struct EnumSet<E> {
// We must maintain the invariant that no bits are set

View File

@ -18,6 +18,7 @@ use core::default::Default;
use core::fmt;
use core::mem;
use core::ptr;
use core::ops;
// FIXME: ICE's abound if you import the `Slice` type while importing `Slice` trait
use core::raw::Slice as RawSlice;
@ -530,7 +531,7 @@ impl String {
/// assert_eq!(s.as_slice(), "abc123");
/// ```
#[inline]
#[stable = "function just renamed from push"]
#[stable = "function just renamed from push_char"]
pub fn push(&mut self, ch: char) {
let cur_len = self.len();
// This may use up to 4 bytes.
@ -926,6 +927,28 @@ impl<S: Str> Add<S, String> for String {
}
}
impl ops::Slice<uint, str> for String {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a str {
self.as_slice()
}
#[inline]
fn slice_from_<'a>(&'a self, from: &uint) -> &'a str {
self[][*from..]
}
#[inline]
fn slice_to_<'a>(&'a self, to: &uint) -> &'a str {
self[][..*to]
}
#[inline]
fn slice_<'a>(&'a self, from: &uint, to: &uint) -> &'a str {
self[][*from..*to]
}
}
/// Unsafe operations
#[unstable = "waiting on raw module conventions"]
pub mod raw {
@ -1290,6 +1313,15 @@ mod tests {
#[test] #[should_fail] fn insert_bad1() { "".to_string().insert(1, 't'); }
#[test] #[should_fail] fn insert_bad2() { "".to_string().insert(1, 't'); }
#[test]
fn test_slicing() {
let s = "foobar".to_string();
assert_eq!("foobar", s[]);
assert_eq!("foo", s[..3]);
assert_eq!("bar", s[3..]);
assert_eq!("oob", s[1..4]);
}
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| {

View File

@ -2393,8 +2393,6 @@ mod tests {
let _ = vec[3];
}
// NOTE uncomment after snapshot
/*
#[test]
#[should_fail]
fn test_slice_out_of_bounds_1() {
@ -2429,7 +2427,6 @@ mod tests {
let x: Vec<int> = vec![1, 2, 3, 4, 5];
x[3..2];
}
*/
#[test]
fn test_swap_remove_empty() {

View File

@ -33,24 +33,9 @@
use fmt;
use intrinsics;
// NOTE: remove after next snapshot
#[cfg(stage0)]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail_"]
fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
let (expr, file, line) = *expr_file_line;
let ref file_line = (file, line);
format_args!(|args| -> () {
fail_fmt(args, file_line);
}, "{}", expr);
unsafe { intrinsics::abort() }
}
#[cfg(not(stage0))]
#[cold] #[inline(never)] // this is the slow path, always
#[lang="fail"]
fn fail(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
pub fn fail(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
let (expr, file, line) = *expr_file_line;
let ref file_line = (file, line);
format_args!(|args| -> () {
@ -70,23 +55,10 @@ fn fail_bounds_check(file_line: &(&'static str, uint),
unsafe { intrinsics::abort() }
}
#[cold] #[inline(never)]
pub fn fail_str(msg: &str, file: &(&'static str, uint)) -> ! {
format_args!(|fmt| fail_fmt(fmt, file), "{}", msg)
}
#[cold] #[inline(never)]
pub fn fail_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
#[allow(ctypes)]
extern {
// NOTE: remove after next snapshot
#[cfg(stage0)]
#[lang = "begin_unwind"]
fn fail_impl(fmt: &fmt::Arguments, file: &'static str,
line: uint) -> !;
#[cfg(not(stage0))]
#[lang = "fail_fmt"]
fn fail_impl(fmt: &fmt::Arguments, file: &'static str,
line: uint) -> !;

View File

@ -366,7 +366,7 @@ pub trait Iterator<A> {
/// let mut sum = 0;
/// for x in it {
/// if x > 5 {
/// continue;
/// break;
/// }
/// sum += x;
/// }
@ -377,6 +377,8 @@ pub trait Iterator<A> {
/// sum
/// }
/// let x = vec![1i,2,3,7,8,9];
/// assert_eq!(process(x.into_iter()), 6);
/// let x = vec![1i,2,3];
/// assert_eq!(process(x.into_iter()), 1006);
/// ```
#[inline]

View File

@ -17,8 +17,8 @@ macro_rules! fail(
fail!("{}", "explicit failure")
);
($msg:expr) => ({
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::failure::fail_str($msg, &_FILE_LINE)
static _MSG_FILE_LINE: (&'static str, &'static str, uint) = ($msg, file!(), line!());
::core::failure::fail(&_MSG_FILE_LINE)
});
($fmt:expr, $($arg:tt)*) => ({
// a closure can't have return type !, so we need a full

View File

@ -764,13 +764,13 @@ pub trait Slice<Idx, Sized? Result> for Sized? {
// FIXME(#17273) remove the postscript _s
#[lang="slice_mut"]
pub trait SliceMut<Idx, Sized? Result> for Sized? {
/// The method for the slicing operation foo[]
/// The method for the slicing operation foo[mut]
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
/// The method for the slicing operation foo[from..]
/// The method for the slicing operation foo[mut from..]
fn slice_from_mut_<'a>(&'a mut self, from: &Idx) -> &'a mut Result;
/// The method for the slicing operation foo[..to]
/// The method for the slicing operation foo[mut ..to]
fn slice_to_mut_<'a>(&'a mut self, to: &Idx) -> &'a mut Result;
/// The method for the slicing operation foo[from..to]
/// The method for the slicing operation foo[mut from..to]
fn slice_mut_<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
}
/**

View File

@ -312,7 +312,7 @@ impl<T> Option<T> {
pub fn expect(self, msg: &str) -> T {
match self {
Some(val) => val,
None => fail!(msg),
None => fail!("{}", msg),
}
}

View File

@ -20,12 +20,12 @@
use mem;
/// The representation of a Rust managed box
pub struct Box<T> {
/// The representation of `std::gc::Gc`.
pub struct GcBox<T> {
pub ref_count: uint,
pub drop_glue: fn(ptr: *mut u8),
pub prev: *mut Box<T>,
pub next: *mut Box<T>,
pub prev: *mut GcBox<T>,
pub next: *mut GcBox<T>,
pub data: T,
}

View File

@ -1123,6 +1123,7 @@ pub mod traits {
use collections::Collection;
use iter::Iterator;
use option::{Option, Some};
use ops;
use str::{Str, StrSlice, eq_slice};
impl<'a> Ord for &'a str {
@ -1162,6 +1163,28 @@ pub mod traits {
#[inline]
fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) }
}
impl ops::Slice<uint, str> for str {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a str {
self
}
#[inline]
fn slice_from_<'a>(&'a self, from: &uint) -> &'a str {
self.slice_from(*from)
}
#[inline]
fn slice_to_<'a>(&'a self, to: &uint) -> &'a str {
self.slice_to(*to)
}
#[inline]
fn slice_<'a>(&'a self, from: &uint, to: &uint) -> &'a str {
self.slice(*from, *to)
}
}
}
/// Any string that can be represented as a slice

View File

@ -277,7 +277,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
try!(self, self.writer.write("box(GC) ".as_bytes()));
self.write_mut_qualifier(mtbl);
self.get::<&raw::Box<()>>(|this, b| {
self.get::<&raw::GcBox<()>>(|this, b| {
let p = &b.data as *const () as *const u8;
this.visit_ptr_inner(p, inner)
})

View File

@ -1319,6 +1319,18 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
sess.abort_if_errors();
}
}
// Fix up permissions of the copy, as fs::copy() preserves
// permissions, but the original file may have been installed
// by a package manager and may be read-only.
match fs::chmod(&dst, io::UserRead | io::UserWrite) {
Ok(..) => {}
Err(e) => {
sess.err(format!("failed to chmod {} when preparing \
for LTO: {}", dst.display(),
e).as_slice());
sess.abort_if_errors();
}
}
let handler = &sess.diagnostic().handler;
let config = ArchiveConfig {
handler: handler,

View File

@ -16,6 +16,7 @@ use driver::session::Session;
use driver::config;
use llvm;
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
use llvm::SMDiagnosticRef;
use util::common::time;
use syntax::abi;
use syntax::codemap;
@ -326,14 +327,40 @@ impl<'a> CodegenContext<'a> {
}
}
struct DiagHandlerFreeVars<'a> {
struct HandlerFreeVars<'a> {
llcx: ContextRef,
cgcx: &'a CodegenContext<'a>,
}
unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
user: *const c_void,
cookie: c_uint) {
use syntax::codemap::ExpnId;
let HandlerFreeVars { cgcx, .. }
= *mem::transmute::<_, *const HandlerFreeVars>(user);
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
.expect("non-UTF8 SMDiagnostic");
match cgcx.lto_ctxt {
Some((sess, _)) => {
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
Some(ei) => sess.span_err(ei.call_site, msg.as_slice()),
None => sess.err(msg.as_slice()),
});
}
None => {
cgcx.handler.err(msg.as_slice());
cgcx.handler.note("build without -C codegen-units for more exact errors");
}
}
}
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
let DiagHandlerFreeVars { llcx, cgcx }
= *mem::transmute::<_, *const DiagHandlerFreeVars>(user);
let HandlerFreeVars { llcx, cgcx }
= *mem::transmute::<_, *const HandlerFreeVars>(user);
match llvm::diagnostic::Diagnostic::unpack(info) {
llvm::diagnostic::Optimization(opt) => {
@ -368,14 +395,16 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
let tm = config.tm;
// llcx doesn't outlive this function, so we can put this on the stack.
let fv = DiagHandlerFreeVars {
let fv = HandlerFreeVars {
llcx: llcx,
cgcx: cgcx,
};
let fv = &fv as *const HandlerFreeVars as *mut c_void;
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
if !cgcx.remark.is_empty() {
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler,
&fv as *const DiagHandlerFreeVars
as *mut c_void);
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
}
if config.emit_no_opt_bc {

View File

@ -288,8 +288,9 @@ pub fn phase_2_configure_and_expand(sess: &Session,
os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap());
}
let cfg = syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: sess.features.borrow().default_type_params,
crate_name: crate_name.to_string(),
deriving_hash_type_parameter: sess.features.borrow().default_type_params,
enable_quotes: sess.features.borrow().quote,
};
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
@ -556,6 +557,8 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
sess.opts.output_types.as_slice(),
outputs));
}
sess.abort_if_errors();
}
/// Run the linker on any artifacts that resulted from the LLVM run.

View File

@ -32,7 +32,6 @@ This API is completely unstable and subject to change.
#![feature(macro_rules, globs, struct_variant, quote)]
#![feature(default_type_params, phase, unsafe_destructor)]
#![allow(unknown_features)] // NOTE: Remove after next snapshot
#![feature(rustc_diagnostic_macros)]
#![feature(import_shadowing)]

View File

@ -652,12 +652,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
debug!("check_if_path_is_moved(id={:?}, use_kind={:?}, lp={})",
id, use_kind, lp.repr(self.bccx.tcx));
let base_lp = owned_ptr_base_path_rc(lp);
self.move_data.each_move_of(id, &base_lp, |move, moved_lp| {
self.move_data.each_move_of(id, &base_lp, |the_move, moved_lp| {
self.bccx.report_use_of_moved_value(
span,
use_kind,
&**lp,
move,
the_move,
moved_lp);
false
});

View File

@ -108,8 +108,8 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
let move_index_to_path = |move_index| {
let move_data = &self.analysis_data.move_data.move_data;
let moves = move_data.moves.borrow();
let move = moves.get(move_index);
move_data.path_loan_path(move.path)
let the_move = moves.get(move_index);
move_data.path_loan_path(the_move.path)
};
self.build_set(e, cfgidx, dfcx, move_index_to_path)
}

View File

@ -409,14 +409,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
use_span: Span,
use_kind: MovedValueUseKind,
lp: &LoanPath,
move: &move_data::Move,
the_move: &move_data::Move,
moved_lp: &LoanPath) {
let verb = match use_kind {
MovedInUse => "use",
MovedInCapture => "capture",
};
match move.kind {
match the_move.kind {
move_data::Declared => {
self.tcx.sess.span_err(
use_span,
@ -435,18 +435,20 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
}
match move.kind {
match the_move.kind {
move_data::Declared => {}
move_data::MoveExpr => {
let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
let (expr_ty, expr_span) = match self.tcx
.map
.find(the_move.id) {
Some(ast_map::NodeExpr(expr)) => {
(ty::expr_ty_adjusted(self.tcx, &*expr), expr.span)
}
r => {
self.tcx.sess.bug(format!("MoveExpr({:?}) maps to \
{:?}, not Expr",
move.id,
the_move.id,
r).as_slice())
}
};
@ -461,8 +463,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
move_data::MovePat => {
let pat_ty = ty::node_id_to_type(self.tcx, move.id);
self.tcx.sess.span_note(self.tcx.map.span(move.id),
let pat_ty = ty::node_id_to_type(self.tcx, the_move.id);
self.tcx.sess.span_note(self.tcx.map.span(the_move.id),
format!("`{}` moved here because it has type `{}`, \
which is moved by default (use `ref` to \
override)",
@ -471,14 +473,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
move_data::Captured => {
let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
let (expr_ty, expr_span) = match self.tcx
.map
.find(the_move.id) {
Some(ast_map::NodeExpr(expr)) => {
(ty::expr_ty_adjusted(self.tcx, &*expr), expr.span)
}
r => {
self.tcx.sess.bug(format!("Captured({:?}) maps to \
{:?}, not Expr",
move.id,
the_move.id,
r).as_slice())
}
};

View File

@ -413,8 +413,8 @@ impl MoveData {
* killed by scoping. See `doc.rs` for more details.
*/
for (i, move) in self.moves.borrow().iter().enumerate() {
dfcx_moves.add_gen(move.id, i);
for (i, the_move) in self.moves.borrow().iter().enumerate() {
dfcx_moves.add_gen(the_move.id, i);
}
for (i, assignment) in self.var_assignments.borrow().iter().enumerate() {
@ -577,10 +577,10 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
let mut ret = None;
for loan_path_index in self.move_data.path_map.borrow().find(&*loan_path).iter() {
self.dfcx_moves.each_gen_bit(id, |move_index| {
let move = self.move_data.moves.borrow();
let move = move.get(move_index);
if move.path == **loan_path_index {
ret = Some(move.kind);
let the_move = self.move_data.moves.borrow();
let the_move = the_move.get(move_index);
if the_move.path == **loan_path_index {
ret = Some(the_move.kind);
false
} else {
true
@ -622,13 +622,13 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
let mut ret = true;
self.dfcx_moves.each_bit_on_entry(id, |index| {
let move = self.move_data.moves.borrow();
let move = move.get(index);
let moved_path = move.path;
let the_move = self.move_data.moves.borrow();
let the_move = the_move.get(index);
let moved_path = the_move.path;
if base_indices.iter().any(|x| x == &moved_path) {
// Scenario 1 or 2: `loan_path` or some base path of
// `loan_path` was moved.
if !f(move, &*self.move_data.path_loan_path(moved_path)) {
if !f(the_move, &*self.move_data.path_loan_path(moved_path)) {
ret = false;
}
} else {
@ -637,7 +637,8 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
if p == loan_path_index {
// Scenario 3: some extension of `loan_path`
// was moved
f(move, &*self.move_data.path_loan_path(moved_path))
f(the_move,
&*self.move_data.path_loan_path(moved_path))
} else {
true
}

View File

@ -25,6 +25,7 @@ use middle::trans::type_::Type;
use std::c_str::ToCStr;
use std::string::String;
use syntax::ast;
use libc::{c_uint, c_char};
// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
@ -141,6 +142,19 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
}
}
// Store expn_id in a metadata node so we can map LLVM errors
// back to source locations. See #17552.
unsafe {
let key = "srcloc";
let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
key.as_ptr() as *const c_char, key.len() as c_uint);
let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie());
llvm::LLVMSetMetadata(r, kind,
llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
}
return bcx;
}

View File

@ -1405,6 +1405,37 @@ fn check_cast(fcx: &FnCtxt,
return
}
if !ty::type_is_sized(fcx.tcx(), t_1) {
let tstr = fcx.infcx().ty_to_string(t_1);
fcx.type_error_message(span, |actual| {
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
}, t_e, None);
match ty::get(t_e).sty {
ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
let mtstr = match mt {
ast::MutMutable => "mut ",
ast::MutImmutable => ""
};
if ty::type_is_trait(t_1) {
span_note!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
} else {
span_note!(fcx.tcx().sess, span,
"consider using an implicit coercion to `&{}{}` instead",
mtstr, tstr);
}
}
ty::ty_uniq(..) => {
span_note!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
}
_ => {
span_note!(fcx.tcx().sess, e.span,
"consider using a box or reference as appropriate");
}
}
fcx.write_error(id);
return
}
if ty::type_is_trait(t_1) {
// This will be looked up later on.
vtable2::check_object_cast(fcx, cast_expr, e, t_1);

View File

@ -49,8 +49,8 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
// FIXME -- it seems like this method actually pushes
// duplicate impls onto the list
ty::populate_implementations_for_type_if_necessary(self.tcx,
trait_def_id);
ty::populate_implementations_for_trait_if_necessary(self.tcx,
trait_def_id);
let mut impls = Vec::new();
self.push_impls_of_trait(trait_def_id, &mut impls);

View File

@ -424,8 +424,11 @@ pub enum DiagnosticInfo_opaque {}
pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque;
pub enum DebugLoc_opaque {}
pub type DebugLocRef = *mut DebugLoc_opaque;
pub enum SMDiagnostic_opaque {}
pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
pub mod debuginfo {
use super::{ValueRef};
@ -1967,6 +1970,12 @@ extern {
pub fn LLVMGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind;
pub fn LLVMWriteDebugLocToString(C: ContextRef, DL: DebugLocRef, s: RustStringRef);
pub fn LLVMSetInlineAsmDiagnosticHandler(C: ContextRef,
H: InlineAsmDiagHandler,
CX: *mut c_void);
pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
}
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {

View File

@ -641,11 +641,27 @@ impl Clean<Option<Lifetime>> for ty::Region {
}
}
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct WherePredicate {
pub name: String,
pub bounds: Vec<TyParamBound>
}
impl Clean<WherePredicate> for ast::WherePredicate {
fn clean(&self, cx: &DocContext) -> WherePredicate {
WherePredicate {
name: self.ident.clean(cx),
bounds: self.bounds.clean(cx)
}
}
}
// maybe use a Generic enum and use ~[Generic]?
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,
pub type_params: Vec<TyParam>,
pub where_predicates: Vec<WherePredicate>
}
impl Clean<Generics> for ast::Generics {
@ -653,6 +669,7 @@ impl Clean<Generics> for ast::Generics {
Generics {
lifetimes: self.lifetimes.clean(cx),
type_params: self.ty_params.clean(cx),
where_predicates: self.where_clause.predicates.clean(cx)
}
}
}
@ -663,6 +680,7 @@ impl<'a> Clean<Generics> for (&'a ty::Generics, subst::ParamSpace) {
Generics {
type_params: me.types.get_slice(space).to_vec().clean(cx),
lifetimes: me.regions.get_slice(space).to_vec().clean(cx),
where_predicates: vec![]
}
}
}
@ -1260,7 +1278,9 @@ impl Clean<Type> for ty::t {
ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl {
fn_style: fty.fn_style,
generics: Generics {
lifetimes: Vec::new(), type_params: Vec::new()
lifetimes: Vec::new(),
type_params: Vec::new(),
where_predicates: Vec::new()
},
decl: (ast_util::local_def(0), &fty.sig).clean(cx),
abi: fty.abi.to_string(),
@ -1670,6 +1690,7 @@ impl Clean<BareFunctionDecl> for ast::BareFnTy {
generics: Generics {
lifetimes: self.lifetimes.clean(cx),
type_params: Vec::new(),
where_predicates: Vec::new()
},
decl: self.decl.clean(cx),
abi: self.abi.to_string(),
@ -2172,6 +2193,7 @@ impl Clean<Item> for ast::Typedef {
generics: Generics {
lifetimes: Vec::new(),
type_params: Vec::new(),
where_predicates: Vec::new()
},
}),
visibility: None,

View File

@ -44,6 +44,11 @@ pub struct RawMutableSpace(pub clean::Mutability);
pub struct Stability<'a>(pub &'a Option<clean::Stability>);
/// Wrapper struct for emitting the stability level concisely.
pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
/// Wrapper struct for emitting a where clause from Generics.
pub struct WhereClause<'a>(pub &'a clean::Generics);
/// Wrapper struct for emitting type parameter bounds.
struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
impl VisSpace {
pub fn get(&self) -> Option<ast::Visibility> {
@ -57,6 +62,19 @@ impl FnStyleSpace {
}
}
impl<'a> fmt::Show for TyParamBounds<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &TyParamBounds(bounds) = self;
for (i, bound) in bounds.iter().enumerate() {
if i > 0 {
try!(f.write(" + ".as_bytes()));
}
try!(write!(f, "{}", *bound));
}
Ok(())
}
}
impl fmt::Show for clean::Generics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.lifetimes.len() == 0 && self.type_params.len() == 0 { return Ok(()) }
@ -73,7 +91,6 @@ impl fmt::Show for clean::Generics {
if self.lifetimes.len() > 0 {
try!(f.write(", ".as_bytes()));
}
for (i, tp) in self.type_params.iter().enumerate() {
if i > 0 {
try!(f.write(", ".as_bytes()))
@ -81,13 +98,7 @@ impl fmt::Show for clean::Generics {
try!(f.write(tp.name.as_bytes()));
if tp.bounds.len() > 0 {
try!(f.write(": ".as_bytes()));
for (i, bound) in tp.bounds.iter().enumerate() {
if i > 0 {
try!(f.write(" + ".as_bytes()));
}
try!(write!(f, "{}", *bound));
}
try!(write!(f, ": {}", TyParamBounds(tp.bounds.as_slice())));
}
match tp.default {
@ -101,6 +112,24 @@ impl fmt::Show for clean::Generics {
}
}
impl<'a> fmt::Show for WhereClause<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &WhereClause(gens) = self;
if gens.where_predicates.len() == 0 {
return Ok(());
}
try!(f.write(" where ".as_bytes()));
for (i, pred) in gens.where_predicates.iter().enumerate() {
if i > 0 {
try!(f.write(", ".as_bytes()));
}
let bounds = pred.bounds.as_slice();
try!(write!(f, "{}: {}", pred.name, TyParamBounds(bounds)));
}
Ok(())
}
}
impl fmt::Show for clean::Lifetime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write(self.get_ref().as_bytes()));

View File

@ -56,7 +56,7 @@ use clean;
use doctree;
use fold::DocFolder;
use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
use html::format::{ConciseStability};
use html::format::{ConciseStability, WhereClause};
use html::highlight;
use html::item_type::{ItemType, shortty};
use html::item_type;
@ -1610,11 +1610,12 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
f: &clean::Function) -> fmt::Result {
try!(write!(w, "<pre class='rust fn'>{vis}{fn_style}fn \
{name}{generics}{decl}</pre>",
{name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(it.visibility),
fn_style = FnStyleSpace(f.fn_style),
name = it.name.get_ref().as_slice(),
generics = f.generics,
where_clause = WhereClause(&f.generics),
decl = f.decl));
document(w, it)
}
@ -1631,11 +1632,12 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
}
// Output the trait definition
try!(write!(w, "<pre class='rust trait'>{}trait {}{}{} ",
try!(write!(w, "<pre class='rust trait'>{}trait {}{}{}{} ",
VisSpace(it.visibility),
it.name.get_ref().as_slice(),
t.generics,
bounds));
bounds,
WhereClause(&t.generics)));
let required = t.items.iter()
.filter(|m| {
match **m {
@ -1719,9 +1721,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
match cache.implementors.find(&it.def_id) {
Some(implementors) => {
for i in implementors.iter() {
try!(writeln!(w, "<li>{}<code>impl{} {} for {}</code></li>",
try!(writeln!(w, "<li>{}<code>impl{} {} for {}{}</code></li>",
ConciseStability(&i.stability),
i.generics, i.trait_, i.for_));
i.generics, i.trait_, i.for_, WhereClause(&i.generics)));
}
}
None => {}
@ -1747,7 +1749,7 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
g: &clean::Generics, selfty: &clean::SelfTy,
d: &clean::FnDecl) -> fmt::Result {
write!(w, "{}fn <a href='#{ty}.{name}' class='fnname'>{name}</a>\
{generics}{decl}",
{generics}{decl}{where_clause}",
match fn_style {
ast::UnsafeFn => "unsafe ",
_ => "",
@ -1755,7 +1757,8 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
ty = shortty(it),
name = it.name.get_ref().as_slice(),
generics = *g,
decl = Method(selfty, d))
decl = Method(selfty, d),
where_clause = WhereClause(g))
}
match meth.inner {
clean::TyMethodItem(ref m) => {
@ -1810,10 +1813,11 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
e: &clean::Enum) -> fmt::Result {
try!(write!(w, "<pre class='rust enum'>{}enum {}{}",
try!(write!(w, "<pre class='rust enum'>{}enum {}{}{}",
VisSpace(it.visibility),
it.name.get_ref().as_slice(),
e.generics));
e.generics,
WhereClause(&e.generics)));
if e.variants.len() == 0 && !e.variants_stripped {
try!(write!(w, " {{}}"));
} else {
@ -1917,7 +1921,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
if structhead {"struct "} else {""},
it.name.get_ref().as_slice()));
match g {
Some(g) => try!(write!(w, "{}", *g)),
Some(g) => try!(write!(w, "{}{}", *g, WhereClause(g))),
None => {}
}
match ty {
@ -2009,7 +2013,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
Some(ref ty) => try!(write!(w, "{} for ", *ty)),
None => {}
}
try!(write!(w, "{}</code></h3>", i.impl_.for_));
try!(write!(w, "{}{}</code></h3>", i.impl_.for_, WhereClause(&i.impl_.generics)));
match i.dox {
Some(ref dox) => {
try!(write!(w, "<div class='docblock'>{}</div>",

View File

@ -24,7 +24,7 @@ use task::Task;
static RC_IMMORTAL : uint = 0x77777777;
pub type Box = raw::Box<()>;
pub type Box = raw::GcBox<()>;
pub struct MemoryRegion {
live_allocations: uint,
@ -32,7 +32,7 @@ pub struct MemoryRegion {
pub struct LocalHeap {
memory_region: MemoryRegion,
live_allocs: *mut raw::Box<()>,
live_allocs: *mut raw::GcBox<()>,
}
impl LocalHeap {
@ -161,7 +161,7 @@ impl LocalHeap {
}
unsafe fn each_live_alloc(&mut self, read_next_before: bool,
f: |&mut LocalHeap, alloc: *mut raw::Box<()>|) {
f: |&mut LocalHeap, alloc: *mut raw::GcBox<()>|) {
//! Walks the internal list of allocations
let mut alloc = self.live_allocs;

View File

@ -37,11 +37,11 @@
//! In the cleanup phase, personality routines invoke cleanup code associated
//! with their stack frames (i.e. destructors). Once stack has been unwound down
//! to the handler frame level, unwinding stops and the last personality routine
//! transfers control to its' catch block.
//! transfers control to its catch block.
//!
//! ## Frame unwind info registration
//!
//! Each module has its' own frame unwind info section (usually ".eh_frame"), and
//! Each module has its own frame unwind info section (usually ".eh_frame"), and
//! unwinder needs to know about all of them in order for unwinding to be able to
//! cross module boundaries.
//!
@ -488,22 +488,13 @@ pub mod eabi {
}
// Entry point of failure from the libcore crate
#[cfg(not(test), not(stage0))]
#[cfg(not(test))]
#[lang = "fail_fmt"]
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
file: &'static str, line: uint) -> ! {
begin_unwind_fmt(msg, &(file, line))
}
//
// Entry point of failure from the libcore crate
#[cfg(stage0, not(test))]
#[lang = "begin_unwind"]
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
file: &'static str, line: uint) -> ! {
begin_unwind_fmt(msg, &(file, line))
}
/// The entry point for unwinding with a formatted message.
///
/// This is designed to reduce the amount of code required at the call

View File

@ -668,16 +668,23 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
if cnt == 0 {
escape_str(self.writer, name)
} else {
try!(write!(self.writer, "{{\n"));
self.curr_indent += self.indent;
try!(write!(self.writer, "[\n"));
try!(spaces(self.writer, self.curr_indent));
try!(write!(self.writer, "\"variant\": "));
try!(escape_str(self.writer, name));
try!(write!(self.writer, ",\n"));
try!(spaces(self.writer, self.curr_indent));
try!(write!(self.writer, "\"fields\": [\n"));
self.curr_indent += self.indent;
try!(f(self));
self.curr_indent -= self.indent;
try!(write!(self.writer, "\n"));
try!(spaces(self.writer, self.curr_indent));
write!(self.writer, "]")
self.curr_indent -= self.indent;
try!(write!(self.writer, "]\n"));
try!(spaces(self.writer, self.curr_indent));
write!(self.writer, "}}")
}
}
@ -2651,12 +2658,13 @@ mod tests {
let mut encoder = PrettyEncoder::new(writer);
animal.encode(&mut encoder).unwrap();
}),
"\
[\n \
\"Frog\",\n \
\"Henry\",\n \
349\n\
]".to_string()
"{\n \
\"variant\": \"Frog\",\n \
\"fields\": [\n \
\"Henry\",\n \
349\n \
]\n\
}".to_string()
);
}

View File

@ -93,6 +93,7 @@
///
/// - `BitOr`: union
/// - `BitAnd`: intersection
/// - `BitXor`: toggle
/// - `Sub`: set difference
/// - `Not`: set complement
///
@ -109,6 +110,8 @@
/// - `contains`: `true` all of the flags in `other` are contained within `self`
/// - `insert`: inserts the specified flags in-place
/// - `remove`: removes the specified flags in-place
/// - `toggle`: the specified flags will be inserted if not present, and removed
/// if they are.
#[macro_export]
macro_rules! bitflags {
($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
@ -184,6 +187,11 @@ macro_rules! bitflags {
pub fn remove(&mut self, other: $BitFlags) {
self.bits &= !other.bits;
}
/// Toggles the specified flags in-place.
pub fn toggle(&mut self, other: $BitFlags) {
self.bits ^= other.bits;
}
}
impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
@ -194,6 +202,14 @@ macro_rules! bitflags {
}
}
impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the left flags, but with all the right flags toggled.
#[inline]
fn bitxor(&self, other: &$BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits ^ other.bits }
}
}
impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the intersection between the two sets of flags.
#[inline]
@ -234,7 +250,7 @@ macro_rules! bitflags {
mod tests {
use hash;
use option::{Some, None};
use ops::{BitOr, BitAnd, Sub, Not};
use ops::{BitOr, BitAnd, BitXor, Sub, Not};
bitflags! {
#[doc = "> The first principle is that you must not fool yourself — and"]
@ -358,10 +374,14 @@ mod tests {
fn test_operators() {
let e1 = FlagA | FlagC;
let e2 = FlagB | FlagC;
assert!((e1 | e2) == FlagABC); // union
assert!((e1 & e2) == FlagC); // intersection
assert!((e1 - e2) == FlagA); // set difference
assert!(!e2 == FlagA); // set complement
assert!((e1 | e2) == FlagABC); // union
assert!((e1 & e2) == FlagC); // intersection
assert!((e1 - e2) == FlagA); // set difference
assert!(!e2 == FlagA); // set complement
assert!(e1 ^ e2 == FlagA | FlagB); // toggle
let mut e3 = e1;
e3.toggle(e2);
assert!(e3 == FlagA | FlagB);
}
#[test]

View File

@ -89,7 +89,7 @@ impl<T: Default + 'static> Default for Gc<T> {
}
}
impl<T: 'static> raw::Repr<*const raw::Box<T>> for Gc<T> {}
impl<T: 'static> raw::Repr<*const raw::GcBox<T>> for Gc<T> {}
impl<S: hash::Writer, T: hash::Hash<S> + 'static> hash::Hash<S> for Gc<T> {
fn hash(&self, s: &mut S) {

View File

@ -229,7 +229,7 @@ use int;
use iter::Iterator;
use libc;
use mem::transmute;
use ops::{BitOr, BitAnd, Sub, Not};
use ops::{BitOr, BitXor, BitAnd, Sub, Not};
use option::{Option, Some, None};
use os;
use boxed::Box;

View File

@ -10,7 +10,7 @@
// The Rust abstract syntax tree.
use codemap::{Span, Spanned, DUMMY_SP};
use codemap::{Span, Spanned, DUMMY_SP, ExpnId};
use abi::Abi;
use ast_util;
use owned_slice::OwnedSlice;
@ -983,7 +983,8 @@ pub struct InlineAsm {
pub clobbers: InternedString,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect
pub dialect: AsmDialect,
pub expn_id: ExpnId,
}
/// represents an argument in a function header

View File

@ -26,6 +26,7 @@ source code snippets, etc.
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::cell::RefCell;
use std::rc::Rc;
use libc::c_uint;
pub trait Pos {
fn from_uint(n: uint) -> Self;
@ -223,11 +224,22 @@ pub struct ExpnInfo {
pub callee: NameAndSpan
}
#[deriving(PartialEq, Eq, Clone, Show, Hash)]
#[deriving(PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)]
pub struct ExpnId(u32);
pub static NO_EXPANSION: ExpnId = ExpnId(-1);
impl ExpnId {
pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
ExpnId(cookie as u32)
}
pub fn to_llvm_cookie(self) -> i32 {
let ExpnId(cookie) = self;
cookie as i32
}
}
pub type FileName = String;
pub struct FileLines {

View File

@ -13,6 +13,7 @@
*/
use ast;
use codemap;
use codemap::Span;
use ext::base;
use ext::base::*;
@ -198,6 +199,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
}
}
let expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
call_site: sp,
callee: codemap::NameAndSpan {
name: "asm".to_string(),
format: codemap::MacroBang,
span: None,
},
});
MacExpr::new(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprInlineAsm(ast::InlineAsm {
@ -208,7 +218,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
clobbers: token::intern_and_get_ident(cons.as_slice()),
volatile: volatile,
alignstack: alignstack,
dialect: dialect
dialect: dialect,
expn_id: expn_id,
}),
span: sp
}))

View File

@ -344,7 +344,7 @@ impl BlockInfo {
/// The base map of methods for expanding syntax extension
/// AST nodes into full ASTs
fn initial_syntax_expander_table() -> SyntaxEnv {
fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
// utility function to simplify creating NormalTT syntax extensions
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
NormalTT(box f, None)
@ -383,31 +383,33 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
syntax_expanders.insert(intern("deriving"),
Decorator(box ext::deriving::expand_meta_deriving));
// Quasi-quoting expanders
syntax_expanders.insert(intern("quote_tokens"),
builtin_normal_expander(
ext::quote::expand_quote_tokens));
syntax_expanders.insert(intern("quote_expr"),
builtin_normal_expander(
ext::quote::expand_quote_expr));
syntax_expanders.insert(intern("quote_ty"),
builtin_normal_expander(
ext::quote::expand_quote_ty));
syntax_expanders.insert(intern("quote_method"),
builtin_normal_expander(
ext::quote::expand_quote_method));
syntax_expanders.insert(intern("quote_item"),
builtin_normal_expander(
ext::quote::expand_quote_item));
syntax_expanders.insert(intern("quote_pat"),
builtin_normal_expander(
ext::quote::expand_quote_pat));
syntax_expanders.insert(intern("quote_arm"),
builtin_normal_expander(
ext::quote::expand_quote_arm));
syntax_expanders.insert(intern("quote_stmt"),
builtin_normal_expander(
ext::quote::expand_quote_stmt));
if ecfg.enable_quotes {
// Quasi-quoting expanders
syntax_expanders.insert(intern("quote_tokens"),
builtin_normal_expander(
ext::quote::expand_quote_tokens));
syntax_expanders.insert(intern("quote_expr"),
builtin_normal_expander(
ext::quote::expand_quote_expr));
syntax_expanders.insert(intern("quote_ty"),
builtin_normal_expander(
ext::quote::expand_quote_ty));
syntax_expanders.insert(intern("quote_method"),
builtin_normal_expander(
ext::quote::expand_quote_method));
syntax_expanders.insert(intern("quote_item"),
builtin_normal_expander(
ext::quote::expand_quote_item));
syntax_expanders.insert(intern("quote_pat"),
builtin_normal_expander(
ext::quote::expand_quote_pat));
syntax_expanders.insert(intern("quote_arm"),
builtin_normal_expander(
ext::quote::expand_quote_arm));
syntax_expanders.insert(intern("quote_stmt"),
builtin_normal_expander(
ext::quote::expand_quote_stmt));
}
syntax_expanders.insert(intern("line"),
builtin_normal_expander(
@ -466,6 +468,7 @@ pub struct ExtCtxt<'a> {
impl<'a> ExtCtxt<'a> {
pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
let env = initial_syntax_expander_table(&ecfg);
ExtCtxt {
parse_sess: parse_sess,
cfg: cfg,
@ -474,7 +477,7 @@ impl<'a> ExtCtxt<'a> {
ecfg: ecfg,
trace_mac: false,
exported_macros: Vec::new(),
syntax_env: initial_syntax_expander_table(),
syntax_env: env,
}
}

View File

@ -975,8 +975,19 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
}
pub struct ExpansionConfig {
pub deriving_hash_type_parameter: bool,
pub crate_name: String,
pub deriving_hash_type_parameter: bool,
pub enable_quotes: bool,
}
impl ExpansionConfig {
pub fn default(crate_name: String) -> ExpansionConfig {
ExpansionConfig {
crate_name: crate_name,
deriving_hash_type_parameter: false,
enable_quotes: false,
}
}
}
pub struct ExportedMacros {
@ -1106,7 +1117,7 @@ impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> {
#[cfg(test)]
mod test {
use super::{pattern_bindings, expand_crate, contains_macro_escape};
use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer};
use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig};
use ast;
use ast::{Attribute_, AttrOuter, MetaWord, Name};
use attr;
@ -1171,6 +1182,10 @@ mod test {
// these following tests are quite fragile, in that they don't test what
// *kind* of failure occurs.
fn test_ecfg() -> ExpansionConfig {
ExpansionConfig::default("test".to_string())
}
// make sure that macros can't escape fns
#[should_fail]
#[test] fn macros_cant_escape_fns_test () {
@ -1182,11 +1197,7 @@ mod test {
src,
Vec::new(), &sess);
// should fail:
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_name: "test".to_string(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast);
}
// make sure that macros can't escape modules
@ -1199,11 +1210,7 @@ mod test {
"<test>".to_string(),
src,
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_name: "test".to_string(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast);
}
// macro_escape modules should allow macros to escape
@ -1215,11 +1222,7 @@ mod test {
"<test>".to_string(),
src,
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_name: "test".to_string(),
};
expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast);
}
#[test] fn test_contains_flatten (){
@ -1252,11 +1255,7 @@ mod test {
let ps = parse::new_parse_sess();
let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
// the cfg argument actually does matter, here...
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_name: "test".to_string(),
};
expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast)
}
// find the pat_ident paths in a crate

View File

@ -102,6 +102,7 @@ pub struct Features {
pub rustc_diagnostic_macros: bool,
pub import_shadowing: bool,
pub visible_private_types: bool,
pub quote: bool,
}
impl Features {
@ -112,6 +113,7 @@ impl Features {
rustc_diagnostic_macros: false,
import_shadowing: false,
visible_private_types: false,
quote: false,
}
}
}
@ -282,10 +284,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
fn visit_mac(&mut self, macro: &ast::Mac) {
let ast::MacInvocTT(ref path, _, _) = macro.node;
let id = path.segments.last().unwrap().identifier;
let quotes = ["quote_tokens", "quote_expr", "quote_ty",
"quote_item", "quote_pat", "quote_stmt"];
let msg = " is not stable enough for use and are subject to change";
if id == token::str_to_ident("macro_rules") {
self.gate_feature("macro_rules", path.span, "macro definitions are \
@ -311,16 +309,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
self.gate_feature("concat_idents", path.span, "`concat_idents` is not \
stable enough for use and is subject to change");
}
else {
for &quote in quotes.iter() {
if id == token::str_to_ident(quote) {
self.gate_feature("quote",
path.span,
format!("{}{}", quote, msg).as_slice());
}
}
}
}
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
@ -483,6 +471,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features,
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
import_shadowing: cx.has_feature("import_shadowing"),
visible_private_types: cx.has_feature("visible_private_types"),
quote: cx.has_feature("quote"),
},
unknown_features)
}

View File

@ -1279,7 +1279,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
clobbers,
volatile,
alignstack,
dialect
dialect,
expn_id,
}) => ExprInlineAsm(InlineAsm {
inputs: inputs.move_map(|(c, input)| {
(c, folder.fold_expr(input))
@ -1292,7 +1293,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
clobbers: clobbers,
volatile: volatile,
alignstack: alignstack,
dialect: dialect
dialect: dialect,
expn_id: expn_id,
}),
ExprMac(mac) => ExprMac(folder.fold_mac(mac)),
ExprStruct(path, fields, maybe_expr) => {

View File

@ -33,6 +33,7 @@ extern crate debug;
#[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate term;
extern crate libc;
pub mod util {
pub mod interner;

View File

@ -2084,7 +2084,7 @@ impl<'a> Parser<'a> {
ExprBlock(blk));
},
token::BINOP(token::OR) | token::OROR => {
return self.parse_lambda_expr(CaptureByValue);
return self.parse_lambda_expr(CaptureByRef);
},
// FIXME #13626: Should be able to stick in
// token::SELF_KEYWORD_NAME
@ -2135,8 +2135,8 @@ impl<'a> Parser<'a> {
hi = self.last_span.hi;
}
_ => {
if self.eat_keyword(keywords::Ref) {
return self.parse_lambda_expr(CaptureByRef);
if self.eat_keyword(keywords::Move) {
return self.parse_lambda_expr(CaptureByValue);
}
if self.eat_keyword(keywords::Proc) {
let decl = self.parse_proc_decl();

View File

@ -482,40 +482,41 @@ declare_special_idents_and_keywords! {
(25, Loop, "loop");
(26, Match, "match");
(27, Mod, "mod");
(28, Mut, "mut");
(29, Once, "once");
(30, Pub, "pub");
(31, Ref, "ref");
(32, Return, "return");
(28, Move, "move");
(29, Mut, "mut");
(30, Once, "once");
(31, Pub, "pub");
(32, Ref, "ref");
(33, Return, "return");
// Static and Self are also special idents (prefill de-dupes)
(super::STATIC_KEYWORD_NAME_NUM, Static, "static");
(super::SELF_KEYWORD_NAME_NUM, Self, "self");
(33, Struct, "struct");
(34, Struct, "struct");
(super::SUPER_KEYWORD_NAME_NUM, Super, "super");
(34, True, "true");
(35, Trait, "trait");
(36, Type, "type");
(37, Unsafe, "unsafe");
(38, Use, "use");
(39, Virtual, "virtual");
(40, While, "while");
(41, Continue, "continue");
(42, Proc, "proc");
(43, Box, "box");
(44, Const, "const");
(45, Where, "where");
(35, True, "true");
(36, Trait, "trait");
(37, Type, "type");
(38, Unsafe, "unsafe");
(39, Use, "use");
(40, Virtual, "virtual");
(41, While, "while");
(42, Continue, "continue");
(43, Proc, "proc");
(44, Box, "box");
(45, Const, "const");
(46, Where, "where");
'reserved:
(46, Alignof, "alignof");
(47, Be, "be");
(48, Offsetof, "offsetof");
(49, Priv, "priv");
(50, Pure, "pure");
(51, Sizeof, "sizeof");
(52, Typeof, "typeof");
(53, Unsized, "unsized");
(54, Yield, "yield");
(55, Do, "do");
(47, Alignof, "alignof");
(48, Be, "be");
(49, Offsetof, "offsetof");
(50, Priv, "priv");
(51, Pure, "pure");
(52, Sizeof, "sizeof");
(53, Typeof, "typeof");
(54, Unsized, "unsized");
(55, Yield, "yield");
(56, Do, "do");
}
}

View File

@ -2176,8 +2176,8 @@ impl<'a> State<'a> {
pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
-> IoResult<()> {
match capture_clause {
ast::CaptureByValue => Ok(()),
ast::CaptureByRef => self.word_space("ref"),
ast::CaptureByValue => self.word_space("move"),
ast::CaptureByRef => Ok(()),
}
}

View File

@ -235,10 +235,7 @@ fn generate_test_harness(sess: &ParseSess,
sess: sess,
span_diagnostic: sd,
ext_cx: ExtCtxt::new(sess, cfg.clone(),
ExpansionConfig {
deriving_hash_type_parameter: false,
crate_name: "test".to_string(),
}),
ExpansionConfig::default("test".to_string())),
path: Vec::new(),
testfns: Vec::new(),
reexport_test_harness_main: reexport_test_harness_main,

View File

@ -871,3 +871,18 @@ extern "C" void LLVMWriteDebugLocToString(
raw_rust_string_ostream os(str);
unwrap(dl)->print(*unwrap(C), os);
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
extern "C" void LLVMSetInlineAsmDiagnosticHandler(
LLVMContextRef C,
LLVMContext::InlineAsmDiagHandlerTy H,
void *CX)
{
unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
}
extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap(d)->print("", os);
}

View File

@ -73,6 +73,7 @@ void LLVMRustSetLastError(const char*);
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
extern "C" void
rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);

View File

@ -1,3 +1,12 @@
S 2014-09-28 7eb9337
freebsd-x86_64 d45e0edd44f40a976ea0affaadd98732684cfca0
linux-i386 3acb35755aa62b7ff78f76007d9a70696fce7aa7
linux-x86_64 2615b67b700ae8f7d8d87c043207a1a6e2339389
macos-i386 5eb4552dc66a14e1eff6e806a8ba27f4a73bb02a
macos-x86_64 c6052632443f638f5024ae38f33ae2c80d8b18bd
winnt-i386 269f46347b5766bff6f888c4307d50c475d3fe0f
winnt-x86_64 06f89825cecda7f2e36a4660ffe6d2d4a0430ab4
S 2014-09-22 437179e
freebsd-x86_64 f693c0441de3dbb2d471dde5a5045ac8a48807d8
linux-i386 5c2132b65f45c21b43d28de6a9460978b1a7b08a

View File

@ -0,0 +1,20 @@
// 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.
//
// compile-flags: -C codegen-units=2
// error-pattern: build without -C codegen-units for more exact errors
#![feature(asm)]
fn main() {
unsafe {
asm!("nowayisthisavalidinstruction");
}
}

View File

@ -0,0 +1,17 @@
// 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(asm)]
fn main() {
unsafe {
asm!("nowayisthisavalidinstruction"); //~ ERROR invalid instruction
}
}

View File

@ -15,7 +15,9 @@
extern crate trait_impl_conflict;
use trait_impl_conflict::Foo;
impl<A> Foo for A { //~ ERROR E0117
impl<A> Foo for A {
//~^ ERROR E0117
//~^^ ERROR E0119
}
fn main() {

View File

@ -0,0 +1,24 @@
// 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.
// Used to cause an ICE
struct Foo<T>{
x : T
}
type FooInt = Foo<int>;
impl Drop for FooInt {
//~^ ERROR cannot implement a destructor on a structure with type parameters
fn drop(&mut self){}
}
fn main() {}

View File

@ -0,0 +1,24 @@
// 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 _foo = &[1u, 2] as [uint];
//~^ ERROR cast to unsized type: `&[uint, .. 2]` as `[uint]`
//~^^ NOTE consider using an implicit coercion to `&[uint]` instead
let _bar = box 1u as std::fmt::Show;
//~^ ERROR cast to unsized type: `Box<uint>` as `core::fmt::Show`
//~^^ NOTE did you mean `Box<core::fmt::Show>`?
let _baz = 1u as std::fmt::Show;
//~^ ERROR cast to unsized type: `uint` as `core::fmt::Show`
//~^^ NOTE consider using a box or reference as appropriate
let _quux = [1u, 2] as [uint];
//~^ ERROR cast to unsized type: `[uint, .. 2]` as `[uint]`
//~^^ NOTE consider using a box or reference as appropriate
}

View File

@ -0,0 +1,18 @@
// 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-test
pub fn main() {
match 22i {
0 .. 3 => {} //~ ERROR expected `=>`, found `..`
_ => {}
}
}

View File

@ -17,7 +17,7 @@ fn main() {
{
let c = 1;
let c_ref = &c; //~ ERROR `c` does not live long enough
f = |&mut: a: int, b: int| { a + b + *c_ref };
f = move |&mut: a: int, b: int| { a + b + *c_ref };
}
}

View File

@ -0,0 +1,12 @@
-include ../tools.mk
all:
$(RUSTC) lib.rs
# the compiler needs to copy and modify the rlib file when performing
# LTO, so we should ensure that it can cope with the original rlib
# being read-only.
chmod 444 $(TMPDIR)/*.rlib
$(RUSTC) main.rs -C lto
$(call RUN,main)

View File

@ -0,0 +1,11 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "rlib"]

View File

@ -0,0 +1,13 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate lib;
fn main() {}

View File

@ -0,0 +1,6 @@
-include ../tools.mk
all: verify.sh foo.rs
$(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs
cp verify.sh $(TMPDIR)
$(call RUN,verify.sh) $(TMPDIR)

View File

@ -0,0 +1,26 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub trait MyTrait {}
pub struct Alpha<A> where A: MyTrait;
pub trait Bravo<B> where B: MyTrait {}
pub fn charlie<C>() where C: MyTrait {}
pub struct Delta<D>;
impl<D> Delta<D> where D: MyTrait {
pub fn delta() {}
}
pub struct Echo<E>;
impl<E> MyTrait for Echo<E> where E: MyTrait {}
pub enum Foxtrot<F> {}
impl<F> MyTrait for Foxtrot<F> where F: MyTrait {}

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -e
# $1 is the TMPDIR
DOC=$1/doc/foo
grep "Alpha.*where.*A:.*MyTrait" $DOC/struct.Alpha.html > /dev/null
echo "Alpha"
grep "Bravo.*where.*B:.*MyTrait" $DOC/trait.Bravo.html > /dev/null
echo "Bravo"
grep "charlie.*where.*C:.*MyTrait" $DOC/fn.charlie.html > /dev/null
echo "Charlie"
grep "impl.*Delta.*where.*D:.*MyTrait" $DOC/struct.Delta.html > /dev/null
echo "Delta"
grep "impl.*MyTrait.*for.*Echo.*where.*E:.*MyTrait" $DOC/struct.Echo.html > /dev/null
echo "Echo"
grep "impl.*MyTrait.*for.*Foxtrot.*where.*F:.*MyTrait" $DOC/enum.Foxtrot.html > /dev/null
echo "Foxtrot"
# check "Implementors" section of MyTrait
grep "impl.*MyTrait.*for.*Echo.*where.*E:.*MyTrait" $DOC/trait.MyTrait.html > /dev/null
grep "impl.*MyTrait.*for.*Foxtrot.*where.*F:.*MyTrait" $DOC/trait.MyTrait.html > /dev/null
echo "Implementors OK"

View File

@ -17,7 +17,7 @@ fn each<T>(x: &[T], f: |&T|) {
fn main() {
let mut sum = 0u;
let elems = [ 1u, 2, 3, 4, 5 ];
each(elems, ref |val| sum += *val);
each(elems, |val| sum += *val);
assert_eq!(sum, 15);
}

View File

@ -0,0 +1,17 @@
// 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(macro_rules)]
macro_rules! quote_tokens ( () => (()) )
pub fn main() {
quote_tokens!();
}

View File

@ -24,8 +24,8 @@ fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
fn main() {
let z: int = 7;
assert_eq!(a(|&: x: int, y| x + y + z), 10);
assert_eq!(b(|&mut: x: int, y| x + y + z), 14);
assert_eq!(c(|: x: int, y| x + y + z), 18);
assert_eq!(a(move |&: x: int, y| x + y + z), 10);
assert_eq!(b(move |&mut: x: int, y| x + y + z), 14);
assert_eq!(c(move |: x: int, y| x + y + z), 18);
}

View File

@ -13,7 +13,8 @@
use std::ops::FnMut;
fn make_adder(x: int) -> Box<FnMut<(int,),int>+'static> {
(box |&mut: y: int| -> int { x + y }) as Box<FnMut<(int,),int>+'static>
(box move |&mut: y: int| -> int { x + y }) as
Box<FnMut<(int,),int>+'static>
}
pub fn main() {

View File

@ -55,13 +55,13 @@ fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
fn test_fn() {
{
a(|&: a: int, b| { a + b });
a(move |&: a: int, b| { a + b });
}
assert_eq!(drop_count(), 0);
{
let z = &Droppable::new();
a(|&: a: int, b| { z; a + b });
a(move |&: a: int, b| { z; a + b });
assert_eq!(drop_count(), 0);
}
assert_eq!(drop_count(), 1);
@ -69,7 +69,7 @@ fn test_fn() {
{
let z = &Droppable::new();
let zz = &Droppable::new();
a(|&: a: int, b| { z; zz; a + b });
a(move |&: a: int, b| { z; zz; a + b });
assert_eq!(drop_count(), 1);
}
assert_eq!(drop_count(), 3);
@ -77,13 +77,13 @@ fn test_fn() {
fn test_fn_mut() {
{
b(|&mut: a: int, b| { a + b });
b(move |&mut: a: int, b| { a + b });
}
assert_eq!(drop_count(), 3);
{
let z = &Droppable::new();
b(|&mut: a: int, b| { z; a + b });
b(move |&mut: a: int, b| { z; a + b });
assert_eq!(drop_count(), 3);
}
assert_eq!(drop_count(), 4);
@ -91,7 +91,7 @@ fn test_fn_mut() {
{
let z = &Droppable::new();
let zz = &Droppable::new();
b(|&mut: a: int, b| { z; zz; a + b });
b(move |&mut: a: int, b| { z; zz; a + b });
assert_eq!(drop_count(), 4);
}
assert_eq!(drop_count(), 6);
@ -99,13 +99,13 @@ fn test_fn_mut() {
fn test_fn_once() {
{
c(|: a: int, b| { a + b });
c(move |: a: int, b| { a + b });
}
assert_eq!(drop_count(), 6);
{
let z = Droppable::new();
c(|: a: int, b| { z; a + b });
c(move |: a: int, b| { z; a + b });
assert_eq!(drop_count(), 7);
}
assert_eq!(drop_count(), 7);
@ -113,7 +113,7 @@ fn test_fn_once() {
{
let z = Droppable::new();
let zz = Droppable::new();
c(|: a: int, b| { z; zz; a + b });
c(move |: a: int, b| { z; zz; a + b });
assert_eq!(drop_count(), 9);
}
assert_eq!(drop_count(), 9);

View File

@ -27,8 +27,8 @@ fn c<F:FnOnce(int, int) -> int>(f: F) -> int {
fn main() {
let z = 10;
assert_eq!(a(|&: x: int, y| x + y + z), 13);
assert_eq!(b(|&mut: x: int, y| x + y + z), 17);
assert_eq!(c(|: x: int, y| x + y + z), 21);
assert_eq!(a(move |&: x: int, y| x + y + z), 13);
assert_eq!(b(move |&mut: x: int, y| x + y + z), 17);
assert_eq!(c(move |: x: int, y| x + y + z), 21);
}