Just small bits of polish.
probe CFG_XELATEX xelatex
probe CFG_LUALATEX lualatex
probe CFG_GDB gdb
+probe CFG_LLDB lldb
+
+if [ ! -z "$CFG_LLDB" ]
+then
+ # If CFG_LLDB_PYTHON_DIR is not already set from the outside and valid, try to read it from
+ # LLDB via the -P commandline options.
+ if [ -z "$CFG_LLDB_PYTHON_DIR" ] || [ ! -d "$CFG_LLDB_PYTHON_DIR" ]
+ then
+ CFG_LLDB_PYTHON_DIR=$($CFG_LLDB -P)
+
+ # If CFG_LLDB_PYTHON_DIR is not a valid directory, set it to something more readable
+ if [ ! -d "$CFG_LLDB_PYTHON_DIR" ]
+ then
+ CFG_LLDB_PYTHON_DIR="LLDB_PYTHON_DIRECTORY_NOT_FOUND"
+ fi
+
+ putvar CFG_LLDB_PYTHON_DIR
+ fi
+fi
+
if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
then
probe CFG_PAXCTL paxctl /sbin/paxctl
make_dir $h/test/bench
make_dir $h/test/perf
make_dir $h/test/pretty
- make_dir $h/test/debug-info
+ make_dir $h/test/debuginfo-gdb
+ make_dir $h/test/debuginfo-lldb
make_dir $h/test/codegen
make_dir $h/test/doc-tutorial
make_dir $h/test/doc-guide-ffi
TARGET_CRATES := libc std green rustuv native flate arena glob term semver \
uuid serialize sync getopts collections num test time rand \
workcache url log regex graphviz core
-HOST_CRATES := syntax rustc rustdoc fourcc hexfloat regex_macros
+HOST_CRATES := syntax rustc rustdoc fourcc hexfloat regex_macros fmt_macros
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc
DEPS_green := std rand native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
-DEPS_syntax := std term serialize collections log
+DEPS_syntax := std term serialize collections log fmt_macros
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
collections time log
DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
DEPS_log := std sync
DEPS_regex := std collections
DEPS_regex_macros = syntax std regex
+DEPS_fmt_macros = std
TOOL_DEPS_compiletest := test green rustuv getopts
TOOL_DEPS_rustdoc := rustdoc native
prepare-host-dirs-$(4)
$$(if $$(findstring $(2), $$(PREPARE_STAGE)),\
$$(if $$(findstring $(3), $$(PREPARE_HOST)),\
- $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$$(PREPARE_HOST),$(1))),),)
+ $$(if $$(findstring 1,$$(ONLY_RLIB_$(1))),,\
+ $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$$(PREPARE_HOST),$(1)))),),)
endef
$$(if $$(findstring $(3), $$(PREPARE_HOST)),\
$$(call PREPARE_DIR,$$(PREPARE_WORKING_DEST_LIB_DIR))\
$$(foreach crate,$$(TARGET_CRATES),\
- $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))\
+ $$(if $$(findstring 1, $$(ONLY_RLIB_$$(crate))),,\
+ $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate))))\
$$(call PREPARE_LIB,$$(call CFG_RLIB_GLOB,$$(crate))))\
$$(if $$(findstring $(2),$$(CFG_HOST)),\
$$(foreach crate,$$(HOST_CRATES),\
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
- check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
+ check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
+ check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs)
BENCH_RS := $(wildcard $(S)src/test/bench/*.rs)
PRETTY_RS := $(wildcard $(S)src/test/pretty/*.rs)
-DEBUGINFO_RS := $(wildcard $(S)src/test/debug-info/*.rs)
+DEBUGINFO_GDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
+DEBUGINFO_LLDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
BENCH_TESTS := $(BENCH_RS)
PERF_TESTS := $(PERF_RS)
PRETTY_TESTS := $(PRETTY_RS)
-DEBUGINFO_TESTS := $(DEBUGINFO_RS)
+DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
+DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
CTEST_SRC_BASE_rpass = run-pass
CTEST_MODE_perf = run-pass
CTEST_RUNTOOL_perf = $(CTEST_PERF_RUNTOOL)
-CTEST_SRC_BASE_debuginfo = debug-info
-CTEST_BUILD_BASE_debuginfo = debug-info
-CTEST_MODE_debuginfo = debug-info
-CTEST_RUNTOOL_debuginfo = $(CTEST_RUNTOOL)
+CTEST_SRC_BASE_debuginfo-gdb = debuginfo
+CTEST_BUILD_BASE_debuginfo-gdb = debuginfo-gdb
+CTEST_MODE_debuginfo-gdb = debuginfo-gdb
+CTEST_RUNTOOL_debuginfo-gdb = $(CTEST_RUNTOOL)
+
+CTEST_SRC_BASE_debuginfo-lldb = debuginfo
+CTEST_BUILD_BASE_debuginfo-lldb = debuginfo-lldb
+CTEST_MODE_debuginfo-lldb = debuginfo-lldb
+CTEST_RUNTOOL_debuginfo-lldb = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_codegen = codegen
CTEST_BUILD_BASE_codegen = codegen
# during attempts to run those tests.
ifeq ($(CFG_GDB),)
-CTEST_DISABLE_debuginfo = "no gdb found"
+CTEST_DISABLE_debuginfo-gdb = "no gdb found"
+endif
+
+ifeq ($(CFG_LLDB),)
+CTEST_DISABLE_debuginfo-lldb = "no lldb found"
endif
+# Completely disable LLDB tests for now
+CTEST_DISABLE_debuginfo-lldb = "LLDB tests are not enabled yet"
+
ifeq ($(CFG_CLANG),)
CTEST_DISABLE_codegen = "no clang found"
endif
ifeq ($(CFG_OSTYPE),apple-darwin)
-CTEST_DISABLE_debuginfo = "gdb on darwing needs root"
+CTEST_DISABLE_debuginfo-gdb = "gdb on darwing needs root"
endif
# CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that
--adb-path=$(CFG_ADB) \
--adb-test-dir=$(CFG_ADB_TEST_DIR) \
--host-rustcflags "$(RUSTC_FLAGS_$(3)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(3))" \
+ --lldb-python-dir=$(CFG_LLDB_PYTHON_DIR) \
--target-rustcflags "$(RUSTC_FLAGS_$(2)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(2))" \
$$(CTEST_TESTARGS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
-CTEST_DEPS_debuginfo_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_TESTS)
+CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
+CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS)
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
endef
endef
-CTEST_NAMES = rpass rpass-full cfail-full rfail cfail bench perf debuginfo codegen
+CTEST_NAMES = rpass rpass-full cfail-full rfail cfail bench perf debuginfo-gdb debuginfo-lldb codegen
$(foreach host,$(CFG_HOST), \
$(eval $(foreach target,$(CFG_TARGET), \
bench \
perf \
rmake \
- debuginfo \
+ debuginfo-gdb \
+ debuginfo-lldb \
codegen \
doc \
$(foreach docname,$(DOCS),doc-$(docname)) \
mode_run_fail,
mode_run_pass,
mode_pretty,
- mode_debug_info,
+ mode_debug_info_gdb,
+ mode_debug_info_lldb,
mode_codegen
}
// status whether android device available or not
pub adb_device_status: bool,
+ // the path containing LLDB's Python module
+ pub lldb_python_dir: Option<~str>,
+
// Explain what's going on
pub verbose: bool
use std::io;
use std::io::fs;
use getopts::{optopt, optflag, reqopt};
-use common::config;
-use common::mode_run_pass;
-use common::mode_run_fail;
-use common::mode_compile_fail;
-use common::mode_pretty;
-use common::mode_debug_info;
-use common::mode_codegen;
-use common::mode;
+use common::{config, mode_run_pass, mode_run_fail, mode_compile_fail, mode_pretty,
+ mode_debug_info_gdb, mode_debug_info_lldb, mode_codegen, mode};
use util::logv;
pub mod procsrv;
optopt("", "host", "the host to build for", "HOST"),
optopt("", "adb-path", "path to the android debugger", "PATH"),
optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"),
+ optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"),
optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", "A.B"),
optflag("h", "help", "show this message"));
"arm-linux-androideabi" == opt_str2(matches.opt_str("target")) &&
"(none)" != opt_str2(matches.opt_str("adb-test-dir")) &&
!opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
+ lldb_python_dir: matches.opt_str("lldb-python-dir"),
test_shard: test::opt_shard(matches.opt_str("test-shard")),
verbose: matches.opt_present("verbose")
}
pub fn str_mode(s: ~str) -> mode {
match s.as_slice() {
- "compile-fail" => mode_compile_fail,
- "run-fail" => mode_run_fail,
- "run-pass" => mode_run_pass,
- "pretty" => mode_pretty,
- "debug-info" => mode_debug_info,
- "codegen" => mode_codegen,
- _ => fail!("invalid mode")
+ "compile-fail" => mode_compile_fail,
+ "run-fail" => mode_run_fail,
+ "run-pass" => mode_run_pass,
+ "pretty" => mode_pretty,
+ "debuginfo-gdb" => mode_debug_info_gdb,
+ "debuginfo-lldb" => mode_debug_info_lldb,
+ "codegen" => mode_codegen,
+ s => fail!("invalid mode: " + s)
}
}
mode_run_fail => "run-fail".to_owned(),
mode_run_pass => "run-pass".to_owned(),
mode_pretty => "pretty".to_owned(),
- mode_debug_info => "debug-info".to_owned(),
+ mode_debug_info_gdb => "debuginfo-gdb".to_owned(),
+ mode_debug_info_lldb => "debuginfo-lldb".to_owned(),
mode_codegen => "codegen".to_owned(),
}
}
pub fn run_tests(config: &config) {
if config.target == "arm-linux-androideabi".to_owned() {
match config.mode{
- mode_debug_info => {
+ mode_debug_info_gdb => {
println!("arm-linux-androideabi debug-info \
test uses tcp 5039 port. please reserve it");
}
pub aux_builds: Vec<~str> ,
// Environment settings to use during execution
pub exec_env: Vec<(~str,~str)> ,
- // Commands to be given to the debugger, when testing debug info
- pub debugger_cmds: Vec<~str> ,
// Lines to check if they appear in the expected debugger output
pub check_lines: Vec<~str> ,
// Flag to force a crate to be built with the host architecture
let mut compile_flags = None;
let mut run_flags = None;
let mut pp_exact = None;
- let mut debugger_cmds = Vec::new();
let mut check_lines = Vec::new();
let mut force_host = false;
let mut check_stdout = false;
None => {}
}
- match parse_debugger_cmd(ln) {
- Some(dc) => debugger_cmds.push(dc),
- None => ()
- };
-
match parse_check_line(ln) {
Some(cl) => check_lines.push(cl),
None => ()
pp_exact: pp_exact,
aux_builds: aux_builds,
exec_env: exec_env,
- debugger_cmds: debugger_cmds,
check_lines: check_lines,
force_host: force_host,
check_stdout: check_stdout,
parse_name_value_directive(line, "run-flags".to_owned())
}
-fn parse_debugger_cmd(line: &str) -> Option<~str> {
- parse_name_value_directive(line, "debugger".to_owned())
-}
-
fn parse_check_line(line: &str) -> Option<~str> {
parse_name_value_directive(line, "check".to_owned())
}
line.contains(directive)
}
-fn parse_name_value_directive(line: &str,
+pub fn parse_name_value_directive(line: &str,
directive: ~str) -> Option<~str> {
let keycolon = directive + ":";
match line.find_str(keycolon) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use common::config;
-use common::mode_compile_fail;
-use common::mode_pretty;
-use common::mode_run_fail;
-use common::mode_run_pass;
+use common::{config, mode_compile_fail, mode_pretty, mode_run_fail, mode_run_pass};
use errors;
use header::TestProps;
-use header::load_props;
+use header;
use procsrv;
use util::logv;
#[cfg(target_os = "win32")]
}
let testfile = Path::new(testfile);
debug!("running {}", testfile.display());
- let props = load_props(&testfile);
+ let props = header::load_props(&testfile);
debug!("loaded props");
match config.mode {
mode_compile_fail => run_cfail_test(&config, &props, &testfile),
mode_run_fail => run_rfail_test(&config, &props, &testfile),
mode_run_pass => run_rpass_test(&config, &props, &testfile),
mode_pretty => run_pretty_test(&config, &props, &testfile),
- mode_debug_info => run_debuginfo_test(&config, &props, &testfile),
+ mode_debug_info_gdb => run_debuginfo_gdb_test(&config, &props, &testfile),
+ mode_debug_info_lldb => run_debuginfo_lldb_test(&config, &props, &testfile),
mode_codegen => run_codegen_test(&config, &props, &testfile, mm)
}
}
}
}
-fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
+fn run_debuginfo_gdb_test(config: &config, props: &TestProps, testfile: &Path) {
let mut config = config {
target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
};
let config = &mut config;
- let check_lines = &props.check_lines;
- let mut cmds = props.debugger_cmds.connect("\n");
+ let DebuggerCommands { commands, check_lines, .. } = parse_debugger_commands(testfile, "gdb");
+ let mut cmds = commands.connect("\n");
// compile test file (it shoud have 'compile-flags:-g' in the header)
- let mut proc_res = compile_test(config, props, testfile);
- if !proc_res.status.success() {
- fatal_ProcRes("compilation failed!".to_owned(), &proc_res);
+ let compiler_run_result = compile_test(config, props, testfile);
+ if !compiler_run_result.status.success() {
+ fatal_ProcRes("compilation failed!".to_owned(), &compiler_run_result);
}
let exe_file = make_exe_name(config, testfile);
let mut proc_args;
+ let debugger_run_result;
match config.target.as_slice() {
"arm-linux-androideabi" => {
cmdline
};
- proc_res = ProcRes {status: status,
- stdout: out,
- stderr: err,
- cmdline: cmdline};
+ debugger_run_result = ProcRes {
+ status: status,
+ stdout: out,
+ stderr: err,
+ cmdline: cmdline
+ };
process.signal_kill().unwrap();
}
"-command=" + debugger_script.as_str().unwrap().to_owned(),
exe_file.as_str().unwrap().to_owned());
proc_args = ProcArgs {prog: debugger(), args: debugger_opts};
- proc_res = compose_and_run(config, testfile, proc_args, Vec::new(), "", None);
+ debugger_run_result = compose_and_run(config,
+ testfile,
+ proc_args,
+ Vec::new(),
+ "",
+ None);
}
}
- if !proc_res.status.success() {
+ if !debugger_run_result.status.success() {
fatal("gdb failed to execute".to_owned());
}
+
+ check_debugger_output(&debugger_run_result, check_lines.as_slice());
+}
+
+fn run_debuginfo_lldb_test(config: &config, props: &TestProps, testfile: &Path) {
+ use std::io::process::{Process, ProcessConfig, ProcessOutput};
+
+ if config.lldb_python_dir.is_none() {
+ fatal("Can't run LLDB test because LLDB's python path is not set.".to_owned());
+ }
+
+ let mut config = config {
+ target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
+ host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
+ .. config.clone()
+ };
+
+ let config = &mut config;
+
+ // compile test file (it shoud have 'compile-flags:-g' in the header)
+ let compile_result = compile_test(config, props, testfile);
+ if !compile_result.status.success() {
+ fatal_ProcRes("compilation failed!".to_owned(), &compile_result);
+ }
+
+ let exe_file = make_exe_name(config, testfile);
+
+ // Parse debugger commands etc from test files
+ let DebuggerCommands {
+ commands,
+ check_lines,
+ breakpoint_lines
+ } = parse_debugger_commands(testfile, "lldb");
+
+ // Write debugger script:
+ // We don't want to hang when calling `quit` while the process is still running
+ let mut script_str = StrBuf::from_str("settings set auto-confirm true\n");
+
+ // Set breakpoints on every line that contains the string "#break"
+ for line in breakpoint_lines.iter() {
+ script_str.push_str(format!("breakpoint set --line {}\n", line));
+ }
+
+ // Append the other commands
+ for line in commands.iter() {
+ script_str.push_str(line.as_slice());
+ script_str.push_str("\n");
+ }
+
+ // Finally, quit the debugger
+ script_str.push_str("quit\n");
+
+ // Write the script into a file
+ debug!("script_str = {}", script_str);
+ dump_output_file(config, testfile, script_str.into_owned(), "debugger.script");
+ let debugger_script = make_out_name(config, testfile, "debugger.script");
+
+ // Let LLDB execute the script via lldb_batchmode.py
+ let debugger_run_result = run_lldb(config, &exe_file, &debugger_script);
+
+ if !debugger_run_result.status.success() {
+ fatal_ProcRes("Error while running LLDB".to_owned(), &debugger_run_result);
+ }
+
+ check_debugger_output(&debugger_run_result, check_lines.as_slice());
+
+ fn run_lldb(config: &config, test_executable: &Path, debugger_script: &Path) -> ProcRes {
+ // Prepare the lldb_batchmode which executes the debugger script
+ let lldb_batchmode_script = "./src/etc/lldb_batchmode.py".to_owned();
+ let test_executable_str = test_executable.as_str().unwrap().to_owned();
+ let debugger_script_str = debugger_script.as_str().unwrap().to_owned();
+ let commandline = format!("python {} {} {}",
+ lldb_batchmode_script.as_slice(),
+ test_executable_str.as_slice(),
+ debugger_script_str.as_slice());
+
+ let args = &[lldb_batchmode_script, test_executable_str, debugger_script_str];
+ let env = &[("PYTHONPATH".to_owned(), config.lldb_python_dir.clone().unwrap())];
+
+ let mut opt_process = Process::configure(ProcessConfig {
+ program: "python",
+ args: args,
+ env: Some(env),
+ .. ProcessConfig::new()
+ });
+
+ let (status, out, err) = match opt_process {
+ Ok(ref mut process) => {
+ let ProcessOutput { status, output, error } = process.wait_with_output();
+
+ (status,
+ str::from_utf8(output.as_slice()).unwrap().to_owned(),
+ str::from_utf8(error.as_slice()).unwrap().to_owned())
+ },
+ Err(e) => {
+ fatal(format!("Failed to setup Python process for LLDB script: {}", e))
+ }
+ };
+
+ dump_output(config, test_executable, out, err);
+ return ProcRes {
+ status: status,
+ stdout: out,
+ stderr: err,
+ cmdline: commandline
+ };
+ }
+}
+
+struct DebuggerCommands
+{
+ commands: Vec<~str>,
+ check_lines: Vec<~str>,
+ breakpoint_lines: Vec<uint>
+}
+
+fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) -> DebuggerCommands {
+ use std::io::{BufferedReader, File};
+
+ let command_directive = debugger_prefix + "-command";
+ let check_directive = debugger_prefix + "-check";
+
+ let mut breakpoint_lines = vec!();
+ let mut commands = vec!();
+ let mut check_lines = vec!();
+ let mut counter = 1;
+ let mut reader = BufferedReader::new(File::open(file_path).unwrap());
+ for line in reader.lines() {
+ match line {
+ Ok(line) => {
+ if line.contains("#break") {
+ breakpoint_lines.push(counter);
+ }
+
+ header::parse_name_value_directive(line, command_directive.clone())
+ .map(|cmd| commands.push(cmd));
+
+ header::parse_name_value_directive(line, check_directive.clone())
+ .map(|cmd| check_lines.push(cmd));
+ }
+ Err(e) => {
+ fatal(format!("Error while parsing debugger commands: {}", e))
+ }
+ }
+ counter += 1;
+ }
+
+ DebuggerCommands {
+ commands: commands,
+ check_lines: check_lines,
+ breakpoint_lines: breakpoint_lines
+ }
+}
+
+fn cleanup_debug_info_options(options: &Option<~str>) -> Option<~str> {
+ if options.is_none() {
+ return None;
+ }
+
+ // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
+ let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
+ let new_options = split_maybe_args(options).move_iter()
+ .filter(|x| !options_to_remove.contains(x))
+ .collect::<Vec<~str>>()
+ .connect(" ");
+ Some(new_options)
+}
+
+fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[~str]) {
let num_check_lines = check_lines.len();
if num_check_lines > 0 {
// Allow check lines to leave parts unspecified (e.g., uninitialized
// bits in the wrong case of an enum) with the notation "[...]".
let check_fragments: Vec<Vec<~str>> =
check_lines.iter().map(|s| {
- s.split_str("[...]").map(|x| x.to_str()).collect()
+ s.trim().split_str("[...]").map(|x| x.to_str()).collect()
}).collect();
// check if each line in props.check_lines appears in the
// output (in order)
let mut i = 0u;
- for line in proc_res.stdout.lines() {
+ for line in debugger_run_result.stdout.lines() {
let mut rest = line.trim();
let mut first = true;
let mut failed = false;
}
if i != num_check_lines {
fatal_ProcRes(format!("line not found in debugger output: {}",
- *check_lines.get(i)), &proc_res);
+ check_lines.get(i).unwrap()), debugger_run_result);
}
}
-
- fn cleanup_debug_info_options(options: &Option<~str>) -> Option<~str> {
- if options.is_none() {
- return None;
- }
-
- // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
- let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
- let new_options = split_maybe_args(options).move_iter()
- .filter(|x| !options_to_remove.contains(x))
- .collect::<Vec<~str>>()
- .connect(" ");
- Some(new_options)
- }
}
fn check_error_patterns(props: &TestProps,
for rel_ab in props.aux_builds.iter() {
let abs_ab = config.aux_base.join(rel_ab.as_slice());
- let aux_props = load_props(&abs_ab);
+ let aux_props = header::load_props(&abs_ab);
let crate_type = if aux_props.no_prefer_dynamic {
Vec::new()
} else {
fn make_exe_name(config: &config, testfile: &Path) -> Path {
let mut f = output_base_name(config, testfile);
if !os::consts::EXE_SUFFIX.is_empty() {
- match f.filename().map(|s| s + os::consts::EXE_SUFFIX.as_bytes()) {
+ match f.filename().map(|s| Vec::from_slice(s).append(os::consts::EXE_SUFFIX.as_bytes())) {
Some(v) => f.set_filename(v),
None => ()
}
fn aux_output_dir_name(config: &config, testfile: &Path) -> Path {
let mut f = output_base_name(config, testfile);
- match f.filename().map(|s| s + bytes!(".libaux")) {
+ match f.filename().map(|s| Vec::from_slice(s).append(bytes!(".libaux"))) {
Some(v) => f.set_filename(v),
None => ()
}
(*p).clone()
} else {
let stem = p.filestem().unwrap();
- p.with_filename(stem + bytes!("-") + suffix.as_bytes())
+ p.with_filename(Vec::from_slice(stem).append(bytes!("-")).append(suffix.as_bytes()))
}
}
~~~
let xs = [0, 1, 1, 2, 3, 5, 8];
-let ys = xs.iter().rev().skip(1).map(|&x| x * 2).collect::<~[int]>();
-assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
+let ys = xs.iter().rev().skip(1).map(|&x| x * 2).collect::<Vec<int>>();
+assert_eq!(ys, vec![10, 6, 4, 2, 2, 0]);
~~~
The method requires a type hint for the container type, if the surrounding code
vectors is as follows:
~~~ {.ignore}
-impl<A> FromIterator<A> for ~[A] {
- pub fn from_iter<T: Iterator<A>>(iterator: &mut T) -> ~[A] {
+impl<T> FromIterator<T> for Vec<T> {
+ fn from_iter<I:Iterator<A>>(mut iterator: I) -> Vec<T> {
let (lower, _) = iterator.size_hint();
- let mut xs = with_capacity(lower);
- for x in iterator {
- xs.push(x);
+ let mut vector = Vec::with_capacity(lower);
+ for element in iterator {
+ vector.push(element);
}
- xs
+ vector
}
}
~~~
~~~~ {.notrust .keyword}
as
-break
+box break
crate
else enum extern
false fn for
Within the body of an item that has type parameter declarations, the names of its type parameters are types:
~~~~
-fn map<A: Clone, B: Clone>(f: |A| -> B, xs: &[A]) -> ~[B] {
+fn map<A: Clone, B: Clone>(f: |A| -> B, xs: &[A]) -> Vec<B> {
if xs.len() == 0 {
- return ~[];
+ return vec![];
}
let first: B = f(xs[0].clone());
- let rest: ~[B] = map(f, xs.slice(1, xs.len()));
- return ~[first] + rest;
+ let rest: Vec<B> = map(f, xs.slice(1, xs.len()));
+ return vec![first].append(rest.as_slice());
}
~~~~
Here, `first` has type `B`, referring to `map`'s `B` type parameter;
-and `rest` has type `~[B]`, a vector type with element type `B`.
+and `rest` has type `Vec<B>`, a vector type with element type `B`.
### Self types
numbers.push(4);
numbers.push(5);
-// The type of a unique vector is written as `~[int]`
-let more_numbers: ~[int] = numbers.move_iter().collect();
+// The type of a unique vector is written as `Vec<int>`
+let more_numbers: Vec<int> = numbers.move_iter().map(|i| i+1).collect();
// The original `numbers` value can no longer be used, due to move semantics.
let ys: &mut [int] = &mut [1, 2, 3];
~~~
-Square brackets denote indexing into a vector:
+Square brackets denote indexing into a slice or fixed-size vector:
~~~~
# enum Crayon { Almond, AntiqueBrass, Apricot,
}
~~~~
-A vector can be destructured using pattern matching:
+A slice or fixed-size vector can be destructured using pattern matching:
~~~~
let numbers: &[int] = &[1, 2, 3];
~~~~
Both vectors and strings support a number of useful [methods](#methods),
-defined in [`std::vec`] and [`std::str`].
+defined in [`std::vec`], [`std::slice`], and [`std::str`].
[`std::vec`]: std/vec/index.html
+[`std::slice`]: std/slice/index.html
[`std::str`]: std/str/index.html
# Ownership escape hatches
<keyword>as</keyword>
<keyword>assert</keyword>
<keyword>break</keyword>
+ <keyword>box</keyword>
<keyword>const</keyword>
<keyword>continue</keyword>
<keyword>crate</keyword>
<list name="keywords">
<item> as </item>
<item> break </item>
+ <item> box </item>
<item> continue </item>
<item> crate </item>
<item> do </item>
--- /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 script allows to use LLDB in a way similar to GDB's batch mode. That is, given a text file
+# containing LLDB commands (one command per line), this script will execute the commands one after
+# the other.
+# LLDB also has the -s and -S commandline options which also execute a list of commands from a text
+# file. However, this command are execute `immediately`: a the command of a `run` or `continue`
+# command will be executed immediately after the `run` or `continue`, without waiting for the next
+# breakpoint to be hit. This a command sequence like the following will not yield reliable results:
+#
+# break 11
+# run
+# print x
+#
+# Most of the time the `print` command will be executed while the program is still running will thus
+# fail. Using this Python script, the above will work as expected.
+
+from __future__ import print_function
+import lldb
+import os
+import sys
+import threading
+import re
+import atexit
+
+# Terminate the debugger
+atexit.register(lambda: lldb.SBDebugger.Terminate())
+
+# Set this to True for additional output
+DEBUG_OUTPUT = False
+
+def print_debug(s):
+ "Print something if DEBUG_OUTPUT is True"
+ global DEBUG_OUTPUT
+ if DEBUG_OUTPUT:
+ print("DEBUG: " + str(s))
+
+
+def normalize_whitespace(s):
+ "Replace newlines, tabs, multiple spaces, etc with exactly one space"
+ return re.sub("\s+", " ", s)
+
+
+# This callback is registered with every breakpoint and makes sure that the frame containing the
+# breakpoint location is selected
+def breakpoint_callback(frame, bp_loc, dict):
+ "Called whenever a breakpoint is hit"
+ print("Hit breakpoint " + str(bp_loc))
+
+ # Select the frame and the thread containing it
+ frame.thread.process.SetSelectedThread(frame.thread)
+ frame.thread.SetSelectedFrame(frame.idx)
+
+ # Returning True means that we actually want to stop at this breakpoint
+ return True
+
+
+# This is a list of breakpoints that are not registered with the breakpoint callback. The list is
+# populated by the breakpoint listener and checked/emptied whenever a command has been executed
+new_breakpoints = []
+
+# This set contains all breakpoint ids that have already been registered with a callback, and is
+# used to avoid hooking callbacks into breakpoints more than once
+registered_breakpoints = set()
+
+def execute_command(command_interpreter, command):
+ "Executes a single CLI command"
+ global new_breakpoints
+ global registered_breakpoints
+
+ res = lldb.SBCommandReturnObject()
+ print(command)
+ command_interpreter.HandleCommand(command, res)
+
+ if res.Succeeded():
+ if res.HasResult():
+ print(normalize_whitespace(res.GetOutput()), end = '\n')
+
+ # If the command introduced any breakpoints, make sure to register them with the breakpoint
+ # callback
+ while len(new_breakpoints) > 0:
+ res.Clear()
+ breakpoint_id = new_breakpoints.pop()
+
+ if breakpoint_id in registered_breakpoints:
+ print_debug("breakpoint with id %s is already registered. Ignoring." % str(breakpoint_id))
+ else:
+ print_debug("registering breakpoint callback, id = " + str(breakpoint_id))
+ callback_command = "breakpoint command add -F breakpoint_callback " + str(breakpoint_id)
+ command_interpreter.HandleCommand(callback_command, res)
+ if res.Succeeded():
+ print_debug("successfully registered breakpoint callback, id = " + str(breakpoint_id))
+ registered_breakpoints.add(breakpoint_id)
+ else:
+ print("Error while trying to register breakpoint callback, id = " + str(breakpoint_id))
+ else:
+ print(res.GetError())
+
+
+def start_breakpoint_listener(target):
+ "Listens for breakpoints being added and adds new ones to the callback registration list"
+ listener = lldb.SBListener("breakpoint listener")
+
+ def listen():
+ event = lldb.SBEvent()
+ try:
+ while True:
+ if listener.WaitForEvent(120, event):
+ if lldb.SBBreakpoint.EventIsBreakpointEvent(event) and \
+ lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == \
+ lldb.eBreakpointEventTypeAdded:
+ global new_breakpoints
+ breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event)
+ print_debug("breakpoint added, id = " + str(breakpoint.id))
+ new_breakpoints.append(breakpoint.id)
+ except:
+ print_debug("breakpoint listener shutting down")
+
+ # Start the listener and let it run as a daemon
+ listener_thread = threading.Thread(target = listen)
+ listener_thread.daemon = True
+ listener_thread.start()
+
+ # Register the listener with the target
+ target.GetBroadcaster().AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged)
+
+
+####################################################################################################
+# ~main
+####################################################################################################
+
+if len(sys.argv) != 3:
+ print("usage: python lldb_batchmode.py target-path script-path")
+ sys.exit(1)
+
+target_path = sys.argv[1]
+script_path = sys.argv[2]
+
+
+# Create a new debugger instance
+debugger = lldb.SBDebugger.Create()
+
+# When we step or continue, don't return from the function until the process
+# stops. We do this by setting the async mode to false.
+debugger.SetAsync(False)
+
+# Create a target from a file and arch
+print("Creating a target for '%s'" % target_path)
+target = debugger.CreateTargetWithFileAndArch(target_path, lldb.LLDB_ARCH_DEFAULT)
+
+if not target:
+ print("Could not create debugging target '" + target_path + "'. Aborting.", file=sys.stderr)
+ sys.exit(1)
+
+
+# Register the breakpoint callback for every breakpoint
+start_breakpoint_listener(target)
+
+command_interpreter = debugger.GetCommandInterpreter()
+
+try:
+ script_file = open(script_path, 'r')
+
+ for line in script_file:
+ command = line.strip()
+ if command != '':
+ execute_command(command_interpreter, command)
+
+except IOError as e:
+ print("Could not read debugging script '%s'." % script_path, file = sys.stderr)
+ print(e, file = sys.stderr)
+ print("Aborting.", file = sys.stderr)
+ sys.exit(1)
+finally:
+ script_file.close()
+
syn match rustAssert "\<assert\(\w\)*!" contained
syn match rustFail "\<fail\(\w\)*!" contained
-syn keyword rustKeyword break continue
+syn keyword rustKeyword break box continue
syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite
syn keyword rustKeyword for in if impl let
syn keyword rustKeyword loop once priv pub
use std::cmp::Equiv;
use std::hash::Hash;
use std::iter::{Iterator,range_inclusive,range_step_inclusive};
- use std::local_data;
- use std::vec;
+ use std::cell::RefCell;
struct KindaIntLike(int);
assert_eq!(*m.find(&2).unwrap(), 4);
}
- local_data_key!(drop_vector: vec::Vec<int>)
+ local_data_key!(drop_vector: RefCell<Vec<int>>)
#[deriving(Hash, Eq, TotalEq)]
struct Dropable {
impl Dropable {
fn new(k: uint) -> Dropable {
- local_data::get_mut(drop_vector,
- |v| { v.unwrap().as_mut_slice()[k] += 1; });
+ let v = drop_vector.get().unwrap();
+ v.borrow_mut().as_mut_slice()[k] += 1;
Dropable { k: k }
}
impl Drop for Dropable {
fn drop(&mut self) {
- local_data::get_mut(drop_vector, |v|
- { v.unwrap().as_mut_slice()[self.k] -= 1; });
+ let v = drop_vector.get().unwrap();
+ v.borrow_mut().as_mut_slice()[self.k] -= 1;
}
}
#[test]
fn test_drops() {
- local_data::set(drop_vector, vec::Vec::from_elem(200, 0));
+ drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0))));
{
let mut m = HashMap::new();
- local_data::get(drop_vector, |v| {
- for i in range(0u, 200) {
- assert_eq!(v.unwrap().as_slice()[i], 0);
- }
- });
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ }
+ drop(v);
for i in range(0u, 100) {
let d1 = Dropable::new(i);
m.insert(d1, d2);
}
- local_data::get(drop_vector, |v| {
- for i in range(0u, 200) {
- assert_eq!(v.unwrap().as_slice()[i], 1);
- }
- });
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ }
+ drop(v);
for i in range(0u, 50) {
let k = Dropable::new(i);
assert!(v.is_some());
- local_data::get(drop_vector, |v| {
- assert_eq!(v.unwrap().as_slice()[i], 1);
- assert_eq!(v.unwrap().as_slice()[i+100], 1);
- });
+ let v = drop_vector.get().unwrap();
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ assert_eq!(v.borrow().as_slice()[i+100], 1);
}
- local_data::get(drop_vector, |v| {
- for i in range(0u, 50) {
- assert_eq!(v.unwrap().as_slice()[i], 0);
- assert_eq!(v.unwrap().as_slice()[i+100], 0);
- }
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 50) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ assert_eq!(v.borrow().as_slice()[i+100], 0);
+ }
- for i in range(50u, 100) {
- assert_eq!(v.unwrap().as_slice()[i], 1);
- assert_eq!(v.unwrap().as_slice()[i+100], 1);
- }
- });
+ for i in range(50u, 100) {
+ assert_eq!(v.borrow().as_slice()[i], 1);
+ assert_eq!(v.borrow().as_slice()[i+100], 1);
+ }
}
- local_data::get(drop_vector, |v| {
- for i in range(0u, 200) {
- assert_eq!(v.unwrap().as_slice()[i], 0);
- }
- });
+ let v = drop_vector.get().unwrap();
+ for i in range(0u, 200) {
+ assert_eq!(v.borrow().as_slice()[i], 0);
+ }
}
#[test]
///
/// ```rust
/// let a = [1, 2, 3, 4, 5];
- /// let b: ~[int] = a.iter().map(|&x| x).collect();
- /// assert!(a == b);
+ /// let b: Vec<int> = a.iter().map(|&x| x).collect();
+ /// assert!(a.as_slice() == b.as_slice());
/// ```
#[inline]
fn collect<B: FromIterator<A>>(&mut self) -> B {
#[test]
fn test_counter_from_iter() {
let it = count(0, 5).take(10);
- let xs: ~[int] = FromIterator::from_iter(it);
- assert_eq!(xs, box [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+ let xs: Vec<int> = FromIterator::from_iter(it);
+ assert_eq!(xs, vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
}
#[test]
fn test_filter_map() {
let mut it = count(0u, 1u).take(10)
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
- assert_eq!(it.collect::<~[uint]>(), box [0*0, 2*2, 4*4, 6*6, 8*8]);
+ assert_eq!(it.collect::<Vec<uint>>(), vec![0*0, 2*2, 4*4, 6*6, 8*8]);
}
#[test]
let ys = xs.iter()
.map(|&x| x)
.inspect(|_| n += 1)
- .collect::<~[uint]>();
+ .collect::<Vec<uint>>();
assert_eq!(n, xs.len());
assert_eq!(xs.as_slice(), ys.as_slice());
#[test]
fn test_collect() {
- let a = box [1, 2, 3, 4, 5];
- let b: ~[int] = a.iter().map(|&x| x).collect();
+ let a = vec![1, 2, 3, 4, 5];
+ let b: Vec<int> = a.iter().map(|&x| x).collect();
assert_eq!(a, b);
}
let mut it = xs.iter();
it.next();
it.next();
- assert_eq!(it.rev().map(|&x| x).collect::<~[int]>(), box [16, 14, 12, 10, 8, 6]);
+ assert_eq!(it.rev().map(|&x| x).collect::<Vec<int>>(), vec![16, 14, 12, 10, 8, 6]);
}
#[test]
#[test]
fn test_double_ended_range() {
- assert_eq!(range(11i, 14).rev().collect::<~[int]>(), box [13i, 12, 11]);
+ assert_eq!(range(11i, 14).rev().collect::<Vec<int>>(), vec![13i, 12, 11]);
for _ in range(10i, 0).rev() {
fail!("unreachable");
}
- assert_eq!(range(11u, 14).rev().collect::<~[uint]>(), box [13u, 12, 11]);
+ assert_eq!(range(11u, 14).rev().collect::<Vec<uint>>(), vec![13u, 12, 11]);
for _ in range(10u, 0).rev() {
fail!("unreachable");
}
}
}
- assert_eq!(range(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4]);
- assert_eq!(range(-10i, -1).collect::<~[int]>(), box [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
- assert_eq!(range(0i, 5).rev().collect::<~[int]>(), box [4, 3, 2, 1, 0]);
- assert_eq!(range(200, -5).collect::<~[int]>(), box []);
- assert_eq!(range(200, -5).rev().collect::<~[int]>(), box []);
- assert_eq!(range(200, 200).collect::<~[int]>(), box []);
- assert_eq!(range(200, 200).rev().collect::<~[int]>(), box []);
+ assert_eq!(range(0i, 5).collect::<Vec<int>>(), vec![0i, 1, 2, 3, 4]);
+ assert_eq!(range(-10i, -1).collect::<Vec<int>>(),
+ vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+ assert_eq!(range(0i, 5).rev().collect::<Vec<int>>(), vec![4, 3, 2, 1, 0]);
+ assert_eq!(range(200, -5).collect::<Vec<int>>(), vec![]);
+ assert_eq!(range(200, -5).rev().collect::<Vec<int>>(), vec![]);
+ assert_eq!(range(200, 200).collect::<Vec<int>>(), vec![]);
+ assert_eq!(range(200, 200).rev().collect::<Vec<int>>(), vec![]);
assert_eq!(range(0i, 100).size_hint(), (100, Some(100)));
// this test is only meaningful when sizeof uint < sizeof u64
#[test]
fn test_range_inclusive() {
- assert_eq!(range_inclusive(0i, 5).collect::<~[int]>(), box [0i, 1, 2, 3, 4, 5]);
- assert_eq!(range_inclusive(0i, 5).rev().collect::<~[int]>(), box [5i, 4, 3, 2, 1, 0]);
- assert_eq!(range_inclusive(200, -5).collect::<~[int]>(), box []);
- assert_eq!(range_inclusive(200, -5).rev().collect::<~[int]>(), box []);
- assert_eq!(range_inclusive(200, 200).collect::<~[int]>(), box [200]);
- assert_eq!(range_inclusive(200, 200).rev().collect::<~[int]>(), box [200]);
+ assert_eq!(range_inclusive(0i, 5).collect::<Vec<int>>(), vec![0i, 1, 2, 3, 4, 5]);
+ assert_eq!(range_inclusive(0i, 5).rev().collect::<Vec<int>>(), vec![5i, 4, 3, 2, 1, 0]);
+ assert_eq!(range_inclusive(200, -5).collect::<Vec<int>>(), vec![]);
+ assert_eq!(range_inclusive(200, -5).rev().collect::<Vec<int>>(), vec![]);
+ assert_eq!(range_inclusive(200, 200).collect::<Vec<int>>(), vec![200]);
+ assert_eq!(range_inclusive(200, 200).rev().collect::<Vec<int>>(), vec![200]);
}
#[test]
fn test_range_step() {
- assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15]);
- assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5]);
- assert_eq!(range_step(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]);
- assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]);
- assert_eq!(range_step(200, -5, 1).collect::<~[int]>(), box []);
- assert_eq!(range_step(200, 200, 1).collect::<~[int]>(), box []);
+ assert_eq!(range_step(0i, 20, 5).collect::<Vec<int>>(), vec![0, 5, 10, 15]);
+ assert_eq!(range_step(20i, 0, -5).collect::<Vec<int>>(), vec![20, 15, 10, 5]);
+ assert_eq!(range_step(20i, 0, -6).collect::<Vec<int>>(), vec![20, 14, 8, 2]);
+ assert_eq!(range_step(200u8, 255, 50).collect::<Vec<u8>>(), vec![200u8, 250]);
+ assert_eq!(range_step(200, -5, 1).collect::<Vec<int>>(), vec![]);
+ assert_eq!(range_step(200, 200, 1).collect::<Vec<int>>(), vec![]);
}
#[test]
fn test_range_step_inclusive() {
- assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), box [0, 5, 10, 15, 20]);
- assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), box [20, 15, 10, 5, 0]);
- assert_eq!(range_step_inclusive(20i, 0, -6).collect::<~[int]>(), box [20, 14, 8, 2]);
- assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), box [200u8, 250]);
- assert_eq!(range_step_inclusive(200, -5, 1).collect::<~[int]>(), box []);
- assert_eq!(range_step_inclusive(200, 200, 1).collect::<~[int]>(), box [200]);
+ assert_eq!(range_step_inclusive(0i, 20, 5).collect::<Vec<int>>(), vec![0, 5, 10, 15, 20]);
+ assert_eq!(range_step_inclusive(20i, 0, -5).collect::<Vec<int>>(), vec![20, 15, 10, 5, 0]);
+ assert_eq!(range_step_inclusive(20i, 0, -6).collect::<Vec<int>>(), vec![20, 14, 8, 2]);
+ assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>(), vec![200u8, 250]);
+ assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>(), vec![]);
+ assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>(), vec![200]);
}
#[test]
#[cfg(test)] pub use realstd::rt; // needed for fail!()
#[cfg(test)] pub use realstd::option; // needed for assert!()
#[cfg(test)] pub use realstd::os; // needed for tests
+ #[cfg(test)] pub use realstd::slice; // needed for tests
+ #[cfg(test)] pub use realstd::vec; // needed for vec![]
}
#[test]
fn test_collect() {
- let v: Option<~[int]> = collect(range(0, 0)
- .map(|_| Some(0)));
- assert_eq!(v, Some(box []));
+ let v: Option<Vec<int>> = collect(range(0, 0)
+ .map(|_| Some(0)));
+ assert_eq!(v, Some(vec![]));
- let v: Option<~[int]> = collect(range(0, 3)
- .map(|x| Some(x)));
- assert_eq!(v, Some(box [0, 1, 2]));
+ let v: Option<Vec<int>> = collect(range(0, 3)
+ .map(|x| Some(x)));
+ assert_eq!(v, Some(vec![0, 1, 2]));
- let v: Option<~[int]> = collect(range(0, 3)
- .map(|x| if x > 1 { None } else { Some(x) }));
+ let v: Option<Vec<int>> = collect(range(0, 3)
+ .map(|x| if x > 1 { None } else { Some(x) }));
assert_eq!(v, None);
// test that it does not take more elements than it needs
let mut functions = [|| Some(()), || None, || fail!()];
- let v: Option<~[()]> = collect(functions.mut_iter().map(|f| (*f)()));
+ let v: Option<Vec<()>> = collect(functions.mut_iter().map(|f| (*f)()));
assert_eq!(v, None);
}
#[test]
fn test_collect() {
- let v: Result<~[int], ()> = collect(range(0, 0).map(|_| Ok::<int, ()>(0)));
- assert_eq!(v, Ok(box []));
+ let v: Result<Vec<int>, ()> = collect(range(0, 0).map(|_| Ok::<int, ()>(0)));
+ assert_eq!(v, Ok(vec![]));
- let v: Result<~[int], ()> = collect(range(0, 3).map(|x| Ok::<int, ()>(x)));
- assert_eq!(v, Ok(box [0, 1, 2]));
+ let v: Result<Vec<int>, ()> = collect(range(0, 3).map(|x| Ok::<int, ()>(x)));
+ assert_eq!(v, Ok(vec![0, 1, 2]));
- let v: Result<~[int], int> = collect(range(0, 3)
- .map(|x| if x > 1 { Err(x) } else { Ok(x) }));
+ let v: Result<Vec<int>, int> = collect(range(0, 3)
+ .map(|x| if x > 1 { Err(x) } else { Ok(x) }));
assert_eq!(v, Err(2));
// test that it does not take more elements than it needs
let mut functions = [|| Ok(()), || Err(1), || fail!()];
- let v: Result<~[()], int> = collect(functions.mut_iter().map(|f| (*f)()));
+ let v: Result<Vec<()>, int> = collect(functions.mut_iter().map(|f| (*f)()));
assert_eq!(v, Err(1));
}
use clone::Clone;
use container::Container;
use default::Default;
+use finally::try_finally;
use intrinsics;
-use iter::{Iterator, FromIterator};
+use iter::{range, Iterator, FromIterator};
use mem;
use num::{CheckedMul, CheckedAdd};
use option::{Some, None};
use str::StrSlice;
#[cfg(not(test))] use ops::Add;
-#[cfg(not(test))] use slice::Vector;
#[allow(ctypes)]
extern {
impl<A: Clone> Clone for ~[A] {
#[inline]
fn clone(&self) -> ~[A] {
- self.iter().map(|a| a.clone()).collect()
- }
-}
-
-impl<A> FromIterator<A> for ~[A] {
- fn from_iter<T: Iterator<A>>(mut iterator: T) -> ~[A] {
- let (lower, _) = iterator.size_hint();
- let cap = if lower == 0 {16} else {lower};
- let mut cap = cap.checked_mul(&mem::size_of::<A>()).unwrap();
- let mut len = 0;
+ let len = self.len();
+ let data_size = len.checked_mul(&mem::size_of::<A>()).unwrap();
+ let size = mem::size_of::<Vec<()>>().checked_add(&data_size).unwrap();
unsafe {
- let mut ptr = alloc(cap) as *mut Vec<A>;
- let mut ret = cast::transmute(ptr);
- for elt in iterator {
- if len * mem::size_of::<A>() >= cap {
- cap = cap.checked_mul(&2).unwrap();
- let ptr2 = alloc(cap) as *mut Vec<A>;
- ptr::copy_nonoverlapping_memory(&mut (*ptr2).data,
- &(*ptr).data,
- len);
- free(ptr as *u8);
- cast::forget(ret);
- ret = cast::transmute(ptr2);
- ptr = ptr2;
- }
-
- let base = &mut (*ptr).data as *mut A;
- intrinsics::move_val_init(&mut *base.offset(len as int), elt);
- len += 1;
- (*ptr).fill = len * mem::nonzero_size_of::<A>();
- }
- ret
+ let ret = alloc(size) as *mut Vec<A>;
+
+ (*ret).fill = len * mem::nonzero_size_of::<A>();
+ (*ret).alloc = len * mem::nonzero_size_of::<A>();
+
+ let mut i = 0;
+ let p = &mut (*ret).data as *mut _ as *mut A;
+ try_finally(
+ &mut i, (),
+ |i, ()| while *i < len {
+ mem::move_val_init(
+ &mut(*p.offset(*i as int)),
+ self.unsafe_ref(*i).clone());
+ *i += 1;
+ },
+ |i| if *i < len {
+ // we must be failing, clean up after ourselves
+ for j in range(0, *i as int) {
+ ptr::read(&*p.offset(j));
+ }
+ free(ret as *u8);
+ });
+ cast::transmute(ret)
}
}
}
-
-#[cfg(not(test))]
-impl<'a,T:Clone, V: Vector<T>> Add<V, ~[T]> for &'a [T] {
- #[inline]
- fn add(&self, rhs: &V) -> ~[T] {
- let first = self.iter().map(|t| t.clone());
- first.chain(rhs.as_slice().iter().map(|t| t.clone())).collect()
- }
-}
-
-#[cfg(not(test))]
-impl<T:Clone, V: Vector<T>> Add<V, ~[T]> for ~[T] {
- #[inline]
- fn add(&self, rhs: &V) -> ~[T] {
- self.as_slice() + rhs.as_slice()
- }
-}
/// 0x0073, 0xDD1E, 0x0069, 0x0063,
/// 0xD834];
///
-/// assert_eq!(str::utf16_items(v).collect::<~[_]>(),
-/// ~[ScalarValue('𝄞'),
-/// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'),
-/// LoneSurrogate(0xDD1E),
-/// ScalarValue('i'), ScalarValue('c'),
-/// LoneSurrogate(0xD834)]);
+/// assert_eq!(str::utf16_items(v).collect::<Vec<_>>(),
+/// vec![ScalarValue('𝄞'),
+/// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'),
+/// LoneSurrogate(0xDD1E),
+/// ScalarValue('i'), ScalarValue('c'),
+/// LoneSurrogate(0xD834)]);
/// ```
pub fn utf16_items<'a>(v: &'a [u16]) -> UTF16Items<'a> {
UTF16Items { iter : v.iter() }
/// # Example
///
/// ```rust
- /// let v: ~[char] = "abc åäö".chars().collect();
- /// assert_eq!(v, ~['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
+ /// let v: Vec<char> = "abc åäö".chars().collect();
+ /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
/// ```
fn chars(&self) -> Chars<'a>;
/// # Example
///
/// ```rust
- /// let v: ~[&str] = "Mary had a little lamb".split(' ').collect();
- /// assert_eq!(v, ~["Mary", "had", "a", "little", "lamb"]);
+ /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
+ /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
///
- /// let v: ~[&str] = "abc1def2ghi".split(|c: char| c.is_digit()).collect();
- /// assert_eq!(v, ~["abc", "def", "ghi"]);
+ /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_digit()).collect();
+ /// assert_eq!(v, vec!["abc", "def", "ghi"]);
///
- /// let v: ~[&str] = "lionXXtigerXleopard".split('X').collect();
- /// assert_eq!(v, ~["lion", "", "tiger", "leopard"]);
+ /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
+ /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]);
/// ```
fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep>;
/// # Example
///
/// ```rust
- /// let v: ~[&str] = "Mary had a little lambda".splitn(' ', 2).collect();
- /// assert_eq!(v, ~["Mary", "had", "a little lambda"]);
+ /// let v: Vec<&str> = "Mary had a little lambda".splitn(' ', 2).collect();
+ /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
///
- /// let v: ~[&str] = "abc1def2ghi".splitn(|c: char| c.is_digit(), 1).collect();
- /// assert_eq!(v, ~["abc", "def2ghi"]);
+ /// let v: Vec<&str> = "abc1def2ghi".splitn(|c: char| c.is_digit(), 1).collect();
+ /// assert_eq!(v, vec!["abc", "def2ghi"]);
///
- /// let v: ~[&str] = "lionXXtigerXleopard".splitn('X', 2).collect();
- /// assert_eq!(v, ~["lion", "", "tigerXleopard"]);
+ /// let v: Vec<&str> = "lionXXtigerXleopard".splitn('X', 2).collect();
+ /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
/// ```
fn splitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
/// # Example
///
/// ```rust
- /// let v: ~[&str] = "A.B.".split_terminator('.').collect();
- /// assert_eq!(v, ~["A", "B"]);
+ /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
+ /// assert_eq!(v, vec!["A", "B"]);
///
- /// let v: ~[&str] = "A..B..".split_terminator('.').collect();
- /// assert_eq!(v, ~["A", "", "B", ""]);
+ /// let v: Vec<&str> = "A..B..".split_terminator('.').collect();
+ /// assert_eq!(v, vec!["A", "", "B", ""]);
///
- /// let v: ~[&str] = "Mary had a little lamb".split(' ').rev().collect();
- /// assert_eq!(v, ~["lamb", "little", "a", "had", "Mary"]);
+ /// let v: Vec<&str> = "Mary had a little lamb".split(' ').rev().collect();
+ /// assert_eq!(v, vec!["lamb", "little", "a", "had", "Mary"]);
///
- /// let v: ~[&str] = "abc1def2ghi".split(|c: char| c.is_digit()).rev().collect();
- /// assert_eq!(v, ~["ghi", "def", "abc"]);
+ /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_digit()).rev().collect();
+ /// assert_eq!(v, vec!["ghi", "def", "abc"]);
///
- /// let v: ~[&str] = "lionXXtigerXleopard".split('X').rev().collect();
- /// assert_eq!(v, ~["leopard", "tiger", "", "lion"]);
+ /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect();
+ /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]);
/// ```
fn split_terminator<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep>;
/// # Example
///
/// ```rust
- /// let v: ~[&str] = "Mary had a little lamb".rsplitn(' ', 2).collect();
- /// assert_eq!(v, ~["lamb", "little", "Mary had a"]);
+ /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(' ', 2).collect();
+ /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
///
- /// let v: ~[&str] = "abc1def2ghi".rsplitn(|c: char| c.is_digit(), 1).collect();
- /// assert_eq!(v, ~["ghi", "abc1def"]);
+ /// let v: Vec<&str> = "abc1def2ghi".rsplitn(|c: char| c.is_digit(), 1).collect();
+ /// assert_eq!(v, vec!["ghi", "abc1def"]);
///
- /// let v: ~[&str] = "lionXXtigerXleopard".rsplitn('X', 2).collect();
- /// assert_eq!(v, ~["leopard", "tiger", "lionX"]);
+ /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn('X', 2).collect();
+ /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
/// ```
fn rsplitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
/// # Example
///
/// ```rust
- /// let v: ~[(uint, uint)] = "abcXXXabcYYYabc".match_indices("abc").collect();
- /// assert_eq!(v, ~[(0,3), (6,9), (12,15)]);
+ /// let v: Vec<(uint, uint)> = "abcXXXabcYYYabc".match_indices("abc").collect();
+ /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]);
///
- /// let v: ~[(uint, uint)] = "1abcabc2".match_indices("abc").collect();
- /// assert_eq!(v, ~[(1,4), (4,7)]);
+ /// let v: Vec<(uint, uint)> = "1abcabc2".match_indices("abc").collect();
+ /// assert_eq!(v, vec![(1,4), (4,7)]);
///
- /// let v: ~[(uint, uint)] = "ababa".match_indices("aba").collect();
- /// assert_eq!(v, ~[(0, 3)]); // only the first `aba`
+ /// let v: Vec<(uint, uint)> = "ababa".match_indices("aba").collect();
+ /// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
/// ```
fn match_indices(&self, sep: &'a str) -> MatchIndices<'a>;
/// # Example
///
/// ```rust
- /// let v: ~[&str] = "abcXXXabcYYYabc".split_str("abc").collect();
- /// assert_eq!(v, ~["", "XXX", "YYY", ""]);
+ /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
+ /// assert_eq!(v, vec!["", "XXX", "YYY", ""]);
///
- /// let v: ~[&str] = "1abcabc2".split_str("abc").collect();
- /// assert_eq!(v, ~["1", "", "2"]);
+ /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
+ /// assert_eq!(v, vec!["1", "", "2"]);
/// ```
fn split_str(&self, &'a str) -> StrSplits<'a>;
///
/// ```rust
/// let four_lines = "foo\nbar\n\nbaz\n";
- /// let v: ~[&str] = four_lines.lines().collect();
- /// assert_eq!(v, ~["foo", "bar", "", "baz"]);
+ /// let v: Vec<&str> = four_lines.lines().collect();
+ /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
/// ```
fn lines(&self) -> CharSplits<'a, char>;
///
/// ```rust
/// let four_lines = "foo\r\nbar\n\r\nbaz\n";
- /// let v: ~[&str] = four_lines.lines_any().collect();
- /// assert_eq!(v, ~["foo", "bar", "", "baz"]);
+ /// let v: Vec<&str> = four_lines.lines_any().collect();
+ /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
/// ```
fn lines_any(&self) -> AnyLines<'a>;
///
/// ```rust
/// let some_words = " Mary had\ta little \n\t lamb";
- /// let v: ~[&str] = some_words.words().collect();
- /// assert_eq!(v, ~["Mary", "had", "a", "little", "lamb"]);
+ /// let v: Vec<&str> = some_words.words().collect();
+ /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
/// ```
fn words(&self) -> Words<'a>;
///
/// ```rust
/// let string = "a\nb\nc";
- /// let lines: ~[&str] = string.lines().collect();
+ /// let lines: Vec<&str> = string.lines().collect();
+ /// let lines = lines.as_slice();
///
/// assert!(string.subslice_offset(lines[0]) == 0); // &"a"
/// assert!(string.subslice_offset(lines[1]) == 2); // &"b"
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+//! Macro support for format strings
+//!
+//! These structures are used when parsing format strings for the compiler.
+//! Parsing does not happen at runtime: structures of `std::fmt::rt` are
+//! generated instead.
+
+#![crate_id = "fmt_macros#0.11-pre"]
+#![license = "MIT/ASL2"]
+#![crate_type = "rlib"]
+#![crate_type = "dylib"]
+#![feature(macro_rules, globs)]
+#![experimental]
+
+use std::char;
+use std::str;
+
+/// A piece is a portion of the format string which represents the next part
+/// to emit. These are emitted as a stream by the `Parser` class.
+#[deriving(Eq)]
+pub enum Piece<'a> {
+ /// A literal string which should directly be emitted
+ String(&'a str),
+ /// A back-reference to whatever the current argument is. This is used
+ /// inside of a method call to refer back to the original argument.
+ CurrentArgument,
+ /// This describes that formatting should process the next argument (as
+ /// specified inside) for emission.
+ Argument(Argument<'a>),
+}
+
+/// Representation of an argument specification.
+#[deriving(Eq)]
+pub struct Argument<'a> {
+ /// Where to find this argument
+ pub position: Position<'a>,
+ /// How to format the argument
+ pub format: FormatSpec<'a>,
+ /// If not `None`, what method to invoke on the argument
+ pub method: Option<Box<Method<'a>>>
+}
+
+/// Specification for the formatting of an argument in the format string.
+#[deriving(Eq)]
+pub struct FormatSpec<'a> {
+ /// Optionally specified character to fill alignment with
+ pub fill: Option<char>,
+ /// Optionally specified alignment
+ pub align: Alignment,
+ /// Packed version of various flags provided
+ pub flags: uint,
+ /// The integer precision to use
+ pub precision: Count<'a>,
+ /// The string width requested for the resulting format
+ pub width: Count<'a>,
+ /// The descriptor string representing the name of the format desired for
+ /// this argument, this can be empty or any number of characters, although
+ /// it is required to be one word.
+ pub ty: &'a str
+}
+
+/// Enum describing where an argument for a format can be located.
+#[deriving(Eq)]
+pub enum Position<'a> {
+ /// The argument will be in the next position. This is the default.
+ ArgumentNext,
+ /// The argument is located at a specific index.
+ ArgumentIs(uint),
+ /// The argument has a name.
+ ArgumentNamed(&'a str),
+}
+
+/// Enum of alignments which are supported.
+#[deriving(Eq)]
+pub enum Alignment {
+ /// The value will be aligned to the left.
+ AlignLeft,
+ /// The value will be aligned to the right.
+ AlignRight,
+ /// The value will take on a default alignment.
+ AlignUnknown,
+}
+
+/// Various flags which can be applied to format strings. The meaning of these
+/// flags is defined by the formatters themselves.
+#[deriving(Eq)]
+pub enum Flag {
+ /// A `+` will be used to denote positive numbers.
+ FlagSignPlus,
+ /// A `-` will be used to denote negative numbers. This is the default.
+ FlagSignMinus,
+ /// An alternate form will be used for the value. In the case of numbers,
+ /// this means that the number will be prefixed with the supplied string.
+ FlagAlternate,
+ /// For numbers, this means that the number will be padded with zeroes,
+ /// and the sign (`+` or `-`) will precede them.
+ FlagSignAwareZeroPad,
+}
+
+/// A count is used for the precision and width parameters of an integer, and
+/// can reference either an argument or a literal integer.
+#[deriving(Eq)]
+pub enum Count<'a> {
+ /// The count is specified explicitly.
+ CountIs(uint),
+ /// The count is specified by the argument with the given name.
+ CountIsName(&'a str),
+ /// The count is specified by the argument at the given index.
+ CountIsParam(uint),
+ /// The count is specified by the next parameter.
+ CountIsNextParam,
+ /// The count is implied and cannot be explicitly specified.
+ CountImplied,
+}
+
+/// Enum describing all of the possible methods which the formatting language
+/// currently supports.
+#[deriving(Eq)]
+pub enum Method<'a> {
+ /// A plural method selects on an integer over a list of either integer or
+ /// keyword-defined clauses. The meaning of the keywords is defined by the
+ /// current locale.
+ ///
+ /// An offset is optionally present at the beginning which is used to
+ /// match against keywords, but it is not matched against the literal
+ /// integers.
+ ///
+ /// The final element of this enum is the default "other" case which is
+ /// always required to be specified.
+ Plural(Option<uint>, Vec<PluralArm<'a>>, Vec<Piece<'a>>),
+
+ /// A select method selects over a string. Each arm is a different string
+ /// which can be selected for.
+ ///
+ /// As with `Plural`, a default "other" case is required as well.
+ Select(Vec<SelectArm<'a>>, Vec<Piece<'a>>),
+}
+
+/// A selector for what pluralization a plural method should take
+#[deriving(Eq, TotalEq, Hash)]
+pub enum PluralSelector {
+ /// One of the plural keywords should be used
+ Keyword(PluralKeyword),
+ /// A literal pluralization should be used
+ Literal(uint),
+}
+
+/// Structure representing one "arm" of the `plural` function.
+#[deriving(Eq)]
+pub struct PluralArm<'a> {
+ /// A selector can either be specified by a keyword or with an integer
+ /// literal.
+ pub selector: PluralSelector,
+ /// Array of pieces which are the format of this arm
+ pub result: Vec<Piece<'a>>,
+}
+
+/// Enum of the 5 CLDR plural keywords. There is one more, "other", but that
+/// is specially placed in the `Plural` variant of `Method`.
+///
+/// http://www.icu-project.org/apiref/icu4c/classicu_1_1PluralRules.html
+#[deriving(Eq, TotalEq, Hash, Show)]
+#[allow(missing_doc)]
+pub enum PluralKeyword {
+ /// The plural form for zero objects.
+ Zero,
+ /// The plural form for one object.
+ One,
+ /// The plural form for two objects.
+ Two,
+ /// The plural form for few objects.
+ Few,
+ /// The plural form for many objects.
+ Many,
+}
+
+/// Structure representing one "arm" of the `select` function.
+#[deriving(Eq)]
+pub struct SelectArm<'a> {
+ /// String selector which guards this arm
+ pub selector: &'a str,
+ /// Array of pieces which are the format of this arm
+ pub result: Vec<Piece<'a>>,
+}
+
+/// The parser structure for interpreting the input format string. This is
+/// modelled as an iterator over `Piece` structures to form a stream of tokens
+/// being output.
+///
+/// This is a recursive-descent parser for the sake of simplicity, and if
+/// necessary there's probably lots of room for improvement performance-wise.
+pub struct Parser<'a> {
+ input: &'a str,
+ cur: str::CharOffsets<'a>,
+ depth: uint,
+ /// Error messages accumulated during parsing
+ pub errors: Vec<~str>,
+}
+
+impl<'a> Iterator<Piece<'a>> for Parser<'a> {
+ fn next(&mut self) -> Option<Piece<'a>> {
+ match self.cur.clone().next() {
+ Some((_, '#')) => { self.cur.next(); Some(CurrentArgument) }
+ Some((_, '{')) => {
+ self.cur.next();
+ let ret = Some(Argument(self.argument()));
+ self.must_consume('}');
+ ret
+ }
+ Some((pos, '\\')) => {
+ self.cur.next();
+ self.escape(); // ensure it's a valid escape sequence
+ Some(String(self.string(pos + 1))) // skip the '\' character
+ }
+ Some((_, '}')) if self.depth == 0 => {
+ self.cur.next();
+ self.err("unmatched `}` found");
+ None
+ }
+ Some((_, '}')) | None => { None }
+ Some((pos, _)) => {
+ Some(String(self.string(pos)))
+ }
+ }
+ }
+}
+
+impl<'a> Parser<'a> {
+ /// Creates a new parser for the given format string
+ pub fn new<'a>(s: &'a str) -> Parser<'a> {
+ Parser {
+ input: s,
+ cur: s.char_indices(),
+ depth: 0,
+ errors: vec!(),
+ }
+ }
+
+ /// Notifies of an error. The message doesn't actually need to be of type
+ /// ~str, but I think it does when this eventually uses conditions so it
+ /// might as well start using it now.
+ fn err(&mut self, msg: &str) {
+ self.errors.push(msg.to_owned());
+ }
+
+ /// Optionally consumes the specified character. If the character is not at
+ /// the current position, then the current iterator isn't moved and false is
+ /// returned, otherwise the character is consumed and true is returned.
+ fn consume(&mut self, c: char) -> bool {
+ match self.cur.clone().next() {
+ Some((_, maybe)) if c == maybe => {
+ self.cur.next();
+ true
+ }
+ Some(..) | None => false,
+ }
+ }
+
+ /// Forces consumption of the specified character. If the character is not
+ /// found, an error is emitted.
+ fn must_consume(&mut self, c: char) {
+ self.ws();
+ match self.cur.clone().next() {
+ Some((_, maybe)) if c == maybe => {
+ self.cur.next();
+ }
+ Some((_, other)) => {
+ self.err(
+ format!("expected `{}` but found `{}`", c, other));
+ }
+ None => {
+ self.err(
+ format!("expected `{}` but string was terminated", c));
+ }
+ }
+ }
+
+ /// Attempts to consume any amount of whitespace followed by a character
+ fn wsconsume(&mut self, c: char) -> bool {
+ self.ws(); self.consume(c)
+ }
+
+ /// Consumes all whitespace characters until the first non-whitespace
+ /// character
+ fn ws(&mut self) {
+ loop {
+ match self.cur.clone().next() {
+ Some((_, c)) if char::is_whitespace(c) => { self.cur.next(); }
+ Some(..) | None => { return }
+ }
+ }
+ }
+
+ /// Consumes an escape sequence, failing if there is not a valid character
+ /// to be escaped.
+ fn escape(&mut self) -> char {
+ match self.cur.next() {
+ Some((_, c @ '#')) | Some((_, c @ '{')) |
+ Some((_, c @ '\\')) | Some((_, c @ '}')) => { c }
+ Some((_, c)) => {
+ self.err(format!("invalid escape character `{}`", c));
+ c
+ }
+ None => {
+ self.err("expected an escape sequence, but format string was \
+ terminated");
+ ' '
+ }
+ }
+ }
+
+ /// Parses all of a string which is to be considered a "raw literal" in a
+ /// format string. This is everything outside of the braces.
+ fn string(&mut self, start: uint) -> &'a str {
+ loop {
+ // we may not consume the character, so clone the iterator
+ match self.cur.clone().next() {
+ Some((pos, '\\')) | Some((pos, '#')) |
+ Some((pos, '}')) | Some((pos, '{')) => {
+ return self.input.slice(start, pos);
+ }
+ Some(..) => { self.cur.next(); }
+ None => {
+ self.cur.next();
+ return self.input.slice(start, self.input.len());
+ }
+ }
+ }
+ }
+
+ /// Parses an Argument structure, or what's contained within braces inside
+ /// the format string
+ fn argument(&mut self) -> Argument<'a> {
+ Argument {
+ position: self.position(),
+ format: self.format(),
+ method: self.method(),
+ }
+ }
+
+ /// Parses a positional argument for a format. This could either be an
+ /// integer index of an argument, a named argument, or a blank string.
+ fn position(&mut self) -> Position<'a> {
+ match self.integer() {
+ Some(i) => { ArgumentIs(i) }
+ None => {
+ match self.cur.clone().next() {
+ Some((_, c)) if char::is_alphabetic(c) => {
+ ArgumentNamed(self.word())
+ }
+ _ => ArgumentNext
+ }
+ }
+ }
+ }
+
+ /// Parses a format specifier at the current position, returning all of the
+ /// relevant information in the FormatSpec struct.
+ fn format(&mut self) -> FormatSpec<'a> {
+ let mut spec = FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: self.input.slice(0, 0),
+ };
+ if !self.consume(':') { return spec }
+
+ // fill character
+ match self.cur.clone().next() {
+ Some((_, c)) => {
+ match self.cur.clone().skip(1).next() {
+ Some((_, '>')) | Some((_, '<')) => {
+ spec.fill = Some(c);
+ self.cur.next();
+ }
+ Some(..) | None => {}
+ }
+ }
+ None => {}
+ }
+ // Alignment
+ if self.consume('<') {
+ spec.align = AlignLeft;
+ } else if self.consume('>') {
+ spec.align = AlignRight;
+ }
+ // Sign flags
+ if self.consume('+') {
+ spec.flags |= 1 << (FlagSignPlus as uint);
+ } else if self.consume('-') {
+ spec.flags |= 1 << (FlagSignMinus as uint);
+ }
+ // Alternate marker
+ if self.consume('#') {
+ spec.flags |= 1 << (FlagAlternate as uint);
+ }
+ // Width and precision
+ let mut havewidth = false;
+ if self.consume('0') {
+ // small ambiguity with '0$' as a format string. In theory this is a
+ // '0' flag and then an ill-formatted format string with just a '$'
+ // and no count, but this is better if we instead interpret this as
+ // no '0' flag and '0$' as the width instead.
+ if self.consume('$') {
+ spec.width = CountIsParam(0);
+ havewidth = true;
+ } else {
+ spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
+ }
+ }
+ if !havewidth {
+ spec.width = self.count();
+ }
+ if self.consume('.') {
+ if self.consume('*') {
+ spec.precision = CountIsNextParam;
+ } else {
+ spec.precision = self.count();
+ }
+ }
+ // Finally the actual format specifier
+ if self.consume('?') {
+ spec.ty = "?";
+ } else {
+ spec.ty = self.word();
+ }
+ return spec;
+ }
+
+ /// Parses a method to be applied to the previously specified argument and
+ /// its format. The two current supported methods are 'plural' and 'select'
+ fn method(&mut self) -> Option<Box<Method<'a>>> {
+ if !self.wsconsume(',') {
+ return None;
+ }
+ self.ws();
+ match self.word() {
+ "select" => {
+ self.must_consume(',');
+ Some(self.select())
+ }
+ "plural" => {
+ self.must_consume(',');
+ Some(self.plural())
+ }
+ "" => {
+ self.err("expected method after comma");
+ return None;
+ }
+ method => {
+ self.err(format!("unknown method: `{}`", method));
+ return None;
+ }
+ }
+ }
+
+ /// Parses a 'select' statement (after the initial 'select' word)
+ fn select(&mut self) -> Box<Method<'a>> {
+ let mut other = None;
+ let mut arms = vec!();
+ // Consume arms one at a time
+ loop {
+ self.ws();
+ let selector = self.word();
+ if selector == "" {
+ self.err("cannot have an empty selector");
+ break
+ }
+ self.must_consume('{');
+ self.depth += 1;
+ let pieces = self.collect();
+ self.depth -= 1;
+ self.must_consume('}');
+ if selector == "other" {
+ if !other.is_none() {
+ self.err("multiple `other` statements in `select");
+ }
+ other = Some(pieces);
+ } else {
+ arms.push(SelectArm { selector: selector, result: pieces });
+ }
+ self.ws();
+ match self.cur.clone().next() {
+ Some((_, '}')) => { break }
+ Some(..) | None => {}
+ }
+ }
+ // The "other" selector must be present
+ let other = match other {
+ Some(arm) => { arm }
+ None => {
+ self.err("`select` statement must provide an `other` case");
+ vec!()
+ }
+ };
+ box Select(arms, other)
+ }
+
+ /// Parses a 'plural' statement (after the initial 'plural' word)
+ fn plural(&mut self) -> Box<Method<'a>> {
+ let mut offset = None;
+ let mut other = None;
+ let mut arms = vec!();
+
+ // First, attempt to parse the 'offset:' field. We know the set of
+ // selector words which can appear in plural arms, and the only ones
+ // which start with 'o' are "other" and "offset", hence look two
+ // characters deep to see if we can consume the word "offset"
+ self.ws();
+ let mut it = self.cur.clone();
+ match it.next() {
+ Some((_, 'o')) => {
+ match it.next() {
+ Some((_, 'f')) => {
+ let word = self.word();
+ if word != "offset" {
+ self.err(format!("expected `offset`, found `{}`",
+ word));
+ } else {
+ self.must_consume(':');
+ match self.integer() {
+ Some(i) => { offset = Some(i); }
+ None => {
+ self.err("offset must be an integer");
+ }
+ }
+ }
+ }
+ Some(..) | None => {}
+ }
+ }
+ Some(..) | None => {}
+ }
+
+ // Next, generate all the arms
+ loop {
+ let mut isother = false;
+ let selector = if self.wsconsume('=') {
+ match self.integer() {
+ Some(i) => Literal(i),
+ None => {
+ self.err("plural `=` selectors must be followed by an \
+ integer");
+ Literal(0)
+ }
+ }
+ } else {
+ let word = self.word();
+ match word {
+ "other" => { isother = true; Keyword(Zero) }
+ "zero" => Keyword(Zero),
+ "one" => Keyword(One),
+ "two" => Keyword(Two),
+ "few" => Keyword(Few),
+ "many" => Keyword(Many),
+ word => {
+ self.err(format!("unexpected plural selector `{}`",
+ word));
+ if word == "" {
+ break
+ } else {
+ Keyword(Zero)
+ }
+ }
+ }
+ };
+ self.must_consume('{');
+ self.depth += 1;
+ let pieces = self.collect();
+ self.depth -= 1;
+ self.must_consume('}');
+ if isother {
+ if !other.is_none() {
+ self.err("multiple `other` statements in `select");
+ }
+ other = Some(pieces);
+ } else {
+ arms.push(PluralArm { selector: selector, result: pieces });
+ }
+ self.ws();
+ match self.cur.clone().next() {
+ Some((_, '}')) => { break }
+ Some(..) | None => {}
+ }
+ }
+
+ let other = match other {
+ Some(arm) => { arm }
+ None => {
+ self.err("`plural` statement must provide an `other` case");
+ vec!()
+ }
+ };
+ box Plural(offset, arms, other)
+ }
+
+ /// Parses a Count parameter at the current position. This does not check
+ /// for 'CountIsNextParam' because that is only used in precision, not
+ /// width.
+ fn count(&mut self) -> Count<'a> {
+ match self.integer() {
+ Some(i) => {
+ if self.consume('$') {
+ CountIsParam(i)
+ } else {
+ CountIs(i)
+ }
+ }
+ None => {
+ let tmp = self.cur.clone();
+ match self.word() {
+ word if word.len() > 0 && self.consume('$') => {
+ CountIsName(word)
+ }
+ _ => {
+ self.cur = tmp;
+ CountImplied
+ }
+ }
+ }
+ }
+ }
+
+ /// Parses a word starting at the current position. A word is considered to
+ /// be an alphabetic character followed by any number of alphanumeric
+ /// characters.
+ fn word(&mut self) -> &'a str {
+ let start = match self.cur.clone().next() {
+ Some((pos, c)) if char::is_XID_start(c) => {
+ self.cur.next();
+ pos
+ }
+ Some(..) | None => { return self.input.slice(0, 0); }
+ };
+ let mut end;
+ loop {
+ match self.cur.clone().next() {
+ Some((_, c)) if char::is_XID_continue(c) => {
+ self.cur.next();
+ }
+ Some((pos, _)) => { end = pos; break }
+ None => { end = self.input.len(); break }
+ }
+ }
+ self.input.slice(start, end)
+ }
+
+ /// Optionally parses an integer at the current position. This doesn't deal
+ /// with overflow at all, it's just accumulating digits.
+ fn integer(&mut self) -> Option<uint> {
+ let mut cur = 0;
+ let mut found = false;
+ loop {
+ match self.cur.clone().next() {
+ Some((_, c)) => {
+ match char::to_digit(c, 10) {
+ Some(i) => {
+ cur = cur * 10 + i;
+ found = true;
+ self.cur.next();
+ }
+ None => { break }
+ }
+ }
+ None => { break }
+ }
+ }
+ if found {
+ return Some(cur);
+ } else {
+ return None;
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn same(fmt: &'static str, p: &[Piece<'static>]) {
+ let mut parser = Parser::new(fmt);
+ assert!(p == parser.collect::<Vec<Piece<'static>>>().as_slice());
+ }
+
+ fn fmtdflt() -> FormatSpec<'static> {
+ return FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "",
+ }
+ }
+
+ fn musterr(s: &str) {
+ let mut p = Parser::new(s);
+ p.next();
+ assert!(p.errors.len() != 0);
+ }
+
+ #[test]
+ fn simple() {
+ same("asdf", [String("asdf")]);
+ same("a\\{b", [String("a"), String("{b")]);
+ same("a\\#b", [String("a"), String("#b")]);
+ same("a\\}b", [String("a"), String("}b")]);
+ same("a\\}", [String("a"), String("}")]);
+ same("\\}", [String("}")]);
+ }
+
+ #[test] fn invalid01() { musterr("{") }
+ #[test] fn invalid02() { musterr("\\") }
+ #[test] fn invalid03() { musterr("\\a") }
+ #[test] fn invalid04() { musterr("{3a}") }
+ #[test] fn invalid05() { musterr("{:|}") }
+ #[test] fn invalid06() { musterr("{:>>>}") }
+
+ #[test]
+ fn format_nothing() {
+ same("{}", [Argument(Argument {
+ position: ArgumentNext,
+ format: fmtdflt(),
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_position() {
+ same("{3}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: fmtdflt(),
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_position_nothing_else() {
+ same("{3:}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: fmtdflt(),
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_type() {
+ same("{3:a}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "a",
+ },
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_align_fill() {
+ same("{3:>}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: FormatSpec {
+ fill: None,
+ align: AlignRight,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "",
+ },
+ method: None,
+ })]);
+ same("{3:0<}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: FormatSpec {
+ fill: Some('0'),
+ align: AlignLeft,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "",
+ },
+ method: None,
+ })]);
+ same("{3:*<abcd}", [Argument(Argument {
+ position: ArgumentIs(3),
+ format: FormatSpec {
+ fill: Some('*'),
+ align: AlignLeft,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "abcd",
+ },
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_counts() {
+ same("{:10s}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountImplied,
+ width: CountIs(10),
+ ty: "s",
+ },
+ method: None,
+ })]);
+ same("{:10$.10s}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountIs(10),
+ width: CountIsParam(10),
+ ty: "s",
+ },
+ method: None,
+ })]);
+ same("{:.*s}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountIsNextParam,
+ width: CountImplied,
+ ty: "s",
+ },
+ method: None,
+ })]);
+ same("{:.10$s}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountIsParam(10),
+ width: CountImplied,
+ ty: "s",
+ },
+ method: None,
+ })]);
+ same("{:a$.b$s}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountIsName("b"),
+ width: CountIsName("a"),
+ ty: "s",
+ },
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_flags() {
+ same("{:-}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: (1 << FlagSignMinus as uint),
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "",
+ },
+ method: None,
+ })]);
+ same("{:+#}", [Argument(Argument {
+ position: ArgumentNext,
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint),
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "",
+ },
+ method: None,
+ })]);
+ }
+ #[test]
+ fn format_mixture() {
+ same("abcd {3:a} efg", [String("abcd "), Argument(Argument {
+ position: ArgumentIs(3),
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountImplied,
+ width: CountImplied,
+ ty: "a",
+ },
+ method: None,
+ }), String(" efg")]);
+ }
+
+ #[test]
+ fn select_simple() {
+ same("{, select, other { haha } }", [Argument(Argument{
+ position: ArgumentNext,
+ format: fmtdflt(),
+ method: Some(box Select(vec![], vec![String(" haha ")]))
+ })]);
+ same("{1, select, other { haha } }", [Argument(Argument{
+ position: ArgumentIs(1),
+ format: fmtdflt(),
+ method: Some(box Select(vec![], vec![String(" haha ")]))
+ })]);
+ same("{1, select, other {#} }", [Argument(Argument{
+ position: ArgumentIs(1),
+ format: fmtdflt(),
+ method: Some(box Select(vec![], vec![CurrentArgument]))
+ })]);
+ same("{1, select, other {{2, select, other {lol}}} }", [Argument(Argument{
+ position: ArgumentIs(1),
+ format: fmtdflt(),
+ method: Some(box Select(vec![], vec![Argument(Argument{
+ position: ArgumentIs(2),
+ format: fmtdflt(),
+ method: Some(box Select(vec![], vec![String("lol")]))
+ })])) // wat
+ })]);
+ }
+
+ #[test]
+ fn select_cases() {
+ same("{1, select, a{1} b{2} c{3} other{4} }", [Argument(Argument{
+ position: ArgumentIs(1),
+ format: fmtdflt(),
+ method: Some(box Select(vec![
+ SelectArm{ selector: "a", result: vec![String("1")] },
+ SelectArm{ selector: "b", result: vec![String("2")] },
+ SelectArm{ selector: "c", result: vec![String("3")] },
+ ], vec![String("4")]))
+ })]);
+ }
+
+ #[test] fn badselect01() { musterr("{select, }") }
+ #[test] fn badselect02() { musterr("{1, select}") }
+ #[test] fn badselect03() { musterr("{1, select, }") }
+ #[test] fn badselect04() { musterr("{1, select, a {}}") }
+ #[test] fn badselect05() { musterr("{1, select, other }}") }
+ #[test] fn badselect06() { musterr("{1, select, other {}") }
+ #[test] fn badselect07() { musterr("{select, other {}") }
+ #[test] fn badselect08() { musterr("{1 select, other {}") }
+ #[test] fn badselect09() { musterr("{:d select, other {}") }
+ #[test] fn badselect10() { musterr("{1:d select, other {}") }
+
+ #[test]
+ fn plural_simple() {
+ same("{, plural, other { haha } }", [Argument(Argument{
+ position: ArgumentNext,
+ format: fmtdflt(),
+ method: Some(box Plural(None, vec![], vec![String(" haha ")]))
+ })]);
+ same("{:, plural, other { haha } }", [Argument(Argument{
+ position: ArgumentNext,
+ format: fmtdflt(),
+ method: Some(box Plural(None, vec![], vec![String(" haha ")]))
+ })]);
+ same("{, plural, offset:1 =2{2} =3{3} many{yes} other{haha} }",
+ [Argument(Argument{
+ position: ArgumentNext,
+ format: fmtdflt(),
+ method: Some(box Plural(Some(1), vec![
+ PluralArm{ selector: Literal(2), result: vec![String("2")] },
+ PluralArm{ selector: Literal(3), result: vec![String("3")] },
+ PluralArm{ selector: Keyword(Many), result: vec![String("yes")] }
+ ], vec![String("haha")]))
+ })]);
+ }
+}
//! fn main() {
//! let args = os::args();
//!
-//! let program = args[0].clone();
+//! let program = args.get(0).clone();
//!
//! let opts = [
//! optopt("o", "", "set output file name", "NAME"),
type Ed = (int,int);
struct Edges(Vec<Ed>);
-pub fn main() {
- use std::io::File;
+pub fn render_to<W:Writer>(output: &mut W) {
let edges = Edges(vec!((0,1), (0,2), (1,3), (2,3), (3,4), (4,4)));
- let mut f = File::create(&Path::new("example1.dot"));
- dot::render(&edges, &mut f).unwrap()
+ dot::render(&edges, output).unwrap()
}
impl<'a> dot::Labeller<'a, Nd, Ed> for Edges {
fn target(&self, e: &Ed) -> Nd { let &(_,t) = e; t }
}
+
+# pub fn main() { use std::io::MemWriter; render_to(&mut MemWriter::new()) }
+```
+
+```no_run
+# pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() }
+pub fn main() {
+ use std::io::File;
+ let mut f = File::create(&Path::new("example1.dot"));
+ render_to(&mut f)
+}
```
Output from first example (in `example1.dot`):
```rust
use dot = graphviz;
use std::str;
-use std::io::File;
type Nd = uint;
type Ed<'a> = &'a (uint, uint);
struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> }
-pub fn main() {
+pub fn render_to<W:Writer>(output: &mut W) {
let nodes = vec!("{x,y}","{x}","{y}","{}");
let edges = vec!((0,1), (0,2), (1,3), (2,3));
let graph = Graph { nodes: nodes, edges: edges };
- let mut f = File::create(&Path::new("example2.dot"));
- dot::render(&graph, &mut f).unwrap()
+ dot::render(&graph, output).unwrap()
}
impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
fn source(&self, e: &Ed) -> Nd { let & &(s,_) = e; s }
fn target(&self, e: &Ed) -> Nd { let & &(_,t) = e; t }
}
+
+# pub fn main() { use std::io::MemWriter; render_to(&mut MemWriter::new()) }
+```
+
+```no_run
+# pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() }
+pub fn main() {
+ use std::io::File;
+ let mut f = File::create(&Path::new("example2.dot"));
+ render_to(&mut f)
+}
```
The third example is similar to the second, except now each node and
```rust
use dot = graphviz;
use std::str;
-use std::io::File;
type Nd<'a> = (uint, &'a str);
type Ed<'a> = (Nd<'a>, Nd<'a>);
struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> }
-pub fn main() {
+pub fn render_to<W:Writer>(output: &mut W) {
let nodes = vec!("{x,y}","{x}","{y}","{}");
let edges = vec!((0,1), (0,2), (1,3), (2,3));
let graph = Graph { nodes: nodes, edges: edges };
- let mut f = File::create(&Path::new("example3.dot"));
- dot::render(&graph, &mut f).unwrap()
+ dot::render(&graph, output).unwrap()
}
impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
fn source(&self, e: &Ed<'a>) -> Nd<'a> { let &(s,_) = e; s }
fn target(&self, e: &Ed<'a>) -> Nd<'a> { let &(_,t) = e; t }
}
+
+# pub fn main() { use std::io::MemWriter; render_to(&mut MemWriter::new()) }
+```
+
+```no_run
+# pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() }
+pub fn main() {
+ use std::io::File;
+ let mut f = File::create(&Path::new("example3.dot"));
+ render_to(&mut f)
+}
```
# References
pub use consts::os::bsd44::{SO_REUSEADDR, SO_BROADCAST, SHUT_WR, IP_MULTICAST_LOOP};
pub use consts::os::bsd44::{IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP};
pub use consts::os::bsd44::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP};
-pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL};
+pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, SHUT_RD};
pub use funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit};
pub use funcs::c95::ctype::{islower, isprint, ispunct, isspace};
#[cfg(windows)] pub use consts::os::extra::{FILE_WRITE_ATTRIBUTES, FILE_READ_ATTRIBUTES};
#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_BUSY, ERROR_IO_PENDING};
#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0};
+#[cfg(windows)] pub use consts::os::extra::{ERROR_NOT_FOUND};
+#[cfg(windows)] pub use consts::os::extra::{ERROR_OPERATION_ABORTED};
#[cfg(windows)] pub use types::os::common::bsd44::{SOCKET};
#[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf};
#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES};
pub static ERROR_NO_DATA: c_int = 232;
pub static ERROR_INVALID_ADDRESS : c_int = 487;
pub static ERROR_PIPE_CONNECTED: c_int = 535;
+ pub static ERROR_OPERATION_ABORTED: c_int = 995;
pub static ERROR_IO_PENDING: c_int = 997;
pub static ERROR_FILE_INVALID : c_int = 1006;
+ pub static ERROR_NOT_FOUND: c_int = 1168;
pub static INVALID_HANDLE_VALUE : c_int = -1;
pub static DELETE : DWORD = 0x00010000;
use std::fmt;
use std::io::LineBufferedWriter;
use std::io;
-use std::local_data;
use std::os;
use std::rt;
use std::slice;
// Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
- let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
+ let mut logger = local_logger.replace(None).unwrap_or_else(|| {
box DefaultLogger { handle: io::stderr() } as Box<Logger:Send>
});
logger.log(&LogRecord {
module_path: loc.module_path,
line: loc.line,
});
- local_data::set(local_logger, logger);
+ local_logger.replace(Some(logger));
}
/// Getter for the global log level. This is a function so that it can be called
/// Replaces the task-local logger with the specified logger, returning the old
/// logger.
pub fn set_logger(logger: Box<Logger:Send>) -> Option<Box<Logger:Send>> {
- let prev = local_data::pop(local_logger);
- local_data::set(local_logger, logger);
- return prev;
+ local_logger.replace(Some(logger))
}
/// A LogRecord is created by the logging macros, and passed as the only
impl GetAddrInfoRequest {
pub fn run(host: Option<&str>, servname: Option<&str>,
- hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
+ hint: Option<ai::Hint>) -> Result<Vec<ai::Info>, IoError> {
assert!(host.is_some() || servname.is_some());
let c_host = host.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
unsafe { freeaddrinfo(res); }
- Ok(addrs.move_iter().collect())
+ Ok(addrs)
}
}
#[cfg(target_os = "android")]
pub static FIOCLEX: libc::c_ulong = 0x5451;
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+pub static MSG_DONTWAIT: libc::c_int = 0x80;
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+pub static MSG_DONTWAIT: libc::c_int = 0x40;
+
extern {
pub fn gettimeofday(timeval: *mut libc::timeval,
tzp: *libc::c_void) -> libc::c_int;
pub static WSASYS_STATUS_LEN: uint = 128;
pub static FIONBIO: libc::c_long = 0x8004667e;
static FD_SETSIZE: uint = 64;
+pub static MSG_DONTWAIT: libc::c_int = 0;
pub struct WSADATA {
pub wVersion: libc::WORD,
optlen: *mut libc::c_int) -> libc::c_int;
pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
+ pub fn CancelIoEx(hFile: libc::HANDLE,
+ lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
}
use libc::{c_int, c_void};
use libc;
-use std::sync::arc::UnsafeArc;
use std::c_str::CString;
use std::io::IoError;
use std::io;
use std::mem;
use std::rt::rtio;
+use std::sync::arc::UnsafeArc;
use io::{IoResult, retry, keep_going};
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
}
+
+ // Only supported on named pipes currently. Note that this doesn't have an
+ // impact on the std::io primitives, this is never called via
+ // std::io::PipeStream. If the functionality is exposed in the future, then
+ // these methods will need to be implemented.
+ fn close_read(&mut self) -> Result<(), IoError> {
+ Err(io::standard_error(io::InvalidInput))
+ }
+ fn close_write(&mut self) -> Result<(), IoError> {
+ Err(io::standard_error(io::InvalidInput))
+ }
+ fn set_timeout(&mut self, _t: Option<u64>) {}
+ fn set_read_timeout(&mut self, _t: Option<u64>) {}
+ fn set_write_timeout(&mut self, _t: Option<u64>) {}
}
impl rtio::RtioTTY for FileDesc {
use std::rt::rtio;
use std::str;
use std::sync::arc::UnsafeArc;
-use std::slice;
+use std::vec;
use io::IoResult;
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
}
+
+ // Only supported on named pipes currently. Note that this doesn't have an
+ // impact on the std::io primitives, this is never called via
+ // std::io::PipeStream. If the functionality is exposed in the future, then
+ // these methods will need to be implemented.
+ fn close_read(&mut self) -> IoResult<()> {
+ Err(io::standard_error(io::InvalidInput))
+ }
+ fn close_write(&mut self) -> IoResult<()> {
+ Err(io::standard_error(io::InvalidInput))
+ }
+ fn set_timeout(&mut self, _t: Option<u64>) {}
+ fn set_read_timeout(&mut self, _t: Option<u64>) {}
+ fn set_write_timeout(&mut self, _t: Option<u64>) {}
}
impl rtio::RtioTTY for FileDesc {
if fp_buf as uint == 0 {
fail!("os::list_dir() failure: got null ptr from wfd");
} else {
- let fp_vec = slice::from_buf(fp_buf, libc::wcslen(fp_buf) as uint);
- let fp_trimmed = str::truncate_utf16_at_nul(fp_vec);
+ let fp_vec = vec::raw::from_buf(fp_buf, libc::wcslen(fp_buf) as uint);
+ let fp_trimmed = str::truncate_utf16_at_nul(fp_vec.as_slice());
let fp_str = str::from_utf16(fp_trimmed)
.expect("rust_list_dir_wfd_fp_buf returned invalid UTF-16");
paths.push(Path::new(fp_str));
})
}
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
- hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
+ hint: Option<ai::Hint>) -> IoResult<Vec<ai::Info>> {
addrinfo::GetAddrInfoRequest::run(host, servname, hint)
}
}
fn spawn(&mut self, config: ProcessConfig)
-> IoResult<(Box<RtioProcess:Send>,
- ~[Option<Box<RtioPipe:Send>>])> {
+ Vec<Option<Box<RtioPipe:Send>>>)> {
process::Process::spawn(config).map(|(p, io)| {
(box p as Box<RtioProcess:Send>,
io.move_iter().map(|p| p.map(|p| {
use std::mem;
use std::rt::rtio;
use std::sync::arc::UnsafeArc;
+use std::unstable::mutex;
use super::{IoResult, retry, keep_going};
use super::c;
pub struct TcpStream {
inner: UnsafeArc<Inner>,
+ read_deadline: u64,
+ write_deadline: u64,
}
struct Inner {
fd: sock_t,
+ lock: mutex::NativeMutex,
+}
+
+pub struct Guard<'a> {
+ pub fd: sock_t,
+ pub guard: mutex::LockGuard<'a>,
+}
+
+impl Inner {
+ fn new(fd: sock_t) -> Inner {
+ Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+ }
}
impl TcpStream {
pub fn connect(addr: ip::SocketAddr,
timeout: Option<u64>) -> IoResult<TcpStream> {
let fd = try!(socket(addr, libc::SOCK_STREAM));
- let (addr, len) = addr_to_sockaddr(addr);
- let inner = Inner { fd: fd };
- let ret = TcpStream { inner: UnsafeArc::new(inner) };
+ let ret = TcpStream::new(Inner::new(fd));
- let len = len as libc::socklen_t;
+ let (addr, len) = addr_to_sockaddr(addr);
let addrp = &addr as *_ as *libc::sockaddr;
+ let len = len as libc::socklen_t;
+
match timeout {
Some(timeout) => {
try!(util::connect_timeout(fd, addrp, len, timeout));
}
}
+ fn new(inner: Inner) -> TcpStream {
+ TcpStream {
+ inner: UnsafeArc::new(inner),
+ read_deadline: 0,
+ write_deadline: 0,
+ }
+ }
+
pub fn fd(&self) -> sock_t {
// This unsafety is fine because it's just a read-only arc
unsafe { (*self.inner.get()).fd }
fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> {
Ok(())
}
+
+ #[cfg(target_os = "linux")]
+ fn lock_nonblocking(&self) {}
+
+ #[cfg(not(target_os = "linux"))]
+ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
+ let ret = Guard {
+ fd: self.fd(),
+ guard: unsafe { (*self.inner.get()).lock.lock() },
+ };
+ assert!(util::set_nonblocking(self.fd(), true).is_ok());
+ ret
+ }
}
#[cfg(windows)] type wrlen = libc::c_int;
impl rtio::RtioTcpStream for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
- let ret = retry(|| {
- unsafe {
- libc::recv(self.fd(),
- buf.as_mut_ptr() as *mut libc::c_void,
- buf.len() as wrlen,
- 0) as libc::c_int
- }
- });
- if ret == 0 {
- Err(io::standard_error(io::EndOfFile))
- } else if ret < 0 {
- Err(last_error())
- } else {
- Ok(ret as uint)
- }
+ let fd = self.fd();
+ let dolock = || self.lock_nonblocking();
+ let doread = |nb| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::recv(fd,
+ buf.as_mut_ptr() as *mut libc::c_void,
+ buf.len() as wrlen,
+ flags) as libc::c_int
+ };
+ read(fd, self.read_deadline, dolock, doread)
}
+
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- let ret = keep_going(buf, |buf, len| unsafe {
- libc::send(self.fd(),
+ let fd = self.fd();
+ let dolock = || self.lock_nonblocking();
+ let dowrite = |nb: bool, buf: *u8, len: uint| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::send(fd,
buf as *mut libc::c_void,
len as wrlen,
- 0) as i64
- });
- if ret < 0 {
- Err(super::last_error())
- } else {
- Ok(())
+ flags) as i64
+ };
+ match write(fd, self.write_deadline, buf, true, dolock, dowrite) {
+ Ok(_) => Ok(()),
+ Err(e) => Err(e)
}
}
fn peer_name(&mut self) -> IoResult<ip::SocketAddr> {
fn clone(&self) -> Box<rtio::RtioTcpStream:Send> {
box TcpStream {
inner: self.inner.clone(),
+ read_deadline: 0,
+ write_deadline: 0,
} as Box<rtio::RtioTcpStream:Send>
}
+
fn close_write(&mut self) -> IoResult<()> {
- super::mkerr_libc(unsafe {
- libc::shutdown(self.fd(), libc::SHUT_WR)
- })
+ super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
+ }
+ fn close_read(&mut self) -> IoResult<()> {
+ super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
+ }
+
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ let deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ self.read_deadline = deadline;
+ self.write_deadline = deadline;
+ }
+ fn set_read_timeout(&mut self, timeout: Option<u64>) {
+ self.read_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
+ fn set_write_timeout(&mut self, timeout: Option<u64>) {
+ self.write_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
}
}
fn drop(&mut self) { unsafe { close(self.fd); } }
}
+#[unsafe_destructor]
+impl<'a> Drop for Guard<'a> {
+ fn drop(&mut self) {
+ assert!(util::set_nonblocking(self.fd, false).is_ok());
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// TCP listeners
////////////////////////////////////////////////////////////////////////////////
impl TcpListener {
pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
- unsafe {
- socket(addr, libc::SOCK_STREAM).and_then(|fd| {
- let (addr, len) = addr_to_sockaddr(addr);
- let addrp = &addr as *libc::sockaddr_storage;
- let inner = Inner { fd: fd };
- let ret = TcpListener { inner: inner };
- // On platforms with Berkeley-derived sockets, this allows
- // to quickly rebind a socket, without needing to wait for
- // the OS to clean up the previous one.
- if cfg!(unix) {
- match setsockopt(fd, libc::SOL_SOCKET,
- libc::SO_REUSEADDR,
- 1 as libc::c_int) {
- Err(n) => { return Err(n); },
- Ok(..) => { }
- }
- }
- match libc::bind(fd, addrp as *libc::sockaddr,
- len as libc::socklen_t) {
- -1 => Err(last_error()),
- _ => Ok(ret),
- }
- })
+ let fd = try!(socket(addr, libc::SOCK_STREAM));
+ let ret = TcpListener { inner: Inner::new(fd) };
+
+ let (addr, len) = addr_to_sockaddr(addr);
+ let addrp = &addr as *_ as *libc::sockaddr;
+ let len = len as libc::socklen_t;
+
+ // On platforms with Berkeley-derived sockets, this allows
+ // to quickly rebind a socket, without needing to wait for
+ // the OS to clean up the previous one.
+ if cfg!(unix) {
+ try!(setsockopt(fd, libc::SOL_SOCKET, libc::SO_REUSEADDR,
+ 1 as libc::c_int));
+ }
+
+ match unsafe { libc::bind(fd, addrp, len) } {
+ -1 => Err(last_error()),
+ _ => Ok(ret),
}
}
pub fn native_accept(&mut self) -> IoResult<TcpStream> {
if self.deadline != 0 {
- try!(util::accept_deadline(self.fd(), self.deadline));
+ try!(util::await(self.fd(), Some(self.deadline), util::Readable));
}
unsafe {
let mut storage: libc::sockaddr_storage = mem::init();
&mut size as *mut libc::socklen_t) as libc::c_int
}) as sock_t {
-1 => Err(last_error()),
- fd => Ok(TcpStream { inner: UnsafeArc::new(Inner { fd: fd })})
+ fd => Ok(TcpStream::new(Inner::new(fd))),
}
}
}
pub struct UdpSocket {
inner: UnsafeArc<Inner>,
+ read_deadline: u64,
+ write_deadline: u64,
}
impl UdpSocket {
pub fn bind(addr: ip::SocketAddr) -> IoResult<UdpSocket> {
- unsafe {
- socket(addr, libc::SOCK_DGRAM).and_then(|fd| {
- let (addr, len) = addr_to_sockaddr(addr);
- let addrp = &addr as *libc::sockaddr_storage;
- let inner = Inner { fd: fd };
- let ret = UdpSocket { inner: UnsafeArc::new(inner) };
- match libc::bind(fd, addrp as *libc::sockaddr,
- len as libc::socklen_t) {
- -1 => Err(last_error()),
- _ => Ok(ret),
- }
- })
+ let fd = try!(socket(addr, libc::SOCK_DGRAM));
+ let ret = UdpSocket {
+ inner: UnsafeArc::new(Inner::new(fd)),
+ read_deadline: 0,
+ write_deadline: 0,
+ };
+
+ let (addr, len) = addr_to_sockaddr(addr);
+ let addrp = &addr as *_ as *libc::sockaddr;
+ let len = len as libc::socklen_t;
+
+ match unsafe { libc::bind(fd, addrp, len) } {
+ -1 => Err(last_error()),
+ _ => Ok(ret),
}
}
}
}
}
+
+ #[cfg(target_os = "linux")]
+ fn lock_nonblocking(&self) {}
+
+ #[cfg(not(target_os = "linux"))]
+ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
+ let ret = Guard {
+ fd: self.fd(),
+ guard: unsafe { (*self.inner.get()).lock.lock() },
+ };
+ assert!(util::set_nonblocking(self.fd(), true).is_ok());
+ ret
+ }
}
impl rtio::RtioSocket for UdpSocket {
impl rtio::RtioUdpSocket for UdpSocket {
fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, ip::SocketAddr)> {
- unsafe {
- let mut storage: libc::sockaddr_storage = mem::init();
- let storagep = &mut storage as *mut libc::sockaddr_storage;
- let mut addrlen: libc::socklen_t =
- mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
- let ret = retry(|| {
- libc::recvfrom(self.fd(),
- buf.as_ptr() as *mut libc::c_void,
- buf.len() as msglen_t,
- 0,
- storagep as *mut libc::sockaddr,
- &mut addrlen) as libc::c_int
- });
- if ret < 0 { return Err(last_error()) }
- sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
- Ok((ret as uint, addr))
- })
- }
+ let fd = self.fd();
+ let mut storage: libc::sockaddr_storage = unsafe { mem::init() };
+ let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
+ let mut addrlen: libc::socklen_t =
+ mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
+
+ let dolock = || self.lock_nonblocking();
+ let doread = |nb| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::recvfrom(fd,
+ buf.as_mut_ptr() as *mut libc::c_void,
+ buf.len() as msglen_t,
+ flags,
+ storagep,
+ &mut addrlen) as libc::c_int
+ };
+ let n = try!(read(fd, self.read_deadline, dolock, doread));
+ sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
+ Ok((n as uint, addr))
+ })
}
+
fn sendto(&mut self, buf: &[u8], dst: ip::SocketAddr) -> IoResult<()> {
- let (dst, len) = addr_to_sockaddr(dst);
- let dstp = &dst as *libc::sockaddr_storage;
- unsafe {
- let ret = retry(|| {
- libc::sendto(self.fd(),
- buf.as_ptr() as *libc::c_void,
- buf.len() as msglen_t,
- 0,
- dstp as *libc::sockaddr,
- len as libc::socklen_t) as libc::c_int
- });
- match ret {
- -1 => Err(last_error()),
- n if n as uint != buf.len() => {
- Err(io::IoError {
- kind: io::OtherIoError,
- desc: "couldn't send entire packet at once",
- detail: None,
- })
- }
- _ => Ok(())
- }
+ let (dst, dstlen) = addr_to_sockaddr(dst);
+ let dstp = &dst as *_ as *libc::sockaddr;
+ let dstlen = dstlen as libc::socklen_t;
+
+ let fd = self.fd();
+ let dolock = || self.lock_nonblocking();
+ let dowrite = |nb, buf: *u8, len: uint| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::sendto(fd,
+ buf as *libc::c_void,
+ len as msglen_t,
+ flags,
+ dstp,
+ dstlen) as i64
+ };
+
+ let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
+ if n != buf.len() {
+ Err(io::IoError {
+ kind: io::ShortWrite(n),
+ desc: "couldn't send entire packet at once",
+ detail: None,
+ })
+ } else {
+ Ok(())
}
}
fn clone(&self) -> Box<rtio::RtioUdpSocket:Send> {
box UdpSocket {
inner: self.inner.clone(),
+ read_deadline: 0,
+ write_deadline: 0,
} as Box<rtio::RtioUdpSocket:Send>
}
+
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ let deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ self.read_deadline = deadline;
+ self.write_deadline = deadline;
+ }
+ fn set_read_timeout(&mut self, timeout: Option<u64>) {
+ self.read_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
+ fn set_write_timeout(&mut self, timeout: Option<u64>) {
+ self.write_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Timeout helpers
+//
+// The read/write functions below are the helpers for reading/writing a socket
+// with a possible deadline specified. This is generally viewed as a timed out
+// I/O operation.
+//
+// From the application's perspective, timeouts apply to the I/O object, not to
+// the underlying file descriptor (it's one timeout per object). This means that
+// we can't use the SO_RCVTIMEO and corresponding send timeout option.
+//
+// The next idea to implement timeouts would be to use nonblocking I/O. An
+// invocation of select() would wait (with a timeout) for a socket to be ready.
+// Once its ready, we can perform the operation. Note that the operation *must*
+// be nonblocking, even though select() says the socket is ready. This is
+// because some other thread could have come and stolen our data (handles can be
+// cloned).
+//
+// To implement nonblocking I/O, the first option we have is to use the
+// O_NONBLOCK flag. Remember though that this is a global setting, affecting all
+// I/O objects, so this was initially viewed as unwise.
+//
+// It turns out that there's this nifty MSG_DONTWAIT flag which can be passed to
+// send/recv, but the niftiness wears off once you realize it only works well on
+// linux [1] [2]. This means that it's pretty easy to get a nonblocking
+// operation on linux (no flag fidding, no affecting other objects), but not on
+// other platforms.
+//
+// To work around this constraint on other platforms, we end up using the
+// original strategy of flipping the O_NONBLOCK flag. As mentioned before, this
+// could cause other objects' blocking operations to suddenly become
+// nonblocking. To get around this, a "blocking operation" which returns EAGAIN
+// falls back to using the same code path as nonblocking operations, but with an
+// infinite timeout (select + send/recv). This helps emulate blocking
+// reads/writes despite the underlying descriptor being nonblocking, as well as
+// optimizing the fast path of just hitting one syscall in the good case.
+//
+// As a final caveat, this implementation uses a mutex so only one thread is
+// doing a nonblocking operation at at time. This is the operation that comes
+// after the select() (at which point we think the socket is ready). This is
+// done for sanity to ensure that the state of the O_NONBLOCK flag is what we
+// expect (wouldn't want someone turning it on when it should be off!). All
+// operations performed in the lock are *nonblocking* to avoid holding the mutex
+// forever.
+//
+// So, in summary, linux uses MSG_DONTWAIT and doesn't need mutexes, everyone
+// else uses O_NONBLOCK and mutexes with some trickery to make sure blocking
+// reads/writes are still blocking.
+//
+// Fun, fun!
+//
+// [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html
+// [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait
+
+pub fn read<T>(fd: sock_t,
+ deadline: u64,
+ lock: || -> T,
+ read: |bool| -> libc::c_int) -> IoResult<uint> {
+ let mut ret = -1;
+ if deadline == 0 {
+ ret = retry(|| read(false));
+ }
+
+ if deadline != 0 || (ret == -1 && util::wouldblock()) {
+ let deadline = match deadline {
+ 0 => None,
+ n => Some(n),
+ };
+ loop {
+ // With a timeout, first we wait for the socket to become
+ // readable using select(), specifying the relevant timeout for
+ // our previously set deadline.
+ try!(util::await(fd, deadline, util::Readable));
+
+ // At this point, we're still within the timeout, and we've
+ // determined that the socket is readable (as returned by
+ // select). We must still read the socket in *nonblocking* mode
+ // because some other thread could come steal our data. If we
+ // fail to read some data, we retry (hence the outer loop) and
+ // wait for the socket to become readable again.
+ let _guard = lock();
+ match retry(|| read(deadline.is_some())) {
+ -1 if util::wouldblock() => { assert!(deadline.is_some()); }
+ -1 => return Err(last_error()),
+ n => { ret = n; break }
+ }
+ }
+ }
+
+ match ret {
+ 0 => Err(io::standard_error(io::EndOfFile)),
+ n if n < 0 => Err(last_error()),
+ n => Ok(n as uint)
+ }
+}
+
+pub fn write<T>(fd: sock_t,
+ deadline: u64,
+ buf: &[u8],
+ write_everything: bool,
+ lock: || -> T,
+ write: |bool, *u8, uint| -> i64) -> IoResult<uint> {
+ let mut ret = -1;
+ let mut written = 0;
+ if deadline == 0 {
+ if write_everything {
+ ret = keep_going(buf, |inner, len| {
+ written = buf.len() - len;
+ write(false, inner, len)
+ });
+ } else {
+ ret = retry(|| {
+ write(false, buf.as_ptr(), buf.len()) as libc::c_int
+ }) as i64;
+ if ret > 0 { written = ret as uint; }
+ }
+ }
+
+ if deadline != 0 || (ret == -1 && util::wouldblock()) {
+ let deadline = match deadline {
+ 0 => None,
+ n => Some(n),
+ };
+ while written < buf.len() && (write_everything || written == 0) {
+ // As with read(), first wait for the socket to be ready for
+ // the I/O operation.
+ match util::await(fd, deadline, util::Writable) {
+ Err(ref e) if e.kind == io::TimedOut && written > 0 => {
+ assert!(deadline.is_some());
+ return Err(io::IoError {
+ kind: io::ShortWrite(written),
+ desc: "short write",
+ detail: None,
+ })
+ }
+ Err(e) => return Err(e),
+ Ok(()) => {}
+ }
+
+ // Also as with read(), we use MSG_DONTWAIT to guard ourselves
+ // against unforseen circumstances.
+ 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) {
+ -1 if util::wouldblock() => {}
+ -1 => return Err(last_error()),
+ n => { written += n as uint; }
+ }
+ }
+ ret = 0;
+ }
+ if ret < 0 {
+ Err(last_error())
+ } else {
+ Ok(written)
+ }
}
use std::mem;
use std::rt::rtio;
use std::sync::arc::UnsafeArc;
+use std::unstable::mutex;
-use super::{IoResult, retry, keep_going};
+use super::{IoResult, retry};
+use super::net;
use super::util;
+use super::c;
use super::file::fd_t;
fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
struct Inner {
fd: fd_t,
+ lock: mutex::NativeMutex,
+}
+
+impl Inner {
+ fn new(fd: fd_t) -> Inner {
+ Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+ }
}
impl Drop for Inner {
fn connect(addr: &CString, ty: libc::c_int,
timeout: Option<u64>) -> IoResult<Inner> {
let (addr, len) = try!(addr_to_sockaddr_un(addr));
- let inner = Inner { fd: try!(unix_socket(ty)) };
+ let inner = Inner::new(try!(unix_socket(ty)));
let addrp = &addr as *_ as *libc::sockaddr;
let len = len as libc::socklen_t;
fn bind(addr: &CString, ty: libc::c_int) -> IoResult<Inner> {
let (addr, len) = try!(addr_to_sockaddr_un(addr));
- let inner = Inner { fd: try!(unix_socket(ty)) };
+ let inner = Inner::new(try!(unix_socket(ty)));
let addrp = &addr as *libc::sockaddr_storage;
match unsafe {
libc::bind(inner.fd, addrp as *libc::sockaddr, len as libc::socklen_t)
pub struct UnixStream {
inner: UnsafeArc<Inner>,
+ read_deadline: u64,
+ write_deadline: u64,
}
impl UnixStream {
pub fn connect(addr: &CString,
timeout: Option<u64>) -> IoResult<UnixStream> {
connect(addr, libc::SOCK_STREAM, timeout).map(|inner| {
- UnixStream { inner: UnsafeArc::new(inner) }
+ UnixStream::new(UnsafeArc::new(inner))
})
}
+ fn new(inner: UnsafeArc<Inner>) -> UnixStream {
+ UnixStream {
+ inner: inner,
+ read_deadline: 0,
+ write_deadline: 0,
+ }
+ }
+
fn fd(&self) -> fd_t { unsafe { (*self.inner.get()).fd } }
+
+ #[cfg(target_os = "linux")]
+ fn lock_nonblocking(&self) {}
+
+ #[cfg(not(target_os = "linux"))]
+ fn lock_nonblocking<'a>(&'a self) -> net::Guard<'a> {
+ let ret = net::Guard {
+ fd: self.fd(),
+ guard: unsafe { (*self.inner.get()).lock.lock() },
+ };
+ assert!(util::set_nonblocking(self.fd(), true).is_ok());
+ ret
+ }
}
impl rtio::RtioPipe for UnixStream {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
- let ret = retry(|| unsafe {
- libc::recv(self.fd(),
- buf.as_ptr() as *mut libc::c_void,
+ let fd = self.fd();
+ let dolock = || self.lock_nonblocking();
+ let doread = |nb| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::recv(fd,
+ buf.as_mut_ptr() as *mut libc::c_void,
buf.len() as libc::size_t,
- 0) as libc::c_int
- });
- if ret == 0 {
- Err(io::standard_error(io::EndOfFile))
- } else if ret < 0 {
- Err(super::last_error())
- } else {
- Ok(ret as uint)
- }
+ flags) as libc::c_int
+ };
+ net::read(fd, self.read_deadline, dolock, doread)
}
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- let ret = keep_going(buf, |buf, len| unsafe {
- libc::send(self.fd(),
+ let fd = self.fd();
+ let dolock = || self.lock_nonblocking();
+ let dowrite = |nb: bool, buf: *u8, len: uint| unsafe {
+ let flags = if nb {c::MSG_DONTWAIT} else {0};
+ libc::send(fd,
buf as *mut libc::c_void,
len as libc::size_t,
- 0) as i64
- });
- if ret < 0 {
- Err(super::last_error())
- } else {
- Ok(())
+ flags) as i64
+ };
+ match net::write(fd, self.write_deadline, buf, true, dolock, dowrite) {
+ Ok(_) => Ok(()),
+ Err(e) => Err(e)
}
}
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
- box UnixStream {
- inner: self.inner.clone(),
- } as Box<rtio::RtioPipe:Send>
+ box UnixStream::new(self.inner.clone()) as Box<rtio::RtioPipe:Send>
+ }
+
+ fn close_write(&mut self) -> IoResult<()> {
+ super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
+ }
+ fn close_read(&mut self) -> IoResult<()> {
+ super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
+ }
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ let deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ self.read_deadline = deadline;
+ self.write_deadline = deadline;
+ }
+ fn set_read_timeout(&mut self, timeout: Option<u64>) {
+ self.read_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
+ fn set_write_timeout(&mut self, timeout: Option<u64>) {
+ self.write_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
}
}
pub fn native_accept(&mut self) -> IoResult<UnixStream> {
if self.deadline != 0 {
- try!(util::accept_deadline(self.fd(), self.deadline));
+ try!(util::await(self.fd(), Some(self.deadline), util::Readable));
}
let mut storage: libc::sockaddr_storage = unsafe { intrinsics::init() };
let storagep = &mut storage as *mut libc::sockaddr_storage;
&mut size as *mut libc::socklen_t) as libc::c_int
}) {
-1 => Err(super::last_error()),
- fd => Ok(UnixStream { inner: UnsafeArc::new(Inner { fd: fd }) })
+ fd => Ok(UnixStream::new(UnsafeArc::new(Inner::new(fd))))
}
}
}
//! the test suite passing (the suite is in libstd), and that's good enough for
//! me!
-use std::c_str::CString;
use libc;
+use std::c_str::CString;
+use std::intrinsics;
+use std::io;
use std::os::win32::as_utf16_p;
+use std::os;
use std::ptr;
use std::rt::rtio;
use std::sync::arc::UnsafeArc;
-use std::intrinsics;
+use std::sync::atomics;
+use std::unstable::mutex;
use super::IoResult;
use super::c;
struct Inner {
handle: libc::HANDLE,
+ lock: mutex::NativeMutex,
+ read_closed: atomics::AtomicBool,
+ write_closed: atomics::AtomicBool,
+}
+
+impl Inner {
+ fn new(handle: libc::HANDLE) -> Inner {
+ Inner {
+ handle: handle,
+ lock: unsafe { mutex::NativeMutex::new() },
+ read_closed: atomics::AtomicBool::new(false),
+ write_closed: atomics::AtomicBool::new(false),
+ }
+ }
}
impl Drop for Inner {
)
}
+pub fn await(handle: libc::HANDLE, deadline: u64,
+ overlapped: &mut libc::OVERLAPPED) -> bool {
+ if deadline == 0 { return true }
+
+ // If we've got a timeout, use WaitForSingleObject in tandem with CancelIo
+ // to figure out if we should indeed get the result.
+ let now = ::io::timer::now();
+ let timeout = deadline < now || unsafe {
+ let ms = (deadline - now) as libc::DWORD;
+ let r = libc::WaitForSingleObject(overlapped.hEvent,
+ ms);
+ r != libc::WAIT_OBJECT_0
+ };
+ if timeout {
+ unsafe { let _ = c::CancelIo(handle); }
+ false
+ } else {
+ true
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Unix Streams
////////////////////////////////////////////////////////////////////////////////
inner: UnsafeArc<Inner>,
write: Option<Event>,
read: Option<Event>,
+ read_deadline: u64,
+ write_deadline: u64,
}
impl UnixStream {
loop {
match UnixStream::try_connect(p) {
Some(handle) => {
- let inner = Inner { handle: handle };
+ let inner = Inner::new(handle);
let mut mode = libc::PIPE_TYPE_BYTE |
libc::PIPE_READMODE_BYTE |
libc::PIPE_WAIT;
inner: UnsafeArc::new(inner),
read: None,
write: None,
+ read_deadline: 0,
+ write_deadline: 0,
})
}
}
}
fn handle(&self) -> libc::HANDLE { unsafe { (*self.inner.get()).handle } }
+
+ fn read_closed(&self) -> bool {
+ unsafe { (*self.inner.get()).read_closed.load(atomics::SeqCst) }
+ }
+
+ fn write_closed(&self) -> bool {
+ unsafe { (*self.inner.get()).write_closed.load(atomics::SeqCst) }
+ }
+
+ fn cancel_io(&self) -> IoResult<()> {
+ match unsafe { c::CancelIoEx(self.handle(), ptr::mut_null()) } {
+ 0 if os::errno() == libc::ERROR_NOT_FOUND as uint => {
+ Ok(())
+ }
+ 0 => Err(super::last_error()),
+ _ => Ok(())
+ }
+ }
}
impl rtio::RtioPipe for UnixStream {
let mut overlapped: libc::OVERLAPPED = unsafe { intrinsics::init() };
overlapped.hEvent = self.read.get_ref().handle();
+ // Pre-flight check to see if the reading half has been closed. This
+ // must be done before issuing the ReadFile request, but after we
+ // acquire the lock.
+ //
+ // See comments in close_read() about why this lock is necessary.
+ let guard = unsafe { (*self.inner.get()).lock.lock() };
+ if self.read_closed() {
+ return Err(io::standard_error(io::EndOfFile))
+ }
+
+ // Issue a nonblocking requests, succeeding quickly if it happened to
+ // succeed.
let ret = unsafe {
libc::ReadFile(self.handle(),
buf.as_ptr() as libc::LPVOID,
&mut bytes_read,
&mut overlapped)
};
- if ret == 0 {
- let err = unsafe { libc::GetLastError() };
- if err == libc::ERROR_IO_PENDING as libc::DWORD {
- let ret = unsafe {
- libc::GetOverlappedResult(self.handle(),
- &mut overlapped,
- &mut bytes_read,
- libc::TRUE)
- };
- if ret == 0 {
- return Err(super::last_error())
- }
- } else {
+ if ret != 0 { return Ok(bytes_read as uint) }
+
+ // If our errno doesn't say that the I/O is pending, then we hit some
+ // legitimate error and reeturn immediately.
+ if os::errno() != libc::ERROR_IO_PENDING as uint {
+ return Err(super::last_error())
+ }
+
+ // Now that we've issued a successful nonblocking request, we need to
+ // wait for it to finish. This can all be done outside the lock because
+ // we'll see any invocation of CancelIoEx. We also call this in a loop
+ // because we're woken up if the writing half is closed, we just need to
+ // realize that the reading half wasn't closed and we go right back to
+ // sleep.
+ drop(guard);
+ loop {
+ // Process a timeout if one is pending
+ let succeeded = await(self.handle(), self.read_deadline,
+ &mut overlapped);
+
+ let ret = unsafe {
+ libc::GetOverlappedResult(self.handle(),
+ &mut overlapped,
+ &mut bytes_read,
+ libc::TRUE)
+ };
+ // If we succeeded, or we failed for some reason other than
+ // CancelIoEx, return immediately
+ if ret != 0 { return Ok(bytes_read as uint) }
+ if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
return Err(super::last_error())
}
- }
- Ok(bytes_read as uint)
+ // If the reading half is now closed, then we're done. If we woke up
+ // because the writing half was closed, keep trying.
+ if !succeeded {
+ return Err(io::standard_error(io::TimedOut))
+ }
+ if self.read_closed() {
+ return Err(io::standard_error(io::EndOfFile))
+ }
+ }
}
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
while offset < buf.len() {
let mut bytes_written = 0;
+
+ // This sequence below is quite similar to the one found in read().
+ // Some careful looping is done to ensure that if close_write() is
+ // invoked we bail out early, and if close_read() is invoked we keep
+ // going after we woke up.
+ //
+ // See comments in close_read() about why this lock is necessary.
+ let guard = unsafe { (*self.inner.get()).lock.lock() };
+ if self.write_closed() {
+ return Err(io::standard_error(io::BrokenPipe))
+ }
let ret = unsafe {
libc::WriteFile(self.handle(),
buf.slice_from(offset).as_ptr() as libc::LPVOID,
&mut bytes_written,
&mut overlapped)
};
+ let err = os::errno();
+ drop(guard);
+
if ret == 0 {
- let err = unsafe { libc::GetLastError() };
- if err == libc::ERROR_IO_PENDING as libc::DWORD {
- let ret = unsafe {
- libc::GetOverlappedResult(self.handle(),
- &mut overlapped,
- &mut bytes_written,
- libc::TRUE)
- };
- if ret == 0 {
+ if err != libc::ERROR_IO_PENDING as uint {
+ return Err(io::IoError::from_errno(err, true));
+ }
+ // Process a timeout if one is pending
+ let succeeded = await(self.handle(), self.write_deadline,
+ &mut overlapped);
+ let ret = unsafe {
+ libc::GetOverlappedResult(self.handle(),
+ &mut overlapped,
+ &mut bytes_written,
+ libc::TRUE)
+ };
+ // If we weren't aborted, this was a legit error, if we were
+ // aborted, then check to see if the write half was actually
+ // closed or whether we woke up from the read half closing.
+ if ret == 0 {
+ if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
return Err(super::last_error())
}
- } else {
- return Err(super::last_error())
+ if !succeeded {
+ let amt = offset + bytes_written as uint;
+ return if amt > 0 {
+ Err(io::IoError {
+ kind: io::ShortWrite(amt),
+ desc: "short write during write",
+ detail: None,
+ })
+ } else {
+ Err(util::timeout("write timed out"))
+ }
+ }
+ if self.write_closed() {
+ return Err(io::standard_error(io::BrokenPipe))
+ }
+ continue // retry
}
}
offset += bytes_written as uint;
inner: self.inner.clone(),
read: None,
write: None,
+ read_deadline: 0,
+ write_deadline: 0,
} as Box<rtio::RtioPipe:Send>
}
+
+ fn close_read(&mut self) -> IoResult<()> {
+ // On windows, there's no actual shutdown() method for pipes, so we're
+ // forced to emulate the behavior manually at the application level. To
+ // do this, we need to both cancel any pending requests, as well as
+ // prevent all future requests from succeeding. These two operations are
+ // not atomic with respect to one another, so we must use a lock to do
+ // so.
+ //
+ // The read() code looks like:
+ //
+ // 1. Make sure the pipe is still open
+ // 2. Submit a read request
+ // 3. Wait for the read request to finish
+ //
+ // The race this lock is preventing is if another thread invokes
+ // close_read() between steps 1 and 2. By atomically executing steps 1
+ // and 2 with a lock with respect to close_read(), we're guaranteed that
+ // no thread will erroneously sit in a read forever.
+ let _guard = unsafe { (*self.inner.get()).lock.lock() };
+ unsafe { (*self.inner.get()).read_closed.store(true, atomics::SeqCst) }
+ self.cancel_io()
+ }
+
+ fn close_write(&mut self) -> IoResult<()> {
+ // see comments in close_read() for why this lock is necessary
+ let _guard = unsafe { (*self.inner.get()).lock.lock() };
+ unsafe { (*self.inner.get()).write_closed.store(true, atomics::SeqCst) }
+ self.cancel_io()
+ }
+
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ let deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ self.read_deadline = deadline;
+ self.write_deadline = deadline;
+ }
+ fn set_read_timeout(&mut self, timeout: Option<u64>) {
+ self.read_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
+ fn set_write_timeout(&mut self, timeout: Option<u64>) {
+ self.write_deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
+ }
}
////////////////////////////////////////////////////////////////////////////////
let mut err = unsafe { libc::GetLastError() };
if err == libc::ERROR_IO_PENDING as libc::DWORD {
- // If we've got a timeout, use WaitForSingleObject in tandem
- // with CancelIo to figure out if we should indeed get the
- // result.
- if self.deadline != 0 {
- let now = ::io::timer::now();
- let timeout = self.deadline < now || unsafe {
- let ms = (self.deadline - now) as libc::DWORD;
- let r = libc::WaitForSingleObject(overlapped.hEvent,
- ms);
- r != libc::WAIT_OBJECT_0
- };
- if timeout {
- unsafe { let _ = c::CancelIo(handle); }
- return Err(util::timeout("accept timed out"))
- }
- }
+ // Process a timeout if one is pending
+ let _ = await(handle, self.deadline, &mut overlapped);
// This will block until the overlapped I/O is completed. The
// timeout was previously handled, so this will either block in
// Transfer ownership of our handle into this stream
Ok(UnixStream {
- inner: UnsafeArc::new(Inner { handle: handle }),
+ inner: UnsafeArc::new(Inner::new(handle)),
read: None,
write: None,
+ read_deadline: 0,
+ write_deadline: 0,
})
}
}
/// os pipe instead. This process takes ownership of these file
/// descriptors, closing them upon destruction of the process.
pub fn spawn(config: p::ProcessConfig)
- -> Result<(Process, ~[Option<file::FileDesc>]), io::IoError>
+ -> Result<(Process, Vec<Option<file::FileDesc>>), io::IoError>
{
// right now we only handle stdin/stdout/stderr.
if config.extra_io.len() > 0 {
exit_code: None,
exit_signal: None,
},
- ret_io.move_iter().collect()))
+ ret_io))
}
Err(e) => Err(e)
}
use std::io::IoResult;
use std::io;
use std::mem;
+use std::os;
use std::ptr;
use super::c;
use super::net;
use super::{retry, last_error};
+#[deriving(Show)]
+pub enum SocketStatus {
+ Readable,
+ Writable,
+}
+
pub fn timeout(desc: &'static str) -> io::IoError {
io::IoError {
kind: io::TimedOut,
}
}
+#[cfg(unix)]
+pub fn wouldblock() -> bool {
+ let err = os::errno();
+ err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
+}
+
+#[cfg(windows)]
+pub fn wouldblock() -> bool {
+ let err = os::errno();
+ err == libc::WSAEWOULDBLOCK as uint
+}
+
+#[cfg(unix)]
+pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> {
+ let set = nb as libc::c_int;
+ super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
+}
+
+#[cfg(windows)]
+pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> {
+ let mut set = nb as libc::c_ulong;
+ if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
+ Err(last_error())
+ } else {
+ Ok(())
+ }
+}
+
// See http://developerweb.net/viewtopic.php?id=3196 for where this is
// derived from.
pub fn connect_timeout(fd: net::sock_t,
try!(set_nonblocking(fd, false));
return ret;
- #[cfg(unix)]
- fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> {
- let set = nb as libc::c_int;
- super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
- }
-
- #[cfg(windows)]
- fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> {
- let mut set = nb as libc::c_ulong;
- if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
- Err(last_error())
- } else {
- Ok(())
- }
- }
-
#[cfg(unix)]
fn await(fd: net::sock_t, set: &mut c::fd_set,
timeout: u64) -> libc::c_int {
}
}
-pub fn accept_deadline(fd: net::sock_t, deadline: u64) -> IoResult<()> {
+pub fn await(fd: net::sock_t, deadline: Option<u64>,
+ status: SocketStatus) -> IoResult<()> {
let mut set: c::fd_set = unsafe { mem::init() };
c::fd_set(&mut set, fd);
+ let (read, write) = match status {
+ Readable => (&set as *_, ptr::null()),
+ Writable => (ptr::null(), &set as *_),
+ };
+ let mut tv: libc::timeval = unsafe { mem::init() };
match retry(|| {
- // If we're past the deadline, then pass a 0 timeout to select() so
- // we can poll the status of the socket.
let now = ::io::timer::now();
- let ms = if deadline < now {0} else {deadline - now};
- let tv = ms_to_timeval(ms);
+ let tvp = match deadline {
+ None => ptr::null(),
+ Some(deadline) => {
+ // If we're past the deadline, then pass a 0 timeout to
+ // select() so we can poll the status
+ let ms = if deadline < now {0} else {deadline - now};
+ tv = ms_to_timeval(ms);
+ &tv as *_
+ }
+ };
let n = if cfg!(windows) {1} else {fd as libc::c_int + 1};
- unsafe { c::select(n, &set, ptr::null(), ptr::null(), &tv) }
+ let r = unsafe { c::select(n, read, write, ptr::null(), tvp) };
+ r
}) {
-1 => Err(last_error()),
- 0 => Err(timeout("accept timed out")),
- _ => return Ok(()),
+ 0 => Err(timeout("timed out")),
+ _ => Ok(()),
}
}
use std::cast;
use std::io::IoResult;
use std::kinds::marker;
-use std::local_data;
use std::strbuf::StrBuf;
pub use isaac::{IsaacRng, Isaac64Rng};
marker: marker::NoSend,
}
-// used to make space in TLS for a random number generator
-local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
-
/// Retrieve the lazily-initialized task-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `task_rng().gen::<int>()`.
/// the same sequence always. If absolute consistency is required,
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
pub fn task_rng() -> TaskRng {
- local_data::get_mut(TASK_RNG_KEY, |rng| match rng {
+ // used to make space in TLS for a random number generator
+ local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
+
+ match TASK_RNG_KEY.get() {
None => {
let r = match StdRng::new() {
Ok(r) => r,
TaskRngReseeder);
let ptr = &mut *rng as *mut TaskRngInner;
- local_data::set(TASK_RNG_KEY, rng);
+ TASK_RNG_KEY.replace(Some(rng));
TaskRng { rng: ptr, marker: marker::NoSend }
}
- Some(rng) => TaskRng { rng: &mut **rng, marker: marker::NoSend }
- })
+ Some(rng) => TaskRng {
+ rng: &**rng as *_ as *mut TaskRngInner,
+ marker: marker::NoSend
+ }
+ }
}
impl Rng for TaskRng {
// the crate id in the hash because lookups are only done by (name/vers),
// not by path.
let mut s = Sha256::new();
- s.input_str(crate_id.short_name_with_version());
+ s.input_str(crate_id.short_name_with_version().as_slice());
truncated_hash_result(&mut s).slice_to(8).to_owned()
}
// to be independent of one another in the crate.
symbol_hasher.reset();
- symbol_hasher.input_str(link_meta.crateid.name);
+ symbol_hasher.input_str(link_meta.crateid.name.as_slice());
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
symbol_hasher.input_str("-");
let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
let libs = libs.move_iter().filter_map(|(_, l)| {
l.map(|p| p.clone())
- }).collect::<~[_]>();
+ }).collect::<Vec<_>>();
- let rpaths = get_rpaths(os, sysroot, output, libs,
+ let rpaths = get_rpaths(os, sysroot, output, libs.as_slice(),
sess.opts.target_triple);
flags.push_all(rpaths_to_flags(rpaths.as_slice()).as_slice());
flags
fn parse_cfgspecs(cfgspecs: Vec<~str> )
-> ast::CrateConfig {
cfgspecs.move_iter().map(|s| {
- parse::parse_meta_from_source_str("cfgspec".to_str(),
- s,
+ parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
+ s.to_strbuf(),
Vec::new(),
&parse::new_parse_sess())
}).collect::<ast::CrateConfig>()
parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess)
}
StrInput(ref src) => {
- parse::parse_crate_from_source_str(anon_src(),
- (*src).clone(),
+ parse::parse_crate_from_source_str(anon_src().to_strbuf(),
+ src.to_strbuf(),
cfg.clone(),
&sess.parse_sess)
}
// write Makefile-compatible dependency rules
let files: Vec<~str> = sess.codemap().files.borrow()
.iter().filter(|fmap| fmap.is_real_file())
- .map(|fmap| fmap.name.clone())
+ .map(|fmap| fmap.name.to_owned())
.collect();
let mut file = try!(io::File::create(&deps_filename));
for path in out_filenames.iter() {
match node {
pprust::NodeItem(item) => {
try!(pp::space(&mut s.s));
- s.synth_comment(item.id.to_str())
+ s.synth_comment(item.id.to_str().to_strbuf())
}
pprust::NodeBlock(blk) => {
try!(pp::space(&mut s.s));
- s.synth_comment("block ".to_owned() + blk.id.to_str())
+ s.synth_comment((format!("block {}", blk.id)).to_strbuf())
}
pprust::NodeExpr(expr) => {
try!(pp::space(&mut s.s));
- try!(s.synth_comment(expr.id.to_str()));
+ try!(s.synth_comment(expr.id.to_str().to_strbuf()));
s.pclose()
}
pprust::NodePat(pat) => {
try!(pp::space(&mut s.s));
- s.synth_comment("pat ".to_owned() + pat.id.to_str())
+ s.synth_comment((format!("pat {}", pat.id)).to_strbuf())
}
}
}
pprust::print_crate(sess.codemap(),
sess.diagnostic(),
&krate,
- src_name,
+ src_name.to_strbuf(),
&mut rdr,
out,
&IdentifiedAnnotation,
pprust::print_crate(annotation.analysis.ty_cx.sess.codemap(),
annotation.analysis.ty_cx.sess.diagnostic(),
&krate,
- src_name,
+ src_name.to_strbuf(),
&mut rdr,
out,
&annotation,
pprust::print_crate(sess.codemap(),
sess.diagnostic(),
&krate,
- src_name,
+ src_name.to_strbuf(),
&mut rdr,
out,
&pprust::NoAnn,
)
// Seems out of place, but it uses session, so I'm putting it here
-pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> ~str) -> T {
+pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
+ -> T {
diagnostic::expect(sess.diagnostic(), opt, msg)
}
cx.ext_cx.bt_push(ExpnInfo {
call_site: DUMMY_SP,
callee: NameAndSpan {
- name: "test".to_owned(),
+ name: "test".to_strbuf(),
format: MacroAttribute,
span: None
}
#![!resolve_unexported]
extern crate test (name = "test", vers = "...");
fn main() {
- test::test_main_static(::os::args(), tests)
+ test::test_main_static(::os::args().as_slice(), tests)
}
static tests : &'static [test::TestDescAndFn] = &[
let mainfn = (quote_item!(&cx.ext_cx,
pub fn main() {
#![main]
- #![allow(deprecated_owned_vector)]
- test::test_main_static(::std::os::args(), TESTS);
+ use std::slice::Vector;
+ test::test_main_static(::std::os::args().as_slice(), TESTS);
}
)).unwrap();
fn is_test_crate(krate: &ast::Crate) -> bool {
match attr::find_crateid(krate.attrs.as_slice()) {
- Some(ref s) if "test" == s.name => true,
+ Some(ref s) if "test" == s.name.as_slice() => true,
_ => false
}
}
let name_lit: ast::Lit =
nospan(ast::LitStr(token::intern_and_get_ident(
- ast_util::path_name_i(path.as_slice())),
+ ast_util::path_name_i(path.as_slice()).as_slice()),
ast::CookedStr));
let name_expr = @ast::Expr {
&sess.parse_sess)
}
d::StrInput(ref src) => {
- parse::parse_crate_attrs_from_source_str(d::anon_src(),
- (*src).clone(),
- Vec::new(),
- &sess.parse_sess)
+ parse::parse_crate_attrs_from_source_str(
+ d::anon_src().to_strbuf(),
+ src.to_strbuf(),
+ Vec::new(),
+ &sess.parse_sess)
}
};
result.move_iter().collect()
}
pub fn main() {
- std::os::set_exit_status(main_args(std::os::args()));
+ std::os::set_exit_status(main_args(std::os::args().as_slice()));
}
pub fn main_args(args: &[~str]) -> int {
};
let macros = decoder::get_exported_macros(library.metadata.as_slice());
let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
- decoder::get_symbol(library.metadata.as_slice(), id)
+ decoder::get_symbol(library.metadata.as_slice(), id).to_strbuf()
});
let mc = MacroCrate {
lib: library.dylib.clone(),
- macros: macros.move_iter().collect(),
+ macros: macros.move_iter().map(|x| x.to_strbuf()).collect(),
registrar_symbol: registrar,
};
if should_link {
let all_items = reader::get_doc(reader::Doc(cdata.data()), tag_items);
let class_doc = expect(tcx.sess.diagnostic(),
decoder::maybe_find_item(class_id.node, all_items),
- || format!("get_field_type: class ID {:?} not found",
- class_id) );
+ || {
+ (format!("get_field_type: class ID {:?} not found",
+ class_id)).to_strbuf()
+ });
let the_field = expect(tcx.sess.diagnostic(),
decoder::maybe_find_item(def.node, class_doc),
- || format!("get_field_type: in class {:?}, field ID {:?} not found",
- class_id, def) );
+ || {
+ (format!("get_field_type: in class {:?}, field ID {:?} not found",
+ class_id,
+ def)).to_strbuf()
+ });
let ty = decoder::item_type(def, the_field, tcx, &*cdata);
ty::ty_param_bounds_and_ty {
generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
UnsafeFn, // u
StaticMethod, // F
UnsafeStaticMethod, // U
- ForeignFn, // e
Type, // y
ForeignType, // T
Mod, // m
'u' => UnsafeFn,
'F' => StaticMethod,
'U' => UnsafeStaticMethod,
- 'e' => ForeignFn,
'y' => Type,
'T' => ForeignType,
'm' => Mod,
Struct => DlDef(ast::DefStruct(did)),
UnsafeFn => DlDef(ast::DefFn(did, ast::UnsafeFn)),
Fn => DlDef(ast::DefFn(did, ast::NormalFn)),
- ForeignFn => DlDef(ast::DefFn(did, ast::ExternFn)),
StaticMethod | UnsafeStaticMethod => {
let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
{ ast::NormalFn };
match s {
UnsafeFn => 'u',
NormalFn => 'f',
- ExternFn => 'e'
}
}
match s {
UnsafeFn => 'U',
NormalFn => 'F',
- _ => fail!("extern fn can't be static")
}
}
let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
.expect("Unable to find source for macro");
self.ebml_w.start_tag(tag_macro_def);
- self.ebml_w.wr_str(def);
+ self.ebml_w.wr_str(def.as_slice());
self.ebml_w.end_tag();
}
_ => {}
match c {
'u' => UnsafeFn,
'n' => NormalFn,
- 'c' => ExternFn,
_ => fail!("parse_fn_style: bad fn_style {}", c)
}
}
match p {
NormalFn => mywrite!(w, "n"),
UnsafeFn => mywrite!(w, "u"),
- ExternFn => mywrite!(w, "c")
}
}
"".to_owned()
};
- try!(ps.synth_comment(format!("id {}: {}{}{}", id, entry_str,
- gens_str, kills_str)));
+ try!(ps.synth_comment((format!("id {}: {}{}{}", id, entry_str,
+ gens_str, kills_str)).to_strbuf()));
try!(pp::space(&mut ps.s));
}
Ok(())
fn check_pat(cx: &mut Context, pat: &Pat) {
let var_name = match pat.node {
PatWild => Some("_".to_owned()),
- PatIdent(_, ref path, _) => Some(path_to_str(path)),
+ PatIdent(_, ref path, _) => Some(path_to_str(path).to_owned()),
_ => None
};
impl<'a> PrivacyVisitor<'a> {
// used when debugging
fn nodestr(&self, id: ast::NodeId) -> ~str {
- self.tcx.map.node_to_str(id)
+ self.tcx.map.node_to_str(id).to_owned()
}
// Determines whether the given definition is public from the point of view
use util::nodemap::NodeSet;
use collections::HashSet;
+use syntax::abi;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{def_id_of_def, is_local};
match *node {
ast_map::NodeItem(item) => {
match item.node {
- ast::ItemFn(_, ast::ExternFn, _, _, _) => {
- self.reachable_symbols.insert(search_item);
+ ast::ItemFn(_, _, abi, _, _) => {
+ if abi != abi::Rust {
+ self.reachable_symbols.insert(search_item);
+ }
}
_ => {}
}
match def {
DefMod(_) | DefForeignMod(_) => {}
- DefVariant(_, variant_id, is_struct) => {
+ DefVariant(enum_did, variant_id, is_struct) => {
debug!("(building reduced graph for external crate) building \
variant {}",
final_ident);
- // We assume the parent is visible, or else we wouldn't have seen
- // it. Also variants are public-by-default if the parent was also
- // public.
+ // If this variant is public, then it was publicly reexported,
+ // otherwise we need to inherit the visibility of the enum
+ // definition.
+ let is_exported = is_public ||
+ self.external_exports.contains(&enum_did);
if is_struct {
- child_name_bindings.define_type(def, DUMMY_SP, true);
+ child_name_bindings.define_type(def, DUMMY_SP, is_exported);
self.structs.insert(variant_id);
} else {
- child_name_bindings.define_value(def, DUMMY_SP, true);
+ child_name_bindings.define_value(def, DUMMY_SP, is_exported);
}
}
DefFn(..) | DefStaticMethod(..) | DefStatic(..) => {
.codemap()
.span_to_snippet(imports.get(index).span)
.unwrap();
- if sn.contains("::") {
+ if sn.as_slice().contains("::") {
self.resolve_error(imports.get(index).span,
"unresolved import");
} else {
let err = format!("unresolved import (maybe you meant `{}::*`?)",
- sn.slice(0, sn.len()));
+ sn.as_slice().slice(0, sn.len()));
self.resolve_error(imports.get(index).span, err);
}
}
use libc::c_uint;
use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
-use std::local_data;
use std::rc::Rc;
use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
use syntax::ast_util::{local_def, is_local};
use time;
-local_data_key!(task_local_insn_key: Vec<&'static str> )
+local_data_key!(task_local_insn_key: RefCell<Vec<&'static str>>)
pub fn with_insn_ctxt(blk: |&[&'static str]|) {
- local_data::get(task_local_insn_key, |c| {
- match c {
- Some(ctx) => blk(ctx.as_slice()),
- None => ()
- }
- })
+ match task_local_insn_key.get() {
+ Some(ctx) => blk(ctx.borrow().as_slice()),
+ None => ()
+ }
}
pub fn init_insn_ctxt() {
- local_data::set(task_local_insn_key, Vec::new());
+ task_local_insn_key.replace(Some(RefCell::new(Vec::new())));
}
pub struct _InsnCtxt { _x: () }
#[unsafe_destructor]
impl Drop for _InsnCtxt {
fn drop(&mut self) {
- local_data::modify(task_local_insn_key, |c| {
- c.map(|mut ctx| {
- ctx.pop();
- ctx
- })
- })
+ match task_local_insn_key.get() {
+ Some(ctx) => { ctx.borrow_mut().pop(); }
+ None => {}
+ }
}
}
pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
debug!("new InsnCtxt: {}", s);
- local_data::modify(task_local_insn_key, |c| {
- c.map(|mut ctx| {
- ctx.push(s);
- ctx
- })
- });
+ match task_local_insn_key.get() {
+ Some(ctx) => ctx.borrow_mut().push(s),
+ None => {}
+ }
_InsnCtxt { _x: () }
}
let f = decl_rust_fn(ccx, false, inputs, output, name);
csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| {
- set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).collect::<~[_]>(), f)
+ set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x))
+ .collect::<Vec<_>>().as_slice(), f)
});
ccx.externs.borrow_mut().insert(name.to_owned(), f);
for p in param_substs.iter() { p.validate(); }
debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
- if id == -1 { "".to_owned() } else { ccx.tcx.map.path_to_str(id) },
+ if id == -1 {
+ "".to_owned()
+ } else {
+ ccx.tcx.map.path_to_str(id).to_owned()
+ },
id, param_substs.map(|s| s.repr(ccx.tcx())));
let substd_output_type = match param_substs {
param_substs: Option<¶m_substs>,
id: ast::NodeId,
attrs: &[ast::Attribute]) {
- let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id));
+ let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id).to_owned());
debug!("trans_fn(param_substs={})", param_substs.map(|s| s.repr(ccx.tcx())));
let _icx = push_ctxt("trans_fn");
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
let _icx = push_ctxt("trans_item");
match item.node {
- ast::ItemFn(decl, fn_style, _abi, ref generics, body) => {
- if fn_style == ast::ExternFn {
+ ast::ItemFn(decl, _fn_style, abi, ref generics, body) => {
+ if abi != Rust {
let llfndecl = get_item_val(ccx, item.id);
foreign::trans_rust_fn_with_foreign_abi(
ccx, decl, body, item.attrs.as_slice(), llfndecl, item.id);
}
}
- ast::ItemFn(_, fn_style, _, _, _) => {
- let llfn = if fn_style != ast::ExternFn {
+ ast::ItemFn(_, _, abi, _, _) => {
+ let llfn = if abi == Rust {
register_fn(ccx, i.span, sym, i.id, ty)
} else {
foreign::register_rust_fn_with_foreign_abi(ccx,
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
let metadata = encoder::encode_metadata(encode_parms, krate);
- let compressed = encoder::metadata_encoding_version +
- match flate::deflate_bytes(metadata.as_slice()) {
- Some(compressed) => compressed,
- None => cx.sess().fatal(format!("failed to compress metadata", ))
- }.as_slice();
- let llmeta = C_bytes(cx, compressed);
+ let compressed = Vec::from_slice(encoder::metadata_encoding_version)
+ .append(match flate::deflate_bytes(metadata.as_slice()) {
+ Some(compressed) => compressed,
+ None => cx.sess().fatal(format!("failed to compress metadata"))
+ }.as_slice());
+ let llmeta = C_bytes(cx, compressed.as_slice());
let llconst = C_struct(cx, [llmeta], false);
let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,
cx.link_meta.crateid.version_or_default(), cx.link_meta.crate_hash);
// crashes if the module identifer is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
- let llmod_id = link_meta.crateid.name + ".rs";
+ let mut llmod_id = link_meta.crateid.name.clone();
+ llmod_id.push_str(".rs");
- let ccx = CrateContext::new(llmod_id, tcx, exp_map2,
+ let ccx = CrateContext::new(llmod_id.as_slice(), tcx, exp_map2,
Sha256::new(), link_meta, reachable);
{
let _icx = push_ctxt("text");
let map_node = session::expect(
ccx.sess(),
tcx.map.find(def_id.node),
- || format!("local item should be in ast map"));
+ || "local item should be in ast map".to_strbuf());
match map_node {
ast_map::NodeForeignItem(_) => {
}
pub fn node_id_to_str(&self, id: ast::NodeId) -> ~str {
- self.tcx().map.node_to_str(id)
+ self.tcx().map.node_to_str(id).to_owned()
}
pub fn expr_to_str(&self, e: &ast::Expr) -> ~str {
-> (ValueRef, ValueRef) {
let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
let filename_cstr = C_cstr(bcx.ccx(),
- token::intern_and_get_ident(loc.file.name), true);
+ token::intern_and_get_ident(loc.file
+ .name
+ .as_slice()),
+ true);
let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx()));
let line = C_int(bcx.ccx(), loc.line as int);
(filename, line)
use util::ppaux::{Repr, ty_to_str};
use std::c_str::ToCStr;
-use std::slice;
+use std::vec;
use std::vec::Vec;
use libc::c_uint;
use syntax::{ast, ast_util};
let vec_ty = ty::expr_ty(cx.tcx(), e);
let unit_ty = ty::sequence_element_type(cx.tcx(), vec_ty);
let llunitty = type_of::type_of(cx, unit_ty);
- let (vs, inlineable) = slice::unzip(es.iter().map(|e| const_expr(cx, *e, is_local)));
+ let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e, is_local)));
// If the vector contains enums, an LLVM array won't work.
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
- C_struct(cx, vs, false)
+ C_struct(cx, vs.as_slice(), false)
} else {
- C_array(llunitty, vs)
+ C_array(llunitty, vs.as_slice())
};
(v, llunitty, inlineable.iter().fold(true, |a, &b| a && b))
}
};
expr::with_field_tys(tcx, ety, Some(e.id), |discr, field_tys| {
- let (cs, inlineable) = slice::unzip(field_tys.iter().enumerate()
+ let (cs, inlineable) = vec::unzip(field_tys.iter().enumerate()
.map(|(ix, &field_ty)| {
match fs.iter().find(|f| field_ty.ident.name == f.ident.node.name) {
Some(f) => const_expr(cx, (*f).expr, is_local),
}
}
}));
- (adt::trans_const(cx, &*repr, discr, cs),
+ (adt::trans_const(cx, &*repr, discr, cs.as_slice()),
inlineable.iter().fold(true, |a, &b| a && b))
})
}
let v_fail_str = C_cstr(ccx, fail_str, true);
let _icx = push_ctxt("trans_fail_value");
let loc = bcx.sess().codemap().lookup_char_pos(sp.lo);
- let v_filename = C_cstr(ccx, token::intern_and_get_ident(loc.file.name), true);
+ let v_filename = C_cstr(ccx,
+ token::intern_and_get_ident(loc.file
+ .name
+ .as_slice()),
+ true);
let v_line = loc.line as int;
let v_str = PointerCast(bcx, v_fail_str, Type::i8p(ccx));
let v_filename = PointerCast(bcx, v_filename, Type::i8p(ccx));
};
let filename = span_start(cx, span).file.name.clone();
- let file_metadata = file_metadata(cx, filename);
+ let file_metadata = file_metadata(cx, filename.as_slice());
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
let loc = span_start(cx, span);
}
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
let function_type_metadata = unsafe {
let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
});
fn fallback_path(cx: &CrateContext) -> CString {
- cx.link_meta.crateid.name.to_c_str()
+ cx.link_meta.crateid.name.as_slice().to_c_str()
}
}
let cx: &CrateContext = bcx.ccx();
let filename = span_start(cx, span).file.name.clone();
- let file_metadata = file_metadata(cx, filename);
+ let file_metadata = file_metadata(cx, filename.as_slice());
let name = token::get_ident(variable_ident);
let loc = span_start(cx, span);
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
let file_name = span_start(cx, definition_span).file.name.clone();
- let file_metadata = file_metadata(cx, file_name);
+ let file_metadata = file_metadata(cx, file_name.as_slice());
let struct_metadata_stub = create_struct_stub(cx,
struct_llvm_type,
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
UnfinishedMetadata {
cache_id: cache_id_for_type(tuple_type),
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
let loc = span_start(cx, definition_span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
// For empty enums there is an early exit. Just describe it as an empty struct with the
// appropriate type name
];
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
return composite_type_metadata(
cx,
assert!(member_descriptions.len() == member_llvm_types.len());
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
composite_type_metadata(
cx,
assert!(member_descriptions.len() == member_llvm_types.len());
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
return composite_type_metadata(
cx,
span: Span)
-> DICompositeType {
let loc = span_start(cx, span);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
let mut signature_metadata: Vec<DIType> =
Vec::with_capacity(signature.inputs.len() + 1);
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
let file_name = span_start(cx, definition_span).file.name.clone();
- let file_metadata = file_metadata(cx, file_name);
+ let file_metadata = file_metadata(cx, file_name.as_slice());
let trait_llvm_type = type_of::type_of(cx, trait_type);
&mut HashMap<ast::NodeId, DIScope>|) {
// Create a new lexical scope and push it onto the stack
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx, loc.file.name.as_slice());
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
if need_new_scope {
// Create a new lexical scope and push it onto the stack
let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
- let file_metadata = file_metadata(cx, loc.file.name);
+ let file_metadata = file_metadata(cx,
+ loc.file
+ .name
+ .as_slice());
let parent_scope = scope_stack.last().unwrap().scope_metadata;
let scope_metadata = unsafe {
ty::with_path(cx.tcx(), def_id, |path| {
// prepend crate name if not already present
let krate = if def_id.krate == ast::LOCAL_CRATE {
- let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
+ let crate_namespace_ident = token::str_to_ident(cx.link_meta
+ .crateid
+ .name
+ .as_slice());
Some(ast_map::PathMod(crate_namespace_ident.name))
} else {
None
let map_node = session::expect(
ccx.sess(),
ccx.tcx.map.find(fn_id.node),
- || format!("while monomorphizing {:?}, couldn't find it in the \
- item map (may have attempted to monomorphize an item \
- defined in a different crate?)", fn_id));
+ || {
+ (format!("while monomorphizing {:?}, couldn't find it in the \
+ item map (may have attempted to monomorphize an item \
+ defined in a different crate?)", fn_id)).to_strbuf()
+ });
match map_node {
ast_map::NodeForeignItem(_) => {
// This is a bit unfortunate.
let idx = real_substs.tps.len() - num_method_ty_params;
- let substs = real_substs.tps.slice(0, idx) +
- &[real_substs.self_ty.unwrap()] + real_substs.tps.tailn(idx);
+ let substs = Vec::from_slice(real_substs.tps.slice(0, idx))
+ .append([real_substs.self_ty.unwrap()])
+ .append(real_substs.tps.tailn(idx));
debug!("static default: changed substitution to {}",
substs.repr(ccx.tcx()));
- ty::subst_tps(ccx.tcx(), substs, None, llitem_ty)
+ ty::subst_tps(ccx.tcx(), substs.as_slice(), None, llitem_ty)
}
};
match fn_style {
ast::UnsafeFn => 1u,
ast::NormalFn => 2u,
- ast::ExternFn => 3u
}
}
}
pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> ~str {
- with_path(cx, id, |path| ast_map::path_to_str(path))
+ with_path(cx, id, |path| ast_map::path_to_str(path)).to_owned()
}
pub enum DtorKind {
fn fold_trait_store(&mut self, s: ty::TraitStore) -> ty::TraitStore {
super_fold_trait_store(self, s)
}
+
+ fn fold_autoref(&mut self, ar: &ty::AutoRef) -> ty::AutoRef {
+ super_fold_autoref(self, ar)
+ }
}
pub fn fold_opt_ty<T:TypeFolder>(this: &mut T,
}
}
+pub fn super_fold_autoref<T:TypeFolder>(this: &mut T,
+ autoref: &ty::AutoRef)
+ -> ty::AutoRef
+{
+ match *autoref {
+ ty::AutoPtr(r, m) => ty::AutoPtr(this.fold_region(r), m),
+ ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(this.fold_region(r), m),
+ ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(this.fold_region(r), m),
+ ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
+ ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(this.fold_region(r), m),
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// Some sample folders
#[deriving(Clone)]
pub struct FnCtxt<'a> {
+ // This flag is set to true if, during the writeback phase, we encounter
+ // a type error in this function.
+ writeback_errors: Cell<bool>,
+
// Number of errors that had been reported when we started
// checking this function. On exit, if we find that *more* errors
// have been reported, we will skip regionck and other work that
region_bnd: ast::NodeId)
-> FnCtxt<'a> {
FnCtxt {
+ writeback_errors: Cell::new(false),
err_count_on_creation: ccx.tcx.sess.err_count(),
ret_ty: rty,
ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
// Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context.
let fcx = FnCtxt {
+ writeback_errors: Cell::new(false),
err_count_on_creation: err_count_on_creation,
ret_ty: ret_ty,
ps: RefCell::new(FnStyleState::function(fn_style, id)),
pub fn opt_node_ty_substs(&self,
id: ast::NodeId,
- f: |&ty::substs| -> bool)
- -> bool {
+ f: |&ty::substs|) {
match self.inh.node_type_substs.borrow().find(&id) {
- Some(s) => f(s),
- None => true
+ Some(s) => { f(s) }
+ None => { }
}
}
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
}
}
- true
});
}
use middle::pat_util;
use middle::ty;
+use middle::ty_fold::TypeFolder;
use middle::typeck::astconv::AstConv;
use middle::typeck::check::FnCtxt;
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::resolve_type;
use middle::typeck::infer;
use middle::typeck::{MethodCall, MethodCallee};
-use middle::typeck::{vtable_res, vtable_static, vtable_param};
+use middle::typeck::{vtable_origin, vtable_static, vtable_param};
use middle::typeck::write_substs_to_tcx;
use middle::typeck::write_ty_to_tcx;
-use util::ppaux;
use util::ppaux::Repr;
use syntax::ast;
use syntax::visit;
use syntax::visit::Visitor;
-fn resolve_type_vars_in_type(fcx: &FnCtxt, sp: Span, typ: ty::t)
- -> Option<ty::t> {
- if !ty::type_needs_infer(typ) { return Some(typ); }
- match resolve_type(fcx.infcx(), typ, resolve_all | force_all) {
- Ok(new_type) => return Some(new_type),
- Err(e) => {
- if !fcx.ccx.tcx.sess.has_errors() {
- fcx.ccx.tcx.sess.span_err(
- sp,
- format!("cannot determine a type \
- for this expression: {}",
- infer::fixup_err_to_str(e)))
- }
- return None;
+///////////////////////////////////////////////////////////////////////////
+// Entry point functions
+
+pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
+ assert_eq!(fcx.writeback_errors.get(), false);
+ let mut wbcx = WritebackCx::new(fcx);
+ wbcx.visit_expr(e, ());
+ wbcx.visit_upvar_borrow_map();
+}
+
+pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
+ decl: &ast::FnDecl,
+ blk: &ast::Block) {
+ assert_eq!(fcx.writeback_errors.get(), false);
+ let mut wbcx = WritebackCx::new(fcx);
+ wbcx.visit_block(blk, ());
+ for arg in decl.inputs.iter() {
+ wbcx.visit_pat(arg.pat, ());
+
+ // Privacy needs the type for the whole pattern, not just each binding
+ if !pat_util::pat_is_binding(&fcx.tcx().def_map, arg.pat) {
+ wbcx.visit_node_id(ResolvingPattern(arg.pat.span),
+ arg.pat.id);
}
}
+ wbcx.visit_upvar_borrow_map();
}
-fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall) {
- let fcx = wbcx.fcx;
- let tcx = fcx.ccx.tcx;
-
- // Resolve any method map entry
- match fcx.inh.method_map.borrow_mut().pop(&method_call) {
- Some(method) => {
- debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
- method_call, method.repr(tcx));
- let new_method = MethodCallee {
- origin: method.origin,
- ty: match resolve_type_vars_in_type(fcx, sp, method.ty) {
- Some(t) => t,
- None => {
- wbcx.success = false;
- return;
- }
- },
- substs: ty::substs {
- tps: method.substs.tps.move_iter().map(|subst| {
- match resolve_type_vars_in_type(fcx, sp, subst) {
- Some(t) => t,
- None => { wbcx.success = false; ty::mk_err() }
- }
- }).collect(),
- regions: ty::ErasedRegions,
- self_ty: None
- }
- };
- tcx.method_map.borrow_mut().insert(method_call, new_method);
- }
- None => {}
+///////////////////////////////////////////////////////////////////////////
+// The Writerback context. This visitor walks the AST, checking the
+// fn-specific tables to find references to types or regions. It
+// resolves those regions to remove inference variables and writes the
+// final result back into the master tables in the tcx. Here and
+// there, it applies a few ad-hoc checks that were not convenient to
+// do elsewhere.
+
+struct WritebackCx<'cx> {
+ fcx: &'cx FnCtxt<'cx>,
+}
+
+impl<'cx> WritebackCx<'cx> {
+ fn new(fcx: &'cx FnCtxt) -> WritebackCx<'cx> {
+ WritebackCx { fcx: fcx }
+ }
+
+ fn tcx(&self) -> &'cx ty::ctxt {
+ self.fcx.tcx()
}
}
-fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
- // Resolve any vtable map entry
- match fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
- Some(origins) => {
- let r_origins = resolve_origins(fcx, sp, origins);
- debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
- vtable_key, r_origins.repr(fcx.tcx()));
- fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
+///////////////////////////////////////////////////////////////////////////
+// Impl of Visitor for Resolver
+//
+// This is the master code which walks the AST. It delegates most of
+// the heavy lifting to the generic visit and resolve functions
+// below. In general, a function is made into a `visitor` if it must
+// traffic in node-ids or update tables in the type context etc.
+
+impl<'cx> Visitor<()> for WritebackCx<'cx> {
+ fn visit_item(&mut self, _: &ast::Item, _: ()) {
+ // Ignore items
+ }
+
+ fn visit_stmt(&mut self, s: &ast::Stmt, _: ()) {
+ if self.fcx.writeback_errors.get() {
+ return;
}
- None => {}
+
+ self.visit_node_id(ResolvingExpr(s.span), ty::stmt_node_id(s));
+ visit::walk_stmt(self, s, ());
}
- fn resolve_origins(fcx: &FnCtxt, sp: Span,
- vtbls: vtable_res) -> vtable_res {
- vtbls.move_iter().map(|os| os.move_iter().map(|origin| {
- match origin {
- vtable_static(def_id, tys, origins) => {
- let r_tys = tys.move_iter().map(|t| {
- match resolve_type_vars_in_type(fcx, sp, t) {
- Some(t1) => t1,
- None => ty::mk_err()
- }
- }).collect();
- let r_origins = resolve_origins(fcx, sp, origins);
- vtable_static(def_id, r_tys, r_origins)
+ fn visit_expr(&mut self, e:&ast::Expr, _: ()) {
+ if self.fcx.writeback_errors.get() {
+ return;
+ }
+
+ self.visit_node_id(ResolvingExpr(e.span), e.id);
+ self.visit_method_map_entry(ResolvingExpr(e.span),
+ MethodCall::expr(e.id));
+ self.visit_vtable_map_entry(ResolvingExpr(e.span),
+ MethodCall::expr(e.id));
+
+ match e.node {
+ ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
+ for input in decl.inputs.iter() {
+ let _ = self.visit_node_id(ResolvingExpr(e.span),
+ input.id);
}
- vtable_param(n, b) => vtable_param(n, b)
}
- }).collect()).collect()
+ _ => {}
+ }
+
+ visit::walk_expr(self, e, ());
}
-}
-fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
- let fcx = wbcx.fcx;
- let tcx = fcx.ccx.tcx;
-
- // Resolve any borrowings for the node with id `id`
- let resolved_adj = match fcx.inh.adjustments.borrow_mut().pop(&id) {
- None => None,
-
- Some(adjustment) => {
- Some(match adjustment {
- ty::AutoAddEnv(store) => {
- let r = match store {
- ty::RegionTraitStore(r, _) => r,
- ty::UniqTraitStore => ty::ReStatic
- };
- match resolve_region(fcx.infcx(),
- r,
- resolve_all | force_all) {
- Err(e) => {
- // This should not, I think, happen:
- tcx.sess.span_err(
- sp,
- format!("cannot resolve bound for closure: \
- {}",
- infer::fixup_err_to_str(e)));
- wbcx.success = false;
- return;
- }
- Ok(r1) => {
- // FIXME(eddyb) #2190 Allow only statically resolved
- // bare functions to coerce to a closure to avoid
- // constructing (slower) indirect call wrappers.
- match tcx.def_map.borrow().find(&id) {
- Some(&ast::DefFn(..)) |
- Some(&ast::DefStaticMethod(..)) |
- Some(&ast::DefVariant(..)) |
- Some(&ast::DefStruct(_)) => {}
- _ => tcx.sess.span_err(sp,
- "cannot coerce non-statically resolved bare fn")
- }
+ fn visit_block(&mut self, b: &ast::Block, _: ()) {
+ if self.fcx.writeback_errors.get() {
+ return;
+ }
- ty::AutoAddEnv(match store {
- ty::RegionTraitStore(..) => {
- ty::RegionTraitStore(r1, ast::MutMutable)
- }
- ty::UniqTraitStore => ty::UniqTraitStore
- })
- }
- }
- }
+ self.visit_node_id(ResolvingExpr(b.span), b.id);
+ visit::walk_block(self, b, ());
+ }
- ty::AutoDerefRef(adj) => {
- for autoderef in range(0, adj.autoderefs) {
- let method_call = MethodCall::autoderef(id, autoderef as u32);
- resolve_method_map_entry(wbcx, sp, method_call);
- resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
- }
+ fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
+ if self.fcx.writeback_errors.get() {
+ return;
+ }
- ty::AutoDerefRef(ty::AutoDerefRef {
- autoderefs: adj.autoderefs,
- autoref: adj.autoref.map(|r| r.map_region(|r| {
- match resolve_region(fcx.infcx(), r,
- resolve_all | force_all) {
- Ok(r1) => r1,
- Err(e) => {
- // This should not, I think, happen.
- tcx.sess.span_err(
- sp,
- format!("cannot resolve scope of borrow: \
- {}",
- infer::fixup_err_to_str(e)));
- r
- }
- }
- })),
- })
- }
+ self.visit_node_id(ResolvingPattern(p.span), p.id);
+
+ debug!("Type for pattern binding {} (id {}) resolved to {}",
+ pat_to_str(p),
+ p.id,
+ ty::node_id_to_type(self.tcx(), p.id).repr(self.tcx()));
+
+ visit::walk_pat(self, p, ());
+ }
- adjustment => adjustment
- })
+ fn visit_local(&mut self, l: &ast::Local, _: ()) {
+ if self.fcx.writeback_errors.get() {
+ return;
}
- };
- debug!("Adjustments for node {}: {:?}",
- id, resolved_adj);
- match resolved_adj {
- Some(adj) => {
- tcx.adjustments.borrow_mut().insert(id, adj);
+ let var_ty = self.fcx.local_ty(l.span, l.id);
+ let var_ty = var_ty.resolve(self.fcx, ResolvingLocal(l.span));
+ write_ty_to_tcx(self.tcx(), l.id, var_ty);
+ visit::walk_local(self, l, ());
+ }
+
+ fn visit_ty(&mut self, _t: &ast::Ty, _: ()) {
+ // ignore
+ }
+}
+
+impl<'cx> WritebackCx<'cx> {
+ fn visit_upvar_borrow_map(&self) {
+ if self.fcx.writeback_errors.get() {
+ return;
+ }
+
+ for (upvar_id, upvar_borrow) in self.fcx.inh.upvar_borrow_map.borrow().iter() {
+ let r = upvar_borrow.region;
+ let r = r.resolve(self.fcx, ResolvingUpvar(*upvar_id));
+ let new_upvar_borrow = ty::UpvarBorrow { kind: upvar_borrow.kind,
+ region: r };
+ debug!("Upvar borrow for {} resolved to {}",
+ upvar_id.repr(self.tcx()),
+ new_upvar_borrow.repr(self.tcx()));
+ self.fcx.tcx().upvar_borrow_map.borrow_mut().insert(
+ *upvar_id, new_upvar_borrow);
}
- None => {}
}
- // Resolve the type of the node with id `id`
- let n_ty = fcx.node_ty(id);
- match resolve_type_vars_in_type(fcx, sp, n_ty) {
- None => {
- wbcx.success = false;
- }
-
- Some(t) => {
- debug!("resolve_type_vars_for_node(id={}, n_ty={}, t={})",
- id, ppaux::ty_to_str(tcx, n_ty), ppaux::ty_to_str(tcx, t));
- write_ty_to_tcx(tcx, id, t);
- fcx.opt_node_ty_substs(id, |substs| {
- let mut new_tps = Vec::new();
- for subst in substs.tps.iter() {
- match resolve_type_vars_in_type(fcx, sp, *subst) {
- Some(t) => new_tps.push(t),
- None => { wbcx.success = false; break }
- }
- }
- write_substs_to_tcx(tcx, id, new_tps);
- wbcx.success
+ fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
+ // Resolve any borrowings for the node with id `id`
+ self.visit_adjustments(reason, id);
+
+ // Resolve the type of the node with id `id`
+ let n_ty = self.fcx.node_ty(id);
+ let n_ty = n_ty.resolve(self.fcx, reason);
+ write_ty_to_tcx(self.tcx(), id, n_ty);
+ debug!("Node {} has type {}", id, n_ty.repr(self.tcx()));
+
+ // Resolve any substitutions
+ self.fcx.opt_node_ty_substs(id, |node_substs| {
+ let mut new_tps = Vec::new();
+ for subst in node_substs.tps.iter() {
+ new_tps.push(subst.resolve(self.fcx, reason));
+ }
+ write_substs_to_tcx(self.tcx(), id, new_tps);
});
- }
}
-}
-struct WbCtxt<'a> {
- fcx: &'a FnCtxt<'a>,
+ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
+ match self.fcx.inh.adjustments.borrow_mut().pop(&id) {
+ None => {
+ debug!("No adjustments for node {}", id);
+ }
- // As soon as we hit an error we have to stop resolving
- // the entire function.
- success: bool,
-}
+ Some(adjustment) => {
+ let resolved_adjustment = match adjustment {
+ ty::AutoAddEnv(store) => {
+ // FIXME(eddyb) #2190 Allow only statically resolved
+ // bare functions to coerce to a closure to avoid
+ // constructing (slower) indirect call wrappers.
+ match self.tcx().def_map.borrow().find(&id) {
+ Some(&ast::DefFn(..)) |
+ Some(&ast::DefStaticMethod(..)) |
+ Some(&ast::DefVariant(..)) |
+ Some(&ast::DefStruct(_)) => {
+ }
+ _ => {
+ self.tcx().sess.span_err(
+ reason.span(self.fcx),
+ "cannot coerce non-statically resolved bare fn")
+ }
+ }
-fn visit_stmt(s: &ast::Stmt, wbcx: &mut WbCtxt) {
- if !wbcx.success { return; }
- resolve_type_vars_for_node(wbcx, s.span, ty::stmt_node_id(s));
- visit::walk_stmt(wbcx, s, ());
-}
+ ty::AutoAddEnv(store.resolve(self.fcx, reason))
+ }
+
+ ty::AutoDerefRef(adj) => {
+ for autoderef in range(0, adj.autoderefs) {
+ let method_call = MethodCall::autoderef(id, autoderef as u32);
+ self.visit_method_map_entry(reason, method_call);
+ self.visit_vtable_map_entry(reason, method_call);
+ }
-fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
- if !wbcx.success {
- return;
+ ty::AutoDerefRef(ty::AutoDerefRef {
+ autoderefs: adj.autoderefs,
+ autoref: adj.autoref.resolve(self.fcx, reason),
+ })
+ }
+
+ adjustment => adjustment
+ };
+ debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
+ self.tcx().adjustments.borrow_mut().insert(
+ id, resolved_adjustment);
+ }
+ }
}
- resolve_type_vars_for_node(wbcx, e.span, e.id);
- resolve_method_map_entry(wbcx, e.span, MethodCall::expr(e.id));
- resolve_vtable_map_entry(wbcx.fcx, e.span, MethodCall::expr(e.id));
+ fn visit_method_map_entry(&self,
+ reason: ResolveReason,
+ method_call: MethodCall) {
+ // Resolve any method map entry
+ match self.fcx.inh.method_map.borrow_mut().pop(&method_call) {
+ Some(method) => {
+ debug!("writeback::resolve_method_map_entry(call={:?}, entry={})",
+ method_call,
+ method.repr(self.tcx()));
+ let mut new_method = MethodCallee {
+ origin: method.origin,
+ ty: method.ty.resolve(self.fcx, reason),
+ substs: method.substs.resolve(self.fcx, reason),
+ };
+
+ // Wack. For some reason I don't quite know, we always
+ // hard-code the self-ty and regions to these
+ // values. Changing this causes downstream errors I
+ // don't feel like investigating right now (in
+ // particular, self_ty is set to mk_err in some cases,
+ // probably for invocations on objects, and this
+ // causes encoding failures). -nmatsakis
+ new_method.substs.self_ty = None;
+ new_method.substs.regions = ty::ErasedRegions;
+
+ self.tcx().method_map.borrow_mut().insert(
+ method_call,
+ new_method);
+ }
+ None => {}
+ }
+ }
- match e.node {
- ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
- for input in decl.inputs.iter() {
- let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
+ fn visit_vtable_map_entry(&self,
+ reason: ResolveReason,
+ vtable_key: MethodCall) {
+ // Resolve any vtable map entry
+ match self.fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
+ Some(origins) => {
+ let r_origins = origins.resolve(self.fcx, reason);
+ debug!("writeback::resolve_vtable_map_entry(\
+ vtable_key={}, vtables={:?})",
+ vtable_key, r_origins.repr(self.tcx()));
+ self.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
}
+ None => {}
}
- _ => {}
}
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Resolution reason.
- visit::walk_expr(wbcx, e, ());
+enum ResolveReason {
+ ResolvingExpr(Span),
+ ResolvingLocal(Span),
+ ResolvingPattern(Span),
+ ResolvingUpvar(ty::UpvarId)
}
-fn visit_block(b: &ast::Block, wbcx: &mut WbCtxt) {
- if !wbcx.success {
- return;
+impl ResolveReason {
+ fn span(&self, fcx: &FnCtxt) -> Span {
+ match *self {
+ ResolvingExpr(s) => s,
+ ResolvingLocal(s) => s,
+ ResolvingPattern(s) => s,
+ ResolvingUpvar(upvar_id) => {
+ ty::expr_span(fcx.tcx(), upvar_id.closure_expr_id)
+ }
+ }
}
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Convenience methods for resolving different kinds of things.
- resolve_type_vars_for_node(wbcx, b.span, b.id);
- visit::walk_block(wbcx, b, ());
+trait Resolve {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Self;
}
-fn visit_pat(p: &ast::Pat, wbcx: &mut WbCtxt) {
- if !wbcx.success {
- return;
+impl<T:Resolve> Resolve for Option<T> {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Option<T> {
+ self.as_ref().map(|t| t.resolve(fcx, reason))
}
+}
- resolve_type_vars_for_node(wbcx, p.span, p.id);
- debug!("Type for pattern binding {} (id {}) resolved to {}",
- pat_to_str(p), p.id,
- wbcx.fcx.infcx().ty_to_str(
- ty::node_id_to_type(wbcx.fcx.ccx.tcx,
- p.id)));
- visit::walk_pat(wbcx, p, ());
+impl<T:Resolve> Resolve for Vec<T> {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Vec<T> {
+ self.iter().map(|t| t.resolve(fcx, reason)).collect()
+ }
}
-fn visit_local(l: &ast::Local, wbcx: &mut WbCtxt) {
- if !wbcx.success { return; }
- let var_ty = wbcx.fcx.local_ty(l.span, l.id);
- match resolve_type(wbcx.fcx.infcx(), var_ty, resolve_all | force_all) {
- Ok(lty) => {
- debug!("Type for local {} (id {}) resolved to {}",
- pat_to_str(l.pat),
- l.id,
- wbcx.fcx.infcx().ty_to_str(lty));
- write_ty_to_tcx(wbcx.fcx.ccx.tcx, l.id, lty);
- }
- Err(e) => {
- wbcx.fcx.ccx.tcx.sess.span_err(
- l.span,
- format!("cannot determine a type \
- for this local variable: {}",
- infer::fixup_err_to_str(e)));
- wbcx.success = false;
- }
+impl Resolve for ty::TraitStore {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::TraitStore {
+ Resolver::new(fcx, reason).fold_trait_store(*self)
}
- visit::walk_local(wbcx, l, ());
}
-fn visit_item(_item: &ast::Item, _wbcx: &mut WbCtxt) {
- // Ignore items
+
+impl Resolve for ty::t {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::t {
+ Resolver::new(fcx, reason).fold_ty(*self)
+ }
}
-impl<'a> Visitor<()> for WbCtxt<'a> {
- fn visit_item(&mut self, i: &ast::Item, _: ()) { visit_item(i, self); }
- fn visit_stmt(&mut self, s: &ast::Stmt, _: ()) { visit_stmt(s, self); }
- fn visit_expr(&mut self, ex:&ast::Expr, _: ()) { visit_expr(ex, self); }
- fn visit_block(&mut self, b: &ast::Block, _: ()) { visit_block(b, self); }
- fn visit_pat(&mut self, p: &ast::Pat, _: ()) { visit_pat(p, self); }
- fn visit_local(&mut self, l: &ast::Local, _: ()) { visit_local(l, self); }
- // FIXME(#10894) should continue recursing
- fn visit_ty(&mut self, _t: &ast::Ty, _: ()) {}
+impl Resolve for ty::Region {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::Region {
+ Resolver::new(fcx, reason).fold_region(*self)
+ }
}
-fn resolve_upvar_borrow_map(wbcx: &mut WbCtxt) {
- if !wbcx.success {
- return;
+impl Resolve for ty::substs {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::substs {
+ Resolver::new(fcx, reason).fold_substs(self)
}
+}
- let fcx = wbcx.fcx;
- let tcx = fcx.tcx();
- for (upvar_id, upvar_borrow) in fcx.inh.upvar_borrow_map.borrow().iter() {
- let r = upvar_borrow.region;
- match resolve_region(fcx.infcx(), r, resolve_all | force_all) {
- Ok(r) => {
- let new_upvar_borrow = ty::UpvarBorrow {
- kind: upvar_borrow.kind,
- region: r
- };
- debug!("Upvar borrow for {} resolved to {}",
- upvar_id.repr(tcx), new_upvar_borrow.repr(tcx));
- tcx.upvar_borrow_map.borrow_mut().insert(*upvar_id,
- new_upvar_borrow);
+impl Resolve for ty::AutoRef {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::AutoRef {
+ Resolver::new(fcx, reason).fold_autoref(self)
+ }
+}
+
+impl Resolve for vtable_origin {
+ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> vtable_origin {
+ match *self {
+ vtable_static(def_id, ref tys, ref origins) => {
+ let r_tys = tys.resolve(fcx, reason);
+ let r_origins = origins.resolve(fcx, reason);
+ vtable_static(def_id, r_tys, r_origins)
}
- Err(e) => {
- let span = ty::expr_span(tcx, upvar_id.closure_expr_id);
- fcx.ccx.tcx.sess.span_err(
- span, format!("cannot resolve lifetime for \
- captured variable `{}`: {}",
- ty::local_var_name_str(tcx, upvar_id.var_id).get().to_str(),
- infer::fixup_err_to_str(e)));
- wbcx.success = false;
+ vtable_param(n, b) => {
+ vtable_param(n, b)
}
- };
+ }
}
}
-pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) -> bool {
- let mut wbcx = WbCtxt { fcx: fcx, success: true };
- let wbcx = &mut wbcx;
- wbcx.visit_expr(e, ());
- resolve_upvar_borrow_map(wbcx);
- return wbcx.success;
+///////////////////////////////////////////////////////////////////////////
+// The Resolver. This is the type folding engine that detects
+// unresolved types and so forth.
+
+struct Resolver<'cx> {
+ fcx: &'cx FnCtxt<'cx>,
+ reason: ResolveReason,
}
-pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, decl: &ast::FnDecl,
- blk: &ast::Block) -> bool {
- let mut wbcx = WbCtxt { fcx: fcx, success: true };
- let wbcx = &mut wbcx;
- wbcx.visit_block(blk, ());
- for arg in decl.inputs.iter() {
- wbcx.visit_pat(arg.pat, ());
- // Privacy needs the type for the whole pattern, not just each binding
- if !pat_util::pat_is_binding(&fcx.tcx().def_map, arg.pat) {
- resolve_type_vars_for_node(wbcx, arg.pat.span, arg.pat.id);
+impl<'cx> Resolver<'cx> {
+ fn new(fcx: &'cx FnCtxt<'cx>,
+ reason: ResolveReason)
+ -> Resolver<'cx>
+ {
+ Resolver { fcx: fcx, reason: reason }
+ }
+
+ fn report_error(&self, e: infer::fixup_err) {
+ self.fcx.writeback_errors.set(true);
+ if !self.tcx().sess.has_errors() {
+ match self.reason {
+ ResolvingExpr(span) => {
+ self.tcx().sess.span_err(
+ span,
+ format!("cannot determine a type for \
+ this expression: {}",
+ infer::fixup_err_to_str(e)))
+ }
+
+ ResolvingLocal(span) => {
+ self.tcx().sess.span_err(
+ span,
+ format!("cannot determine a type for \
+ this local variable: {}",
+ infer::fixup_err_to_str(e)))
+ }
+
+ ResolvingPattern(span) => {
+ self.tcx().sess.span_err(
+ span,
+ format!("cannot determine a type for \
+ this pattern binding: {}",
+ infer::fixup_err_to_str(e)))
+ }
+
+ ResolvingUpvar(upvar_id) => {
+ let span = self.reason.span(self.fcx);
+ self.tcx().sess.span_err(
+ span,
+ format!("cannot resolve lifetime for \
+ captured variable `{}`: {}",
+ ty::local_var_name_str(
+ self.tcx(),
+ upvar_id.var_id).get().to_str(),
+ infer::fixup_err_to_str(e)));
+ }
+ }
+ }
+ }
+}
+
+impl<'cx> TypeFolder for Resolver<'cx> {
+ fn tcx<'a>(&'a self) -> &'a ty::ctxt {
+ self.fcx.tcx()
+ }
+
+ fn fold_ty(&mut self, t: ty::t) -> ty::t {
+ if !ty::type_needs_infer(t) {
+ return t;
+ }
+
+ match resolve_type(self.fcx.infcx(), t, resolve_all | force_all) {
+ Ok(t) => t,
+ Err(e) => {
+ self.report_error(e);
+ ty::mk_err()
+ }
+ }
+ }
+
+ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+ match resolve_region(self.fcx.infcx(), r, resolve_all | force_all) {
+ Ok(r) => r,
+ Err(e) => {
+ self.report_error(e);
+ ty::ReStatic
+ }
}
}
- resolve_upvar_borrow_map(wbcx);
- return wbcx.success;
}
use middle::typeck::infer::{TypeTrace, Subtype};
use middle::typeck::infer::fold_regions_in_sig;
use syntax::ast::{Many, Once, MutImmutable, MutMutable};
-use syntax::ast::{ExternFn, NormalFn, UnsafeFn, NodeId};
+use syntax::ast::{NormalFn, UnsafeFn, NodeId};
use syntax::ast::{Onceness, FnStyle};
use collections::HashMap;
use util::common::{indenter};
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
match (a, b) {
- (ExternFn, _) | (_, ExternFn) => Ok(ExternFn),
(NormalFn, _) | (_, NormalFn) => Ok(NormalFn),
(UnsafeFn, UnsafeFn) => Ok(UnsafeFn)
}
use middle::typeck::infer::{TypeTrace, Subtype};
use collections::HashMap;
use syntax::ast::{Many, Once, NodeId};
-use syntax::ast::{ExternFn, NormalFn, UnsafeFn};
+use syntax::ast::{NormalFn, UnsafeFn};
use syntax::ast::{Onceness, FnStyle};
use util::ppaux::mt_to_str;
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
match (a, b) {
(UnsafeFn, _) | (_, UnsafeFn) => Ok(UnsafeFn),
- (NormalFn, _) | (_, NormalFn) => Ok(NormalFn),
- (ExternFn, ExternFn) => Ok(ExternFn),
+ (NormalFn, NormalFn) => Ok(NormalFn),
}
}
use syntax::visit;
use syntax::visit::Visitor;
-use std::local_data;
-
use time;
pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
local_data_key!(depth: uint);
if !do_it { return f(u); }
- let old = local_data::get(depth, |d| d.map(|a| *a).unwrap_or(0));
- local_data::set(depth, old + 1);
+ let old = depth.get().map(|d| *d).unwrap_or(0);
+ depth.replace(Some(old + 1));
let start = time::precise_time_s();
let rv = f(u);
let end = time::precise_time_s();
println!("{}time: {:3.3f} s\t{}", " ".repeat(old), end - start, what);
- local_data::set(depth, old);
+ depth.replace(Some(old));
rv
}
ty_bot => "!".to_owned(),
ty_bool => "bool".to_owned(),
ty_char => "char".to_owned(),
- ty_int(t) => ast_util::int_ty_to_str(t, None),
- ty_uint(t) => ast_util::uint_ty_to_str(t, None),
- ty_float(t) => ast_util::float_ty_to_str(t),
+ ty_int(t) => ast_util::int_ty_to_str(t, None).to_owned(),
+ ty_uint(t) => ast_util::uint_ty_to_str(t, None).to_owned(),
+ ty_float(t) => ast_util::float_ty_to_str(t).to_owned(),
ty_box(typ) => "@".to_owned() + ty_to_str(cx, typ),
ty_uniq(typ) => "~".to_owned() + ty_to_str(cx, typ),
ty_ptr(ref tm) => "*".to_owned() + mt_to_str(cx, tm),
impl Repr for Span {
fn repr(&self, tcx: &ctxt) -> ~str {
- tcx.sess.codemap().span_to_str(*self)
+ tcx.sess.codemap().span_to_str(*self).to_owned()
}
}
use rustc::metadata::csearch;
use rustc::metadata::decoder;
-use std::local_data;
use std::strbuf::StrBuf;
use core;
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
fn clean(&self) -> Crate {
- let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let cx = super::ctxtkey.get().unwrap();
let mut externs = Vec::new();
cx.sess().cstore.iter_crate_data(|n, meta| {
let id = link::find_crate_id(self.attrs.as_slice(),
t_outputs.out_filestem);
Crate {
- name: id.name,
+ name: id.name.to_owned(),
module: Some(self.module.clean()),
externs: externs,
}
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
let where = {
- let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap();
let outer = cm.lookup_char_pos(self.where_outer.lo);
let inner = cm.lookup_char_pos(self.where_inner.lo);
fn clean(&self) -> Type {
use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
- let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let ctxt = super::ctxtkey.get().unwrap();
let codemap = ctxt.sess().codemap();
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node {
impl Clean<Span> for syntax::codemap::Span {
fn clean(&self) -> Span {
- let ctxt = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap();
let filename = cm.span_to_filename(*self);
let lo = cm.lookup_char_pos(self.lo);
ForeignFunctionItem(Function {
decl: decl.clean(),
generics: generics.clean(),
- fn_style: ast::ExternFn,
+ fn_style: ast::NormalFn,
})
}
ast::ForeignItemStatic(ref ty, mutbl) => {
impl ToSource for syntax::codemap::Span {
fn to_src(&self) -> ~str {
debug!("converting span {:?} to snippet", self.clean());
- let ctxt = local_data::get(super::ctxtkey, |x| x.unwrap().clone());
+ let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap().clone();
let sn = match cm.span_to_snippet(*self) {
- Some(x) => x,
+ Some(x) => x.to_owned(),
None => "".to_owned()
};
debug!("got snippet {}", sn);
/// Given a Type, resolve it using the def_map
fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
id: ast::NodeId) -> Type {
- let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let cx = super::ctxtkey.get().unwrap();
let tycx = match cx.maybe_typed {
core::Typed(ref tycx) => tycx,
// If we're extracting tests, this return value doesn't matter.
}
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
- let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
+ let cx = super::ctxtkey.get().unwrap();
match cx.maybe_typed {
core::Typed(ref tcx) => {
tcx.def_map.borrow().find(&id).map(|&d| ast_util::def_id_of_def(d))
use std::cell::RefCell;
use std::os;
-use std::local_data;
use collections::HashSet;
use visit_ast::RustdocVisitor;
-> (clean::Crate, CrateAnalysis) {
let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs);
let ctxt = @ctxt;
- local_data::set(super::ctxtkey, ctxt);
+ super::ctxtkey.replace(Some(ctxt));
let krate = {
let mut v = RustdocVisitor::new(ctxt, Some(&analysis));
use std::fmt;
use std::io;
-use std::local_data;
use std::strbuf::StrBuf;
use syntax::ast;
generics.push_str(">");
}
- // Did someone say rightward-drift?
- local_data::get(current_location_key, |loc| {
- let loc = loc.unwrap();
-
- local_data::get(cache_key, |cache| {
- let cache = cache.unwrap();
- let abs_root = root(&**cache, loc.as_slice());
- let rel_root = match path.segments.get(0).name.as_slice() {
- "self" => Some("./".to_owned()),
- _ => None,
- };
-
- if print_all {
- let amt = path.segments.len() - 1;
- match rel_root {
- Some(root) => {
- let mut root = StrBuf::from_str(root);
- for seg in path.segments.slice_to(amt).iter() {
- if "super" == seg.name || "self" == seg.name {
- try!(write!(w, "{}::", seg.name));
- } else {
- root.push_str(seg.name);
- root.push_str("/");
- try!(write!(w, "<a class='mod'
- href='{}index.html'>{}</a>::",
- root.as_slice(),
- seg.name));
- }
- }
- }
- None => {
- for seg in path.segments.slice_to(amt).iter() {
- try!(write!(w, "{}::", seg.name));
- }
+ let loc = current_location_key.get().unwrap();
+ let cache = cache_key.get().unwrap();
+ let abs_root = root(&**cache, loc.as_slice());
+ let rel_root = match path.segments.get(0).name.as_slice() {
+ "self" => Some("./".to_owned()),
+ _ => None,
+ };
+
+ if print_all {
+ let amt = path.segments.len() - 1;
+ match rel_root {
+ Some(root) => {
+ let mut root = StrBuf::from_str(root);
+ for seg in path.segments.slice_to(amt).iter() {
+ if "super" == seg.name || "self" == seg.name {
+ try!(write!(w, "{}::", seg.name));
+ } else {
+ root.push_str(seg.name);
+ root.push_str("/");
+ try!(write!(w, "<a class='mod'
+ href='{}index.html'>{}</a>::",
+ root.as_slice(),
+ seg.name));
}
}
}
-
- match info(&**cache) {
- // This is a documented path, link to it!
- Some((ref fqp, shortty)) if abs_root.is_some() => {
- let mut url = StrBuf::from_str(abs_root.unwrap());
- let to_link = fqp.slice_to(fqp.len() - 1);
- for component in to_link.iter() {
- url.push_str(*component);
- url.push_str("/");
- }
- match shortty {
- item_type::Module => {
- url.push_str(*fqp.last().unwrap());
- url.push_str("/index.html");
- }
- _ => {
- url.push_str(shortty.to_static_str());
- url.push_str(".");
- url.push_str(*fqp.last().unwrap());
- url.push_str(".html");
- }
- }
-
- try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
- shortty, url, fqp.connect("::"), last.name));
+ None => {
+ for seg in path.segments.slice_to(amt).iter() {
+ try!(write!(w, "{}::", seg.name));
}
+ }
+ }
+ }
+ match info(&**cache) {
+ // This is a documented path, link to it!
+ Some((ref fqp, shortty)) if abs_root.is_some() => {
+ let mut url = StrBuf::from_str(abs_root.unwrap());
+ let to_link = fqp.slice_to(fqp.len() - 1);
+ for component in to_link.iter() {
+ url.push_str(*component);
+ url.push_str("/");
+ }
+ match shortty {
+ item_type::Module => {
+ url.push_str(*fqp.last().unwrap());
+ url.push_str("/index.html");
+ }
_ => {
- try!(write!(w, "{}", last.name));
+ url.push_str(shortty.to_static_str());
+ url.push_str(".");
+ url.push_str(*fqp.last().unwrap());
+ url.push_str(".html");
}
}
- try!(write!(w, "{}", generics.as_slice()));
- Ok(())
- })
- })
+
+ try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
+ shortty, url, fqp.connect("::"), last.name));
+ }
+
+ _ => {
+ try!(write!(w, "{}", last.name));
+ }
+ }
+ try!(write!(w, "{}", generics.as_slice()));
+ Ok(())
}
/// Helper to render type parameters
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
clean::TyParamBinder(id) | clean::Generic(id) => {
- local_data::get(cache_key, |cache| {
- let m = cache.unwrap();
- f.buf.write(m.typarams.get(&id).as_bytes())
- })
+ let m = cache_key.get().unwrap();
+ f.buf.write(m.typarams.get(&id).as_bytes())
}
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
try!(resolved_path(f.buf, id, path, false));
"".to_owned()
} else {
let mut m = decl.bounds.iter().map(|s| s.to_str());
- ": " + m.collect::<~[~str]>().connect(" + ")
+ ": " + m.collect::<Vec<~str>>().connect(" + ")
},
arrow = match decl.decl.output { clean::Unit => "no", _ => "yes" },
ret = decl.decl.output)
clean::BareFunction(ref decl) => {
write!(f.buf, "{}{}fn{}{}",
FnStyleSpace(decl.fn_style),
- match decl.abi {
- ref x if "" == *x => "".to_owned(),
- ref x if "\"Rust\"" == *x => "".to_owned(),
- ref s => " " + *s + " ",
+ match decl.abi.as_slice() {
+ "" => " extern ".to_owned(),
+ "\"Rust\"" => "".to_owned(),
+ s => format!(" extern {} ", s)
},
decl.generics,
decl.decl)
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.get() {
ast::UnsafeFn => write!(f.buf, "unsafe "),
- ast::ExternFn => write!(f.buf, "extern "),
ast::NormalFn => Ok(())
}
}
/// Highlights some source code, returning the HTML output.
pub fn highlight(src: &str, class: Option<&str>) -> ~str {
let sess = parse::new_parse_sess();
- let fm = parse::string_to_filemap(&sess, src.to_owned(), "<stdin>".to_owned());
+ let fm = parse::string_to_filemap(&sess,
+ src.to_strbuf(),
+ "<stdin>".to_strbuf());
let mut out = io::MemWriter::new();
doit(&sess,
hi: test,
expn_info: None,
}).unwrap();
- if snip.contains("/") {
+ if snip.as_slice().contains("/") {
try!(write!(out, "<span class='comment'>{}</span>",
- Escape(snip)));
+ Escape(snip.as_slice())));
} else {
- try!(write!(out, "{}", Escape(snip)));
+ try!(write!(out, "{}", Escape(snip.as_slice())));
}
}
last = next.sp.hi;
// stringifying this token
let snip = sess.span_diagnostic.cm.span_to_snippet(next.sp).unwrap();
if klass == "" {
- try!(write!(out, "{}", Escape(snip)));
+ try!(write!(out, "{}", Escape(snip.as_slice())));
} else {
try!(write!(out, "<span class='{}'>{}</span>", klass,
- Escape(snip)));
+ Escape(snip.as_slice())));
}
}
#![allow(non_camel_case_types)]
use libc;
+use std::cell::RefCell;
use std::fmt;
use std::io;
-use std::local_data;
-use std::str;
use std::slice;
+use std::str;
use collections::HashMap;
use html::toc::TocBuilder;
}
}
-local_data_key!(used_header_map: HashMap<~str, uint>)
+local_data_key!(used_header_map: RefCell<HashMap<~str, uint>>)
pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
// Make sure our hyphenated ID is unique for this page
- let id = local_data::get_mut(used_header_map, |map| {
- let map = map.unwrap();
- match map.find_mut(&id) {
- None => {}
- Some(a) => { *a += 1; return format!("{}-{}", id, *a - 1) }
- }
- map.insert(id.clone(), 1);
- id.clone()
- });
+ let map = used_header_map.get().unwrap();
+ let id = match map.borrow_mut().find_mut(&id) {
+ None => id,
+ Some(a) => { *a += 1; format!("{}-{}", id, *a - 1) }
+ };
+ map.borrow_mut().insert(id.clone(), 1);
let sec = match opaque.toc_builder {
Some(ref mut builder) => {
/// used at the beginning of rendering an entire HTML page to reset from the
/// previous state (if any).
pub fn reset_headers() {
- local_data::set(used_header_map, HashMap::new())
+ used_header_map.replace(Some(RefCell::new(HashMap::new())));
}
impl<'a> fmt::Show for Markdown<'a> {
use std::fmt;
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
use std::io;
-use std::local_data;
use std::str;
use std::strbuf::StrBuf;
}
// Crawl the crate to build various caches used for the output
- let mut cache = local_data::get(::analysiskey, |analysis| {
- let public_items = analysis.map(|a| a.public_items.clone());
- let public_items = public_items.unwrap_or(NodeSet::new());
- Cache {
- impls: HashMap::new(),
- typarams: HashMap::new(),
- paths: HashMap::new(),
- traits: HashMap::new(),
- implementors: HashMap::new(),
- stack: Vec::new(),
- parent_stack: Vec::new(),
- search_index: Vec::new(),
- extern_locations: HashMap::new(),
- privmod: false,
- public_items: public_items,
- orphan_methods: Vec::new(),
- }
- });
+ let public_items = ::analysiskey.get().map(|a| a.public_items.clone());
+ let public_items = public_items.unwrap_or(NodeSet::new());
+ let mut cache = Cache {
+ impls: HashMap::new(),
+ typarams: HashMap::new(),
+ paths: HashMap::new(),
+ traits: HashMap::new(),
+ implementors: HashMap::new(),
+ stack: Vec::new(),
+ parent_stack: Vec::new(),
+ search_index: Vec::new(),
+ extern_locations: HashMap::new(),
+ privmod: false,
+ public_items: public_items,
+ orphan_methods: Vec::new(),
+ };
cache.stack.push(krate.name.clone());
krate = cache.fold_crate(krate);
root_path.push_str("../");
});
- cur.push(p.filename().expect("source has no filename") + bytes!(".html"));
+ cur.push(Vec::from_slice(p.filename().expect("source has no filename"))
+ .append(bytes!(".html")));
let mut w = BufferedWriter::new(try!(File::create(&cur)));
let title = format!("{} -- source", cur.filename_display());
item.name = Some(krate.name);
// using a rwarc makes this parallelizable in the future
- local_data::set(cache_key, Arc::new(cache));
+ cache_key.replace(Some(Arc::new(cache)));
let mut work = vec!((self, item));
loop {
info!("Rendering an item to {}", w.path().display());
// A little unfortunate that this is done like this, but it sure
// does make formatting *a lot* nicer.
- local_data::set(current_location_key, cx.current.clone());
+ current_location_key.replace(Some(cx.current.clone()));
let mut title = StrBuf::from_str(cx.current.connect("::"));
if pushname {
try!(write!(w, "</div>"));
}
- local_data::get(cache_key, |cache| {
- let cache = cache.unwrap();
- match cache.implementors.find(&it.id) {
- Some(implementors) => {
- try!(write!(w, "
- <h2 id='implementors'>Implementors</h2>
- <ul class='item-list'>
- "));
- for i in implementors.iter() {
- match *i {
- PathType(ref ty) => {
- try!(write!(w, "<li><code>{}</code></li>", *ty));
- }
- OtherType(ref generics, ref trait_, ref for_) => {
- try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
- *generics, *trait_, *for_));
- }
+ match cache_key.get().unwrap().implementors.find(&it.id) {
+ Some(implementors) => {
+ try!(write!(w, "
+ <h2 id='implementors'>Implementors</h2>
+ <ul class='item-list'>
+ "));
+ for i in implementors.iter() {
+ match *i {
+ PathType(ref ty) => {
+ try!(write!(w, "<li><code>{}</code></li>", *ty));
+ }
+ OtherType(ref generics, ref trait_, ref for_) => {
+ try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
+ *generics, *trait_, *for_));
}
}
- try!(write!(w, "</ul>"));
}
- None => {}
+ try!(write!(w, "</ul>"));
}
- Ok(())
- })
+ None => {}
+ }
+ Ok(())
}
fn render_method(w: &mut Writer, meth: &clean::Item) -> fmt::Result {
}
fn render_methods(w: &mut Writer, it: &clean::Item) -> fmt::Result {
- local_data::get(cache_key, |cache| {
- let c = cache.unwrap();
- match c.impls.find(&it.id) {
- Some(v) => {
- let mut non_trait = v.iter().filter(|p| {
- p.ref0().trait_.is_none()
- });
- let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
- let mut traits = v.iter().filter(|p| {
- p.ref0().trait_.is_some()
- });
- let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
-
- if non_trait.len() > 0 {
- try!(write!(w, "<h2 id='methods'>Methods</h2>"));
- for &(ref i, ref dox) in non_trait.move_iter() {
+ match cache_key.get().unwrap().impls.find(&it.id) {
+ Some(v) => {
+ let mut non_trait = v.iter().filter(|p| {
+ p.ref0().trait_.is_none()
+ });
+ let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
+ let mut traits = v.iter().filter(|p| {
+ p.ref0().trait_.is_some()
+ });
+ let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
+
+ if non_trait.len() > 0 {
+ try!(write!(w, "<h2 id='methods'>Methods</h2>"));
+ for &(ref i, ref dox) in non_trait.move_iter() {
+ try!(render_impl(w, i, dox));
+ }
+ }
+ if traits.len() > 0 {
+ try!(write!(w, "<h2 id='implementations'>Trait \
+ Implementations</h2>"));
+ let mut any_derived = false;
+ for & &(ref i, ref dox) in traits.iter() {
+ if !i.derived {
try!(render_impl(w, i, dox));
+ } else {
+ any_derived = true;
}
}
- if traits.len() > 0 {
- try!(write!(w, "<h2 id='implementations'>Trait \
- Implementations</h2>"));
- let mut any_derived = false;
- for & &(ref i, ref dox) in traits.iter() {
- if !i.derived {
+ if any_derived {
+ try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
+ </h3>"));
+ for &(ref i, ref dox) in traits.move_iter() {
+ if i.derived {
try!(render_impl(w, i, dox));
- } else {
- any_derived = true;
- }
- }
- if any_derived {
- try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
- </h3>"));
- for &(ref i, ref dox) in traits.move_iter() {
- if i.derived {
- try!(render_impl(w, i, dox));
- }
}
}
}
}
- None => {}
}
- Ok(())
- })
+ None => {}
+ }
+ Ok(())
}
fn render_impl(w: &mut Writer, i: &clean::Impl,
match trait_id {
None => {}
Some(id) => {
- try!(local_data::get(cache_key, |cache| {
- let cache = cache.unwrap();
- match cache.traits.find(&id) {
+ try!({
+ match cache_key.get().unwrap().traits.find(&id) {
Some(t) => {
for method in t.methods.iter() {
let n = method.item().name.clone();
None => {}
}
Ok(())
- }))
+ })
}
}
try!(write!(w, "</div>"));
extern crate log;
extern crate libc;
-use std::local_data;
use std::io;
use std::io::{File, MemWriter};
use std::str;
type Output = (clean::Crate, Vec<plugins::PluginJson> );
pub fn main() {
- std::os::set_exit_status(main_args(std::os::args()));
+ std::os::set_exit_status(main_args(std::os::args().as_slice()));
}
pub fn opts() -> Vec<getopts::OptGroup> {
&cr)
}).unwrap();
info!("finished with rustc");
- local_data::set(analysiskey, analysis);
+ analysiskey.replace(Some(analysis));
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
use collections::HashSet;
use rustc::util::nodemap::NodeSet;
use std::cmp;
-use std::local_data;
use std::strbuf::StrBuf;
use std::uint;
use syntax::ast;
/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
-pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
+pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
// This stripper collects all *retained* nodes.
let mut retained = HashSet::new();
- let exported_items = local_data::get(super::analysiskey, |analysis| {
- analysis.unwrap().exported_items.clone()
- });
- let mut krate = krate;
+ let analysis = super::analysiskey.get().unwrap();
+ let exported_items = analysis.exported_items.clone();
// strip all private items
{
use std::char;
use std::io;
use std::io::{Process, TempDir};
-use std::local_data;
use std::os;
use std::str;
use std::strbuf::StrBuf;
maybe_typed: core::NotTyped(sess),
src: input_path,
};
- local_data::set(super::ctxtkey, ctx);
+ super::ctxtkey.replace(Some(ctx));
let mut v = RustdocVisitor::new(ctx, None);
v.visit(&ctx.krate);
}
struct Inner {
- queue: Vec<BlockedTask>,
+ queue: Vec<(BlockedTask, uint)>,
held: bool,
+ closed: bool,
}
impl Access {
inner: UnsafeArc::new(Inner {
queue: vec![],
held: false,
+ closed: false,
})
}
}
- pub fn grant<'a>(&'a mut self, missile: HomingMissile) -> Guard<'a> {
+ pub fn grant<'a>(&'a mut self, token: uint,
+ missile: HomingMissile) -> Guard<'a> {
// This unsafety is actually OK because the homing missile argument
// guarantees that we're on the same event loop as all the other objects
// attempting to get access granted.
- let inner: &mut Inner = unsafe { cast::transmute(self.inner.get()) };
+ let inner: &mut Inner = unsafe { &mut *self.inner.get() };
if inner.held {
let t: Box<Task> = Local::take();
t.deschedule(1, |task| {
- inner.queue.push(task);
+ inner.queue.push((task, token));
Ok(())
});
assert!(inner.held);
Guard { access: self, missile: Some(missile) }
}
+
+ pub fn close(&self, _missile: &HomingMissile) {
+ // This unsafety is OK because with a homing missile we're guaranteed to
+ // be the only task looking at the `closed` flag (and are therefore
+ // allowed to modify it). Additionally, no atomics are necessary because
+ // everyone's running on the same thread and has already done the
+ // necessary synchronization to be running on this thread.
+ unsafe { (*self.inner.get()).closed = true; }
+ }
+
+ // Dequeue a blocked task with a specified token. This is unsafe because it
+ // is only safe to invoke while on the home event loop, and there is no
+ // guarantee that this i being invoked on the home event loop.
+ pub unsafe fn dequeue(&mut self, token: uint) -> Option<BlockedTask> {
+ let inner: &mut Inner = &mut *self.inner.get();
+ match inner.queue.iter().position(|&(_, t)| t == token) {
+ Some(i) => Some(inner.queue.remove(i).unwrap().val0()),
+ None => None,
+ }
+ }
}
impl Clone for Access {
}
}
+impl<'a> Guard<'a> {
+ pub fn is_closed(&self) -> bool {
+ // See above for why this unsafety is ok, it just applies to the read
+ // instead of the write.
+ unsafe { (*self.access.inner.get()).closed }
+ }
+}
+
#[unsafe_destructor]
impl<'a> Drop for Guard<'a> {
fn drop(&mut self) {
// scheduled on this scheduler. Because we might be woken up on some
// other scheduler, we drop our homing missile before we reawaken
// the task.
- Some(task) => {
+ Some((task, _)) => {
drop(self.missile.take());
- let _ = task.wake().map(|t| t.reawaken());
+ task.reawaken();
}
None => { inner.held = false; }
}
impl GetAddrInfoRequest {
pub fn run(loop_: &Loop, node: Option<&str>, service: Option<&str>,
- hints: Option<ai::Hint>) -> Result<~[ai::Info], UvError> {
+ hints: Option<ai::Hint>) -> Result<Vec<ai::Info>, UvError> {
assert!(node.is_some() || service.is_some());
let (_c_node, c_node_ptr) = match node {
Some(n) => {
}
// Traverse the addrinfo linked list, producing a vector of Rust socket addresses
-pub fn accum_addrinfo(addr: &Addrinfo) -> ~[ai::Info] {
+pub fn accum_addrinfo(addr: &Addrinfo) -> Vec<ai::Info> {
unsafe {
let mut addr = addr.handle;
}
}
- return addrs.move_iter().collect();
+ addrs
}
}
mod macros;
mod access;
+mod timeout;
mod homing;
mod queue;
mod rc;
use libc::{size_t, ssize_t, c_int, c_void, c_uint};
use libc;
use std::cast;
-use std::io::{IoError, IoResult};
+use std::io;
+use std::io::IoError;
use std::io::net::ip;
use std::mem;
use std::ptr;
use std::rt::rtio;
use std::rt::task::BlockedTask;
-use access::Access;
use homing::{HomingIO, HomeHandle};
use rc::Refcount;
use stream::StreamWatcher;
use super::{Loop, Request, UvError, Buf, status_to_io_result,
uv_error_to_io_error, UvHandle, slice_to_uv_buf,
wait_until_woken_after, wakeup};
-use timer::TimerWatcher;
+use timeout::{AccessTimeout, AcceptTimeout, ConnectCtx};
use uvio::UvIoFactory;
use uvll;
n => Err(uv_error_to_io_error(UvError(n)))
}
}
-////////////////////////////////////////////////////////////////////////////////
-// Helpers for handling timeouts, shared for pipes/tcp
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct ConnectCtx {
- pub status: c_int,
- pub task: Option<BlockedTask>,
- pub timer: Option<Box<TimerWatcher>>,
-}
-
-pub struct AcceptTimeout {
- timer: Option<TimerWatcher>,
- timeout_tx: Option<Sender<()>>,
- timeout_rx: Option<Receiver<()>>,
-}
-
-impl ConnectCtx {
- pub fn connect<T>(
- mut self, obj: T, timeout: Option<u64>, io: &mut UvIoFactory,
- f: |&Request, &T, uvll::uv_connect_cb| -> libc::c_int
- ) -> Result<T, UvError> {
- let mut req = Request::new(uvll::UV_CONNECT);
- let r = f(&req, &obj, connect_cb);
- return match r {
- 0 => {
- req.defuse(); // uv callback now owns this request
- match timeout {
- Some(t) => {
- let mut timer = TimerWatcher::new(io);
- timer.start(timer_cb, t, 0);
- self.timer = Some(timer);
- }
- None => {}
- }
- wait_until_woken_after(&mut self.task, &io.loop_, || {
- let data = &self as *_;
- match self.timer {
- Some(ref mut timer) => unsafe { timer.set_data(data) },
- None => {}
- }
- req.set_data(data);
- });
- // Make sure an erroneously fired callback doesn't have access
- // to the context any more.
- req.set_data(0 as *int);
-
- // If we failed because of a timeout, drop the TcpWatcher as
- // soon as possible because it's data is now set to null and we
- // want to cancel the callback ASAP.
- match self.status {
- 0 => Ok(obj),
- n => { drop(obj); Err(UvError(n)) }
- }
- }
- n => Err(UvError(n))
- };
-
- extern fn timer_cb(handle: *uvll::uv_timer_t) {
- // Don't close the corresponding tcp request, just wake up the task
- // and let RAII take care of the pending watcher.
- let cx: &mut ConnectCtx = unsafe {
- &mut *(uvll::get_data_for_uv_handle(handle) as *mut ConnectCtx)
- };
- cx.status = uvll::ECANCELED;
- wakeup(&mut cx.task);
- }
-
- extern fn connect_cb(req: *uvll::uv_connect_t, status: c_int) {
- // This callback can be invoked with ECANCELED if the watcher is
- // closed by the timeout callback. In that case we just want to free
- // the request and be along our merry way.
- let req = Request::wrap(req);
- if status == uvll::ECANCELED { return }
-
- // Apparently on windows when the handle is closed this callback may
- // not be invoked with ECANCELED but rather another error code.
- // Either ways, if the data is null, then our timeout has expired
- // and there's nothing we can do.
- let data = unsafe { uvll::get_data_for_req(req.handle) };
- if data.is_null() { return }
-
- let cx: &mut ConnectCtx = unsafe { &mut *(data as *mut ConnectCtx) };
- cx.status = status;
- match cx.timer {
- Some(ref mut t) => t.stop(),
- None => {}
- }
- // Note that the timer callback doesn't cancel the connect request
- // (that's the job of uv_close()), so it's possible for this
- // callback to get triggered after the timeout callback fires, but
- // before the task wakes up. In that case, we did indeed
- // successfully connect, but we don't need to wake someone up. We
- // updated the status above (correctly so), and the task will pick
- // up on this when it wakes up.
- if cx.task.is_some() {
- wakeup(&mut cx.task);
- }
- }
- }
-}
-
-impl AcceptTimeout {
- pub fn new() -> AcceptTimeout {
- AcceptTimeout { timer: None, timeout_tx: None, timeout_rx: None }
- }
-
- pub fn accept<T: Send>(&mut self, c: &Receiver<IoResult<T>>) -> IoResult<T> {
- match self.timeout_rx {
- None => c.recv(),
- Some(ref rx) => {
- use std::comm::Select;
-
- // Poll the incoming channel first (don't rely on the order of
- // select just yet). If someone's pending then we should return
- // them immediately.
- match c.try_recv() {
- Ok(data) => return data,
- Err(..) => {}
- }
-
- // Use select to figure out which channel gets ready first. We
- // do some custom handling of select to ensure that we never
- // actually drain the timeout channel (we'll keep seeing the
- // timeout message in the future).
- let s = Select::new();
- let mut timeout = s.handle(rx);
- let mut data = s.handle(c);
- unsafe {
- timeout.add();
- data.add();
- }
- if s.wait() == timeout.id() {
- Err(uv_error_to_io_error(UvError(uvll::ECANCELED)))
- } else {
- c.recv()
- }
- }
- }
- }
-
- pub fn clear(&mut self) {
- // Clear any previous timeout by dropping the timer and transmission
- // channels
- drop((self.timer.take(),
- self.timeout_tx.take(),
- self.timeout_rx.take()))
- }
-
- pub fn set_timeout<U, T: UvHandle<U> + HomingIO>(
- &mut self, ms: u64, t: &mut T
- ) {
- // If we have a timeout, lazily initialize the timer which will be used
- // to fire when the timeout runs out.
- if self.timer.is_none() {
- let _m = t.fire_homing_missile();
- let loop_ = Loop::wrap(unsafe {
- uvll::get_loop_for_uv_handle(t.uv_handle())
- });
- let mut timer = TimerWatcher::new_home(&loop_, t.home().clone());
- unsafe {
- timer.set_data(self as *mut _ as *AcceptTimeout);
- }
- self.timer = Some(timer);
- }
-
- // Once we've got a timer, stop any previous timeout, reset it for the
- // current one, and install some new channels to send/receive data on
- let timer = self.timer.get_mut_ref();
- timer.stop();
- timer.start(timer_cb, ms, 0);
- let (tx, rx) = channel();
- self.timeout_tx = Some(tx);
- self.timeout_rx = Some(rx);
-
- extern fn timer_cb(timer: *uvll::uv_timer_t) {
- let acceptor: &mut AcceptTimeout = unsafe {
- &mut *(uvll::get_data_for_uv_handle(timer) as *mut AcceptTimeout)
- };
- // This send can never fail because if this timer is active then the
- // receiving channel is guaranteed to be alive
- acceptor.timeout_tx.get_ref().send(());
- }
- }
-}
////////////////////////////////////////////////////////////////////////////////
/// TCP implementation
// stream object, so we use these access guards in order to arbitrate among
// multiple concurrent reads and writes. Note that libuv *can* read and
// write simultaneously, it just can't read and read simultaneously.
- read_access: Access,
- write_access: Access,
+ read_access: AccessTimeout,
+ write_access: AccessTimeout,
}
pub struct TcpListener {
handle: handle,
stream: StreamWatcher::new(handle),
refcount: Refcount::new(),
- read_access: Access::new(),
- write_access: Access::new(),
+ read_access: AccessTimeout::new(),
+ write_access: AccessTimeout::new(),
}
}
impl rtio::RtioTcpStream for TcpWatcher {
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
let m = self.fire_homing_missile();
- let _g = self.read_access.grant(m);
+ let guard = try!(self.read_access.grant(m));
+
+ // see comments in close_read about this check
+ if guard.access.is_closed() {
+ return Err(io::standard_error(io::EndOfFile))
+ }
+
self.stream.read(buf).map_err(uv_error_to_io_error)
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
let m = self.fire_homing_missile();
- let _g = self.write_access.grant(m);
- self.stream.write(buf).map_err(uv_error_to_io_error)
+ let guard = try!(self.write_access.grant(m));
+ self.stream.write(buf, guard.can_timeout).map_err(uv_error_to_io_error)
}
fn peer_name(&mut self) -> Result<ip::SocketAddr, IoError> {
stream: StreamWatcher::new(self.handle),
home: self.home.clone(),
refcount: self.refcount.clone(),
- write_access: self.write_access.clone(),
read_access: self.read_access.clone(),
+ write_access: self.write_access.clone(),
} as Box<rtio::RtioTcpStream:Send>
}
+ fn close_read(&mut self) -> Result<(), IoError> {
+ // see comments in PipeWatcher::close_read
+ let task = {
+ let m = self.fire_homing_missile();
+ self.read_access.access.close(&m);
+ self.stream.cancel_read(uvll::EOF as libc::ssize_t)
+ };
+ let _ = task.map(|t| t.reawaken());
+ Ok(())
+ }
+
fn close_write(&mut self) -> Result<(), IoError> {
- struct Ctx {
- slot: Option<BlockedTask>,
- status: c_int,
- }
- let mut req = Request::new(uvll::UV_SHUTDOWN);
+ let _m = self.fire_homing_missile();
+ shutdown(self.handle, &self.uv_loop())
+ }
- return match unsafe {
- uvll::uv_shutdown(req.handle, self.handle, shutdown_cb)
- } {
- 0 => {
- req.defuse(); // uv callback now owns this request
- let mut cx = Ctx { slot: None, status: 0 };
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ self.set_read_timeout(timeout);
+ self.set_write_timeout(timeout);
+ }
- wait_until_woken_after(&mut cx.slot, &self.uv_loop(), || {
- req.set_data(&cx);
- });
+ fn set_read_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.read_access.set_timeout(ms, &self.home, &loop_, cancel_read,
+ &self.stream as *_ as uint);
- status_to_io_result(cx.status)
- }
- n => Err(uv_error_to_io_error(UvError(n)))
- };
+ fn cancel_read(stream: uint) -> Option<BlockedTask> {
+ let stream: &mut StreamWatcher = unsafe { cast::transmute(stream) };
+ stream.cancel_read(uvll::ECANCELED as ssize_t)
+ }
+ }
- extern fn shutdown_cb(req: *uvll::uv_shutdown_t, status: libc::c_int) {
- let req = Request::wrap(req);
- assert!(status != uvll::ECANCELED);
- let cx: &mut Ctx = unsafe { req.get_data() };
- cx.status = status;
- wakeup(&mut cx.slot);
+ fn set_write_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.write_access.set_timeout(ms, &self.home, &loop_, cancel_write,
+ &self.stream as *_ as uint);
+
+ fn cancel_write(stream: uint) -> Option<BlockedTask> {
+ let stream: &mut StreamWatcher = unsafe { cast::transmute(stream) };
+ stream.cancel_write()
}
}
}
}
fn set_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
match ms {
None => self.timeout.clear(),
Some(ms) => self.timeout.set_timeout(ms, &mut *self.listener),
// See above for what these fields are
refcount: Refcount,
- read_access: Access,
- write_access: Access,
+ read_access: AccessTimeout,
+ write_access: AccessTimeout,
+
+ blocked_sender: Option<BlockedTask>,
+}
+
+struct UdpRecvCtx {
+ task: Option<BlockedTask>,
+ buf: Option<Buf>,
+ result: Option<(ssize_t, Option<ip::SocketAddr>)>,
+}
+
+struct UdpSendCtx {
+ result: c_int,
+ data: Option<Vec<u8>>,
+ udp: *mut UdpWatcher,
}
impl UdpWatcher {
handle: unsafe { uvll::malloc_handle(uvll::UV_UDP) },
home: io.make_handle(),
refcount: Refcount::new(),
- read_access: Access::new(),
- write_access: Access::new(),
+ read_access: AccessTimeout::new(),
+ write_access: AccessTimeout::new(),
+ blocked_sender: None,
};
assert_eq!(unsafe {
uvll::uv_udp_init(io.uv_loop(), udp.handle)
fn recvfrom(&mut self, buf: &mut [u8])
-> Result<(uint, ip::SocketAddr), IoError>
{
- struct Ctx {
- task: Option<BlockedTask>,
- buf: Option<Buf>,
- result: Option<(ssize_t, Option<ip::SocketAddr>)>,
- }
let loop_ = self.uv_loop();
let m = self.fire_homing_missile();
- let _g = self.read_access.grant(m);
+ let _guard = try!(self.read_access.grant(m));
- let a = match unsafe {
+ return match unsafe {
uvll::uv_udp_recv_start(self.handle, alloc_cb, recv_cb)
} {
0 => {
- let mut cx = Ctx {
+ let mut cx = UdpRecvCtx {
task: None,
buf: Some(slice_to_uv_buf(buf)),
result: None,
}
n => Err(uv_error_to_io_error(UvError(n)))
};
- return a;
extern fn alloc_cb(handle: *uvll::uv_udp_t,
_suggested_size: size_t,
buf: *mut Buf) {
unsafe {
- let cx: &mut Ctx =
- cast::transmute(uvll::get_data_for_uv_handle(handle));
+ let cx = uvll::get_data_for_uv_handle(handle);
+ let cx = &mut *(cx as *mut UdpRecvCtx);
*buf = cx.buf.take().expect("recv alloc_cb called more than once")
}
}
extern fn recv_cb(handle: *uvll::uv_udp_t, nread: ssize_t, buf: *Buf,
addr: *libc::sockaddr, _flags: c_uint) {
assert!(nread != uvll::ECANCELED as ssize_t);
- let cx: &mut Ctx = unsafe {
- cast::transmute(uvll::get_data_for_uv_handle(handle))
+ let cx = unsafe {
+ &mut *(uvll::get_data_for_uv_handle(handle) as *mut UdpRecvCtx)
};
// When there's no data to read the recv callback can be a no-op.
return
}
- unsafe {
- assert_eq!(uvll::uv_udp_recv_stop(handle), 0)
- }
-
- let cx: &mut Ctx = unsafe {
- cast::transmute(uvll::get_data_for_uv_handle(handle))
- };
+ unsafe { assert_eq!(uvll::uv_udp_recv_stop(handle), 0) }
let addr = if addr == ptr::null() {
None
} else {
}
fn sendto(&mut self, buf: &[u8], dst: ip::SocketAddr) -> Result<(), IoError> {
- struct Ctx { task: Option<BlockedTask>, result: c_int }
-
let m = self.fire_homing_missile();
let loop_ = self.uv_loop();
- let _g = self.write_access.grant(m);
+ let guard = try!(self.write_access.grant(m));
let mut req = Request::new(uvll::UV_UDP_SEND);
- let buf = slice_to_uv_buf(buf);
let (addr, _len) = addr_to_sockaddr(dst);
- let result = unsafe {
- let addr_p = &addr as *libc::sockaddr_storage;
- uvll::uv_udp_send(req.handle, self.handle, [buf],
- addr_p as *libc::sockaddr, send_cb)
+ let addr_p = &addr as *_ as *libc::sockaddr;
+
+ // see comments in StreamWatcher::write for why we may allocate a buffer
+ // here.
+ let data = if guard.can_timeout {Some(Vec::from_slice(buf))} else {None};
+ let uv_buf = if guard.can_timeout {
+ slice_to_uv_buf(data.get_ref().as_slice())
+ } else {
+ slice_to_uv_buf(buf)
};
- return match result {
+ return match unsafe {
+ uvll::uv_udp_send(req.handle, self.handle, [uv_buf], addr_p, send_cb)
+ } {
0 => {
req.defuse(); // uv callback now owns this request
- let mut cx = Ctx { task: None, result: 0 };
- wait_until_woken_after(&mut cx.task, &loop_, || {
+ let mut cx = UdpSendCtx {
+ result: uvll::ECANCELED, data: data, udp: self as *mut _
+ };
+ wait_until_woken_after(&mut self.blocked_sender, &loop_, || {
req.set_data(&cx);
});
- match cx.result {
- 0 => Ok(()),
- n => Err(uv_error_to_io_error(UvError(n)))
+
+ if cx.result != uvll::ECANCELED {
+ return match cx.result {
+ 0 => Ok(()),
+ n => Err(uv_error_to_io_error(UvError(n)))
+ }
+ }
+ let new_cx = box UdpSendCtx {
+ result: 0,
+ udp: 0 as *mut UdpWatcher,
+ data: cx.data.take(),
+ };
+ unsafe {
+ req.set_data(&*new_cx);
+ cast::forget(new_cx);
}
+ Err(uv_error_to_io_error(UvError(cx.result)))
}
n => Err(uv_error_to_io_error(UvError(n)))
};
+ // This function is the same as stream::write_cb, but adapted for udp
+ // instead of streams.
extern fn send_cb(req: *uvll::uv_udp_send_t, status: c_int) {
let req = Request::wrap(req);
- assert!(status != uvll::ECANCELED);
- let cx: &mut Ctx = unsafe { req.get_data() };
+ let cx: &mut UdpSendCtx = unsafe { req.get_data() };
cx.result = status;
- wakeup(&mut cx.task);
+
+ if cx.udp as uint != 0 {
+ let udp: &mut UdpWatcher = unsafe { &mut *cx.udp };
+ wakeup(&mut udp.blocked_sender);
+ } else {
+ let _cx: Box<UdpSendCtx> = unsafe { cast::transmute(cx) };
+ }
}
}
refcount: self.refcount.clone(),
write_access: self.write_access.clone(),
read_access: self.read_access.clone(),
+ blocked_sender: None,
} as Box<rtio::RtioUdpSocket:Send>
}
+
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ self.set_read_timeout(timeout);
+ self.set_write_timeout(timeout);
+ }
+
+ fn set_read_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.read_access.set_timeout(ms, &self.home, &loop_, cancel_read,
+ self.handle as uint);
+
+ fn cancel_read(stream: uint) -> Option<BlockedTask> {
+ // This method is quite similar to StreamWatcher::cancel_read, see
+ // there for more information
+ let handle = stream as *uvll::uv_udp_t;
+ assert_eq!(unsafe { uvll::uv_udp_recv_stop(handle) }, 0);
+ let data = unsafe {
+ let data = uvll::get_data_for_uv_handle(handle);
+ if data.is_null() { return None }
+ uvll::set_data_for_uv_handle(handle, 0 as *int);
+ &mut *(data as *mut UdpRecvCtx)
+ };
+ data.result = Some((uvll::ECANCELED as ssize_t, None));
+ data.task.take()
+ }
+ }
+
+ fn set_write_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.write_access.set_timeout(ms, &self.home, &loop_, cancel_write,
+ self as *mut _ as uint);
+
+ fn cancel_write(stream: uint) -> Option<BlockedTask> {
+ let stream: &mut UdpWatcher = unsafe { cast::transmute(stream) };
+ stream.blocked_sender.take()
+ }
+ }
}
impl Drop for UdpWatcher {
}
}
+////////////////////////////////////////////////////////////////////////////////
+// Shutdown helper
+////////////////////////////////////////////////////////////////////////////////
+
+pub fn shutdown(handle: *uvll::uv_stream_t, loop_: &Loop) -> Result<(), IoError> {
+ struct Ctx {
+ slot: Option<BlockedTask>,
+ status: c_int,
+ }
+ let mut req = Request::new(uvll::UV_SHUTDOWN);
+
+ return match unsafe { uvll::uv_shutdown(req.handle, handle, shutdown_cb) } {
+ 0 => {
+ req.defuse(); // uv callback now owns this request
+ let mut cx = Ctx { slot: None, status: 0 };
+
+ wait_until_woken_after(&mut cx.slot, loop_, || {
+ req.set_data(&cx);
+ });
+
+ status_to_io_result(cx.status)
+ }
+ n => Err(uv_error_to_io_error(UvError(n)))
+ };
+
+ extern fn shutdown_cb(req: *uvll::uv_shutdown_t, status: libc::c_int) {
+ let req = Request::wrap(req);
+ assert!(status != uvll::ECANCELED);
+ let cx: &mut Ctx = unsafe { req.get_data() };
+ cx.status = status;
+ wakeup(&mut cx.slot);
+ }
+}
+
#[cfg(test)]
mod test {
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioTcpAcceptor,
use libc;
use std::c_str::CString;
+use std::cast;
use std::io::IoError;
+use std::io;
use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor};
+use std::rt::task::BlockedTask;
-use access::Access;
use homing::{HomingIO, HomeHandle};
use net;
use rc::Refcount;
use stream::StreamWatcher;
use super::{Loop, UvError, UvHandle, uv_error_to_io_error};
+use timeout::{AcceptTimeout, ConnectCtx, AccessTimeout};
use uvio::UvIoFactory;
use uvll;
refcount: Refcount,
// see comments in TcpWatcher for why these exist
- write_access: Access,
- read_access: Access,
+ write_access: AccessTimeout,
+ read_access: AccessTimeout,
}
pub struct PipeListener {
pub struct PipeAcceptor {
listener: Box<PipeListener>,
- timeout: net::AcceptTimeout,
+ timeout: AcceptTimeout,
}
// PipeWatcher implementation and traits
home: home,
defused: false,
refcount: Refcount::new(),
- read_access: Access::new(),
- write_access: Access::new(),
+ read_access: AccessTimeout::new(),
+ write_access: AccessTimeout::new(),
}
}
-> Result<PipeWatcher, UvError>
{
let pipe = PipeWatcher::new(io, false);
- let cx = net::ConnectCtx { status: -1, task: None, timer: None };
+ let cx = ConnectCtx { status: -1, task: None, timer: None };
cx.connect(pipe, timeout, io, |req, pipe, cb| {
unsafe {
uvll::uv_pipe_connect(req.handle, pipe.handle(),
impl RtioPipe for PipeWatcher {
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
let m = self.fire_homing_missile();
- let _g = self.read_access.grant(m);
+ let guard = try!(self.read_access.grant(m));
+
+ // see comments in close_read about this check
+ if guard.access.is_closed() {
+ return Err(io::standard_error(io::EndOfFile))
+ }
+
self.stream.read(buf).map_err(uv_error_to_io_error)
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
let m = self.fire_homing_missile();
- let _g = self.write_access.grant(m);
- self.stream.write(buf).map_err(uv_error_to_io_error)
+ let guard = try!(self.write_access.grant(m));
+ self.stream.write(buf, guard.can_timeout).map_err(uv_error_to_io_error)
}
fn clone(&self) -> Box<RtioPipe:Send> {
write_access: self.write_access.clone(),
} as Box<RtioPipe:Send>
}
+
+ fn close_read(&mut self) -> Result<(), IoError> {
+ // The current uv_shutdown method only shuts the writing half of the
+ // connection, and no method is provided to shut down the reading half
+ // of the connection. With a lack of method, we emulate shutting down
+ // the reading half of the connection by manually returning early from
+ // all future calls to `read`.
+ //
+ // Note that we must be careful to ensure that *all* cloned handles see
+ // the closing of the read half, so we stored the "is closed" bit in the
+ // Access struct, not in our own personal watcher. Additionally, the
+ // homing missile is used as a locking mechanism to ensure there is no
+ // contention over this bit.
+ //
+ // To shutdown the read half, we must first flag the access as being
+ // closed, and then afterwards we cease any pending read. Note that this
+ // ordering is crucial because we could in theory be rescheduled during
+ // the uv_read_stop which means that another read invocation could leak
+ // in before we set the flag.
+ let task = {
+ let m = self.fire_homing_missile();
+ self.read_access.access.close(&m);
+ self.stream.cancel_read(uvll::EOF as libc::ssize_t)
+ };
+ let _ = task.map(|t| t.reawaken());
+ Ok(())
+ }
+
+ fn close_write(&mut self) -> Result<(), IoError> {
+ let _m = self.fire_homing_missile();
+ net::shutdown(self.stream.handle, &self.uv_loop())
+ }
+
+ fn set_timeout(&mut self, timeout: Option<u64>) {
+ self.set_read_timeout(timeout);
+ self.set_write_timeout(timeout);
+ }
+
+ fn set_read_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.read_access.set_timeout(ms, &self.home, &loop_, cancel_read,
+ &self.stream as *_ as uint);
+
+ fn cancel_read(stream: uint) -> Option<BlockedTask> {
+ let stream: &mut StreamWatcher = unsafe { cast::transmute(stream) };
+ stream.cancel_read(uvll::ECANCELED as libc::ssize_t)
+ }
+ }
+
+ fn set_write_timeout(&mut self, ms: Option<u64>) {
+ let _m = self.fire_homing_missile();
+ let loop_ = self.uv_loop();
+ self.write_access.set_timeout(ms, &self.home, &loop_, cancel_write,
+ &self.stream as *_ as uint);
+
+ fn cancel_write(stream: uint) -> Option<BlockedTask> {
+ let stream: &mut StreamWatcher = unsafe { cast::transmute(stream) };
+ stream.cancel_write()
+ }
+ }
}
impl HomingIO for PipeWatcher {
// create the acceptor object from ourselves
let mut acceptor = box PipeAcceptor {
listener: self,
- timeout: net::AcceptTimeout::new(),
+ timeout: AcceptTimeout::new(),
};
let _m = acceptor.fire_homing_missile();
/// Returns either the corresponding process object or an error which
/// occurred.
pub fn spawn(io_loop: &mut UvIoFactory, config: process::ProcessConfig)
- -> Result<(Box<Process>, ~[Option<PipeWatcher>]), UvError> {
+ -> Result<(Box<Process>, Vec<Option<PipeWatcher>>), UvError>
+ {
let cwd = config.cwd.map(|s| s.to_c_str());
let mut io = vec![config.stdin, config.stdout, config.stderr];
for slot in config.extra_io.iter() {
});
match ret {
- Ok(p) => Ok((p, ret_io.move_iter().collect())),
+ Ok(p) => Ok((p, ret_io)),
Err(e) => Err(e),
}
}
// structure, but currently we don't have mappings for all the structures
// defined in libuv, so we're foced to malloc this.
last_write_req: Option<Request>,
+
+ blocked_writer: Option<BlockedTask>,
}
struct ReadContext {
struct WriteContext {
result: c_int,
- task: Option<BlockedTask>,
+ stream: *mut StreamWatcher,
+ data: Option<Vec<u8>>,
}
impl StreamWatcher {
// Wrappers should ensure to always reset the field to an appropriate value
// if they rely on the field to perform an action.
pub fn new(stream: *uvll::uv_stream_t) -> StreamWatcher {
+ unsafe { uvll::set_data_for_uv_handle(stream, 0 as *int) }
StreamWatcher {
handle: stream,
last_write_req: None,
+ blocked_writer: None,
}
}
let mut rcx = ReadContext {
buf: Some(slice_to_uv_buf(buf)),
+ // if the read is canceled, we'll see eof, otherwise this will get
+ // overwritten
result: 0,
task: None,
};
// we must be ready for this to happen (by setting the data in the uv
// handle). In theory this otherwise doesn't need to happen until after
// the read is succesfully started.
- unsafe {
- uvll::set_data_for_uv_handle(self.handle, &rcx)
- }
+ unsafe { uvll::set_data_for_uv_handle(self.handle, &rcx) }
// Send off the read request, but don't block until we're sure that the
// read request is queued.
- match unsafe {
+ let ret = match unsafe {
uvll::uv_read_start(self.handle, alloc_cb, read_cb)
} {
0 => {
}
}
n => Err(UvError(n))
- }
+ };
+ // Make sure a read cancellation sees that there's no pending read
+ unsafe { uvll::set_data_for_uv_handle(self.handle, 0 as *int) }
+ return ret;
+ }
+
+ pub fn cancel_read(&mut self, reason: ssize_t) -> Option<BlockedTask> {
+ // When we invoke uv_read_stop, it cancels the read and alloc
+ // callbacks. We need to manually wake up a pending task (if one was
+ // present).
+ assert_eq!(unsafe { uvll::uv_read_stop(self.handle) }, 0);
+ let data = unsafe {
+ let data = uvll::get_data_for_uv_handle(self.handle);
+ if data.is_null() { return None }
+ uvll::set_data_for_uv_handle(self.handle, 0 as *int);
+ &mut *(data as *mut ReadContext)
+ };
+ data.result = reason;
+ data.task.take()
}
- pub fn write(&mut self, buf: &[u8]) -> Result<(), UvError> {
+ pub fn write(&mut self, buf: &[u8], may_timeout: bool) -> Result<(), UvError> {
// The ownership of the write request is dubious if this function
// unwinds. I believe that if the write_cb fails to re-schedule the task
// then the write request will be leaked.
};
req.set_data(ptr::null::<()>());
+ // And here's where timeouts get a little interesting. Currently, libuv
+ // does not support canceling an in-flight write request. Consequently,
+ // when a write timeout expires, there's not much we can do other than
+ // detach the sleeping task from the write request itself. Semantically,
+ // this means that the write request will complete asynchronously, but
+ // the calling task will return error (because the write timed out).
+ //
+ // There is special wording in the documentation of set_write_timeout()
+ // indicating that this is a plausible failure scenario, and this
+ // function is why that wording exists.
+ //
+ // Implementation-wise, we must be careful when passing a buffer down to
+ // libuv. Most of this implementation avoids allocations becuase of the
+ // blocking guarantee (all stack local variables are valid for the
+ // entire read/write request). If our write request can be timed out,
+ // however, we must heap allocate the data and pass that to the libuv
+ // functions instead. The reason for this is that if we time out and
+ // return, there's no guarantee that `buf` is a valid buffer any more.
+ //
+ // To do this, the write context has an optionally owned vector of
+ // bytes.
+ let data = if may_timeout {Some(Vec::from_slice(buf))} else {None};
+ let uv_buf = if may_timeout {
+ slice_to_uv_buf(data.get_ref().as_slice())
+ } else {
+ slice_to_uv_buf(buf)
+ };
+
// Send off the request, but be careful to not block until we're sure
// that the write reqeust is queued. If the reqeust couldn't be queued,
// then we should return immediately with an error.
match unsafe {
- uvll::uv_write(req.handle, self.handle, [slice_to_uv_buf(buf)],
- write_cb)
+ uvll::uv_write(req.handle, self.handle, [uv_buf], write_cb)
} {
0 => {
- let mut wcx = WriteContext { result: 0, task: None, };
+ let mut wcx = WriteContext {
+ result: uvll::ECANCELED,
+ stream: self as *mut _,
+ data: data,
+ };
req.defuse(); // uv callback now owns this request
let loop_ = unsafe { uvll::get_loop_for_uv_handle(self.handle) };
- wait_until_woken_after(&mut wcx.task, &Loop::wrap(loop_), || {
+ wait_until_woken_after(&mut self.blocked_writer,
+ &Loop::wrap(loop_), || {
req.set_data(&wcx);
});
- self.last_write_req = Some(Request::wrap(req.handle));
- match wcx.result {
- 0 => Ok(()),
- n => Err(UvError(n)),
+
+ if wcx.result != uvll::ECANCELED {
+ self.last_write_req = Some(Request::wrap(req.handle));
+ return match wcx.result {
+ 0 => Ok(()),
+ n => Err(UvError(n)),
+ }
+ }
+
+ // This is the second case where canceling an in-flight write
+ // gets interesting. If we've been canceled (no one reset our
+ // result), then someone still needs to free the request, and
+ // someone still needs to free the allocate buffer.
+ //
+ // To take care of this, we swap out the stack-allocated write
+ // context for a heap-allocated context, transferring ownership
+ // of everything to the write_cb. Libuv guarantees that this
+ // callback will be invoked at some point, and the callback will
+ // be responsible for deallocating these resources.
+ //
+ // Note that we don't cache this write request back in the
+ // stream watcher because we no longer have ownership of it, and
+ // we never will.
+ let new_wcx = box WriteContext {
+ result: 0,
+ stream: 0 as *mut StreamWatcher,
+ data: wcx.data.take(),
+ };
+ unsafe {
+ req.set_data(&*new_wcx);
+ cast::forget(new_wcx);
}
+ Err(UvError(wcx.result))
}
n => Err(UvError(n)),
}
}
+
+ pub fn cancel_write(&mut self) -> Option<BlockedTask> {
+ self.blocked_writer.take()
+ }
}
// This allocation callback expects to be invoked once and only once. It will
// away the error code as a result.
extern fn write_cb(req: *uvll::uv_write_t, status: c_int) {
let mut req = Request::wrap(req);
- assert!(status != uvll::ECANCELED);
// Remember to not free the request because it is re-used between writes on
// the same stream.
let wcx: &mut WriteContext = unsafe { req.get_data() };
wcx.result = status;
- req.defuse();
- wakeup(&mut wcx.task);
+ // If the stream is present, we haven't timed out, otherwise we acquire
+ // ownership of everything and then deallocate it all at once.
+ if wcx.stream as uint != 0 {
+ req.defuse();
+ let stream: &mut StreamWatcher = unsafe { &mut *wcx.stream };
+ wakeup(&mut stream.blocked_writer);
+ } else {
+ let _wcx: Box<WriteContext> = unsafe { cast::transmute(wcx) };
+ }
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use libc::c_int;
+use std::cast;
+use std::io::IoResult;
+use std::mem;
+use std::rt::task::BlockedTask;
+
+use access;
+use homing::{HomeHandle, HomingMissile, HomingIO};
+use timer::TimerWatcher;
+use uvll;
+use uvio::UvIoFactory;
+use {Loop, UvError, uv_error_to_io_error, Request, wakeup};
+use {UvHandle, wait_until_woken_after};
+
+/// Managment of a timeout when gaining access to a portion of a duplex stream.
+pub struct AccessTimeout {
+ state: TimeoutState,
+ timer: Option<Box<TimerWatcher>>,
+ pub access: access::Access,
+}
+
+pub struct Guard<'a> {
+ state: &'a mut TimeoutState,
+ pub access: access::Guard<'a>,
+ pub can_timeout: bool,
+}
+
+#[deriving(Eq)]
+enum TimeoutState {
+ NoTimeout,
+ TimeoutPending(ClientState),
+ TimedOut,
+}
+
+#[deriving(Eq)]
+enum ClientState {
+ NoWaiter,
+ AccessPending,
+ RequestPending,
+}
+
+struct TimerContext {
+ timeout: *mut AccessTimeout,
+ callback: fn(uint) -> Option<BlockedTask>,
+ payload: uint,
+}
+
+impl AccessTimeout {
+ pub fn new() -> AccessTimeout {
+ AccessTimeout {
+ state: NoTimeout,
+ timer: None,
+ access: access::Access::new(),
+ }
+ }
+
+ /// Grants access to half of a duplex stream, timing out if necessary.
+ ///
+ /// On success, Ok(Guard) is returned and access has been granted to the
+ /// stream. If a timeout occurs, then Err is returned with an appropriate
+ /// error.
+ pub fn grant<'a>(&'a mut self, m: HomingMissile) -> IoResult<Guard<'a>> {
+ // First, flag that we're attempting to acquire access. This will allow
+ // us to cancel the pending grant if we timeout out while waiting for a
+ // grant.
+ match self.state {
+ NoTimeout => {},
+ TimeoutPending(ref mut client) => *client = AccessPending,
+ TimedOut => return Err(uv_error_to_io_error(UvError(uvll::ECANCELED)))
+ }
+ let access = self.access.grant(self as *mut _ as uint, m);
+
+ // After acquiring the grant, we need to flag ourselves as having a
+ // pending request so the timeout knows to cancel the request.
+ let can_timeout = match self.state {
+ NoTimeout => false,
+ TimeoutPending(ref mut client) => { *client = RequestPending; true }
+ TimedOut => return Err(uv_error_to_io_error(UvError(uvll::ECANCELED)))
+ };
+
+ Ok(Guard {
+ access: access,
+ state: &mut self.state,
+ can_timeout: can_timeout
+ })
+ }
+
+ /// Sets the pending timeout to the value specified.
+ ///
+ /// The home/loop variables are used to construct a timer if one has not
+ /// been previously constructed.
+ ///
+ /// The callback will be invoked if the timeout elapses, and the data of
+ /// the time will be set to `data`.
+ pub fn set_timeout(&mut self, ms: Option<u64>,
+ home: &HomeHandle,
+ loop_: &Loop,
+ cb: fn(uint) -> Option<BlockedTask>,
+ data: uint) {
+ self.state = NoTimeout;
+ let ms = match ms {
+ Some(ms) => ms,
+ None => return match self.timer {
+ Some(ref mut t) => t.stop(),
+ None => {}
+ }
+ };
+
+ // If we have a timeout, lazily initialize the timer which will be used
+ // to fire when the timeout runs out.
+ if self.timer.is_none() {
+ let mut timer = box TimerWatcher::new_home(loop_, home.clone());
+ let cx = box TimerContext {
+ timeout: self as *mut _,
+ callback: cb,
+ payload: data,
+ };
+ unsafe {
+ timer.set_data(&*cx);
+ cast::forget(cx);
+ }
+ self.timer = Some(timer);
+ }
+
+ let timer = self.timer.get_mut_ref();
+ unsafe {
+ let cx = uvll::get_data_for_uv_handle(timer.handle);
+ let cx = cx as *mut TimerContext;
+ (*cx).callback = cb;
+ (*cx).payload = data;
+ }
+ timer.stop();
+ timer.start(timer_cb, ms, 0);
+ self.state = TimeoutPending(NoWaiter);
+
+ extern fn timer_cb(timer: *uvll::uv_timer_t) {
+ let cx: &TimerContext = unsafe {
+ &*(uvll::get_data_for_uv_handle(timer) as *TimerContext)
+ };
+ let me = unsafe { &mut *cx.timeout };
+
+ match mem::replace(&mut me.state, TimedOut) {
+ TimedOut | NoTimeout => unreachable!(),
+ TimeoutPending(NoWaiter) => {}
+ TimeoutPending(AccessPending) => {
+ match unsafe { me.access.dequeue(me as *mut _ as uint) } {
+ Some(task) => task.reawaken(),
+ None => unreachable!(),
+ }
+ }
+ TimeoutPending(RequestPending) => {
+ match (cx.callback)(cx.payload) {
+ Some(task) => task.reawaken(),
+ None => unreachable!(),
+ }
+ }
+ }
+ }
+ }
+}
+
+impl Clone for AccessTimeout {
+ fn clone(&self) -> AccessTimeout {
+ AccessTimeout {
+ access: self.access.clone(),
+ state: NoTimeout,
+ timer: None,
+ }
+ }
+}
+
+#[unsafe_destructor]
+impl<'a> Drop for Guard<'a> {
+ fn drop(&mut self) {
+ match *self.state {
+ TimeoutPending(NoWaiter) | TimeoutPending(AccessPending) =>
+ unreachable!(),
+
+ NoTimeout | TimedOut => {}
+ TimeoutPending(RequestPending) => {
+ *self.state = TimeoutPending(NoWaiter);
+ }
+ }
+ }
+}
+
+impl Drop for AccessTimeout {
+ fn drop(&mut self) {
+ match self.timer {
+ Some(ref timer) => unsafe {
+ let data = uvll::get_data_for_uv_handle(timer.handle);
+ let _data: Box<TimerContext> = cast::transmute(data);
+ },
+ None => {}
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Connect timeouts
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct ConnectCtx {
+ pub status: c_int,
+ pub task: Option<BlockedTask>,
+ pub timer: Option<Box<TimerWatcher>>,
+}
+
+pub struct AcceptTimeout {
+ timer: Option<TimerWatcher>,
+ timeout_tx: Option<Sender<()>>,
+ timeout_rx: Option<Receiver<()>>,
+}
+
+impl ConnectCtx {
+ pub fn connect<T>(
+ mut self, obj: T, timeout: Option<u64>, io: &mut UvIoFactory,
+ f: |&Request, &T, uvll::uv_connect_cb| -> c_int
+ ) -> Result<T, UvError> {
+ let mut req = Request::new(uvll::UV_CONNECT);
+ let r = f(&req, &obj, connect_cb);
+ return match r {
+ 0 => {
+ req.defuse(); // uv callback now owns this request
+ match timeout {
+ Some(t) => {
+ let mut timer = TimerWatcher::new(io);
+ timer.start(timer_cb, t, 0);
+ self.timer = Some(timer);
+ }
+ None => {}
+ }
+ wait_until_woken_after(&mut self.task, &io.loop_, || {
+ let data = &self as *_;
+ match self.timer {
+ Some(ref mut timer) => unsafe { timer.set_data(data) },
+ None => {}
+ }
+ req.set_data(data);
+ });
+ // Make sure an erroneously fired callback doesn't have access
+ // to the context any more.
+ req.set_data(0 as *int);
+
+ // If we failed because of a timeout, drop the TcpWatcher as
+ // soon as possible because it's data is now set to null and we
+ // want to cancel the callback ASAP.
+ match self.status {
+ 0 => Ok(obj),
+ n => { drop(obj); Err(UvError(n)) }
+ }
+ }
+ n => Err(UvError(n))
+ };
+
+ extern fn timer_cb(handle: *uvll::uv_timer_t) {
+ // Don't close the corresponding tcp request, just wake up the task
+ // and let RAII take care of the pending watcher.
+ let cx: &mut ConnectCtx = unsafe {
+ &mut *(uvll::get_data_for_uv_handle(handle) as *mut ConnectCtx)
+ };
+ cx.status = uvll::ECANCELED;
+ wakeup(&mut cx.task);
+ }
+
+ extern fn connect_cb(req: *uvll::uv_connect_t, status: c_int) {
+ // This callback can be invoked with ECANCELED if the watcher is
+ // closed by the timeout callback. In that case we just want to free
+ // the request and be along our merry way.
+ let req = Request::wrap(req);
+ if status == uvll::ECANCELED { return }
+
+ // Apparently on windows when the handle is closed this callback may
+ // not be invoked with ECANCELED but rather another error code.
+ // Either ways, if the data is null, then our timeout has expired
+ // and there's nothing we can do.
+ let data = unsafe { uvll::get_data_for_req(req.handle) };
+ if data.is_null() { return }
+
+ let cx: &mut ConnectCtx = unsafe { &mut *(data as *mut ConnectCtx) };
+ cx.status = status;
+ match cx.timer {
+ Some(ref mut t) => t.stop(),
+ None => {}
+ }
+ // Note that the timer callback doesn't cancel the connect request
+ // (that's the job of uv_close()), so it's possible for this
+ // callback to get triggered after the timeout callback fires, but
+ // before the task wakes up. In that case, we did indeed
+ // successfully connect, but we don't need to wake someone up. We
+ // updated the status above (correctly so), and the task will pick
+ // up on this when it wakes up.
+ if cx.task.is_some() {
+ wakeup(&mut cx.task);
+ }
+ }
+ }
+}
+
+impl AcceptTimeout {
+ pub fn new() -> AcceptTimeout {
+ AcceptTimeout { timer: None, timeout_tx: None, timeout_rx: None }
+ }
+
+ pub fn accept<T: Send>(&mut self, c: &Receiver<IoResult<T>>) -> IoResult<T> {
+ match self.timeout_rx {
+ None => c.recv(),
+ Some(ref rx) => {
+ use std::comm::Select;
+
+ // Poll the incoming channel first (don't rely on the order of
+ // select just yet). If someone's pending then we should return
+ // them immediately.
+ match c.try_recv() {
+ Ok(data) => return data,
+ Err(..) => {}
+ }
+
+ // Use select to figure out which channel gets ready first. We
+ // do some custom handling of select to ensure that we never
+ // actually drain the timeout channel (we'll keep seeing the
+ // timeout message in the future).
+ let s = Select::new();
+ let mut timeout = s.handle(rx);
+ let mut data = s.handle(c);
+ unsafe {
+ timeout.add();
+ data.add();
+ }
+ if s.wait() == timeout.id() {
+ Err(uv_error_to_io_error(UvError(uvll::ECANCELED)))
+ } else {
+ c.recv()
+ }
+ }
+ }
+ }
+
+ pub fn clear(&mut self) {
+ match self.timeout_rx {
+ Some(ref t) => { let _ = t.try_recv(); }
+ None => {}
+ }
+ match self.timer {
+ Some(ref mut t) => t.stop(),
+ None => {}
+ }
+ }
+
+ pub fn set_timeout<U, T: UvHandle<U> + HomingIO>(
+ &mut self, ms: u64, t: &mut T
+ ) {
+ // If we have a timeout, lazily initialize the timer which will be used
+ // to fire when the timeout runs out.
+ if self.timer.is_none() {
+ let loop_ = Loop::wrap(unsafe {
+ uvll::get_loop_for_uv_handle(t.uv_handle())
+ });
+ let mut timer = TimerWatcher::new_home(&loop_, t.home().clone());
+ unsafe {
+ timer.set_data(self as *mut _ as *AcceptTimeout);
+ }
+ self.timer = Some(timer);
+ }
+
+ // Once we've got a timer, stop any previous timeout, reset it for the
+ // current one, and install some new channels to send/receive data on
+ let timer = self.timer.get_mut_ref();
+ timer.stop();
+ timer.start(timer_cb, ms, 0);
+ let (tx, rx) = channel();
+ self.timeout_tx = Some(tx);
+ self.timeout_rx = Some(rx);
+
+ extern fn timer_cb(timer: *uvll::uv_timer_t) {
+ let acceptor: &mut AcceptTimeout = unsafe {
+ &mut *(uvll::get_data_for_uv_handle(timer) as *mut AcceptTimeout)
+ };
+ // This send can never fail because if this timer is active then the
+ // receiving channel is guaranteed to be alive
+ acceptor.timeout_tx.get_ref().send(());
+ }
+ }
+}
use uvll;
pub struct TimerWatcher {
- handle: *uvll::uv_timer_t,
+ pub handle: *uvll::uv_timer_t,
home: HomeHandle,
action: Option<NextAction>,
blocker: Option<BlockedTask>,
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
let _m = self.fire_homing_missile();
- self.stream.write(buf).map_err(uv_error_to_io_error)
+ self.stream.write(buf, false).map_err(uv_error_to_io_error)
}
fn set_raw(&mut self, raw: bool) -> Result<(), IoError> {
}
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
- hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
+ hint: Option<ai::Hint>) -> Result<Vec<ai::Info>, IoError> {
let r = GetAddrInfoRequest::run(&self.loop_, host, servname, hint);
r.map_err(uv_error_to_io_error)
}
fn spawn(&mut self, config: ProcessConfig)
-> Result<(Box<rtio::RtioProcess:Send>,
- ~[Option<Box<rtio::RtioPipe:Send>>]),
+ Vec<Option<Box<rtio::RtioPipe:Send>>>),
IoError>
{
match Process::spawn(self, config) {
}
unsafe {
- str::raw::from_utf8_owned(v.move_iter().collect())
+ str::raw::from_utf8(v.as_slice()).to_owned()
}
}
}
pub trait FromBase64 {
/// Converts the value of `self`, interpreted as base64 encoded data, into
/// an owned vector of bytes, returning the vector.
- fn from_base64(&self) -> Result<~[u8], FromBase64Error>;
+ fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error>;
}
/// Errors that can occur when decoding a base64 encoded string
* ```rust
* extern crate serialize;
* use serialize::base64::{ToBase64, FromBase64, STANDARD};
- * use std::str;
*
* fn main () {
* let hello_str = bytes!("Hello, World").to_base64(STANDARD);
* println!("base64 output: {}", hello_str);
* let res = hello_str.from_base64();
* if res.is_ok() {
- * let opt_bytes = str::from_utf8_owned(res.unwrap());
+ * let opt_bytes = StrBuf::from_utf8(res.unwrap());
* if opt_bytes.is_some() {
* println!("decoded from base64: {}", opt_bytes.unwrap());
* }
* }
* ```
*/
- fn from_base64(&self) -> Result<~[u8], FromBase64Error> {
+ fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
let mut r = Vec::new();
let mut buf: u32 = 0;
let mut modulus = 0;
_ => return Err(InvalidBase64Length),
}
- Ok(r.move_iter().collect())
+ Ok(r)
}
}
#[test]
fn test_from_base64_basic() {
- assert_eq!("".from_base64().unwrap(), "".as_bytes().to_owned());
- assert_eq!("Zg==".from_base64().unwrap(), "f".as_bytes().to_owned());
- assert_eq!("Zm8=".from_base64().unwrap(), "fo".as_bytes().to_owned());
- assert_eq!("Zm9v".from_base64().unwrap(), "foo".as_bytes().to_owned());
- assert_eq!("Zm9vYg==".from_base64().unwrap(), "foob".as_bytes().to_owned());
- assert_eq!("Zm9vYmE=".from_base64().unwrap(), "fooba".as_bytes().to_owned());
- assert_eq!("Zm9vYmFy".from_base64().unwrap(), "foobar".as_bytes().to_owned());
+ assert_eq!("".from_base64().unwrap().as_slice(), "".as_bytes());
+ assert_eq!("Zg==".from_base64().unwrap().as_slice(), "f".as_bytes());
+ assert_eq!("Zm8=".from_base64().unwrap().as_slice(), "fo".as_bytes());
+ assert_eq!("Zm9v".from_base64().unwrap().as_slice(), "foo".as_bytes());
+ assert_eq!("Zm9vYg==".from_base64().unwrap().as_slice(), "foob".as_bytes());
+ assert_eq!("Zm9vYmE=".from_base64().unwrap().as_slice(), "fooba".as_bytes());
+ assert_eq!("Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
}
#[test]
fn test_from_base64_newlines() {
- assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
- "foobar".as_bytes().to_owned());
- assert_eq!("Zm9vYg==\r\n".from_base64().unwrap(),
- "foob".as_bytes().to_owned());
+ assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap().as_slice(),
+ "foobar".as_bytes());
+ assert_eq!("Zm9vYg==\r\n".from_base64().unwrap().as_slice(),
+ "foob".as_bytes());
}
#[test]
for _ in range(0, 1000) {
let times = task_rng().gen_range(1u, 100);
let v = Vec::from_fn(times, |_| random::<u8>());
- assert_eq!(v.as_slice().to_base64(STANDARD).from_base64().unwrap(),
- v.as_slice().to_owned());
+ assert_eq!(v.as_slice().to_base64(STANDARD).from_base64().unwrap().as_slice(),
+ v.as_slice());
}
}
}
unsafe {
- str::raw::from_utf8_owned(v.move_iter().collect())
+ str::raw::from_utf8(v.as_slice()).to_owned()
}
}
}
pub trait FromHex {
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
/// into an owned vector of bytes, returning the vector.
- fn from_hex(&self) -> Result<~[u8], FromHexError>;
+ fn from_hex(&self) -> Result<Vec<u8>, FromHexError>;
}
/// Errors that can occur when decoding a hex encoded string
* ```rust
* extern crate serialize;
* use serialize::hex::{FromHex, ToHex};
- * use std::str;
*
* fn main () {
* let hello_str = "Hello, World".as_bytes().to_hex();
* println!("{}", hello_str);
* let bytes = hello_str.from_hex().unwrap();
* println!("{:?}", bytes);
- * let result_str = str::from_utf8_owned(bytes).unwrap();
+ * let result_str = StrBuf::from_utf8(bytes).unwrap();
* println!("{}", result_str);
* }
* ```
*/
- fn from_hex(&self) -> Result<~[u8], FromHexError> {
+ fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
// This may be an overestimate if there is any whitespace
let mut b = Vec::with_capacity(self.len() / 2);
let mut modulus = 0;
#[test]
pub fn test_from_hex_okay() {
- assert_eq!("666f6f626172".from_hex().unwrap(),
- "foobar".as_bytes().to_owned());
- assert_eq!("666F6F626172".from_hex().unwrap(),
- "foobar".as_bytes().to_owned());
+ assert_eq!("666f6f626172".from_hex().unwrap().as_slice(),
+ "foobar".as_bytes());
+ assert_eq!("666F6F626172".from_hex().unwrap().as_slice(),
+ "foobar".as_bytes());
}
#[test]
#[test]
pub fn test_from_hex_ignores_whitespace() {
- assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(),
- "foobar".as_bytes().to_owned());
+ assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap().as_slice(),
+ "foobar".as_bytes());
}
#[test]
#[test]
pub fn test_from_hex_all_bytes() {
for i in range(0, 256) {
- assert_eq!(format!("{:02x}", i as uint).from_hex().unwrap(), ~[i as u8]);
- assert_eq!(format!("{:02X}", i as uint).from_hex().unwrap(), ~[i as u8]);
+ assert_eq!(format!("{:02x}", i as uint).from_hex().unwrap().as_slice(), &[i as u8]);
+ assert_eq!(format!("{:02X}", i as uint).from_hex().unwrap().as_slice(), &[i as u8]);
}
}
pub struct TestStruct1 {
data_int: u8,
data_str: ~str,
- data_vector: ~[u8],
+ data_vector: Vec<u8>,
}
// To serialize use the `json::str_encode` to encode an object in a string.
// It calls the generated `Encodable` impl.
fn main() {
let to_encode_object = TestStruct1
- {data_int: 1, data_str:"toto".to_owned(), data_vector:~[2,3,4,5]};
+ {data_int: 1, data_str:"toto".to_owned(), data_vector:vec![2,3,4,5]};
let encoded_str: ~str = json::Encoder::str_encode(&to_encode_object);
// To deserialize use the `json::from_str` and `json::Decoder`
pub struct TestStruct1 {
data_int: u8,
data_str: ~str,
- data_vector: ~[u8],
+ data_vector: Vec<u8>,
}
impl ToJson for TestStruct1 {
// Serialization using our impl of to_json
let test2: TestStruct1 = TestStruct1 {data_int: 1, data_str:"toto".to_owned(),
- data_vector:~[2,3,4,5]};
+ data_vector:vec![2,3,4,5]};
let tjson: json::Json = test2.to_json();
let json_str: ~str = tjson.to_str();
Null,
}
-pub type List = ~[Json];
+pub type List = Vec<Json>;
pub type Object = TreeMap<~str, Json>;
/// The errors that can arise while parsing a JSON stream.
fn to_json(&self) -> Json {
match *self {
(ref a, ref b) => {
- List(box [a.to_json(), b.to_json()])
+ List(vec![a.to_json(), b.to_json()])
}
}
}
fn to_json(&self) -> Json {
match *self {
(ref a, ref b, ref c) => {
- List(box [a.to_json(), b.to_json(), c.to_json()])
+ List(vec![a.to_json(), b.to_json(), c.to_json()])
}
}
}
struct Inner {
a: (),
b: uint,
- c: ~[~str],
+ c: Vec<~str>,
}
#[deriving(Eq, Encodable, Decodable, Show)]
struct Outer {
- inner: ~[Inner],
+ inner: Vec<Inner>,
}
fn mk_object(items: &[(~str, Json)]) -> Json {
#[test]
fn test_write_list() {
- assert_eq!(List(~[]).to_str(), "[]".to_owned());
- assert_eq!(List(~[]).to_pretty_str(), "[]".to_owned());
+ assert_eq!(List(vec![]).to_str(), "[]".to_owned());
+ assert_eq!(List(vec![]).to_pretty_str(), "[]".to_owned());
- assert_eq!(List(~[Boolean(true)]).to_str(), "[true]".to_owned());
+ assert_eq!(List(vec![Boolean(true)]).to_str(), "[true]".to_owned());
assert_eq!(
- List(~[Boolean(true)]).to_pretty_str(),
+ List(vec![Boolean(true)]).to_pretty_str(),
"\
[\n \
true\n\
]".to_owned()
);
- let long_test_list = List(box [
+ let long_test_list = List(vec![
Boolean(false),
Null,
- List(box [String("foo\nbar".to_owned()), Number(3.5)])]);
+ List(vec![String("foo\nbar".to_owned()), Number(3.5)])]);
assert_eq!(long_test_list.to_str(),
"[false,null,[\"foo\\nbar\",3.5]]".to_owned());
);
let complex_obj = mk_object([
- ("b".to_owned(), List(box [
+ ("b".to_owned(), List(vec![
mk_object([("c".to_owned(), String("\x0c\r".to_owned()))]),
mk_object([("d".to_owned(), String("".to_owned()))])
]))
let a = mk_object([
("a".to_owned(), Boolean(true)),
- ("b".to_owned(), List(box [
+ ("b".to_owned(), List(vec![
mk_object([("c".to_owned(), String("\x0c\r".to_owned()))]),
mk_object([("d".to_owned(), String("".to_owned()))])
]))
assert_eq!(from_str("[1,]"), Err(SyntaxError(InvalidSyntax, 1, 4)));
assert_eq!(from_str("[6 7]"), Err(SyntaxError(InvalidSyntax, 1, 4)));
- assert_eq!(from_str("[]"), Ok(List(~[])));
- assert_eq!(from_str("[ ]"), Ok(List(~[])));
- assert_eq!(from_str("[true]"), Ok(List(~[Boolean(true)])));
- assert_eq!(from_str("[ false ]"), Ok(List(~[Boolean(false)])));
- assert_eq!(from_str("[null]"), Ok(List(~[Null])));
+ assert_eq!(from_str("[]"), Ok(List(vec![])));
+ assert_eq!(from_str("[ ]"), Ok(List(vec![])));
+ assert_eq!(from_str("[true]"), Ok(List(vec![Boolean(true)])));
+ assert_eq!(from_str("[ false ]"), Ok(List(vec![Boolean(false)])));
+ assert_eq!(from_str("[null]"), Ok(List(vec![Null])));
assert_eq!(from_str("[3, 1]"),
- Ok(List(~[Number(3.0), Number(1.0)])));
+ Ok(List(vec![Number(3.0), Number(1.0)])));
assert_eq!(from_str("\n[3, 2]\n"),
- Ok(List(~[Number(3.0), Number(2.0)])));
+ Ok(List(vec![Number(3.0), Number(2.0)])));
assert_eq!(from_str("[2, [4, 1]]"),
- Ok(List(~[Number(2.0), List(~[Number(4.0), Number(1.0)])])));
+ Ok(List(vec![Number(2.0), List(vec![Number(4.0), Number(1.0)])])));
}
#[test]
fn test_decode_list() {
let mut decoder = Decoder::new(from_str("[]").unwrap());
- let v: ~[()] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[]);
+ let v: Vec<()> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![]);
let mut decoder = Decoder::new(from_str("[null]").unwrap());
- let v: ~[()] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[()]);
+ let v: Vec<()> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![()]);
let mut decoder = Decoder::new(from_str("[true]").unwrap());
- let v: ~[bool] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[true]);
+ let v: Vec<bool> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![true]);
let mut decoder = Decoder::new(from_str("[true]").unwrap());
- let v: ~[bool] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[true]);
+ let v: Vec<bool> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![true]);
let mut decoder = Decoder::new(from_str("[3, 1]").unwrap());
- let v: ~[int] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[3, 1]);
+ let v: Vec<int> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![3, 1]);
let mut decoder = Decoder::new(from_str("[[3], [1, 2]]").unwrap());
- let v: ~[~[uint]] = Decodable::decode(&mut decoder).unwrap();
- assert_eq!(v, ~[~[3], ~[1, 2]]);
+ let v: Vec<Vec<uint>> = Decodable::decode(&mut decoder).unwrap();
+ assert_eq!(v, vec![vec![3], vec![1, 2]]);
}
#[test]
"{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(),
mk_object([
("a".to_owned(), Number(1.0)),
- ("b".to_owned(), List(~[Boolean(true)]))
+ ("b".to_owned(), List(vec![Boolean(true)]))
]));
assert_eq!(from_str(
"{".to_owned() +
"}").unwrap(),
mk_object([
("a".to_owned(), Number(1.0)),
- ("b".to_owned(), List(~[
+ ("b".to_owned(), List(vec![
Boolean(true),
String("foo\nbar".to_owned()),
mk_object([
assert_eq!(
v,
Outer {
- inner: ~[
- Inner { a: (), b: 2, c: ~["abc".to_owned(), "xyz".to_owned()] }
+ inner: vec![
+ Inner { a: (), b: 2, c: vec!["abc".to_owned(), "xyz".to_owned()] }
]
}
);
x: f64,
y: bool,
z: ~str,
- w: ~[DecodeStruct]
+ w: Vec<DecodeStruct>
}
#[deriving(Decodable)]
enum DecodeEnum {
impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~[T] {
fn decode(d: &mut D) -> Result<~[T], E> {
+ use std::vec::FromVec;
+
d.read_seq(|d, len| {
let mut v: Vec<T> = Vec::with_capacity(len);
for i in range(0, len) {
v.push(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
- let k = v.move_iter().collect::<~[T]>();
+ let k: ~[T] = FromVec::from_vec(v);
Ok(k)
})
}
impl<E, D: Decoder<E>> Decodable<D, E> for path::posix::Path {
fn decode(d: &mut D) -> Result<path::posix::Path, E> {
- let bytes: ~[u8] = try!(Decodable::decode(d));
+ let bytes: Vec<u8> = try!(Decodable::decode(d));
Ok(path::posix::Path::new(bytes))
}
}
impl<E, D: Decoder<E>> Decodable<D, E> for path::windows::Path {
fn decode(d: &mut D) -> Result<path::windows::Path, E> {
- let bytes: ~[u8] = try!(Decodable::decode(d));
+ let bytes: Vec<u8> = try!(Decodable::decode(d));
Ok(path::windows::Path::new(bytes))
}
}
}
pub trait DecoderHelpers<E> {
- fn read_to_vec<T>(&mut self, f: |&mut Self| -> Result<T, E>) -> Result<~[T], E>;
+ fn read_to_vec<T>(&mut self, f: |&mut Self| -> Result<T, E>) -> Result<Vec<T>, E>;
}
impl<E, D:Decoder<E>> DecoderHelpers<E> for D {
- fn read_to_vec<T>(&mut self, f: |&mut D| -> Result<T, E>) -> Result<~[T], E> {
+ fn read_to_vec<T>(&mut self, f: |&mut D| -> Result<T, E>) -> Result<Vec<T>, E> {
self.read_seq(|this, len| {
let mut v = Vec::with_capacity(len);
for i in range(0, len) {
v.push(try!(this.read_seq_elt(i, |this| f(this))));
}
- Ok(v.move_iter().collect())
+ Ok(v)
})
}
}
use to_str::{IntoStr};
use str;
use str::Str;
-use str::StrSlice;
+use str::{StrAllocating, StrSlice};
use str::OwnedStr;
use container::Container;
use cast;
/// Take ownership and cast to an ascii vector. Fail on non-ASCII input.
#[inline]
- fn into_ascii(self) -> ~[Ascii] {
+ fn into_ascii(self) -> Vec<Ascii> {
assert!(self.is_ascii());
unsafe {self.into_ascii_nocheck()}
}
/// Take ownership and cast to an ascii vector. Return None on non-ASCII input.
#[inline]
- fn into_ascii_opt(self) -> Option<~[Ascii]> {
+ fn into_ascii_opt(self) -> Option<Vec<Ascii>> {
if self.is_ascii() {
Some(unsafe { self.into_ascii_nocheck() })
} else {
/// Take ownership and cast to an ascii vector.
/// Does not perform validation checks.
- unsafe fn into_ascii_nocheck(self) -> ~[Ascii];
+ unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
}
impl OwnedAsciiCast for ~[u8] {
}
#[inline]
- unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
- cast::transmute(self)
+ unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
+ cast::transmute(Vec::from_slice(self.as_slice()))
}
}
}
#[inline]
- unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
+ unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
+ let v: ~[u8] = cast::transmute(self);
+ v.into_ascii_nocheck()
+ }
+}
+
+impl OwnedAsciiCast for Vec<u8> {
+ #[inline]
+ fn is_ascii(&self) -> bool {
+ self.as_slice().is_ascii()
+ }
+
+ #[inline]
+ unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
cast::transmute(self)
}
}
fn as_str_ascii<'a>(&'a self) -> &'a str;
/// Convert to vector representing a lower cased ascii string.
- fn to_lower(&self) -> ~[Ascii];
+ fn to_lower(&self) -> Vec<Ascii>;
/// Convert to vector representing a upper cased ascii string.
- fn to_upper(&self) -> ~[Ascii];
+ fn to_upper(&self) -> Vec<Ascii>;
/// Compares two Ascii strings ignoring case.
fn eq_ignore_case(self, other: &[Ascii]) -> bool;
}
#[inline]
- fn to_lower(&self) -> ~[Ascii] {
+ fn to_lower(&self) -> Vec<Ascii> {
self.iter().map(|a| a.to_lower()).collect()
}
#[inline]
- fn to_upper(&self) -> ~[Ascii] {
+ fn to_upper(&self) -> Vec<Ascii> {
self.iter().map(|a| a.to_upper()).collect()
}
impl IntoStr for Vec<Ascii> {
#[inline]
fn into_str(self) -> ~str {
- let v: ~[Ascii] = self.move_iter().collect();
- unsafe { cast::transmute(v) }
+ unsafe {
+ let s: &str = cast::transmute(self.as_slice());
+ s.to_owned()
+ }
}
}
-/// Trait to convert to an owned byte array by consuming self
+/// Trait to convert to an owned byte vector by consuming self
pub trait IntoBytes {
- /// Converts to an owned byte array by consuming self
- fn into_bytes(self) -> ~[u8];
+ /// Converts to an owned byte vector by consuming self
+ fn into_bytes(self) -> Vec<u8>;
}
-impl IntoBytes for ~[Ascii] {
- fn into_bytes(self) -> ~[u8] {
+impl IntoBytes for Vec<Ascii> {
+ fn into_bytes(self) -> Vec<u8> {
unsafe { cast::transmute(self) }
}
}
#[inline]
unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str {
- let bytes = string.bytes().map(|b| map[b as uint]).collect::<~[_]>();
-
- str::raw::from_utf8_owned(bytes)
+ let mut s = string.to_owned();
+ for b in str::raw::as_owned_vec(&mut s).mut_iter() {
+ *b = map[*b as uint];
+ }
+ s
}
static ASCII_LOWER_MAP: &'static [u8] = &[
macro_rules! v2ascii (
( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
(&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
- (~[$($e:expr),*]) => (box [$(Ascii{chr:$e}),*]);
)
macro_rules! vec2ascii (
#[test]
fn test_ascii_vec_ng() {
- assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_lower()).into_str(),
- "abcdef&?#".to_owned());
- assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_upper()).into_str(),
- "ABCDEF&?#".to_owned());
- assert_eq!(Vec::from_slice("".to_ascii().to_lower()).into_str(), "".to_owned());
- assert_eq!(Vec::from_slice("YMCA".to_ascii().to_lower()).into_str(), "ymca".to_owned());
- assert_eq!(Vec::from_slice("abcDEFxyz:.;".to_ascii().to_upper()).into_str(),
- "ABCDEFXYZ:.;".to_owned());
+ assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), "abcdef&?#".to_owned());
+ assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), "ABCDEF&?#".to_owned());
+ assert_eq!("".to_ascii().to_lower().into_str(), "".to_owned());
+ assert_eq!("YMCA".to_ascii().to_lower().into_str(), "ymca".to_owned());
+ assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), "ABCDEFXYZ:.;".to_owned());
}
#[test]
fn test_owned_ascii_vec() {
- assert_eq!(("( ;".to_owned()).into_ascii(), v2ascii!(~[40, 32, 59]));
- assert_eq!((box [40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59]));
+ assert_eq!(("( ;".to_owned()).into_ascii(), vec2ascii![40, 32, 59]);
+ assert_eq!((box [40u8, 32u8, 59u8]).into_ascii(), vec2ascii![40, 32, 59]);
}
#[test]
#[test]
fn test_ascii_into_str() {
- assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), "( ;".to_owned());
+ assert_eq!(vec2ascii![40, 32, 59].into_str(), "( ;".to_owned());
assert_eq!(vec2ascii!(40, 32, 59).into_str(), "( ;".to_owned());
}
#[test]
fn test_ascii_to_bytes() {
- assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), box [40u8, 32u8, 59u8]);
+ assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
}
#[test] #[should_fail]
assert_eq!(v.to_ascii_opt(), Some(v2));
assert_eq!("zoä华".to_ascii_opt(), None);
- assert_eq!((box [40u8, 32u8, 59u8]).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59])));
- assert_eq!((box [127u8, 128u8, 255u8]).into_ascii_opt(), None);
+ assert_eq!((vec![40u8, 32u8, 59u8]).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
+ assert_eq!((vec![127u8, 128u8, 255u8]).into_ascii_opt(), None);
- assert_eq!(("( ;".to_owned()).into_ascii_opt(), Some(v2ascii!(~[40, 32, 59])));
+ assert_eq!(("( ;".to_owned()).into_ascii_opt(), Some(vec2ascii![40, 32, 59]));
assert_eq!(("zoä华".to_owned()).into_ascii_opt(), None);
}
pub use self::num::RadixFmt;
mod num;
-pub mod parse;
pub mod rt;
+#[cfg(stage0)]
+#[allow(missing_doc)]
+pub mod parse {
+ #[deriving(Eq)]
+ pub enum Alignment {
+ AlignLeft,
+ AlignRight,
+ AlignUnknown,
+ }
+
+ pub enum PluralKeyword {
+ Zero,
+ One,
+ Two,
+ Few,
+ Many,
+ }
+
+ pub enum Flag {
+ FlagSignPlus,
+ FlagSignMinus,
+ FlagAlternate,
+ FlagSignAwareZeroPad,
+ }
+}
+
pub type Result = io::IoResult<()>;
/// A struct to represent both where to emit formatting strings to and how they
/// Character used as 'fill' whenever there is alignment
pub fill: char,
/// Boolean indication of whether the output should be left-aligned
- pub align: parse::Alignment,
+ pub align: rt::Alignment,
/// Optionally specified integer width that the output should be
pub width: Option<uint>,
/// Optionally specified precision for numeric types
width: None,
precision: None,
buf: output,
- align: parse::AlignUnknown,
+ align: rt::AlignUnknown,
fill: ' ',
args: args,
curarg: args.iter(),
let value = value - match offset { Some(i) => i, None => 0 };
for s in selectors.iter() {
let run = match s.selector {
- rt::Keyword(parse::Zero) => value == 0,
- rt::Keyword(parse::One) => value == 1,
- rt::Keyword(parse::Two) => value == 2,
+ rt::Keyword(rt::Zero) => value == 0,
+ rt::Keyword(rt::One) => value == 1,
+ rt::Keyword(rt::Two) => value == 2,
// FIXME: Few/Many should have a user-specified boundary
// One possible option would be in the function
// pointer of the 'arg: Argument' struct.
- rt::Keyword(parse::Few) => value < 8,
- rt::Keyword(parse::Many) => value >= 8,
+ rt::Keyword(rt::Few) => value < 8,
+ rt::Keyword(rt::Many) => value >= 8,
rt::Literal(..) => false
};
/// This function will correctly account for the flags provided as well as
/// the minimum width. It will not take precision into account.
pub fn pad_integral(&mut self, is_positive: bool, prefix: &str, buf: &[u8]) -> Result {
- use fmt::parse::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad};
+ use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad};
let mut width = buf.len();
Some(min) if self.flags & (1 << (FlagSignAwareZeroPad as uint)) != 0 => {
self.fill = '0';
try!(write_prefix(self));
- self.with_padding(min - width, parse::AlignRight, |f| f.buf.write(buf))
+ self.with_padding(min - width, rt::AlignRight, |f| f.buf.write(buf))
}
// Otherwise, the sign and prefix goes after the padding
Some(min) => {
- self.with_padding(min - width, parse::AlignRight, |f| {
+ self.with_padding(min - width, rt::AlignRight, |f| {
try!(write_prefix(f)); f.buf.write(buf)
})
}
// If we're under both the maximum and the minimum width, then fill
// up the minimum width with the specified string + some alignment.
Some(width) => {
- self.with_padding(width - s.len(), parse::AlignLeft, |me| {
+ self.with_padding(width - s.len(), rt::AlignLeft, |me| {
me.buf.write(s.as_bytes())
})
}
/// afterwards depending on whether right or left alingment is requested.
fn with_padding(&mut self,
padding: uint,
- default: parse::Alignment,
+ default: rt::Alignment,
f: |&mut Formatter| -> Result) -> Result {
let align = match self.align {
- parse::AlignUnknown => default,
- parse::AlignLeft | parse::AlignRight => self.align
+ rt::AlignUnknown => default,
+ rt::AlignLeft | rt::AlignRight => self.align
};
- if align == parse::AlignLeft {
+ if align == rt::AlignLeft {
try!(f(self));
}
let mut fill = [0u8, ..4];
for _ in range(0, padding) {
try!(self.buf.write(fill.slice_to(len)));
}
- if align == parse::AlignRight {
+ if align == rt::AlignRight {
try!(f(self));
}
Ok(())
impl<T> Pointer for *T {
fn fmt(&self, f: &mut Formatter) -> Result {
- f.flags |= 1 << (parse::FlagAlternate as uint);
+ f.flags |= 1 << (rt::FlagAlternate as uint);
secret_lower_hex::<uint>(&(*self as uint), f)
}
}
impl<'a, T: Show> Show for &'a [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
- if f.flags & (1 << (parse::FlagAlternate as uint)) == 0 {
+ if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f.buf, "["));
}
let mut is_first = true;
}
try!(write!(f.buf, "{}", *x))
}
- if f.flags & (1 << (parse::FlagAlternate as uint)) == 0 {
+ if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f.buf, "]"));
}
Ok(())
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-//! Parsing of format strings
-//!
-//! These structures are used when parsing format strings for the compiler.
-//! Parsing does not happen at runtime: structures of `std::fmt::rt` are
-//! generated instead.
-
-use prelude::*;
-
-use char;
-use owned::Box;
-use str;
-
-/// A piece is a portion of the format string which represents the next part
-/// to emit. These are emitted as a stream by the `Parser` class.
-#[deriving(Eq)]
-pub enum Piece<'a> {
- /// A literal string which should directly be emitted
- String(&'a str),
- /// A back-reference to whatever the current argument is. This is used
- /// inside of a method call to refer back to the original argument.
- CurrentArgument,
- /// This describes that formatting should process the next argument (as
- /// specified inside) for emission.
- Argument(Argument<'a>),
-}
-
-/// Representation of an argument specification.
-#[deriving(Eq)]
-pub struct Argument<'a> {
- /// Where to find this argument
- pub position: Position<'a>,
- /// How to format the argument
- pub format: FormatSpec<'a>,
- /// If not `None`, what method to invoke on the argument
- pub method: Option<Box<Method<'a>>>
-}
-
-/// Specification for the formatting of an argument in the format string.
-#[deriving(Eq)]
-pub struct FormatSpec<'a> {
- /// Optionally specified character to fill alignment with
- pub fill: Option<char>,
- /// Optionally specified alignment
- pub align: Alignment,
- /// Packed version of various flags provided
- pub flags: uint,
- /// The integer precision to use
- pub precision: Count<'a>,
- /// The string width requested for the resulting format
- pub width: Count<'a>,
- /// The descriptor string representing the name of the format desired for
- /// this argument, this can be empty or any number of characters, although
- /// it is required to be one word.
- pub ty: &'a str
-}
-
-/// Enum describing where an argument for a format can be located.
-#[deriving(Eq)]
-pub enum Position<'a> {
- /// The argument will be in the next position. This is the default.
- ArgumentNext,
- /// The argument is located at a specific index.
- ArgumentIs(uint),
- /// The argument has a name.
- ArgumentNamed(&'a str),
-}
-
-/// Enum of alignments which are supported.
-#[deriving(Eq)]
-pub enum Alignment {
- /// The value will be aligned to the left.
- AlignLeft,
- /// The value will be aligned to the right.
- AlignRight,
- /// The value will take on a default alignment.
- AlignUnknown,
-}
-
-/// Various flags which can be applied to format strings. The meaning of these
-/// flags is defined by the formatters themselves.
-#[deriving(Eq)]
-pub enum Flag {
- /// A `+` will be used to denote positive numbers.
- FlagSignPlus,
- /// A `-` will be used to denote negative numbers. This is the default.
- FlagSignMinus,
- /// An alternate form will be used for the value. In the case of numbers,
- /// this means that the number will be prefixed with the supplied string.
- FlagAlternate,
- /// For numbers, this means that the number will be padded with zeroes,
- /// and the sign (`+` or `-`) will precede them.
- FlagSignAwareZeroPad,
-}
-
-/// A count is used for the precision and width parameters of an integer, and
-/// can reference either an argument or a literal integer.
-#[deriving(Eq)]
-pub enum Count<'a> {
- /// The count is specified explicitly.
- CountIs(uint),
- /// The count is specified by the argument with the given name.
- CountIsName(&'a str),
- /// The count is specified by the argument at the given index.
- CountIsParam(uint),
- /// The count is specified by the next parameter.
- CountIsNextParam,
- /// The count is implied and cannot be explicitly specified.
- CountImplied,
-}
-
-/// Enum describing all of the possible methods which the formatting language
-/// currently supports.
-#[deriving(Eq)]
-pub enum Method<'a> {
- /// A plural method selects on an integer over a list of either integer or
- /// keyword-defined clauses. The meaning of the keywords is defined by the
- /// current locale.
- ///
- /// An offset is optionally present at the beginning which is used to
- /// match against keywords, but it is not matched against the literal
- /// integers.
- ///
- /// The final element of this enum is the default "other" case which is
- /// always required to be specified.
- Plural(Option<uint>, Vec<PluralArm<'a>>, Vec<Piece<'a>>),
-
- /// A select method selects over a string. Each arm is a different string
- /// which can be selected for.
- ///
- /// As with `Plural`, a default "other" case is required as well.
- Select(Vec<SelectArm<'a>>, Vec<Piece<'a>>),
-}
-
-/// A selector for what pluralization a plural method should take
-#[deriving(Eq, TotalEq, Hash)]
-pub enum PluralSelector {
- /// One of the plural keywords should be used
- Keyword(PluralKeyword),
- /// A literal pluralization should be used
- Literal(uint),
-}
-
-/// Structure representing one "arm" of the `plural` function.
-#[deriving(Eq)]
-pub struct PluralArm<'a> {
- /// A selector can either be specified by a keyword or with an integer
- /// literal.
- pub selector: PluralSelector,
- /// Array of pieces which are the format of this arm
- pub result: Vec<Piece<'a>>,
-}
-
-/// Enum of the 5 CLDR plural keywords. There is one more, "other", but that
-/// is specially placed in the `Plural` variant of `Method`.
-///
-/// http://www.icu-project.org/apiref/icu4c/classicu_1_1PluralRules.html
-#[deriving(Eq, TotalEq, Hash)]
-#[allow(missing_doc)]
-pub enum PluralKeyword {
- /// The plural form for zero objects.
- Zero,
- /// The plural form for one object.
- One,
- /// The plural form for two objects.
- Two,
- /// The plural form for few objects.
- Few,
- /// The plural form for many objects.
- Many,
-}
-
-/// Structure representing one "arm" of the `select` function.
-#[deriving(Eq)]
-pub struct SelectArm<'a> {
- /// String selector which guards this arm
- pub selector: &'a str,
- /// Array of pieces which are the format of this arm
- pub result: Vec<Piece<'a>>,
-}
-
-/// The parser structure for interpreting the input format string. This is
-/// modelled as an iterator over `Piece` structures to form a stream of tokens
-/// being output.
-///
-/// This is a recursive-descent parser for the sake of simplicity, and if
-/// necessary there's probably lots of room for improvement performance-wise.
-pub struct Parser<'a> {
- input: &'a str,
- cur: str::CharOffsets<'a>,
- depth: uint,
- /// Error messages accumulated during parsing
- pub errors: Vec<~str>,
-}
-
-impl<'a> Iterator<Piece<'a>> for Parser<'a> {
- fn next(&mut self) -> Option<Piece<'a>> {
- match self.cur.clone().next() {
- Some((_, '#')) => { self.cur.next(); Some(CurrentArgument) }
- Some((_, '{')) => {
- self.cur.next();
- let ret = Some(Argument(self.argument()));
- self.must_consume('}');
- ret
- }
- Some((pos, '\\')) => {
- self.cur.next();
- self.escape(); // ensure it's a valid escape sequence
- Some(String(self.string(pos + 1))) // skip the '\' character
- }
- Some((_, '}')) if self.depth == 0 => {
- self.cur.next();
- self.err("unmatched `}` found");
- None
- }
- Some((_, '}')) | None => { None }
- Some((pos, _)) => {
- Some(String(self.string(pos)))
- }
- }
- }
-}
-
-impl<'a> Parser<'a> {
- /// Creates a new parser for the given format string
- pub fn new<'a>(s: &'a str) -> Parser<'a> {
- Parser {
- input: s,
- cur: s.char_indices(),
- depth: 0,
- errors: vec!(),
- }
- }
-
- /// Notifies of an error. The message doesn't actually need to be of type
- /// ~str, but I think it does when this eventually uses conditions so it
- /// might as well start using it now.
- fn err(&mut self, msg: &str) {
- self.errors.push(msg.to_owned());
- }
-
- /// Optionally consumes the specified character. If the character is not at
- /// the current position, then the current iterator isn't moved and false is
- /// returned, otherwise the character is consumed and true is returned.
- fn consume(&mut self, c: char) -> bool {
- match self.cur.clone().next() {
- Some((_, maybe)) if c == maybe => {
- self.cur.next();
- true
- }
- Some(..) | None => false,
- }
- }
-
- /// Forces consumption of the specified character. If the character is not
- /// found, an error is emitted.
- fn must_consume(&mut self, c: char) {
- self.ws();
- match self.cur.clone().next() {
- Some((_, maybe)) if c == maybe => {
- self.cur.next();
- }
- Some((_, other)) => {
- self.err(
- format!("expected `{}` but found `{}`", c, other));
- }
- None => {
- self.err(
- format!("expected `{}` but string was terminated", c));
- }
- }
- }
-
- /// Attempts to consume any amount of whitespace followed by a character
- fn wsconsume(&mut self, c: char) -> bool {
- self.ws(); self.consume(c)
- }
-
- /// Consumes all whitespace characters until the first non-whitespace
- /// character
- fn ws(&mut self) {
- loop {
- match self.cur.clone().next() {
- Some((_, c)) if char::is_whitespace(c) => { self.cur.next(); }
- Some(..) | None => { return }
- }
- }
- }
-
- /// Consumes an escape sequence, failing if there is not a valid character
- /// to be escaped.
- fn escape(&mut self) -> char {
- match self.cur.next() {
- Some((_, c @ '#')) | Some((_, c @ '{')) |
- Some((_, c @ '\\')) | Some((_, c @ '}')) => { c }
- Some((_, c)) => {
- self.err(format!("invalid escape character `{}`", c));
- c
- }
- None => {
- self.err("expected an escape sequence, but format string was \
- terminated");
- ' '
- }
- }
- }
-
- /// Parses all of a string which is to be considered a "raw literal" in a
- /// format string. This is everything outside of the braces.
- fn string(&mut self, start: uint) -> &'a str {
- loop {
- // we may not consume the character, so clone the iterator
- match self.cur.clone().next() {
- Some((pos, '\\')) | Some((pos, '#')) |
- Some((pos, '}')) | Some((pos, '{')) => {
- return self.input.slice(start, pos);
- }
- Some(..) => { self.cur.next(); }
- None => {
- self.cur.next();
- return self.input.slice(start, self.input.len());
- }
- }
- }
- }
-
- /// Parses an Argument structure, or what's contained within braces inside
- /// the format string
- fn argument(&mut self) -> Argument<'a> {
- Argument {
- position: self.position(),
- format: self.format(),
- method: self.method(),
- }
- }
-
- /// Parses a positional argument for a format. This could either be an
- /// integer index of an argument, a named argument, or a blank string.
- fn position(&mut self) -> Position<'a> {
- match self.integer() {
- Some(i) => { ArgumentIs(i) }
- None => {
- match self.cur.clone().next() {
- Some((_, c)) if char::is_alphabetic(c) => {
- ArgumentNamed(self.word())
- }
- _ => ArgumentNext
- }
- }
- }
- }
-
- /// Parses a format specifier at the current position, returning all of the
- /// relevant information in the FormatSpec struct.
- fn format(&mut self) -> FormatSpec<'a> {
- let mut spec = FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: self.input.slice(0, 0),
- };
- if !self.consume(':') { return spec }
-
- // fill character
- match self.cur.clone().next() {
- Some((_, c)) => {
- match self.cur.clone().skip(1).next() {
- Some((_, '>')) | Some((_, '<')) => {
- spec.fill = Some(c);
- self.cur.next();
- }
- Some(..) | None => {}
- }
- }
- None => {}
- }
- // Alignment
- if self.consume('<') {
- spec.align = AlignLeft;
- } else if self.consume('>') {
- spec.align = AlignRight;
- }
- // Sign flags
- if self.consume('+') {
- spec.flags |= 1 << (FlagSignPlus as uint);
- } else if self.consume('-') {
- spec.flags |= 1 << (FlagSignMinus as uint);
- }
- // Alternate marker
- if self.consume('#') {
- spec.flags |= 1 << (FlagAlternate as uint);
- }
- // Width and precision
- let mut havewidth = false;
- if self.consume('0') {
- // small ambiguity with '0$' as a format string. In theory this is a
- // '0' flag and then an ill-formatted format string with just a '$'
- // and no count, but this is better if we instead interpret this as
- // no '0' flag and '0$' as the width instead.
- if self.consume('$') {
- spec.width = CountIsParam(0);
- havewidth = true;
- } else {
- spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
- }
- }
- if !havewidth {
- spec.width = self.count();
- }
- if self.consume('.') {
- if self.consume('*') {
- spec.precision = CountIsNextParam;
- } else {
- spec.precision = self.count();
- }
- }
- // Finally the actual format specifier
- if self.consume('?') {
- spec.ty = "?";
- } else {
- spec.ty = self.word();
- }
- return spec;
- }
-
- /// Parses a method to be applied to the previously specified argument and
- /// its format. The two current supported methods are 'plural' and 'select'
- fn method(&mut self) -> Option<Box<Method<'a>>> {
- if !self.wsconsume(',') {
- return None;
- }
- self.ws();
- match self.word() {
- "select" => {
- self.must_consume(',');
- Some(self.select())
- }
- "plural" => {
- self.must_consume(',');
- Some(self.plural())
- }
- "" => {
- self.err("expected method after comma");
- return None;
- }
- method => {
- self.err(format!("unknown method: `{}`", method));
- return None;
- }
- }
- }
-
- /// Parses a 'select' statement (after the initial 'select' word)
- fn select(&mut self) -> Box<Method<'a>> {
- let mut other = None;
- let mut arms = vec!();
- // Consume arms one at a time
- loop {
- self.ws();
- let selector = self.word();
- if selector == "" {
- self.err("cannot have an empty selector");
- break
- }
- self.must_consume('{');
- self.depth += 1;
- let pieces = self.collect();
- self.depth -= 1;
- self.must_consume('}');
- if selector == "other" {
- if !other.is_none() {
- self.err("multiple `other` statements in `select");
- }
- other = Some(pieces);
- } else {
- arms.push(SelectArm { selector: selector, result: pieces });
- }
- self.ws();
- match self.cur.clone().next() {
- Some((_, '}')) => { break }
- Some(..) | None => {}
- }
- }
- // The "other" selector must be present
- let other = match other {
- Some(arm) => { arm }
- None => {
- self.err("`select` statement must provide an `other` case");
- vec!()
- }
- };
- box Select(arms, other)
- }
-
- /// Parses a 'plural' statement (after the initial 'plural' word)
- fn plural(&mut self) -> Box<Method<'a>> {
- let mut offset = None;
- let mut other = None;
- let mut arms = vec!();
-
- // First, attempt to parse the 'offset:' field. We know the set of
- // selector words which can appear in plural arms, and the only ones
- // which start with 'o' are "other" and "offset", hence look two
- // characters deep to see if we can consume the word "offset"
- self.ws();
- let mut it = self.cur.clone();
- match it.next() {
- Some((_, 'o')) => {
- match it.next() {
- Some((_, 'f')) => {
- let word = self.word();
- if word != "offset" {
- self.err(format!("expected `offset`, found `{}`",
- word));
- } else {
- self.must_consume(':');
- match self.integer() {
- Some(i) => { offset = Some(i); }
- None => {
- self.err("offset must be an integer");
- }
- }
- }
- }
- Some(..) | None => {}
- }
- }
- Some(..) | None => {}
- }
-
- // Next, generate all the arms
- loop {
- let mut isother = false;
- let selector = if self.wsconsume('=') {
- match self.integer() {
- Some(i) => Literal(i),
- None => {
- self.err("plural `=` selectors must be followed by an \
- integer");
- Literal(0)
- }
- }
- } else {
- let word = self.word();
- match word {
- "other" => { isother = true; Keyword(Zero) }
- "zero" => Keyword(Zero),
- "one" => Keyword(One),
- "two" => Keyword(Two),
- "few" => Keyword(Few),
- "many" => Keyword(Many),
- word => {
- self.err(format!("unexpected plural selector `{}`",
- word));
- if word == "" {
- break
- } else {
- Keyword(Zero)
- }
- }
- }
- };
- self.must_consume('{');
- self.depth += 1;
- let pieces = self.collect();
- self.depth -= 1;
- self.must_consume('}');
- if isother {
- if !other.is_none() {
- self.err("multiple `other` statements in `select");
- }
- other = Some(pieces);
- } else {
- arms.push(PluralArm { selector: selector, result: pieces });
- }
- self.ws();
- match self.cur.clone().next() {
- Some((_, '}')) => { break }
- Some(..) | None => {}
- }
- }
-
- let other = match other {
- Some(arm) => { arm }
- None => {
- self.err("`plural` statement must provide an `other` case");
- vec!()
- }
- };
- box Plural(offset, arms, other)
- }
-
- /// Parses a Count parameter at the current position. This does not check
- /// for 'CountIsNextParam' because that is only used in precision, not
- /// width.
- fn count(&mut self) -> Count<'a> {
- match self.integer() {
- Some(i) => {
- if self.consume('$') {
- CountIsParam(i)
- } else {
- CountIs(i)
- }
- }
- None => {
- let tmp = self.cur.clone();
- match self.word() {
- word if word.len() > 0 && self.consume('$') => {
- CountIsName(word)
- }
- _ => {
- self.cur = tmp;
- CountImplied
- }
- }
- }
- }
- }
-
- /// Parses a word starting at the current position. A word is considered to
- /// be an alphabetic character followed by any number of alphanumeric
- /// characters.
- fn word(&mut self) -> &'a str {
- let start = match self.cur.clone().next() {
- Some((pos, c)) if char::is_XID_start(c) => {
- self.cur.next();
- pos
- }
- Some(..) | None => { return self.input.slice(0, 0); }
- };
- let mut end;
- loop {
- match self.cur.clone().next() {
- Some((_, c)) if char::is_XID_continue(c) => {
- self.cur.next();
- }
- Some((pos, _)) => { end = pos; break }
- None => { end = self.input.len(); break }
- }
- }
- self.input.slice(start, end)
- }
-
- /// Optionally parses an integer at the current position. This doesn't deal
- /// with overflow at all, it's just accumulating digits.
- fn integer(&mut self) -> Option<uint> {
- let mut cur = 0;
- let mut found = false;
- loop {
- match self.cur.clone().next() {
- Some((_, c)) => {
- match char::to_digit(c, 10) {
- Some(i) => {
- cur = cur * 10 + i;
- found = true;
- self.cur.next();
- }
- None => { break }
- }
- }
- None => { break }
- }
- }
- if found {
- return Some(cur);
- } else {
- return None;
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use prelude::*;
-
- fn same(fmt: &'static str, p: &[Piece<'static>]) {
- let mut parser = Parser::new(fmt);
- assert!(p == parser.collect::<Vec<Piece<'static>>>().as_slice());
- }
-
- fn fmtdflt() -> FormatSpec<'static> {
- return FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "",
- }
- }
-
- fn musterr(s: &str) {
- let mut p = Parser::new(s);
- p.next();
- assert!(p.errors.len() != 0);
- }
-
- #[test]
- fn simple() {
- same("asdf", [String("asdf")]);
- same("a\\{b", [String("a"), String("{b")]);
- same("a\\#b", [String("a"), String("#b")]);
- same("a\\}b", [String("a"), String("}b")]);
- same("a\\}", [String("a"), String("}")]);
- same("\\}", [String("}")]);
- }
-
- #[test] fn invalid01() { musterr("{") }
- #[test] fn invalid02() { musterr("\\") }
- #[test] fn invalid03() { musterr("\\a") }
- #[test] fn invalid04() { musterr("{3a}") }
- #[test] fn invalid05() { musterr("{:|}") }
- #[test] fn invalid06() { musterr("{:>>>}") }
-
- #[test]
- fn format_nothing() {
- same("{}", [Argument(Argument {
- position: ArgumentNext,
- format: fmtdflt(),
- method: None,
- })]);
- }
- #[test]
- fn format_position() {
- same("{3}", [Argument(Argument {
- position: ArgumentIs(3),
- format: fmtdflt(),
- method: None,
- })]);
- }
- #[test]
- fn format_position_nothing_else() {
- same("{3:}", [Argument(Argument {
- position: ArgumentIs(3),
- format: fmtdflt(),
- method: None,
- })]);
- }
- #[test]
- fn format_type() {
- same("{3:a}", [Argument(Argument {
- position: ArgumentIs(3),
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "a",
- },
- method: None,
- })]);
- }
- #[test]
- fn format_align_fill() {
- same("{3:>}", [Argument(Argument {
- position: ArgumentIs(3),
- format: FormatSpec {
- fill: None,
- align: AlignRight,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "",
- },
- method: None,
- })]);
- same("{3:0<}", [Argument(Argument {
- position: ArgumentIs(3),
- format: FormatSpec {
- fill: Some('0'),
- align: AlignLeft,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "",
- },
- method: None,
- })]);
- same("{3:*<abcd}", [Argument(Argument {
- position: ArgumentIs(3),
- format: FormatSpec {
- fill: Some('*'),
- align: AlignLeft,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "abcd",
- },
- method: None,
- })]);
- }
- #[test]
- fn format_counts() {
- same("{:10s}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- width: CountIs(10),
- ty: "s",
- },
- method: None,
- })]);
- same("{:10$.10s}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountIs(10),
- width: CountIsParam(10),
- ty: "s",
- },
- method: None,
- })]);
- same("{:.*s}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountIsNextParam,
- width: CountImplied,
- ty: "s",
- },
- method: None,
- })]);
- same("{:.10$s}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountIsParam(10),
- width: CountImplied,
- ty: "s",
- },
- method: None,
- })]);
- same("{:a$.b$s}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountIsName("b"),
- width: CountIsName("a"),
- ty: "s",
- },
- method: None,
- })]);
- }
- #[test]
- fn format_flags() {
- same("{:-}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: (1 << FlagSignMinus as uint),
- precision: CountImplied,
- width: CountImplied,
- ty: "",
- },
- method: None,
- })]);
- same("{:+#}", [Argument(Argument {
- position: ArgumentNext,
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint),
- precision: CountImplied,
- width: CountImplied,
- ty: "",
- },
- method: None,
- })]);
- }
- #[test]
- fn format_mixture() {
- same("abcd {3:a} efg", [String("abcd "), Argument(Argument {
- position: ArgumentIs(3),
- format: FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- width: CountImplied,
- ty: "a",
- },
- method: None,
- }), String(" efg")]);
- }
-
- #[test]
- fn select_simple() {
- same("{, select, other { haha } }", [Argument(Argument{
- position: ArgumentNext,
- format: fmtdflt(),
- method: Some(box Select(vec![], vec![String(" haha ")]))
- })]);
- same("{1, select, other { haha } }", [Argument(Argument{
- position: ArgumentIs(1),
- format: fmtdflt(),
- method: Some(box Select(vec![], vec![String(" haha ")]))
- })]);
- same("{1, select, other {#} }", [Argument(Argument{
- position: ArgumentIs(1),
- format: fmtdflt(),
- method: Some(box Select(vec![], vec![CurrentArgument]))
- })]);
- same("{1, select, other {{2, select, other {lol}}} }", [Argument(Argument{
- position: ArgumentIs(1),
- format: fmtdflt(),
- method: Some(box Select(vec![], vec![Argument(Argument{
- position: ArgumentIs(2),
- format: fmtdflt(),
- method: Some(box Select(vec![], vec![String("lol")]))
- })])) // wat
- })]);
- }
-
- #[test]
- fn select_cases() {
- same("{1, select, a{1} b{2} c{3} other{4} }", [Argument(Argument{
- position: ArgumentIs(1),
- format: fmtdflt(),
- method: Some(box Select(vec![
- SelectArm{ selector: "a", result: vec![String("1")] },
- SelectArm{ selector: "b", result: vec![String("2")] },
- SelectArm{ selector: "c", result: vec![String("3")] },
- ], vec![String("4")]))
- })]);
- }
-
- #[test] fn badselect01() { musterr("{select, }") }
- #[test] fn badselect02() { musterr("{1, select}") }
- #[test] fn badselect03() { musterr("{1, select, }") }
- #[test] fn badselect04() { musterr("{1, select, a {}}") }
- #[test] fn badselect05() { musterr("{1, select, other }}") }
- #[test] fn badselect06() { musterr("{1, select, other {}") }
- #[test] fn badselect07() { musterr("{select, other {}") }
- #[test] fn badselect08() { musterr("{1 select, other {}") }
- #[test] fn badselect09() { musterr("{:d select, other {}") }
- #[test] fn badselect10() { musterr("{1:d select, other {}") }
-
- #[test]
- fn plural_simple() {
- same("{, plural, other { haha } }", [Argument(Argument{
- position: ArgumentNext,
- format: fmtdflt(),
- method: Some(box Plural(None, vec![], vec![String(" haha ")]))
- })]);
- same("{:, plural, other { haha } }", [Argument(Argument{
- position: ArgumentNext,
- format: fmtdflt(),
- method: Some(box Plural(None, vec![], vec![String(" haha ")]))
- })]);
- same("{, plural, offset:1 =2{2} =3{3} many{yes} other{haha} }",
- [Argument(Argument{
- position: ArgumentNext,
- format: fmtdflt(),
- method: Some(box Plural(Some(1), vec![
- PluralArm{ selector: Literal(2), result: vec![String("2")] },
- PluralArm{ selector: Literal(3), result: vec![String("3")] },
- PluralArm{ selector: Keyword(Many), result: vec![String("yes")] }
- ], vec![String("haha")]))
- })]);
- }
-}
#![allow(missing_doc)]
#![doc(hidden)]
-use fmt::parse;
use option::Option;
+#[cfg(stage0)]
+pub use fmt::parse::{Alignment, AlignLeft, AlignRight, AlignUnknown};
+#[cfg(stage0)]
+pub use fmt::parse::{PluralKeyword, Zero, One, Two, Few, Many};
+#[cfg(stage0)]
+pub use fmt::parse::{Flag, FlagSignPlus, FlagSignMinus, FlagSignAwareZeroPad};
+#[cfg(stage0)]
+pub use fmt::parse::{FlagAlternate};
+
pub enum Piece<'a> {
String(&'a str),
// FIXME(#8259): this shouldn't require the unit-value here
pub struct FormatSpec {
pub fill: char,
- pub align: parse::Alignment,
+ pub align: Alignment,
pub flags: uint,
pub precision: Count,
pub width: Count,
}
+#[cfg(not(stage0))]
+#[deriving(Eq)]
+pub enum Alignment {
+ AlignLeft,
+ AlignRight,
+ AlignUnknown,
+}
+
pub enum Count {
CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied,
}
ArgumentNext, ArgumentIs(uint)
}
+#[cfg(not(stage0))]
+pub enum Flag {
+ FlagSignPlus,
+ FlagSignMinus,
+ FlagAlternate,
+ FlagSignAwareZeroPad,
+}
+
pub enum Method<'a> {
Plural(Option<uint>, &'a [PluralArm<'a>], &'a [Piece<'a>]),
Select(&'a [SelectArm<'a>], &'a [Piece<'a>]),
}
pub enum PluralSelector {
- Keyword(parse::PluralKeyword),
+ Keyword(PluralKeyword),
Literal(uint),
}
+pub enum PluralKeyword {
+ Zero,
+ One,
+ Two,
+ Few,
+ Many,
+}
+
pub struct PluralArm<'a> {
pub selector: PluralSelector,
pub result: &'a [Piece<'a>],
let path = Path::new("message.txt");
let mut file = BufferedReader::new(File::open(&path));
- let lines: ~[~str] = file.lines().map(|x| x.unwrap()).collect();
+ let lines: Vec<~str> = file.lines().map(|x| x.unwrap()).collect();
```
* Make a simple TCP client connection and request
libc::WSAEADDRNOTAVAIL => (ConnectionRefused, "address not available"),
libc::WSAEADDRINUSE => (ConnectionRefused, "address in use"),
libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"),
+ libc::ERROR_OPERATION_ABORTED =>
+ (TimedOut, "operation timed out"),
// libuv maps this error code to EISDIR. we do too. if it is found
// to be incorrect, we can add in some more machinery to only
InvalidInput,
/// The I/O operation's timeout expired, causing it to be canceled.
TimedOut,
+ /// This write operation failed to write all of its data.
+ ///
+ /// Normally the write() method on a Writer guarantees that all of its data
+ /// has been written, but some operations may be terminated after only
+ /// partially writing some data. An example of this is a timed out write
+ /// which successfully wrote a known number of bytes, but bailed out after
+ /// doing so.
+ ///
+ /// The payload contained as part of this variant is the number of bytes
+ /// which are known to have been successfully written.
+ ShortWrite(uint),
}
/// A trait for objects which are byte-oriented streams. Readers are defined by
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.inner.read(buf) }
}
+impl<'a, R: Buffer> Buffer for RefReader<'a, R> {
+ fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() }
+ fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
+}
+
fn extend_sign(val: u64, nbytes: uint) -> i64 {
let shift = (8 - nbytes) * 8;
(val << shift) as i64 >> shift
PathDoesntExist => "no such file",
MismatchedFileTypeForOperation => "mismatched file type",
ResourceUnavailable => "resource unavailable",
- TimedOut => "operation timed out"
+ TimedOut => "operation timed out",
+ ShortWrite(..) => "short write",
};
IoError {
kind: kind,
use io::net::ip::{SocketAddr, IpAddr};
use option::{Option, Some, None};
use rt::rtio::{IoFactory, LocalIo};
-use slice::OwnedVector;
+use vec::Vec;
/// Hints to the types of sockets that are desired when looking up hosts
pub enum SocketType {
/// Easy name resolution. Given a hostname, returns the list of IP addresses for
/// that hostname.
-pub fn get_host_addresses(host: &str) -> IoResult<~[IpAddr]> {
+pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> {
lookup(Some(host), None, None).map(|a| a.move_iter().map(|i| i.address.ip).collect())
}
/// FIXME: this is not public because the `Hint` structure is not ready for public
/// consumption just yet.
fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>)
- -> IoResult<~[Info]> {
+ -> IoResult<Vec<Info>> {
LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint))
}
///
/// # Example
///
-/// ```rust
+/// ```no_run
/// # #![allow(unused_must_use)]
/// use std::io::net::tcp::TcpStream;
/// use std::io::net::ip::{Ipv4Addr, SocketAddr};
None => self.obj.letdie(),
}
}
+
+ /// Closes the reading half of this connection.
+ ///
+ /// This method will close the reading portion of this connection, causing
+ /// all pending and future reads to immediately return with an error.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # #![allow(unused_must_use)]
+ /// use std::io::timer;
+ /// use std::io::net::tcp::TcpStream;
+ /// use std::io::net::ip::{Ipv4Addr, SocketAddr};
+ ///
+ /// let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 34254 };
+ /// let mut stream = TcpStream::connect(addr).unwrap();
+ /// let stream2 = stream.clone();
+ ///
+ /// spawn(proc() {
+ /// // close this stream after one second
+ /// timer::sleep(1000);
+ /// let mut stream = stream2;
+ /// stream.close_read();
+ /// });
+ ///
+ /// // wait for some data, will get canceled after one second
+ /// let mut buf = [0];
+ /// stream.read(buf);
+ /// ```
+ ///
+ /// Note that this method affects all cloned handles associated with this
+ /// stream, not just this one handle.
+ pub fn close_read(&mut self) -> IoResult<()> { self.obj.close_read() }
+
+ /// Closes the writing half of this connection.
+ ///
+ /// This method will close the writing portion of this connection, causing
+ /// all future writes to immediately return with an error.
+ ///
+ /// Note that this method affects all cloned handles associated with this
+ /// stream, not just this one handle.
+ pub fn close_write(&mut self) -> IoResult<()> { self.obj.close_write() }
+
+ /// Sets a timeout, in milliseconds, for blocking operations on this stream.
+ ///
+ /// This function will set a timeout for all blocking operations (including
+ /// reads and writes) on this stream. The timeout specified is a relative
+ /// time, in milliseconds, into the future after which point operations will
+ /// time out. This means that the timeout must be reset periodically to keep
+ /// it from expiring. Specifying a value of `None` will clear the timeout
+ /// for this stream.
+ ///
+ /// The timeout on this stream is local to this stream only. Setting a
+ /// timeout does not affect any other cloned instances of this stream, nor
+ /// does the timeout propagated to cloned handles of this stream. Setting
+ /// this timeout will override any specific read or write timeouts
+ /// previously set for this stream.
+ ///
+ /// For clarification on the semantics of interrupting a read and a write,
+ /// take a look at `set_read_timeout` and `set_write_timeout`.
+ pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_timeout(timeout_ms)
+ }
+
+ /// Sets the timeout for read operations on this stream.
+ ///
+ /// See documentation in `set_timeout` for the semantics of this read time.
+ /// This will overwrite any previous read timeout set through either this
+ /// function or `set_timeout`.
+ ///
+ /// # Errors
+ ///
+ /// When this timeout expires, if there is no pending read operation, no
+ /// action is taken. Otherwise, the read operation will be scheduled to
+ /// promptly return. If a timeout error is returned, then no data was read
+ /// during the timeout period.
+ pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_read_timeout(timeout_ms)
+ }
+
+ /// Sets the timeout for write operations on this stream.
+ ///
+ /// See documentation in `set_timeout` for the semantics of this write time.
+ /// This will overwrite any previous write timeout set through either this
+ /// function or `set_timeout`.
+ ///
+ /// # Errors
+ ///
+ /// When this timeout expires, if there is no pending write operation, no
+ /// action is taken. Otherwise, the pending write operation will be
+ /// scheduled to promptly return. The actual state of the underlying stream
+ /// is not specified.
+ ///
+ /// The write operation may return an error of type `ShortWrite` which
+ /// indicates that the object is known to have written an exact number of
+ /// bytes successfully during the timeout period, and the remaining bytes
+ /// were never written.
+ ///
+ /// If the write operation returns `TimedOut`, then it the timeout primitive
+ /// does not know how many bytes were written as part of the timeout
+ /// operation. It may be the case that bytes continue to be written in an
+ /// asynchronous fashion after the call to write returns.
+ pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_write_timeout(timeout_ms)
+ }
}
impl Clone for TcpStream {
// Also make sure that even though the timeout is expired that we will
// continue to receive any pending connections.
- let l = TcpStream::connect(addr).unwrap();
+ let (tx, rx) = channel();
+ spawn(proc() {
+ tx.send(TcpStream::connect(addr).unwrap());
+ });
+ let l = rx.recv();
for i in range(0, 1001) {
match a.accept() {
Ok(..) => break,
Err(ref e) if e.kind == TimedOut => {}
Err(e) => fail!("error: {}", e),
}
+ ::task::deschedule();
if i == 1000 { fail!("should have a pending connection") }
}
drop(l);
// Unset the timeout and make sure that this always blocks.
a.set_timeout(None);
spawn(proc() {
- drop(TcpStream::connect(addr));
+ drop(TcpStream::connect(addr).unwrap());
});
a.accept().unwrap();
})
+
+ iotest!(fn close_readwrite_smoke() {
+ let addr = next_test_ip4();
+ let a = TcpListener::bind(addr).listen().unwrap();
+ let (_tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut a = a;
+ let _s = a.accept().unwrap();
+ let _ = rx.recv_opt();
+ });
+
+ let mut b = [0];
+ let mut s = TcpStream::connect(addr).unwrap();
+ let mut s2 = s.clone();
+
+ // closing should prevent reads/writes
+ s.close_write().unwrap();
+ assert!(s.write([0]).is_err());
+ s.close_read().unwrap();
+ assert!(s.read(b).is_err());
+
+ // closing should affect previous handles
+ assert!(s2.write([0]).is_err());
+ assert!(s2.read(b).is_err());
+
+ // closing should affect new handles
+ let mut s3 = s.clone();
+ assert!(s3.write([0]).is_err());
+ assert!(s3.read(b).is_err());
+
+ // make sure these don't die
+ let _ = s2.close_read();
+ let _ = s2.close_write();
+ let _ = s3.close_read();
+ let _ = s3.close_write();
+ })
+
+ iotest!(fn close_read_wakes_up() {
+ let addr = next_test_ip4();
+ let a = TcpListener::bind(addr).listen().unwrap();
+ let (_tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut a = a;
+ let _s = a.accept().unwrap();
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = TcpStream::connect(addr).unwrap();
+ let s2 = s.clone();
+ let (tx, rx) = channel();
+ spawn(proc() {
+ let mut s2 = s2;
+ assert!(s2.read([0]).is_err());
+ tx.send(());
+ });
+ // this should wake up the child task
+ s.close_read().unwrap();
+
+ // this test will never finish if the child doesn't wake up
+ rx.recv();
+ })
+
+ iotest!(fn readwrite_timeouts() {
+ let addr = next_test_ip6();
+ let mut a = TcpListener::bind(addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = TcpStream::connect(addr).unwrap();
+ rx.recv();
+ assert!(s.write([0]).is_ok());
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+
+ s.set_timeout(Some(20));
+ for i in range(0, 1001) {
+ match s.write([0, .. 128 * 1024]) {
+ Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
+ Err(IoError { kind: TimedOut, .. }) => break,
+ Err(e) => fail!("{}", e),
+ }
+ if i == 1000 { fail!("should have filled up?!"); }
+ }
+ assert_eq!(s.write([0]).err().unwrap().kind, TimedOut);
+
+ tx.send(());
+ s.set_timeout(None);
+ assert_eq!(s.read([0, 0]), Ok(1));
+ })
+
+ iotest!(fn read_timeouts() {
+ let addr = next_test_ip6();
+ let mut a = TcpListener::bind(addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = TcpStream::connect(addr).unwrap();
+ rx.recv();
+ let mut amt = 0;
+ while amt < 100 * 128 * 1024 {
+ match s.read([0, ..128 * 1024]) {
+ Ok(n) => { amt += n; }
+ Err(e) => fail!("{}", e),
+ }
+ }
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_read_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+
+ tx.send(());
+ for _ in range(0, 100) {
+ assert!(s.write([0, ..128 * 1024]).is_ok());
+ }
+ })
+
+ iotest!(fn write_timeouts() {
+ let addr = next_test_ip6();
+ let mut a = TcpListener::bind(addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = TcpStream::connect(addr).unwrap();
+ rx.recv();
+ assert!(s.write([0]).is_ok());
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_write_timeout(Some(20));
+ for i in range(0, 1001) {
+ match s.write([0, .. 128 * 1024]) {
+ Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
+ Err(IoError { kind: TimedOut, .. }) => break,
+ Err(e) => fail!("{}", e),
+ }
+ if i == 1000 { fail!("should have filled up?!"); }
+ }
+ assert_eq!(s.write([0]).err().unwrap().kind, TimedOut);
+
+ tx.send(());
+ assert!(s.read([0]).is_ok());
+ })
+
+ iotest!(fn timeout_concurrent_read() {
+ let addr = next_test_ip6();
+ let mut a = TcpListener::bind(addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = TcpStream::connect(addr).unwrap();
+ rx.recv();
+ assert_eq!(s.write([0]), Ok(()));
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ let s2 = s.clone();
+ let (tx2, rx2) = channel();
+ spawn(proc() {
+ let mut s2 = s2;
+ assert_eq!(s2.read([0]), Ok(1));
+ tx2.send(());
+ });
+
+ s.set_read_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ tx.send(());
+
+ rx2.recv();
+ })
}
use io::{Reader, Writer, IoResult};
use kinds::Send;
use owned::Box;
+use option::Option;
use result::{Ok, Err};
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
self.obj.ignore_broadcasts()
}
}
+
+ /// Sets the read/write timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_timeout(timeout_ms)
+ }
+
+ /// Sets the read timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_read_timeout(timeout_ms)
+ }
+
+ /// Sets the write timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_write_timeout(timeout_ms)
+ }
}
impl Clone for UdpSocket {
rx.recv();
serv_rx.recv();
})
+
+ iotest!(fn recvfrom_timeout() {
+ let addr1 = next_test_ip4();
+ let addr2 = next_test_ip4();
+ let mut a = UdpSocket::bind(addr1).unwrap();
+
+ let (tx, rx) = channel();
+ let (tx2, rx2) = channel();
+ spawn(proc() {
+ let mut a = UdpSocket::bind(addr2).unwrap();
+ assert_eq!(a.recvfrom([0]), Ok((1, addr1)));
+ assert_eq!(a.sendto([0], addr1), Ok(()));
+ rx.recv();
+ assert_eq!(a.sendto([0], addr1), Ok(()));
+
+ tx2.send(());
+ });
+
+ // Make sure that reads time out, but writes can continue
+ a.set_read_timeout(Some(20));
+ assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.sendto([0], addr2), Ok(()));
+
+ // Cloned handles should be able to block
+ let mut a2 = a.clone();
+ assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+
+ // Clearing the timeout should allow for receiving
+ a.set_timeout(None);
+ tx.send(());
+ assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+
+ // Make sure the child didn't die
+ rx2.recv();
+ })
+
+ iotest!(fn sendto_timeout() {
+ let addr1 = next_test_ip4();
+ let addr2 = next_test_ip4();
+ let mut a = UdpSocket::bind(addr1).unwrap();
+ let _b = UdpSocket::bind(addr2).unwrap();
+
+ a.set_write_timeout(Some(1000));
+ for _ in range(0, 100) {
+ match a.sendto([0, ..4*1024], addr2) {
+ Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
+ Err(IoError { kind: TimedOut, .. }) => break,
+ Err(e) => fail!("other error: {}", e),
+ }
+ }
+ })
}
use c_str::ToCStr;
use clone::Clone;
-use io::pipe::PipeStream;
use io::{Listener, Acceptor, Reader, Writer, IoResult};
use kinds::Send;
use owned::Box;
/// A stream which communicates over a named pipe.
pub struct UnixStream {
- obj: PipeStream,
+ obj: Box<RtioPipe:Send>,
}
impl UnixStream {
- fn new(obj: Box<RtioPipe:Send>) -> UnixStream {
- UnixStream { obj: PipeStream::new(obj) }
- }
-
/// Connect to a pipe named by `path`. This will attempt to open a
/// connection to the underlying socket.
///
/// ```
pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
LocalIo::maybe_raise(|io| {
- io.unix_connect(&path.to_c_str(), None).map(UnixStream::new)
+ io.unix_connect(&path.to_c_str(), None).map(|p| UnixStream { obj: p })
})
}
- /// Connect to a pipe named by `path`. This will attempt to open a
- /// connection to the underlying socket.
- ///
- /// The returned stream will be closed when the object falls out of scope.
- ///
- /// # Example
+ /// Connect to a pipe named by `path`, timing out if the specified number of
+ /// milliseconds.
///
- /// ```rust
- /// # #![allow(unused_must_use)]
- /// use std::io::net::unix::UnixStream;
- ///
- /// let server = Path::new("path/to/my/socket");
- /// let mut stream = UnixStream::connect(&server);
- /// stream.write([1, 2, 3]);
- /// ```
+ /// This function is similar to `connect`, except that if `timeout_ms`
+ /// elapses the function will return an error of kind `TimedOut`.
#[experimental = "the timeout argument is likely to change types"]
pub fn connect_timeout<P: ToCStr>(path: &P,
timeout_ms: u64) -> IoResult<UnixStream> {
LocalIo::maybe_raise(|io| {
let s = io.unix_connect(&path.to_c_str(), Some(timeout_ms));
- s.map(UnixStream::new)
+ s.map(|p| UnixStream { obj: p })
})
}
+
+
+ /// Closes the reading half of this connection.
+ ///
+ /// This method will close the reading portion of this connection, causing
+ /// all pending and future reads to immediately return with an error.
+ ///
+ /// Note that this method affects all cloned handles associated with this
+ /// stream, not just this one handle.
+ pub fn close_read(&mut self) -> IoResult<()> { self.obj.close_read() }
+
+ /// Closes the writing half of this connection.
+ ///
+ /// This method will close the writing portion of this connection, causing
+ /// all pending and future writes to immediately return with an error.
+ ///
+ /// Note that this method affects all cloned handles associated with this
+ /// stream, not just this one handle.
+ pub fn close_write(&mut self) -> IoResult<()> { self.obj.close_write() }
+
+ /// Sets the read/write timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_timeout(timeout_ms)
+ }
+
+ /// Sets the read timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_read_timeout(timeout_ms)
+ }
+
+ /// Sets the write timeout for this socket.
+ ///
+ /// For more information, see `TcpStream::set_timeout`
+ pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
+ self.obj.set_write_timeout(timeout_ms)
+ }
}
impl Clone for UnixStream {
impl Acceptor<UnixStream> for UnixAcceptor {
fn accept(&mut self) -> IoResult<UnixStream> {
- self.obj.accept().map(UnixStream::new)
+ self.obj.accept().map(|s| UnixStream { obj: s })
}
}
// Also make sure that even though the timeout is expired that we will
// continue to receive any pending connections.
- let l = UnixStream::connect(&addr).unwrap();
+ let (tx, rx) = channel();
+ let addr2 = addr.clone();
+ spawn(proc() {
+ tx.send(UnixStream::connect(&addr2).unwrap());
+ });
+ let l = rx.recv();
for i in range(0, 1001) {
match a.accept() {
Ok(..) => break,
Err(ref e) if e.kind == TimedOut => {}
Err(e) => fail!("error: {}", e),
}
+ ::task::deschedule();
if i == 1000 { fail!("should have a pending connection") }
}
drop(l);
a.set_timeout(None);
let addr2 = addr.clone();
spawn(proc() {
- drop(UnixStream::connect(&addr2));
+ drop(UnixStream::connect(&addr2).unwrap());
});
a.accept().unwrap();
})
let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
assert!(UnixStream::connect_timeout(&addr, 100).is_ok());
})
+
+ iotest!(fn close_readwrite_smoke() {
+ let addr = next_test_unix();
+ let a = UnixListener::bind(&addr).listen().unwrap();
+ let (_tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut a = a;
+ let _s = a.accept().unwrap();
+ let _ = rx.recv_opt();
+ });
+
+ let mut b = [0];
+ let mut s = UnixStream::connect(&addr).unwrap();
+ let mut s2 = s.clone();
+
+ // closing should prevent reads/writes
+ s.close_write().unwrap();
+ assert!(s.write([0]).is_err());
+ s.close_read().unwrap();
+ assert!(s.read(b).is_err());
+
+ // closing should affect previous handles
+ assert!(s2.write([0]).is_err());
+ assert!(s2.read(b).is_err());
+
+ // closing should affect new handles
+ let mut s3 = s.clone();
+ assert!(s3.write([0]).is_err());
+ assert!(s3.read(b).is_err());
+
+ // make sure these don't die
+ let _ = s2.close_read();
+ let _ = s2.close_write();
+ let _ = s3.close_read();
+ let _ = s3.close_write();
+ })
+
+ iotest!(fn close_read_wakes_up() {
+ let addr = next_test_unix();
+ let a = UnixListener::bind(&addr).listen().unwrap();
+ let (_tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut a = a;
+ let _s = a.accept().unwrap();
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = UnixStream::connect(&addr).unwrap();
+ let s2 = s.clone();
+ let (tx, rx) = channel();
+ spawn(proc() {
+ let mut s2 = s2;
+ assert!(s2.read([0]).is_err());
+ tx.send(());
+ });
+ // this should wake up the child task
+ s.close_read().unwrap();
+
+ // this test will never finish if the child doesn't wake up
+ rx.recv();
+ })
+
+ iotest!(fn readwrite_timeouts() {
+ let addr = next_test_unix();
+ let mut a = UnixListener::bind(&addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = UnixStream::connect(&addr).unwrap();
+ rx.recv();
+ assert!(s.write([0]).is_ok());
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+
+ s.set_timeout(Some(20));
+ for i in range(0, 1001) {
+ match s.write([0, .. 128 * 1024]) {
+ Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
+ Err(IoError { kind: TimedOut, .. }) => break,
+ Err(e) => fail!("{}", e),
+ }
+ if i == 1000 { fail!("should have filled up?!"); }
+ }
+
+ // I'm not sure as to why, but apparently the write on windows always
+ // succeeds after the previous timeout. Who knows?
+ if !cfg!(windows) {
+ assert_eq!(s.write([0]).err().unwrap().kind, TimedOut);
+ }
+
+ tx.send(());
+ s.set_timeout(None);
+ assert_eq!(s.read([0, 0]), Ok(1));
+ })
+
+ iotest!(fn read_timeouts() {
+ let addr = next_test_unix();
+ let mut a = UnixListener::bind(&addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = UnixStream::connect(&addr).unwrap();
+ rx.recv();
+ let mut amt = 0;
+ while amt < 100 * 128 * 1024 {
+ match s.read([0, ..128 * 1024]) {
+ Ok(n) => { amt += n; }
+ Err(e) => fail!("{}", e),
+ }
+ }
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_read_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+
+ tx.send(());
+ for _ in range(0, 100) {
+ assert!(s.write([0, ..128 * 1024]).is_ok());
+ }
+ })
+
+ iotest!(fn write_timeouts() {
+ let addr = next_test_unix();
+ let mut a = UnixListener::bind(&addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = UnixStream::connect(&addr).unwrap();
+ rx.recv();
+ assert!(s.write([0]).is_ok());
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ s.set_write_timeout(Some(20));
+ for i in range(0, 1001) {
+ match s.write([0, .. 128 * 1024]) {
+ Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
+ Err(IoError { kind: TimedOut, .. }) => break,
+ Err(e) => fail!("{}", e),
+ }
+ if i == 1000 { fail!("should have filled up?!"); }
+ }
+
+ tx.send(());
+ assert!(s.read([0]).is_ok());
+ })
+
+ iotest!(fn timeout_concurrent_read() {
+ let addr = next_test_unix();
+ let mut a = UnixListener::bind(&addr).listen().unwrap();
+ let (tx, rx) = channel::<()>();
+ spawn(proc() {
+ let mut s = UnixStream::connect(&addr).unwrap();
+ rx.recv();
+ assert!(s.write([0]).is_ok());
+ let _ = rx.recv_opt();
+ });
+
+ let mut s = a.accept().unwrap();
+ let s2 = s.clone();
+ let (tx2, rx2) = channel();
+ spawn(proc() {
+ let mut s2 = s2;
+ assert!(s2.read([0]).is_ok());
+ tx2.send(());
+ });
+
+ s.set_read_timeout(Some(20));
+ assert_eq!(s.read([0]).err().unwrap().kind, TimedOut);
+ tx.send(());
+
+ rx2.recv();
+ })
}
/// Extra I/O handles as configured by the original `ProcessConfig` when
/// this process was created. This is by default empty.
- pub extra_io: ~[Option<io::PipeStream>],
+ pub extra_io: Vec<Option<io::PipeStream>>,
}
/// This configuration describes how a new process should be spawned. A blank
drop(self.stdin.take());
drop(self.stdout.take());
drop(self.stderr.take());
- drop(mem::replace(&mut self.extra_io, box []));
+ drop(mem::replace(&mut self.extra_io, Vec::new()));
self.wait();
}
}
}
+impl<R: Buffer> Buffer for LimitReader<R> {
+ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
+ let amt = try!(self.inner.fill_buf());
+ let buf = amt.slice_to(cmp::min(amt.len(), self.limit));
+ if buf.len() == 0 {
+ Err(io::standard_error(io::EndOfFile))
+ } else {
+ Ok(buf)
+ }
+ }
+
+ fn consume(&mut self, amt: uint) {
+ self.limit -= amt;
+ self.inner.consume(amt);
+ }
+
+}
+
/// A `Writer` which ignores bytes written to it, like /dev/null.
pub struct NullWriter;
}
}
+impl Buffer for ZeroReader {
+ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
+ static DATA: [u8, ..64] = [0, ..64];
+ Ok(DATA.as_slice())
+ }
+ fn consume(&mut self, _amt: uint) {}
+}
+
/// A `Reader` which is always at EOF, like /dev/null.
pub struct NullReader;
}
}
+impl Buffer for NullReader {
+ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
+ Err(io::standard_error(io::EndOfFile))
+ }
+ fn consume(&mut self, _amt: uint) {}
+}
+
/// A `Writer` which multiplexes writes to a set of `Writers`.
pub struct MultiWriter {
writers: Vec<Box<Writer>>
#[cfg(test)]
mod test {
+ use io::{MemReader, MemWriter, BufReader};
use io;
- use io::{MemReader, MemWriter};
use owned::Box;
use super::*;
use prelude::*;
copy(&mut r, &mut w).unwrap();
assert_eq!(vec!(0, 1, 2, 3, 4), w.unwrap());
}
+
+ #[test]
+ fn limit_reader_buffer() {
+ let data = "0123456789\n0123456789\n";
+ let mut r = BufReader::new(data.as_bytes());
+ {
+ let mut r = LimitReader::new(r.by_ref(), 3);
+ assert_eq!(r.read_line(), Ok("012".to_str()));
+ assert_eq!(r.limit(), 0);
+ assert_eq!(r.read_line().err().unwrap().kind, io::EndOfFile);
+ }
+ {
+ let mut r = LimitReader::new(r.by_ref(), 9);
+ assert_eq!(r.read_line(), Ok("3456789\n".to_str()));
+ assert_eq!(r.limit(), 1);
+ assert_eq!(r.read_line(), Ok("0".to_str()));
+ }
+ {
+ let mut r = LimitReader::new(r.by_ref(), 100);
+ assert_eq!(r.read_char(), Ok('1'));
+ assert_eq!(r.limit(), 99);
+ assert_eq!(r.read_line(), Ok("23456789\n".to_str()));
+ }
+ }
}
pub use ty;
pub use unstable;
pub use vec;
+
+ // The test runner requires std::slice::Vector, so re-export std::slice just for it.
+ #[cfg(test)] pub use slice;
}
modify/read the slot specified by the key.
```rust
-use std::local_data;
-
local_data_key!(key_int: int)
local_data_key!(key_vector: ~[int])
-local_data::set(key_int, 3);
-local_data::get(key_int, |opt| assert_eq!(opt.map(|x| *x), Some(3)));
+key_int.replace(Some(3));
+assert_eq!(*key_int.get().unwrap(), 3);
-local_data::set(key_vector, ~[4]);
-local_data::get(key_vector, |opt| assert_eq!(*opt.unwrap(), ~[4]));
+key_vector.replace(Some(~[4]));
+assert_eq!(*key_vector.get().unwrap(), ~[4]);
```
*/
use cast;
use iter::{Iterator};
use kinds::Send;
+use kinds::marker;
use mem::replace;
+use ops::{Drop, Deref};
use option::{None, Option, Some};
use owned::Box;
+use raw;
use rt::task::{Task, LocalStorage};
use slice::{ImmutableVector, MutableVector};
use vec::Vec;
#[allow(missing_doc)]
pub enum KeyValue<T> { Key }
-#[allow(missing_doc)]
+#[doc(hidden)]
trait LocalData {}
impl<T: 'static> LocalData for T {}
// n.b. If TLS is used heavily in future, this could be made more efficient with
// a proper map.
#[doc(hidden)]
-pub type Map = Vec<Option<(*u8, TLSValue, LoanState)>>;
+pub type Map = Vec<Option<(*u8, TLSValue, uint)>>;
type TLSValue = Box<LocalData:Send>;
// Gets the map from the runtime. Lazily initialises if not done so already.
*slot = Some(vec!());
match *slot {
Some(ref mut map_ptr) => { return map_ptr }
- None => abort()
+ None => unreachable!(),
}
}
}
}
-#[deriving(Eq)]
-enum LoanState {
- NoLoan, ImmLoan, MutLoan
-}
-
-impl LoanState {
- fn describe(&self) -> &'static str {
- match *self {
- NoLoan => "no loan",
- ImmLoan => "immutable",
- MutLoan => "mutable"
- }
- }
-}
-
fn key_to_key_value<T: 'static>(key: Key<T>) -> *u8 {
- unsafe { cast::transmute(key) }
+ key as *KeyValue<T> as *u8
}
-/// Removes a task-local value from task-local storage. This will return
-/// Some(value) if the key was present in TLS, otherwise it will return None.
+/// An RAII immutable reference to a task-local value.
///
-/// A runtime assertion will be triggered it removal of TLS value is attempted
-/// while the value is still loaned out via `get` or `get_mut`.
-pub fn pop<T: 'static>(key: Key<T>) -> Option<T> {
- let map = unsafe { get_local_map() };
- let key_value = key_to_key_value(key);
-
- for entry in map.mut_iter() {
- match *entry {
- Some((k, _, loan)) if k == key_value => {
- if loan != NoLoan {
- fail!("TLS value cannot be removed because it is currently \
- borrowed as {}", loan.describe());
- }
- // Move the data out of the `entry` slot via prelude::replace.
- // This is guaranteed to succeed because we already matched
- // on `Some` above.
- let data = match replace(entry, None) {
- Some((_, data, _)) => data,
- None => abort()
- };
-
- // Move `data` into transmute to get out the memory that it
- // owns, we must free it manually later.
- let (_vtable, alloc): (uint, Box<T>) = unsafe {
- cast::transmute(data)
- };
-
- // Now that we own `alloc`, we can just move out of it as we
- // would with any other data.
- return Some(*alloc);
- }
- _ => {}
- }
- }
- return None;
+/// The task-local data can be accessed through this value, and when this
+/// structure is dropped it will return the borrow on the data.
+pub struct Ref<T> {
+ ptr: &'static T,
+ key: Key<T>,
+ index: uint,
+ nosend: marker::NoSend,
}
-/// Retrieves a value from TLS. The closure provided is yielded `Some` of a
-/// reference to the value located in TLS if one exists, or `None` if the key
-/// provided is not present in TLS currently.
-///
-/// It is considered a runtime error to attempt to get a value which is already
-/// on loan via the `get_mut` method provided.
-pub fn get<T: 'static, U>(key: Key<T>, f: |Option<&T>| -> U) -> U {
- get_with(key, ImmLoan, f)
-}
-
-/// Retrieves a mutable value from TLS. The closure provided is yielded `Some`
-/// of a reference to the mutable value located in TLS if one exists, or `None`
-/// if the key provided is not present in TLS currently.
-///
-/// It is considered a runtime error to attempt to get a value which is already
-/// on loan via this or the `get` methods.
-pub fn get_mut<T: 'static, U>(key: Key<T>, f: |Option<&mut T>| -> U) -> U {
- get_with(key, MutLoan, |x| {
- match x {
- None => f(None),
- // We're violating a lot of compiler guarantees with this
- // invocation of `transmute`, but we're doing runtime checks to
- // ensure that it's always valid (only one at a time).
- //
- // there is no need to be upset!
- Some(x) => { f(Some(unsafe { cast::transmute::<&_, &mut _>(x) })) }
- }
- })
-}
+impl<T: 'static> KeyValue<T> {
+ /// Replaces a value in task local storage.
+ ///
+ /// If this key is already present in TLS, then the previous value is
+ /// replaced with the provided data, and then returned.
+ ///
+ /// # Failure
+ ///
+ /// This function will fail if this key is present in TLS and currently on
+ /// loan with the `get` method.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// local_data_key!(foo: int)
+ ///
+ /// assert_eq!(foo.replace(Some(10)), None);
+ /// assert_eq!(foo.replace(Some(4)), Some(10));
+ /// assert_eq!(foo.replace(None), Some(4));
+ /// ```
+ pub fn replace(&'static self, data: Option<T>) -> Option<T> {
+ let map = unsafe { get_local_map() };
+ let keyval = key_to_key_value(self);
+
+ // When the task-local map is destroyed, all the data needs to be
+ // cleaned up. For this reason we can't do some clever tricks to store
+ // '~T' as a '*c_void' or something like that. To solve the problem, we
+ // cast everything to a trait (LocalData) which is then stored inside
+ // the map. Upon destruction of the map, all the objects will be
+ // destroyed and the traits have enough information about them to
+ // destroy themselves.
+ //
+ // Additionally, the type of the local data map must ascribe to Send, so
+ // we do the transmute here to add the Send bound back on. This doesn't
+ // actually matter because TLS will always own the data (until its moved
+ // out) and we're not actually sending it to other schedulers or
+ // anything.
+ let newval = data.map(|d| {
+ let d = box d as Box<LocalData>;
+ let d: Box<LocalData:Send> = unsafe { cast::transmute(d) };
+ (keyval, d, 0)
+ });
-fn get_with<T:'static,
- U>(
- key: Key<T>,
- state: LoanState,
- f: |Option<&T>| -> U)
- -> U {
- // This function must be extremely careful. Because TLS can store owned
- // values, and we must have some form of `get` function other than `pop`,
- // this function has to give a `&` reference back to the caller.
- //
- // One option is to return the reference, but this cannot be sound because
- // the actual lifetime of the object is not known. The slot in TLS could not
- // be modified until the object goes out of scope, but the TLS code cannot
- // know when this happens.
- //
- // For this reason, the reference is yielded to a specified closure. This
- // way the TLS code knows exactly what the lifetime of the yielded pointer
- // is, allowing callers to acquire references to owned data. This is also
- // sound so long as measures are taken to ensure that while a TLS slot is
- // loaned out to a caller, it's not modified recursively.
- let map = unsafe { get_local_map() };
- let key_value = key_to_key_value(key);
-
- let pos = map.iter().position(|entry| {
- match *entry {
- Some((k, _, _)) if k == key_value => true, _ => false
- }
- });
- match pos {
- None => { return f(None); }
- Some(i) => {
- let ret;
- let mut return_loan = false;
- match *map.get_mut(i) {
- Some((_, ref data, ref mut loan)) => {
- match (state, *loan) {
- (_, NoLoan) => {
- *loan = state;
- return_loan = true;
- }
- (ImmLoan, ImmLoan) => {}
- (want, cur) => {
- fail!("TLS slot cannot be borrowed as {} because \
- it is already borrowed as {}",
- want.describe(), cur.describe());
- }
- }
- // data was created with `box T as Box<LocalData>`, so we
- // extract pointer part of the trait, (as Box<T>), and
- // then use compiler coercions to achieve a '&' pointer.
- unsafe {
- match *cast::transmute::<&TLSValue,
- &(uint, Box<T>)>(data){
- (_vtable, ref alloc) => {
- let value: &T = *alloc;
- ret = f(Some(value));
- }
- }
- }
- }
- _ => abort()
+ let pos = match self.find(map) {
+ Some((i, _, &0)) => Some(i),
+ Some((_, _, _)) => fail!("TLS value cannot be replaced because it \
+ is already borrowed"),
+ None => map.iter().position(|entry| entry.is_none()),
+ };
+
+ match pos {
+ Some(i) => {
+ replace(map.get_mut(i), newval).map(|(_, data, _)| {
+ // Move `data` into transmute to get out the memory that it
+ // owns, we must free it manually later.
+ let t: raw::TraitObject = unsafe { cast::transmute(data) };
+ let alloc: Box<T> = unsafe { cast::transmute(t.data) };
+
+ // Now that we own `alloc`, we can just move out of it as we
+ // would with any other data.
+ *alloc
+ })
}
-
- // n.b. 'data' and 'loans' are both invalid pointers at the point
- // 'f' returned because `f` could have appended more TLS items which
- // in turn relocated the vector. Hence we do another lookup here to
- // fixup the loans.
- if return_loan {
- match *map.get_mut(i) {
- Some((_, _, ref mut loan)) => { *loan = NoLoan; }
- None => abort()
- }
+ None => {
+ map.push(newval);
+ None
}
- return ret;
}
}
-}
-fn abort() -> ! {
- use intrinsics;
- unsafe { intrinsics::abort() }
-}
+ /// Borrows a value from TLS.
+ ///
+ /// If `None` is returned, then this key is not present in TLS. If `Some` is
+ /// returned, then the returned data is a smart pointer representing a new
+ /// loan on this TLS key. While on loan, this key cannot be altered via the
+ /// `replace` method.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// local_data_key!(key: int)
+ ///
+ /// assert!(key.get().is_none());
+ ///
+ /// key.replace(Some(3));
+ /// assert_eq!(*key.get().unwrap(), 3);
+ /// ```
+ pub fn get(&'static self) -> Option<Ref<T>> {
+ let map = unsafe { get_local_map() };
+
+ self.find(map).map(|(pos, data, loan)| {
+ *loan += 1;
+
+ // data was created with `~T as ~LocalData`, so we extract
+ // pointer part of the trait, (as ~T), and then use
+ // compiler coercions to achieve a '&' pointer.
+ let ptr = unsafe {
+ let data = data as *Box<LocalData:Send> as *raw::TraitObject;
+ &mut *((*data).data as *mut T)
+ };
+ Ref { ptr: ptr, index: pos, nosend: marker::NoSend, key: self }
+ })
+ }
-/// Inserts a value into task local storage. If the key is already present in
-/// TLS, then the previous value is removed and replaced with the provided data.
-///
-/// It is considered a runtime error to attempt to set a key which is currently
-/// on loan via the `get` or `get_mut` methods.
-pub fn set<T: 'static>(key: Key<T>, data: T) {
- let map = unsafe { get_local_map() };
- let keyval = key_to_key_value(key);
-
- // When the task-local map is destroyed, all the data needs to be cleaned
- // up. For this reason we can't do some clever tricks to store 'Box<T>' as
- // a '*c_void' or something like that. To solve the problem, we cast
- // everything to a trait (LocalData) which is then stored inside the map.
- // Upon destruction of the map, all the objects will be destroyed and the
- // traits have enough information about them to destroy themselves.
- let data = box data as Box<LocalData:>;
-
- fn insertion_position(map: &mut Map,
- key: *u8) -> Option<uint> {
- // First see if the map contains this key already
- let curspot = map.iter().position(|entry| {
+ fn find<'a>(&'static self,
+ map: &'a mut Map) -> Option<(uint, &'a TLSValue, &'a mut uint)>{
+ let key_value = key_to_key_value(self);
+ map.mut_iter().enumerate().filter_map(|(i, entry)| {
match *entry {
- Some((ekey, _, loan)) if key == ekey => {
- if loan != NoLoan {
- fail!("TLS value cannot be overwritten because it is
- already borrowed as {}", loan.describe())
- }
- true
+ Some((k, ref data, ref mut loan)) if k == key_value => {
+ Some((i, data, loan))
}
- _ => false,
+ _ => None
}
- });
- // If it doesn't contain the key, just find a slot that's None
- match curspot {
- Some(i) => Some(i),
- None => map.iter().position(|entry| entry.is_none())
- }
+ }).next()
}
+}
- // The type of the local data map must ascribe to Send, so we do the
- // transmute here to add the Send bound back on. This doesn't actually
- // matter because TLS will always own the data (until its moved out) and
- // we're not actually sending it to other schedulers or anything.
- let data: Box<LocalData:Send> = unsafe { cast::transmute(data) };
- match insertion_position(map, keyval) {
- Some(i) => { *map.get_mut(i) = Some((keyval, data, NoLoan)); }
- None => { map.push(Some((keyval, data, NoLoan))); }
- }
+impl<T: 'static> Deref<T> for Ref<T> {
+ fn deref<'a>(&'a self) -> &'a T { self.ptr }
}
-/// Modifies a task-local value by temporarily removing it from task-local
-/// storage and then re-inserting if `Some` is returned from the closure.
-///
-/// This function will have the same runtime errors as generated from `pop` and
-/// `set` (the key must not currently be on loan
-pub fn modify<T: 'static>(key: Key<T>, f: |Option<T>| -> Option<T>) {
- match f(pop(key)) {
- Some(next) => { set(key, next); }
- None => {}
+#[unsafe_destructor]
+impl<T: 'static> Drop for Ref<T> {
+ fn drop(&mut self) {
+ let map = unsafe { get_local_map() };
+
+ let (_, _, ref mut loan) = *map.get_mut(self.index).get_mut_ref();
+ *loan -= 1;
}
}
#[test]
fn test_tls_multitask() {
static my_key: Key<~str> = &Key;
- set(my_key, "parent data".to_owned());
+ my_key.replace(Some("parent data".to_owned()));
task::spawn(proc() {
// TLS shouldn't carry over.
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).is_none());
- set(my_key, "child data".to_owned());
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() ==
- "child data".to_owned());
+ assert!(my_key.get().is_none());
+ my_key.replace(Some("child data".to_owned()));
+ assert!(my_key.get().get_ref().as_slice() == "child data");
// should be cleaned up for us
});
+
// Must work multiple times
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "parent data".to_owned());
+ assert!(my_key.get().unwrap().as_slice() == "parent data");
+ assert!(my_key.get().unwrap().as_slice() == "parent data");
+ assert!(my_key.get().unwrap().as_slice() == "parent data");
}
#[test]
fn test_tls_overwrite() {
static my_key: Key<~str> = &Key;
- set(my_key, "first data".to_owned());
- set(my_key, "next data".to_owned()); // Shouldn't leak.
- assert!(get(my_key, |k| k.map(|k| (*k).clone())).unwrap() == "next data".to_owned());
+ my_key.replace(Some("first data".to_owned()));
+ my_key.replace(Some("next data".to_owned())); // Shouldn't leak.
+ assert!(my_key.get().unwrap().as_slice() == "next data");
}
#[test]
fn test_tls_pop() {
static my_key: Key<~str> = &Key;
- set(my_key, "weasel".to_owned());
- assert!(pop(my_key).unwrap() == "weasel".to_owned());
+ my_key.replace(Some("weasel".to_owned()));
+ assert!(my_key.replace(None).unwrap() == "weasel".to_owned());
// Pop must remove the data from the map.
- assert!(pop(my_key).is_none());
- }
-
- #[test]
- fn test_tls_modify() {
- static my_key: Key<~str> = &Key;
- modify(my_key, |data| {
- match data {
- Some(ref val) => fail!("unwelcome value: {}", *val),
- None => Some("first data".to_owned())
- }
- });
- modify(my_key, |data| {
- match data.as_ref().map(|s| s.as_slice()) {
- Some("first data") => Some("next data".to_owned()),
- Some(ref val) => fail!("wrong value: {}", *val),
- None => fail!("missing value")
- }
- });
- assert!(pop(my_key).unwrap() == "next data".to_owned());
+ assert!(my_key.replace(None).is_none());
}
#[test]
// a stack smaller than 1 MB.
static my_key: Key<~str> = &Key;
task::spawn(proc() {
- set(my_key, "hax".to_owned());
+ my_key.replace(Some("hax".to_owned()));
});
}
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
task::spawn(proc() {
- set(str_key, "string data".to_owned());
- set(box_key, @());
- set(int_key, 42);
+ str_key.replace(Some("string data".to_owned()));
+ box_key.replace(Some(@()));
+ int_key.replace(Some(42));
});
}
#[test]
- #[allow(dead_code)]
fn test_tls_overwrite_multiple_types() {
static str_key: Key<~str> = &Key;
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
task::spawn(proc() {
- set(str_key, "string data".to_owned());
- set(str_key, "string data 2".to_owned());
- set(box_key, @());
- set(box_key, @());
- set(int_key, 42);
+ str_key.replace(Some("string data".to_owned()));
+ str_key.replace(Some("string data 2".to_owned()));
+ box_key.replace(Some(@()));
+ box_key.replace(Some(@()));
+ int_key.replace(Some(42));
// This could cause a segfault if overwriting-destruction is done
// with the crazy polymorphic transmute rather than the provided
// finaliser.
- set(int_key, 31337);
+ int_key.replace(Some(31337));
});
}
static str_key: Key<~str> = &Key;
static box_key: Key<@()> = &Key;
static int_key: Key<int> = &Key;
- set(str_key, "parent data".to_owned());
- set(box_key, @());
+ str_key.replace(Some("parent data".to_owned()));
+ box_key.replace(Some(@()));
task::spawn(proc() {
- // spawn_linked
- set(str_key, "string data".to_owned());
- set(box_key, @());
- set(int_key, 42);
+ str_key.replace(Some("string data".to_owned()));
+ box_key.replace(Some(@()));
+ int_key.replace(Some(42));
fail!();
});
// Not quite nondeterministic.
- set(int_key, 31337);
+ int_key.replace(Some(31337));
fail!();
}
fn test_static_pointer() {
static key: Key<&'static int> = &Key;
static VALUE: int = 0;
- let v: &'static int = &VALUE;
- set(key, v);
+ key.replace(Some(&VALUE));
}
#[test]
fn test_owned() {
static key: Key<Box<int>> = &Key;
- set(key, box 1);
-
- get(key, |v| {
- get(key, |v| {
- get(key, |v| {
- assert_eq!(**v.unwrap(), 1);
- });
- assert_eq!(**v.unwrap(), 1);
- });
- assert_eq!(**v.unwrap(), 1);
- });
- set(key, box 2);
- get(key, |v| {
- assert_eq!(**v.unwrap(), 2);
- })
- }
-
- #[test]
- fn test_get_mut() {
- static key: Key<int> = &Key;
- set(key, 1);
-
- get_mut(key, |v| {
- *v.unwrap() = 2;
- });
-
- get(key, |v| {
- assert_eq!(*v.unwrap(), 2);
- })
+ key.replace(Some(box 1));
+
+ {
+ let k1 = key.get().unwrap();
+ let k2 = key.get().unwrap();
+ let k3 = key.get().unwrap();
+ assert_eq!(**k1, 1);
+ assert_eq!(**k2, 1);
+ assert_eq!(**k3, 1);
+ }
+ key.replace(Some(box 2));
+ assert_eq!(**key.get().unwrap(), 2);
}
#[test]
static key3: Key<int> = &Key;
static key4: Key<int> = &Key;
static key5: Key<int> = &Key;
- set(key1, 1);
- set(key2, 2);
- set(key3, 3);
- set(key4, 4);
- set(key5, 5);
-
- get(key1, |x| assert_eq!(*x.unwrap(), 1));
- get(key2, |x| assert_eq!(*x.unwrap(), 2));
- get(key3, |x| assert_eq!(*x.unwrap(), 3));
- get(key4, |x| assert_eq!(*x.unwrap(), 4));
- get(key5, |x| assert_eq!(*x.unwrap(), 5));
+ key1.replace(Some(1));
+ key2.replace(Some(2));
+ key3.replace(Some(3));
+ key4.replace(Some(4));
+ key5.replace(Some(5));
+
+ assert_eq!(*key1.get().unwrap(), 1);
+ assert_eq!(*key2.get().unwrap(), 2);
+ assert_eq!(*key3.get().unwrap(), 3);
+ assert_eq!(*key4.get().unwrap(), 4);
+ assert_eq!(*key5.get().unwrap(), 5);
}
#[test]
#[should_fail]
fn test_nested_get_set1() {
static key: Key<int> = &Key;
- set(key, 4);
- get(key, |_| {
- set(key, 4);
- })
- }
-
- #[test]
- #[should_fail]
- fn test_nested_get_mut2() {
- static key: Key<int> = &Key;
- set(key, 4);
- get(key, |_| {
- get_mut(key, |_| {})
- })
- }
-
- #[test]
- #[should_fail]
- fn test_nested_get_mut3() {
- static key: Key<int> = &Key;
- set(key, 4);
- get_mut(key, |_| {
- get(key, |_| {})
- })
- }
+ key.replace(Some(4));
- #[test]
- #[should_fail]
- fn test_nested_get_mut4() {
- static key: Key<int> = &Key;
- set(key, 4);
- get_mut(key, |_| {
- get_mut(key, |_| {})
- })
+ let _k = key.get();
+ key.replace(Some(4));
}
}
/// # Example
///
/// ```
-/// use std::local_data;
-///
/// local_data_key!(my_integer: int)
///
-/// local_data::set(my_integer, 2);
-/// local_data::get(my_integer, |val| println!("{}", val.map(|i| *i)));
+/// my_integer.replace(Some(2));
+/// println!("{}", my_integer.get().map(|a| *a));
/// ```
#[macro_export]
macro_rules! local_data_key(
//! Operations and constants for signed 16-bits integers (`i16` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::i16::{BITS, BYTES, MIN, MAX};
//! Operations and constants for signed 32-bits integers (`i32` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::i32::{BITS, BYTES, MIN, MAX};
//! Operations and constants for signed 64-bits integers (`i64` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::i64::{BITS, BYTES, MIN, MAX};
//! Operations and constants for signed 8-bits integers (`i8` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::i8::{BITS, BYTES, MIN, MAX};
//! Operations and constants for architecture-sized signed integers (`int` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::int::{BITS, BYTES, MIN, MAX};
/// Convert to a string in a given base.
#[inline]
fn to_str_radix(&self, radix: uint) -> ~str {
+ use slice::Vector;
+ use str::StrAllocating;
+
let mut buf = ::vec::Vec::new();
strconv::int_to_str_bytes_common(*self, radix, strconv::SignNeg, |i| {
buf.push(i);
});
// We know we generated valid utf-8, so we don't need to go through that
// check.
- unsafe { str::raw::from_utf8_owned(buf.move_iter().collect()) }
+ unsafe { str::raw::from_utf8(buf.as_slice()).to_owned() }
}
}
use num;
use ops::{Add, Sub, Mul, Div, Rem, Neg};
use option::{None, Option, Some};
-use slice::OwnedVector;
use slice::{CloneableVector, ImmutableVector, MutableVector};
use std::cmp::{Ord, Eq};
-use str::{StrSlice};
-use str;
+use str::{StrAllocating, StrSlice};
+use strbuf::StrBuf;
use vec::Vec;
/// A flag that specifies whether to use exponential (scientific) notation.
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
num: T, radix: uint, negative_zero: bool,
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
- ) -> (~[u8], bool) {
+ ) -> (Vec<u8>, bool) {
assert!(2 <= radix && radix <= 36);
match exp_format {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
let _1: T = One::one();
match num.classify() {
- FPNaN => { return ("NaN".as_bytes().to_owned(), true); }
+ FPNaN => { return (Vec::from_slice("NaN".as_bytes()), true); }
FPInfinite if num > _0 => {
return match sign {
- SignAll => ("+inf".as_bytes().to_owned(), true),
- _ => ("inf".as_bytes().to_owned(), true)
+ SignAll => (Vec::from_slice("+inf".as_bytes()), true),
+ _ => (Vec::from_slice("inf".as_bytes()), true)
};
}
FPInfinite if num < _0 => {
return match sign {
- SignNone => ("inf".as_bytes().to_owned(), true),
- _ => ("-inf".as_bytes().to_owned(), true),
+ SignNone => (Vec::from_slice("inf".as_bytes()), true),
+ _ => (Vec::from_slice("-inf".as_bytes()), true),
};
}
_ => {}
}
}
- (buf.move_iter().collect(), false)
+ (buf, false)
}
/**
) -> (~str, bool) {
let (bytes, special) = float_to_str_bytes_common(num, radix,
negative_zero, sign, digits, exp_format, exp_capital);
- (str::from_utf8_owned(bytes).unwrap(), special)
+ (StrBuf::from_utf8(bytes).unwrap().into_owned(), special)
}
// Some constants for from_str_bytes_common's input validation,
//! Operations and constants for unsigned 16-bits integers (`u16` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::u16::{BITS, BYTES, MIN, MAX};
//! Operations and constants for unsigned 32-bits integers (`u32` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::u32::{BITS, BYTES, MIN, MAX};
//! Operations and constants for unsigned 64-bits integer (`u64` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::u64::{BITS, BYTES, MIN, MAX};
//! Operations and constants for unsigned 8-bits integers (`u8` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::u8::{BITS, BYTES, MIN, MAX};
//! Operations and constants for architecture-sized unsigned integers (`uint` type)
use from_str::FromStr;
-use iter::Iterator;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::{ImmutableVector, OwnedVector};
+use slice::ImmutableVector;
use str;
pub use core::uint::{BITS, BYTES, MIN, MAX};
/// Convert to a string in a given base.
#[inline]
fn to_str_radix(&self, radix: uint) -> ~str {
+ use slice::Vector;
+ use str::StrAllocating;
+
let mut buf = ::vec::Vec::new();
strconv::int_to_str_bytes_common(*self, radix, strconv::SignNone, |i| {
buf.push(i);
});
// We know we generated valid utf-8, so we don't need to go through that
// check.
- unsafe { str::raw::from_utf8_owned(buf.move_iter().collect()) }
+ unsafe { str::raw::from_utf8(buf.as_slice()).to_owned() }
}
}
///
/// Invalid UTF-8 bytes are replaced with \uFFFD. See `str::from_utf8_lossy()`
/// for details.
-pub fn env() -> ~[(~str,~str)] {
+pub fn env() -> Vec<(~str,~str)> {
env_as_bytes().move_iter().map(|(k,v)| {
let k = str::from_utf8_lossy(k).into_owned();
let v = str::from_utf8_lossy(v).into_owned();
/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
-pub fn env_as_bytes() -> ~[(~[u8],~[u8])] {
+pub fn env_as_bytes() -> Vec<(~[u8],~[u8])> {
unsafe {
#[cfg(windows)]
unsafe fn get_env_pairs() -> Vec<~[u8]> {
fn env_convert(input: Vec<~[u8]>) -> Vec<(~[u8], ~[u8])> {
let mut pairs = Vec::new();
for p in input.iter() {
- let vs: ~[&[u8]] = p.splitn(1, |b| *b == '=' as u8).collect();
- let key = vs[0].to_owned();
- let val = if vs.len() < 2 { box [] } else { vs[1].to_owned() };
+ let mut it = p.splitn(1, |b| *b == '=' as u8);
+ let key = it.next().unwrap().to_owned();
+ let val = it.next().unwrap_or(&[]).to_owned();
pairs.push((key, val));
}
pairs
}
with_env_lock(|| {
let unparsed_environ = get_env_pairs();
- env_convert(unparsed_environ).move_iter().collect()
+ env_convert(unparsed_environ)
})
}
}
pub fn self_exe_name() -> Option<Path> {
#[cfg(target_os = "freebsd")]
- fn load_self() -> Option<~[u8]> {
+ fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::bsd44::*;
use libc::consts::os::extra::*;
if err != 0 { return None; }
if sz == 0 { return None; }
v.set_len(sz as uint - 1); // chop off trailing NUL
- Some(v.move_iter().collect())
+ Some(v)
}
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
- fn load_self() -> Option<~[u8]> {
+ fn load_self() -> Option<Vec<u8>> {
use std::io;
match io::fs::readlink(&Path::new("/proc/self/exe")) {
- Ok(path) => Some(path.as_vec().to_owned()),
+ Ok(path) => Some(path.into_vec()),
Err(..) => None
}
}
#[cfg(target_os = "macos")]
- fn load_self() -> Option<~[u8]> {
+ fn load_self() -> Option<Vec<u8>> {
unsafe {
use libc::funcs::extra::_NSGetExecutablePath;
let mut sz: u32 = 0;
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
if err != 0 { return None; }
v.set_len(sz as uint - 1); // chop off trailing NUL
- Some(v.move_iter().collect())
+ Some(v)
}
}
#[cfg(windows)]
- fn load_self() -> Option<~[u8]> {
+ fn load_self() -> Option<Vec<u8>> {
use str::OwnedStr;
unsafe {
use os::win32::fill_utf16_buf_and_decode;
fill_utf16_buf_and_decode(|buf, sz| {
libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
- }).map(|s| s.into_bytes())
+ }).map(|s| s.into_strbuf().into_bytes())
}
}
}
#[cfg(target_os = "macos")]
-unsafe fn load_argc_and_argv(argc: int, argv: **c_char) -> ~[~[u8]] {
+unsafe fn load_argc_and_argv(argc: int, argv: **c_char) -> Vec<~[u8]> {
use c_str::CString;
Vec::from_fn(argc as uint, |i| {
CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_owned()
- }).move_iter().collect()
+ })
}
/**
* Returns a list of the command line arguments.
*/
#[cfg(target_os = "macos")]
-fn real_args_as_bytes() -> ~[~[u8]] {
+fn real_args_as_bytes() -> Vec<~[u8]> {
unsafe {
let (argc, argv) = (*_NSGetArgc() as int,
*_NSGetArgv() as **c_char);
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
-fn real_args_as_bytes() -> ~[~[u8]] {
+fn real_args_as_bytes() -> Vec<~[u8]> {
use rt;
match rt::args::clone() {
}
#[cfg(not(windows))]
-fn real_args() -> ~[~str] {
+fn real_args() -> Vec<~str> {
real_args_as_bytes().move_iter().map(|v| str::from_utf8_lossy(v).into_owned()).collect()
}
#[cfg(windows)]
-fn real_args() -> ~[~str] {
+fn real_args() -> Vec<~str> {
use slice;
use option::Expect;
LocalFree(szArgList as *c_void);
}
- return args.move_iter().collect();
+ return args
}
#[cfg(windows)]
-fn real_args_as_bytes() -> ~[~[u8]] {
+fn real_args_as_bytes() -> Vec<~[u8]> {
real_args().move_iter().map(|s| s.into_bytes()).collect()
}
///
/// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD.
/// See `str::from_utf8_lossy` for details.
-pub fn args() -> ~[~str] {
+pub fn args() -> Vec<~str> {
real_args()
}
/// Returns the arguments which this program was started with (normally passed
/// via the command line) as byte vectors.
-pub fn args_as_bytes() -> ~[~[u8]] {
+pub fn args_as_bytes() -> Vec<~[u8]> {
real_args_as_bytes()
}
//! FIXME #7756: This has a lot of C glue for lack of globals.
use option::Option;
+use vec::Vec;
#[cfg(test)] use option::{Some, None};
#[cfg(test)] use realstd;
#[cfg(test)] use realargs = realstd::rt::args;
#[cfg(test)] pub unsafe fn cleanup() { realargs::cleanup() }
/// Take the global arguments from global storage.
-#[cfg(not(test))] pub fn take() -> Option<~[~[u8]]> { imp::take() }
-#[cfg(test)] pub fn take() -> Option<~[~[u8]]> {
+#[cfg(not(test))] pub fn take() -> Option<Vec<~[u8]>> { imp::take() }
+#[cfg(test)] pub fn take() -> Option<Vec<~[u8]>> {
match realargs::take() {
- realstd::option::Some(a) => Some(a),
+ realstd::option::Some(v) => Some(unsafe{ ::cast::transmute(v) }),
realstd::option::None => None,
}
}
/// Give the global arguments to global storage.
///
/// It is an error if the arguments already exist.
-#[cfg(not(test))] pub fn put(args: ~[~[u8]]) { imp::put(args) }
-#[cfg(test)] pub fn put(args: ~[~[u8]]) { realargs::put(args) }
+#[cfg(not(test))] pub fn put(args: Vec<~[u8]>) { imp::put(args) }
+#[cfg(test)] pub fn put(args: Vec<~[u8]>) { realargs::put(unsafe { ::cast::transmute(args) }) }
/// Make a clone of the global arguments.
-#[cfg(not(test))] pub fn clone() -> Option<~[~[u8]]> { imp::clone() }
-#[cfg(test)] pub fn clone() -> Option<~[~[u8]]> {
+#[cfg(not(test))] pub fn clone() -> Option<Vec<~[u8]>> { imp::clone() }
+#[cfg(test)] pub fn clone() -> Option<Vec<~[u8]>> {
match realargs::clone() {
- realstd::option::Some(a) => Some(a),
+ realstd::option::Some(v) => Some(unsafe { ::cast::transmute(v) }),
realstd::option::None => None,
}
}
use owned::Box;
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use mem;
+ use vec::Vec;
#[cfg(not(test))] use ptr::RawPtr;
static mut global_args_ptr: uint = 0;
lock.destroy();
}
- pub fn take() -> Option<~[~[u8]]> {
+ pub fn take() -> Option<Vec<~[u8]>> {
with_lock(|| unsafe {
let ptr = get_global_ptr();
let val = mem::replace(&mut *ptr, None);
- val.as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone())
+ val.as_ref().map(|s: &Box<Vec<~[u8]>>| (**s).clone())
})
}
- pub fn put(args: ~[~[u8]]) {
+ pub fn put(args: Vec<~[u8]>) {
with_lock(|| unsafe {
let ptr = get_global_ptr();
rtassert!((*ptr).is_none());
})
}
- pub fn clone() -> Option<~[~[u8]]> {
+ pub fn clone() -> Option<Vec<~[u8]>> {
with_lock(|| unsafe {
let ptr = get_global_ptr();
- (*ptr).as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone())
+ (*ptr).as_ref().map(|s: &Box<Vec<~[u8]>>| (**s).clone())
})
}
}
}
- fn get_global_ptr() -> *mut Option<Box<~[~[u8]]>> {
+ fn get_global_ptr() -> *mut Option<Box<Vec<~[u8]>>> {
unsafe { cast::transmute(&global_args_ptr) }
}
// Copied from `os`.
#[cfg(not(test))]
- unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> ~[~[u8]] {
+ unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> Vec<~[u8]> {
use c_str::CString;
use ptr::RawPtr;
use libc;
Vec::from_fn(argc as uint, |i| {
let cs = CString::new(*(argv as **libc::c_char).offset(i as int), false);
cs.as_bytes_no_nul().to_owned()
- }).move_iter().collect()
+ })
}
#[cfg(test)]
// Preserve the actual global state.
let saved_value = take();
- let expected = box [bytes!("happy").to_owned(), bytes!("today?").to_owned()];
+ let expected = vec![bytes!("happy").to_owned(), bytes!("today?").to_owned()];
put(expected.clone());
assert!(clone() == Some(expected.clone()));
#[cfg(target_os = "win32", not(test))]
mod imp {
use option::Option;
+ use vec::Vec;
pub unsafe fn init(_argc: int, _argv: **u8) {
}
pub fn cleanup() {
}
- pub fn take() -> Option<~[~[u8]]> {
+ pub fn take() -> Option<Vec<~[u8]>> {
fail!()
}
- pub fn put(_args: ~[~[u8]]) {
+ pub fn put(_args: Vec<~[u8]>) {
fail!()
}
- pub fn clone() -> Option<~[~[u8]]> {
+ pub fn clone() -> Option<Vec<~[u8]>> {
fail!()
}
}
fn unix_connect(&mut self, path: &CString,
timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>>;
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
- hint: Option<ai::Hint>) -> IoResult<~[ai::Info]>;
+ hint: Option<ai::Hint>) -> IoResult<Vec<ai::Info>>;
// filesystem operations
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>>;
fn spawn(&mut self, config: ProcessConfig)
-> IoResult<(Box<RtioProcess:Send>,
- ~[Option<Box<RtioPipe:Send>>])>;
+ Vec<Option<Box<RtioPipe:Send>>>)>;
fn kill(&mut self, pid: libc::pid_t, signal: int) -> IoResult<()>;
fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>>;
fn tty_open(&mut self, fd: c_int, readable: bool)
fn letdie(&mut self) -> IoResult<()>;
fn clone(&self) -> Box<RtioTcpStream:Send>;
fn close_write(&mut self) -> IoResult<()>;
+ fn close_read(&mut self) -> IoResult<()>;
+ fn set_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
}
pub trait RtioSocket {
fn ignore_broadcasts(&mut self) -> IoResult<()>;
fn clone(&self) -> Box<RtioUdpSocket:Send>;
+ fn set_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
}
pub trait RtioTimer {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
fn write(&mut self, buf: &[u8]) -> IoResult<()>;
fn clone(&self) -> Box<RtioPipe:Send>;
+
+ fn close_write(&mut self) -> IoResult<()>;
+ fn close_read(&mut self) -> IoResult<()>;
+ fn set_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_read_timeout(&mut self, timeout_ms: Option<u64>);
+ fn set_write_timeout(&mut self, timeout_ms: Option<u64>);
}
pub trait RtioUnixListener {
}
}
+ /// Reawakens this task if ownership is acquired. If finer-grained control
+ /// is desired, use `wake` instead.
+ pub fn reawaken(self) {
+ self.wake().map(|t| t.reawaken());
+ }
+
// This assertion has two flavours because the wake involves an atomic op.
// In the faster version, destructors will fail dramatically instead.
#[cfg(not(test))] pub fn trash(self) { }
#[test]
fn tls() {
- use local_data;
local_data_key!(key: @~str)
- local_data::set(key, @"data".to_owned());
- assert!(*local_data::get(key, |k| k.map(|k| *k)).unwrap() == "data".to_owned());
+ key.replace(Some(@"data".to_owned()));
+ assert_eq!(key.get().unwrap().as_slice(), "data");
local_data_key!(key2: @~str)
- local_data::set(key2, @"data".to_owned());
- assert!(*local_data::get(key2, |k| k.map(|k| *k)).unwrap() == "data".to_owned());
+ key2.replace(Some(@"data".to_owned()));
+ assert_eq!(key2.get().unwrap().as_slice(), "data");
}
#[test]
// FIXME #5898: calling these .concat and .connect conflicts with
// StrVector::con{cat,nect}, since they have generic contents.
/// Flattens a vector of vectors of T into a single vector of T.
- fn concat_vec(&self) -> ~[T];
+ fn concat_vec(&self) -> Vec<T>;
/// Concatenate a vector of vectors, placing a given separator between each.
- fn connect_vec(&self, sep: &T) -> ~[T];
+ fn connect_vec(&self, sep: &T) -> Vec<T>;
}
impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] {
- fn concat_vec(&self) -> ~[T] {
+ fn concat_vec(&self) -> Vec<T> {
let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
let mut result = Vec::with_capacity(size);
for v in self.iter() {
result.push_all(v.as_slice())
}
- result.move_iter().collect()
+ result
}
- fn connect_vec(&self, sep: &T) -> ~[T] {
+ fn connect_vec(&self, sep: &T) -> Vec<T> {
let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
let mut result = Vec::with_capacity(size + self.len());
let mut first = true;
if first { first = false } else { result.push(sep.clone()) }
result.push_all(v.as_slice())
}
- result.move_iter().collect()
+ result
}
}
-/**
- * Convert an iterator of pairs into a pair of vectors.
- *
- * Returns a tuple containing two vectors where the i-th element of the first
- * vector contains the first element of the i-th tuple of the input iterator,
- * and the i-th element of the second vector contains the second element
- * of the i-th tuple of the input iterator.
- */
-pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (~[T], ~[U]) {
- let (lo, _) = iter.size_hint();
- let mut ts = Vec::with_capacity(lo);
- let mut us = Vec::with_capacity(lo);
- for (t, u) in iter {
- ts.push(t);
- us.push(u);
- }
- (ts.move_iter().collect(), us.move_iter().collect())
-}
-
/// An Iterator that yields the element swaps needed to produce
/// a sequence of all possible permutations for an indexed sequence of
/// elements. Each permutation is only a single swap apart.
/// The last generated swap is always (0, 1), and it returns the
/// sequence to its initial order.
pub struct ElementSwaps {
- sdir: ~[SizeDirection],
+ sdir: Vec<SizeDirection>,
/// If true, emit the last swap that returns the sequence to initial state
emit_reset: bool,
swaps_made : uint,
// element (equal to the original index).
ElementSwaps{
emit_reset: true,
- sdir: range(0, length)
- .map(|i| SizeDirection{ size: i, dir: Neg })
- .collect::<~[_]>(),
+ sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
swaps_made: 0
}
}
let max = self.sdir.iter().map(|&x| x).enumerate()
.filter(|&(i, sd)|
new_pos(i, sd.dir) < self.sdir.len() &&
- self.sdir[new_pos(i, sd.dir)].size < sd.size)
+ self.sdir.get(new_pos(i, sd.dir)).size < sd.size)
.max_by(|&(_, sd)| sd.size);
match max {
Some((i, sd)) => {
let j = new_pos(i, sd.dir);
- self.sdir.swap(i, j);
+ self.sdir.as_mut_slice().swap(i, j);
// Swap the direction of each larger SizeDirection
for x in self.sdir.mut_iter() {
/// Returns a copy of `v`.
#[inline]
fn to_owned(&self) -> ~[T] {
+ use RawVec = core::raw::Vec;
+ use rt::global_heap::{malloc_raw, exchange_free};
+ use num::{CheckedAdd, CheckedMul};
+ use option::Expect;
+
let len = self.len();
- let mut result = Vec::with_capacity(len);
- // Unsafe code so this can be optimised to a memcpy (or something
- // similarly fast) when T is Copy. LLVM is easily confused, so any
- // extra operations during the loop can prevent this optimisation
+ let data_size = len.checked_mul(&mem::size_of::<T>());
+ let data_size = data_size.expect("overflow in to_owned()");
+ let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
+ let size = size.expect("overflow in to_owned()");
+
unsafe {
+ let ret = malloc_raw(size) as *mut RawVec<()>;
+
+ (*ret).fill = len * mem::nonzero_size_of::<T>();
+ (*ret).alloc = len * mem::nonzero_size_of::<T>();
+
+ // Be careful with the following loop. We want it to be optimized
+ // to a memcpy (or something similarly fast) when T is Copy. LLVM
+ // is easily confused, so any extra operations during the loop can
+ // prevent this optimization.
let mut i = 0;
- let p = result.as_mut_ptr();
- // Use try_finally here otherwise the write to length
- // inside the loop stops LLVM from optimising this.
+ let p = &mut (*ret).data as *mut _ as *mut T;
try_finally(
&mut i, (),
|i, ()| while *i < len {
self.unsafe_ref(*i).clone());
*i += 1;
},
- |i| result.set_len(*i));
+ |i| if *i < len {
+ // we must be failing, clean up after ourselves
+ for j in range(0, *i as int) {
+ ptr::read(&*p.offset(j));
+ }
+ exchange_free(ret as *u8);
+ });
+ cast::transmute(ret)
}
- result.move_iter().collect()
}
#[inline(always)]
pub trait ImmutableCloneableVector<T> {
/// Partitions the vector into two vectors `(A,B)`, where all
/// elements of `A` satisfy `f` and all elements of `B` do not.
- fn partitioned(&self, f: |&T| -> bool) -> (~[T], ~[T]);
+ fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
/// Create an iterator that yields every possible permutation of the
/// vector in succession.
impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] {
#[inline]
- fn partitioned(&self, f: |&T| -> bool) -> (~[T], ~[T]) {
+ fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
let mut lefts = Vec::new();
let mut rights = Vec::new();
}
}
- (lefts.move_iter().collect(), rights.move_iter().collect())
+ (lefts, rights)
}
fn permutations(self) -> Permutations<T> {
* Partitions the vector into two vectors `(A,B)`, where all
* elements of `A` satisfy `f` and all elements of `B` do not.
*/
- fn partition(self, f: |&T| -> bool) -> (~[T], ~[T]);
+ fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
}
impl<T> OwnedVector<T> for ~[T] {
}
#[inline]
- fn partition(self, f: |&T| -> bool) -> (~[T], ~[T]) {
+ fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
let mut lefts = Vec::new();
let mut rights = Vec::new();
}
}
- (lefts.move_iter().collect(), rights.move_iter().collect())
+ (lefts, rights)
}
}
}
}
-/**
-* Constructs a vector from an unsafe pointer to a buffer
-*
-* # Arguments
-*
-* * ptr - An unsafe pointer to a buffer of `T`
-* * elts - The number of elements in the buffer
-*/
-// Wrapper for fn in raw: needs to be called by net_tcp::on_tcp_read_cb
-pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] {
- raw::from_buf_raw(ptr, elts)
-}
-
/// Unsafe operations
pub mod raw {
- use iter::Iterator;
- use ptr;
- use slice::{MutableVector, OwnedVector};
- use vec::Vec;
-
pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
pub use core::slice::raw::{shift_ptr, pop_ptr};
-
- /**
- * Constructs a vector from an unsafe pointer to a buffer
- *
- * # Arguments
- *
- * * ptr - An unsafe pointer to a buffer of `T`
- * * elts - The number of elements in the buffer
- */
- // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb
- #[inline]
- pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] {
- let mut dst = Vec::with_capacity(elts);
- dst.set_len(elts);
- ptr::copy_memory(dst.as_mut_ptr(), ptr, elts);
- dst.move_iter().collect()
- }
}
/// An iterator that moves out of a vector.
fn is_odd(n: &uint) -> bool { *n % 2u == 1u }
- #[test]
- fn test_unsafe_ptrs() {
- unsafe {
- // Test on-stack copy-from-buf.
- let a = box [1, 2, 3];
- let mut ptr = a.as_ptr();
- let b = from_buf(ptr, 3u);
- assert_eq!(b.len(), 3u);
- assert_eq!(b[0], 1);
- assert_eq!(b[1], 2);
- assert_eq!(b[2], 3);
-
- // Test on-heap copy-from-buf.
- let c = box [1, 2, 3, 4, 5];
- ptr = c.as_ptr();
- let d = from_buf(ptr, 5u);
- assert_eq!(d.len(), 5u);
- assert_eq!(d[0], 1);
- assert_eq!(d[1], 2);
- assert_eq!(d[2], 3);
- assert_eq!(d[3], 4);
- assert_eq!(d[4], 5);
- }
- }
-
#[test]
fn test_from_fn() {
// Test on-stack from_fn.
assert_eq!(v, vec![1, 3, 5]);
}
- #[test]
- fn test_zip_unzip() {
- let z1 = vec![(1, 4), (2, 5), (3, 6)];
-
- let (left, right) = unzip(z1.iter().map(|&x| x));
-
- assert_eq!((1, 4), (left[0], right[0]));
- assert_eq!((2, 5), (left[1], right[1]));
- assert_eq!((3, 6), (left[2], right[2]));
- }
-
#[test]
fn test_element_swaps() {
let mut v = [1, 2, 3];
let n = task_rng().gen::<uint>() % 10;
counts[n] += 1;
(n, counts[n])
- }).collect::<~[(uint, int)]>();
+ }).collect::<Vec<(uint, int)>>();
// only sort on the first element, so an unstable sort
// may mix up the counts.
// will need to be ordered with increasing
// counts... i.e. exactly asserting that this sort is
// stable.
- assert!(v.windows(2).all(|w| w[0] <= w[1]));
+ assert!(v.as_slice().windows(2).all(|w| w[0] <= w[1]));
}
}
}
#[test]
fn test_partition() {
- assert_eq!((box []).partition(|x: &int| *x < 3), (box [], box []));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (box [1, 2, 3], box []));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (box [1], box [2, 3]));
- assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (box [], box [1, 2, 3]));
+ assert_eq!((box []).partition(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!((box [1, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
}
#[test]
fn test_partitioned() {
- assert_eq!(([]).partitioned(|x: &int| *x < 3), (box [], box []))
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (box [1, 2, 3], box []));
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (box [1], box [2, 3]));
- assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (box [], box [1, 2, 3]));
+ assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
}
#[test]
fn test_concat() {
let v: [~[int], ..0] = [];
- assert_eq!(v.concat_vec(), box []);
- assert_eq!([box [1], box [2,3]].concat_vec(), box [1, 2, 3]);
+ assert_eq!(v.concat_vec(), vec![]);
+ assert_eq!([box [1], box [2,3]].concat_vec(), vec![1, 2, 3]);
- assert_eq!([&[1], &[2,3]].concat_vec(), box [1, 2, 3]);
+ assert_eq!([&[1], &[2,3]].concat_vec(), vec![1, 2, 3]);
}
#[test]
fn test_connect() {
let v: [~[int], ..0] = [];
- assert_eq!(v.connect_vec(&0), box []);
- assert_eq!([box [1], box [2, 3]].connect_vec(&0), box [1, 0, 2, 3]);
- assert_eq!([box [1], box [2], box [3]].connect_vec(&0), box [1, 0, 2, 0, 3]);
+ assert_eq!(v.connect_vec(&0), vec![]);
+ assert_eq!([box [1], box [2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+ assert_eq!([box [1], box [2], box [3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
- assert_eq!(v.connect_vec(&0), box []);
- assert_eq!([&[1], &[2, 3]].connect_vec(&0), box [1, 0, 2, 3]);
- assert_eq!([&[1], &[2], &[3]].connect_vec(&0), box [1, 0, 2, 0, 3]);
+ assert_eq!([&[1], &[2, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
+ assert_eq!([&[1], &[2], &[3]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
}
#[test]
fn test_splitator() {
let xs = &[1i,2,3,4,5];
- assert_eq!(xs.split(|x| *x % 2 == 0).collect::<~[&[int]]>(),
- box [&[1], &[3], &[5]]);
- assert_eq!(xs.split(|x| *x == 1).collect::<~[&[int]]>(),
- box [&[], &[2,3,4,5]]);
- assert_eq!(xs.split(|x| *x == 5).collect::<~[&[int]]>(),
- box [&[1,2,3,4], &[]]);
- assert_eq!(xs.split(|x| *x == 10).collect::<~[&[int]]>(),
- box [&[1,2,3,4,5]]);
- assert_eq!(xs.split(|_| true).collect::<~[&[int]]>(),
- box [&[], &[], &[], &[], &[], &[]]);
+ assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1], &[3], &[5]]);
+ assert_eq!(xs.split(|x| *x == 1).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[2,3,4,5]]);
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4], &[]]);
+ assert_eq!(xs.split(|x| *x == 10).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.split(|_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[], &[], &[]]);
let xs: &[int] = &[];
- assert_eq!(xs.split(|x| *x == 5).collect::<~[&[int]]>(), box [&[]]);
+ assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
}
#[test]
fn test_splitnator() {
let xs = &[1i,2,3,4,5];
- assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<~[&[int]]>(),
- box [&[1,2,3,4,5]]);
- assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<~[&[int]]>(),
- box [&[1], &[3,4,5]]);
- assert_eq!(xs.splitn(3, |_| true).collect::<~[&[int]]>(),
- box [&[], &[], &[], &[4,5]]);
+ assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1], &[3,4,5]]);
+ assert_eq!(xs.splitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[4,5]]);
let xs: &[int] = &[];
- assert_eq!(xs.splitn(1, |x| *x == 5).collect::<~[&[int]]>(), box [&[]]);
+ assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
}
#[test]
fn test_rsplitator() {
let xs = &[1i,2,3,4,5];
- assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<~[&[int]]>(),
- box [&[5], &[3], &[1]]);
- assert_eq!(xs.split(|x| *x == 1).rev().collect::<~[&[int]]>(),
- box [&[2,3,4,5], &[]]);
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<~[&[int]]>(),
- box [&[], &[1,2,3,4]]);
- assert_eq!(xs.split(|x| *x == 10).rev().collect::<~[&[int]]>(),
- box [&[1,2,3,4,5]]);
+ assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[5], &[3], &[1]]);
+ assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[2,3,4,5], &[]]);
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[1,2,3,4]]);
+ assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
let xs: &[int] = &[];
- assert_eq!(xs.split(|x| *x == 5).rev().collect::<~[&[int]]>(), box [&[]]);
+ assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[int]>>().as_slice(), &[&[]]);
}
#[test]
fn test_rsplitnator() {
let xs = &[1,2,3,4,5];
- assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<~[&[int]]>(),
- box [&[1,2,3,4,5]]);
- assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<~[&[int]]>(),
- box [&[5], &[1,2,3]]);
- assert_eq!(xs.rsplitn(3, |_| true).collect::<~[&[int]]>(),
- box [&[], &[], &[], &[1,2]]);
+ assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[1,2,3,4,5]]);
+ assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<&[int]>>().as_slice(),
+ &[&[5], &[1,2,3]]);
+ assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<&[int]>>().as_slice(),
+ &[&[], &[], &[], &[1,2]]);
let xs: &[int] = &[];
- assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<~[&[int]]>(), box [&[]]);
+ assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[int]>>().as_slice(), &[&[]]);
}
#[test]
fn test_windowsator() {
let v = &[1i,2,3,4];
- assert_eq!(v.windows(2).collect::<~[&[int]]>(), box [&[1,2], &[2,3], &[3,4]]);
- assert_eq!(v.windows(3).collect::<~[&[int]]>(), box [&[1i,2,3], &[2,3,4]]);
+ assert_eq!(v.windows(2).collect::<Vec<&[int]>>().as_slice(), &[&[1,2], &[2,3], &[3,4]]);
+ assert_eq!(v.windows(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[2,3,4]]);
assert!(v.windows(6).next().is_none());
}
fn test_chunksator() {
let v = &[1i,2,3,4,5];
- assert_eq!(v.chunks(2).collect::<~[&[int]]>(), box [&[1i,2], &[3,4], &[5]]);
- assert_eq!(v.chunks(3).collect::<~[&[int]]>(), box [&[1i,2,3], &[4,5]]);
- assert_eq!(v.chunks(6).collect::<~[&[int]]>(), box [&[1i,2,3,4,5]]);
+ assert_eq!(v.chunks(2).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2], &[3,4], &[5]]);
+ assert_eq!(v.chunks(3).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3], &[4,5]]);
+ assert_eq!(v.chunks(6).collect::<Vec<&[int]>>().as_slice(), &[&[1i,2,3,4,5]]);
- assert_eq!(v.chunks(2).rev().collect::<~[&[int]]>(), box [&[5i], &[3,4], &[1,2]]);
+ assert_eq!(v.chunks(2).rev().collect::<Vec<&[int]>>().as_slice(), &[&[5i], &[3,4], &[1,2]]);
let mut it = v.chunks(2);
assert_eq!(it.indexable(), 3);
assert_eq!(it.idx(0).unwrap(), &[1,2]);
})
}
- #[bench]
- fn add(b: &mut Bencher) {
- let xs: &[int] = [5, ..10];
- let ys: &[int] = [5, ..10];
- b.iter(|| {
- xs + ys;
- });
- }
-
#[bench]
fn concat(b: &mut Bencher) {
let xss: Vec<Vec<uint>> = Vec::from_fn(100, |i| range(0, i).collect());
use io::Writer;
use iter::{Iterator, range, AdditiveIterator};
use option::{None, Option, Some};
-use ptr;
use from_str::FromStr;
-use slice::{OwnedVector, ImmutableVector, MutableVector};
-use slice::{Vector};
+use slice::{ImmutableVector, MutableVector, CloneableVector};
+use slice::Vector;
use vec::Vec;
use default::Default;
use strbuf::StrBuf;
/// Unsafe operations
pub mod raw {
use cast;
- use iter::Iterator;
use libc;
use ptr::RawPtr;
- use ptr;
- use slice::{MutableVector, OwnedVector, Vector};
- use str::{is_utf8};
- use vec::Vec;
+ use raw::Slice;
+ use slice::CloneableVector;
+ use str::{is_utf8, StrAllocating};
pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
pub use core::str::raw::{slice_unchecked};
/// Create a Rust string from a *u8 buffer of the given length
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
- let mut v = Vec::with_capacity(len);
- ptr::copy_memory(v.as_mut_ptr(), buf, len);
- v.set_len(len);
-
- assert!(is_utf8(v.as_slice()));
- ::cast::transmute(v.move_iter().collect::<~[u8]>())
+ let v = Slice { data: buf, len: len };
+ let bytes: &[u8] = ::cast::transmute(v);
+ assert!(is_utf8(bytes));
+ let s: &str = ::cast::transmute(bytes);
+ s.to_owned()
}
#[lang="strdup_uniq"]
/// Copy a slice into a new owned str.
#[inline]
fn to_owned(&self) -> ~str {
- let me = self.as_slice();
- let len = me.len();
- unsafe {
- let mut v = Vec::with_capacity(len);
+ use slice::Vector;
- ptr::copy_memory(v.as_mut_ptr(), me.as_ptr(), len);
- v.set_len(len);
- ::cast::transmute(v.move_iter().collect::<~[u8]>())
+ unsafe {
+ ::cast::transmute(self.as_slice().as_bytes().to_owned())
}
}
/// Converts to a vector of `u16` encoded as UTF-16.
- fn to_utf16(&self) -> ~[u16] {
+ fn to_utf16(&self) -> Vec<u16> {
let me = self.as_slice();
- let mut u = Vec::new();;
+ let mut u = Vec::new();
for ch in me.chars() {
let mut buf = [0u16, ..2];
let n = ch.encode_utf16(buf /* as mut slice! */);
u.push_all(buf.slice_to(n));
}
- u.move_iter().collect()
+ u
}
/// Given a string, make a new string with repeated copies of it.
assert_eq!(a.subslice_offset(c), 0);
let string = "a\nb\nc";
- let lines: ~[&str] = string.lines().collect();
+ let lines: Vec<&str> = string.lines().collect();
+ let lines = lines.as_slice();
assert_eq!(string.subslice_offset(lines[0]), 0);
assert_eq!(string.subslice_offset(lines[1]), 2);
assert_eq!(string.subslice_offset(lines[2]), 4);
fn test_utf16() {
let pairs =
[("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n".to_owned(),
- box [0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
+ vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
0xd800_u16, 0xdf30_u16, 0x000a_u16]),
("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n".to_owned(),
- box [0xd801_u16, 0xdc12_u16, 0xd801_u16,
+ vec![0xd801_u16, 0xdc12_u16, 0xd801_u16,
0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
0x000a_u16]),
("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n".to_owned(),
- box [0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
+ vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n".to_owned(),
- box [0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
+ vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
0x000a_u16 ]),
// Issue #12318, even-numbered non-BMP planes
("\U00020000".to_owned(),
- box [0xD840, 0xDC00])];
+ vec![0xD840, 0xDC00])];
for p in pairs.iter() {
let (s, u) = (*p).clone();
- assert!(is_utf16(u));
+ assert!(is_utf16(u.as_slice()));
assert_eq!(s.to_utf16(), u);
- assert_eq!(from_utf16(u).unwrap(), s);
- assert_eq!(from_utf16_lossy(u), s);
+ assert_eq!(from_utf16(u.as_slice()).unwrap(), s);
+ assert_eq!(from_utf16_lossy(u.as_slice()), s);
- assert_eq!(from_utf16(s.to_utf16()).unwrap(), s);
- assert_eq!(from_utf16(u).unwrap().to_utf16(), u);
+ assert_eq!(from_utf16(s.to_utf16().as_slice()).unwrap(), s);
+ assert_eq!(from_utf16(u.as_slice()).unwrap().to_utf16(), u);
}
}
fn test_split_char_iterator() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let split: ~[&str] = data.split(' ').collect();
- assert_eq!( split, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+ let split: Vec<&str> = data.split(' ').collect();
+ assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
- let mut rsplit: ~[&str] = data.split(' ').rev().collect();
+ let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
rsplit.reverse();
- assert_eq!(rsplit, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+ assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
- let split: ~[&str] = data.split(|c: char| c == ' ').collect();
- assert_eq!( split, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+ let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
+ assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
- let mut rsplit: ~[&str] = data.split(|c: char| c == ' ').rev().collect();
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
rsplit.reverse();
- assert_eq!(rsplit, box ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+ assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
// Unicode
- let split: ~[&str] = data.split('ä').collect();
- assert_eq!( split, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+ let split: Vec<&str> = data.split('ä').collect();
+ assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
- let mut rsplit: ~[&str] = data.split('ä').rev().collect();
+ let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
rsplit.reverse();
- assert_eq!(rsplit, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+ assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
- let split: ~[&str] = data.split(|c: char| c == 'ä').collect();
- assert_eq!( split, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+ let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
+ assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
- let mut rsplit: ~[&str] = data.split(|c: char| c == 'ä').rev().collect();
+ let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
rsplit.reverse();
- assert_eq!(rsplit, box ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+ assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
}
#[test]
fn test_splitn_char_iterator() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let split: ~[&str] = data.splitn(' ', 3).collect();
- assert_eq!(split, box ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+ let split: Vec<&str> = data.splitn(' ', 3).collect();
+ assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
- let split: ~[&str] = data.splitn(|c: char| c == ' ', 3).collect();
- assert_eq!(split, box ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+ let split: Vec<&str> = data.splitn(|c: char| c == ' ', 3).collect();
+ assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
// Unicode
- let split: ~[&str] = data.splitn('ä', 3).collect();
- assert_eq!(split, box ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+ let split: Vec<&str> = data.splitn('ä', 3).collect();
+ assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
- let split: ~[&str] = data.splitn(|c: char| c == 'ä', 3).collect();
- assert_eq!(split, box ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+ let split: Vec<&str> = data.splitn(|c: char| c == 'ä', 3).collect();
+ assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
}
#[test]
fn test_rsplitn_char_iterator() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let mut split: ~[&str] = data.rsplitn(' ', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(' ', 3).collect();
split.reverse();
- assert_eq!(split, box ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+ assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
- let mut split: ~[&str] = data.rsplitn(|c: char| c == ' ', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect();
split.reverse();
- assert_eq!(split, box ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+ assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
// Unicode
- let mut split: ~[&str] = data.rsplitn('ä', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn('ä', 3).collect();
split.reverse();
- assert_eq!(split, box ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+ assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
- let mut split: ~[&str] = data.rsplitn(|c: char| c == 'ä', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect();
split.reverse();
- assert_eq!(split, box ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+ assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
}
#[test]
fn test_split_char_iterator_no_trailing() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let split: ~[&str] = data.split('\n').collect();
- assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb", ""]);
+ let split: Vec<&str> = data.split('\n').collect();
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
- let split: ~[&str] = data.split_terminator('\n').collect();
- assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb"]);
+ let split: Vec<&str> = data.split_terminator('\n').collect();
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
}
#[test]
fn test_rev_split_char_iterator_no_trailing() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let mut split: ~[&str] = data.split('\n').rev().collect();
+ let mut split: Vec<&str> = data.split('\n').rev().collect();
split.reverse();
- assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb", ""]);
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
- let mut split: ~[&str] = data.split_terminator('\n').rev().collect();
+ let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
split.reverse();
- assert_eq!(split, box ["", "Märy häd ä little lämb", "Little lämb"]);
+ assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
}
#[test]
fn test_words() {
let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
- let words: ~[&str] = data.words().collect();
- assert_eq!(words, box ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
+ let words: Vec<&str> = data.words().collect();
+ assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
}
#[test]
#[test]
fn test_lines() {
let data = "\nMäry häd ä little lämb\n\nLittle lämb\n";
- let lines: ~[&str] = data.lines().collect();
- assert_eq!(lines, box ["", "Märy häd ä little lämb", "", "Little lämb"]);
+ let lines: Vec<&str> = data.lines().collect();
+ assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
- let lines: ~[&str] = data.lines().collect();
- assert_eq!(lines, box ["", "Märy häd ä little lämb", "", "Little lämb"]);
+ let lines: Vec<&str> = data.lines().collect();
+ assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
}
#[test]
fn test_split_strator() {
- fn t<'a>(s: &str, sep: &'a str, u: ~[&str]) {
- let v: ~[&str] = s.split_str(sep).collect();
- assert_eq!(v, u);
+ fn t(s: &str, sep: &str, u: &[&str]) {
+ let v: Vec<&str> = s.split_str(sep).collect();
+ assert_eq!(v.as_slice(), u.as_slice());
}
- t("--1233345--", "12345", box ["--1233345--"]);
- t("abc::hello::there", "::", box ["abc", "hello", "there"]);
- t("::hello::there", "::", box ["", "hello", "there"]);
- t("hello::there::", "::", box ["hello", "there", ""]);
- t("::hello::there::", "::", box ["", "hello", "there", ""]);
- t("ประเทศไทย中华Việt Nam", "中华", box ["ประเทศไทย", "Việt Nam"]);
- t("zzXXXzzYYYzz", "zz", box ["", "XXX", "YYY", ""]);
- t("zzXXXzYYYz", "XXX", box ["zz", "zYYYz"]);
- t(".XXX.YYY.", ".", box ["", "XXX", "YYY", ""]);
- t("", ".", box [""]);
- t("zz", "zz", box ["",""]);
- t("ok", "z", box ["ok"]);
- t("zzz", "zz", box ["","z"]);
- t("zzzzz", "zz", box ["","","z"]);
+ t("--1233345--", "12345", ["--1233345--"]);
+ t("abc::hello::there", "::", ["abc", "hello", "there"]);
+ t("::hello::there", "::", ["", "hello", "there"]);
+ t("hello::there::", "::", ["hello", "there", ""]);
+ t("::hello::there::", "::", ["", "hello", "there", ""]);
+ t("ประเทศไทย中华Việt Nam", "中华", ["ประเทศไทย", "Việt Nam"]);
+ t("zzXXXzzYYYzz", "zz", ["", "XXX", "YYY", ""]);
+ t("zzXXXzYYYz", "XXX", ["zz", "zYYYz"]);
+ t(".XXX.YYY.", ".", ["", "XXX", "YYY", ""]);
+ t("", ".", [""]);
+ t("zz", "zz", ["",""]);
+ t("ok", "z", ["ok"]);
+ t("zzz", "zz", ["","z"]);
+ t("zzzzz", "zz", ["","","z"]);
}
#[test]
use iter::{Extendable, FromIterator, Iterator, range};
use option::{None, Option, Some};
use ptr::RawPtr;
-use slice::{OwnedVector, Vector};
+use slice::{OwnedVector, Vector, CloneableVector};
use str::{OwnedStr, Str, StrSlice, StrAllocating};
use str;
use vec::Vec;
impl StrAllocating for StrBuf {
#[inline]
fn into_owned(self) -> ~str {
- let StrBuf {
- vec: vec
- } = self;
unsafe {
- cast::transmute::<~[u8],~str>(vec.move_iter().collect())
+ cast::transmute(self.vec.as_slice().to_owned())
}
}
/// As new(), but returns a vector of as many pre-cloned handles as
/// requested.
- pub fn newN(data: T, num_handles: uint) -> ~[UnsafeArc<T>] {
+ pub fn newN(data: T, num_handles: uint) -> Vec<UnsafeArc<T>> {
unsafe {
if num_handles == 0 {
- box [] // need to free data here
+ vec![] // need to free data here
} else {
let ptr = new_inner(data, num_handles);
let v = Vec::from_fn(num_handles, |_| UnsafeArc { data: ptr });
- v.move_iter().collect()
+ v
}
}
}
use rand::Rng;
use sync::atomics::{AtomicBool, INIT_ATOMIC_BOOL, SeqCst,
AtomicUint, INIT_ATOMIC_UINT};
- use slice;
+ use vec;
#[test]
fn smoke() {
let mut pool = BufferPool::<(int, uint)>::new();
let (mut w, s) = pool.deque();
- let (threads, hits) = slice::unzip(range(0, NTHREADS).map(|_| {
+ let (threads, hits) = vec::unzip(range(0, NTHREADS).map(|_| {
let s = s.clone();
let unique_box = box AtomicUint::new(0);
let thread_box = unsafe {
use c_str::ToCStr;
use cast;
+use iter::Iterator;
use ops::*;
use option::*;
use os;
use path::GenericPath;
use path;
use result::*;
+use slice::{Vector,OwnedVector};
use str;
+use vec::Vec;
pub struct DynamicLibrary { handle: *u8}
("LD_LIBRARY_PATH", ':' as u8)
};
let newenv = os::getenv_as_bytes(envvar).unwrap_or(box []);
- let newenv = newenv + &[sep] + path.as_vec();
- os::setenv(envvar, str::from_utf8(newenv).unwrap());
+ let mut newenv = newenv.move_iter().collect::<Vec<_>>();
+ newenv.push_all(&[sep]);
+ newenv.push_all(path.as_vec());
+ os::setenv(envvar, str::from_utf8(newenv.as_slice()).unwrap());
}
/// Access the value at the symbol of the dynamic library
use mem;
use num;
use num::{CheckedMul, CheckedAdd};
-use ops::Drop;
+use ops::{Add, Drop};
use option::{None, Option, Some, Expect};
use ptr::RawPtr;
use ptr;
use rt::global_heap::{malloc_raw, realloc_raw};
use raw::Slice;
+use RawVec = raw::Vec;
use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
use slice::{MutableTotalOrdVector, OwnedVector, Vector};
use slice::{MutableVectorAllocating};
}
}
+impl<T: Clone, V: Vector<T>> Add<V, Vec<T>> for Vec<T> {
+ #[inline]
+ fn add(&self, rhs: &V) -> Vec<T> {
+ let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
+ res.push_all(self.as_slice());
+ res.push_all(rhs.as_slice());
+ res
+ }
+}
+
#[unsafe_destructor]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
}
}
+/**
+ * Convert an iterator of pairs into a pair of vectors.
+ *
+ * Returns a tuple containing two vectors where the i-th element of the first
+ * vector contains the first element of the i-th tuple of the input iterator,
+ * and the i-th element of the second vector contains the second element
+ * of the i-th tuple of the input iterator.
+ */
+pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
+ let (lo, _) = iter.size_hint();
+ let mut ts = Vec::with_capacity(lo);
+ let mut us = Vec::with_capacity(lo);
+ for (t, u) in iter {
+ ts.push(t);
+ us.push(u);
+ }
+ (ts, us)
+}
+
+/// Mechanism to convert from a `Vec<T>` to a `[T]`.
+///
+/// In a post-DST world this will be used to convert to any `Ptr<[T]>`.
+///
+/// This could be implemented on more types than just pointers to vectors, but
+/// the recommended approach for those types is to implement `FromIterator`.
+// FIXME(#12938): Update doc comment when DST lands
+pub trait FromVec<T> {
+ /// Convert a `Vec<T>` into the receiver type.
+ fn from_vec(v: Vec<T>) -> Self;
+}
+
+impl<T> FromVec<T> for ~[T] {
+ fn from_vec(mut v: Vec<T>) -> ~[T] {
+ let len = v.len();
+ let data_size = len.checked_mul(&mem::size_of::<T>());
+ let data_size = data_size.expect("overflow in from_vec()");
+ let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
+ let size = size.expect("overflow in from_vec()");
+
+ // In a post-DST world, we can attempt to reuse the Vec allocation by calling
+ // shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
+ // diffrent than what we're doing manually here.
+
+ let vp = v.as_mut_ptr();
+
+ unsafe {
+ let ret = malloc_raw(size) as *mut RawVec<()>;
+
+ (*ret).fill = len * mem::nonzero_size_of::<T>();
+ (*ret).alloc = len * mem::nonzero_size_of::<T>();
+
+ ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
+ vp as *u8, data_size);
+
+ // we've transferred ownership of the contents from v, but we can't drop it
+ // as it still needs to free its own allocation.
+ v.set_len(0);
+
+ transmute(ret)
+ }
+ }
+}
+
+/// Unsafe operations
+pub mod raw {
+ use super::Vec;
+ use ptr;
+
+ /// Constructs a vector from an unsafe pointer to a buffer.
+ ///
+ /// The elements of the buffer are copied into the vector without cloning,
+ /// as if `ptr::read()` were called on them.
+ #[inline]
+ pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> Vec<T> {
+ let mut dst = Vec::with_capacity(elts);
+ dst.set_len(elts);
+ ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
+ dst
+ }
+}
+
+
#[cfg(test)]
mod tests {
use prelude::*;
use mem::size_of;
+ use kinds::marker;
+ use super::{unzip, raw, FromVec};
#[test]
fn test_small_vec_struct() {
unsafe { v.set_len(0); }
assert_eq!(v.mut_iter().len(), 0);
}
+
+ #[test]
+ fn test_partition() {
+ assert_eq!(vec![].partition(|x: &int| *x < 3), (vec![], vec![]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(vec![1, 2, 3].partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_partitioned() {
+ assert_eq!(vec![].partitioned(|x: &int| *x < 3), (vec![], vec![]))
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![]));
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3]));
+ assert_eq!(vec![1, 2, 3].partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3]));
+ }
+
+ #[test]
+ fn test_zip_unzip() {
+ let z1 = vec![(1, 4), (2, 5), (3, 6)];
+
+ let (left, right) = unzip(z1.iter().map(|&x| x));
+
+ let (left, right) = (left.as_slice(), right.as_slice());
+ assert_eq!((1, 4), (left[0], right[0]));
+ assert_eq!((2, 5), (left[1], right[1]));
+ assert_eq!((3, 6), (left[2], right[2]));
+ }
+
+ #[test]
+ fn test_unsafe_ptrs() {
+ unsafe {
+ // Test on-stack copy-from-buf.
+ let a = [1, 2, 3];
+ let ptr = a.as_ptr();
+ let b = raw::from_buf(ptr, 3u);
+ assert_eq!(b, vec![1, 2, 3]);
+
+ // Test on-heap copy-from-buf.
+ let c = box [1, 2, 3, 4, 5];
+ let ptr = c.as_ptr();
+ let d = raw::from_buf(ptr, 5u);
+ assert_eq!(d, vec![1, 2, 3, 4, 5]);
+ }
+ }
+
+ #[test]
+ fn test_from_vec() {
+ let a = vec![1u, 2, 3];
+ let b: ~[uint] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &[1u, 2, 3]);
+
+ let a = vec![];
+ let b: ~[u8] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &[]);
+
+ let a = vec!["one".to_owned(), "two".to_owned()];
+ let b: ~[~str] = FromVec::from_vec(a);
+ assert_eq!(b.as_slice(), &["one".to_owned(), "two".to_owned()]);
+
+ struct Foo {
+ x: uint,
+ nocopy: marker::NoCopy
+ }
+
+ let a = vec![Foo{x: 42, nocopy: marker::NoCopy}, Foo{x: 84, nocopy: marker::NoCopy}];
+ let b: ~[Foo] = FromVec::from_vec(a);
+ assert_eq!(b.len(), 2);
+ assert_eq!(b[0].x, 42);
+ assert_eq!(b[1].x, 84);
+ }
}
pub enum FnStyle {
UnsafeFn, // declared with "unsafe fn"
NormalFn, // declared with "fn"
- ExternFn, // declared with "extern fn"
}
impl fmt::Show for FnStyle {
match *self {
NormalFn => "normal".fmt(f),
UnsafeFn => "unsafe".fmt(f),
- ExternFn => "extern".fmt(f),
}
}
}
/// The type of the iterator used by with_path.
pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
-pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> ~str {
+pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
let itr = token::get_ident_interner();
path.fold(StrBuf::new(), |mut s, e| {
}
s.push_str(e.as_slice());
s
- }).into_owned()
+ }).to_strbuf()
}
#[deriving(Clone)]
self.with_path_next(id, None, f)
}
- pub fn path_to_str(&self, id: NodeId) -> ~str {
+ pub fn path_to_str(&self, id: NodeId) -> StrBuf {
self.with_path(id, |path| path_to_str(path))
}
- fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> ~str {
+ fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> StrBuf {
self.with_path(id, |path| {
path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
})
}
}
- pub fn node_to_str(&self, id: NodeId) -> ~str {
+ pub fn node_to_str(&self, id: NodeId) -> StrBuf {
node_id_to_str(self, id)
}
}
ii
}
-fn node_id_to_str(map: &Map, id: NodeId) -> ~str {
+fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf {
match map.find(id) {
Some(NodeItem(item)) => {
let path_str = map.path_to_str_with_ident(id, item.ident);
ItemImpl(..) => "impl",
ItemMac(..) => "macro"
};
- format!("{} {} (id={})", item_str, path_str, id)
+ (format!("{} {} (id={})", item_str, path_str, id)).to_strbuf()
}
Some(NodeForeignItem(item)) => {
let path_str = map.path_to_str_with_ident(id, item.ident);
- format!("foreign item {} (id={})", path_str, id)
+ (format!("foreign item {} (id={})", path_str, id)).to_strbuf()
}
Some(NodeMethod(m)) => {
- format!("method {} in {} (id={})",
+ (format!("method {} in {} (id={})",
token::get_ident(m.ident),
- map.path_to_str(id), id)
+ map.path_to_str(id), id)).to_strbuf()
}
Some(NodeTraitMethod(ref tm)) => {
let m = ast_util::trait_method_to_ty_method(&**tm);
- format!("method {} in {} (id={})",
+ (format!("method {} in {} (id={})",
token::get_ident(m.ident),
- map.path_to_str(id), id)
+ map.path_to_str(id), id)).to_strbuf()
}
Some(NodeVariant(ref variant)) => {
- format!("variant {} in {} (id={})",
+ (format!("variant {} in {} (id={})",
token::get_ident(variant.node.name),
- map.path_to_str(id), id)
+ map.path_to_str(id), id)).to_strbuf()
}
Some(NodeExpr(expr)) => {
- format!("expr {} (id={})", pprust::expr_to_str(expr), id)
+ (format!("expr {} (id={})",
+ pprust::expr_to_str(expr), id)).to_strbuf()
}
Some(NodeStmt(stmt)) => {
- format!("stmt {} (id={})", pprust::stmt_to_str(stmt), id)
+ (format!("stmt {} (id={})",
+ pprust::stmt_to_str(stmt), id)).to_strbuf()
}
Some(NodeArg(pat)) => {
- format!("arg {} (id={})", pprust::pat_to_str(pat), id)
+ (format!("arg {} (id={})",
+ pprust::pat_to_str(pat), id)).to_strbuf()
}
Some(NodeLocal(pat)) => {
- format!("local {} (id={})", pprust::pat_to_str(pat), id)
+ (format!("local {} (id={})",
+ pprust::pat_to_str(pat), id)).to_strbuf()
}
Some(NodeBlock(block)) => {
- format!("block {} (id={})", pprust::block_to_str(block), id)
+ (format!("block {} (id={})",
+ pprust::block_to_str(block), id)).to_strbuf()
}
Some(NodeStructCtor(_)) => {
- format!("struct_ctor {} (id={})", map.path_to_str(id), id)
+ (format!("struct_ctor {} (id={})",
+ map.path_to_str(id), id)).to_strbuf()
}
Some(NodeLifetime(ref l)) => {
- format!("lifetime {} (id={})", pprust::lifetime_to_str(*l), id)
+ (format!("lifetime {} (id={})",
+ pprust::lifetime_to_str(*l), id)).to_strbuf()
}
None => {
- format!("unknown node (id={})", id)
+ (format!("unknown node (id={})", id)).to_strbuf()
}
}
}
use std::strbuf::StrBuf;
use std::u32;
-pub fn path_name_i(idents: &[Ident]) -> ~str {
+pub fn path_name_i(idents: &[Ident]) -> StrBuf {
// FIXME: Bad copies (#2543 -- same for everything else that says "bad")
idents.iter().map(|i| {
- token::get_ident(*i).get().to_str()
- }).collect::<Vec<~str>>().connect("::")
+ token::get_ident(*i).get().to_strbuf()
+ }).collect::<Vec<StrBuf>>().connect("::").to_strbuf()
}
// totally scary function: ignores all but the last element, should have
// Get a string representation of a signed int type, with its value.
// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
-pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> ~str {
+pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> StrBuf {
let s = match t {
TyI if val.is_some() => "",
TyI => "int",
};
match val {
- Some(n) => format!("{}{}", n, s),
- None => s.to_owned()
+ Some(n) => format!("{}{}", n, s).to_strbuf(),
+ None => s.to_strbuf()
}
}
// Get a string representation of an unsigned int type, with its value.
// We want to avoid "42uint" in favor of "42u"
-pub fn uint_ty_to_str(t: UintTy, val: Option<u64>) -> ~str {
+pub fn uint_ty_to_str(t: UintTy, val: Option<u64>) -> StrBuf {
let s = match t {
TyU if val.is_some() => "u",
TyU => "uint",
};
match val {
- Some(n) => format!("{}{}", n, s),
- None => s.to_owned()
+ Some(n) => format!("{}{}", n, s).to_strbuf(),
+ None => s.to_strbuf()
}
}
}
}
-pub fn float_ty_to_str(t: FloatTy) -> ~str {
- match t { TyF32 => "f32".to_owned(), TyF64 => "f64".to_owned(), TyF128 => "f128".to_owned() }
+pub fn float_ty_to_str(t: FloatTy) -> StrBuf {
+ match t {
+ TyF32 => "f32".to_strbuf(),
+ TyF64 => "f64".to_strbuf(),
+ TyF128 => "f128".to_strbuf(),
+ }
}
pub fn is_call_expr(e: @Expr) -> bool {
/// listed as `__extensions__::method_name::hash`, with no indication
/// of the type).
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
- let mut pretty = StrBuf::from_owned_str(pprust::ty_to_str(ty));
+ let mut pretty = pprust::ty_to_str(ty);
match *trait_ref {
Some(ref trait_ref) => {
pretty.push_char('.');
- pretty.push_str(pprust::path_to_str(&trait_ref.path));
+ pretty.push_str(pprust::path_to_str(&trait_ref.path).as_slice());
}
None => {}
}
let meta = mk_name_value_item_str(
InternedString::new("doc"),
token::intern_and_get_ident(strip_doc_comment_decoration(
- comment.get())));
+ comment.get()).as_slice()));
mk_attr(meta)
} else {
*self
pub struct NameAndSpan {
/// The name of the macro that was invoked to create the thing
/// with this Span.
- pub name: ~str,
+ pub name: StrBuf,
/// The format with which the macro was invoked.
pub format: MacroFormat,
/// The span of the macro definition itself. The macro may not
pub callee: NameAndSpan
}
-pub type FileName = ~str;
+pub type FileName = StrBuf;
pub struct FileLines {
pub file: Rc<FileMap>,
/// e.g. `<anon>`
pub name: FileName,
/// The complete source code
- pub src: ~str,
+ pub src: StrBuf,
/// The start position of this source in the CodeMap
pub start_pos: BytePos,
/// Locations of lines beginnings in the source code
}
// get a line from the list of pre-computed line-beginnings
- pub fn get_line(&self, line: int) -> ~str {
+ pub fn get_line(&self, line: int) -> StrBuf {
let mut lines = self.lines.borrow_mut();
let begin: BytePos = *lines.get(line as uint) - self.start_pos;
let begin = begin.to_uint();
- let slice = self.src.slice_from(begin);
+ let slice = self.src.as_slice().slice_from(begin);
match slice.find('\n') {
- Some(e) => slice.slice_to(e).to_owned(),
- None => slice.to_owned()
+ Some(e) => slice.slice_to(e).to_strbuf(),
+ None => slice.to_strbuf()
}
}
}
pub fn is_real_file(&self) -> bool {
- !(self.name.starts_with("<") && self.name.ends_with(">"))
+ !(self.name.as_slice().starts_with("<") &&
+ self.name.as_slice().ends_with(">"))
}
}
}
}
- pub fn new_filemap(&self, filename: FileName, src: ~str) -> Rc<FileMap> {
+ pub fn new_filemap(&self, filename: FileName, src: StrBuf) -> Rc<FileMap> {
let mut files = self.files.borrow_mut();
let start_pos = match files.last() {
None => 0,
// Remove utf-8 BOM if any.
// FIXME #12884: no efficient/safe way to remove from the start of a string
// and reuse the allocation.
- let mut src = if src.starts_with("\ufeff") {
+ let mut src = if src.as_slice().starts_with("\ufeff") {
StrBuf::from_str(src.as_slice().slice_from(3))
} else {
- StrBuf::from_owned_str(src)
+ StrBuf::from_str(src.as_slice())
};
// Append '\n' in case it's not already there.
let filemap = Rc::new(FileMap {
name: filename,
- src: src.into_owned(),
+ src: src.to_strbuf(),
start_pos: Pos::from_uint(start_pos),
lines: RefCell::new(Vec::new()),
multibyte_chars: RefCell::new(Vec::new()),
filemap
}
- pub fn mk_substr_filename(&self, sp: Span) -> ~str {
+ pub fn mk_substr_filename(&self, sp: Span) -> StrBuf {
let pos = self.lookup_char_pos(sp.lo);
- format!("<{}:{}:{}>", pos.file.name, pos.line, pos.col.to_uint() + 1)
+ (format!("<{}:{}:{}>",
+ pos.file.name,
+ pos.line,
+ pos.col.to_uint() + 1)).to_strbuf()
}
/// Lookup source information about a BytePos
pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
let loc = self.lookup_char_pos(pos);
LocWithOpt {
- filename: loc.file.name.to_str(),
+ filename: loc.file.name.to_strbuf(),
line: loc.line,
col: loc.col,
file: Some(loc.file)
}
}
- pub fn span_to_str(&self, sp: Span) -> ~str {
+ pub fn span_to_str(&self, sp: Span) -> StrBuf {
if self.files.borrow().len() == 0 && sp == DUMMY_SP {
- return "no-location".to_owned();
+ return "no-location".to_strbuf();
}
let lo = self.lookup_char_pos_adj(sp.lo);
let hi = self.lookup_char_pos_adj(sp.hi);
- return format!("{}:{}:{}: {}:{}", lo.filename,
- lo.line, lo.col.to_uint() + 1, hi.line, hi.col.to_uint() + 1)
+ return (format!("{}:{}:{}: {}:{}",
+ lo.filename,
+ lo.line,
+ lo.col.to_uint() + 1,
+ hi.line,
+ hi.col.to_uint() + 1)).to_strbuf()
}
pub fn span_to_filename(&self, sp: Span) -> FileName {
- self.lookup_char_pos(sp.lo).file.name.to_str()
+ self.lookup_char_pos(sp.lo).file.name.to_strbuf()
}
pub fn span_to_lines(&self, sp: Span) -> FileLines {
FileLines {file: lo.file, lines: lines}
}
- pub fn span_to_snippet(&self, sp: Span) -> Option<~str> {
+ pub fn span_to_snippet(&self, sp: Span) -> Option<StrBuf> {
let begin = self.lookup_byte_offset(sp.lo);
let end = self.lookup_byte_offset(sp.hi);
if begin.fm.start_pos != end.fm.start_pos {
None
} else {
- Some(begin.fm.src.slice( begin.pos.to_uint(), end.pos.to_uint()).to_owned())
+ Some(begin.fm.src.as_slice().slice(begin.pos.to_uint(),
+ end.pos.to_uint()).to_strbuf())
}
}
pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> {
for fm in self.files.borrow().iter() {
- if filename == fm.name {
+ if filename == fm.name.as_slice() {
return fm.clone();
}
}
#[test]
fn t1 () {
let cm = CodeMap::new();
- let fm = cm.new_filemap("blork.rs".to_owned(),"first line.\nsecond line".to_owned());
+ let fm = cm.new_filemap("blork.rs".to_strbuf(),
+ "first line.\nsecond line".to_strbuf());
fm.next_line(BytePos(0));
- assert_eq!(&fm.get_line(0),&"first line.".to_owned());
+ assert_eq!(&fm.get_line(0),&"first line.".to_strbuf());
// TESTING BROKEN BEHAVIOR:
fm.next_line(BytePos(10));
- assert_eq!(&fm.get_line(1),&".".to_owned());
+ assert_eq!(&fm.get_line(1), &".".to_strbuf());
}
#[test]
#[should_fail]
fn t2 () {
let cm = CodeMap::new();
- let fm = cm.new_filemap("blork.rs".to_owned(),"first line.\nsecond line".to_owned());
+ let fm = cm.new_filemap("blork.rs".to_strbuf(),
+ "first line.\nsecond line".to_strbuf());
// TESTING *REALLY* BROKEN BEHAVIOR:
fm.next_line(BytePos(0));
fm.next_line(BytePos(10));
fn init_code_map() -> CodeMap {
let cm = CodeMap::new();
- let fm1 = cm.new_filemap("blork.rs".to_owned(),"first line.\nsecond line".to_owned());
- let fm2 = cm.new_filemap("empty.rs".to_owned(),"".to_owned());
- let fm3 = cm.new_filemap("blork2.rs".to_owned(),"first line.\nsecond line".to_owned());
+ let fm1 = cm.new_filemap("blork.rs".to_strbuf(),
+ "first line.\nsecond line".to_strbuf());
+ let fm2 = cm.new_filemap("empty.rs".to_strbuf(),
+ "".to_strbuf());
+ let fm3 = cm.new_filemap("blork2.rs".to_strbuf(),
+ "first line.\nsecond line".to_strbuf());
fm1.next_line(BytePos(0));
fm1.next_line(BytePos(12));
let cm = init_code_map();
let fmabp1 = cm.lookup_byte_offset(BytePos(22));
- assert_eq!(fmabp1.fm.name, "blork.rs".to_owned());
+ assert_eq!(fmabp1.fm.name, "blork.rs".to_strbuf());
assert_eq!(fmabp1.pos, BytePos(22));
let fmabp2 = cm.lookup_byte_offset(BytePos(24));
- assert_eq!(fmabp2.fm.name, "blork2.rs".to_owned());
+ assert_eq!(fmabp2.fm.name, "blork2.rs".to_strbuf());
assert_eq!(fmabp2.pos, BytePos(0));
}
let cm = init_code_map();
let loc1 = cm.lookup_char_pos(BytePos(22));
- assert_eq!(loc1.file.name, "blork.rs".to_owned());
+ assert_eq!(loc1.file.name, "blork.rs".to_strbuf());
assert_eq!(loc1.line, 2);
assert_eq!(loc1.col, CharPos(10));
let loc2 = cm.lookup_char_pos(BytePos(24));
- assert_eq!(loc2.file.name, "blork2.rs".to_owned());
+ assert_eq!(loc2.file.name, "blork2.rs".to_strbuf());
assert_eq!(loc2.line, 1);
assert_eq!(loc2.col, CharPos(0));
}
fn init_code_map_mbc() -> CodeMap {
let cm = CodeMap::new();
// € is a three byte utf8 char.
- let fm1 = cm.new_filemap("blork.rs".to_owned(),"fir€st €€€€ line.\nsecond line".to_owned());
- let fm2 = cm.new_filemap("blork2.rs".to_owned(),"first line€€.\n€ second line".to_owned());
+ let fm1 =
+ cm.new_filemap("blork.rs".to_strbuf(),
+ "fir€st €€€€ line.\nsecond line".to_strbuf());
+ let fm2 = cm.new_filemap("blork2.rs".to_strbuf(),
+ "first line€€.\n€ second line".to_strbuf());
fm1.next_line(BytePos(0));
fm1.next_line(BytePos(22));
let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
let file_lines = cm.span_to_lines(span);
- assert_eq!(file_lines.file.name, "blork.rs".to_owned());
+ assert_eq!(file_lines.file.name, "blork.rs".to_strbuf());
assert_eq!(file_lines.lines.len(), 1);
assert_eq!(*file_lines.lines.get(0), 1u);
}
let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
let snippet = cm.span_to_snippet(span);
- assert_eq!(snippet, Some("second line".to_owned()));
+ assert_eq!(snippet, Some("second line".to_strbuf()));
}
#[test]
let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
let sstr = cm.span_to_str(span);
- assert_eq!(sstr, "blork.rs:2:1: 2:12".to_owned());
+ assert_eq!(sstr, "blork.rs:2:1: 2:12".to_strbuf());
}
}
pub struct CrateId {
/// A path which represents the codes origin. By convention this is the
/// URL, without `http://` or `https://` prefix, to the crate's repository
- pub path: ~str,
+ pub path: StrBuf,
/// The name of the crate.
- pub name: ~str,
+ pub name: StrBuf,
/// The version of the crate.
- pub version: Option<~str>,
+ pub version: Option<StrBuf>,
}
impl fmt::Show for CrateId {
None => "0.0",
Some(ref version) => version.as_slice(),
};
- if self.path == self.name || self.path.ends_with(format!("/{}", self.name)) {
+ if self.path == self.name ||
+ self.path.as_slice().ends_with(format!("/{}", self.name)) {
write!(f.buf, "\\#{}", version)
} else {
write!(f.buf, "\\#{}:{}", self.name, version)
let inferred_name = *path_pieces.get(0);
let (name, version) = if pieces.len() == 1 {
- (inferred_name.to_owned(), None)
+ (inferred_name.to_strbuf(), None)
} else {
let hash_pieces: Vec<&str> = pieces.get(1)
.splitn(':', 1)
};
let name = if !hash_name.is_empty() {
- hash_name.to_owned()
+ hash_name.to_strbuf()
} else {
- inferred_name.to_owned()
+ inferred_name.to_strbuf()
};
let version = if !hash_version.is_empty() {
if hash_version == "0.0" {
None
} else {
- Some(hash_version.to_owned())
+ Some(hash_version.to_strbuf())
}
} else {
None
};
Some(CrateId {
- path: path.clone(),
+ path: path.to_strbuf(),
name: name,
version: version,
})
}
}
- pub fn short_name_with_version(&self) -> ~str {
- format!("{}-{}", self.name, self.version_or_default())
+ pub fn short_name_with_version(&self) -> StrBuf {
+ (format!("{}-{}", self.name, self.version_or_default())).to_strbuf()
}
pub fn matches(&self, other: &CrateId) -> bool {
#[test]
fn bare_name() {
let crateid: CrateId = from_str("foo").expect("valid crateid");
- assert_eq!(crateid.name, "foo".to_owned());
+ assert_eq!(crateid.name, "foo".to_strbuf());
assert_eq!(crateid.version, None);
- assert_eq!(crateid.path, "foo".to_owned());
+ assert_eq!(crateid.path, "foo".to_strbuf());
}
#[test]
fn bare_name_single_char() {
let crateid: CrateId = from_str("f").expect("valid crateid");
- assert_eq!(crateid.name, "f".to_owned());
+ assert_eq!(crateid.name, "f".to_strbuf());
assert_eq!(crateid.version, None);
- assert_eq!(crateid.path, "f".to_owned());
+ assert_eq!(crateid.path, "f".to_strbuf());
}
#[test]
#[test]
fn simple_path() {
let crateid: CrateId = from_str("example.com/foo/bar").expect("valid crateid");
- assert_eq!(crateid.name, "bar".to_owned());
+ assert_eq!(crateid.name, "bar".to_strbuf());
assert_eq!(crateid.version, None);
- assert_eq!(crateid.path, "example.com/foo/bar".to_owned());
+ assert_eq!(crateid.path, "example.com/foo/bar".to_strbuf());
}
#[test]
fn simple_version() {
let crateid: CrateId = from_str("foo#1.0").expect("valid crateid");
- assert_eq!(crateid.name, "foo".to_owned());
- assert_eq!(crateid.version, Some("1.0".to_owned()));
- assert_eq!(crateid.path, "foo".to_owned());
+ assert_eq!(crateid.name, "foo".to_strbuf());
+ assert_eq!(crateid.version, Some("1.0".to_strbuf()));
+ assert_eq!(crateid.path, "foo".to_strbuf());
}
#[test]
#[test]
fn path_and_version() {
let crateid: CrateId = from_str("example.com/foo/bar#1.0").expect("valid crateid");
- assert_eq!(crateid.name, "bar".to_owned());
- assert_eq!(crateid.version, Some("1.0".to_owned()));
- assert_eq!(crateid.path, "example.com/foo/bar".to_owned());
+ assert_eq!(crateid.name, "bar".to_strbuf());
+ assert_eq!(crateid.version, Some("1.0".to_strbuf()));
+ assert_eq!(crateid.path, "example.com/foo/bar".to_strbuf());
}
#[test]
fn single_chars() {
let crateid: CrateId = from_str("a/b#1").expect("valid crateid");
- assert_eq!(crateid.name, "b".to_owned());
- assert_eq!(crateid.version, Some("1".to_owned()));
- assert_eq!(crateid.path, "a/b".to_owned());
+ assert_eq!(crateid.name, "b".to_strbuf());
+ assert_eq!(crateid.version, Some("1".to_strbuf()));
+ assert_eq!(crateid.path, "a/b".to_strbuf());
}
#[test]
fn missing_version() {
let crateid: CrateId = from_str("foo#").expect("valid crateid");
- assert_eq!(crateid.name, "foo".to_owned());
+ assert_eq!(crateid.name, "foo".to_strbuf());
assert_eq!(crateid.version, None);
- assert_eq!(crateid.path, "foo".to_owned());
+ assert_eq!(crateid.path, "foo".to_strbuf());
}
#[test]
fn path_and_name() {
let crateid: CrateId = from_str("foo/rust-bar#bar:1.0").expect("valid crateid");
- assert_eq!(crateid.name, "bar".to_owned());
- assert_eq!(crateid.version, Some("1.0".to_owned()));
- assert_eq!(crateid.path, "foo/rust-bar".to_owned());
+ assert_eq!(crateid.name, "bar".to_strbuf());
+ assert_eq!(crateid.version, Some("1.0".to_strbuf()));
+ assert_eq!(crateid.path, "foo/rust-bar".to_strbuf());
}
#[test]
fn empty_name() {
let crateid: CrateId = from_str("foo/bar#:1.0").expect("valid crateid");
- assert_eq!(crateid.name, "bar".to_owned());
- assert_eq!(crateid.version, Some("1.0".to_owned()));
- assert_eq!(crateid.path, "foo/bar".to_owned());
+ assert_eq!(crateid.name, "bar".to_strbuf());
+ assert_eq!(crateid.version, Some("1.0".to_strbuf()));
+ assert_eq!(crateid.path, "foo/bar".to_strbuf());
}
// the span)
let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info};
let ses = cm.span_to_str(span_end);
- try!(print_diagnostic(dst, ses, lvl, msg));
+ try!(print_diagnostic(dst, ses.as_slice(), lvl, msg));
if rsp.is_full_span() {
try!(custom_highlight_lines(dst, cm, sp, lvl, lines));
}
} else {
- try!(print_diagnostic(dst, ss, lvl, msg));
+ try!(print_diagnostic(dst, ss.as_slice(), lvl, msg));
if rsp.is_full_span() {
try!(highlight_lines(dst, cm, sp, lvl, lines));
}
}
let orig = fm.get_line(*lines.lines.get(0) as int);
for pos in range(0u, left-skip) {
- let cur_char = orig[pos] as char;
+ let cur_char = orig.as_slice()[pos] as char;
// Whenever a tab occurs on the previous line, we insert one on
// the error-point-squiggly-line as well (instead of a space).
// That way the squiggly line will usually appear in the correct
sp: Span)
-> io::IoResult<()> {
for ei in sp.expn_info.iter() {
- let ss = ei.callee.span.as_ref().map_or("".to_owned(), |span| cm.span_to_str(*span));
+ let ss = ei.callee
+ .span
+ .as_ref()
+ .map_or("".to_strbuf(), |span| cm.span_to_str(*span));
let (pre, post) = match ei.callee.format {
codemap::MacroAttribute => ("#[", "]"),
codemap::MacroBang => ("", "!")
};
- try!(print_diagnostic(w, ss, Note,
+ try!(print_diagnostic(w, ss.as_slice(), Note,
format!("in expansion of {}{}{}", pre,
ei.callee.name, post)));
let ss = cm.span_to_str(ei.call_site);
- try!(print_diagnostic(w, ss, Note, "expansion site"));
+ try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site"));
try!(print_macro_backtrace(w, cm, ei.call_site));
}
Ok(())
}
-pub fn expect<T:Clone>(diag: &SpanHandler, opt: Option<T>, msg: || -> ~str) -> T {
+pub fn expect<T:Clone>(diag: &SpanHandler, opt: Option<T>, msg: || -> StrBuf)
+ -> T {
match opt {
Some(ref t) => (*t).clone(),
- None => diag.handler().bug(msg()),
+ None => diag.handler().bug(msg().as_slice()),
}
}
// ast::MacInvocTT.
pub struct MacroDef {
- pub name: ~str,
+ pub name: StrBuf,
pub ext: SyntaxExtension
}
pub struct MacroCrate {
pub lib: Option<Path>,
- pub macros: Vec<~str>,
- pub registrar_symbol: Option<~str>,
+ pub macros: Vec<StrBuf>,
+ pub registrar_symbol: Option<StrBuf>,
}
pub trait CrateLoader {
pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
pub fn mod_path(&self) -> Vec<ast::Ident> {
let mut v = Vec::new();
- v.push(token::str_to_ident(self.ecfg.crate_id.name));
+ v.push(token::str_to_ident(self.ecfg.crate_id.name.as_slice()));
v.extend(self.mod_path.iter().map(|a| *a));
return v;
}
sp: Span,
tts: &[ast::TokenTree],
name: &str)
- -> Option<~str> {
+ -> Option<StrBuf> {
if tts.len() != 1 {
cx.span_err(sp, format!("{} takes 1 argument.", name));
} else {
match tts[0] {
ast::TTTok(_, token::LIT_STR(ident))
| ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => {
- return Some(token::get_ident(ident).get().to_str())
+ return Some(token::get_ident(ident).get().to_strbuf())
}
_ => cx.span_err(sp, format!("{} requires a string.", name)),
}
vec!(
self.expr_str(span, msg),
self.expr_str(span,
- token::intern_and_get_ident(loc.file.name)),
+ token::intern_and_get_ident(loc.file
+ .name
+ .as_slice())),
self.expr_uint(span, loc.line)))
}
to_set.expn_info = Some(@codemap::ExpnInfo {
call_site: to_set,
callee: codemap::NameAndSpan {
- name: format!("deriving({})", trait_name),
+ name: format!("deriving({})", trait_name).to_strbuf(),
format: codemap::MacroAttribute,
span: Some(self.span)
}
Some(v) => v
};
- let e = match os::getenv(var) {
+ let e = match os::getenv(var.as_slice()) {
None => {
cx.expr_path(cx.path_all(sp,
true,
fld.cx.bt_push(ExpnInfo {
call_site: e.span,
callee: NameAndSpan {
- name: extnamestr.get().to_str(),
+ name: extnamestr.get().to_strbuf(),
format: MacroBang,
span: exp_span,
},
fld.cx.bt_push(ExpnInfo {
call_site: attr.span,
callee: NameAndSpan {
- name: mname.get().to_str(),
+ name: mname.get().to_strbuf(),
format: MacroAttribute,
span: None
}
fld.cx.bt_push(ExpnInfo {
call_site: attr.span,
callee: NameAndSpan {
- name: mname.get().to_str(),
+ name: mname.get().to_strbuf(),
format: MacroAttribute,
span: None,
}
fld.cx.bt_push(ExpnInfo {
call_site: it.span,
callee: NameAndSpan {
- name: extnamestr.get().to_str(),
+ name: extnamestr.get().to_strbuf(),
format: MacroBang,
span: span
}
fld.cx.bt_push(ExpnInfo {
call_site: it.span,
callee: NameAndSpan {
- name: extnamestr.get().to_str(),
+ name: extnamestr.get().to_strbuf(),
format: MacroBang,
span: span
}
Some(MacroDef { name, ext }) => {
// yikes... no idea how to apply the mark to this. I'm afraid
// we're going to have to wait-and-see on this one.
- fld.extsbox.insert(intern(name), ext);
+ fld.extsbox.insert(intern(name.as_slice()), ext);
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
SmallVector::one(it)
} else {
_ => unreachable!()
};
let name = format!("<{} macros>", token::get_ident(crate_name));
+ let name = name.to_strbuf();
for source in macros.iter() {
let item = parse::parse_item_from_source_str(name.clone(),
};
unsafe {
- let registrar: MacroCrateRegistrationFun = match lib.symbol(registrar) {
- Ok(registrar) => registrar,
- // again fatal if we can't register macros
- Err(err) => fld.cx.span_fatal(krate.span, err)
- };
+ let registrar: MacroCrateRegistrationFun =
+ match lib.symbol(registrar.as_slice()) {
+ Ok(registrar) => registrar,
+ // again fatal if we can't register macros
+ Err(err) => fld.cx.span_fatal(krate.span, err)
+ };
registrar(|name, extension| {
let extension = match extension {
NormalTT(ext, _) => NormalTT(ext, Some(krate.span)),
fld.cx.bt_push(ExpnInfo {
call_site: s.span,
callee: NameAndSpan {
- name: extnamestr.get().to_str(),
+ name: extnamestr.get().to_strbuf(),
format: MacroBang,
span: exp_span,
}
#[should_fail]
#[test] fn macros_cant_escape_fns_test () {
let src = "fn bogus() {macro_rules! z (() => (3+4))}\
- fn inty() -> int { z!() }".to_owned();
+ fn inty() -> int { z!() }".to_strbuf();
let sess = parse::new_parse_sess();
let crate_ast = parse::parse_crate_from_source_str(
- "<test>".to_owned(),
+ "<test>".to_strbuf(),
src,
Vec::new(), &sess);
// should fail:
#[should_fail]
#[test] fn macros_cant_escape_mods_test () {
let src = "mod foo {macro_rules! z (() => (3+4))}\
- fn inty() -> int { z!() }".to_owned();
+ fn inty() -> int { z!() }".to_strbuf();
let sess = parse::new_parse_sess();
let crate_ast = parse::parse_crate_from_source_str(
- "<test>".to_owned(),
+ "<test>".to_strbuf(),
src,
Vec::new(), &sess);
// should fail:
// macro_escape modules shouldn't cause macros to leave scope
#[test] fn macros_can_escape_flattened_mods_test () {
let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\
- fn inty() -> int { z!() }".to_owned();
+ fn inty() -> int { z!() }".to_strbuf();
let sess = parse::new_parse_sess();
let crate_ast = parse::parse_crate_from_source_str(
- "<test>".to_owned(),
+ "<test>".to_strbuf(),
src,
Vec::new(), &sess);
// should fail:
}
}
- fn expand_crate_str(crate_str: ~str) -> ast::Crate {
+ fn expand_crate_str(crate_str: StrBuf) -> ast::Crate {
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...
// println!("expanded: {:?}\n",expanded_ast);
//mtwt_resolve_crate(expanded_ast)
//}
- //fn expand_and_resolve_and_pretty_print (crate_str: @str) -> ~str {
+ //fn expand_and_resolve_and_pretty_print (crate_str: @str) -> StrBuf {
//let resolved_ast = expand_and_resolve(crate_str);
//pprust::to_str(&resolved_ast,fake_print_crate,get_ident_interner())
//}
#[test] fn macro_tokens_should_match(){
- expand_crate_str("macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_owned());
+ expand_crate_str(
+ "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_strbuf());
}
// renaming tests expand a crate and then check that the bindings match
let (teststr, bound_connections, bound_ident_check) = match *t {
(ref str,ref conns, bic) => (str.to_owned(), conns.clone(), bic)
};
- let cr = expand_crate_str(teststr.to_owned());
+ let cr = expand_crate_str(teststr.to_strbuf());
// find the bindings:
let mut name_finder = new_name_finder(Vec::new());
visit::walk_crate(&mut name_finder,&cr,());
let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_str()))
macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}}))
foo_module!()
-".to_owned();
+".to_strbuf();
let cr = expand_crate_str(crate_str);
// find the xx binding
let mut name_finder = new_name_finder(Vec::new());
#[test]
fn pat_idents(){
- let pat = string_to_pat("(a,Foo{x:c @ (b,9),y:Bar(4,d)})".to_owned());
+ let pat = string_to_pat(
+ "(a,Foo{x:c @ (b,9),y:Bar(4,d)})".to_strbuf());
let mut pat_idents = new_name_finder(Vec::new());
pat_idents.visit_pat(pat, ());
assert_eq!(pat_idents.ident_accumulator,
use parse::token;
use rsparse = parse;
-use std::fmt::parse;
+use parse = fmt_macros;
use collections::{HashMap, HashSet};
#[deriving(Eq)]
enum ArgumentType {
- Known(~str),
+ Known(StrBuf),
Unsigned,
String,
}
enum Position {
Exact(uint),
- Named(~str),
+ Named(StrBuf),
}
struct Context<'a, 'b> {
// Note that we keep a side-array of the ordering of the named arguments
// found to be sure that we can translate them in the same order that they
// were declared in.
- names: HashMap<~str, @ast::Expr>,
- name_types: HashMap<~str, ArgumentType>,
- name_ordering: Vec<~str>,
+ names: HashMap<StrBuf, @ast::Expr>,
+ name_types: HashMap<StrBuf, ArgumentType>,
+ name_ordering: Vec<StrBuf>,
// Collection of the compiled `rt::Piece` structures
pieces: Vec<@ast::Expr> ,
- name_positions: HashMap<~str, uint>,
+ name_positions: HashMap<StrBuf, uint>,
method_statics: Vec<@ast::Item> ,
// Updated as arguments are consumed or methods are entered
/// Some((fmtstr, unnamed arguments, ordering of named arguments,
/// named arguments))
fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> (@ast::Expr, Option<(@ast::Expr, Vec<@ast::Expr>, Vec<~str>,
- HashMap<~str, @ast::Expr>)>) {
+ -> (@ast::Expr, Option<(@ast::Expr, Vec<@ast::Expr>, Vec<StrBuf>,
+ HashMap<StrBuf, @ast::Expr>)>) {
let mut args = Vec::new();
- let mut names = HashMap::<~str, @ast::Expr>::new();
+ let mut names = HashMap::<StrBuf, @ast::Expr>::new();
let mut order = Vec::new();
let mut p = rsparse::new_parser_from_tts(ecx.parse_sess(),
continue
}
}
- order.push(name.to_str());
- names.insert(name.to_str(), e);
+ order.push(name.to_strbuf());
+ names.insert(name.to_strbuf(), e);
} else {
args.push(p.parse_expr());
}
Exact(i)
}
parse::ArgumentIs(i) => Exact(i),
- parse::ArgumentNamed(s) => Named(s.to_str()),
+ parse::ArgumentNamed(s) => Named(s.to_strbuf()),
};
// and finally the method being applied
match arg.method {
None => {
- let ty = Known(arg.format.ty.to_str());
+ let ty = Known(arg.format.ty.to_strbuf());
self.verify_arg_type(pos, ty);
}
Some(ref method) => { self.verify_method(pos, *method); }
self.verify_arg_type(Exact(i), Unsigned);
}
parse::CountIsName(s) => {
- self.verify_arg_type(Named(s.to_str()), Unsigned);
+ self.verify_arg_type(Named(s.to_strbuf()), Unsigned);
}
parse::CountIsNextParam => {
if self.check_positional_ok() {
parse::Keyword(name) => {
self.ecx.span_err(self.fmtsp,
format!("duplicate selector \
- `{:?}`", name));
+ `{}`", name));
}
parse::Literal(idx) => {
self.ecx.span_err(self.fmtsp,
return vec!(unnamed, allow_dead_code);
}
- fn parsepath(&self, s: &str) -> Vec<ast::Ident> {
- vec!(self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
- self.ecx.ident_of("parse"), self.ecx.ident_of(s))
- }
-
fn rtpath(&self, s: &str) -> Vec<ast::Ident> {
vec!(self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
self.ecx.ident_of("rt"), self.ecx.ident_of(s))
}
- fn ctpath(&self, s: &str) -> Vec<ast::Ident> {
- vec!(self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
- self.ecx.ident_of("parse"), self.ecx.ident_of(s))
- }
-
fn none(&self) -> @ast::Expr {
let none = self.ecx.path_global(self.fmtsp, vec!(
self.ecx.ident_of("std"),
}).collect();
let (lr, selarg) = match arm.selector {
parse::Keyword(t) => {
- let p = self.ctpath(format!("{:?}", t));
+ let p = self.rtpath(t.to_str());
let p = self.ecx.path_global(sp, p);
(self.rtpath("Keyword"), self.ecx.expr_path(p))
}
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill));
let align = match arg.format.align {
parse::AlignLeft => {
- self.ecx.path_global(sp, self.parsepath("AlignLeft"))
+ self.ecx.path_global(sp, self.rtpath("AlignLeft"))
}
parse::AlignRight => {
- self.ecx.path_global(sp, self.parsepath("AlignRight"))
+ self.ecx.path_global(sp, self.rtpath("AlignRight"))
}
parse::AlignUnknown => {
- self.ecx.path_global(sp, self.parsepath("AlignUnknown"))
+ self.ecx.path_global(sp, self.rtpath("AlignUnknown"))
}
};
let align = self.ecx.expr_path(align);
pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
extra: @ast::Expr,
efmt: @ast::Expr, args: Vec<@ast::Expr>,
- name_ordering: Vec<~str>,
- names: HashMap<~str, @ast::Expr>) -> @ast::Expr {
+ name_ordering: Vec<StrBuf>,
+ names: HashMap<StrBuf, @ast::Expr>) -> @ast::Expr {
let arg_types = Vec::from_fn(args.len(), |_| None);
let mut cx = Context {
ecx: ecx,
use ast::{Ident, Mrk, Name, SyntaxContext};
use std::cell::RefCell;
-use std::local_data;
use std::rc::Rc;
use collections::HashMap;
pub fn with_sctable<T>(op: |&SCTable| -> T) -> T {
local_data_key!(sctable_key: Rc<SCTable>)
- local_data::get(sctable_key, |opt_ts| {
- let table = match opt_ts {
- None => {
- let ts = Rc::new(new_sctable_internal());
- local_data::set(sctable_key, ts.clone());
- ts
- }
- Some(ts) => ts.clone()
- };
- op(&*table)
- })
+ match sctable_key.get() {
+ Some(ts) => op(&**ts),
+ None => {
+ let ts = Rc::new(new_sctable_internal());
+ sctable_key.replace(Some(ts.clone()));
+ op(&*ts)
+ }
+ }
}
// Make a fresh syntax context table with EmptyCtxt in slot zero
fn with_resolve_table_mut<T>(op: |&mut ResolveTable| -> T) -> T {
local_data_key!(resolve_table_key: Rc<RefCell<ResolveTable>>)
- local_data::get(resolve_table_key, |opt_ts| {
- let table = match opt_ts {
- None => {
- let ts = Rc::new(RefCell::new(HashMap::new()));
- local_data::set(resolve_table_key, ts.clone());
- ts
- }
- Some(ts) => ts.clone()
- };
- op(&mut *table.borrow_mut())
- })
+ match resolve_table_key.get() {
+ Some(ts) => op(&mut *ts.borrow_mut()),
+ None => {
+ let ts = Rc::new(RefCell::new(HashMap::new()));
+ resolve_table_key.replace(Some(ts.clone()));
+ op(&mut *ts.borrow_mut())
+ }
+ }
}
// Resolve a syntax object to a name, per MTWT.
trait ToSource : ToTokens {
// Takes a thing and generates a string containing rust code for it.
- pub fn to_source() -> ~str;
+ pub fn to_source() -> StrBuf;
// If you can make source, you can definitely make tokens.
pub fn to_tokens(cx: &ExtCtxt) -> ~[TokenTree] {
pub trait ToSource {
// Takes a thing and generates a string containing rust code for it.
- fn to_source(&self) -> ~str;
+ fn to_source(&self) -> StrBuf;
}
impl ToSource for ast::Ident {
- fn to_source(&self) -> ~str {
- get_ident(*self).get().to_str()
+ fn to_source(&self) -> StrBuf {
+ get_ident(*self).get().to_strbuf()
}
}
impl ToSource for @ast::Item {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
pprust::item_to_str(*self)
}
}
impl<'a> ToSource for &'a [@ast::Item] {
- fn to_source(&self) -> ~str {
- self.iter().map(|i| i.to_source()).collect::<Vec<~str>>().connect("\n\n")
+ fn to_source(&self) -> StrBuf {
+ self.iter()
+ .map(|i| i.to_source())
+ .collect::<Vec<StrBuf>>()
+ .connect("\n\n")
+ .to_strbuf()
}
}
impl ToSource for ast::Ty {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
pprust::ty_to_str(self)
}
}
impl<'a> ToSource for &'a [ast::Ty] {
- fn to_source(&self) -> ~str {
- self.iter().map(|i| i.to_source()).collect::<Vec<~str>>().connect(", ")
+ fn to_source(&self) -> StrBuf {
+ self.iter()
+ .map(|i| i.to_source())
+ .collect::<Vec<StrBuf>>()
+ .connect(", ")
+ .to_strbuf()
}
}
impl ToSource for Generics {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
pprust::generics_to_str(self)
}
}
impl ToSource for @ast::Expr {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
pprust::expr_to_str(*self)
}
}
impl ToSource for ast::Block {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
pprust::block_to_str(self)
}
}
impl<'a> ToSource for &'a str {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitStr(
token::intern_and_get_ident(*self), ast::CookedStr));
pprust::lit_to_str(&lit)
}
impl ToSource for () {
- fn to_source(&self) -> ~str {
- "()".to_owned()
+ fn to_source(&self) -> StrBuf {
+ "()".to_strbuf()
}
}
impl ToSource for bool {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitBool(*self));
pprust::lit_to_str(&lit)
}
}
impl ToSource for char {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitChar(*self));
pprust::lit_to_str(&lit)
}
}
impl ToSource for int {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI));
pprust::lit_to_str(&lit)
}
}
impl ToSource for i8 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI8));
pprust::lit_to_str(&lit)
}
}
impl ToSource for i16 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI16));
pprust::lit_to_str(&lit)
}
impl ToSource for i32 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI32));
pprust::lit_to_str(&lit)
}
}
impl ToSource for i64 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI64));
pprust::lit_to_str(&lit)
}
}
impl ToSource for uint {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU));
pprust::lit_to_str(&lit)
}
}
impl ToSource for u8 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU8));
pprust::lit_to_str(&lit)
}
}
impl ToSource for u16 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU16));
pprust::lit_to_str(&lit)
}
}
impl ToSource for u32 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU32));
pprust::lit_to_str(&lit)
}
}
impl ToSource for u64 {
- fn to_source(&self) -> ~str {
+ fn to_source(&self) -> StrBuf {
let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU64));
pprust::lit_to_str(&lit)
}
impl_to_tokens!(u64)
pub trait ExtParseUtils {
- fn parse_item(&self, s: ~str) -> @ast::Item;
- fn parse_expr(&self, s: ~str) -> @ast::Expr;
- fn parse_stmt(&self, s: ~str) -> @ast::Stmt;
- fn parse_tts(&self, s: ~str) -> Vec<ast::TokenTree> ;
+ fn parse_item(&self, s: StrBuf) -> @ast::Item;
+ fn parse_expr(&self, s: StrBuf) -> @ast::Expr;
+ fn parse_stmt(&self, s: StrBuf) -> @ast::Stmt;
+ fn parse_tts(&self, s: StrBuf) -> Vec<ast::TokenTree> ;
}
impl<'a> ExtParseUtils for ExtCtxt<'a> {
- fn parse_item(&self, s: ~str) -> @ast::Item {
+ fn parse_item(&self, s: StrBuf) -> @ast::Item {
let res = parse::parse_item_from_source_str(
- "<quote expansion>".to_str(),
+ "<quote expansion>".to_strbuf(),
s,
self.cfg(),
self.parse_sess());
}
}
- fn parse_stmt(&self, s: ~str) -> @ast::Stmt {
- parse::parse_stmt_from_source_str("<quote expansion>".to_str(),
+ fn parse_stmt(&self, s: StrBuf) -> @ast::Stmt {
+ parse::parse_stmt_from_source_str("<quote expansion>".to_strbuf(),
s,
self.cfg(),
Vec::new(),
self.parse_sess())
}
- fn parse_expr(&self, s: ~str) -> @ast::Expr {
- parse::parse_expr_from_source_str("<quote expansion>".to_str(),
+ fn parse_expr(&self, s: StrBuf) -> @ast::Expr {
+ parse::parse_expr_from_source_str("<quote expansion>".to_strbuf(),
s,
self.cfg(),
self.parse_sess())
}
- fn parse_tts(&self, s: ~str) -> Vec<ast::TokenTree> {
- parse::parse_tts_from_source_str("<quote expansion>".to_str(),
+ fn parse_tts(&self, s: StrBuf) -> Vec<ast::TokenTree> {
+ parse::parse_tts_from_source_str("<quote expansion>".to_strbuf(),
s,
self.cfg(),
self.parse_sess())
base::MacExpr::new(expanded)
}
-fn ids_ext(strs: Vec<~str> ) -> Vec<ast::Ident> {
- strs.iter().map(|str| str_to_ident(*str)).collect()
+fn ids_ext(strs: Vec<StrBuf> ) -> Vec<ast::Ident> {
+ strs.iter().map(|str| str_to_ident((*str).as_slice())).collect()
}
fn id_ext(str: &str) -> ast::Ident {
sp: Span,
cx_expr: @ast::Expr,
expr: @ast::Expr) -> @ast::Expr {
- let uses = vec!( cx.view_use_glob(sp, ast::Inherited,
- ids_ext(vec!("syntax".to_owned(),
- "ext".to_owned(),
- "quote".to_owned(),
- "rt".to_owned()))) );
+ let uses = vec![ cx.view_use_glob(sp, ast::Inherited,
+ ids_ext(vec!["syntax".to_strbuf(),
+ "ext".to_strbuf(),
+ "quote".to_strbuf(),
+ "rt".to_strbuf()])) ];
let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr);
let topmost = topmost_expn_info(cx.backtrace().unwrap());
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
- let filename = token::intern_and_get_ident(loc.file.name);
+ let filename = token::intern_and_get_ident(loc.file.name.as_slice());
base::MacExpr::new(cx.expr_str(topmost.call_site, filename))
}
pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult> {
let s = pprust::tts_to_str(tts);
- base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(s)))
+ base::MacExpr::new(cx.expr_str(sp,
+ token::intern_and_get_ident(s.as_slice())))
}
pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
base::check_zero_tts(cx, sp, tts, "module_path!");
let string = cx.mod_path()
.iter()
- .map(|x| token::get_ident(*x).get().to_str())
- .collect::<Vec<~str>>()
+ .map(|x| token::get_ident(*x).get().to_strbuf())
+ .collect::<Vec<StrBuf>>()
.connect("::");
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(string)))
}
Some(src) => {
// Add this input file to the code map to make it available as
// dependency information
- let filename = file.display().to_str();
+ let filename = file.display().to_str().to_strbuf();
let interned = token::intern_and_get_ident(src);
- cx.codemap().new_filemap(filename, src.to_owned());
+ cx.codemap().new_filemap(filename, src.to_strbuf());
base::MacExpr::new(cx.expr_str(sp, interned))
}
..
} => {
// Don't recurse into file using "include!"
- if "include" == *name {
+ if "include" == name.as_slice() {
expn_info
} else {
topmost_expn_info(next_expn_info)
pub enum ParseResult {
Success(HashMap<Ident, Rc<NamedMatch>>),
- Failure(codemap::Span, ~str),
- Error(codemap::Span, ~str)
+ Failure(codemap::Span, StrBuf),
+ Error(codemap::Span, StrBuf)
}
pub fn parse_or_else(sess: &ParseSess,
-> HashMap<Ident, Rc<NamedMatch>> {
match parse(sess, cfg, rdr, ms.as_slice()) {
Success(m) => m,
- Failure(sp, str) => sess.span_diagnostic.span_fatal(sp, str),
- Error(sp, str) => sess.span_diagnostic.span_fatal(sp, str)
+ Failure(sp, str) => {
+ sess.span_diagnostic.span_fatal(sp, str.as_slice())
+ }
+ Error(sp, str) => {
+ sess.span_diagnostic.span_fatal(sp, str.as_slice())
+ }
}
}
}
return Success(nameize(sess, ms, v.as_slice()));
} else if eof_eis.len() > 1u {
- return Error(sp, "ambiguity: multiple successful parses".to_owned());
+ return Error(sp, "ambiguity: multiple successful parses".to_strbuf());
} else {
- return Failure(sp, "unexpected end of macro invocation".to_owned());
+ return Failure(sp, "unexpected end of macro invocation".to_strbuf());
}
} else {
if (bb_eis.len() > 0u && next_eis.len() > 0u)
let nts = bb_eis.iter().map(|ei| {
match ei.elts.get(ei.idx).node {
MatchNonterminal(bind, name, _) => {
- format!("{} ('{}')",
+ (format!("{} ('{}')",
token::get_ident(name),
- token::get_ident(bind))
+ token::get_ident(bind))).to_strbuf()
}
_ => fail!()
- } }).collect::<Vec<~str>>().connect(" or ");
+ } }).collect::<Vec<StrBuf>>().connect(" or ");
return Error(sp, format!(
"local ambiguity: multiple parsing options: \
built-in NTs {} or {} other options.",
- nts, next_eis.len()));
+ nts, next_eis.len()).to_strbuf());
} else if bb_eis.len() == 0u && next_eis.len() == 0u {
return Failure(sp, format!("no rules expected the token `{}`",
- token::to_str(&tok)));
+ token::to_str(&tok)).to_strbuf());
} else if next_eis.len() > 0u {
/* Now process the next token */
while next_eis.len() > 0u {
token::IDENT(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
_ => {
let token_str = token::to_str(&p.token);
- p.fatal("expected ident, found ".to_owned() + token_str)
+ p.fatal((format!("expected ident, found {}",
+ token_str.as_slice())).as_slice())
}
},
"path" => {
// Which arm's failure should we report? (the one furthest along)
let mut best_fail_spot = DUMMY_SP;
- let mut best_fail_msg = "internal error: ran no matchers".to_owned();
+ let mut best_fail_msg = "internal error: ran no matchers".to_strbuf();
for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
match **lhs {
best_fail_spot = sp;
best_fail_msg = (*msg).clone();
},
- Error(sp, ref msg) => cx.span_fatal(sp, (*msg))
+ Error(sp, ref msg) => cx.span_fatal(sp, msg.as_slice())
}
}
_ => cx.bug("non-matcher found in parsed lhses")
}
}
- cx.span_fatal(best_fail_spot, best_fail_msg);
+ cx.span_fatal(best_fail_spot, best_fail_msg.as_slice());
}
// this procedure performs the expansion of the
box MacroRulesDefiner {
def: RefCell::new(Some(MacroDef {
- name: token::get_ident(name).to_str(),
+ name: token::get_ident(name).to_str().to_strbuf(),
ext: NormalTT(exp, Some(sp))
}))
} as Box<MacResult>
enum LockstepIterSize {
LisUnconstrained,
LisConstraint(uint, Ident),
- LisContradiction(~str),
+ LisContradiction(StrBuf),
}
fn lis_merge(lhs: LockstepIterSize, rhs: LockstepIterSize) -> LockstepIterSize {
let r_n = token::get_ident(r_id);
LisContradiction(format!("inconsistent lockstep iteration: \
'{}' has {} items, but '{}' has {}",
- l_n, l_len, r_n, r_len))
+ l_n, l_len, r_n, r_len).to_strbuf())
}
}
}
}
LisContradiction(ref msg) => {
// FIXME #2887 blame macro invoker instead
- r.sp_diag.span_fatal(sp.clone(), *msg);
+ r.sp_diag.span_fatal(sp.clone(), msg.as_slice());
}
LisConstraint(len, _) => {
if len == 0 {
let pred_val = $pred;
let a_val = $a;
let b_val = $b;
- if !(pred_val(a_val,b_val)) {
+ if !(pred_val(a_val.as_slice(),b_val.as_slice())) {
fail!("expected args satisfying {}, got {:?} and {:?}",
$predname, a_val, b_val);
}
#[test] fn ident_transformation () {
let mut zz_fold = ToZzIdentFolder;
let ast = string_to_crate(
- "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_owned());
+ "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_strbuf());
let folded_crate = zz_fold.fold_crate(ast);
- assert_pred!(matches_codepattern,
- "matches_codepattern",
- pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
- "#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_owned());
+ assert_pred!(
+ matches_codepattern,
+ "matches_codepattern",
+ pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
+ "#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_strbuf());
}
// even inside macro defs....
let mut zz_fold = ToZzIdentFolder;
let ast = string_to_crate(
"macro_rules! a {(b $c:expr $(d $e:token)f+ => \
- (g $(d $d $e)+))} ".to_owned());
+ (g $(d $d $e)+))} ".to_strbuf());
let folded_crate = zz_fold.fold_crate(ast);
- assert_pred!(matches_codepattern,
- "matches_codepattern",
- pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
- "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_owned());
+ assert_pred!(
+ matches_codepattern,
+ "matches_codepattern",
+ pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
+ "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_strbuf());
}
}
extern crate collections;
#[phase(syntax, link)]
extern crate log;
+extern crate fmt_macros;
pub mod util {
pub mod interner;
#[deriving(Clone)]
pub struct Comment {
pub style: CommentStyle,
- pub lines: Vec<~str>,
+ pub lines: Vec<StrBuf>,
pub pos: BytePos,
}
}
}
-pub fn strip_doc_comment_decoration(comment: &str) -> ~str {
+pub fn strip_doc_comment_decoration(comment: &str) -> StrBuf {
/// remove whitespace-only lines from the start/end of lines
- fn vertical_trim(lines: Vec<~str> ) -> Vec<~str> {
+ fn vertical_trim(lines: Vec<StrBuf> ) -> Vec<StrBuf> {
let mut i = 0u;
let mut j = lines.len();
// first line of all-stars should be omitted
- if lines.len() > 0 && lines.get(0).chars().all(|c| c == '*') {
+ if lines.len() > 0 &&
+ lines.get(0).as_slice().chars().all(|c| c == '*') {
i += 1;
}
- while i < j && lines.get(i).trim().is_empty() {
+ while i < j && lines.get(i).as_slice().trim().is_empty() {
i += 1;
}
// like the first, a last line of all stars should be omitted
- if j > i && lines.get(j - 1).chars().skip(1).all(|c| c == '*') {
+ if j > i && lines.get(j - 1)
+ .as_slice()
+ .chars()
+ .skip(1)
+ .all(|c| c == '*') {
j -= 1;
}
- while j > i && lines.get(j - 1).trim().is_empty() {
+ while j > i && lines.get(j - 1).as_slice().trim().is_empty() {
j -= 1;
}
return lines.slice(i, j).iter().map(|x| (*x).clone()).collect();
}
/// remove a "[ \t]*\*" block from each line, if possible
- fn horizontal_trim(lines: Vec<~str> ) -> Vec<~str> {
+ fn horizontal_trim(lines: Vec<StrBuf> ) -> Vec<StrBuf> {
let mut i = uint::MAX;
let mut can_trim = true;
let mut first = true;
for line in lines.iter() {
- for (j, c) in line.chars().enumerate() {
+ for (j, c) in line.as_slice().chars().enumerate() {
if j > i || !"* \t".contains_char(c) {
can_trim = false;
break;
}
if can_trim {
- lines.iter().map(|line| line.slice(i + 1, line.len()).to_owned()).collect()
+ lines.iter().map(|line| {
+ line.as_slice().slice(i + 1, line.len()).to_strbuf()
+ }).collect()
} else {
lines
}
static ONLINERS: &'static [&'static str] = &["///!", "///", "//!", "//"];
for prefix in ONLINERS.iter() {
if comment.starts_with(*prefix) {
- return comment.slice_from(prefix.len()).to_owned();
+ return comment.slice_from(prefix.len()).to_strbuf();
}
}
if comment.starts_with("/*") {
let lines = comment.slice(3u, comment.len() - 2u)
.lines_any()
- .map(|s| s.to_owned())
- .collect::<Vec<~str> >();
+ .map(|s| s.to_strbuf())
+ .collect::<Vec<StrBuf> >();
let lines = vertical_trim(lines);
let lines = horizontal_trim(lines);
- return lines.connect("\n");
+ return lines.connect("\n").to_strbuf();
}
fail!("not a doc-comment: {}", comment);
}
-fn read_to_eol(rdr: &mut StringReader) -> ~str {
+fn read_to_eol(rdr: &mut StringReader) -> StrBuf {
let mut val = StrBuf::new();
while !rdr.curr_is('\n') && !is_eof(rdr) {
val.push_char(rdr.curr.unwrap());
bump(rdr);
}
if rdr.curr_is('\n') { bump(rdr); }
- return val.into_owned();
+ return val
}
-fn read_one_line_comment(rdr: &mut StringReader) -> ~str {
+fn read_one_line_comment(rdr: &mut StringReader) -> StrBuf {
let val = read_to_eol(rdr);
- assert!((val[0] == '/' as u8 && val[1] == '/' as u8) ||
- (val[0] == '#' as u8 && val[1] == '!' as u8));
+ assert!((val.as_slice()[0] == '/' as u8 &&
+ val.as_slice()[1] == '/' as u8) ||
+ (val.as_slice()[0] == '#' as u8 &&
+ val.as_slice()[1] == '!' as u8));
return val;
}
comments: &mut Vec<Comment>) {
debug!(">>> line comments");
let p = rdr.last_pos;
- let mut lines: Vec<~str> = Vec::new();
+ let mut lines: Vec<StrBuf> = Vec::new();
while rdr.curr_is('/') && nextch_is(rdr, '/') {
let line = read_one_line_comment(rdr);
debug!("{}", line);
- if is_doc_comment(line) { // doc-comments are not put in comments
+ // Doc comments are not put in comments.
+ if is_doc_comment(line.as_slice()) {
break;
}
lines.push(line);
return Some(cursor);
}
-fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<~str> ,
- s: ~str, col: CharPos) {
+fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<StrBuf> ,
+ s: StrBuf, col: CharPos) {
let len = s.len();
- let s1 = match all_whitespace(s, col) {
+ let s1 = match all_whitespace(s.as_slice(), col) {
Some(col) => {
if col < len {
- s.slice(col, len).to_owned()
- } else { "".to_owned() }
+ s.as_slice().slice(col, len).to_strbuf()
+ } else {
+ "".to_strbuf()
+ }
}
None => s,
};
comments: &mut Vec<Comment> ) {
debug!(">>> block comment");
let p = rdr.last_pos;
- let mut lines: Vec<~str> = Vec::new();
+ let mut lines: Vec<StrBuf> = Vec::new();
let col = rdr.col;
bump(rdr);
bump(rdr);
return
}
assert!(!curr_line.as_slice().contains_char('\n'));
- lines.push(curr_line.into_owned());
+ lines.push(curr_line);
} else {
let mut level: int = 1;
while level > 0 {
debug!("=== block comment level {}", level);
if is_eof(rdr) {
- rdr.fatal("unterminated block comment".to_owned());
+ rdr.fatal("unterminated block comment".to_strbuf());
}
if rdr.curr_is('\n') {
trim_whitespace_prefix_and_push_line(&mut lines,
- curr_line.into_owned(),
+ curr_line,
col);
curr_line = StrBuf::new();
bump(rdr);
}
if curr_line.len() != 0 {
trim_whitespace_prefix_and_push_line(&mut lines,
- curr_line.into_owned(),
+ curr_line,
col);
}
}
#[deriving(Clone)]
pub struct Literal {
- pub lit: ~str,
+ pub lit: StrBuf,
pub pos: BytePos,
}
// probably not a good thing.
pub fn gather_comments_and_literals(span_diagnostic:
&diagnostic::SpanHandler,
- path: ~str,
+ path: StrBuf,
srdr: &mut io::Reader)
-> (Vec<Comment>, Vec<Literal>) {
let src = srdr.read_to_end().unwrap();
- let src = str::from_utf8(src.as_slice()).unwrap().to_owned();
+ let src = str::from_utf8(src.as_slice()).unwrap().to_strbuf();
let cm = CodeMap::new();
let filemap = cm.new_filemap(path, src);
let mut rdr = lexer::new_low_level_string_reader(span_diagnostic, filemap);
if token::is_lit(&tok) {
with_str_from(&rdr, bstart, |s| {
debug!("tok lit: {}", s);
- literals.push(Literal {lit: s.to_owned(), pos: sp.lo});
+ literals.push(Literal {lit: s.to_strbuf(), pos: sp.lo});
})
} else {
debug!("tok: {}", token::to_str(&tok));
#[test] fn test_block_doc_comment_1() {
let comment = "/**\n * Test \n ** Test\n * Test\n*/";
let stripped = strip_doc_comment_decoration(comment);
- assert_eq!(stripped, " Test \n* Test\n Test".to_owned());
+ assert_eq!(stripped, " Test \n* Test\n Test".to_strbuf());
}
#[test] fn test_block_doc_comment_2() {
let comment = "/**\n * Test\n * Test\n*/";
let stripped = strip_doc_comment_decoration(comment);
- assert_eq!(stripped, " Test\n Test".to_owned());
+ assert_eq!(stripped, " Test\n Test".to_strbuf());
}
#[test] fn test_block_doc_comment_3() {
let comment = "/**\n let a: *int;\n *a = 5;\n*/";
let stripped = strip_doc_comment_decoration(comment);
- assert_eq!(stripped, " let a: *int;\n *a = 5;".to_owned());
+ assert_eq!(stripped, " let a: *int;\n *a = 5;".to_strbuf());
}
#[test] fn test_block_doc_comment_4() {
let comment = "/*******************\n test\n *********************/";
let stripped = strip_doc_comment_decoration(comment);
- assert_eq!(stripped, " test".to_owned());
+ assert_eq!(stripped, " test".to_strbuf());
}
#[test] fn test_line_doc_comment() {
let stripped = strip_doc_comment_decoration("/// test");
- assert_eq!(stripped, " test".to_owned());
+ assert_eq!(stripped, " test".to_strbuf());
let stripped = strip_doc_comment_decoration("///! test");
- assert_eq!(stripped, " test".to_owned());
+ assert_eq!(stripped, " test".to_strbuf());
let stripped = strip_doc_comment_decoration("// test");
- assert_eq!(stripped, " test".to_owned());
+ assert_eq!(stripped, " test".to_strbuf());
let stripped = strip_doc_comment_decoration("// test");
- assert_eq!(stripped, " test".to_owned());
+ assert_eq!(stripped, " test".to_strbuf());
let stripped = strip_doc_comment_decoration("///test");
- assert_eq!(stripped, "test".to_owned());
+ assert_eq!(stripped, "test".to_strbuf());
let stripped = strip_doc_comment_decoration("///!test");
- assert_eq!(stripped, "test".to_owned());
+ assert_eq!(stripped, "test".to_strbuf());
let stripped = strip_doc_comment_decoration("//test");
- assert_eq!(stripped, "test".to_owned());
+ assert_eq!(stripped, "test".to_strbuf());
}
}
pub trait Reader {
fn is_eof(&self) -> bool;
fn next_token(&mut self) -> TokenAndSpan;
- fn fatal(&self, ~str) -> !;
+ fn fatal(&self, StrBuf) -> !;
fn span_diag<'a>(&'a self) -> &'a SpanHandler;
fn peek(&self) -> TokenAndSpan;
}
string_advance_token(self);
ret_val
}
- fn fatal(&self, m: ~str) -> ! {
- self.span_diagnostic.span_fatal(self.peek_span, m)
+ fn fatal(&self, m: StrBuf) -> ! {
+ self.span_diagnostic.span_fatal(self.peek_span, m.as_slice())
}
fn span_diag<'a>(&'a self) -> &'a SpanHandler { self.span_diagnostic }
fn peek(&self) -> TokenAndSpan {
debug!("TtReader: r={:?}", r);
r
}
- fn fatal(&self, m: ~str) -> ! {
- self.sp_diag.span_fatal(self.cur_span, m);
+ fn fatal(&self, m: StrBuf) -> ! {
+ self.sp_diag.span_fatal(self.cur_span, m.as_slice());
}
fn span_diag<'a>(&'a self) -> &'a SpanHandler { self.sp_diag }
fn peek(&self) -> TokenAndSpan {
fn fatal_span(rdr: &mut StringReader,
from_pos: BytePos,
to_pos: BytePos,
- m: ~str)
+ m: StrBuf)
-> ! {
rdr.peek_span = codemap::mk_sp(from_pos, to_pos);
rdr.fatal(m);
fn fatal_span_char(rdr: &mut StringReader,
from_pos: BytePos,
to_pos: BytePos,
- m: ~str,
+ m: StrBuf,
c: char)
-> ! {
- let mut m = StrBuf::from_owned_str(m);
+ let mut m = m;
m.push_str(": ");
char::escape_default(c, |c| m.push_char(c));
- fatal_span(rdr, from_pos, to_pos, m.into_owned());
+ fatal_span(rdr, from_pos, to_pos, m.into_strbuf());
}
// report a lexical error spanning [`from_pos`, `to_pos`), appending the
fn fatal_span_verbose(rdr: &mut StringReader,
from_pos: BytePos,
to_pos: BytePos,
- m: ~str)
+ m: StrBuf)
-> ! {
- let mut m = StrBuf::from_owned_str(m);
+ let mut m = m;
m.push_str(": ");
let from = byte_offset(rdr, from_pos).to_uint();
let to = byte_offset(rdr, to_pos).to_uint();
- m.push_str(rdr.filemap.src.slice(from, to));
- fatal_span(rdr, from_pos, to_pos, m.into_owned());
+ m.push_str(rdr.filemap.src.as_slice().slice(from, to));
+ fatal_span(rdr, from_pos, to_pos, m);
}
// EFFECT: advance peek_tok and peek_span to refer to the next token.
end: BytePos,
f: |s: &str| -> T)
-> T {
- f(rdr.filemap.src.slice(
+ f(rdr.filemap.src.as_slice().slice(
byte_offset(rdr, start).to_uint(),
byte_offset(rdr, end).to_uint()))
}
if current_byte_offset < rdr.filemap.src.len() {
assert!(rdr.curr.is_some());
let last_char = rdr.curr.unwrap();
- let next = rdr.filemap.src.char_range_at(current_byte_offset);
+ let next = rdr.filemap
+ .src
+ .as_slice()
+ .char_range_at(current_byte_offset);
let byte_offset_diff = next.next - current_byte_offset;
rdr.pos = rdr.pos + Pos::from_uint(byte_offset_diff);
rdr.curr = Some(next.ch);
pub fn nextch(rdr: &StringReader) -> Option<char> {
let offset = byte_offset(rdr, rdr.pos).to_uint();
if offset < rdr.filemap.src.len() {
- Some(rdr.filemap.src.char_at(offset))
+ Some(rdr.filemap.src.as_slice().char_at(offset))
} else {
None
}
while level > 0 {
if is_eof(rdr) {
let msg = if is_doc_comment {
- "unterminated block doc-comment".to_owned()
+ "unterminated block doc-comment".to_strbuf()
} else {
- "unterminated block comment".to_owned()
+ "unterminated block comment".to_strbuf()
};
fatal_span(rdr, start_bpos, rdr.last_pos, msg);
} else if rdr.curr_is('/') && nextch_is(rdr, '*') {
if res.is_some() { res } else { consume_whitespace_and_comments(rdr) }
}
-fn scan_exponent(rdr: &mut StringReader, start_bpos: BytePos) -> Option<~str> {
+fn scan_exponent(rdr: &mut StringReader, start_bpos: BytePos) -> Option<StrBuf> {
// \x00 hits the `return None` case immediately, so this is fine.
let mut c = rdr.curr.unwrap_or('\x00');
let mut rslt = StrBuf::new();
}
let exponent = scan_digits(rdr, 10u);
if exponent.len() > 0u {
- rslt.push_str(exponent);
- return Some(rslt.into_owned());
+ rslt.push_str(exponent.as_slice());
+ return Some(rslt);
} else {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "scan_exponent: bad fp literal".to_owned());
+ "scan_exponent: bad fp literal".to_strbuf());
}
- } else { return None::<~str>; }
+ } else {
+ return None::<StrBuf>;
+ }
}
-fn scan_digits(rdr: &mut StringReader, radix: uint) -> ~str {
+fn scan_digits(rdr: &mut StringReader, radix: uint) -> StrBuf {
let mut rslt = StrBuf::new();
loop {
let c = rdr.curr;
rslt.push_char(c.unwrap());
bump(rdr);
}
- _ => return rslt.into_owned()
+ _ => return rslt
}
};
}
fn check_float_base(rdr: &mut StringReader, start_bpos: BytePos, last_bpos: BytePos,
base: uint) {
match base {
- 16u => fatal_span(rdr, start_bpos, last_bpos,
- "hexadecimal float literal is not supported".to_owned()),
+ 16u => {
+ fatal_span(rdr, start_bpos, last_bpos,
+ "hexadecimal float literal is not supported".to_strbuf())
+ }
8u => fatal_span(rdr, start_bpos, last_bpos,
- "octal float literal is not supported".to_owned()),
+ "octal float literal is not supported".to_strbuf()),
2u => fatal_span(rdr, start_bpos, last_bpos,
- "binary float literal is not supported".to_owned()),
+ "binary float literal is not supported".to_strbuf()),
_ => ()
}
}
bump(rdr);
base = 2u;
}
- num_str = StrBuf::from_owned_str(scan_digits(rdr, base));
+ num_str = scan_digits(rdr, base);
c = rdr.curr.unwrap_or('\x00');
nextch(rdr);
if c == 'u' || c == 'i' {
}
if num_str.len() == 0u {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "no valid digits found for number".to_owned());
+ "no valid digits found for number".to_strbuf());
}
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
base as uint) {
Some(p) => p,
None => fatal_span(rdr, start_bpos, rdr.last_pos,
- "int literal is too large".to_owned())
+ "int literal is too large".to_strbuf())
};
match tp {
bump(rdr);
let dec_part = scan_digits(rdr, 10u);
num_str.push_char('.');
- num_str.push_str(dec_part);
+ num_str.push_str(dec_part.as_slice());
}
match scan_exponent(rdr, start_bpos) {
Some(ref s) => {
is_float = true;
- num_str.push_str(*s);
+ num_str.push_str(s.as_slice());
}
None => ()
}
return token::LIT_FLOAT(str_to_ident(num_str.as_slice()), ast::TyF128);
}
fatal_span(rdr, start_bpos, rdr.last_pos,
- "expected `f32`, `f64` or `f128` suffix".to_owned());
+ "expected `f32`, `f64` or `f128` suffix".to_strbuf());
}
if is_float {
check_float_base(rdr, start_bpos, rdr.last_pos, base);
} else {
if num_str.len() == 0u {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "no valid digits found for number".to_owned());
+ "no valid digits found for number".to_strbuf());
}
let parsed = match from_str_radix::<u64>(num_str.as_slice(),
base as uint) {
Some(p) => p,
None => fatal_span(rdr, start_bpos, rdr.last_pos,
- "int literal is too large".to_owned())
+ "int literal is too large".to_strbuf())
};
debug!("lexing {} as an unsuffixed integer literal",
while i != 0u && !is_eof(rdr) {
let n = rdr.curr;
if !is_hex_digit(n) {
- fatal_span_char(rdr, rdr.last_pos, rdr.pos,
- "illegal character in numeric character escape".to_owned(),
- n.unwrap());
+ fatal_span_char(
+ rdr,
+ rdr.last_pos,
+ rdr.pos,
+ "illegal character in numeric character escape".to_strbuf(),
+ n.unwrap());
}
bump(rdr);
accum_int *= 16;
}
if i != 0 && is_eof(rdr) {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "unterminated numeric character escape".to_owned());
+ "unterminated numeric character escape".to_strbuf());
}
match char::from_u32(accum_int as u32) {
Some(x) => x,
None => fatal_span(rdr, start_bpos, rdr.last_pos,
- "illegal numeric character escape".to_owned())
+ "illegal numeric character escape".to_strbuf())
}
}
if token::is_keyword(token::keywords::Self, tok) {
fatal_span(rdr, start, rdr.last_pos,
"invalid lifetime name: 'self \
- is no longer a special lifetime".to_owned());
+ is no longer a special lifetime".to_strbuf());
} else if token::is_any_keyword(tok) &&
!token::is_keyword(token::keywords::Static, tok) {
fatal_span(rdr, start, rdr.last_pos,
- "invalid lifetime name".to_owned());
+ "invalid lifetime name".to_strbuf());
} else {
return token::LIFETIME(ident);
}
'u' => scan_numeric_escape(rdr, 4u),
'U' => scan_numeric_escape(rdr, 8u),
c2 => {
- fatal_span_char(rdr, escaped_pos, rdr.last_pos,
- "unknown character escape".to_owned(), c2)
+ fatal_span_char(rdr,
+ escaped_pos,
+ rdr.last_pos,
+ "unknown character \
+ escape".to_strbuf(),
+ c2)
}
}
}
}
}
'\t' | '\n' | '\r' | '\'' => {
- fatal_span_char(rdr, start, rdr.last_pos,
- "character constant must be escaped".to_owned(), c2);
+ fatal_span_char(
+ rdr,
+ start,
+ rdr.last_pos,
+ "character constant must be escaped".to_strbuf(),
+ c2);
}
_ => {}
}
// ascii single quote.
start - BytePos(1),
rdr.last_pos,
- "unterminated character constant".to_owned());
+ "unterminated character constant".to_strbuf());
}
bump(rdr); // advance curr past token
return token::LIT_CHAR(c2);
while !rdr.curr_is('"') {
if is_eof(rdr) {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "unterminated double quote string".to_owned());
+ "unterminated double quote string".to_strbuf());
}
let ch = rdr.curr.unwrap();
'\\' => {
if is_eof(rdr) {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "unterminated double quote string".to_owned());
+ "unterminated double quote string".to_strbuf());
}
let escaped = rdr.curr.unwrap();
}
c2 => {
fatal_span_char(rdr, escaped_pos, rdr.last_pos,
- "unknown string escape".to_owned(), c2);
+ "unknown string escape".to_strbuf(), c2);
}
}
}
if is_eof(rdr) {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "unterminated raw string".to_owned());
+ "unterminated raw string".to_strbuf());
} else if !rdr.curr_is('"') {
fatal_span_char(rdr, start_bpos, rdr.last_pos,
"only `#` is allowed in raw string delimitation; \
- found illegal character".to_owned(),
+ found illegal character".to_strbuf(),
rdr.curr.unwrap());
}
bump(rdr);
'outer: loop {
if is_eof(rdr) {
fatal_span(rdr, start_bpos, rdr.last_pos,
- "unterminated raw string".to_owned());
+ "unterminated raw string".to_strbuf());
}
if rdr.curr_is('"') {
content_end_bpos = rdr.last_pos;
'%' => { return binop(rdr, token::PERCENT); }
c => {
fatal_span_char(rdr, rdr.last_pos, rdr.pos,
- "unknown start of token".to_owned(), c);
+ "unknown start of token".to_strbuf(), c);
}
}
}
// open a string reader for the given string
fn setup<'a>(span_handler: &'a diagnostic::SpanHandler,
- teststr: ~str) -> StringReader<'a> {
- let fm = span_handler.cm.new_filemap("zebra.rs".to_owned(), teststr);
+ teststr: StrBuf) -> StringReader<'a> {
+ let fm = span_handler.cm.new_filemap("zebra.rs".to_strbuf(), teststr);
new_string_reader(span_handler, fm)
}
let span_handler = mk_sh();
let mut string_reader = setup(&span_handler,
"/* my source file */ \
- fn main() { println!(\"zebra\"); }\n".to_owned());
+ fn main() { println!(\"zebra\"); }\n".to_strbuf());
let id = str_to_ident("fn");
let tok1 = string_reader.next_token();
let tok2 = TokenAndSpan{
}
#[test] fn doublecolonparsing () {
- check_tokenization(setup(&mk_sh(), "a b".to_owned()),
+ check_tokenization(setup(&mk_sh(), "a b".to_strbuf()),
vec!(mk_ident("a",false),
mk_ident("b",false)));
}
#[test] fn dcparsing_2 () {
- check_tokenization(setup(&mk_sh(), "a::b".to_owned()),
+ check_tokenization(setup(&mk_sh(), "a::b".to_strbuf()),
vec!(mk_ident("a",true),
token::MOD_SEP,
mk_ident("b",false)));
}
#[test] fn dcparsing_3 () {
- check_tokenization(setup(&mk_sh(), "a ::b".to_owned()),
+ check_tokenization(setup(&mk_sh(), "a ::b".to_strbuf()),
vec!(mk_ident("a",false),
token::MOD_SEP,
mk_ident("b",false)));
}
#[test] fn dcparsing_4 () {
- check_tokenization(setup(&mk_sh(), "a:: b".to_owned()),
+ check_tokenization(setup(&mk_sh(), "a:: b".to_strbuf()),
vec!(mk_ident("a",true),
token::MOD_SEP,
mk_ident("b",false)));
}
#[test] fn character_a() {
- assert_eq!(setup(&mk_sh(), "'a'".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(), "'a'".to_strbuf()).next_token().tok,
token::LIT_CHAR('a'));
}
#[test] fn character_space() {
- assert_eq!(setup(&mk_sh(), "' '".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(), "' '".to_strbuf()).next_token().tok,
token::LIT_CHAR(' '));
}
#[test] fn character_escaped() {
- assert_eq!(setup(&mk_sh(), "'\\n'".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(), "'\\n'".to_strbuf()).next_token().tok,
token::LIT_CHAR('\n'));
}
#[test] fn lifetime_name() {
- assert_eq!(setup(&mk_sh(), "'abc".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(), "'abc".to_strbuf()).next_token().tok,
token::LIFETIME(token::str_to_ident("abc")));
}
#[test] fn raw_string() {
- assert_eq!(setup(&mk_sh(), "r###\"\"#a\\b\x00c\"\"###".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(),
+ "r###\"\"#a\\b\x00c\"\"###".to_strbuf()).next_token()
+ .tok,
token::LIT_STR_RAW(token::str_to_ident("\"#a\\b\x00c\""), 3));
}
}
#[test] fn nested_block_comments() {
- assert_eq!(setup(&mk_sh(), "/* /* */ */'a'".to_owned()).next_token().tok,
+ assert_eq!(setup(&mk_sh(),
+ "/* /* */ */'a'".to_strbuf()).next_token().tok,
token::LIT_CHAR('a'));
}
inner
}
-pub fn parse_crate_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_crate_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> ast::Crate {
maybe_aborted(p.parse_crate_mod(),p)
}
-pub fn parse_crate_attrs_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_crate_attrs_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> Vec<ast::Attribute> {
inner
}
-pub fn parse_expr_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_expr_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> @ast::Expr {
maybe_aborted(p.parse_expr(), p)
}
-pub fn parse_item_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_item_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> Option<@ast::Item> {
maybe_aborted(p.parse_item(attrs),p)
}
-pub fn parse_meta_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_meta_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> @ast::MetaItem {
maybe_aborted(p.parse_meta_item(),p)
}
-pub fn parse_stmt_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_stmt_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
attrs: Vec<ast::Attribute> ,
sess: &ParseSess)
maybe_aborted(p.parse_stmt(attrs),p)
}
-pub fn parse_tts_from_source_str(name: ~str,
- source: ~str,
+pub fn parse_tts_from_source_str(name: StrBuf,
+ source: StrBuf,
cfg: ast::CrateConfig,
sess: &ParseSess)
-> Vec<ast::TokenTree> {
// Create a new parser from a source string
pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
cfg: ast::CrateConfig,
- name: ~str,
- source: ~str)
+ name: StrBuf,
+ source: StrBuf)
-> Parser<'a> {
filemap_to_parser(sess, string_to_filemap(sess, source, name), cfg)
}
};
match str::from_utf8(bytes.as_slice()) {
Some(s) => {
- return string_to_filemap(sess, s.to_owned(),
- path.as_str().unwrap().to_str())
+ return string_to_filemap(sess, s.to_strbuf(),
+ path.as_str().unwrap().to_strbuf())
}
None => err(format!("{} is not UTF-8 encoded", path.display())),
}
// given a session and a string, add the string to
// the session's codemap and return the new filemap
-pub fn string_to_filemap(sess: &ParseSess, source: ~str, path: ~str)
+pub fn string_to_filemap(sess: &ParseSess, source: StrBuf, path: StrBuf)
-> Rc<FileMap> {
sess.span_diagnostic.cm.new_filemap(path, source)
}
use util::parser_testing::{string_to_expr, string_to_item};
use util::parser_testing::string_to_stmt;
- fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> ~str {
+ fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> StrBuf {
let mut writer = MemWriter::new();
let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
let _ = val.encode(&mut encoder);
- str::from_utf8(writer.unwrap().as_slice()).unwrap().to_owned()
+ str::from_utf8(writer.unwrap().as_slice()).unwrap().to_strbuf()
}
// produce a codemap::span
}
#[test] fn path_exprs_1() {
- assert!(string_to_expr("a".to_owned()) ==
+ assert!(string_to_expr("a".to_strbuf()) ==
@ast::Expr{
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
}
#[test] fn path_exprs_2 () {
- assert!(string_to_expr("::a::b".to_owned()) ==
+ assert!(string_to_expr("::a::b".to_strbuf()) ==
@ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
#[should_fail]
#[test] fn bad_path_expr_1() {
- string_to_expr("::abc::def::return".to_owned());
+ string_to_expr("::abc::def::return".to_strbuf());
}
// check the token-tree-ization of macros
#[test] fn string_to_tts_macro () {
- let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_owned());
+ let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_strbuf());
let tts: &[ast::TokenTree] = tts.as_slice();
match tts {
[ast::TTTok(_,_),
}
#[test] fn string_to_tts_1 () {
- let tts = string_to_tts("fn a (b : int) { b; }".to_owned());
+ let tts = string_to_tts("fn a (b : int) { b; }".to_strbuf());
assert_eq!(to_json_str(&tts),
"[\
{\
]\
]\
}\
-]".to_owned()
+]".to_strbuf()
);
}
#[test] fn ret_expr() {
- assert!(string_to_expr("return d".to_owned()) ==
+ assert!(string_to_expr("return d".to_strbuf()) ==
@ast::Expr{
id: ast::DUMMY_NODE_ID,
node:ast::ExprRet(Some(@ast::Expr{
}
#[test] fn parse_stmt_1 () {
- assert!(string_to_stmt("b;".to_owned()) ==
+ assert!(string_to_stmt("b;".to_strbuf()) ==
@Spanned{
node: ast::StmtExpr(@ast::Expr {
id: ast::DUMMY_NODE_ID,
#[test] fn parse_ident_pat () {
let sess = new_parse_sess();
- let mut parser = string_to_parser(&sess, "b".to_owned());
+ let mut parser = string_to_parser(&sess, "b".to_strbuf());
assert!(parser.parse_pat() ==
@ast::Pat{id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
// check the contents of the tt manually:
#[test] fn parse_fundecl () {
// this test depends on the intern order of "fn" and "int"
- assert!(string_to_item("fn a (b : int) { b; }".to_owned()) ==
+ assert!(string_to_item("fn a (b : int) { b; }".to_strbuf()) ==
Some(
@ast::Item{ident:str_to_ident("a"),
attrs:Vec::new(),
#[test] fn parse_exprs () {
// just make sure that they parse....
- string_to_expr("3 + 4".to_owned());
- string_to_expr("a::z.froob(b,@(987+3))".to_owned());
+ string_to_expr("3 + 4".to_strbuf());
+ string_to_expr("a::z.froob(b,@(987+3))".to_strbuf());
}
#[test] fn attrs_fix_bug () {
string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
- -> Result<@Writer, ~str> {
+ -> Result<@Writer, StrBuf> {
#[cfg(windows)]
fn wb() -> c_int {
(O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
fn wb() -> c_int { O_WRONLY as c_int }
let mut fflags: c_int = wb();
-}".to_owned());
+}".to_strbuf());
}
}
),
ObsoleteManagedString => (
"managed string",
- "use `Rc<~str>` instead of a managed string"
+ "use `Rc<StrBuf>` instead of a managed string"
),
ObsoleteManagedVec => (
"managed vector",
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
-use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl};
+use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
use ast::{ExprVstoreUniq, Once, Many};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
impl<'a> Parser<'a> {
// convert a token to a string using self's reader
- pub fn token_to_str(token: &token::Token) -> ~str {
+ pub fn token_to_str(token: &token::Token) -> StrBuf {
token::to_str(token)
}
// convert the current token to a string using self's reader
- pub fn this_token_to_str(&mut self) -> ~str {
+ pub fn this_token_to_str(&mut self) -> StrBuf {
Parser::token_to_str(&self.token)
}
pub fn expect_one_of(&mut self,
edible: &[token::Token],
inedible: &[token::Token]) {
- fn tokens_to_str(tokens: &[token::Token]) -> ~str {
+ fn tokens_to_str(tokens: &[token::Token]) -> StrBuf {
let mut i = tokens.iter();
// This might be a sign we need a connect method on Iterator.
- let b = i.next().map_or("".to_owned(), |t| Parser::token_to_str(t));
- i.fold(b, |b,a| b + "`, `" + Parser::token_to_str(a))
+ let b = i.next()
+ .map_or("".to_strbuf(), |t| Parser::token_to_str(t));
+ i.fold(b, |b,a| {
+ let mut b = b;
+ b.push_str("`, `");
+ b.push_str(Parser::token_to_str(a).as_slice());
+ b
+ })
}
if edible.contains(&self.token) {
self.bump();
pub fn parse_ty_bare_fn(&mut self) -> Ty_ {
/*
- [extern "ABI"] [unsafe] fn <'lt> (S) -> T
- ^~~~^ ^~~~~~~^ ^~~~^ ^~^ ^
- | | | | |
- | | | | Return type
- | | | Argument types
- | | Lifetimes
- | |
- | Function Style
- ABI
-
+ [unsafe] [extern "ABI"] fn <'lt> (S) -> T
+ ^~~~^ ^~~~^ ^~~~^ ^~^ ^
+ | | | | |
+ | | | | Return type
+ | | | Argument types
+ | | Lifetimes
+ | ABI
+ Function Style
*/
+ let fn_style = self.parse_unsafety();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi().unwrap_or(abi::C)
} else {
abi::Rust
};
- let fn_style = self.parse_unsafety();
+ // NOTE: remove after a stage0 snapshot
+ let fn_style = match self.parse_unsafety() {
+ UnsafeFn => UnsafeFn,
+ NormalFn => fn_style,
+ };
+
self.expect_keyword(keywords::Fn);
let (decl, lifetimes) = self.parse_ty_fn_decl(true);
return TyBareFn(@BareFnTy {
self.expect_and();
self.parse_borrowed_pointee()
} else if self.is_keyword(keywords::Extern) ||
+ self.is_keyword(keywords::Unsafe) ||
self.token_is_bare_fn_keyword() {
// BARE FUNCTION
self.parse_ty_bare_fn()
(ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
}
- // parse a::B<~str,int>
+ // parse a::B<StrBuf,int>
fn parse_trait_ref(&mut self) -> TraitRef {
ast::TraitRef {
path: self.parse_path(LifetimeAndTypesWithoutColons).path,
}
}
- // parse B + C<~str,int> + D
+ // parse B + C<StrBuf,int> + D
fn parse_trait_ref_list(&mut self, ket: &token::Token) -> Vec<TraitRef> {
self.parse_seq_to_before_end(
ket,
// EXTERN FUNCTION ITEM
let abi = opt_abi.unwrap_or(abi::C);
let (ident, item_, extra_attrs) =
- self.parse_item_fn(ExternFn, abi);
+ self.parse_item_fn(NormalFn, abi);
let item = self.mk_item(lo,
self.last_span.hi,
ident,
&& self.look_ahead(1u, |t| *t != token::LBRACE) {
// UNSAFE FUNCTION ITEM
self.bump();
+ let abi = if self.eat_keyword(keywords::Extern) {
+ self.parse_opt_abi().unwrap_or(abi::C)
+ } else {
+ abi::Rust
+ };
self.expect_keyword(keywords::Fn);
let (ident, item_, extra_attrs) =
- self.parse_item_fn(UnsafeFn, abi::Rust);
+ self.parse_item_fn(UnsafeFn, abi);
let item = self.mk_item(lo,
self.last_span.hi,
ident,
use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cast;
use std::fmt;
-use std::local_data;
use std::path::BytesContainer;
use std::rc::Rc;
use std::strbuf::StrBuf;
}
}
-pub fn binop_to_str(o: BinOp) -> ~str {
+pub fn binop_to_str(o: BinOp) -> StrBuf {
match o {
- PLUS => "+".to_owned(),
- MINUS => "-".to_owned(),
- STAR => "*".to_owned(),
- SLASH => "/".to_owned(),
- PERCENT => "%".to_owned(),
- CARET => "^".to_owned(),
- AND => "&".to_owned(),
- OR => "|".to_owned(),
- SHL => "<<".to_owned(),
- SHR => ">>".to_owned()
+ PLUS => "+".to_strbuf(),
+ MINUS => "-".to_strbuf(),
+ STAR => "*".to_strbuf(),
+ SLASH => "/".to_strbuf(),
+ PERCENT => "%".to_strbuf(),
+ CARET => "^".to_strbuf(),
+ AND => "&".to_strbuf(),
+ OR => "|".to_strbuf(),
+ SHL => "<<".to_strbuf(),
+ SHR => ">>".to_strbuf()
}
}
-pub fn to_str(t: &Token) -> ~str {
+pub fn to_str(t: &Token) -> StrBuf {
match *t {
- EQ => "=".to_owned(),
- LT => "<".to_owned(),
- LE => "<=".to_owned(),
- EQEQ => "==".to_owned(),
- NE => "!=".to_owned(),
- GE => ">=".to_owned(),
- GT => ">".to_owned(),
- NOT => "!".to_owned(),
- TILDE => "~".to_owned(),
- OROR => "||".to_owned(),
- ANDAND => "&&".to_owned(),
+ EQ => "=".to_strbuf(),
+ LT => "<".to_strbuf(),
+ LE => "<=".to_strbuf(),
+ EQEQ => "==".to_strbuf(),
+ NE => "!=".to_strbuf(),
+ GE => ">=".to_strbuf(),
+ GT => ">".to_strbuf(),
+ NOT => "!".to_strbuf(),
+ TILDE => "~".to_strbuf(),
+ OROR => "||".to_strbuf(),
+ ANDAND => "&&".to_strbuf(),
BINOP(op) => binop_to_str(op),
- BINOPEQ(op) => binop_to_str(op) + "=",
+ BINOPEQ(op) => {
+ let mut s = binop_to_str(op);
+ s.push_str("=");
+ s
+ }
/* Structural symbols */
- AT => "@".to_owned(),
- DOT => ".".to_owned(),
- DOTDOT => "..".to_owned(),
- DOTDOTDOT => "...".to_owned(),
- COMMA => ",".to_owned(),
- SEMI => ";".to_owned(),
- COLON => ":".to_owned(),
- MOD_SEP => "::".to_owned(),
- RARROW => "->".to_owned(),
- LARROW => "<-".to_owned(),
- DARROW => "<->".to_owned(),
- FAT_ARROW => "=>".to_owned(),
- LPAREN => "(".to_owned(),
- RPAREN => ")".to_owned(),
- LBRACKET => "[".to_owned(),
- RBRACKET => "]".to_owned(),
- LBRACE => "{".to_owned(),
- RBRACE => "}".to_owned(),
- POUND => "#".to_owned(),
- DOLLAR => "$".to_owned(),
+ AT => "@".to_strbuf(),
+ DOT => ".".to_strbuf(),
+ DOTDOT => "..".to_strbuf(),
+ DOTDOTDOT => "...".to_strbuf(),
+ COMMA => ",".to_strbuf(),
+ SEMI => ";".to_strbuf(),
+ COLON => ":".to_strbuf(),
+ MOD_SEP => "::".to_strbuf(),
+ RARROW => "->".to_strbuf(),
+ LARROW => "<-".to_strbuf(),
+ DARROW => "<->".to_strbuf(),
+ FAT_ARROW => "=>".to_strbuf(),
+ LPAREN => "(".to_strbuf(),
+ RPAREN => ")".to_strbuf(),
+ LBRACKET => "[".to_strbuf(),
+ RBRACKET => "]".to_strbuf(),
+ LBRACE => "{".to_strbuf(),
+ RBRACE => "}".to_strbuf(),
+ POUND => "#".to_strbuf(),
+ DOLLAR => "$".to_strbuf(),
/* Literals */
LIT_CHAR(c) => {
res.push_char(c);
});
res.push_char('\'');
- res.into_owned()
+ res
}
LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
- LIT_INT_UNSUFFIXED(i) => { i.to_str() }
+ LIT_INT_UNSUFFIXED(i) => { i.to_str().to_strbuf() }
LIT_FLOAT(s, t) => {
let mut body = StrBuf::from_str(get_ident(s).get());
if body.as_slice().ends_with(".") {
body.push_char('0'); // `10.f` is not a float literal
}
- body.push_str(ast_util::float_ty_to_str(t));
- body.into_owned()
+ body.push_str(ast_util::float_ty_to_str(t).as_slice());
+ body
}
LIT_FLOAT_UNSUFFIXED(s) => {
let mut body = StrBuf::from_str(get_ident(s).get());
if body.as_slice().ends_with(".") {
body.push_char('0'); // `10.f` is not a float literal
}
- body.into_owned()
+ body
}
LIT_STR(s) => {
- format!("\"{}\"", get_ident(s).get().escape_default())
+ (format!("\"{}\"", get_ident(s).get().escape_default())).to_strbuf()
}
LIT_STR_RAW(s, n) => {
- format!("r{delim}\"{string}\"{delim}",
- delim="#".repeat(n), string=get_ident(s))
+ (format!("r{delim}\"{string}\"{delim}",
+ delim="#".repeat(n), string=get_ident(s))).to_strbuf()
}
/* Name components */
- IDENT(s, _) => get_ident(s).get().to_str(),
+ IDENT(s, _) => get_ident(s).get().to_strbuf(),
LIFETIME(s) => {
- format!("'{}", get_ident(s))
+ (format!("'{}", get_ident(s))).to_strbuf()
}
- UNDERSCORE => "_".to_owned(),
+ UNDERSCORE => "_".to_strbuf(),
/* Other */
- DOC_COMMENT(s) => get_ident(s).get().to_str(),
- EOF => "<eof>".to_owned(),
+ DOC_COMMENT(s) => get_ident(s).get().to_strbuf(),
+ EOF => "<eof>".to_strbuf(),
INTERPOLATED(ref nt) => {
match nt {
&NtExpr(e) => ::print::pprust::expr_to_str(e),
&NtMeta(e) => ::print::pprust::meta_item_to_str(e),
_ => {
- "an interpolated ".to_owned() +
- match *nt {
- NtItem(..) => "item".to_owned(),
- NtBlock(..) => "block".to_owned(),
- NtStmt(..) => "statement".to_owned(),
- NtPat(..) => "pattern".to_owned(),
- NtMeta(..) => fail!("should have been handled"),
- NtExpr(..) => fail!("should have been handled above"),
- NtTy(..) => "type".to_owned(),
- NtIdent(..) => "identifier".to_owned(),
- NtPath(..) => "path".to_owned(),
- NtTT(..) => "tt".to_owned(),
- NtMatchers(..) => "matcher sequence".to_owned()
- }
+ let mut s = "an interpolated ".to_strbuf();
+ match *nt {
+ NtItem(..) => s.push_str("item"),
+ NtBlock(..) => s.push_str("block"),
+ NtStmt(..) => s.push_str("statement"),
+ NtPat(..) => s.push_str("pattern"),
+ NtMeta(..) => fail!("should have been handled"),
+ NtExpr(..) => fail!("should have been handled above"),
+ NtTy(..) => s.push_str("type"),
+ NtIdent(..) => s.push_str("identifier"),
+ NtPath(..) => s.push_str("path"),
+ NtTT(..) => s.push_str("tt"),
+ NtMatchers(..) => s.push_str("matcher sequence")
+ };
+ s
}
}
}
// FIXME(eddyb) #8726 This should probably use a task-local reference.
pub fn get_ident_interner() -> Rc<IdentInterner> {
local_data_key!(key: Rc<::parse::token::IdentInterner>)
- match local_data::get(key, |k| k.map(|k| k.clone())) {
- Some(interner) => interner,
+ match key.get() {
+ Some(interner) => interner.clone(),
None => {
let interner = Rc::new(mk_fresh_ident_interner());
- local_data::set(key, interner.clone());
+ key.replace(Some(interner.clone()));
interner
}
}
#[deriving(Clone)]
pub enum Token {
- String(~str, int),
+ String(StrBuf, int),
Break(BreakToken),
Begin(BeginToken),
End,
}
}
-pub fn tok_str(t: Token) -> ~str {
+pub fn tok_str(t: Token) -> StrBuf {
match t {
- String(s, len) => return format!("STR({},{})", s, len),
- Break(_) => return "BREAK".to_owned(),
- Begin(_) => return "BEGIN".to_owned(),
- End => return "END".to_owned(),
- Eof => return "EOF".to_owned()
+ String(s, len) => return format!("STR({},{})", s, len).to_strbuf(),
+ Break(_) => return "BREAK".to_strbuf(),
+ Begin(_) => return "BEGIN".to_strbuf(),
+ End => return "END".to_strbuf(),
+ Eof => return "EOF".to_strbuf()
}
}
left: uint,
right: uint,
lim: uint)
- -> ~str {
+ -> StrBuf {
let n = toks.len();
assert_eq!(n, szs.len());
let mut i = left;
i %= n;
}
s.push_char(']');
- return s.into_owned();
+ return s.into_strbuf();
}
pub enum PrintStackBreak {
assert_eq!(l, len);
// assert!(l <= space);
self.space -= len;
- self.print_str(s)
+ self.print_str(s.as_slice())
}
Eof => {
// Eof should never get here.
pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) }
pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
- p.pretty_print(String(/* bad */ wrd.to_str(), wrd.len() as int))
+ p.pretty_print(String(/* bad */ wrd.to_strbuf(), wrd.len() as int))
}
pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
- p.pretty_print(String(/* bad */ wrd.to_str(), SIZE_INFINITY))
+ p.pretty_print(String(/* bad */ wrd.to_strbuf(), SIZE_INFINITY))
}
pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
- p.pretty_print(String(/* bad */ wrd.to_str(), 0))
+ p.pretty_print(String(/* bad */ wrd.to_strbuf(), 0))
}
pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
pub fn print_crate<'a>(cm: &'a CodeMap,
span_diagnostic: &diagnostic::SpanHandler,
krate: &ast::Crate,
- filename: ~str,
+ filename: StrBuf,
input: &mut io::Reader,
out: Box<io::Writer>,
ann: &'a PpAnn,
eof(&mut s.s)
}
-pub fn to_str(f: |&mut State| -> IoResult<()>) -> ~str {
+pub fn to_str(f: |&mut State| -> IoResult<()>) -> StrBuf {
let mut s = rust_printer(box MemWriter::new());
f(&mut s).unwrap();
eof(&mut s.s).unwrap();
let (_, wr): (uint, Box<MemWriter>) = cast::transmute_copy(&s.s.out);
let result = str::from_utf8_owned(wr.get_ref().to_owned()).unwrap();
cast::forget(wr);
- result
+ result.to_strbuf()
}
}
-pub fn ty_to_str(ty: &ast::Ty) -> ~str {
+pub fn ty_to_str(ty: &ast::Ty) -> StrBuf {
to_str(|s| s.print_type(ty))
}
-pub fn pat_to_str(pat: &ast::Pat) -> ~str {
+pub fn pat_to_str(pat: &ast::Pat) -> StrBuf {
to_str(|s| s.print_pat(pat))
}
-pub fn expr_to_str(e: &ast::Expr) -> ~str {
+pub fn expr_to_str(e: &ast::Expr) -> StrBuf {
to_str(|s| s.print_expr(e))
}
-pub fn lifetime_to_str(e: &ast::Lifetime) -> ~str {
+pub fn lifetime_to_str(e: &ast::Lifetime) -> StrBuf {
to_str(|s| s.print_lifetime(e))
}
-pub fn tt_to_str(tt: &ast::TokenTree) -> ~str {
+pub fn tt_to_str(tt: &ast::TokenTree) -> StrBuf {
to_str(|s| s.print_tt(tt))
}
-pub fn tts_to_str(tts: &[ast::TokenTree]) -> ~str {
+pub fn tts_to_str(tts: &[ast::TokenTree]) -> StrBuf {
to_str(|s| s.print_tts(&tts))
}
-pub fn stmt_to_str(stmt: &ast::Stmt) -> ~str {
+pub fn stmt_to_str(stmt: &ast::Stmt) -> StrBuf {
to_str(|s| s.print_stmt(stmt))
}
-pub fn item_to_str(i: &ast::Item) -> ~str {
+pub fn item_to_str(i: &ast::Item) -> StrBuf {
to_str(|s| s.print_item(i))
}
-pub fn generics_to_str(generics: &ast::Generics) -> ~str {
+pub fn generics_to_str(generics: &ast::Generics) -> StrBuf {
to_str(|s| s.print_generics(generics))
}
-pub fn ty_method_to_str(p: &ast::TypeMethod) -> ~str {
+pub fn ty_method_to_str(p: &ast::TypeMethod) -> StrBuf {
to_str(|s| s.print_ty_method(p))
}
-pub fn method_to_str(p: &ast::Method) -> ~str {
+pub fn method_to_str(p: &ast::Method) -> StrBuf {
to_str(|s| s.print_method(p))
}
-pub fn fn_block_to_str(p: &ast::FnDecl) -> ~str {
+pub fn fn_block_to_str(p: &ast::FnDecl) -> StrBuf {
to_str(|s| s.print_fn_block_args(p))
}
-pub fn path_to_str(p: &ast::Path) -> ~str {
+pub fn path_to_str(p: &ast::Path) -> StrBuf {
to_str(|s| s.print_path(p, false))
}
pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
opt_explicit_self: Option<ast::ExplicitSelf_>,
- generics: &ast::Generics) -> ~str {
+ generics: &ast::Generics) -> StrBuf {
to_str(|s| {
try!(s.print_fn(decl, Some(fn_style), abi::Rust,
name, generics, opt_explicit_self, ast::Inherited));
})
}
-pub fn block_to_str(blk: &ast::Block) -> ~str {
+pub fn block_to_str(blk: &ast::Block) -> StrBuf {
to_str(|s| {
// containing cbox, will be closed by print-block at }
try!(s.cbox(indent_unit));
})
}
-pub fn meta_item_to_str(mi: &ast::MetaItem) -> ~str {
+pub fn meta_item_to_str(mi: &ast::MetaItem) -> StrBuf {
to_str(|s| s.print_meta_item(mi))
}
-pub fn attribute_to_str(attr: &ast::Attribute) -> ~str {
+pub fn attribute_to_str(attr: &ast::Attribute) -> StrBuf {
to_str(|s| s.print_attribute(attr))
}
-pub fn lit_to_str(l: &ast::Lit) -> ~str {
+pub fn lit_to_str(l: &ast::Lit) -> StrBuf {
to_str(|s| s.print_literal(l))
}
-pub fn explicit_self_to_str(explicit_self: ast::ExplicitSelf_) -> ~str {
+pub fn explicit_self_to_str(explicit_self: ast::ExplicitSelf_) -> StrBuf {
to_str(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
}
-pub fn variant_to_str(var: &ast::Variant) -> ~str {
+pub fn variant_to_str(var: &ast::Variant) -> StrBuf {
to_str(|s| s.print_variant(var))
}
-pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> ~str {
+pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> StrBuf {
match vis {
- ast::Public => format!("pub {}", s),
- ast::Inherited => s.to_owned()
+ ast::Public => format!("pub {}", s).to_strbuf(),
+ ast::Inherited => s.to_strbuf()
}
}
// Synthesizes a comment that was not textually present in the original source
// file.
- pub fn synth_comment(&mut self, text: ~str) -> IoResult<()> {
+ pub fn synth_comment(&mut self, text: StrBuf) -> IoResult<()> {
try!(word(&mut self.s, "/*"));
try!(space(&mut self.s));
- try!(word(&mut self.s, text));
+ try!(word(&mut self.s, text.as_slice()));
try!(space(&mut self.s));
word(&mut self.s, "*/")
}
self.end() // end the outer fn box
}
ast::ForeignItemStatic(t, m) => {
- try!(self.head(visibility_qualified(item.vis, "static")));
+ try!(self.head(visibility_qualified(item.vis,
+ "static").as_slice()));
if m {
try!(self.word_space("mut"));
}
try!(self.ann.pre(self, NodeItem(item)));
match item.node {
ast::ItemStatic(ty, m, expr) => {
- try!(self.head(visibility_qualified(item.vis, "static")));
+ try!(self.head(visibility_qualified(item.vis,
+ "static").as_slice()));
if m == ast::MutMutable {
try!(self.word_space("mut"));
}
try!(self.print_block_with_attrs(body, item.attrs.as_slice()));
}
ast::ItemMod(ref _mod) => {
- try!(self.head(visibility_qualified(item.vis, "mod")));
+ try!(self.head(visibility_qualified(item.vis,
+ "mod").as_slice()));
try!(self.print_ident(item.ident));
try!(self.nbsp());
try!(self.bopen());
ast::ItemTy(ty, ref params) => {
try!(self.ibox(indent_unit));
try!(self.ibox(0u));
- try!(self.word_nbsp(visibility_qualified(item.vis, "type")));
+ try!(self.word_nbsp(visibility_qualified(item.vis,
+ "type").as_slice()));
try!(self.print_ident(item.ident));
try!(self.print_generics(params));
try!(self.end()); // end the inner ibox
if struct_def.is_virtual {
try!(self.word_space("virtual"));
}
- try!(self.head(visibility_qualified(item.vis, "struct")));
+ try!(self.head(visibility_qualified(item.vis,
+ "struct").as_slice()));
try!(self.print_struct(struct_def, generics, item.ident, item.span));
}
ast::ItemImpl(ref generics, ref opt_trait, ty, ref methods) => {
- try!(self.head(visibility_qualified(item.vis, "impl")));
+ try!(self.head(visibility_qualified(item.vis,
+ "impl").as_slice()));
if generics.is_parameterized() {
try!(self.print_generics(generics));
try!(space(&mut self.s));
try!(self.bclose(item.span));
}
ast::ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
- try!(self.head(visibility_qualified(item.vis, "trait")));
+ try!(self.head(visibility_qualified(item.vis,
+ "trait").as_slice()));
try!(self.print_ident(item.ident));
try!(self.print_generics(generics));
if *sized == ast::DynSize {
generics: &ast::Generics, ident: ast::Ident,
span: codemap::Span,
visibility: ast::Visibility) -> IoResult<()> {
- try!(self.head(visibility_qualified(visibility, "enum")));
+ try!(self.head(visibility_qualified(visibility, "enum").as_slice()));
try!(self.print_ident(ident));
try!(self.print_generics(generics));
try!(space(&mut self.s));
match *tt {
ast::TTDelim(ref tts) => self.print_tts(&(tts.as_slice())),
ast::TTTok(_, ref tk) => {
- word(&mut self.s, parse::token::to_str(tk))
+ word(&mut self.s, parse::token::to_str(tk).as_slice())
}
ast::TTSeq(_, ref tts, ref sep, zerok) => {
try!(word(&mut self.s, "$("));
try!(word(&mut self.s, ")"));
match *sep {
Some(ref tk) => {
- try!(word(&mut self.s, parse::token::to_str(tk)));
+ try!(word(&mut self.s,
+ parse::token::to_str(tk).as_slice()));
}
None => ()
}
try!(self.maybe_print_comment(lit.span.lo));
match self.next_lit(lit.span.lo) {
Some(ref ltrl) => {
- return word(&mut self.s, (*ltrl).lit);
+ return word(&mut self.s, (*ltrl).lit.as_slice());
}
_ => ()
}
word(&mut self.s, res.into_owned())
}
ast::LitInt(i, t) => {
- word(&mut self.s, ast_util::int_ty_to_str(t, Some(i)))
+ word(&mut self.s,
+ ast_util::int_ty_to_str(t, Some(i)).as_slice())
}
ast::LitUint(u, t) => {
- word(&mut self.s, ast_util::uint_ty_to_str(t, Some(u)))
+ word(&mut self.s,
+ ast_util::uint_ty_to_str(t, Some(u)).as_slice())
}
ast::LitIntUnsuffixed(i) => {
word(&mut self.s, format!("{}", i))
}
ast::LitFloat(ref f, t) => {
- word(&mut self.s, f.get() + ast_util::float_ty_to_str(t))
+ word(&mut self.s,
+ f.get() + ast_util::float_ty_to_str(t).as_slice())
}
ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()),
ast::LitNil => word(&mut self.s, "()"),
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1u);
try!(zerobreak(&mut self.s));
- try!(word(&mut self.s, *cmnt.lines.get(0)));
+ try!(word(&mut self.s, cmnt.lines.get(0).as_slice()));
zerobreak(&mut self.s)
}
comments::Isolated => {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
- try!(word(&mut self.s, *line));
+ try!(word(&mut self.s, line.as_slice()));
}
try!(hardbreak(&mut self.s));
}
comments::Trailing => {
try!(word(&mut self.s, " "));
if cmnt.lines.len() == 1u {
- try!(word(&mut self.s, *cmnt.lines.get(0)));
+ try!(word(&mut self.s, cmnt.lines.get(0).as_slice()));
hardbreak(&mut self.s)
} else {
try!(self.ibox(0u));
for line in cmnt.lines.iter() {
if !line.is_empty() {
- try!(word(&mut self.s, *line));
+ try!(word(&mut self.s, line.as_slice()));
}
try!(hardbreak(&mut self.s));
}
comments::BlankLine => {
// We need to do at least one, possibly two hardbreaks.
let is_semi = match self.s.last_token() {
- pp::String(s, _) => ";" == s,
+ pp::String(s, _) => ";" == s.as_slice(),
_ => false
};
if is_semi || self.is_begin() || self.is_end() {
opt_fn_style: Option<ast::FnStyle>,
abi: abi::Abi,
vis: ast::Visibility) -> IoResult<()> {
- try!(word(&mut self.s, visibility_qualified(vis, "")));
+ try!(word(&mut self.s, visibility_qualified(vis, "").as_slice()));
+ try!(self.print_opt_fn_style(opt_fn_style));
if abi != abi::Rust {
try!(self.word_nbsp("extern"));
try!(self.word_nbsp(abi.to_str()));
-
- if opt_fn_style != Some(ast::ExternFn) {
- try!(self.print_opt_fn_style(opt_fn_style));
- }
- } else {
- try!(self.print_opt_fn_style(opt_fn_style));
}
word(&mut self.s, "fn")
match s {
ast::NormalFn => Ok(()),
ast::UnsafeFn => self.word_nbsp("unsafe"),
- ast::ExternFn => self.word_nbsp("extern")
}
}
let generics = ast_util::empty_generics();
assert_eq!(&fun_to_str(&decl, ast::NormalFn, abba_ident,
None, &generics),
- &"fn abba()".to_owned());
+ &"fn abba()".to_strbuf());
}
#[test]
});
let varstr = variant_to_str(&var);
- assert_eq!(&varstr,&"pub principal_skinner".to_owned());
+ assert_eq!(&varstr,&"pub principal_skinner".to_strbuf());
}
}
#[deriving(Clone, Eq, Hash, Ord)]
pub struct RcStr {
- string: Rc<~str>,
+ string: Rc<StrBuf>,
}
impl TotalEq for RcStr {}
impl Str for RcStr {
#[inline]
fn as_slice<'a>(&'a self) -> &'a str {
- let s: &'a str = *self.string;
+ let s: &'a str = self.string.as_slice();
s
}
}
impl RcStr {
pub fn new(string: &str) -> RcStr {
RcStr {
- string: Rc::new(string.to_owned()),
+ string: Rc::new(string.to_strbuf()),
}
}
}
use parse::token;
// map a string to tts, using a made-up filename:
-pub fn string_to_tts(source_str: ~str) -> Vec<ast::TokenTree> {
+pub fn string_to_tts(source_str: StrBuf) -> Vec<ast::TokenTree> {
let ps = new_parse_sess();
- filemap_to_tts(&ps, string_to_filemap(&ps, source_str,"bogofile".to_owned()))
+ filemap_to_tts(&ps,
+ string_to_filemap(&ps, source_str, "bogofile".to_strbuf()))
}
// map string to parser (via tts)
-pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: ~str) -> Parser<'a> {
- new_parser_from_source_str(ps, Vec::new(), "bogofile".to_owned(), source_str)
+pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: StrBuf) -> Parser<'a> {
+ new_parser_from_source_str(ps,
+ Vec::new(),
+ "bogofile".to_strbuf(),
+ source_str)
}
-fn with_error_checking_parse<T>(s: ~str, f: |&mut Parser| -> T) -> T {
+fn with_error_checking_parse<T>(s: StrBuf, f: |&mut Parser| -> T) -> T {
let ps = new_parse_sess();
let mut p = string_to_parser(&ps, s);
let x = f(&mut p);
}
// parse a string, return a crate.
-pub fn string_to_crate (source_str : ~str) -> ast::Crate {
+pub fn string_to_crate (source_str : StrBuf) -> ast::Crate {
with_error_checking_parse(source_str, |p| {
p.parse_crate_mod()
})
}
// parse a string, return an expr
-pub fn string_to_expr (source_str : ~str) -> @ast::Expr {
+pub fn string_to_expr (source_str : StrBuf) -> @ast::Expr {
with_error_checking_parse(source_str, |p| {
p.parse_expr()
})
}
// parse a string, return an item
-pub fn string_to_item (source_str : ~str) -> Option<@ast::Item> {
+pub fn string_to_item (source_str : StrBuf) -> Option<@ast::Item> {
with_error_checking_parse(source_str, |p| {
p.parse_item(Vec::new())
})
}
// parse a string, return a stmt
-pub fn string_to_stmt(source_str : ~str) -> @ast::Stmt {
+pub fn string_to_stmt(source_str : StrBuf) -> @ast::Stmt {
with_error_checking_parse(source_str, |p| {
p.parse_stmt(Vec::new())
})
// parse a string, return a pat. Uses "irrefutable"... which doesn't
// (currently) affect parsing.
-pub fn string_to_pat(source_str: ~str) -> @ast::Pat {
+pub fn string_to_pat(source_str: StrBuf) -> @ast::Pat {
string_to_parser(&new_parse_sess(), source_str).parse_pat()
}
--- /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.
+
+enum Foo {
+ Bar(int)
+}
+
+pub mod test {
+ enum Foo {
+ Bar(int)
+ }
+}
extern crate syntax;
use std::any::Any;
-use std::local_data;
use syntax::ast::Name;
use syntax::ext::base::SyntaxExtension;
#[macro_registrar]
pub fn registrar(_: |Name, SyntaxExtension|) {
local_data_key!(foo: Box<Any:Send>);
- local_data::set(foo, box Foo { foo: 10 } as Box<Any:Send>);
+ foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
}
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n_keys = {
if args.len() == 2 {
from_str::<uint>(args[1]).unwrap()
fn main() {
let args = os::args();
+ let args = args.as_slice();
let num_keys = {
if args.len() == 2 {
from_str::<uint>(args[1]).unwrap()
use std::io::File;
macro_rules! bench (
- ($argv:expr, $id:ident) => (maybe_run_test($argv, stringify!($id).to_owned(), $id))
+ ($argv:expr, $id:ident) => (maybe_run_test($argv.as_slice(), stringify!($id).to_owned(), $id))
)
fn main() {
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n = if args.len() == 3 {
from_str::<uint>(args[1]).unwrap()
} else {
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n = if args.len() == 2 {
from_str::<uint>(args[1]).unwrap()
} else {
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n = if args.len() == 2 {
from_str::<uint>(args[1]).unwrap()
} else {
fn main() {
let args = std::os::args();
+ let args = args.as_slice();
let n = if std::os::getenv("RUST_BENCH").is_some() {
17
} else if args.len() <= 1u {
let nn = if std::os::getenv("RUST_BENCH").is_some() {
200000
} else {
- std::os::args().get(1).and_then(|arg| from_str(*arg)).unwrap_or(600)
+ std::os::args().as_slice().get(1).and_then(|arg| from_str(*arg)).unwrap_or(600)
};
print_complements();
}
fn main() {
- let n = std::os::args().get(1).and_then(|arg| from_str(*arg)).unwrap_or(2u);
+ let n = std::os::args().as_slice().get(1).and_then(|arg| from_str(*arg)).unwrap_or(2u);
let (tx, rx) = channel();
for i in range(0, n) {
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n = if args.len() > 1 {
from_str::<uint>(args[1]).unwrap()
} else {
fn run<W: Writer>(writer: &mut W) {
let args = os::args();
+ let args = args.as_slice();
let n = if os::getenv("RUST_BENCH").is_some() {
25000000
} else if args.len() <= 1u {
// given a map, search for the frequency of a pattern
fn find(mm: &HashMap<Vec<u8> , uint>, key: ~str) -> uint {
- let key = key.into_ascii().to_lower().into_str();
+ let key = key.into_ascii().as_slice().to_lower().into_str();
match mm.find_equiv(&key.as_bytes()) {
option::None => { return 0u; }
option::Some(&num) => { return num; }
fn main() {
let args = std::os::args();
+ let args = args.as_slice();
let res = if args.len() < 2 {
println!("Test mode: do not dump the image because it's not utf8, \
which interferes with the test runner.");
}
}
}
- std::str::from_utf8_owned(sol.move_iter().collect()).unwrap()
+ std::str::from_utf8(sol.as_slice()).unwrap().to_owned()
}
// Prints a solution in ~str form.
fn main () {
let args = std::os::args();
+ let args = args.as_slice();
let stop_after = if args.len() <= 1 {
2098
} else {
fn main() {
let args = std::os::args();
+ let args = args.as_slice();
let n = if args.len() < 2 {
512
} else {
fn main() {
let args = os::args();
+ let args = args.as_slice();
let n = if os::getenv("RUST_BENCH").is_some() {
5500
} else if args.len() < 2 {
fn main() {
let args = std::os::args();
+ let args = args.as_slice();
let token = if std::os::getenv("RUST_BENCH").is_some() {
2000000
} else {
// Testing that we can't store a reference it task-local storage
-use std::local_data;
-
local_data_key!(key: @&int)
//~^ ERROR missing lifetime specifier
--- /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 file must never have a trailing newline
+
+fn main() {
+ let x = Some(3);
+ let y = x.as_ref().unwrap_or(&5); //~ ERROR: borrowed value does not live long enough
+}
\ No newline at end of file
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-11680.rs
+
+extern crate other = "issue-11680";
+
+fn main() {
+ let _b = other::Bar(1);
+ //~^ ERROR: variant `Bar` is private
+
+ let _b = other::test::Bar(1);
+ //~^ ERROR: variant `Bar` is private
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::local_data;
-
// check that the local data keys are private by default.
mod bar {
}
fn main() {
- local_data::set(bar::baz, -10.0);
+ bar::baz.replace(Some(-10.0));
//~^ ERROR static `baz` is private
}
fn test2() {
let x: Foo<_> = Bar::<uint>;
//~^ ERROR mismatched types: expected `Foo<<generic #0>>` but found `Bar<uint>`
- //~^^ ERROR cannot determine a type for this local variable: unconstrained type
}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:whatis 'basic-types-globals-metadata::B'
-// check:type = bool
-// debugger:whatis 'basic-types-globals-metadata::I'
-// check:type = int
-// debugger:whatis 'basic-types-globals-metadata::C'
-// check:type = char
-// debugger:whatis 'basic-types-globals-metadata::I8'
-// check:type = i8
-// debugger:whatis 'basic-types-globals-metadata::I16'
-// check:type = i16
-// debugger:whatis 'basic-types-globals-metadata::I32'
-// check:type = i32
-// debugger:whatis 'basic-types-globals-metadata::I64'
-// check:type = i64
-// debugger:whatis 'basic-types-globals-metadata::U'
-// check:type = uint
-// debugger:whatis 'basic-types-globals-metadata::U8'
-// check:type = u8
-// debugger:whatis 'basic-types-globals-metadata::U16'
-// check:type = u16
-// debugger:whatis 'basic-types-globals-metadata::U32'
-// check:type = u32
-// debugger:whatis 'basic-types-globals-metadata::U64'
-// check:type = u64
-// debugger:whatis 'basic-types-globals-metadata::F32'
-// check:type = f32
-// debugger:whatis 'basic-types-globals-metadata::F64'
-// check:type = f64
-// debugger:continue
-
-#![allow(unused_variable)]
-#![allow(dead_code)]
-
-
-static B: bool = false;
-static I: int = -1;
-static C: char = 'a';
-static I8: i8 = 68;
-static I16: i16 = -16;
-static I32: i32 = -32;
-static I64: i64 = -64;
-static U: uint = 1;
-static U8: u8 = 100;
-static U16: u16 = 16;
-static U32: u32 = 32;
-static U64: u64 = 64;
-static F32: f32 = 2.5;
-static F64: f64 = 3.5;
-
-fn main() {
- _zzz();
-
- let a = (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64);
-}
-
-fn _zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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.
-
-// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
-// as its numerical value along with its associated ASCII char, there
-// doesn't seem to be any way around this. Also, gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print 'basic-types-globals::B'
-// check:$1 = false
-// debugger:print 'basic-types-globals::I'
-// check:$2 = -1
-// debugger:print 'basic-types-globals::C'
-// check:$3 = 97
-// debugger:print/d 'basic-types-globals::I8'
-// check:$4 = 68
-// debugger:print 'basic-types-globals::I16'
-// check:$5 = -16
-// debugger:print 'basic-types-globals::I32'
-// check:$6 = -32
-// debugger:print 'basic-types-globals::I64'
-// check:$7 = -64
-// debugger:print 'basic-types-globals::U'
-// check:$8 = 1
-// debugger:print/d 'basic-types-globals::U8'
-// check:$9 = 100
-// debugger:print 'basic-types-globals::U16'
-// check:$10 = 16
-// debugger:print 'basic-types-globals::U32'
-// check:$11 = 32
-// debugger:print 'basic-types-globals::U64'
-// check:$12 = 64
-// debugger:print 'basic-types-globals::F32'
-// check:$13 = 2.5
-// debugger:print 'basic-types-globals::F64'
-// check:$14 = 3.5
-// debugger:continue
-
-#![allow(unused_variable)]
-
-static B: bool = false;
-static I: int = -1;
-static C: char = 'a';
-static I8: i8 = 68;
-static I16: i16 = -16;
-static I32: i32 = -32;
-static I64: i64 = -64;
-static U: uint = 1;
-static U8: u8 = 100;
-static U16: u16 = 16;
-static U32: u32 = 32;
-static U64: u64 = 64;
-static F32: f32 = 2.5;
-static F64: f64 = 3.5;
-
-fn main() {
- _zzz();
-
- let a = (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64);
-}
-
-fn _zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:whatis unit
-// check:type = ()
-// debugger:whatis b
-// check:type = bool
-// debugger:whatis i
-// check:type = int
-// debugger:whatis c
-// check:type = char
-// debugger:whatis i8
-// check:type = i8
-// debugger:whatis i16
-// check:type = i16
-// debugger:whatis i32
-// check:type = i32
-// debugger:whatis i64
-// check:type = i64
-// debugger:whatis u
-// check:type = uint
-// debugger:whatis u8
-// check:type = u8
-// debugger:whatis u16
-// check:type = u16
-// debugger:whatis u32
-// check:type = u32
-// debugger:whatis u64
-// check:type = u64
-// debugger:whatis f32
-// check:type = f32
-// debugger:whatis f64
-// check:type = f64
-// debugger:info functions _yyy
-// check:[...]![...]_yyy([...])([...]);
-// debugger:continue
-
-#![allow(unused_variable)]
-
-fn main() {
- let unit: () = ();
- let b: bool = false;
- let i: int = -1;
- let c: char = 'a';
- let i8: i8 = 68;
- let i16: i16 = -16;
- let i32: i32 = -32;
- let i64: i64 = -64;
- let u: uint = 1;
- let u8: u8 = 100;
- let u16: u16 = 16;
- let u32: u32 = 32;
- let u64: u64 = 64;
- let f32: f32 = 2.5;
- let f64: f64 = 3.5;
- _zzz();
- if 1 == 1 { _yyy(); }
-}
-
-fn _zzz() {()}
-fn _yyy() -> ! {fail!()}
+++ /dev/null
-// 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.
-//
-// 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.
-
-// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
-// as its numerical value along with its associated ASCII char, there
-// doesn't seem to be any way around this. Also, gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// Check initializers
-// debugger:print 'basic-types-mut-globals::B'
-// check:$1 = false
-// debugger:print 'basic-types-mut-globals::I'
-// check:$2 = -1
-// debugger:print 'basic-types-mut-globals::C'
-// check:$3 = 97
-// debugger:print/d 'basic-types-mut-globals::I8'
-// check:$4 = 68
-// debugger:print 'basic-types-mut-globals::I16'
-// check:$5 = -16
-// debugger:print 'basic-types-mut-globals::I32'
-// check:$6 = -32
-// debugger:print 'basic-types-mut-globals::I64'
-// check:$7 = -64
-// debugger:print 'basic-types-mut-globals::U'
-// check:$8 = 1
-// debugger:print/d 'basic-types-mut-globals::U8'
-// check:$9 = 100
-// debugger:print 'basic-types-mut-globals::U16'
-// check:$10 = 16
-// debugger:print 'basic-types-mut-globals::U32'
-// check:$11 = 32
-// debugger:print 'basic-types-mut-globals::U64'
-// check:$12 = 64
-// debugger:print 'basic-types-mut-globals::F32'
-// check:$13 = 2.5
-// debugger:print 'basic-types-mut-globals::F64'
-// check:$14 = 3.5
-// debugger:continue
-
-// Check new values
-// debugger:print 'basic-types-mut-globals'::B
-// check:$15 = true
-// debugger:print 'basic-types-mut-globals'::I
-// check:$16 = 2
-// debugger:print 'basic-types-mut-globals'::C
-// check:$17 = 102
-// debugger:print/d 'basic-types-mut-globals'::I8
-// check:$18 = 78
-// debugger:print 'basic-types-mut-globals'::I16
-// check:$19 = -26
-// debugger:print 'basic-types-mut-globals'::I32
-// check:$20 = -12
-// debugger:print 'basic-types-mut-globals'::I64
-// check:$21 = -54
-// debugger:print 'basic-types-mut-globals'::U
-// check:$22 = 5
-// debugger:print/d 'basic-types-mut-globals'::U8
-// check:$23 = 20
-// debugger:print 'basic-types-mut-globals'::U16
-// check:$24 = 32
-// debugger:print 'basic-types-mut-globals'::U32
-// check:$25 = 16
-// debugger:print 'basic-types-mut-globals'::U64
-// check:$26 = 128
-// debugger:print 'basic-types-mut-globals'::F32
-// check:$27 = 5.75
-// debugger:print 'basic-types-mut-globals'::F64
-// check:$28 = 9.25
-
-// debugger:detach
-// debugger:quit
-
-#![allow(unused_variable)]
-
-static mut B: bool = false;
-static mut I: int = -1;
-static mut C: char = 'a';
-static mut I8: i8 = 68;
-static mut I16: i16 = -16;
-static mut I32: i32 = -32;
-static mut I64: i64 = -64;
-static mut U: uint = 1;
-static mut U8: u8 = 100;
-static mut U16: u16 = 16;
-static mut U32: u32 = 32;
-static mut U64: u64 = 64;
-static mut F32: f32 = 2.5;
-static mut F64: f64 = 3.5;
-
-fn main() {
- _zzz();
-
- unsafe {
- B = true;
- I = 2;
- C = 'f';
- I8 = 78;
- I16 = -26;
- I32 = -12;
- I64 = -54;
- U = 5;
- U8 = 20;
- U16 = 32;
- U32 = 16;
- U64 = 128;
- F32 = 5.75;
- F64 = 9.25;
- }
-
- _zzz();
-}
-
-fn _zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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.
-
-// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
-// as its numerical value along with its associated ASCII char, there
-// doesn't seem to be any way around this. Also, gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print b
-// check:$1 = false
-// debugger:print i
-// check:$2 = -1
-// debugger:print c
-// check:$3 = 97
-// debugger:print/d i8
-// check:$4 = 68
-// debugger:print i16
-// check:$5 = -16
-// debugger:print i32
-// check:$6 = -32
-// debugger:print i64
-// check:$7 = -64
-// debugger:print u
-// check:$8 = 1
-// debugger:print/d u8
-// check:$9 = 100
-// debugger:print u16
-// check:$10 = 16
-// debugger:print u32
-// check:$11 = 32
-// debugger:print u64
-// check:$12 = 64
-// debugger:print f32
-// check:$13 = 2.5
-// debugger:print f64
-// check:$14 = 3.5
-
-#![allow(unused_variable)]
-
-fn main() {
- let b: bool = false;
- let i: int = -1;
- let c: char = 'a';
- let i8: i8 = 68;
- let i16: i16 = -16;
- let i32: i32 = -32;
- let i64: i64 = -64;
- let u: uint = 1;
- let u8: u8 = 100;
- let u16: u16 = 16;
- let u32: u32 = 32;
- let u64: u64 = 64;
- let f32: f32 = 2.5;
- let f64: f64 = 3.5;
- _zzz();
-}
-
-fn _zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print *bool_ref
-// check:$1 = true
-
-// debugger:print *int_ref
-// check:$2 = -1
-
-// debugger:print *char_ref
-// check:$3 = 97
-
-// debugger:print *i8_ref
-// check:$4 = 68 'D'
-
-// debugger:print *i16_ref
-// check:$5 = -16
-
-// debugger:print *i32_ref
-// check:$6 = -32
-
-// debugger:print *i64_ref
-// check:$7 = -64
-
-// debugger:print *uint_ref
-// check:$8 = 1
-
-// debugger:print *u8_ref
-// check:$9 = 100 'd'
-
-// debugger:print *u16_ref
-// check:$10 = 16
-
-// debugger:print *u32_ref
-// check:$11 = 32
-
-// debugger:print *u64_ref
-// check:$12 = 64
-
-// debugger:print *f32_ref
-// check:$13 = 2.5
-
-// debugger:print *f64_ref
-// check:$14 = 3.5
-
-#![allow(unused_variable)]
-
-fn main() {
- let bool_val: bool = true;
- let bool_ref: &bool = &bool_val;
-
- let int_val: int = -1;
- let int_ref: &int = &int_val;
-
- let char_val: char = 'a';
- let char_ref: &char = &char_val;
-
- let i8_val: i8 = 68;
- let i8_ref: &i8 = &i8_val;
-
- let i16_val: i16 = -16;
- let i16_ref: &i16 = &i16_val;
-
- let i32_val: i32 = -32;
- let i32_ref: &i32 = &i32_val;
-
- let uint_val: i64 = -64;
- let i64_ref: &i64 = &uint_val;
-
- let uint_val: uint = 1;
- let uint_ref: &uint = &uint_val;
-
- let u8_val: u8 = 100;
- let u8_ref: &u8 = &u8_val;
-
- let u16_val: u16 = 16;
- let u16_ref: &u16 = &u16_val;
-
- let u32_val: u32 = 32;
- let u32_ref: &u32 = &u32_val;
-
- let u64_val: u64 = 64;
- let u64_ref: &u64 = &u64_val;
-
- let f32_val: f32 = 2.5;
- let f32_ref: &f32 = &f32_val;
-
- let f64_val: f64 = 3.5;
- let f64_ref: &f64 = &f64_val;
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *the_a_ref
-// check:$1 = TheA
-
-// debugger:print *the_b_ref
-// check:$2 = TheB
-
-// debugger:print *the_c_ref
-// check:$3 = TheC
-
-#![allow(unused_variable)]
-
-enum ABC { TheA, TheB, TheC }
-
-fn main() {
- let the_a = TheA;
- let the_a_ref: &ABC = &the_a;
-
- let the_b = TheB;
- let the_b_ref: &ABC = &the_b;
-
- let the_c = TheC;
- let the_c_ref: &ABC = &the_c;
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *the_a_ref
-// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
-
-// debugger:print *the_b_ref
-// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
-
-// debugger:print *univariant_ref
-// check:$3 = {4820353753753434}
-
-#![allow(unused_variable)]
-#![feature(struct_variant)]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
- TheA { x: i64, y: i64 },
- TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
- TheOnlyCase(i64)
-}
-
-fn main() {
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let the_a = TheA { x: 0, y: 8970181431921507452 };
- let the_a_ref: &ABC = &the_a;
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let the_b = TheB (0, 286331153, 286331153);
- let the_b_ref: &ABC = &the_b;
-
- let univariant = TheOnlyCase(4820353753753434);
- let univariant_ref: &Univariant = &univariant;
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print *bool_ref
-// check:$1 = true
-
-// debugger:print *int_ref
-// check:$2 = -1
-
-// debugger:print *char_ref
-// check:$3 = 97
-
-// debugger:print/d *i8_ref
-// check:$4 = 68
-
-// debugger:print *i16_ref
-// check:$5 = -16
-
-// debugger:print *i32_ref
-// check:$6 = -32
-
-// debugger:print *i64_ref
-// check:$7 = -64
-
-// debugger:print *uint_ref
-// check:$8 = 1
-
-// debugger:print/d *u8_ref
-// check:$9 = 100
-
-// debugger:print *u16_ref
-// check:$10 = 16
-
-// debugger:print *u32_ref
-// check:$11 = 32
-
-// debugger:print *u64_ref
-// check:$12 = 64
-
-// debugger:print *f32_ref
-// check:$13 = 2.5
-
-// debugger:print *f64_ref
-// check:$14 = 3.5
-
-#![allow(unused_variable)]
-
-fn main() {
- let bool_box: @bool = @true;
- let bool_ref: &bool = bool_box;
-
- let int_box: @int = @-1;
- let int_ref: &int = int_box;
-
- let char_box: @char = @'a';
- let char_ref: &char = char_box;
-
- let i8_box: @i8 = @68;
- let i8_ref: &i8 = i8_box;
-
- let i16_box: @i16 = @-16;
- let i16_ref: &i16 = i16_box;
-
- let i32_box: @i32 = @-32;
- let i32_ref: &i32 = i32_box;
-
- let i64_box: @i64 = @-64;
- let i64_ref: &i64 = i64_box;
-
- let uint_box: @uint = @1;
- let uint_ref: &uint = uint_box;
-
- let u8_box: @u8 = @100;
- let u8_ref: &u8 = u8_box;
-
- let u16_box: @u16 = @16;
- let u16_ref: &u16 = u16_box;
-
- let u32_box: @u32 = @32;
- let u32_ref: &u32 = u32_box;
-
- let u64_box: @u64 = @64;
- let u64_ref: &u64 = u64_box;
-
- let f32_box: @f32 = @2.5;
- let f32_ref: &f32 = f32_box;
-
- let f64_box: @f64 = @3.5;
- let f64_ref: &f64 = f64_box;
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *stack_val_ref
-// check:$1 = {x = 10, y = 23.5}
-
-// debugger:print *stack_val_interior_ref_1
-// check:$2 = 10
-
-// debugger:print *stack_val_interior_ref_2
-// check:$3 = 23.5
-
-// debugger:print *ref_to_unnamed
-// check:$4 = {x = 11, y = 24.5}
-
-// debugger:print *managed_val_ref
-// check:$5 = {x = 12, y = 25.5}
-
-// debugger:print *managed_val_interior_ref_1
-// check:$6 = 12
-
-// debugger:print *managed_val_interior_ref_2
-// check:$7 = 25.5
-
-// debugger:print *unique_val_ref
-// check:$8 = {x = 13, y = 26.5}
-
-// debugger:print *unique_val_interior_ref_1
-// check:$9 = 13
-
-// debugger:print *unique_val_interior_ref_2
-// check:$10 = 26.5
-
-#![feature(managed_boxes)]
-#![allow(unused_variable)]
-
-struct SomeStruct {
- x: int,
- y: f64
-}
-
-fn main() {
- let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 };
- let stack_val_ref: &SomeStruct = &stack_val;
- let stack_val_interior_ref_1: &int = &stack_val.x;
- let stack_val_interior_ref_2: &f64 = &stack_val.y;
- let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
-
- let managed_val = @SomeStruct { x: 12, y: 25.5 };
- let managed_val_ref: &SomeStruct = managed_val;
- let managed_val_interior_ref_1: &int = &managed_val.x;
- let managed_val_interior_ref_2: &f64 = &managed_val.y;
-
- let unique_val = box SomeStruct { x: 13, y: 26.5 };
- let unique_val_ref: &SomeStruct = unique_val;
- let unique_val_interior_ref_1: &int = &unique_val.x;
- let unique_val_interior_ref_2: &f64 = &unique_val.y;
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *stack_val_ref
-// check:$1 = {-14, -19}
-
-// debugger:print *ref_to_unnamed
-// check:$2 = {-15, -20}
-
-// debugger:print *managed_val_ref
-// check:$3 = {-16, -21}
-
-// debugger:print *unique_val_ref
-// check:$4 = {-17, -22}
-
-#![allow(unused_variable)]
-
-
-fn main() {
- let stack_val: (i16, f32) = (-14, -19f32);
- let stack_val_ref: &(i16, f32) = &stack_val;
- let ref_to_unnamed: &(i16, f32) = &(-15, -20f32);
-
- let managed_val: @(i16, f32) = @(-16, -21f32);
- let managed_val_ref: &(i16, f32) = managed_val;
-
- let unique_val: Box<(i16, f32)> = box() (-17, -22f32);
- let unique_val_ref: &(i16, f32) = unique_val;
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
-// its numerical value.
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print *bool_ref
-// check:$1 = true
-
-// debugger:print *int_ref
-// check:$2 = -1
-
-// debugger:print *char_ref
-// check:$3 = 97
-
-// debugger:print/d *i8_ref
-// check:$4 = 68
-
-// debugger:print *i16_ref
-// check:$5 = -16
-
-// debugger:print *i32_ref
-// check:$6 = -32
-
-// debugger:print *i64_ref
-// check:$7 = -64
-
-// debugger:print *uint_ref
-// check:$8 = 1
-
-// debugger:print/d *u8_ref
-// check:$9 = 100
-
-// debugger:print *u16_ref
-// check:$10 = 16
-
-// debugger:print *u32_ref
-// check:$11 = 32
-
-// debugger:print *u64_ref
-// check:$12 = 64
-
-// debugger:print *f32_ref
-// check:$13 = 2.5
-
-// debugger:print *f64_ref
-// check:$14 = 3.5
-
-#![allow(unused_variable)]
-
-
-fn main() {
- let bool_box: Box<bool> = box true;
- let bool_ref: &bool = bool_box;
-
- let int_box: Box<int> = box -1;
- let int_ref: &int = int_box;
-
- let char_box: Box<char> = box 'a';
- let char_ref: &char = char_box;
-
- let i8_box: Box<i8> = box 68;
- let i8_ref: &i8 = i8_box;
-
- let i16_box: Box<i16> = box -16;
- let i16_ref: &i16 = i16_box;
-
- let i32_box: Box<i32> = box -32;
- let i32_ref: &i32 = i32_box;
-
- let i64_box: Box<i64> = box -64;
- let i64_ref: &i64 = i64_box;
-
- let uint_box: Box<uint> = box 1;
- let uint_ref: &uint = uint_box;
-
- let u8_box: Box<u8> = box 100;
- let u8_ref: &u8 = u8_box;
-
- let u16_box: Box<u16> = box 16;
- let u16_ref: &u16 = u16_box;
-
- let u32_box: Box<u32> = box 32;
- let u32_ref: &u32 = u32_box;
-
- let u64_box: Box<u64> = box 64;
- let u64_ref: &u64 = u64_box;
-
- let f32_box: Box<f32> = box 2.5;
- let f32_ref: &f32 = f32_box;
-
- let f64_box: Box<f64> = box 3.5;
- let f64_ref: &f64 = f64_box;
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print *a
-// check:$1 = 1
-// debugger:print *b
-// check:$2 = {2, 3.5}
-// debugger:print c->val
-// check:$3 = 4
-// debugger:print d->val
-// check:$4 = false
-
-#![feature(managed_boxes)]
-#![allow(unused_variable)]
-
-fn main() {
- let a = box 1;
- let b = box() (2, 3.5);
- let c = @4;
- let d = @false;
- _zzz();
-}
-
-fn _zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *unique
-// check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
-
-// debugger:print managed->val
-// check:$2 = {x = 88, y = 888, z = 8888, w = 88888}
-
-// debugger:print *unique_dtor
-// check:$3 = {x = 77, y = 777, z = 7777, w = 77777}
-
-// debugger:print managed_dtor->val
-// check:$4 = {x = 33, y = 333, z = 3333, w = 33333}
-
-#![feature(managed_boxes)]
-#![allow(unused_variable)]
-
-
-struct StructWithSomePadding {
- x: i16,
- y: i32,
- z: i32,
- w: i64
-}
-
-struct StructWithDestructor {
- x: i16,
- y: i32,
- z: i32,
- w: i64
-}
-
-impl Drop for StructWithDestructor {
- fn drop(&mut self) {}
-}
-
-fn main() {
-
- let unique = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
- let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 };
-
- let unique_dtor = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
- let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print s
-// check:$1 = {a = 1, b = 2.5}
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = {a = 3, b = 4.5}
-// debugger:print y
-// check:$3 = 5
-// debugger:print z
-// check:$4 = 6.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$5 = {7, 8, 9.5, 10.5}
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$6 = {11.5, 12.5, 13, 14}
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$7 = {{Case1, x = 0, y = 8970181431921507452}, {Case1, 0, 2088533116, 2088533116}}
-// debugger:continue
-
-#![feature(struct_variant)]
-
-#[deriving(Clone)]
-struct Struct {
- a: int,
- b: f64
-}
-
-#[deriving(Clone)]
-struct StructStruct {
- a: Struct,
- b: Struct
-}
-
-fn fun(s: Struct) {
- zzz();
-}
-
-fn fun_fun(StructStruct { a: x, b: Struct { a: y, b: z } }: StructStruct) {
- zzz();
-}
-
-fn tup(a: (int, uint, f64, f64)) {
- zzz();
-}
-
-struct Newtype(f64, f64, int, uint);
-
-fn new_type(a: Newtype) {
- zzz();
-}
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Enum {
- Case1 { x: i64, y: i64 },
- Case2 (i64, i32, i32),
-}
-
-fn by_val_enum(x: Enum) {
- zzz();
-}
-
-fn main() {
- fun(Struct { a: 1, b: 2.5 });
- fun_fun(StructStruct { a: Struct { a: 3, b: 4.5 }, b: Struct { a: 5, b: 6.5 } });
- tup((7, 8, 9.5, 10.5));
- new_type(Newtype(11.5, 12.5, 13, 14));
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- by_val_enum(Case1 { x: 0, y: 8970181431921507452 });
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print self
-// check:$1 = 1111
-// debugger:continue
-
-// debugger:finish
-// debugger:print self
-// check:$2 = {x = 2222, y = 3333}
-// debugger:continue
-
-// debugger:finish
-// debugger:print self
-// check:$3 = {4444.5, 5555, 6666, 7777.5}
-// debugger:continue
-
-// debugger:finish
-// debugger:print self->val
-// check:$4 = 8888
-// debugger:continue
-
-trait Trait {
- fn method(self) -> Self;
-}
-
-impl Trait for int {
- fn method(self) -> int {
- zzz();
- self
- }
-}
-
-struct Struct {
- x: uint,
- y: uint,
-}
-
-impl Trait for Struct {
- fn method(self) -> Struct {
- zzz();
- self
- }
-}
-
-impl Trait for (f64, int, int, f64) {
- fn method(self) -> (f64, int, int, f64) {
- zzz();
- self
- }
-}
-
-impl Trait for @int {
- fn method(self) -> @int {
- zzz();
- self
- }
-}
-
-fn main() {
- let _ = (1111 as int).method();
- let _ = Struct { x: 2222, y: 3333 }.method();
- let _ = (4444.5, 5555, 6666, 7777.5).method();
- let _ = (@8888).method();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print tuple_interior_padding
-// check:$1 = {0, OneHundred}
-
-// debugger:print tuple_padding_at_end
-// check:$2 = {{1, OneThousand}, 2}
-
-// debugger:print tuple_different_enums
-// check:$3 = {OneThousand, MountainView, OneMillion, Vienna}
-
-// debugger:print padded_struct
-// check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5}
-
-// debugger:print packed_struct
-// check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8}
-
-// debugger:print non_padded_struct
-// check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto}
-
-// debugger:print struct_with_drop
-// check:$7 = {{a = OneHundred, b = Vienna}, 9}
-
-#![allow(unused_variable)]
-
-enum AnEnum {
- OneHundred = 100,
- OneThousand = 1000,
- OneMillion = 1000000
-}
-
-enum AnotherEnum {
- MountainView,
- Toronto,
- Vienna
-}
-
-struct PaddedStruct {
- a: i16,
- b: AnEnum,
- c: i16,
- d: AnotherEnum,
- e: i16
-}
-
-#[packed]
-struct PackedStruct {
- a: i16,
- b: AnEnum,
- c: i16,
- d: AnotherEnum,
- e: i16
-}
-
-struct NonPaddedStruct {
- a: AnEnum,
- b: AnotherEnum,
- c: AnEnum,
- d: AnotherEnum
-}
-
-struct StructWithDrop {
- a: AnEnum,
- b: AnotherEnum
-}
-
-impl Drop for StructWithDrop {
- fn drop(&mut self) {()}
-}
-
-fn main() {
-
- let tuple_interior_padding = (0_i16, OneHundred);
- // It will depend on the machine architecture if any padding is actually involved here
- let tuple_padding_at_end = ((1_u64, OneThousand), 2_u64);
- let tuple_different_enums = (OneThousand, MountainView, OneMillion, Vienna);
-
- let padded_struct = PaddedStruct {
- a: 3,
- b: OneMillion,
- c: 4,
- d: Toronto,
- e: 5
- };
-
- let packed_struct = PackedStruct {
- a: 6,
- b: OneHundred,
- c: 7,
- d: Vienna,
- e: 8
- };
-
- let non_padded_struct = NonPaddedStruct {
- a: OneMillion,
- b: MountainView,
- c: OneThousand,
- d: Toronto
- };
-
- let struct_with_drop = (StructWithDrop { a: OneHundred, b: Vienna }, 9_i64);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-
-// debugger:print 'c-style-enum::SINGLE_VARIANT'
-// check:$1 = TheOnlyVariant
-
-// debugger:print 'c-style-enum::AUTO_ONE'
-// check:$2 = One
-
-// debugger:print 'c-style-enum::AUTO_TWO'
-// check:$3 = One
-
-// debugger:print 'c-style-enum::AUTO_THREE'
-// check:$4 = One
-
-// debugger:print 'c-style-enum::MANUAL_ONE'
-// check:$5 = OneHundred
-
-// debugger:print 'c-style-enum::MANUAL_TWO'
-// check:$6 = OneHundred
-
-// debugger:print 'c-style-enum::MANUAL_THREE'
-// check:$7 = OneHundred
-
-// debugger:run
-// debugger:finish
-
-// debugger:print auto_one
-// check:$8 = One
-
-// debugger:print auto_two
-// check:$9 = Two
-
-// debugger:print auto_three
-// check:$10 = Three
-
-// debugger:print manual_one_hundred
-// check:$11 = OneHundred
-
-// debugger:print manual_one_thousand
-// check:$12 = OneThousand
-
-// debugger:print manual_one_million
-// check:$13 = OneMillion
-
-// debugger:print single_variant
-// check:$14 = TheOnlyVariant
-
-// debugger:print 'c-style-enum::AUTO_TWO'
-// check:$15 = Two
-
-// debugger:print 'c-style-enum::AUTO_THREE'
-// check:$16 = Three
-
-// debugger:print 'c-style-enum::MANUAL_TWO'
-// check:$17 = OneThousand
-
-// debugger:print 'c-style-enum::MANUAL_THREE'
-// check:$18 = OneMillion
-
-#![allow(unused_variable)]
-#![allow(dead_code)]
-
-enum AutoDiscriminant {
- One,
- Two,
- Three
-}
-
-enum ManualDiscriminant {
- OneHundred = 100,
- OneThousand = 1000,
- OneMillion = 1000000
-}
-
-enum SingleVariant {
- TheOnlyVariant
-}
-
-static SINGLE_VARIANT: SingleVariant = TheOnlyVariant;
-
-static mut AUTO_ONE: AutoDiscriminant = One;
-static mut AUTO_TWO: AutoDiscriminant = One;
-static mut AUTO_THREE: AutoDiscriminant = One;
-
-static mut MANUAL_ONE: ManualDiscriminant = OneHundred;
-static mut MANUAL_TWO: ManualDiscriminant = OneHundred;
-static mut MANUAL_THREE: ManualDiscriminant = OneHundred;
-
-fn main() {
-
- let auto_one = One;
- let auto_two = Two;
- let auto_three = Three;
-
- let manual_one_hundred = OneHundred;
- let manual_one_thousand = OneThousand;
- let manual_one_million = OneMillion;
-
- let single_variant = TheOnlyVariant;
-
- unsafe {
- AUTO_TWO = Two;
- AUTO_THREE = Three;
-
- MANUAL_TWO = OneThousand;
- MANUAL_THREE = OneMillion;
- };
-
- zzz();
-
- let a = SINGLE_VARIANT;
- let a = unsafe { AUTO_ONE };
- let a = unsafe { MANUAL_ONE };
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = 0.5
-// debugger:print y
-// check:$2 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print *x
-// check:$3 = 29
-// debugger:print *y
-// check:$4 = 110
-// debugger:continue
-
-fn some_generic_fun<T1, T2>(a: T1, b: T2) -> (T2, T1) {
-
- let closure = |x, y| {
- zzz();
- (y, x)
- };
-
- closure(a, b)
-}
-
-fn main() {
- some_generic_fun(0.5, 10);
- some_generic_fun(&29, box 110);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print a
-// check:$1 = 1
-// debugger:print b
-// check:$2 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$3 = 2
-// debugger:print b
-// check:$4 = 3
-// debugger:print c
-// check:$5 = 4
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$6 = 5
-// debugger:print b
-// check:$7 = {6, 7}
-// debugger:continue
-
-// debugger:finish
-// debugger:print h
-// check:$8 = 8
-// debugger:print i
-// check:$9 = {a = 9, b = 10}
-// debugger:print j
-// check:$10 = 11
-// debugger:continue
-
-// debugger:finish
-// debugger:print k
-// check:$11 = 12
-// debugger:print l
-// check:$12 = 13
-// debugger:continue
-
-// debugger:finish
-// debugger:print m
-// check:$13 = 14
-// debugger:print n
-// check:$14 = 16
-// debugger:continue
-
-// debugger:finish
-// debugger:print o
-// check:$15 = 18
-// debugger:continue
-
-// debugger:finish
-// debugger:print p
-// check:$16 = 19
-// debugger:print q
-// check:$17 = 20
-// debugger:print r
-// check:$18 = {a = 21, b = 22}
-// debugger:continue
-
-// debugger:finish
-// debugger:print s
-// check:$19 = 24
-// debugger:print t
-// check:$20 = 23
-// debugger:continue
-
-// debugger:finish
-// debugger:print u
-// check:$21 = 25
-// debugger:print v
-// check:$22 = 26
-// debugger:print w
-// check:$23 = 27
-// debugger:print x
-// check:$24 = 28
-// debugger:print y
-// check:$25 = 29
-// debugger:print z
-// check:$26 = 30
-// debugger:print ae
-// check:$27 = 31
-// debugger:print oe
-// check:$28 = 32
-// debugger:print ue
-// check:$29 = 33
-// debugger:continue
-
-// debugger:finish
-// debugger:print aa
-// check:$30 = {34, 35}
-// debugger:continue
-
-// debugger:finish
-// debugger:print bb
-// check:$31 = {36, 37}
-// debugger:continue
-
-// debugger:finish
-// debugger:print cc
-// check:$32 = 38
-// debugger:continue
-
-// debugger:finish
-// debugger:print dd
-// check:$33 = {40, 41, 42}
-// debugger:continue
-
-// debugger:finish
-// debugger:print *ee
-// check:$34 = {43, 44, 45}
-// debugger:continue
-
-// debugger:finish
-// debugger:print *ff
-// check:$35 = 46
-// debugger:print gg
-// check:$36 = {47, 48}
-// debugger:continue
-
-// debugger:finish
-// debugger:print *hh
-// check:$37 = 50
-// debugger:continue
-
-// debugger:finish
-// debugger:print ii
-// check:$38 = 51
-// debugger:continue
-
-// debugger:finish
-// debugger:print *jj
-// check:$39 = 52
-// debugger:continue
-
-// debugger:finish
-// debugger:print kk
-// check:$40 = 53
-// debugger:print ll
-// check:$41 = 54
-// debugger:continue
-
-// debugger:finish
-// debugger:print mm
-// check:$42 = 55
-// debugger:print *nn
-// check:$43 = 56
-// debugger:continue
-
-// debugger:finish
-// debugger:print oo
-// check:$44 = 57
-// debugger:print pp
-// check:$45 = 58
-// debugger:print qq
-// check:$46 = 59
-// debugger:continue
-
-// debugger:finish
-// debugger:print rr
-// check:$47 = 60
-// debugger:print ss
-// check:$48 = 61
-// debugger:print tt
-// check:$49 = 62
-// debugger:continue
-
-#![allow(unused_variable)]
-
-
-struct Struct {
- a: i64,
- b: i32
-}
-
-enum Univariant {
- Unit(i32)
-}
-
-struct TupleStruct (f64, int);
-
-
-fn simple_tuple((a, b): (int, bool)) {
- zzz();
-}
-
-fn nested_tuple((a, (b, c)): (int, (u16, u16))) {
- zzz();
-}
-
-fn destructure_only_first_level((a, b): (int, (u32, u32))) {
- zzz();
-}
-
-fn struct_as_tuple_element((h, i, j): (i16, Struct, i16)) {
- zzz();
-}
-
-fn struct_pattern(Struct { a: k, b: l }: Struct) {
- zzz();
-}
-
-fn ignored_tuple_element((m, _, n): (int, u16, i32)) {
- zzz();
-}
-
-fn ignored_struct_field(Struct { b: o, .. }: Struct) {
- zzz();
-}
-
-fn one_struct_destructured_one_not((Struct { a: p, b: q }, r): (Struct, Struct)) {
- zzz();
-}
-
-fn different_order_of_struct_fields(Struct { b: s, a: t }: Struct ) {
- zzz();
-}
-
-fn complex_nesting(((u, v ), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue ):
- ((i16, i32), ((i64, (i32, Struct, )), Struct ), u16))
-{
- zzz();
-}
-
-fn managed_box(&aa: &(int, int)) {
- zzz();
-}
-
-fn borrowed_pointer(&bb: &(int, int)) {
- zzz();
-}
-
-fn contained_borrowed_pointer((&cc, _): (&int, int)) {
- zzz();
-}
-
-fn unique_pointer(box dd: Box<(int, int, int)>) {
- zzz();
-}
-
-fn ref_binding(ref ee: (int, int, int)) {
- zzz();
-}
-
-fn ref_binding_in_tuple((ref ff, gg): (int, (int, int))) {
- zzz();
-}
-
-fn ref_binding_in_struct(Struct { b: ref hh, .. }: Struct) {
- zzz();
-}
-
-fn univariant_enum(Unit(ii): Univariant) {
- zzz();
-}
-
-fn univariant_enum_with_ref_binding(Unit(ref jj): Univariant) {
- zzz();
-}
-
-fn tuple_struct(TupleStruct(kk, ll): TupleStruct) {
- zzz();
-}
-
-fn tuple_struct_with_ref_binding(TupleStruct(mm, ref nn): TupleStruct) {
- zzz();
-}
-
-fn multiple_arguments((oo, pp): (int, int), qq : int) {
- zzz();
-}
-
-fn main() {
- simple_tuple((1, false));
- nested_tuple((2, (3, 4)));
- destructure_only_first_level((5, (6, 7)));
- struct_as_tuple_element((8, Struct { a: 9, b: 10 }, 11));
- struct_pattern(Struct { a: 12, b: 13 });
- ignored_tuple_element((14, 15, 16));
- ignored_struct_field(Struct { a: 17, b: 18 });
- one_struct_destructured_one_not((Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 }));
- different_order_of_struct_fields(Struct { a: 23, b: 24 });
- complex_nesting(((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33));
- managed_box(&(34, 35));
- borrowed_pointer(&(36, 37));
- contained_borrowed_pointer((&38, 39));
- unique_pointer(box() (40, 41, 42));
- ref_binding((43, 44, 45));
- ref_binding_in_tuple((46, (47, 48)));
- ref_binding_in_struct(Struct { a: 49, b: 50 });
- univariant_enum(Unit(51));
- univariant_enum_with_ref_binding(Unit(52));
- tuple_struct(TupleStruct(53.0, 54));
- tuple_struct_with_ref_binding(TupleStruct(55.0, 56));
- multiple_arguments((57, 58), 59);
-
- fn nested_function(rr: int, (ss, tt): (int, int)) {
- zzz();
- }
-
- nested_function(60, (61, 62));
-}
-
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print a
-// check:$1 = 1
-// debugger:print b
-// check:$2 = false
-
-// debugger:print c
-// check:$3 = 2
-// debugger:print d
-// check:$4 = 3
-// debugger:print e
-// check:$5 = 4
-
-// debugger:print f
-// check:$6 = 5
-// debugger:print g
-// check:$7 = {6, 7}
-
-// debugger:print h
-// check:$8 = 8
-// debugger:print i
-// check:$9 = {a = 9, b = 10}
-// debugger:print j
-// check:$10 = 11
-
-// debugger:print k
-// check:$11 = 12
-// debugger:print l
-// check:$12 = 13
-
-// debugger:print m
-// check:$13 = 14
-// debugger:print n
-// check:$14 = 16
-
-// debugger:print o
-// check:$15 = 18
-
-// debugger:print p
-// check:$16 = 19
-// debugger:print q
-// check:$17 = 20
-// debugger:print r
-// check:$18 = {a = 21, b = 22}
-
-// debugger:print s
-// check:$19 = 24
-// debugger:print t
-// check:$20 = 23
-
-// debugger:print u
-// check:$21 = 25
-// debugger:print v
-// check:$22 = 26
-// debugger:print w
-// check:$23 = 27
-// debugger:print x
-// check:$24 = 28
-// debugger:print y
-// check:$25 = 29
-// debugger:print z
-// check:$26 = 30
-// debugger:print ae
-// check:$27 = 31
-// debugger:print oe
-// check:$28 = 32
-// debugger:print ue
-// check:$29 = 33
-
-// debugger:print aa
-// check:$30 = {34, 35}
-
-// debugger:print bb
-// check:$31 = {36, 37}
-
-// debugger:print cc
-// check:$32 = 38
-
-// debugger:print dd
-// check:$33 = {40, 41, 42}
-
-// debugger:print *ee
-// check:$34 = {43, 44, 45}
-
-// debugger:print *ff
-// check:$35 = 46
-
-// debugger:print gg
-// check:$36 = {47, 48}
-
-// debugger:print *hh
-// check:$37 = 50
-
-// debugger:print ii
-// check:$38 = 51
-
-// debugger:print *jj
-// check:$39 = 52
-
-// debugger:print kk
-// check:$40 = 53
-
-// debugger:print ll
-// check:$41 = 54
-
-// debugger:print mm
-// check:$42 = 55
-
-// debugger:print *nn
-// check:$43 = 56
-
-#![allow(unused_variable)]
-
-struct Struct {
- a: i64,
- b: i32
-}
-
-enum Univariant {
- Unit(i32)
-}
-
-struct TupleStruct (f64, int);
-
-
-fn main() {
- // simple tuple
- let (a, b) : (int, bool) = (1, false);
-
- // nested tuple
- let (c, (d, e)) : (int, (u16, u16)) = (2, (3, 4));
-
- // bind tuple-typed value to one name (destructure only first level)
- let (f, g) : (int, (u32, u32)) = (5, (6, 7));
-
- // struct as tuple element
- let (h, i, j) : (i16, Struct, i16) = (8, Struct { a: 9, b: 10 }, 11);
-
- // struct pattern
- let Struct { a: k, b: l } = Struct { a: 12, b: 13 };
-
- // ignored tuple element
- let (m, _, n) = (14, 15, 16);
-
- // ignored struct field
- let Struct { b: o, .. } = Struct { a: 17, b: 18 };
-
- // one struct destructured, one not
- let (Struct { a: p, b: q }, r) = (Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 });
-
- // different order of struct fields
- let Struct { b: s, a: t } = Struct { a: 23, b: 24 };
-
- // complex nesting
- let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) =
- ((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33);
-
- // reference
- let &aa = &(34, 35);
-
- // reference
- let &bb = &(36, 37);
-
- // contained reference
- let (&cc, _) = (&38, 39);
-
- // unique pointer
- let box dd = box() (40, 41, 42);
-
- // ref binding
- let ref ee = (43, 44, 45);
-
- // ref binding in tuple
- let (ref ff, gg) = (46, (47, 48));
-
- // ref binding in struct
- let Struct { b: ref hh, .. } = Struct { a: 49, b: 50 };
-
- // univariant enum
- let Unit(ii) = Unit(51);
-
- // univariant enum with ref binding
- let &Unit(ref jj) = &Unit(52);
-
- // tuple struct
- let &TupleStruct(kk, ll) = &TupleStruct(53.0, 54);
-
- // tuple struct with ref binding
- let &TupleStruct(mm, ref nn) = &TupleStruct(55.0, 56);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print no_padding1
-// check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}}
-// debugger:print no_padding2
-// check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}}
-
-// debugger:print struct_internal_padding
-// check:$3 = {x = {13, 14}, y = {15, 16}}
-
-// debugger:print single_vec
-// check:$4 = {x = {17, 18, 19, 20, 21}}
-
-// debugger:print struct_padded_at_end
-// check:$5 = {x = {22, 23}, y = {24, 25}}
-
-#![allow(unused_variable)]
-
-struct NoPadding1 {
- x: [u32, ..3],
- y: i32,
- z: [f32, ..2]
-}
-
-struct NoPadding2 {
- x: [u32, ..3],
- y: [[u32, ..2], ..2]
-}
-
-struct StructInternalPadding {
- x: [i16, ..2],
- y: [i64, ..2]
-}
-
-struct SingleVec {
- x: [i16, ..5]
-}
-
-struct StructPaddedAtEnd {
- x: [i64, ..2],
- y: [i16, ..2]
-}
-
-fn main() {
-
- let no_padding1 = NoPadding1 {
- x: [0, 1, 2],
- y: -3,
- z: [4.5, 5.5]
- };
-
- let no_padding2 = NoPadding2 {
- x: [6, 7, 8],
- y: [[9, 10], [11, 12]]
- };
-
- let struct_internal_padding = StructInternalPadding {
- x: [13, 14],
- y: [15, 16]
- };
-
- let single_vec = SingleVec {
- x: [17, 18, 19, 20, 21]
- };
-
- let struct_padded_at_end = StructPaddedAtEnd {
- x: [22, 23],
- y: [24, 25]
- };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// This test case checks if function arguments already have the correct value when breaking at the
-// first line of the function, that is if the function prologue has already been executed at the
-// first line. Note that because of the __morestack part of the prologue GDB incorrectly breaks at
-// before the arguments have been properly loaded when setting the breakpoint via the function name.
-// Therefore the setup here sets them using line numbers (so be careful when changing this file).
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:break function-arg-initialization.rs:139
-// debugger:break function-arg-initialization.rs:154
-// debugger:break function-arg-initialization.rs:158
-// debugger:break function-arg-initialization.rs:162
-// debugger:break function-arg-initialization.rs:166
-// debugger:break function-arg-initialization.rs:170
-// debugger:break function-arg-initialization.rs:174
-// debugger:break function-arg-initialization.rs:178
-// debugger:break function-arg-initialization.rs:182
-// debugger:break function-arg-initialization.rs:190
-// debugger:break function-arg-initialization.rs:197
-
-
-// debugger:run
-
-// IMMEDIATE ARGS
-// debugger:print a
-// check:$1 = 1
-// debugger:print b
-// check:$2 = true
-// debugger:print c
-// check:$3 = 2.5
-// debugger:continue
-
-// NON IMMEDIATE ARGS
-// debugger:print a
-// check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
-// debugger:print b
-// check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
-// debugger:continue
-
-// BINDING
-// debugger:print a
-// check:$6 = 19
-// debugger:print b
-// check:$7 = 20
-// debugger:print c
-// check:$8 = 21.5
-// debugger:continue
-
-// ASSIGNMENT
-// debugger:print a
-// check:$9 = 22
-// debugger:print b
-// check:$10 = 23
-// debugger:print c
-// check:$11 = 24.5
-// debugger:continue
-
-// FUNCTION CALL
-// debugger:print x
-// check:$12 = 25
-// debugger:print y
-// check:$13 = 26
-// debugger:print z
-// check:$14 = 27.5
-// debugger:continue
-
-// EXPR
-// debugger:print x
-// check:$15 = 28
-// debugger:print y
-// check:$16 = 29
-// debugger:print z
-// check:$17 = 30.5
-// debugger:continue
-
-// RETURN EXPR
-// debugger:print x
-// check:$18 = 31
-// debugger:print y
-// check:$19 = 32
-// debugger:print z
-// check:$20 = 33.5
-// debugger:continue
-
-// ARITHMETIC EXPR
-// debugger:print x
-// check:$21 = 34
-// debugger:print y
-// check:$22 = 35
-// debugger:print z
-// check:$23 = 36.5
-// debugger:continue
-
-// IF EXPR
-// debugger:print x
-// check:$24 = 37
-// debugger:print y
-// check:$25 = 38
-// debugger:print z
-// check:$26 = 39.5
-// debugger:continue
-
-// WHILE EXPR
-// debugger:print x
-// check:$27 = 40
-// debugger:print y
-// check:$28 = 41
-// debugger:print z
-// check:$29 = 42
-// debugger:continue
-
-// LOOP EXPR
-// debugger:print x
-// check:$30 = 43
-// debugger:print y
-// check:$31 = 44
-// debugger:print z
-// check:$32 = 45
-// debugger:continue
-
-#![allow(unused_variable)]
-
-
-
-
-fn immediate_args(a: int, b: bool, c: f64) {
- ()
-}
-
-struct BigStruct {
- a: u64,
- b: u64,
- c: u64,
- d: u64,
- e: u64,
- f: u64,
- g: u64,
- h: u64
-}
-
-fn non_immediate_args(a: BigStruct, b: BigStruct) {
- ()
-}
-
-fn binding(a: i64, b: u64, c: f64) {
- let x = 0;
-}
-
-fn assignment(mut a: u64, b: u64, c: f64) {
- a = b;
-}
-
-fn function_call(x: u64, y: u64, z: f64) {
- std::io::stdio::print("Hi!")
-}
-
-fn identifier(x: u64, y: u64, z: f64) -> u64 {
- x
-}
-
-fn return_expr(x: u64, y: u64, z: f64) -> u64 {
- return x;
-}
-
-fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
- x + y
-}
-
-fn if_expr(x: u64, y: u64, z: f64) -> u64 {
- if x + y < 1000 {
- x
- } else {
- y
- }
-}
-
-fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
- while x + y < 1000 {
- x += z
- }
- return x;
-}
-
-fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
- loop {
- x += z;
-
- if x + y > 1000 {
- return x;
- }
- }
-}
-
-fn main() {
- immediate_args(1, true, 2.5);
-
- non_immediate_args(
- BigStruct {
- a: 3,
- b: 4,
- c: 5,
- d: 6,
- e: 7,
- f: 8,
- g: 9,
- h: 10
- },
- BigStruct {
- a: 11,
- b: 12,
- c: 13,
- d: 14,
- e: 15,
- f: 16,
- g: 17,
- h: 18
- }
- );
-
- binding(19, 20, 21.5);
- assignment(22, 23, 24.5);
- function_call(25, 26, 27.5);
- identifier(28, 29, 30.5);
- return_expr(31, 32, 33.5);
- arithmetic_expr(34, 35, 36.5);
- if_expr(37, 38, 39.5);
- while_expr(40, 41, 42);
- loop_expr(43, 44, 45);
-}
-
-
-
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print x
-// check:$1 = 111102
-// debugger:print y
-// check:$2 = true
-
-// debugger:continue
-// debugger:finish
-
-// debugger:print a
-// check:$3 = 2000
-// debugger:print b
-// check:$4 = 3000
-
-fn main() {
-
- fun(111102, true);
- nested(2000, 3000);
-
- fn nested(a: i32, b: i64) -> (i32, i64) {
- zzz();
- (a, b)
- }
-}
-
-fn fun(x: int, y: bool) -> (int, bool) {
- zzz();
-
- (x, y)
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// This test case checks if function arguments already have the correct value when breaking at the
-// beginning of a function. Functions with the #[no_split_stack] attribute have the same prologue as
-// regular C functions compiled with GCC or Clang and therefore are better handled by GDB. As a
-// consequence, and as opposed to regular Rust functions, we can set the breakpoints via the
-// function name (and don't have to fall back on using line numbers).
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak immediate_args
-// debugger:rbreak binding
-// debugger:rbreak assignment
-// debugger:rbreak function_call
-// debugger:rbreak identifier
-// debugger:rbreak return_expr
-// debugger:rbreak arithmetic_expr
-// debugger:rbreak if_expr
-// debugger:rbreak while_expr
-// debugger:rbreak loop_expr
-// debugger:run
-
-// IMMEDIATE ARGS
-// debugger:print a
-// check:$1 = 1
-// debugger:print b
-// check:$2 = true
-// debugger:print c
-// check:$3 = 2.5
-// debugger:continue
-
-// NON IMMEDIATE ARGS
-// debugger:print a
-// check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
-// debugger:print b
-// check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
-// debugger:continue
-
-// BINDING
-// debugger:print a
-// check:$6 = 19
-// debugger:print b
-// check:$7 = 20
-// debugger:print c
-// check:$8 = 21.5
-// debugger:continue
-
-// ASSIGNMENT
-// debugger:print a
-// check:$9 = 22
-// debugger:print b
-// check:$10 = 23
-// debugger:print c
-// check:$11 = 24.5
-// debugger:continue
-
-// FUNCTION CALL
-// debugger:print x
-// check:$12 = 25
-// debugger:print y
-// check:$13 = 26
-// debugger:print z
-// check:$14 = 27.5
-// debugger:continue
-
-// EXPR
-// debugger:print x
-// check:$15 = 28
-// debugger:print y
-// check:$16 = 29
-// debugger:print z
-// check:$17 = 30.5
-// debugger:continue
-
-// RETURN EXPR
-// debugger:print x
-// check:$18 = 31
-// debugger:print y
-// check:$19 = 32
-// debugger:print z
-// check:$20 = 33.5
-// debugger:continue
-
-// ARITHMETIC EXPR
-// debugger:print x
-// check:$21 = 34
-// debugger:print y
-// check:$22 = 35
-// debugger:print z
-// check:$23 = 36.5
-// debugger:continue
-
-// IF EXPR
-// debugger:print x
-// check:$24 = 37
-// debugger:print y
-// check:$25 = 38
-// debugger:print z
-// check:$26 = 39.5
-// debugger:continue
-
-// WHILE EXPR
-// debugger:print x
-// check:$27 = 40
-// debugger:print y
-// check:$28 = 41
-// debugger:print z
-// check:$29 = 42
-// debugger:continue
-
-// LOOP EXPR
-// debugger:print x
-// check:$30 = 43
-// debugger:print y
-// check:$31 = 44
-// debugger:print z
-// check:$32 = 45
-// debugger:continue
-
-#![allow(unused_variable)]
-
-#[no_split_stack]
-fn immediate_args(a: int, b: bool, c: f64) {
- ()
-}
-
-struct BigStruct {
- a: u64,
- b: u64,
- c: u64,
- d: u64,
- e: u64,
- f: u64,
- g: u64,
- h: u64
-}
-
-#[no_split_stack]
-fn non_immediate_args(a: BigStruct, b: BigStruct) {
- ()
-}
-
-#[no_split_stack]
-fn binding(a: i64, b: u64, c: f64) {
- let x = 0;
-}
-
-#[no_split_stack]
-fn assignment(mut a: u64, b: u64, c: f64) {
- a = b;
-}
-
-#[no_split_stack]
-fn function_call(x: u64, y: u64, z: f64) {
- std::io::stdio::print("Hi!")
-}
-
-#[no_split_stack]
-fn identifier(x: u64, y: u64, z: f64) -> u64 {
- x
-}
-
-#[no_split_stack]
-fn return_expr(x: u64, y: u64, z: f64) -> u64 {
- return x;
-}
-
-#[no_split_stack]
-fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
- x + y
-}
-
-#[no_split_stack]
-fn if_expr(x: u64, y: u64, z: f64) -> u64 {
- if x + y < 1000 {
- x
- } else {
- y
- }
-}
-
-#[no_split_stack]
-fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
- while x + y < 1000 {
- x += z
- }
- return x;
-}
-
-#[no_split_stack]
-fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
- loop {
- x += z;
-
- if x + y > 1000 {
- return x;
- }
- }
-}
-
-fn main() {
- immediate_args(1, true, 2.5);
-
- non_immediate_args(
- BigStruct {
- a: 3,
- b: 4,
- c: 5,
- d: 6,
- e: 7,
- f: 8,
- g: 9,
- h: 10
- },
- BigStruct {
- a: 11,
- b: 12,
- c: 13,
- d: 14,
- e: 15,
- f: 16,
- g: 17,
- h: 18
- }
- );
-
- binding(19, 20, 21.5);
- assignment(22, 23, 24.5);
- function_call(25, 26, 27.5);
- identifier(28, 29, 30.5);
- return_expr(31, 32, 33.5);
- arithmetic_expr(34, 35, 36.5);
- if_expr(37, 38, 39.5);
- while_expr(40, 41, 42);
- loop_expr(43, 44, 45);
-}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print *t0
-// check:$1 = 1
-// debugger:print *t1
-// check:$2 = 2.5
-// debugger:print ret
-// check:$3 = {{1, 2.5}, {2.5, 1}}
-// debugger:continue
-
-// debugger:finish
-// debugger:print *t0
-// check:$4 = 3.5
-// debugger:print *t1
-// check:$5 = 4
-// debugger:print ret
-// check:$6 = {{3.5, 4}, {4, 3.5}}
-// debugger:continue
-
-// debugger:finish
-// debugger:print *t0
-// check:$7 = 5
-// debugger:print *t1
-// check:$8 = {a = 6, b = 7.5}
-// debugger:print ret
-// check:$9 = {{5, {a = 6, b = 7.5}}, {{a = 6, b = 7.5}, 5}}
-// debugger:continue
-
-#[deriving(Clone)]
-struct Struct {
- a: int,
- b: f64
-}
-
-fn dup_tup<T0: Clone, T1: Clone>(t0: &T0, t1: &T1) -> ((T0, T1), (T1, T0)) {
- let ret = ((t0.clone(), t1.clone()), (t1.clone(), t0.clone()));
- zzz();
- ret
-}
-
-fn main() {
-
- let _ = dup_tup(&1, &2.5);
- let _ = dup_tup(&3.5, &4_u16);
- let _ = dup_tup(&5, &Struct { a: 6, b: 7.5 });
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = -1
-// debugger:print y
-// check:$2 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = -1
-// debugger:print y
-// check:$4 = 2.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = -2.5
-// debugger:print y
-// check:$6 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$7 = -2.5
-// debugger:print y
-// check:$8 = 2.5
-// debugger:continue
-
-fn outer<TA: Clone>(a: TA) {
- inner(a.clone(), 1);
- inner(a.clone(), 2.5);
-
- fn inner<TX, TY>(x: TX, y: TY) {
- zzz();
- }
-}
-
-fn main() {
- outer(-1);
- outer(-2.5);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = {8888, -8888}}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print/d arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = {8888, -8888}}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 1234.5}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 1234.5}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 1234.5}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10.5
-// debugger:continue
-
-struct Struct<T> {
- x: T
-}
-
-impl<T1> Struct<T1> {
-
- fn self_by_ref<T2>(&self, arg1: int, arg2: T2) -> int {
- zzz();
- arg1
- }
-
- fn self_by_val<T2>(self, arg1: int, arg2: T2) -> int {
- zzz();
- arg1
- }
-
- fn self_owned<T2>(~self, arg1: int, arg2: T2) -> int {
- zzz();
- arg1
- }
-}
-
-fn main() {
- let stack = Struct { x: (8888_u32, -8888_i32) };
- let _ = stack.self_by_ref(-1, -2_i8);
- let _ = stack.self_by_val(-3, -4_i16);
-
- let owned = box Struct { x: 1234.5 };
- let _ = owned.self_by_ref(-5, -6_i32);
- let _ = owned.self_by_val(-7, -8_i64);
- let _ = owned.self_owned(-9, -10.5_f32);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STRUCT
-// debugger:finish
-// debugger:print arg1
-// check:$1 = 1
-// debugger:print arg2
-// check:$2 = 2
-// debugger:continue
-
-// ENUM
-// debugger:finish
-// debugger:print arg1
-// check:$3 = -3
-// debugger:print arg2
-// check:$4 = 4.5
-// debugger:print arg3
-// check:$5 = 5
-// debugger:continue
-
-#![feature(struct_variant)]
-
-struct Struct {
- x: int
-}
-
-impl Struct {
-
- fn static_method<T1, T2>(arg1: T1, arg2: T2) -> int {
- zzz();
- return 0;
- }
-}
-
-enum Enum {
- Variant1 { x: int },
- Variant2,
- Variant3(f64, int, char),
-}
-
-impl Enum {
-
- fn static_method<T1, T2, T3>(arg1: T1, arg2: T2, arg3: T3) -> int {
- zzz();
- return 1;
- }
-}
-
-fn main() {
- Struct::static_method(1, 2);
- Enum::static_method(-3, 4.5, 5);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print union on
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print case1
-// check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
-
-// debugger:print case2
-// check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
-
-// debugger:print case3
-// check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
-
-// debugger:print univariant
-// check:$4 = {a = -1}
-
-#![feature(struct_variant)]
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
- Case1 { a: T64, b: T16, c: T16, d: T16, e: T16},
- Case2 { a: T64, b: T32, c: T32},
- Case3 { a: T64, b: T64 }
-}
-
-enum Univariant<T> {
- TheOnlyCase { a: T }
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let case1: Regular<u16, u32, i64> = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let case2: Regular<i16, u32, i64> = Case2 { a: 0, b: 286331153, c: 286331153 };
-
- // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
- // 0b01011001010110010101100101011001 = 1499027801
- // 0b0101100101011001 = 22873
- // 0b01011001 = 89
- let case3: Regular<u16, i32, u64> = Case3 { a: 0, b: 6438275382588823897 };
-
- let univariant = TheOnlyCase { a: -1 };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print int_int
-// check:$1 = {key = 0, value = 1}
-// debugger:print int_float
-// check:$2 = {key = 2, value = 3.5}
-// debugger:print float_int
-// check:$3 = {key = 4.5, value = 5}
-// debugger:print float_int_float
-// check:$4 = {key = 6.5, value = {key = 7, value = 8.5}}
-
-struct AGenericStruct<TKey, TValue> {
- key: TKey,
- value: TValue
-}
-
-fn main() {
-
- let int_int = AGenericStruct { key: 0, value: 1 };
- let int_float = AGenericStruct { key: 2, value: 3.5 };
- let float_int = AGenericStruct { key: 4.5, value: 5 };
- let float_int_float = AGenericStruct { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// ignore-test
-
-// 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.
-//
-// 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:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print arg1
-// check:$1 = 1000
-// debugger:print *arg2
-// check:$2 = {1, 2.5}
-// debugger:continue
-
-// debugger:finish
-// debugger:print arg1
-// check:$3 = 2000
-// debugger:print *arg2
-// check:$4 = {3.5, {4, 5, 6}}
-// debugger:continue
-
-
-struct Struct {
- x: int
-}
-
-trait Trait<T1> {
- fn generic_static_default_method<T2>(arg1: int, arg2: &(T1, T2)) -> int {
- zzz();
- arg1
- }
-}
-
-impl<T> Trait<T> for Struct {}
-
-fn main() {
-
- // Is this really how to use these?
- Trait::generic_static_default_method::<int, Struct, float>(1000, &(1, 2.5));
- Trait::generic_static_default_method::<float, Struct, (int, int, int)>(2000, &(3.5, (4, 5, 6)));
-
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print union on
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print case1
-// check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
-
-// debugger:print case2
-// check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
-
-// debugger:print case3
-// check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
-
-// debugger:print univariant
-// check:$4 = {-1}
-
-
-// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
-// substituted with something of size `xx` bits and the same alignment as an integer type of the
-// same size.
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular<T16, T32, T64> {
- Case1(T64, T16, T16, T16, T16),
- Case2(T64, T32, T32),
- Case3(T64, T64)
-}
-
-enum Univariant<T64> {
- TheOnlyCase(T64)
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let case1: Regular<u16, u32, u64> = Case1(0_u64, 31868_u16, 31868_u16, 31868_u16, 31868_u16);
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let case2: Regular<i16, i32, i64> = Case2(0_i64, 286331153_i32, 286331153_i32);
-
- // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
- // 0b01011001010110010101100101011001 = 1499027801
- // 0b0101100101011001 = 22873
- // 0b01011001 = 89
- let case3: Regular<i16, i32, i64> = Case3(0_i64, 6438275382588823897_i64);
-
- let univariant = TheOnlyCase(-1_i64);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print string1.length
-// check:$1 = 48
-// debugger:print string2.length
-// check:$2 = 48
-// debugger:print string3.length
-// check:$3 = 48
-// debugger:continue
-
-#![allow(unused_variable)]
-
-// This test case makes sure that debug info does not ICE when include_str is
-// used multiple times (see issue #11322).
-
-fn main() {
- let string1 = include_str!("text-to-include-1.txt");
- let string2 = include_str!("text-to-include-2.txt");
- let string3 = include_str!("text-to-include-3.txt");
- zzz();
-}
-
-fn zzz() {()}
+++ /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 args : ~[~str] = ::std::os::args();
- ::std::io::println(args[0]);
-}
-
-
-// ignore-android: FIXME(#10381)
-
-// This test case checks whether compile unit names are set correctly, so that the correct default
-// source file can be found.
-
-// compile-flags:-g
-// debugger:list
-// check:1[...]fn main() {
-// check:2[...]let args : ~[~str] = ::std::os::args();
-// check:3[...]::std::io::println(args[0]);
-// check:4[...]}
-
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
+++ /dev/null
-// Copyright 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:break issue12886.rs:29
-// debugger:run
-// debugger:next
-// check:[...]30[...]s
-// debugger:continue
-
-// IF YOU MODIFY THIS FILE, BE CAREFUL TO ADAPT THE LINE NUMBERS IN THE DEBUGGER COMMANDS
-
-// This test makes sure that gdb does not set unwanted breakpoints in inlined functions. If a
-// breakpoint existed in unwrap(), then calling `next` would (when stopped at line 27) would stop
-// in unwrap() instead of stepping over the function invocation. By making sure that `s` is
-// contained in the output, after calling `next` just once, we can be sure that we did not stop in
-// unwrap(). (The testing framework doesn't allow for checking that some text is *not* contained in
-// the output, which is why we have to make the test in this kind of roundabout way)
-fn bar() -> int {
- let s = Some(5).unwrap();
- s
-}
-
-fn main() {
- let _ = bar();
-}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// aux-build:issue13213aux.rs
-extern crate issue13213aux;
-
-// compile-flags:-g
-
-// This tests make sure that we get no linker error when using a completely inlined static. Some
-// statics that are marked with AvailableExternallyLinkage in the importing crate, may actually not
-// be available because they have been optimized out from the exporting crate.
-fn main() {
- let b: issue13213aux::S = issue13213aux::A;
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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:--debuginfo=1
-
-pub trait TraitWithDefaultMethod {
- fn method(self) {
- ()
- }
-}
-
-struct MyStruct;
-
-impl TraitWithDefaultMethod for MyStruct { }
-
-pub fn main() {
- MyStruct.method();
-}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// FIRST ITERATION
-// debugger:finish
-// debugger:print x
-// check:$1 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = -1
-// debugger:continue
-
-// SECOND ITERATION
-// debugger:finish
-// debugger:print x
-// check:$3 = 2
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = -2
-// debugger:continue
-
-// THIRD ITERATION
-// debugger:finish
-// debugger:print x
-// check:$5 = 3
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = -3
-// debugger:continue
-
-// AFTER LOOP
-// debugger:finish
-// debugger:print x
-// check:$7 = 1000000
-// debugger:continue
-
-fn main() {
-
- let range = [1, 2, 3];
-
- let x = 1000000; // wan meeeljen doollaars!
-
- for &x in range.iter() {
- zzz();
- sentinel();
-
- let x = -1 * x;
-
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// BEFORE if
-// debugger:finish
-// debugger:print x
-// check:$1 = 999
-// debugger:print y
-// check:$2 = -1
-// debugger:continue
-
-// AT BEGINNING of 'then' block
-// debugger:finish
-// debugger:print x
-// check:$3 = 999
-// debugger:print y
-// check:$4 = -1
-// debugger:continue
-
-// AFTER 1st redeclaration of 'x'
-// debugger:finish
-// debugger:print x
-// check:$5 = 1001
-// debugger:print y
-// check:$6 = -1
-// debugger:continue
-
-// AFTER 2st redeclaration of 'x'
-// debugger:finish
-// debugger:print x
-// check:$7 = 1002
-// debugger:print y
-// check:$8 = 1003
-// debugger:continue
-
-// AFTER 1st if expression
-// debugger:finish
-// debugger:print x
-// check:$9 = 999
-// debugger:print y
-// check:$10 = -1
-// debugger:continue
-
-// BEGINNING of else branch
-// debugger:finish
-// debugger:print x
-// check:$11 = 999
-// debugger:print y
-// check:$12 = -1
-// debugger:continue
-
-// BEGINNING of else branch
-// debugger:finish
-// debugger:print x
-// check:$13 = 1004
-// debugger:print y
-// check:$14 = 1005
-// debugger:continue
-
-// BEGINNING of else branch
-// debugger:finish
-// debugger:print x
-// check:$15 = 999
-// debugger:print y
-// check:$16 = -1
-// debugger:continue
-
-fn main() {
-
- let x = 999;
- let y = -1;
-
- zzz();
- sentinel();
-
- if x < 1000 {
- zzz();
- sentinel();
-
- let x = 1001;
-
- zzz();
- sentinel();
-
- let x = 1002;
- let y = 1003;
- zzz();
- sentinel();
- } else {
- unreachable!();
- }
-
- zzz();
- sentinel();
-
- if x > 1000 {
- unreachable!();
- } else {
- zzz();
- sentinel();
-
- let x = 1004;
- let y = 1005;
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print shadowed
-// check:$1 = 231
-// debugger:print not_shadowed
-// check:$2 = 232
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$3 = 233
-// debugger:print not_shadowed
-// check:$4 = 232
-// debugger:print local_to_arm
-// check:$5 = 234
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$6 = 236
-// debugger:print not_shadowed
-// check:$7 = 232
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$8 = 237
-// debugger:print not_shadowed
-// check:$9 = 232
-// debugger:print local_to_arm
-// check:$10 = 238
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$11 = 239
-// debugger:print not_shadowed
-// check:$12 = 232
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$13 = 241
-// debugger:print not_shadowed
-// check:$14 = 232
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$15 = 243
-// debugger:print *local_to_arm
-// check:$16 = 244
-// debugger:continue
-
-// debugger:finish
-// debugger:print shadowed
-// check:$17 = 231
-// debugger:print not_shadowed
-// check:$18 = 232
-// debugger:continue
-
-struct Struct {
- x: int,
- y: int
-}
-
-fn main() {
-
- let shadowed = 231;
- let not_shadowed = 232;
-
- zzz();
- sentinel();
-
- match (233, 234) {
- (shadowed, local_to_arm) => {
-
- zzz();
- sentinel();
- }
- }
-
- match (235, 236) {
- // with literal
- (235, shadowed) => {
-
- zzz();
- sentinel();
- }
- _ => {}
- }
-
- match Struct { x: 237, y: 238 } {
- Struct { x: shadowed, y: local_to_arm } => {
-
- zzz();
- sentinel();
- }
- }
-
- match Struct { x: 239, y: 240 } {
- // ignored field
- Struct { x: shadowed, .. } => {
-
- zzz();
- sentinel();
- }
- }
-
- match Struct { x: 241, y: 242 } {
- // with literal
- Struct { x: shadowed, y: 242 } => {
-
- zzz();
- sentinel();
- }
- _ => {}
- }
-
- match (243, 244) {
- (shadowed, ref local_to_arm) => {
-
- zzz();
- sentinel();
- }
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:--debuginfo=1
-// debugger:run
-
-// Nothing to do here really, just make sure it compiles. See issue #8513.
-fn main() {
- let _ = ||();
- let _ = range(1u,3).map(|_| 5);
-}
-
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 1000
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 2.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = false
-// debugger:continue
-
-fn main() {
-
- let x = false;
-
- zzz();
- sentinel();
-
- let stack_closure: |int| = |x| {
- zzz();
- sentinel();
-
- let x = 2.5;
-
- zzz();
- sentinel();
-
- let x = true;
-
- zzz();
- sentinel();
- };
-
- zzz();
- sentinel();
-
- stack_closure(1000);
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// FIRST ITERATION
-// debugger:finish
-// debugger:print x
-// check:$1 = 0
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 101
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 101
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = -987
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = 101
-// debugger:continue
-
-
-// SECOND ITERATION
-// debugger:finish
-// debugger:print x
-// check:$7 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$8 = 2
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$9 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$10 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$11 = -987
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$12 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$13 = 2
-// debugger:continue
-
-fn main() {
-
- let mut x = 0;
-
- loop {
- if x >= 2 {
- break;
- }
-
- zzz();
- sentinel();
-
- x += 1;
- zzz();
- sentinel();
-
- // Shadow x
- let x = x + 100;
- zzz();
- sentinel();
-
- // open scope within loop's top level scope
- {
- zzz();
- sentinel();
-
- let x = -987;
-
- zzz();
- sentinel();
- }
-
- // Check that we get the x before the inner scope again
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 1000
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 2.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = false
-// debugger:continue
-
-fn main() {
-
- let x = false;
-
- zzz();
- sentinel();
-
- let unique_closure: proc(int) = proc(x) {
- zzz();
- sentinel();
-
- let x = 2.5;
-
- zzz();
- sentinel();
-
- let x = true;
-
- zzz();
- sentinel();
- };
-
- zzz();
- sentinel();
-
- unique_closure(1000);
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// FIRST ITERATION
-// debugger:finish
-// debugger:print x
-// check:$1 = 0
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 101
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 101
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = -987
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = 101
-// debugger:continue
-
-
-// SECOND ITERATION
-// debugger:finish
-// debugger:print x
-// check:$7 = 1
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$8 = 2
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$9 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$10 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$11 = -987
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$12 = 102
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$13 = 2
-// debugger:continue
-
-fn main() {
-
- let mut x = 0;
-
- while x < 2 {
- zzz();
- sentinel();
-
- x += 1;
- zzz();
- sentinel();
-
- // Shadow x
- let x = x + 100;
- zzz();
- sentinel();
-
- // open scope within loop's top level scope
- {
- zzz();
- sentinel();
-
- let x = -987;
-
- zzz();
- sentinel();
- }
-
- // Check that we get the x before the inner scope again
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print a
-// check:$1 = 10
-// debugger:print b
-// check:$2 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$3 = 890242
-// debugger:print b
-// check:$4 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$5 = 10
-// debugger:print b
-// check:$6 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$7 = 102
-// debugger:print b
-// check:$8 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$9 = 110
-// debugger:print b
-// check:$10 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$11 = 10
-// debugger:print b
-// check:$12 = 34
-// debugger:continue
-
-// debugger:finish
-// debugger:print a
-// check:$13 = 10
-// debugger:print b
-// check:$14 = 34
-// debugger:print c
-// check:$15 = 400
-// debugger:continue
-
-#![feature(macro_rules)]
-
-macro_rules! trivial(
- ($e1:expr) => ($e1)
-)
-
-macro_rules! no_new_scope(
- ($e1:expr) => (($e1 + 2) - 1)
-)
-
-macro_rules! new_scope(
- () => ({
- let a = 890242;
- zzz();
- sentinel();
- })
-)
-
-macro_rules! shadow_within_macro(
- ($e1:expr) => ({
- let a = $e1 + 2;
-
- zzz();
- sentinel();
-
- let a = $e1 + 10;
-
- zzz();
- sentinel();
- })
-)
-
-
-macro_rules! dup_expr(
- ($e1:expr) => (($e1) + ($e1))
-)
-
-
-fn main() {
-
- let a = trivial!(10);
- let b = no_new_scope!(33);
-
- zzz();
- sentinel();
-
- new_scope!();
-
- zzz();
- sentinel();
-
- shadow_within_macro!(100);
-
- zzz();
- sentinel();
-
- let c = dup_expr!(10 * 20);
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$1 = 0
-
-// STRUCT EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$2 = -1
-// debugger:print ten
-// check:$3 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$4 = 11
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$5 = 1
-// debugger:print ten
-// check:$6 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$7 = -1
-// debugger:print ten
-// check:$8 = 10
-// debugger:continue
-
-// FUNCTION CALL
-// debugger:finish
-// debugger:print val
-// check:$9 = -1
-// debugger:print ten
-// check:$10 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$11 = 12
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$12 = 2
-// debugger:print ten
-// check:$13 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$14 = -1
-// debugger:print ten
-// check:$15 = 10
-// debugger:continue
-
-// TUPLE EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$16 = -1
-// debugger:print ten
-// check:$17 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$18 = 13
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$19 = 3
-// debugger:print ten
-// check:$20 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$21 = -1
-// debugger:print ten
-// check:$22 = 10
-// debugger:continue
-
-// VEC EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$23 = -1
-// debugger:print ten
-// check:$24 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$25 = 14
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$26 = 4
-// debugger:print ten
-// check:$27 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$28 = -1
-// debugger:print ten
-// check:$29 = 10
-// debugger:continue
-
-// REPEAT VEC EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$30 = -1
-// debugger:print ten
-// check:$31 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$32 = 15
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$33 = 5
-// debugger:print ten
-// check:$34 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$35 = -1
-// debugger:print ten
-// check:$36 = 10
-// debugger:continue
-
-// ASSIGNMENT EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$37 = -1
-// debugger:print ten
-// check:$38 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$39 = 16
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$40 = 6
-// debugger:print ten
-// check:$41 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$42 = -1
-// debugger:print ten
-// check:$43 = 10
-// debugger:continue
-
-
-// ARITHMETIC EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$44 = -1
-// debugger:print ten
-// check:$45 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$46 = 17
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$47 = 7
-// debugger:print ten
-// check:$48 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$49 = -1
-// debugger:print ten
-// check:$50 = 10
-// debugger:continue
-
-// INDEX EXPRESSION
-// debugger:finish
-// debugger:print val
-// check:$51 = -1
-// debugger:print ten
-// check:$52 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$53 = 18
-// debugger:print 'lexical-scopes-in-block-expression::MUT_INT'
-// check:$54 = 8
-// debugger:print ten
-// check:$55 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print val
-// check:$56 = -1
-// debugger:print ten
-// check:$57 = 10
-// debugger:continue
-
-#![allow(unused_variable)]
-#![allow(dead_assignment)]
-
-static mut MUT_INT: int = 0;
-
-struct Point {
- x: int,
- y: int
-}
-
-fn a_function(x: int) -> int {
- x + 1
-}
-
-fn main() {
-
- let val = -1;
- let ten = 10;
-
- // surrounded by struct expression
- let point = Point {
- x: {
- zzz();
- sentinel();
-
- let val = ten + 1;
- unsafe {MUT_INT = 1;};
-
- zzz();
- sentinel();
-
- val
- },
- y: 10
- };
-
- zzz();
- sentinel();
-
- // surrounded by function call
- let _ = a_function({
- zzz();
- sentinel();
-
- let val = ten + 2;
- unsafe {MUT_INT = 2;};
-
- zzz();
- sentinel();
-
- val
- });
-
- zzz();
- sentinel();
-
-
- // surrounded by tup
- let _ = ({
- zzz();
- sentinel();
-
- let val = ten + 3;
- unsafe {MUT_INT = 3;};
-
- zzz();
- sentinel();
-
- val
- }, 0);
-
- zzz();
- sentinel();
-
- // surrounded by vec
- let _ = [{
- zzz();
- sentinel();
-
- let val = ten + 4;
- unsafe {MUT_INT = 4;};
-
- zzz();
- sentinel();
-
- val
- }, 0, 0];
-
- zzz();
- sentinel();
-
- // surrounded by repeat vec
- let _ = [{
- zzz();
- sentinel();
-
- let val = ten + 5;
- unsafe {MUT_INT = 5;};
-
- zzz();
- sentinel();
-
- val
- }, ..10];
-
- zzz();
- sentinel();
-
- // assignment expression
- let mut var = 0;
- var = {
- zzz();
- sentinel();
-
- let val = ten + 6;
- unsafe {MUT_INT = 6;};
-
- zzz();
- sentinel();
-
- val
- };
-
- zzz();
- sentinel();
-
- // arithmetic expression
- var = 10 + -{
- zzz();
- sentinel();
-
- let val = ten + 7;
- unsafe {MUT_INT = 7;};
-
- zzz();
- sentinel();
-
- val
- } * 5;
-
- zzz();
- sentinel();
-
- // index expression
- let a_vector = [10, ..20];
- let _ = a_vector[{
- zzz();
- sentinel();
-
- let val = ten + 8;
- unsafe {MUT_INT = 8;};
-
- zzz();
- sentinel();
-
- val as uint
- }];
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:--debuginfo=1
-
-// Make sure functions have proper names
-// debugger:info functions
-// check:[...]void[...]main([...]);
-// check:[...]void[...]some_function([...]);
-// check:[...]void[...]some_other_function([...]);
-// check:[...]void[...]zzz([...]);
-
-// debugger:rbreak zzz
-// debugger:run
-
-// Make sure there is no information about locals
-// debugger:finish
-// debugger:info locals
-// check:No locals.
-// debugger:continue
-
-
-#![allow(unused_variable)]
-
-struct Struct {
- a: i64,
- b: i32
-}
-
-fn main() {
- some_function(101, 202);
- some_other_function(1, 2);
-}
-
-
-fn zzz() {()}
-
-fn some_function(a: int, b: int) {
- let some_variable = Struct { a: 11, b: 22 };
- let some_other_variable = 23;
- zzz();
-}
-
-fn some_other_function(a: int, b: int) -> bool { true }
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print the_a->val
-// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
-
-// debugger:print the_b->val
-// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
-
-// debugger:print univariant->val
-// check:$3 = {-9747455}
-
-#![allow(unused_variable)]
-#![feature(struct_variant, managed_boxes)]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
- TheA { x: i64, y: i64 },
- TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
- TheOnlyCase(i64)
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let the_a = @TheA { x: 0, y: 8970181431921507452 };
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let the_b = @TheB (0, 286331153, 286331153);
-
- let univariant = @TheOnlyCase(-9747455);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print unique.ptr[0]->val
-// check:$1 = 10
-
-// debugger:print unique.ptr[1]->val
-// check:$2 = 11
-
-// debugger:print unique.ptr[2]->val
-// check:$3 = 12
-
-// debugger:print unique.ptr[3]->val
-// check:$4 = 13
-
-#![allow(unused_variable)]
-
-fn main() {
-
- let unique: Vec<@i64> = vec!(@10, @11, @12, @13);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *ordinary_unique
-// check:$1 = {-1, -2}
-
-// debugger:print managed_within_unique->x
-// check:$2 = -3
-
-// debugger:print managed_within_unique->y->val
-// check:$3 = -4
-
-#![allow(unused_variable)]
-
-struct ContainsManaged {
- x: int,
- y: @int
-}
-
-fn main() {
- let ordinary_unique = box() (-1, -2);
-
- let managed_within_unique = box ContainsManaged { x: -3, y: @-4 };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {{Variant2, [...]}, {Variant2, 117901063}}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {{Variant2, [...]}, {Variant2, 117901063}}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-#![feature(struct_variant)]
-
-enum Enum {
- Variant1 { x: u16, y: u16 },
- Variant2 (u32)
-}
-
-impl Enum {
-
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-}
-
-fn main() {
- let stack = Variant2(117901063);
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box Variant1{ x: 1799, y: 1799 };
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = {8888, -8888}}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = {8888, -8888}}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 1234.5}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 1234.5}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 1234.5}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-struct Struct<T> {
- x: T
-}
-
-impl<T> Struct<T> {
-
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-}
-
-fn main() {
- let stack = Struct { x: (8888_u32, -8888_i32) };
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box Struct { x: 1234.5 };
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = 100}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = 100}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 200}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 200}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 200}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-struct Struct {
- x: int
-}
-
-impl Struct {
-
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-}
-
-fn main() {
- let stack = Struct { x: 100 };
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box Struct { x: 200 };
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = 100}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = 100}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 200}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 200}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 200}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-struct Struct {
- x: int
-}
-
-trait Trait {
- fn self_by_ref(&self, arg1: int, arg2: int) -> int;
- fn self_by_val(self, arg1: int, arg2: int) -> int;
- fn self_owned(~self, arg1: int, arg2: int) -> int;
-}
-
-impl Trait for Struct {
-
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- self.x + arg1 + arg2
- }
-}
-
-fn main() {
- let stack = Struct { x: 100 };
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box Struct { x: 200 };
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {100, -100.5}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {100, -100.5}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {200, -200.5}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {200, -200.5}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {200, -200.5}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-struct TupleStruct(int, f64);
-
-impl TupleStruct {
-
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-}
-
-fn main() {
- let stack = TupleStruct(100, -100.5);
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box TupleStruct(200, -200.5);
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print abc
-// check:$1 = 10101
-// debugger:continue
-
-// debugger:finish
-// debugger:print abc
-// check:$2 = 20202
-// debugger:continue
-
-// debugger:finish
-// debugger:print abc
-// check:$3 = 30303
-
-#![allow(unused_variable)]
-
-fn function_one() {
- let abc = 10101;
- zzz();
-}
-
-fn function_two() {
- let abc = 20202;
- zzz();
-}
-
-
-fn function_three() {
- let abc = 30303;
- zzz();
-}
-
-
-fn main() {
- function_one();
- function_two();
- function_three();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print a
-// check:$1 = 10101
-// debugger:continue
-
-// debugger:finish
-// debugger:print b
-// check:$2 = 20202
-// debugger:continue
-
-// debugger:finish
-// debugger:print c
-// check:$3 = 30303
-
-#![allow(unused_variable)]
-
-fn function_one() {
- let a = 10101;
- zzz();
-}
-
-fn function_two() {
- let b = 20202;
- zzz();
-}
-
-
-fn function_three() {
- let c = 30303;
- zzz();
-}
-
-
-fn main() {
- function_one();
- function_two();
- function_three();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:print y
-// check:$2 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 10
-// debugger:print y
-// check:$4 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = 10.5
-// debugger:print y
-// check:$6 = 20
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$7 = true
-// debugger:print y
-// check:$8 = 2220
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$9 = 203203.5
-// debugger:print y
-// check:$10 = 2220
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$11 = 10.5
-// debugger:print y
-// check:$12 = 20
-// debugger:continue
-
-fn main() {
- let x = false;
- let y = true;
-
- zzz();
- sentinel();
-
- let x = 10;
-
- zzz();
- sentinel();
-
- let x = 10.5;
- let y = 20;
-
- zzz();
- sentinel();
-
- {
- let x = true;
- let y = 2220;
-
- zzz();
- sentinel();
-
- let x = 203203.5;
-
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print first
-// check:$1 = {<No data fields>}
-
-// debugger:print second
-// check:$2 = {<No data fields>}
-
-#![allow(unused_variable)]
-
-enum ANilEnum {}
-enum AnotherNilEnum {}
-
-// I (mw) am not sure this test case makes much sense...
-// Also, it relies on some implementation details:
-// 1. That empty enums as well as '()' are represented as empty structs
-// 2. That gdb prints the string "{<No data fields>}" for empty structs (which may change some time)
-fn main() {
- unsafe {
- let first: ANilEnum = std::cast::transmute(());
- let second: AnotherNilEnum = std::cast::transmute(());
-
- zzz();
- }
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print some
-// check:$1 = {0x12345678}
-
-// debugger:print none
-// check:$2 = {0x0}
-
-// debugger:print full
-// check:$3 = {454545, 0x87654321, 9988}
-
-// debugger:print empty->discr
-// check:$4 = (int *) 0x0
-
-// debugger:print droid
-// check:$5 = {id = 675675, range = 10000001, internals = 0x43218765}
-
-// debugger:print void_droid->internals
-// check:$6 = (int *) 0x0
-
-// debugger:continue
-
-#![feature(struct_variant)]
-
-// If a struct has exactly two variants, one of them is empty, and the other one
-// contains a non-nullable pointer, then this value is used as the discriminator.
-// The test cases in this file make sure that something readable is generated for
-// this kind of types.
-// Unfortunately (for these test cases) the content of the non-discriminant fields
-// in the null-case is not defined. So we just read the discriminator field in
-// this case (by casting the value to a memory-equivalent struct).
-
-enum MoreFields<'a> {
- Full(u32, &'a int, i16),
- Empty
-}
-
-struct MoreFieldsRepr<'a> {
- a: u32,
- discr: &'a int,
- b: i16
-}
-
-enum NamedFields<'a> {
- Droid { id: i32, range: i64, internals: &'a int },
- Void
-}
-
-struct NamedFieldsRepr<'a> {
- id: i32,
- range: i64,
- internals: &'a int
-}
-
-fn main() {
-
- let some: Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) });
- let none: Option<&u32> = None;
-
- let full = Full(454545, unsafe { std::cast::transmute(0x87654321) }, 9988);
-
- let int_val = 0;
- let empty: &MoreFieldsRepr = unsafe { std::cast::transmute(&Empty) };
-
- let droid = Droid {
- id: 675675,
- range: 10000001,
- internals: unsafe { std::cast::transmute(0x43218765) }
- };
-
- let void_droid: &NamedFieldsRepr = unsafe { std::cast::transmute(&Void) };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print packed
-// check:$1 = {x = 123, y = 234, z = 345}
-
-// debugger:print packedInPacked
-// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
-
-// debugger:print packedInUnpacked
-// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
-
-// debugger:print unpackedInPacked
-// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210}
-
-
-// debugger:print packedInPackedWithDrop
-// check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}}
-
-// debugger:print packedInUnpackedWithDrop
-// check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}}
-
-// debugger:print unpackedInPackedWithDrop
-// check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21}
-
-// debugger:print deeplyNested
-// check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}}
-
-#![allow(unused_variable)]
-
-#[packed]
-struct Packed {
- x: i16,
- y: i32,
- z: i64
-}
-
-impl Drop for Packed {
- fn drop(&mut self) {}
-}
-
-#[packed]
-struct PackedInPacked {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-struct PackedInUnpacked {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-struct Unpacked {
- x: i64,
- y: i32,
- z: i16
-}
-
-impl Drop for Unpacked {
- fn drop(&mut self) {}
-}
-
-#[packed]
-struct UnpackedInPacked {
- a: i16,
- b: Unpacked,
- c: Unpacked,
- d: i64
-}
-
-#[packed]
-struct PackedInPackedWithDrop {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-impl Drop for PackedInPackedWithDrop {
- fn drop(&mut self) {}
-}
-
-struct PackedInUnpackedWithDrop {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-impl Drop for PackedInUnpackedWithDrop {
- fn drop(&mut self) {}
-}
-
-#[packed]
-struct UnpackedInPackedWithDrop {
- a: i16,
- b: Unpacked,
- c: Unpacked,
- d: i64
-}
-
-impl Drop for UnpackedInPackedWithDrop {
- fn drop(&mut self) {}
-}
-
-struct DeeplyNested {
- a: PackedInPacked,
- b: UnpackedInPackedWithDrop,
- c: PackedInUnpacked,
- d: PackedInUnpackedWithDrop,
- e: UnpackedInPacked,
- f: PackedInPackedWithDrop
-}
-
-fn main() {
- let packed = Packed { x: 123, y: 234, z: 345 };
-
- let packedInPacked = PackedInPacked {
- a: 1111,
- b: Packed { x: 2222, y: 3333, z: 4444 },
- c: 5555,
- d: Packed { x: 6666, y: 7777, z: 8888 }
- };
-
- let packedInUnpacked = PackedInUnpacked {
- a: -1111,
- b: Packed { x: -2222, y: -3333, z: -4444 },
- c: -5555,
- d: Packed { x: -6666, y: -7777, z: -8888 }
- };
-
- let unpackedInPacked = UnpackedInPacked {
- a: 987,
- b: Unpacked { x: 876, y: 765, z: 654 },
- c: Unpacked { x: 543, y: 432, z: 321 },
- d: 210
- };
-
- let packedInPackedWithDrop = PackedInPackedWithDrop {
- a: 11,
- b: Packed { x: 22, y: 33, z: 44 },
- c: 55,
- d: Packed { x: 66, y: 77, z: 88 }
- };
-
- let packedInUnpackedWithDrop = PackedInUnpackedWithDrop {
- a: -11,
- b: Packed { x: -22, y: -33, z: -44 },
- c: -55,
- d: Packed { x: -66, y: -77, z: -88 }
- };
-
- let unpackedInPackedWithDrop = UnpackedInPackedWithDrop {
- a: 98,
- b: Unpacked { x: 87, y: 76, z: 65 },
- c: Unpacked { x: 54, y: 43, z: 32 },
- d: 21
- };
-
- let deeplyNested = DeeplyNested {
- a: PackedInPacked {
- a: 1,
- b: Packed { x: 2, y: 3, z: 4 },
- c: 5,
- d: Packed { x: 6, y: 7, z: 8 }
- },
- b: UnpackedInPackedWithDrop {
- a: 9,
- b: Unpacked { x: 10, y: 11, z: 12 },
- c: Unpacked { x: 13, y: 14, z: 15 },
- d: 16
- },
- c: PackedInUnpacked {
- a: 17,
- b: Packed { x: 18, y: 19, z: 20 },
- c: 21,
- d: Packed { x: 22, y: 23, z: 24 }
- },
- d: PackedInUnpackedWithDrop {
- a: 25,
- b: Packed { x: 26, y: 27, z: 28 },
- c: 29,
- d: Packed { x: 30, y: 31, z: 32 }
- },
- e: UnpackedInPacked {
- a: 33,
- b: Unpacked { x: 34, y: 35, z: 36 },
- c: Unpacked { x: 37, y: 38, z: 39 },
- d: 40
- },
- f: PackedInPackedWithDrop {
- a: 41,
- b: Packed { x: 42, y: 43, z: 44 },
- c: 45,
- d: Packed { x: 46, y: 47, z: 48 }
- }
- };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print packed
-// check:$1 = {x = 123, y = 234, z = 345}
-
-// debugger:print packedInPacked
-// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
-
-// debugger:print packedInUnpacked
-// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
-
-// debugger:print unpackedInPacked
-// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98}
-
-// debugger:print sizeof(packed)
-// check:$5 = 14
-
-// debugger:print sizeof(packedInPacked)
-// check:$6 = 40
-
-#![allow(unused_variable)]
-
-#[packed]
-struct Packed {
- x: i16,
- y: i32,
- z: i64
-}
-
-#[packed]
-struct PackedInPacked {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-// layout (64 bit): aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd..
-struct PackedInUnpacked {
- a: i32,
- b: Packed,
- c: i64,
- d: Packed
-}
-
-// layout (64 bit): xx.. yyyy zz.. .... wwww wwww
-struct Unpacked {
- x: i16,
- y: i32,
- z: i16,
- w: i64
-}
-
-// layout (64 bit): aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd
-#[packed]
-struct UnpackedInPacked {
- a: i16,
- b: Unpacked,
- c: Unpacked,
- d: i64
-}
-
-fn main() {
- let packed = Packed { x: 123, y: 234, z: 345 };
-
- let packedInPacked = PackedInPacked {
- a: 1111,
- b: Packed { x: 2222, y: 3333, z: 4444 },
- c: 5555,
- d: Packed { x: 6666, y: 7777, z: 8888 }
- };
-
- let packedInUnpacked = PackedInUnpacked {
- a: -1111,
- b: Packed { x: -2222, y: -3333, z: -4444 },
- c: -5555,
- d: Packed { x: -6666, y: -7777, z: -8888 }
- };
-
- let unpackedInPacked = UnpackedInPacked {
- a: 987,
- b: Unpacked { x: 876, y: 765, z: 654, w: 543 },
- c: Unpacked { x: 432, y: 321, z: 210, w: 109 },
- d: -98
- };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:run
-
-// Test whether compiling a recursive enum definition crashes debug info generation. The test case
-// is taken from issue #11083.
-
-#![allow(unused_variable)]
-
-pub struct Window<'a> {
- callbacks: WindowCallbacks<'a>
-}
-
-struct WindowCallbacks<'a> {
- pos_callback: Option<WindowPosCallback<'a>>,
-}
-
-pub type WindowPosCallback<'a> = |&Window, i32, i32|: 'a;
-
-fn main() {
- let x = WindowCallbacks { pos_callback: None };
-}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-#![feature(managed_boxes)]
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print stack_unique.value
-// check:$1 = 0
-// debugger:print stack_unique.next.val->value
-// check:$2 = 1
-
-// debugger:print unique_unique->value
-// check:$3 = 2
-// debugger:print unique_unique->next.val->value
-// check:$4 = 3
-
-// debugger:print box_unique->val.value
-// check:$5 = 4
-// debugger:print box_unique->val.next.val->value
-// check:$6 = 5
-
-// debugger:print vec_unique[0].value
-// check:$7 = 6.5
-// debugger:print vec_unique[0].next.val->value
-// check:$8 = 7.5
-
-// debugger:print borrowed_unique->value
-// check:$9 = 8.5
-// debugger:print borrowed_unique->next.val->value
-// check:$10 = 9.5
-
-// MANAGED
-// debugger:print stack_managed.value
-// check:$11 = 10
-// debugger:print stack_managed.next.val->val.value
-// check:$12 = 11
-
-// debugger:print unique_managed->value
-// check:$13 = 12
-// debugger:print unique_managed->next.val->val.value
-// check:$14 = 13
-
-// debugger:print box_managed->val.value
-// check:$15 = 14
-// debugger:print box_managed->val.next.val->val.value
-// check:$16 = 15
-
-// debugger:print vec_managed[0].value
-// check:$17 = 16.5
-// debugger:print vec_managed[0].next.val->val.value
-// check:$18 = 17.5
-
-// debugger:print borrowed_managed->value
-// check:$19 = 18.5
-// debugger:print borrowed_managed->next.val->val.value
-// check:$20 = 19.5
-
-// LONG CYCLE
-// debugger:print long_cycle1.value
-// check:$21 = 20
-// debugger:print long_cycle1.next->value
-// check:$22 = 21
-// debugger:print long_cycle1.next->next->value
-// check:$23 = 22
-// debugger:print long_cycle1.next->next->next->value
-// check:$24 = 23
-
-// debugger:print long_cycle2.value
-// check:$25 = 24
-// debugger:print long_cycle2.next->value
-// check:$26 = 25
-// debugger:print long_cycle2.next->next->value
-// check:$27 = 26
-
-// debugger:print long_cycle3.value
-// check:$28 = 27
-// debugger:print long_cycle3.next->value
-// check:$29 = 28
-
-// debugger:print long_cycle4.value
-// check:$30 = 29.5
-
-// debugger:print (*****long_cycle_w_anonymous_types).value
-// check:$31 = 30
-
-// debugger:print (*****((*****long_cycle_w_anonymous_types).next.val)).value
-// check:$32 = 31
-
-// debugger:continue
-
-#![allow(unused_variable)]
-#![feature(struct_variant)]
-
-
-enum Opt<T> {
- Empty,
- Val { val: T }
-}
-
-struct UniqueNode<T> {
- next: Opt<Box<UniqueNode<T>>>,
- value: T
-}
-
-struct ManagedNode<T> {
- next: Opt<@ManagedNode<T>>,
- value: T
-}
-
-struct LongCycle1<T> {
- next: Box<LongCycle2<T>>,
- value: T,
-}
-
-struct LongCycle2<T> {
- next: Box<LongCycle3<T>>,
- value: T,
-}
-
-struct LongCycle3<T> {
- next: Box<LongCycle4<T>>,
- value: T,
-}
-
-struct LongCycle4<T> {
- next: Option<Box<LongCycle1<T>>>,
- value: T,
-}
-
-struct LongCycleWithAnonymousTypes {
- next: Opt<Box<Box<Box<Box<Box<LongCycleWithAnonymousTypes>>>>>>,
- value: uint,
-}
-
-// This test case makes sure that recursive structs are properly described. The Node structs are
-// generic so that we can have a new type (that newly needs to be described) for the different
-// cases. The potential problem with recursive types is that the DI generation algorithm gets
-// trapped in an endless loop. To make sure, we actually test this in the different cases, we have
-// to operate on a new type each time, otherwise we would just hit the DI cache for all but the
-// first case.
-
-// The different cases below (stack_*, unique_*, box_*, etc) are set up so that the type description
-// algorithm will enter the type reference cycle that is created by a recursive definition from a
-// different context each time.
-
-// The "long cycle" cases are constructed to span a longer, indirect recursion cycle between types.
-// The different locals will cause the DI algorithm to enter the type reference cycle at different
-// points.
-
-fn main() {
- let stack_unique: UniqueNode<u16> = UniqueNode {
- next: Val {
- val: box UniqueNode {
- next: Empty,
- value: 1_u16,
- }
- },
- value: 0_u16,
- };
-
- let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
- next: Val {
- val: box UniqueNode {
- next: Empty,
- value: 3,
- }
- },
- value: 2,
- };
-
- let box_unique: @UniqueNode<u64> = @UniqueNode {
- next: Val {
- val: box UniqueNode {
- next: Empty,
- value: 5,
- }
- },
- value: 4,
- };
-
- let vec_unique: [UniqueNode<f32>, ..1] = [UniqueNode {
- next: Val {
- val: box UniqueNode {
- next: Empty,
- value: 7.5,
- }
- },
- value: 6.5,
- }];
-
- let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
- next: Val {
- val: box UniqueNode {
- next: Empty,
- value: 9.5,
- }
- },
- value: 8.5,
- };
-
- let stack_managed: ManagedNode<u16> = ManagedNode {
- next: Val {
- val: @ManagedNode {
- next: Empty,
- value: 11,
- }
- },
- value: 10,
- };
-
- let unique_managed: Box<ManagedNode<u32>> = box ManagedNode {
- next: Val {
- val: @ManagedNode {
- next: Empty,
- value: 13,
- }
- },
- value: 12,
- };
-
- let box_managed: @ManagedNode<u64> = @ManagedNode {
- next: Val {
- val: @ManagedNode {
- next: Empty,
- value: 15,
- }
- },
- value: 14,
- };
-
- let vec_managed: [ManagedNode<f32>, ..1] = [ManagedNode {
- next: Val {
- val: @ManagedNode {
- next: Empty,
- value: 17.5,
- }
- },
- value: 16.5,
- }];
-
- let borrowed_managed: &ManagedNode<f64> = &ManagedNode {
- next: Val {
- val: @ManagedNode {
- next: Empty,
- value: 19.5,
- }
- },
- value: 18.5,
- };
-
- // LONG CYCLE
- let long_cycle1: LongCycle1<u16> = LongCycle1 {
- next: box LongCycle2 {
- next: box LongCycle3 {
- next: box LongCycle4 {
- next: None,
- value: 23,
- },
- value: 22,
- },
- value: 21
- },
- value: 20
- };
-
- let long_cycle2: LongCycle2<u32> = LongCycle2 {
- next: box LongCycle3 {
- next: box LongCycle4 {
- next: None,
- value: 26,
- },
- value: 25,
- },
- value: 24
- };
-
- let long_cycle3: LongCycle3<u64> = LongCycle3 {
- next: box LongCycle4 {
- next: None,
- value: 28,
- },
- value: 27,
- };
-
- let long_cycle4: LongCycle4<f32> = LongCycle4 {
- next: None,
- value: 29.5,
- };
-
- // It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
- // `box` chain.
- let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
- next: Val {
- val: box box box box box LongCycleWithAnonymousTypes {
- next: Empty,
- value: 31,
- }
- },
- value: 30
- };
-
- zzz();
-}
-
-fn zzz() {()}
-
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = 100}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = 100}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 200}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 200}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 200}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10
-// debugger:continue
-
-struct Struct {
- x: int
-}
-
-trait Trait {
- fn self_by_ref(&self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_by_val(self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-
- fn self_owned(~self, arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-}
-
-impl Trait for Struct {}
-
-fn main() {
- let stack = Struct { x: 100 };
- let _ = stack.self_by_ref(-1, -2);
- let _ = stack.self_by_val(-3, -4);
-
- let owned = box Struct { x: 200 };
- let _ = owned.self_by_ref(-5, -6);
- let _ = owned.self_by_val(-7, -8);
- let _ = owned.self_owned(-9, -10);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STACK BY REF
-// debugger:finish
-// debugger:print *self
-// check:$1 = {x = 987}
-// debugger:print arg1
-// check:$2 = -1
-// debugger:print/d arg2
-// check:$3 = -2
-// debugger:continue
-
-// STACK BY VAL
-// debugger:finish
-// debugger:print self
-// check:$4 = {x = 987}
-// debugger:print arg1
-// check:$5 = -3
-// debugger:print arg2
-// check:$6 = -4
-// debugger:continue
-
-// OWNED BY REF
-// debugger:finish
-// debugger:print *self
-// check:$7 = {x = 879}
-// debugger:print arg1
-// check:$8 = -5
-// debugger:print arg2
-// check:$9 = -6
-// debugger:continue
-
-// OWNED BY VAL
-// debugger:finish
-// debugger:print self
-// check:$10 = {x = 879}
-// debugger:print arg1
-// check:$11 = -7
-// debugger:print arg2
-// check:$12 = -8
-// debugger:continue
-
-// OWNED MOVED
-// debugger:finish
-// debugger:print *self
-// check:$13 = {x = 879}
-// debugger:print arg1
-// check:$14 = -9
-// debugger:print arg2
-// check:$15 = -10.5
-// debugger:continue
-
-struct Struct {
- x: int
-}
-
-trait Trait {
-
- fn self_by_ref<T>(&self, arg1: int, arg2: T) -> int {
- zzz();
- arg1
- }
-
- fn self_by_val<T>(self, arg1: int, arg2: T) -> int {
- zzz();
- arg1
- }
-
- fn self_owned<T>(~self, arg1: int, arg2: T) -> int {
- zzz();
- arg1
- }
-}
-
-impl Trait for Struct {}
-
-fn main() {
- let stack = Struct { x: 987 };
- let _ = stack.self_by_ref(-1, -2_i8);
- let _ = stack.self_by_val(-3, -4_i16);
-
- let owned = box Struct { x: 879 };
- let _ = owned.self_by_ref(-5, -6_i32);
- let _ = owned.self_by_val(-7, -8_i64);
- let _ = owned.self_owned(-9, -10.5_f32);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:print y
-// check:$2 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 10
-// debugger:print y
-// check:$4 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = 10.5
-// debugger:print y
-// check:$6 = 20
-// debugger:continue
-
-fn a_function(x: bool, y: bool) {
- zzz();
- sentinel();
-
- let x = 10;
-
- zzz();
- sentinel();
-
- let x = 10.5;
- let y = 20;
-
- zzz();
- sentinel();
-}
-
-fn main() {
- a_function(false, true);
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:print y
-// check:$2 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 10
-// debugger:print y
-// check:$4 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = 10.5
-// debugger:print y
-// check:$6 = 20
-// debugger:continue
-
-fn main() {
- let x = false;
- let y = true;
-
- zzz();
- sentinel();
-
- let x = 10;
-
- zzz();
- sentinel();
-
- let x = 10.5;
- let y = 20;
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print/d i8x16
-// check:$1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
-// debugger:print/d i16x8
-// check:$2 = {16, 17, 18, 19, 20, 21, 22, 23}
-// debugger:print/d i32x4
-// check:$3 = {24, 25, 26, 27}
-// debugger:print/d i64x2
-// check:$4 = {28, 29}
-
-// debugger:print/d u8x16
-// check:$5 = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}
-// debugger:print/d u16x8
-// check:$6 = {46, 47, 48, 49, 50, 51, 52, 53}
-// debugger:print/d u32x4
-// check:$7 = {54, 55, 56, 57}
-// debugger:print/d u64x2
-// check:$8 = {58, 59}
-
-// debugger:print f32x4
-// check:$9 = {60.5, 61.5, 62.5, 63.5}
-// debugger:print f64x2
-// check:$10 = {64.5, 65.5}
-
-// debugger:continue
-
-#![allow(experimental)]
-#![allow(unused_variable)]
-
-use std::unstable::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
-
-fn main() {
-
- let i8x16 = i8x16(0i8, 1i8, 2i8, 3i8, 4i8, 5i8, 6i8, 7i8,
- 8i8, 9i8, 10i8, 11i8, 12i8, 13i8, 14i8, 15i8);
-
- let i16x8 = i16x8(16i16, 17i16, 18i16, 19i16, 20i16, 21i16, 22i16, 23i16);
- let i32x4 = i32x4(24i32, 25i32, 26i32, 27i32);
- let i64x2 = i64x2(28i64, 29i64);
-
- let u8x16 = u8x16(30u8, 31u8, 32u8, 33u8, 34u8, 35u8, 36u8, 37u8,
- 38u8, 39u8, 40u8, 41u8, 42u8, 43u8, 44u8, 45u8);
- let u16x8 = u16x8(46u16, 47u16, 48u16, 49u16, 50u16, 51u16, 52u16, 53u16);
- let u32x4 = u32x4(54u32, 55u32, 56u32, 57u32);
- let u64x2 = u64x2(58u64, 59u64);
-
- let f32x4 = f32x4(60.5f32, 61.5f32, 62.5f32, 63.5f32);
- let f64x2 = f64x2(64.5f64, 65.5f64);
-
- zzz();
-}
-
-#[inline(never)]
-fn zzz() { () }
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = 10.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = 10
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$7 = false
-// debugger:continue
-
-
-fn main() {
- let x = false;
-
- zzz();
- sentinel();
-
- {
- zzz();
- sentinel();
-
- let x = 10;
-
- zzz();
- sentinel();
-
- {
- zzz();
- sentinel();
-
- let x = 10.5;
-
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
- }
-
- zzz();
- sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-
-// debugger:print 'simple-struct::NO_PADDING_16'
-// check:$1 = {x = 1000, y = -1001}
-
-// debugger:print 'simple-struct::NO_PADDING_32'
-// check:$2 = {x = 1, y = 2, z = 3}
-
-// debugger:print 'simple-struct::NO_PADDING_64'
-// check:$3 = {x = 4, y = 5, z = 6}
-
-// debugger:print 'simple-struct::NO_PADDING_163264'
-// check:$4 = {a = 7, b = 8, c = 9, d = 10}
-
-// debugger:print 'simple-struct::INTERNAL_PADDING'
-// check:$5 = {x = 11, y = 12}
-
-// debugger:print 'simple-struct::PADDING_AT_END'
-// check:$6 = {x = 13, y = 14}
-
-// debugger:run
-// debugger:finish
-
-// debugger:print no_padding16
-// check:$7 = {x = 10000, y = -10001}
-
-// debugger:print no_padding32
-// check:$8 = {x = -10002, y = -10003.5, z = 10004}
-
-// debugger:print no_padding64
-// check:$9 = {x = -10005.5, y = 10006, z = 10007}
-
-// debugger:print no_padding163264
-// check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011}
-
-// debugger:print internal_padding
-// check:$11 = {x = 10012, y = -10013}
-
-// debugger:print padding_at_end
-// check:$12 = {x = -10014, y = 10015}
-
-// debugger:print 'simple-struct::NO_PADDING_16'
-// check:$13 = {x = 100, y = -101}
-
-// debugger:print 'simple-struct::NO_PADDING_32'
-// check:$14 = {x = -15, y = -16, z = 17}
-
-// debugger:print 'simple-struct::NO_PADDING_64'
-// check:$15 = {x = -18, y = 19, z = 20}
-
-// debugger:print 'simple-struct::NO_PADDING_163264'
-// check:$16 = {a = -21, b = 22, c = 23, d = 24}
-
-// debugger:print 'simple-struct::INTERNAL_PADDING'
-// check:$17 = {x = 25, y = -26}
-
-// debugger:print 'simple-struct::PADDING_AT_END'
-// check:$18 = {x = -27, y = 28}
-
-// debugger:print inheriting
-// check:$19 = {a = 10019, b = -10020, x = -10016, y = -10017.5, z = 10018}
-
-
-#![feature(struct_inherit)];
-#![allow(unused_variable)];
-#![allow(dead_code)];
-
-struct NoPadding16 {
- x: u16,
- y: i16
-}
-
-virtual struct NoPadding32 {
- x: i32,
- y: f32,
- z: u32
-}
-
-struct NoPadding64 {
- x: f64,
- y: i64,
- z: u64
-}
-
-struct NoPadding163264 {
- a: i16,
- b: u16,
- c: i32,
- d: u64
-}
-
-struct InternalPadding {
- x: u16,
- y: i64
-}
-
-struct PaddingAtEnd {
- x: i64,
- y: u16
-}
-
-static mut NO_PADDING_16: NoPadding16 = NoPadding16 {
- x: 1000,
- y: -1001
-};
-
-static mut NO_PADDING_32: NoPadding32 = NoPadding32 {
- x: 1,
- y: 2.0,
- z: 3
-};
-
-static mut NO_PADDING_64: NoPadding64 = NoPadding64 {
- x: 4.0,
- y: 5,
- z: 6
-};
-
-static mut NO_PADDING_163264: NoPadding163264 = NoPadding163264 {
- a: 7,
- b: 8,
- c: 9,
- d: 10
-};
-
-static mut INTERNAL_PADDING: InternalPadding = InternalPadding {
- x: 11,
- y: 12
-};
-
-static mut PADDING_AT_END: PaddingAtEnd = PaddingAtEnd {
- x: 13,
- y: 14
-};
-
-struct Inheriting : NoPadding32 {
- a: u16,
- b: i16
-}
-
-fn main() {
- let no_padding16 = NoPadding16 { x: 10000, y: -10001 };
- let no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 };
- let no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 };
- let no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 };
-
- let internal_padding = InternalPadding { x: 10012, y: -10013 };
- let padding_at_end = PaddingAtEnd { x: -10014, y: 10015 };
-
- let inheriting = Inheriting { a: 10019, b: -10020, x: -10016, y: -10017.5, z: 10018 };
-
- unsafe {
- NO_PADDING_16.x = 100;
- NO_PADDING_16.y = -101;
-
- NO_PADDING_32.x = -15;
- NO_PADDING_32.y = -16.0;
- NO_PADDING_32.z = 17;
-
- NO_PADDING_64.x = -18.0;
- NO_PADDING_64.y = 19;
- NO_PADDING_64.z = 20;
-
- NO_PADDING_163264.a = -21;
- NO_PADDING_163264.b = 22;
- NO_PADDING_163264.c = 23;
- NO_PADDING_163264.d = 24;
-
- INTERNAL_PADDING.x = 25;
- INTERNAL_PADDING.y = -26;
-
- PADDING_AT_END.x = -27;
- PADDING_AT_END.y = 28;
- }
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-
-// debugger:print/d 'simple-tuple::NO_PADDING_8'
-// check:$1 = {-50, 50}
-// debugger:print 'simple-tuple::NO_PADDING_16'
-// check:$2 = {-1, 2, 3}
-// debugger:print 'simple-tuple::NO_PADDING_32'
-// check:$3 = {4, 5, 6}
-// debugger:print 'simple-tuple::NO_PADDING_64'
-// check:$4 = {7, 8, 9}
-
-// debugger:print 'simple-tuple::INTERNAL_PADDING_1'
-// check:$5 = {10, 11}
-// debugger:print 'simple-tuple::INTERNAL_PADDING_2'
-// check:$6 = {12, 13, 14, 15}
-
-// debugger:print 'simple-tuple::PADDING_AT_END'
-// check:$7 = {16, 17}
-
-// debugger:run
-// debugger:finish
-
-// debugger:print/d noPadding8
-// check:$8 = {-100, 100}
-// debugger:print noPadding16
-// check:$9 = {0, 1, 2}
-// debugger:print noPadding32
-// check:$10 = {3, 4.5, 5}
-// debugger:print noPadding64
-// check:$11 = {6, 7.5, 8}
-
-// debugger:print internalPadding1
-// check:$12 = {9, 10}
-// debugger:print internalPadding2
-// check:$13 = {11, 12, 13, 14}
-
-// debugger:print paddingAtEnd
-// check:$14 = {15, 16}
-
-// debugger:print/d 'simple-tuple::NO_PADDING_8'
-// check:$15 = {-127, 127}
-// debugger:print 'simple-tuple::NO_PADDING_16'
-// check:$16 = {-10, 10, 9}
-// debugger:print 'simple-tuple::NO_PADDING_32'
-// check:$17 = {14, 15, 16}
-// debugger:print 'simple-tuple::NO_PADDING_64'
-// check:$18 = {17, 18, 19}
-
-// debugger:print 'simple-tuple::INTERNAL_PADDING_1'
-// check:$19 = {110, 111}
-// debugger:print 'simple-tuple::INTERNAL_PADDING_2'
-// check:$20 = {112, 113, 114, 115}
-
-// debugger:print 'simple-tuple::PADDING_AT_END'
-// check:$21 = {116, 117}
-
-#![allow(unused_variable)]
-#![allow(dead_code)]
-
-static mut NO_PADDING_8: (i8, u8) = (-50, 50);
-static mut NO_PADDING_16: (i16, i16, u16) = (-1, 2, 3);
-
-static mut NO_PADDING_32: (i32, f32, u32) = (4, 5.0, 6);
-static mut NO_PADDING_64: (i64, f64, u64) = (7, 8.0, 9);
-
-static mut INTERNAL_PADDING_1: (i16, i32) = (10, 11);
-static mut INTERNAL_PADDING_2: (i16, i32, u32, u64) = (12, 13, 14, 15);
-
-static mut PADDING_AT_END: (i32, i16) = (16, 17);
-
-fn main() {
- let noPadding8: (i8, u8) = (-100, 100);
- let noPadding16: (i16, i16, u16) = (0, 1, 2);
- let noPadding32: (i32, f32, u32) = (3, 4.5, 5);
- let noPadding64: (i64, f64, u64) = (6, 7.5, 8);
-
- let internalPadding1: (i16, i32) = (9, 10);
- let internalPadding2: (i16, i32, u32, u64) = (11, 12, 13, 14);
-
- let paddingAtEnd: (i32, i16) = (15, 16);
-
- unsafe {
- NO_PADDING_8 = (-127, 127);
- NO_PADDING_16 = (-10, 10, 9);
-
- NO_PADDING_32 = (14, 15.0, 16);
- NO_PADDING_64 = (17, 18.0, 19);
-
- INTERNAL_PADDING_1 = (110, 111);
- INTERNAL_PADDING_2 = (112, 113, 114, 115);
-
- PADDING_AT_END = (116, 117);
- }
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// STRUCT
-// debugger:finish
-// debugger:print arg1
-// check:$1 = 1
-// debugger:print arg2
-// check:$2 = 2
-// debugger:continue
-
-// ENUM
-// debugger:finish
-// debugger:print arg1
-// check:$3 = -3
-// debugger:print arg2
-// check:$4 = 4.5
-// debugger:print arg3
-// check:$5 = 5
-// debugger:continue
-
-#![feature(struct_variant)]
-
-struct Struct {
- x: int
-}
-
-impl Struct {
-
- fn static_method(arg1: int, arg2: int) -> int {
- zzz();
- arg1 + arg2
- }
-}
-
-enum Enum {
- Variant1 { x: int },
- Variant2,
- Variant3(f64, int, char),
-}
-
-impl Enum {
-
- fn static_method(arg1: int, arg2: f64, arg3: uint) -> int {
- zzz();
- arg1
- }
-}
-
-fn main() {
- Struct::static_method(1, 2);
- Enum::static_method(-3, 4.5, 5);
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print union on
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print case1
-// check:$1 = {{Case1, 0, {x = 2088533116, y = 2088533116, z = 31868}}, {Case1, 0, 8970181431921507452, 31868}}
-
-// debugger:print case2
-// check:$2 = {{Case2, 0, {x = 286331153, y = 286331153, z = 4369}}, {Case2, 0, 1229782938247303441, 4369}}
-
-// debugger:print univariant
-// check:$3 = {{x = 123, y = 456, z = 789}}
-
-#![allow(unused_variable)]
-
-struct Struct {
- x: u32,
- y: i32,
- z: i16
-}
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
- Case1(u64, Struct),
- Case2(u64, u64, i16)
-}
-
-enum Univariant {
- TheOnlyCase(Struct)
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let case1 = Case1(0, Struct { x: 2088533116, y: 2088533116, z: 31868 });
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let case2 = Case2(0, 1229782938247303441, 4369);
-
- let univariant = TheOnlyCase(Struct { x: 123, y: 456, z: 789 });
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print three_simple_structs
-// check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}}
-
-// debugger:print internal_padding_parent
-// check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}}
-
-// debugger:print padding_at_end_parent
-// check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}}
-
-#![allow(unused_variable)]
-
-struct Simple {
- x: i32
-}
-
-struct InternalPadding {
- x: i32,
- y: i64
-}
-
-struct PaddingAtEnd {
- x: i64,
- y: i32
-}
-
-struct ThreeSimpleStructs {
- x: Simple,
- y: Simple,
- z: Simple
-}
-
-struct InternalPaddingParent {
- x: InternalPadding,
- y: InternalPadding,
- z: InternalPadding
-}
-
-struct PaddingAtEndParent {
- x: PaddingAtEnd,
- y: PaddingAtEnd,
- z: PaddingAtEnd
-}
-
-struct Mixed {
- x: PaddingAtEnd,
- y: InternalPadding,
- z: Simple,
- w: i16
-}
-
-struct Bag {
- x: Simple
-}
-
-struct BagInBag {
- x: Bag
-}
-
-struct ThatsJustOverkill {
- x: BagInBag
-}
-
-struct Tree {
- x: Simple,
- y: InternalPaddingParent,
- z: BagInBag
-}
-
-fn main() {
-
- let three_simple_structs = ThreeSimpleStructs {
- x: Simple { x: 1 },
- y: Simple { x: 2 },
- z: Simple { x: 3 }
- };
-
- let internal_padding_parent = InternalPaddingParent {
- x: InternalPadding { x: 4, y: 5 },
- y: InternalPadding { x: 6, y: 7 },
- z: InternalPadding { x: 8, y: 9 }
- };
-
- let padding_at_end_parent = PaddingAtEndParent {
- x: PaddingAtEnd { x: 10, y: 11 },
- y: PaddingAtEnd { x: 12, y: 13 },
- z: PaddingAtEnd { x: 14, y: 15 }
- };
-
- let mixed = Mixed {
- x: PaddingAtEnd { x: 16, y: 17 },
- y: InternalPadding { x: 18, y: 19 },
- z: Simple { x: 20 },
- w: 21
- };
-
- let bag = Bag { x: Simple { x: 22 } };
- let bag_in_bag = BagInBag {
- x: Bag {
- x: Simple { x: 23 }
- }
- };
-
- let tjo = ThatsJustOverkill {
- x: BagInBag {
- x: Bag {
- x: Simple { x: 24 }
- }
- }
- };
-
- let tree = Tree {
- x: Simple { x: 25 },
- y: InternalPaddingParent {
- x: InternalPadding { x: 26, y: 27 },
- y: InternalPadding { x: 28, y: 29 },
- z: InternalPadding { x: 30, y: 31 }
- },
- z: BagInBag {
- x: Bag {
- x: Simple { x: 32 }
- }
- }
- };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print union on
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print case1
-// check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
-
-// debugger:print case2
-// check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
-
-// debugger:print case3
-// check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
-
-// debugger:print univariant
-// check:$4 = {a = -1}
-
-#![allow(unused_variable)]
-#![feature(struct_variant)]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
- Case1 { a: u64, b: u16, c: u16, d: u16, e: u16},
- Case2 { a: u64, b: u32, c: u32},
- Case3 { a: u64, b: u64 }
-}
-
-enum Univariant {
- TheOnlyCase { a: i64 }
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let case2 = Case2 { a: 0, b: 286331153, c: 286331153 };
-
- // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
- // 0b01011001010110010101100101011001 = 1499027801
- // 0b0101100101011001 = 22873
- // 0b01011001 = 89
- let case3 = Case3 { a: 0, b: 6438275382588823897 };
-
- let univariant = TheOnlyCase { a: -1 };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print simple
-// check:$1 = {x = 10, y = 20}
-
-// debugger:print noDestructor
-// check:$2 = {a = {x = 10, y = 20}, guard = -1}
-
-// debugger:print withDestructor
-// check:$3 = {a = {x = 10, y = 20}, guard = -1}
-
-// debugger:print nested
-// check:$4 = {a = {a = {x = 7890, y = 9870}}}
-
-#![allow(unused_variable)]
-
-struct NoDestructor {
- x: i32,
- y: i64
-}
-
-struct WithDestructor {
- x: i32,
- y: i64
-}
-
-impl Drop for WithDestructor {
- fn drop(&mut self) {}
-}
-
-struct NoDestructorGuarded {
- a: NoDestructor,
- guard: i64
-}
-
-struct WithDestructorGuarded {
- a: WithDestructor,
- guard: i64
-}
-
-struct NestedInner {
- a: WithDestructor
-}
-
-impl Drop for NestedInner {
- fn drop(&mut self) {}
-}
-
-struct NestedOuter {
- a: NestedInner
-}
-
-
-// The compiler adds a 'destructed' boolean field to structs implementing Drop. This field is used
-// at runtime to prevent drop() to be executed more than once (see middle::trans::adt).
-// This field must be incorporated by the debug info generation. Otherwise the debugger assumes a
-// wrong size/layout for the struct.
-fn main() {
-
- let simple = WithDestructor { x: 10, y: 20 };
-
- let noDestructor = NoDestructorGuarded {
- a: NoDestructor { x: 10, y: 20 },
- guard: -1
- };
-
- // If the destructor flag field is not incorporated into the debug info for 'WithDestructor'
- // then the debugger will have an invalid offset for the field 'guard' and thus should not be
- // able to read its value correctly (dots are padding bytes, D is the boolean destructor flag):
- //
- // 64 bit
- //
- // NoDestructorGuarded = 0000....00000000FFFFFFFF
- // <--------------><------>
- // NoDestructor guard
- //
- //
- // withDestructorGuarded = 0000....00000000D.......FFFFFFFF
- // <--------------><------> // How debug info says it is
- // WithDestructor guard
- //
- // <----------------------><------> // How it actually is
- // WithDestructor guard
- //
- // 32 bit
- //
- // NoDestructorGuarded = 000000000000FFFFFFFF
- // <----------><------>
- // NoDestructor guard
- //
- //
- // withDestructorGuarded = 000000000000D...FFFFFFFF
- // <----------><------> // How debug info says it is
- // WithDestructor guard
- //
- // <--------------><------> // How it actually is
- // WithDestructor guard
- //
- let withDestructor = WithDestructorGuarded {
- a: WithDestructor { x: 10, y: 20 },
- guard: -1
- };
-
- // expected layout (64 bit) = xxxx....yyyyyyyyD.......D...
- // <--WithDestructor------>
- // <-------NestedInner-------->
- // <-------NestedOuter-------->
- let nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-some text to include in another file as string 1
\ No newline at end of file
+++ /dev/null
-some text to include in another file as string 2
\ No newline at end of file
+++ /dev/null
-some text to include in another file as string 3
\ No newline at end of file
+++ /dev/null
-// ignore-test
-
-// 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.
-//
-// 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:-g
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print arg1
-// check:$1 = 1000
-// debugger:print arg2
-// check:$2 = 0.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print arg1
-// check:$3 = 2000
-// debugger:print *arg2
-// check:$4 = {1, 2, 3}
-// debugger:continue
-
-
-struct Struct {
- x: int
-}
-
-trait Trait {
- fn generic_static_default_method<T>(arg1: int, arg2: T) -> int {
- zzz();
- arg1
- }
-}
-
-impl Trait for Struct {}
-
-fn main() {
-
- // Is this really how to use these?
- Trait::generic_static_default_method::<Struct, float>(1000, 0.5);
- Trait::generic_static_default_method::<Struct, &(int, int, int)>(2000, &(1, 2, 3));
-
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:run
-
-#![allow(unused_variable)]
-
-
-trait Trait {
- fn method(&self) -> int { 0 }
-}
-
-struct Struct {
- a: int,
- b: f64
-}
-
-impl Trait for Struct {}
-
-// There is no real test here yet. Just make sure that it compiles without crashing.
-fn main() {
- let stack_struct = Struct { a:0, b: 1.0 };
- let reference: &Trait = &stack_struct as &Trait;
- let unique: Box<Trait> = box Struct { a:2, b: 3.0 } as Box<Trait>;
-}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print no_padding1
-// check:$1 = {x = {0, 1}, y = 2, z = {3, 4, 5}}
-// debugger:print no_padding2
-// check:$2 = {x = {6, 7}, y = {{8, 9}, 10}}
-
-// debugger:print tuple_internal_padding
-// check:$3 = {x = {11, 12}, y = {13, 14}}
-// debugger:print struct_internal_padding
-// check:$4 = {x = {15, 16}, y = {17, 18}}
-// debugger:print both_internally_padded
-// check:$5 = {x = {19, 20, 21}, y = {22, 23}}
-
-// debugger:print single_tuple
-// check:$6 = {x = {24, 25, 26}}
-
-// debugger:print tuple_padded_at_end
-// check:$7 = {x = {27, 28}, y = {29, 30}}
-// debugger:print struct_padded_at_end
-// check:$8 = {x = {31, 32}, y = {33, 34}}
-// debugger:print both_padded_at_end
-// check:$9 = {x = {35, 36, 37}, y = {38, 39}}
-
-// debugger:print mixed_padding
-// check:$10 = {x = {{40, 41, 42}, {43, 44}}, y = {45, 46, 47, 48}}
-
-#![allow(unused_variable)]
-
-struct NoPadding1 {
- x: (i32, i32),
- y: i32,
- z: (i32, i32, i32)
-}
-
-struct NoPadding2 {
- x: (i32, i32),
- y: ((i32, i32), i32)
-}
-
-struct TupleInternalPadding {
- x: (i16, i32),
- y: (i32, i64)
-}
-
-struct StructInternalPadding {
- x: (i16, i16),
- y: (i64, i64)
-}
-
-struct BothInternallyPadded {
- x: (i16, i32, i32),
- y: (i32, i64)
-}
-
-struct SingleTuple {
- x: (i16, i32, i64)
-}
-
-struct TuplePaddedAtEnd {
- x: (i32, i16),
- y: (i64, i32)
-}
-
-struct StructPaddedAtEnd {
- x: (i64, i64),
- y: (i16, i16)
-}
-
-struct BothPaddedAtEnd {
- x: (i32, i32, i16),
- y: (i64, i32)
-}
-
-// Data-layout (padding signified by dots, one column = 2 bytes):
-// [a.bbc...ddddee..ffffg.hhi...]
-struct MixedPadding {
- x: ((i16, i32, i16), (i64, i32)),
- y: (i64, i16, i32, i16)
-}
-
-
-fn main() {
- let no_padding1 = NoPadding1 {
- x: (0, 1),
- y: 2,
- z: (3, 4, 5)
- };
-
- let no_padding2 = NoPadding2 {
- x: (6, 7),
- y: ((8, 9), 10)
- };
-
- let tuple_internal_padding = TupleInternalPadding {
- x: (11, 12),
- y: (13, 14)
- };
-
- let struct_internal_padding = StructInternalPadding {
- x: (15, 16),
- y: (17, 18)
- };
-
- let both_internally_padded = BothInternallyPadded {
- x: (19, 20, 21),
- y: (22, 23)
- };
-
- let single_tuple = SingleTuple {
- x: (24, 25, 26)
- };
-
- let tuple_padded_at_end = TuplePaddedAtEnd {
- x: (27, 28),
- y: (29, 30)
- };
-
- let struct_padded_at_end = StructPaddedAtEnd {
- x: (31, 32),
- y: (33, 34)
- };
-
- let both_padded_at_end = BothPaddedAtEnd {
- x: (35, 36, 37),
- y: (38, 39)
- };
-
- let mixed_padding = MixedPadding {
- x: ((40, 41, 42), (43, 44)),
- y: (45, 46, 47, 48)
- };
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print no_padding1
-// check:$1 = {{0, 1}, 2, 3}
-// debugger:print no_padding2
-// check:$2 = {4, {5, 6}, 7}
-// debugger:print no_padding3
-// check:$3 = {8, 9, {10, 11}}
-
-// debugger:print internal_padding1
-// check:$4 = {12, {13, 14}}
-// debugger:print internal_padding2
-// check:$5 = {15, {16, 17}}
-
-// debugger:print padding_at_end1
-// check:$6 = {18, {19, 20}}
-// debugger:print padding_at_end2
-// check:$7 = {{21, 22}, 23}
-
-#![allow(unused_variable)]
-
-fn main() {
- let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3);
- let no_padding2: (u32, (u32, u32), u32) = (4, (5, 6), 7);
- let no_padding3: (u32, u32, (u32, u32)) = (8, 9, (10, 11));
-
- let internal_padding1: (i16, (i32, i32)) = (12, (13, 14));
- let internal_padding2: (i16, (i16, i32)) = (15, (16, 17));
-
- let padding_at_end1: (i32, (i32, i16)) = (18, (19, 20));
- let padding_at_end2: ((i32, i16), i32) = ((21, 22), 23);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print no_padding16
-// check:$1 = {10000, -10001}
-
-// debugger:print no_padding32
-// check:$2 = {-10002, -10003.5, 10004}
-
-// debugger:print no_padding64
-// check:$3 = {-10005.5, 10006, 10007}
-
-// debugger:print no_padding163264
-// check:$4 = {-10008, 10009, 10010, 10011}
-
-// debugger:print internal_padding
-// check:$5 = {10012, -10013}
-
-// debugger:print padding_at_end
-// check:$6 = {-10014, 10015}
-
-
-// This test case mainly makes sure that no field names are generated for tuple structs (as opposed
-// to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
-// structs.
-
-struct NoPadding16(u16, i16);
-struct NoPadding32(i32, f32, u32);
-struct NoPadding64(f64, i64, u64);
-struct NoPadding163264(i16, u16, i32, u64);
-struct InternalPadding(u16, i64);
-struct PaddingAtEnd(i64, u16);
-
-fn main() {
- let no_padding16 = NoPadding16(10000, -10001);
- let no_padding32 = NoPadding32(-10002, -10003.5, 10004);
- let no_padding64 = NoPadding64(-10005.5, 10006, 10007);
- let no_padding163264 = NoPadding163264(-10008, 10009, 10010, 10011);
-
- let internal_padding = InternalPadding(10012, -10013);
- let padding_at_end = PaddingAtEnd(-10014, 10015);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-tidy-linelength
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print union on
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print case1
-// check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
-
-// debugger:print case2
-// check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
-
-// debugger:print case3
-// check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
-
-// debugger:print univariant
-// check:$4 = {-1}
-
-#![allow(unused_variable)]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum Regular {
- Case1(u64, u16, u16, u16, u16),
- Case2(u64, u32, u32),
- Case3(u64, u64)
-}
-
-enum Univariant {
- TheOnlyCase(i64)
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let case1 = Case1(0, 31868, 31868, 31868, 31868);
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let case2 = Case2(0, 286331153, 286331153);
-
- // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
- // 0b01011001010110010101100101011001 = 1499027801
- // 0b0101100101011001 = 22873
- // 0b01011001 = 89
- let case3 = Case3(0, 6438275382588823897);
-
- let univariant = TheOnlyCase(-1);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print *the_a
-// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
-
-// debugger:print *the_b
-// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
-
-// debugger:print *univariant
-// check:$3 = {123234}
-
-#![allow(unused_variable)]
-#![feature(struct_variant)]
-
-// The first element is to ensure proper alignment, irrespective of the machines word size. Since
-// the size of the discriminant value is machine dependent, this has be taken into account when
-// datatype layout should be predictable as in this case.
-enum ABC {
- TheA { x: i64, y: i64 },
- TheB (i64, i32, i32),
-}
-
-// This is a special case since it does not have the implicit discriminant field.
-enum Univariant {
- TheOnlyCase(i64)
-}
-
-fn main() {
-
- // In order to avoid endianess trouble all of the following test values consist of a single
- // repeated byte. This way each interpretation of the union should look the same, no matter if
- // this is a big or little endian machine.
-
- // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
- // 0b01111100011111000111110001111100 = 2088533116
- // 0b0111110001111100 = 31868
- // 0b01111100 = 124
- let the_a = box TheA { x: 0, y: 8970181431921507452 };
-
- // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
- // 0b00010001000100010001000100010001 = 286331153
- // 0b0001000100010001 = 4369
- // 0b00010001 = 17
- let the_b = box TheB (0, 286331153, 286331153);
-
- let univariant = box TheOnlyCase(123234);
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print variable
-// check:$1 = 1
-// debugger:print constant
-// check:$2 = 2
-// debugger:print a_struct
-// check:$3 = {a = -3, b = 4.5, c = 5}
-// debugger:print *struct_ref
-// check:$4 = {a = -3, b = 4.5, c = 5}
-// debugger:print *owned
-// check:$5 = 6
-// debugger:print managed->val
-// check:$6 = 7
-// debugger:print closure_local
-// check:$7 = 8
-// debugger:continue
-
-// debugger:finish
-// debugger:print variable
-// check:$8 = 1
-// debugger:print constant
-// check:$9 = 2
-// debugger:print a_struct
-// check:$10 = {a = -3, b = 4.5, c = 5}
-// debugger:print *struct_ref
-// check:$11 = {a = -3, b = 4.5, c = 5}
-// debugger:print *owned
-// check:$12 = 6
-// debugger:print managed->val
-// check:$13 = 7
-// debugger:print closure_local
-// check:$14 = 8
-// debugger:continue
-
-#![feature(managed_boxes)]
-#![allow(unused_variable)]
-
-struct Struct {
- a: int,
- b: f64,
- c: uint
-}
-
-fn main() {
- let mut variable = 1;
- let constant = 2;
-
- let a_struct = Struct {
- a: -3,
- b: 4.5,
- c: 5
- };
-
- let struct_ref = &a_struct;
- let owned = box 6;
- let managed = @7;
-
- let closure = || {
- let closure_local = 8;
-
- let nested_closure = || {
- zzz();
- variable = constant + a_struct.a + struct_ref.a + *owned + *managed + closure_local;
- };
-
- zzz();
-
- nested_closure();
- };
-
- closure();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print constant
-// check:$1 = 1
-// debugger:print a_struct
-// check:$2 = {a = -2, b = 3.5, c = 4}
-// debugger:print *owned
-// check:$3 = 5
-
-#![allow(unused_variable)]
-
-struct Struct {
- a: int,
- b: f64,
- c: uint
-}
-
-fn main() {
- let constant = 1;
-
- let a_struct = Struct {
- a: -2,
- b: 3.5,
- c: 4
- };
-
- let owned = box 5;
-
- let closure: proc() = proc() {
- zzz();
- do_something(&constant, &a_struct.a, owned);
- };
-
- closure();
-}
-
-fn do_something(_: &int, _:&int, _:&int) {
-
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// 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-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print variable
-// check:$1 = 1
-// debugger:print constant
-// check:$2 = 2
-// debugger:print a_struct
-// check:$3 = {a = -3, b = 4.5, c = 5}
-// debugger:print *struct_ref
-// check:$4 = {a = -3, b = 4.5, c = 5}
-// debugger:print *owned
-// check:$5 = 6
-// debugger:print managed->val
-// check:$6 = 7
-
-#![feature(managed_boxes)]
-#![allow(unused_variable)]
-
-struct Struct {
- a: int,
- b: f64,
- c: uint
-}
-
-fn main() {
- let mut variable = 1;
- let constant = 2;
-
- let a_struct = Struct {
- a: -3,
- b: 4.5,
- c: 5
- };
-
- let struct_ref = &a_struct;
- let owned = box 6;
- let managed = @7;
-
- let closure = || {
- zzz();
- variable = constant + a_struct.a + struct_ref.a + *owned + *managed;
- };
-
- closure();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print empty.length
-// check:$1 = 0
-
-// debugger:print singleton.length
-// check:$2 = 1
-// debugger:print *((int64_t[1]*)(singleton.data_ptr))
-// check:$3 = {1}
-
-// debugger:print multiple.length
-// check:$4 = 4
-// debugger:print *((int64_t[4]*)(multiple.data_ptr))
-// check:$5 = {2, 3, 4, 5}
-
-// debugger:print slice_of_slice.length
-// check:$6 = 2
-// debugger:print *((int64_t[2]*)(slice_of_slice.data_ptr))
-// check:$7 = {3, 4}
-
-// debugger:print padded_tuple.length
-// check:$8 = 2
-// debugger:print padded_tuple.data_ptr[0]
-// check:$9 = {6, 7}
-// debugger:print padded_tuple.data_ptr[1]
-// check:$10 = {8, 9}
-
-// debugger:print padded_struct.length
-// check:$11 = 2
-// debugger:print padded_struct.data_ptr[0]
-// check:$12 = {x = 10, y = 11, z = 12}
-// debugger:print padded_struct.data_ptr[1]
-// check:$13 = {x = 13, y = 14, z = 15}
-
-// debugger:print 'vec-slices::MUT_VECT_SLICE'.length
-// check:$14 = 2
-// debugger:print *((int64_t[2]*)('vec-slices::MUT_VECT_SLICE'.data_ptr))
-// check:$15 = {64, 65}
-
-#![allow(unused_variable)]
-
-struct AStruct {
- x: i16,
- y: i32,
- z: i16
-}
-
-static VECT_SLICE: &'static [i64] = &[64, 65];
-static mut MUT_VECT_SLICE: &'static [i64] = &[32];
-
-fn main() {
- let empty: &[i64] = &[];
- let singleton: &[i64] = &[1];
- let multiple: &[i64] = &[2, 3, 4, 5];
- let slice_of_slice = multiple.slice(1,3);
-
- let padded_tuple: &[(i32, i16)] = &[(6, 7), (8, 9)];
-
- let padded_struct: &[AStruct] = &[
- AStruct { x: 10, y: 11, z: 12 },
- AStruct { x: 13, y: 14, z: 15 }
- ];
-
- unsafe {
- MUT_VECT_SLICE = VECT_SLICE;
- }
-
- zzz();
-}
-
-fn zzz() {()}
+++ /dev/null
-// 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.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-win32: FIXME #13256
-// ignore-android: FIXME(#10381)
-
-// compile-flags:-g
-// debugger:set print pretty off
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-// debugger:print a
-// check:$1 = {1, 2, 3}
-// debugger:print vec::VECT
-// check:$2 = {4, 5, 6}
-
-#![allow(unused_variable)]
-
-static mut VECT: [i32, ..3] = [1, 2, 3];
-
-fn main() {
- let a = [1, 2, 3];
-
- unsafe {
- VECT[0] = 4;
- VECT[1] = 5;
- VECT[2] = 6;
- }
-
- zzz();
-}
-
-fn zzz() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:whatis 'basic-types-globals-metadata::B'
+// gdb-check:type = bool
+// gdb-command:whatis 'basic-types-globals-metadata::I'
+// gdb-check:type = int
+// gdb-command:whatis 'basic-types-globals-metadata::C'
+// gdb-check:type = char
+// gdb-command:whatis 'basic-types-globals-metadata::I8'
+// gdb-check:type = i8
+// gdb-command:whatis 'basic-types-globals-metadata::I16'
+// gdb-check:type = i16
+// gdb-command:whatis 'basic-types-globals-metadata::I32'
+// gdb-check:type = i32
+// gdb-command:whatis 'basic-types-globals-metadata::I64'
+// gdb-check:type = i64
+// gdb-command:whatis 'basic-types-globals-metadata::U'
+// gdb-check:type = uint
+// gdb-command:whatis 'basic-types-globals-metadata::U8'
+// gdb-check:type = u8
+// gdb-command:whatis 'basic-types-globals-metadata::U16'
+// gdb-check:type = u16
+// gdb-command:whatis 'basic-types-globals-metadata::U32'
+// gdb-check:type = u32
+// gdb-command:whatis 'basic-types-globals-metadata::U64'
+// gdb-check:type = u64
+// gdb-command:whatis 'basic-types-globals-metadata::F32'
+// gdb-check:type = f32
+// gdb-command:whatis 'basic-types-globals-metadata::F64'
+// gdb-check:type = f64
+// gdb-command:continue
+
+#![allow(unused_variable)]
+#![allow(dead_code)]
+
+
+static B: bool = false;
+static I: int = -1;
+static C: char = 'a';
+static I8: i8 = 68;
+static I16: i16 = -16;
+static I32: i32 = -32;
+static I64: i64 = -64;
+static U: uint = 1;
+static U8: u8 = 100;
+static U16: u16 = 16;
+static U32: u32 = 32;
+static U64: u64 = 64;
+static F32: f32 = 2.5;
+static F64: f64 = 3.5;
+
+fn main() {
+ _zzz();
+
+ let a = (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64);
+}
+
+fn _zzz() {()}
--- /dev/null
+// 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.
+//
+// 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.
+
+// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
+// as its numerical value along with its associated ASCII char, there
+// doesn't seem to be any way around this. Also, gdb doesn't know
+// about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print 'basic-types-globals::B'
+// gdb-check:$1 = false
+// gdb-command:print 'basic-types-globals::I'
+// gdb-check:$2 = -1
+// gdb-command:print 'basic-types-globals::C'
+// gdb-check:$3 = 97
+// gdb-command:print/d 'basic-types-globals::I8'
+// gdb-check:$4 = 68
+// gdb-command:print 'basic-types-globals::I16'
+// gdb-check:$5 = -16
+// gdb-command:print 'basic-types-globals::I32'
+// gdb-check:$6 = -32
+// gdb-command:print 'basic-types-globals::I64'
+// gdb-check:$7 = -64
+// gdb-command:print 'basic-types-globals::U'
+// gdb-check:$8 = 1
+// gdb-command:print/d 'basic-types-globals::U8'
+// gdb-check:$9 = 100
+// gdb-command:print 'basic-types-globals::U16'
+// gdb-check:$10 = 16
+// gdb-command:print 'basic-types-globals::U32'
+// gdb-check:$11 = 32
+// gdb-command:print 'basic-types-globals::U64'
+// gdb-check:$12 = 64
+// gdb-command:print 'basic-types-globals::F32'
+// gdb-check:$13 = 2.5
+// gdb-command:print 'basic-types-globals::F64'
+// gdb-check:$14 = 3.5
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+static B: bool = false;
+static I: int = -1;
+static C: char = 'a';
+static I8: i8 = 68;
+static I16: i16 = -16;
+static I32: i32 = -32;
+static I64: i64 = -64;
+static U: uint = 1;
+static U8: u8 = 100;
+static U16: u16 = 16;
+static U32: u32 = 32;
+static U64: u64 = 64;
+static F32: f32 = 2.5;
+static F64: f64 = 3.5;
+
+fn main() {
+ _zzz();
+
+ let a = (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64);
+}
+
+fn _zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:whatis unit
+// gdb-check:type = ()
+// gdb-command:whatis b
+// gdb-check:type = bool
+// gdb-command:whatis i
+// gdb-check:type = int
+// gdb-command:whatis c
+// gdb-check:type = char
+// gdb-command:whatis i8
+// gdb-check:type = i8
+// gdb-command:whatis i16
+// gdb-check:type = i16
+// gdb-command:whatis i32
+// gdb-check:type = i32
+// gdb-command:whatis i64
+// gdb-check:type = i64
+// gdb-command:whatis u
+// gdb-check:type = uint
+// gdb-command:whatis u8
+// gdb-check:type = u8
+// gdb-command:whatis u16
+// gdb-check:type = u16
+// gdb-command:whatis u32
+// gdb-check:type = u32
+// gdb-command:whatis u64
+// gdb-check:type = u64
+// gdb-command:whatis f32
+// gdb-check:type = f32
+// gdb-command:whatis f64
+// gdb-check:type = f64
+// gdb-command:info functions _yyy
+// gdb-check:[...]![...]_yyy([...])([...]);
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+fn main() {
+ let unit: () = ();
+ let b: bool = false;
+ let i: int = -1;
+ let c: char = 'a';
+ let i8: i8 = 68;
+ let i16: i16 = -16;
+ let i32: i32 = -32;
+ let i64: i64 = -64;
+ let u: uint = 1;
+ let u8: u8 = 100;
+ let u16: u16 = 16;
+ let u32: u32 = 32;
+ let u64: u64 = 64;
+ let f32: f32 = 2.5;
+ let f64: f64 = 3.5;
+ _zzz();
+ if 1 == 1 { _yyy(); }
+}
+
+fn _zzz() {()}
+fn _yyy() -> ! {fail!()}
--- /dev/null
+// 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.
+//
+// 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.
+
+// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
+// as its numerical value along with its associated ASCII char, there
+// doesn't seem to be any way around this. Also, gdb doesn't know
+// about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// Check initializers
+// gdb-command:print 'basic-types-mut-globals::B'
+// gdb-check:$1 = false
+// gdb-command:print 'basic-types-mut-globals::I'
+// gdb-check:$2 = -1
+// gdb-command:print 'basic-types-mut-globals::C'
+// gdb-check:$3 = 97
+// gdb-command:print/d 'basic-types-mut-globals::I8'
+// gdb-check:$4 = 68
+// gdb-command:print 'basic-types-mut-globals::I16'
+// gdb-check:$5 = -16
+// gdb-command:print 'basic-types-mut-globals::I32'
+// gdb-check:$6 = -32
+// gdb-command:print 'basic-types-mut-globals::I64'
+// gdb-check:$7 = -64
+// gdb-command:print 'basic-types-mut-globals::U'
+// gdb-check:$8 = 1
+// gdb-command:print/d 'basic-types-mut-globals::U8'
+// gdb-check:$9 = 100
+// gdb-command:print 'basic-types-mut-globals::U16'
+// gdb-check:$10 = 16
+// gdb-command:print 'basic-types-mut-globals::U32'
+// gdb-check:$11 = 32
+// gdb-command:print 'basic-types-mut-globals::U64'
+// gdb-check:$12 = 64
+// gdb-command:print 'basic-types-mut-globals::F32'
+// gdb-check:$13 = 2.5
+// gdb-command:print 'basic-types-mut-globals::F64'
+// gdb-check:$14 = 3.5
+// gdb-command:continue
+
+// Check new values
+// gdb-command:print 'basic-types-mut-globals'::B
+// gdb-check:$15 = true
+// gdb-command:print 'basic-types-mut-globals'::I
+// gdb-check:$16 = 2
+// gdb-command:print 'basic-types-mut-globals'::C
+// gdb-check:$17 = 102
+// gdb-command:print/d 'basic-types-mut-globals'::I8
+// gdb-check:$18 = 78
+// gdb-command:print 'basic-types-mut-globals'::I16
+// gdb-check:$19 = -26
+// gdb-command:print 'basic-types-mut-globals'::I32
+// gdb-check:$20 = -12
+// gdb-command:print 'basic-types-mut-globals'::I64
+// gdb-check:$21 = -54
+// gdb-command:print 'basic-types-mut-globals'::U
+// gdb-check:$22 = 5
+// gdb-command:print/d 'basic-types-mut-globals'::U8
+// gdb-check:$23 = 20
+// gdb-command:print 'basic-types-mut-globals'::U16
+// gdb-check:$24 = 32
+// gdb-command:print 'basic-types-mut-globals'::U32
+// gdb-check:$25 = 16
+// gdb-command:print 'basic-types-mut-globals'::U64
+// gdb-check:$26 = 128
+// gdb-command:print 'basic-types-mut-globals'::F32
+// gdb-check:$27 = 5.75
+// gdb-command:print 'basic-types-mut-globals'::F64
+// gdb-check:$28 = 9.25
+
+// gdb-command:detach
+// gdb-command:quit
+
+#![allow(unused_variable)]
+
+static mut B: bool = false;
+static mut I: int = -1;
+static mut C: char = 'a';
+static mut I8: i8 = 68;
+static mut I16: i16 = -16;
+static mut I32: i32 = -32;
+static mut I64: i64 = -64;
+static mut U: uint = 1;
+static mut U8: u8 = 100;
+static mut U16: u16 = 16;
+static mut U32: u32 = 32;
+static mut U64: u64 = 64;
+static mut F32: f32 = 2.5;
+static mut F64: f64 = 3.5;
+
+fn main() {
+ _zzz();
+
+ unsafe {
+ B = true;
+ I = 2;
+ C = 'f';
+ I8 = 78;
+ I16 = -26;
+ I32 = -12;
+ I64 = -54;
+ U = 5;
+ U8 = 20;
+ U16 = 32;
+ U32 = 16;
+ U64 = 128;
+ F32 = 5.75;
+ F64 = 9.25;
+ }
+
+ _zzz();
+}
+
+fn _zzz() {()}
--- /dev/null
+// 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.
+//
+// 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.
+
+// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
+// as its numerical value along with its associated ASCII char, there
+// doesn't seem to be any way around this. Also, gdb doesn't know
+// about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print b
+// gdb-check:$1 = false
+// gdb-command:print i
+// gdb-check:$2 = -1
+// gdb-command:print c
+// gdb-check:$3 = 97
+// gdb-command:print/d i8
+// gdb-check:$4 = 68
+// gdb-command:print i16
+// gdb-check:$5 = -16
+// gdb-command:print i32
+// gdb-check:$6 = -32
+// gdb-command:print i64
+// gdb-check:$7 = -64
+// gdb-command:print u
+// gdb-check:$8 = 1
+// gdb-command:print/d u8
+// gdb-check:$9 = 100
+// gdb-command:print u16
+// gdb-check:$10 = 16
+// gdb-command:print u32
+// gdb-check:$11 = 32
+// gdb-command:print u64
+// gdb-check:$12 = 64
+// gdb-command:print f32
+// gdb-check:$13 = 2.5
+// gdb-command:print f64
+// gdb-check:$14 = 3.5
+
+#![allow(unused_variable)]
+
+fn main() {
+ let b: bool = false;
+ let i: int = -1;
+ let c: char = 'a';
+ let i8: i8 = 68;
+ let i16: i16 = -16;
+ let i32: i32 = -32;
+ let i64: i64 = -64;
+ let u: uint = 1;
+ let u8: u8 = 100;
+ let u16: u16 = 16;
+ let u32: u32 = 32;
+ let u64: u64 = 64;
+ let f32: f32 = 2.5;
+ let f64: f64 = 3.5;
+ _zzz();
+}
+
+fn _zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print *bool_ref
+// gdb-check:$1 = true
+
+// gdb-command:print *int_ref
+// gdb-check:$2 = -1
+
+// gdb-command:print *char_ref
+// gdb-check:$3 = 97
+
+// gdb-command:print *i8_ref
+// gdb-check:$4 = 68 'D'
+
+// gdb-command:print *i16_ref
+// gdb-check:$5 = -16
+
+// gdb-command:print *i32_ref
+// gdb-check:$6 = -32
+
+// gdb-command:print *i64_ref
+// gdb-check:$7 = -64
+
+// gdb-command:print *uint_ref
+// gdb-check:$8 = 1
+
+// gdb-command:print *u8_ref
+// gdb-check:$9 = 100 'd'
+
+// gdb-command:print *u16_ref
+// gdb-check:$10 = 16
+
+// gdb-command:print *u32_ref
+// gdb-check:$11 = 32
+
+// gdb-command:print *u64_ref
+// gdb-check:$12 = 64
+
+// gdb-command:print *f32_ref
+// gdb-check:$13 = 2.5
+
+// gdb-command:print *f64_ref
+// gdb-check:$14 = 3.5
+
+#![allow(unused_variable)]
+
+fn main() {
+ let bool_val: bool = true;
+ let bool_ref: &bool = &bool_val;
+
+ let int_val: int = -1;
+ let int_ref: &int = &int_val;
+
+ let char_val: char = 'a';
+ let char_ref: &char = &char_val;
+
+ let i8_val: i8 = 68;
+ let i8_ref: &i8 = &i8_val;
+
+ let i16_val: i16 = -16;
+ let i16_ref: &i16 = &i16_val;
+
+ let i32_val: i32 = -32;
+ let i32_ref: &i32 = &i32_val;
+
+ let uint_val: i64 = -64;
+ let i64_ref: &i64 = &uint_val;
+
+ let uint_val: uint = 1;
+ let uint_ref: &uint = &uint_val;
+
+ let u8_val: u8 = 100;
+ let u8_ref: &u8 = &u8_val;
+
+ let u16_val: u16 = 16;
+ let u16_ref: &u16 = &u16_val;
+
+ let u32_val: u32 = 32;
+ let u32_ref: &u32 = &u32_val;
+
+ let u64_val: u64 = 64;
+ let u64_ref: &u64 = &u64_val;
+
+ let f32_val: f32 = 2.5;
+ let f32_ref: &f32 = &f32_val;
+
+ let f64_val: f64 = 3.5;
+ let f64_ref: &f64 = &f64_val;
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *the_a_ref
+// gdb-check:$1 = TheA
+
+// gdb-command:print *the_b_ref
+// gdb-check:$2 = TheB
+
+// gdb-command:print *the_c_ref
+// gdb-check:$3 = TheC
+
+#![allow(unused_variable)]
+
+enum ABC { TheA, TheB, TheC }
+
+fn main() {
+ let the_a = TheA;
+ let the_a_ref: &ABC = &the_a;
+
+ let the_b = TheB;
+ let the_b_ref: &ABC = &the_b;
+
+ let the_c = TheC;
+ let the_c_ref: &ABC = &the_c;
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *the_a_ref
+// gdb-check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// gdb-command:print *the_b_ref
+// gdb-check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// gdb-command:print *univariant_ref
+// gdb-check:$3 = {4820353753753434}
+
+#![allow(unused_variable)]
+#![feature(struct_variant)]
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+ TheA { x: i64, y: i64 },
+ TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+ TheOnlyCase(i64)
+}
+
+fn main() {
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let the_a = TheA { x: 0, y: 8970181431921507452 };
+ let the_a_ref: &ABC = &the_a;
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let the_b = TheB (0, 286331153, 286331153);
+ let the_b_ref: &ABC = &the_b;
+
+ let univariant = TheOnlyCase(4820353753753434);
+ let univariant_ref: &Univariant = &univariant;
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print *bool_ref
+// gdb-check:$1 = true
+
+// gdb-command:print *int_ref
+// gdb-check:$2 = -1
+
+// gdb-command:print *char_ref
+// gdb-check:$3 = 97
+
+// gdb-command:print/d *i8_ref
+// gdb-check:$4 = 68
+
+// gdb-command:print *i16_ref
+// gdb-check:$5 = -16
+
+// gdb-command:print *i32_ref
+// gdb-check:$6 = -32
+
+// gdb-command:print *i64_ref
+// gdb-check:$7 = -64
+
+// gdb-command:print *uint_ref
+// gdb-check:$8 = 1
+
+// gdb-command:print/d *u8_ref
+// gdb-check:$9 = 100
+
+// gdb-command:print *u16_ref
+// gdb-check:$10 = 16
+
+// gdb-command:print *u32_ref
+// gdb-check:$11 = 32
+
+// gdb-command:print *u64_ref
+// gdb-check:$12 = 64
+
+// gdb-command:print *f32_ref
+// gdb-check:$13 = 2.5
+
+// gdb-command:print *f64_ref
+// gdb-check:$14 = 3.5
+
+#![allow(unused_variable)]
+
+fn main() {
+ let bool_box: @bool = @true;
+ let bool_ref: &bool = bool_box;
+
+ let int_box: @int = @-1;
+ let int_ref: &int = int_box;
+
+ let char_box: @char = @'a';
+ let char_ref: &char = char_box;
+
+ let i8_box: @i8 = @68;
+ let i8_ref: &i8 = i8_box;
+
+ let i16_box: @i16 = @-16;
+ let i16_ref: &i16 = i16_box;
+
+ let i32_box: @i32 = @-32;
+ let i32_ref: &i32 = i32_box;
+
+ let i64_box: @i64 = @-64;
+ let i64_ref: &i64 = i64_box;
+
+ let uint_box: @uint = @1;
+ let uint_ref: &uint = uint_box;
+
+ let u8_box: @u8 = @100;
+ let u8_ref: &u8 = u8_box;
+
+ let u16_box: @u16 = @16;
+ let u16_ref: &u16 = u16_box;
+
+ let u32_box: @u32 = @32;
+ let u32_ref: &u32 = u32_box;
+
+ let u64_box: @u64 = @64;
+ let u64_ref: &u64 = u64_box;
+
+ let f32_box: @f32 = @2.5;
+ let f32_ref: &f32 = f32_box;
+
+ let f64_box: @f64 = @3.5;
+ let f64_ref: &f64 = f64_box;
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *stack_val_ref
+// gdb-check:$1 = {x = 10, y = 23.5}
+
+// gdb-command:print *stack_val_interior_ref_1
+// gdb-check:$2 = 10
+
+// gdb-command:print *stack_val_interior_ref_2
+// gdb-check:$3 = 23.5
+
+// gdb-command:print *ref_to_unnamed
+// gdb-check:$4 = {x = 11, y = 24.5}
+
+// gdb-command:print *managed_val_ref
+// gdb-check:$5 = {x = 12, y = 25.5}
+
+// gdb-command:print *managed_val_interior_ref_1
+// gdb-check:$6 = 12
+
+// gdb-command:print *managed_val_interior_ref_2
+// gdb-check:$7 = 25.5
+
+// gdb-command:print *unique_val_ref
+// gdb-check:$8 = {x = 13, y = 26.5}
+
+// gdb-command:print *unique_val_interior_ref_1
+// gdb-check:$9 = 13
+
+// gdb-command:print *unique_val_interior_ref_2
+// gdb-check:$10 = 26.5
+
+#![feature(managed_boxes)]
+#![allow(unused_variable)]
+
+struct SomeStruct {
+ x: int,
+ y: f64
+}
+
+fn main() {
+ let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 };
+ let stack_val_ref: &SomeStruct = &stack_val;
+ let stack_val_interior_ref_1: &int = &stack_val.x;
+ let stack_val_interior_ref_2: &f64 = &stack_val.y;
+ let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
+
+ let managed_val = @SomeStruct { x: 12, y: 25.5 };
+ let managed_val_ref: &SomeStruct = managed_val;
+ let managed_val_interior_ref_1: &int = &managed_val.x;
+ let managed_val_interior_ref_2: &f64 = &managed_val.y;
+
+ let unique_val = box SomeStruct { x: 13, y: 26.5 };
+ let unique_val_ref: &SomeStruct = unique_val;
+ let unique_val_interior_ref_1: &int = &unique_val.x;
+ let unique_val_interior_ref_2: &f64 = &unique_val.y;
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *stack_val_ref
+// gdb-check:$1 = {-14, -19}
+
+// gdb-command:print *ref_to_unnamed
+// gdb-check:$2 = {-15, -20}
+
+// gdb-command:print *managed_val_ref
+// gdb-check:$3 = {-16, -21}
+
+// gdb-command:print *unique_val_ref
+// gdb-check:$4 = {-17, -22}
+
+#![allow(unused_variable)]
+
+
+fn main() {
+ let stack_val: (i16, f32) = (-14, -19f32);
+ let stack_val_ref: &(i16, f32) = &stack_val;
+ let ref_to_unnamed: &(i16, f32) = &(-15, -20f32);
+
+ let managed_val: @(i16, f32) = @(-16, -21f32);
+ let managed_val_ref: &(i16, f32) = managed_val;
+
+ let unique_val: Box<(i16, f32)> = box() (-17, -22f32);
+ let unique_val_ref: &(i16, f32) = unique_val;
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print *bool_ref
+// gdb-check:$1 = true
+
+// gdb-command:print *int_ref
+// gdb-check:$2 = -1
+
+// gdb-command:print *char_ref
+// gdb-check:$3 = 97
+
+// gdb-command:print/d *i8_ref
+// gdb-check:$4 = 68
+
+// gdb-command:print *i16_ref
+// gdb-check:$5 = -16
+
+// gdb-command:print *i32_ref
+// gdb-check:$6 = -32
+
+// gdb-command:print *i64_ref
+// gdb-check:$7 = -64
+
+// gdb-command:print *uint_ref
+// gdb-check:$8 = 1
+
+// gdb-command:print/d *u8_ref
+// gdb-check:$9 = 100
+
+// gdb-command:print *u16_ref
+// gdb-check:$10 = 16
+
+// gdb-command:print *u32_ref
+// gdb-check:$11 = 32
+
+// gdb-command:print *u64_ref
+// gdb-check:$12 = 64
+
+// gdb-command:print *f32_ref
+// gdb-check:$13 = 2.5
+
+// gdb-command:print *f64_ref
+// gdb-check:$14 = 3.5
+
+#![allow(unused_variable)]
+
+
+fn main() {
+ let bool_box: Box<bool> = box true;
+ let bool_ref: &bool = bool_box;
+
+ let int_box: Box<int> = box -1;
+ let int_ref: &int = int_box;
+
+ let char_box: Box<char> = box 'a';
+ let char_ref: &char = char_box;
+
+ let i8_box: Box<i8> = box 68;
+ let i8_ref: &i8 = i8_box;
+
+ let i16_box: Box<i16> = box -16;
+ let i16_ref: &i16 = i16_box;
+
+ let i32_box: Box<i32> = box -32;
+ let i32_ref: &i32 = i32_box;
+
+ let i64_box: Box<i64> = box -64;
+ let i64_ref: &i64 = i64_box;
+
+ let uint_box: Box<uint> = box 1;
+ let uint_ref: &uint = uint_box;
+
+ let u8_box: Box<u8> = box 100;
+ let u8_ref: &u8 = u8_box;
+
+ let u16_box: Box<u16> = box 16;
+ let u16_ref: &u16 = u16_box;
+
+ let u32_box: Box<u32> = box 32;
+ let u32_ref: &u32 = u32_box;
+
+ let u64_box: Box<u64> = box 64;
+ let u64_ref: &u64 = u64_box;
+
+ let f32_box: Box<f32> = box 2.5;
+ let f32_ref: &f32 = f32_box;
+
+ let f64_box: Box<f64> = box 3.5;
+ let f64_ref: &f64 = f64_box;
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print *a
+// gdb-check:$1 = 1
+// gdb-command:print *b
+// gdb-check:$2 = {2, 3.5}
+// gdb-command:print c->val
+// gdb-check:$3 = 4
+// gdb-command:print d->val
+// gdb-check:$4 = false
+
+#![feature(managed_boxes)]
+#![allow(unused_variable)]
+
+fn main() {
+ let a = box 1;
+ let b = box() (2, 3.5);
+ let c = @4;
+ let d = @false;
+ _zzz();
+}
+
+fn _zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *unique
+// gdb-check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
+
+// gdb-command:print managed->val
+// gdb-check:$2 = {x = 88, y = 888, z = 8888, w = 88888}
+
+// gdb-command:print *unique_dtor
+// gdb-check:$3 = {x = 77, y = 777, z = 7777, w = 77777}
+
+// gdb-command:print managed_dtor->val
+// gdb-check:$4 = {x = 33, y = 333, z = 3333, w = 33333}
+
+#![feature(managed_boxes)]
+#![allow(unused_variable)]
+
+
+struct StructWithSomePadding {
+ x: i16,
+ y: i32,
+ z: i32,
+ w: i64
+}
+
+struct StructWithDestructor {
+ x: i16,
+ y: i32,
+ z: i32,
+ w: i64
+}
+
+impl Drop for StructWithDestructor {
+ fn drop(&mut self) {}
+}
+
+fn main() {
+
+ let unique = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
+ let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 };
+
+ let unique_dtor = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
+ let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print s
+// gdb-check:$1 = {a = 1, b = 2.5}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = {a = 3, b = 4.5}
+// gdb-command:print y
+// gdb-check:$3 = 5
+// gdb-command:print z
+// gdb-check:$4 = 6.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$5 = {7, 8, 9.5, 10.5}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$6 = {11.5, 12.5, 13, 14}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = {{Case1, x = 0, y = 8970181431921507452}, {Case1, 0, 2088533116, 2088533116}}
+// gdb-command:continue
+
+#![feature(struct_variant)]
+
+#[deriving(Clone)]
+struct Struct {
+ a: int,
+ b: f64
+}
+
+#[deriving(Clone)]
+struct StructStruct {
+ a: Struct,
+ b: Struct
+}
+
+fn fun(s: Struct) {
+ zzz();
+}
+
+fn fun_fun(StructStruct { a: x, b: Struct { a: y, b: z } }: StructStruct) {
+ zzz();
+}
+
+fn tup(a: (int, uint, f64, f64)) {
+ zzz();
+}
+
+struct Newtype(f64, f64, int, uint);
+
+fn new_type(a: Newtype) {
+ zzz();
+}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Enum {
+ Case1 { x: i64, y: i64 },
+ Case2 (i64, i32, i32),
+}
+
+fn by_val_enum(x: Enum) {
+ zzz();
+}
+
+fn main() {
+ fun(Struct { a: 1, b: 2.5 });
+ fun_fun(StructStruct { a: Struct { a: 3, b: 4.5 }, b: Struct { a: 5, b: 6.5 } });
+ tup((7, 8, 9.5, 10.5));
+ new_type(Newtype(11.5, 12.5, 13, 14));
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ by_val_enum(Case1 { x: 0, y: 8970181431921507452 });
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$1 = 1111
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$2 = {x = 2222, y = 3333}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$3 = {4444.5, 5555, 6666, 7777.5}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print self->val
+// gdb-check:$4 = 8888
+// gdb-command:continue
+
+trait Trait {
+ fn method(self) -> Self;
+}
+
+impl Trait for int {
+ fn method(self) -> int {
+ zzz();
+ self
+ }
+}
+
+struct Struct {
+ x: uint,
+ y: uint,
+}
+
+impl Trait for Struct {
+ fn method(self) -> Struct {
+ zzz();
+ self
+ }
+}
+
+impl Trait for (f64, int, int, f64) {
+ fn method(self) -> (f64, int, int, f64) {
+ zzz();
+ self
+ }
+}
+
+impl Trait for @int {
+ fn method(self) -> @int {
+ zzz();
+ self
+ }
+}
+
+fn main() {
+ let _ = (1111 as int).method();
+ let _ = Struct { x: 2222, y: 3333 }.method();
+ let _ = (4444.5, 5555, 6666, 7777.5).method();
+ let _ = (@8888).method();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print tuple_interior_padding
+// gdb-check:$1 = {0, OneHundred}
+
+// gdb-command:print tuple_padding_at_end
+// gdb-check:$2 = {{1, OneThousand}, 2}
+
+// gdb-command:print tuple_different_enums
+// gdb-check:$3 = {OneThousand, MountainView, OneMillion, Vienna}
+
+// gdb-command:print padded_struct
+// gdb-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5}
+
+// gdb-command:print packed_struct
+// gdb-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8}
+
+// gdb-command:print non_padded_struct
+// gdb-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto}
+
+// gdb-command:print struct_with_drop
+// gdb-check:$7 = {{a = OneHundred, b = Vienna}, 9}
+
+#![allow(unused_variable)]
+
+enum AnEnum {
+ OneHundred = 100,
+ OneThousand = 1000,
+ OneMillion = 1000000
+}
+
+enum AnotherEnum {
+ MountainView,
+ Toronto,
+ Vienna
+}
+
+struct PaddedStruct {
+ a: i16,
+ b: AnEnum,
+ c: i16,
+ d: AnotherEnum,
+ e: i16
+}
+
+#[packed]
+struct PackedStruct {
+ a: i16,
+ b: AnEnum,
+ c: i16,
+ d: AnotherEnum,
+ e: i16
+}
+
+struct NonPaddedStruct {
+ a: AnEnum,
+ b: AnotherEnum,
+ c: AnEnum,
+ d: AnotherEnum
+}
+
+struct StructWithDrop {
+ a: AnEnum,
+ b: AnotherEnum
+}
+
+impl Drop for StructWithDrop {
+ fn drop(&mut self) {()}
+}
+
+fn main() {
+
+ let tuple_interior_padding = (0_i16, OneHundred);
+ // It will depend on the machine architecture if any padding is actually involved here
+ let tuple_padding_at_end = ((1_u64, OneThousand), 2_u64);
+ let tuple_different_enums = (OneThousand, MountainView, OneMillion, Vienna);
+
+ let padded_struct = PaddedStruct {
+ a: 3,
+ b: OneMillion,
+ c: 4,
+ d: Toronto,
+ e: 5
+ };
+
+ let packed_struct = PackedStruct {
+ a: 6,
+ b: OneHundred,
+ c: 7,
+ d: Vienna,
+ e: 8
+ };
+
+ let non_padded_struct = NonPaddedStruct {
+ a: OneMillion,
+ b: MountainView,
+ c: OneThousand,
+ d: Toronto
+ };
+
+ let struct_with_drop = (StructWithDrop { a: OneHundred, b: Vienna }, 9_i64);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+
+// gdb-command:print 'c-style-enum::SINGLE_VARIANT'
+// gdb-check:$1 = TheOnlyVariant
+
+// gdb-command:print 'c-style-enum::AUTO_ONE'
+// gdb-check:$2 = One
+
+// gdb-command:print 'c-style-enum::AUTO_TWO'
+// gdb-check:$3 = One
+
+// gdb-command:print 'c-style-enum::AUTO_THREE'
+// gdb-check:$4 = One
+
+// gdb-command:print 'c-style-enum::MANUAL_ONE'
+// gdb-check:$5 = OneHundred
+
+// gdb-command:print 'c-style-enum::MANUAL_TWO'
+// gdb-check:$6 = OneHundred
+
+// gdb-command:print 'c-style-enum::MANUAL_THREE'
+// gdb-check:$7 = OneHundred
+
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print auto_one
+// gdb-check:$8 = One
+
+// gdb-command:print auto_two
+// gdb-check:$9 = Two
+
+// gdb-command:print auto_three
+// gdb-check:$10 = Three
+
+// gdb-command:print manual_one_hundred
+// gdb-check:$11 = OneHundred
+
+// gdb-command:print manual_one_thousand
+// gdb-check:$12 = OneThousand
+
+// gdb-command:print manual_one_million
+// gdb-check:$13 = OneMillion
+
+// gdb-command:print single_variant
+// gdb-check:$14 = TheOnlyVariant
+
+// gdb-command:print 'c-style-enum::AUTO_TWO'
+// gdb-check:$15 = Two
+
+// gdb-command:print 'c-style-enum::AUTO_THREE'
+// gdb-check:$16 = Three
+
+// gdb-command:print 'c-style-enum::MANUAL_TWO'
+// gdb-check:$17 = OneThousand
+
+// gdb-command:print 'c-style-enum::MANUAL_THREE'
+// gdb-check:$18 = OneMillion
+
+#![allow(unused_variable)]
+#![allow(dead_code)]
+
+enum AutoDiscriminant {
+ One,
+ Two,
+ Three
+}
+
+enum ManualDiscriminant {
+ OneHundred = 100,
+ OneThousand = 1000,
+ OneMillion = 1000000
+}
+
+enum SingleVariant {
+ TheOnlyVariant
+}
+
+static SINGLE_VARIANT: SingleVariant = TheOnlyVariant;
+
+static mut AUTO_ONE: AutoDiscriminant = One;
+static mut AUTO_TWO: AutoDiscriminant = One;
+static mut AUTO_THREE: AutoDiscriminant = One;
+
+static mut MANUAL_ONE: ManualDiscriminant = OneHundred;
+static mut MANUAL_TWO: ManualDiscriminant = OneHundred;
+static mut MANUAL_THREE: ManualDiscriminant = OneHundred;
+
+fn main() {
+
+ let auto_one = One;
+ let auto_two = Two;
+ let auto_three = Three;
+
+ let manual_one_hundred = OneHundred;
+ let manual_one_thousand = OneThousand;
+ let manual_one_million = OneMillion;
+
+ let single_variant = TheOnlyVariant;
+
+ unsafe {
+ AUTO_TWO = Two;
+ AUTO_THREE = Three;
+
+ MANUAL_TWO = OneThousand;
+ MANUAL_THREE = OneMillion;
+ };
+
+ zzz();
+
+ let a = SINGLE_VARIANT;
+ let a = unsafe { AUTO_ONE };
+ let a = unsafe { MANUAL_ONE };
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = 0.5
+// gdb-command:print y
+// gdb-check:$2 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *x
+// gdb-check:$3 = 29
+// gdb-command:print *y
+// gdb-check:$4 = 110
+// gdb-command:continue
+
+fn some_generic_fun<T1, T2>(a: T1, b: T2) -> (T2, T1) {
+
+ let closure = |x, y| {
+ zzz();
+ (y, x)
+ };
+
+ closure(a, b)
+}
+
+fn main() {
+ some_generic_fun(0.5, 10);
+ some_generic_fun(&29, box 110);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$1 = 1
+// gdb-command:print b
+// gdb-check:$2 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$3 = 2
+// gdb-command:print b
+// gdb-check:$4 = 3
+// gdb-command:print c
+// gdb-check:$5 = 4
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$6 = 5
+// gdb-command:print b
+// gdb-check:$7 = {6, 7}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print h
+// gdb-check:$8 = 8
+// gdb-command:print i
+// gdb-check:$9 = {a = 9, b = 10}
+// gdb-command:print j
+// gdb-check:$10 = 11
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print k
+// gdb-check:$11 = 12
+// gdb-command:print l
+// gdb-check:$12 = 13
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print m
+// gdb-check:$13 = 14
+// gdb-command:print n
+// gdb-check:$14 = 16
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print o
+// gdb-check:$15 = 18
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print p
+// gdb-check:$16 = 19
+// gdb-command:print q
+// gdb-check:$17 = 20
+// gdb-command:print r
+// gdb-check:$18 = {a = 21, b = 22}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print s
+// gdb-check:$19 = 24
+// gdb-command:print t
+// gdb-check:$20 = 23
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print u
+// gdb-check:$21 = 25
+// gdb-command:print v
+// gdb-check:$22 = 26
+// gdb-command:print w
+// gdb-check:$23 = 27
+// gdb-command:print x
+// gdb-check:$24 = 28
+// gdb-command:print y
+// gdb-check:$25 = 29
+// gdb-command:print z
+// gdb-check:$26 = 30
+// gdb-command:print ae
+// gdb-check:$27 = 31
+// gdb-command:print oe
+// gdb-check:$28 = 32
+// gdb-command:print ue
+// gdb-check:$29 = 33
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print aa
+// gdb-check:$30 = {34, 35}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print bb
+// gdb-check:$31 = {36, 37}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print cc
+// gdb-check:$32 = 38
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print dd
+// gdb-check:$33 = {40, 41, 42}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *ee
+// gdb-check:$34 = {43, 44, 45}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *ff
+// gdb-check:$35 = 46
+// gdb-command:print gg
+// gdb-check:$36 = {47, 48}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *hh
+// gdb-check:$37 = 50
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print ii
+// gdb-check:$38 = 51
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *jj
+// gdb-check:$39 = 52
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print kk
+// gdb-check:$40 = 53
+// gdb-command:print ll
+// gdb-check:$41 = 54
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print mm
+// gdb-check:$42 = 55
+// gdb-command:print *nn
+// gdb-check:$43 = 56
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print oo
+// gdb-check:$44 = 57
+// gdb-command:print pp
+// gdb-check:$45 = 58
+// gdb-command:print qq
+// gdb-check:$46 = 59
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print rr
+// gdb-check:$47 = 60
+// gdb-command:print ss
+// gdb-check:$48 = 61
+// gdb-command:print tt
+// gdb-check:$49 = 62
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+
+struct Struct {
+ a: i64,
+ b: i32
+}
+
+enum Univariant {
+ Unit(i32)
+}
+
+struct TupleStruct (f64, int);
+
+
+fn simple_tuple((a, b): (int, bool)) {
+ zzz();
+}
+
+fn nested_tuple((a, (b, c)): (int, (u16, u16))) {
+ zzz();
+}
+
+fn destructure_only_first_level((a, b): (int, (u32, u32))) {
+ zzz();
+}
+
+fn struct_as_tuple_element((h, i, j): (i16, Struct, i16)) {
+ zzz();
+}
+
+fn struct_pattern(Struct { a: k, b: l }: Struct) {
+ zzz();
+}
+
+fn ignored_tuple_element((m, _, n): (int, u16, i32)) {
+ zzz();
+}
+
+fn ignored_struct_field(Struct { b: o, .. }: Struct) {
+ zzz();
+}
+
+fn one_struct_destructured_one_not((Struct { a: p, b: q }, r): (Struct, Struct)) {
+ zzz();
+}
+
+fn different_order_of_struct_fields(Struct { b: s, a: t }: Struct ) {
+ zzz();
+}
+
+fn complex_nesting(((u, v ), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue ):
+ ((i16, i32), ((i64, (i32, Struct, )), Struct ), u16))
+{
+ zzz();
+}
+
+fn managed_box(&aa: &(int, int)) {
+ zzz();
+}
+
+fn borrowed_pointer(&bb: &(int, int)) {
+ zzz();
+}
+
+fn contained_borrowed_pointer((&cc, _): (&int, int)) {
+ zzz();
+}
+
+fn unique_pointer(box dd: Box<(int, int, int)>) {
+ zzz();
+}
+
+fn ref_binding(ref ee: (int, int, int)) {
+ zzz();
+}
+
+fn ref_binding_in_tuple((ref ff, gg): (int, (int, int))) {
+ zzz();
+}
+
+fn ref_binding_in_struct(Struct { b: ref hh, .. }: Struct) {
+ zzz();
+}
+
+fn univariant_enum(Unit(ii): Univariant) {
+ zzz();
+}
+
+fn univariant_enum_with_ref_binding(Unit(ref jj): Univariant) {
+ zzz();
+}
+
+fn tuple_struct(TupleStruct(kk, ll): TupleStruct) {
+ zzz();
+}
+
+fn tuple_struct_with_ref_binding(TupleStruct(mm, ref nn): TupleStruct) {
+ zzz();
+}
+
+fn multiple_arguments((oo, pp): (int, int), qq : int) {
+ zzz();
+}
+
+fn main() {
+ simple_tuple((1, false));
+ nested_tuple((2, (3, 4)));
+ destructure_only_first_level((5, (6, 7)));
+ struct_as_tuple_element((8, Struct { a: 9, b: 10 }, 11));
+ struct_pattern(Struct { a: 12, b: 13 });
+ ignored_tuple_element((14, 15, 16));
+ ignored_struct_field(Struct { a: 17, b: 18 });
+ one_struct_destructured_one_not((Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 }));
+ different_order_of_struct_fields(Struct { a: 23, b: 24 });
+ complex_nesting(((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33));
+ managed_box(&(34, 35));
+ borrowed_pointer(&(36, 37));
+ contained_borrowed_pointer((&38, 39));
+ unique_pointer(box() (40, 41, 42));
+ ref_binding((43, 44, 45));
+ ref_binding_in_tuple((46, (47, 48)));
+ ref_binding_in_struct(Struct { a: 49, b: 50 });
+ univariant_enum(Unit(51));
+ univariant_enum_with_ref_binding(Unit(52));
+ tuple_struct(TupleStruct(53.0, 54));
+ tuple_struct_with_ref_binding(TupleStruct(55.0, 56));
+ multiple_arguments((57, 58), 59);
+
+ fn nested_function(rr: int, (ss, tt): (int, int)) {
+ zzz();
+ }
+
+ nested_function(60, (61, 62));
+}
+
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print a
+// gdb-check:$1 = 1
+// gdb-command:print b
+// gdb-check:$2 = false
+
+// gdb-command:print c
+// gdb-check:$3 = 2
+// gdb-command:print d
+// gdb-check:$4 = 3
+// gdb-command:print e
+// gdb-check:$5 = 4
+
+// gdb-command:print f
+// gdb-check:$6 = 5
+// gdb-command:print g
+// gdb-check:$7 = {6, 7}
+
+// gdb-command:print h
+// gdb-check:$8 = 8
+// gdb-command:print i
+// gdb-check:$9 = {a = 9, b = 10}
+// gdb-command:print j
+// gdb-check:$10 = 11
+
+// gdb-command:print k
+// gdb-check:$11 = 12
+// gdb-command:print l
+// gdb-check:$12 = 13
+
+// gdb-command:print m
+// gdb-check:$13 = 14
+// gdb-command:print n
+// gdb-check:$14 = 16
+
+// gdb-command:print o
+// gdb-check:$15 = 18
+
+// gdb-command:print p
+// gdb-check:$16 = 19
+// gdb-command:print q
+// gdb-check:$17 = 20
+// gdb-command:print r
+// gdb-check:$18 = {a = 21, b = 22}
+
+// gdb-command:print s
+// gdb-check:$19 = 24
+// gdb-command:print t
+// gdb-check:$20 = 23
+
+// gdb-command:print u
+// gdb-check:$21 = 25
+// gdb-command:print v
+// gdb-check:$22 = 26
+// gdb-command:print w
+// gdb-check:$23 = 27
+// gdb-command:print x
+// gdb-check:$24 = 28
+// gdb-command:print y
+// gdb-check:$25 = 29
+// gdb-command:print z
+// gdb-check:$26 = 30
+// gdb-command:print ae
+// gdb-check:$27 = 31
+// gdb-command:print oe
+// gdb-check:$28 = 32
+// gdb-command:print ue
+// gdb-check:$29 = 33
+
+// gdb-command:print aa
+// gdb-check:$30 = {34, 35}
+
+// gdb-command:print bb
+// gdb-check:$31 = {36, 37}
+
+// gdb-command:print cc
+// gdb-check:$32 = 38
+
+// gdb-command:print dd
+// gdb-check:$33 = {40, 41, 42}
+
+// gdb-command:print *ee
+// gdb-check:$34 = {43, 44, 45}
+
+// gdb-command:print *ff
+// gdb-check:$35 = 46
+
+// gdb-command:print gg
+// gdb-check:$36 = {47, 48}
+
+// gdb-command:print *hh
+// gdb-check:$37 = 50
+
+// gdb-command:print ii
+// gdb-check:$38 = 51
+
+// gdb-command:print *jj
+// gdb-check:$39 = 52
+
+// gdb-command:print kk
+// gdb-check:$40 = 53
+
+// gdb-command:print ll
+// gdb-check:$41 = 54
+
+// gdb-command:print mm
+// gdb-check:$42 = 55
+
+// gdb-command:print *nn
+// gdb-check:$43 = 56
+
+#![allow(unused_variable)]
+
+struct Struct {
+ a: i64,
+ b: i32
+}
+
+enum Univariant {
+ Unit(i32)
+}
+
+struct TupleStruct (f64, int);
+
+
+fn main() {
+ // simple tuple
+ let (a, b) : (int, bool) = (1, false);
+
+ // nested tuple
+ let (c, (d, e)) : (int, (u16, u16)) = (2, (3, 4));
+
+ // bind tuple-typed value to one name (destructure only first level)
+ let (f, g) : (int, (u32, u32)) = (5, (6, 7));
+
+ // struct as tuple element
+ let (h, i, j) : (i16, Struct, i16) = (8, Struct { a: 9, b: 10 }, 11);
+
+ // struct pattern
+ let Struct { a: k, b: l } = Struct { a: 12, b: 13 };
+
+ // ignored tuple element
+ let (m, _, n) = (14, 15, 16);
+
+ // ignored struct field
+ let Struct { b: o, .. } = Struct { a: 17, b: 18 };
+
+ // one struct destructured, one not
+ let (Struct { a: p, b: q }, r) = (Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 });
+
+ // different order of struct fields
+ let Struct { b: s, a: t } = Struct { a: 23, b: 24 };
+
+ // complex nesting
+ let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) =
+ ((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33);
+
+ // reference
+ let &aa = &(34, 35);
+
+ // reference
+ let &bb = &(36, 37);
+
+ // contained reference
+ let (&cc, _) = (&38, 39);
+
+ // unique pointer
+ let box dd = box() (40, 41, 42);
+
+ // ref binding
+ let ref ee = (43, 44, 45);
+
+ // ref binding in tuple
+ let (ref ff, gg) = (46, (47, 48));
+
+ // ref binding in struct
+ let Struct { b: ref hh, .. } = Struct { a: 49, b: 50 };
+
+ // univariant enum
+ let Unit(ii) = Unit(51);
+
+ // univariant enum with ref binding
+ let &Unit(ref jj) = &Unit(52);
+
+ // tuple struct
+ let &TupleStruct(kk, ll) = &TupleStruct(53.0, 54);
+
+ // tuple struct with ref binding
+ let &TupleStruct(mm, ref nn) = &TupleStruct(55.0, 56);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print no_padding1
+// gdb-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}}
+// gdb-command:print no_padding2
+// gdb-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}}
+
+// gdb-command:print struct_internal_padding
+// gdb-check:$3 = {x = {13, 14}, y = {15, 16}}
+
+// gdb-command:print single_vec
+// gdb-check:$4 = {x = {17, 18, 19, 20, 21}}
+
+// gdb-command:print struct_padded_at_end
+// gdb-check:$5 = {x = {22, 23}, y = {24, 25}}
+
+#![allow(unused_variable)]
+
+struct NoPadding1 {
+ x: [u32, ..3],
+ y: i32,
+ z: [f32, ..2]
+}
+
+struct NoPadding2 {
+ x: [u32, ..3],
+ y: [[u32, ..2], ..2]
+}
+
+struct StructInternalPadding {
+ x: [i16, ..2],
+ y: [i64, ..2]
+}
+
+struct SingleVec {
+ x: [i16, ..5]
+}
+
+struct StructPaddedAtEnd {
+ x: [i64, ..2],
+ y: [i16, ..2]
+}
+
+fn main() {
+
+ let no_padding1 = NoPadding1 {
+ x: [0, 1, 2],
+ y: -3,
+ z: [4.5, 5.5]
+ };
+
+ let no_padding2 = NoPadding2 {
+ x: [6, 7, 8],
+ y: [[9, 10], [11, 12]]
+ };
+
+ let struct_internal_padding = StructInternalPadding {
+ x: [13, 14],
+ y: [15, 16]
+ };
+
+ let single_vec = SingleVec {
+ x: [17, 18, 19, 20, 21]
+ };
+
+ let struct_padded_at_end = StructPaddedAtEnd {
+ x: [22, 23],
+ y: [24, 25]
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// This test case checks if function arguments already have the correct value when breaking at the
+// first line of the function, that is if the function prologue has already been executed at the
+// first line. Note that because of the __morestack part of the prologue GDB incorrectly breaks at
+// before the arguments have been properly loaded when setting the breakpoint via the function name.
+// Therefore the setup here sets them using line numbers (so be careful when changing this file).
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:break function-arg-initialization.rs:139
+// gdb-command:break function-arg-initialization.rs:154
+// gdb-command:break function-arg-initialization.rs:158
+// gdb-command:break function-arg-initialization.rs:162
+// gdb-command:break function-arg-initialization.rs:166
+// gdb-command:break function-arg-initialization.rs:170
+// gdb-command:break function-arg-initialization.rs:174
+// gdb-command:break function-arg-initialization.rs:178
+// gdb-command:break function-arg-initialization.rs:182
+// gdb-command:break function-arg-initialization.rs:190
+// gdb-command:break function-arg-initialization.rs:197
+
+
+// gdb-command:run
+
+// IMMEDIATE ARGS
+// gdb-command:print a
+// gdb-check:$1 = 1
+// gdb-command:print b
+// gdb-check:$2 = true
+// gdb-command:print c
+// gdb-check:$3 = 2.5
+// gdb-command:continue
+
+// NON IMMEDIATE ARGS
+// gdb-command:print a
+// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
+// gdb-command:print b
+// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
+// gdb-command:continue
+
+// BINDING
+// gdb-command:print a
+// gdb-check:$6 = 19
+// gdb-command:print b
+// gdb-check:$7 = 20
+// gdb-command:print c
+// gdb-check:$8 = 21.5
+// gdb-command:continue
+
+// ASSIGNMENT
+// gdb-command:print a
+// gdb-check:$9 = 22
+// gdb-command:print b
+// gdb-check:$10 = 23
+// gdb-command:print c
+// gdb-check:$11 = 24.5
+// gdb-command:continue
+
+// FUNCTION CALL
+// gdb-command:print x
+// gdb-check:$12 = 25
+// gdb-command:print y
+// gdb-check:$13 = 26
+// gdb-command:print z
+// gdb-check:$14 = 27.5
+// gdb-command:continue
+
+// EXPR
+// gdb-command:print x
+// gdb-check:$15 = 28
+// gdb-command:print y
+// gdb-check:$16 = 29
+// gdb-command:print z
+// gdb-check:$17 = 30.5
+// gdb-command:continue
+
+// RETURN EXPR
+// gdb-command:print x
+// gdb-check:$18 = 31
+// gdb-command:print y
+// gdb-check:$19 = 32
+// gdb-command:print z
+// gdb-check:$20 = 33.5
+// gdb-command:continue
+
+// ARITHMETIC EXPR
+// gdb-command:print x
+// gdb-check:$21 = 34
+// gdb-command:print y
+// gdb-check:$22 = 35
+// gdb-command:print z
+// gdb-check:$23 = 36.5
+// gdb-command:continue
+
+// IF EXPR
+// gdb-command:print x
+// gdb-check:$24 = 37
+// gdb-command:print y
+// gdb-check:$25 = 38
+// gdb-command:print z
+// gdb-check:$26 = 39.5
+// gdb-command:continue
+
+// WHILE EXPR
+// gdb-command:print x
+// gdb-check:$27 = 40
+// gdb-command:print y
+// gdb-check:$28 = 41
+// gdb-command:print z
+// gdb-check:$29 = 42
+// gdb-command:continue
+
+// LOOP EXPR
+// gdb-command:print x
+// gdb-check:$30 = 43
+// gdb-command:print y
+// gdb-check:$31 = 44
+// gdb-command:print z
+// gdb-check:$32 = 45
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+
+
+
+fn immediate_args(a: int, b: bool, c: f64) {
+ ()
+}
+
+struct BigStruct {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+ e: u64,
+ f: u64,
+ g: u64,
+ h: u64
+}
+
+fn non_immediate_args(a: BigStruct, b: BigStruct) {
+ ()
+}
+
+fn binding(a: i64, b: u64, c: f64) {
+ let x = 0;
+}
+
+fn assignment(mut a: u64, b: u64, c: f64) {
+ a = b;
+}
+
+fn function_call(x: u64, y: u64, z: f64) {
+ std::io::stdio::print("Hi!")
+}
+
+fn identifier(x: u64, y: u64, z: f64) -> u64 {
+ x
+}
+
+fn return_expr(x: u64, y: u64, z: f64) -> u64 {
+ return x;
+}
+
+fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
+ x + y
+}
+
+fn if_expr(x: u64, y: u64, z: f64) -> u64 {
+ if x + y < 1000 {
+ x
+ } else {
+ y
+ }
+}
+
+fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
+ while x + y < 1000 {
+ x += z
+ }
+ return x;
+}
+
+fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
+ loop {
+ x += z;
+
+ if x + y > 1000 {
+ return x;
+ }
+ }
+}
+
+fn main() {
+ immediate_args(1, true, 2.5);
+
+ non_immediate_args(
+ BigStruct {
+ a: 3,
+ b: 4,
+ c: 5,
+ d: 6,
+ e: 7,
+ f: 8,
+ g: 9,
+ h: 10
+ },
+ BigStruct {
+ a: 11,
+ b: 12,
+ c: 13,
+ d: 14,
+ e: 15,
+ f: 16,
+ g: 17,
+ h: 18
+ }
+ );
+
+ binding(19, 20, 21.5);
+ assignment(22, 23, 24.5);
+ function_call(25, 26, 27.5);
+ identifier(28, 29, 30.5);
+ return_expr(31, 32, 33.5);
+ arithmetic_expr(34, 35, 36.5);
+ if_expr(37, 38, 39.5);
+ while_expr(40, 41, 42);
+ loop_expr(43, 44, 45);
+}
+
+
+
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print x
+// gdb-check:$1 = 111102
+// gdb-command:print y
+// gdb-check:$2 = true
+
+// gdb-command:continue
+// gdb-command:finish
+
+// gdb-command:print a
+// gdb-check:$3 = 2000
+// gdb-command:print b
+// gdb-check:$4 = 3000
+
+fn main() {
+
+ fun(111102, true);
+ nested(2000, 3000);
+
+ fn nested(a: i32, b: i64) -> (i32, i64) {
+ zzz();
+ (a, b)
+ }
+}
+
+fn fun(x: int, y: bool) -> (int, bool) {
+ zzz();
+
+ (x, y)
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// This test case checks if function arguments already have the correct value when breaking at the
+// beginning of a function. Functions with the #[no_split_stack] attribute have the same prologue as
+// regular C functions compiled with GCC or Clang and therefore are better handled by GDB. As a
+// consequence, and as opposed to regular Rust functions, we can set the breakpoints via the
+// function name (and don't have to fall back on using line numbers).
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak immediate_args
+// gdb-command:rbreak binding
+// gdb-command:rbreak assignment
+// gdb-command:rbreak function_call
+// gdb-command:rbreak identifier
+// gdb-command:rbreak return_expr
+// gdb-command:rbreak arithmetic_expr
+// gdb-command:rbreak if_expr
+// gdb-command:rbreak while_expr
+// gdb-command:rbreak loop_expr
+// gdb-command:run
+
+// IMMEDIATE ARGS
+// gdb-command:print a
+// gdb-check:$1 = 1
+// gdb-command:print b
+// gdb-check:$2 = true
+// gdb-command:print c
+// gdb-check:$3 = 2.5
+// gdb-command:continue
+
+// NON IMMEDIATE ARGS
+// gdb-command:print a
+// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
+// gdb-command:print b
+// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
+// gdb-command:continue
+
+// BINDING
+// gdb-command:print a
+// gdb-check:$6 = 19
+// gdb-command:print b
+// gdb-check:$7 = 20
+// gdb-command:print c
+// gdb-check:$8 = 21.5
+// gdb-command:continue
+
+// ASSIGNMENT
+// gdb-command:print a
+// gdb-check:$9 = 22
+// gdb-command:print b
+// gdb-check:$10 = 23
+// gdb-command:print c
+// gdb-check:$11 = 24.5
+// gdb-command:continue
+
+// FUNCTION CALL
+// gdb-command:print x
+// gdb-check:$12 = 25
+// gdb-command:print y
+// gdb-check:$13 = 26
+// gdb-command:print z
+// gdb-check:$14 = 27.5
+// gdb-command:continue
+
+// EXPR
+// gdb-command:print x
+// gdb-check:$15 = 28
+// gdb-command:print y
+// gdb-check:$16 = 29
+// gdb-command:print z
+// gdb-check:$17 = 30.5
+// gdb-command:continue
+
+// RETURN EXPR
+// gdb-command:print x
+// gdb-check:$18 = 31
+// gdb-command:print y
+// gdb-check:$19 = 32
+// gdb-command:print z
+// gdb-check:$20 = 33.5
+// gdb-command:continue
+
+// ARITHMETIC EXPR
+// gdb-command:print x
+// gdb-check:$21 = 34
+// gdb-command:print y
+// gdb-check:$22 = 35
+// gdb-command:print z
+// gdb-check:$23 = 36.5
+// gdb-command:continue
+
+// IF EXPR
+// gdb-command:print x
+// gdb-check:$24 = 37
+// gdb-command:print y
+// gdb-check:$25 = 38
+// gdb-command:print z
+// gdb-check:$26 = 39.5
+// gdb-command:continue
+
+// WHILE EXPR
+// gdb-command:print x
+// gdb-check:$27 = 40
+// gdb-command:print y
+// gdb-check:$28 = 41
+// gdb-command:print z
+// gdb-check:$29 = 42
+// gdb-command:continue
+
+// LOOP EXPR
+// gdb-command:print x
+// gdb-check:$30 = 43
+// gdb-command:print y
+// gdb-check:$31 = 44
+// gdb-command:print z
+// gdb-check:$32 = 45
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+#[no_split_stack]
+fn immediate_args(a: int, b: bool, c: f64) {
+ ()
+}
+
+struct BigStruct {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+ e: u64,
+ f: u64,
+ g: u64,
+ h: u64
+}
+
+#[no_split_stack]
+fn non_immediate_args(a: BigStruct, b: BigStruct) {
+ ()
+}
+
+#[no_split_stack]
+fn binding(a: i64, b: u64, c: f64) {
+ let x = 0;
+}
+
+#[no_split_stack]
+fn assignment(mut a: u64, b: u64, c: f64) {
+ a = b;
+}
+
+#[no_split_stack]
+fn function_call(x: u64, y: u64, z: f64) {
+ std::io::stdio::print("Hi!")
+}
+
+#[no_split_stack]
+fn identifier(x: u64, y: u64, z: f64) -> u64 {
+ x
+}
+
+#[no_split_stack]
+fn return_expr(x: u64, y: u64, z: f64) -> u64 {
+ return x;
+}
+
+#[no_split_stack]
+fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
+ x + y
+}
+
+#[no_split_stack]
+fn if_expr(x: u64, y: u64, z: f64) -> u64 {
+ if x + y < 1000 {
+ x
+ } else {
+ y
+ }
+}
+
+#[no_split_stack]
+fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
+ while x + y < 1000 {
+ x += z
+ }
+ return x;
+}
+
+#[no_split_stack]
+fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
+ loop {
+ x += z;
+
+ if x + y > 1000 {
+ return x;
+ }
+ }
+}
+
+fn main() {
+ immediate_args(1, true, 2.5);
+
+ non_immediate_args(
+ BigStruct {
+ a: 3,
+ b: 4,
+ c: 5,
+ d: 6,
+ e: 7,
+ f: 8,
+ g: 9,
+ h: 10
+ },
+ BigStruct {
+ a: 11,
+ b: 12,
+ c: 13,
+ d: 14,
+ e: 15,
+ f: 16,
+ g: 17,
+ h: 18
+ }
+ );
+
+ binding(19, 20, 21.5);
+ assignment(22, 23, 24.5);
+ function_call(25, 26, 27.5);
+ identifier(28, 29, 30.5);
+ return_expr(31, 32, 33.5);
+ arithmetic_expr(34, 35, 36.5);
+ if_expr(37, 38, 39.5);
+ while_expr(40, 41, 42);
+ loop_expr(43, 44, 45);
+}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print *t0
+// gdb-check:$1 = 1
+// gdb-command:print *t1
+// gdb-check:$2 = 2.5
+// gdb-command:print ret
+// gdb-check:$3 = {{1, 2.5}, {2.5, 1}}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *t0
+// gdb-check:$4 = 3.5
+// gdb-command:print *t1
+// gdb-check:$5 = 4
+// gdb-command:print ret
+// gdb-check:$6 = {{3.5, 4}, {4, 3.5}}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print *t0
+// gdb-check:$7 = 5
+// gdb-command:print *t1
+// gdb-check:$8 = {a = 6, b = 7.5}
+// gdb-command:print ret
+// gdb-check:$9 = {{5, {a = 6, b = 7.5}}, {{a = 6, b = 7.5}, 5}}
+// gdb-command:continue
+
+#[deriving(Clone)]
+struct Struct {
+ a: int,
+ b: f64
+}
+
+fn dup_tup<T0: Clone, T1: Clone>(t0: &T0, t1: &T1) -> ((T0, T1), (T1, T0)) {
+ let ret = ((t0.clone(), t1.clone()), (t1.clone(), t0.clone()));
+ zzz();
+ ret
+}
+
+fn main() {
+
+ let _ = dup_tup(&1, &2.5);
+ let _ = dup_tup(&3.5, &4_u16);
+ let _ = dup_tup(&5, &Struct { a: 6, b: 7.5 });
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = -1
+// gdb-command:print y
+// gdb-check:$2 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = -1
+// gdb-command:print y
+// gdb-check:$4 = 2.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = -2.5
+// gdb-command:print y
+// gdb-check:$6 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = -2.5
+// gdb-command:print y
+// gdb-check:$8 = 2.5
+// gdb-command:continue
+
+fn outer<TA: Clone>(a: TA) {
+ inner(a.clone(), 1);
+ inner(a.clone(), 2.5);
+
+ fn inner<TX, TY>(x: TX, y: TY) {
+ zzz();
+ }
+}
+
+fn main() {
+ outer(-1);
+ outer(-2.5);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = {8888, -8888}}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print/d arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = {8888, -8888}}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10.5
+// gdb-command:continue
+
+struct Struct<T> {
+ x: T
+}
+
+impl<T1> Struct<T1> {
+
+ fn self_by_ref<T2>(&self, arg1: int, arg2: T2) -> int {
+ zzz();
+ arg1
+ }
+
+ fn self_by_val<T2>(self, arg1: int, arg2: T2) -> int {
+ zzz();
+ arg1
+ }
+
+ fn self_owned<T2>(~self, arg1: int, arg2: T2) -> int {
+ zzz();
+ arg1
+ }
+}
+
+fn main() {
+ let stack = Struct { x: (8888_u32, -8888_i32) };
+ let _ = stack.self_by_ref(-1, -2_i8);
+ let _ = stack.self_by_val(-3, -4_i16);
+
+ let owned = box Struct { x: 1234.5 };
+ let _ = owned.self_by_ref(-5, -6_i32);
+ let _ = owned.self_by_val(-7, -8_i64);
+ let _ = owned.self_owned(-9, -10.5_f32);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STRUCT
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$1 = 1
+// gdb-command:print arg2
+// gdb-check:$2 = 2
+// gdb-command:continue
+
+// ENUM
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$3 = -3
+// gdb-command:print arg2
+// gdb-check:$4 = 4.5
+// gdb-command:print arg3
+// gdb-check:$5 = 5
+// gdb-command:continue
+
+#![feature(struct_variant)]
+
+struct Struct {
+ x: int
+}
+
+impl Struct {
+
+ fn static_method<T1, T2>(arg1: T1, arg2: T2) -> int {
+ zzz();
+ return 0;
+ }
+}
+
+enum Enum {
+ Variant1 { x: int },
+ Variant2,
+ Variant3(f64, int, char),
+}
+
+impl Enum {
+
+ fn static_method<T1, T2, T3>(arg1: T1, arg2: T2, arg3: T3) -> int {
+ zzz();
+ return 1;
+ }
+}
+
+fn main() {
+ Struct::static_method(1, 2);
+ Enum::static_method(-3, 4.5, 5);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print union on
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print case1
+// gdb-check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
+
+// gdb-command:print case2
+// gdb-check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
+
+// gdb-command:print case3
+// gdb-check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
+
+// gdb-command:print univariant
+// gdb-check:$4 = {a = -1}
+
+#![feature(struct_variant)]
+
+// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
+// substituted with something of size `xx` bits and the same alignment as an integer type of the
+// same size.
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular<T16, T32, T64> {
+ Case1 { a: T64, b: T16, c: T16, d: T16, e: T16},
+ Case2 { a: T64, b: T32, c: T32},
+ Case3 { a: T64, b: T64 }
+}
+
+enum Univariant<T> {
+ TheOnlyCase { a: T }
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let case1: Regular<u16, u32, i64> = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let case2: Regular<i16, u32, i64> = Case2 { a: 0, b: 286331153, c: 286331153 };
+
+ // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+ // 0b01011001010110010101100101011001 = 1499027801
+ // 0b0101100101011001 = 22873
+ // 0b01011001 = 89
+ let case3: Regular<u16, i32, u64> = Case3 { a: 0, b: 6438275382588823897 };
+
+ let univariant = TheOnlyCase { a: -1 };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print int_int
+// gdb-check:$1 = {key = 0, value = 1}
+// gdb-command:print int_float
+// gdb-check:$2 = {key = 2, value = 3.5}
+// gdb-command:print float_int
+// gdb-check:$3 = {key = 4.5, value = 5}
+// gdb-command:print float_int_float
+// gdb-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}}
+
+struct AGenericStruct<TKey, TValue> {
+ key: TKey,
+ value: TValue
+}
+
+fn main() {
+
+ let int_int = AGenericStruct { key: 0, value: 1 };
+ let int_float = AGenericStruct { key: 2, value: 3.5 };
+ let float_int = AGenericStruct { key: 4.5, value: 5 };
+ let float_int_float = AGenericStruct { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// ignore-test
+
+// 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.
+//
+// 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:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$1 = 1000
+// gdb-command:print *arg2
+// gdb-check:$2 = {1, 2.5}
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$3 = 2000
+// gdb-command:print *arg2
+// gdb-check:$4 = {3.5, {4, 5, 6}}
+// gdb-command:continue
+
+
+struct Struct {
+ x: int
+}
+
+trait Trait<T1> {
+ fn generic_static_default_method<T2>(arg1: int, arg2: &(T1, T2)) -> int {
+ zzz();
+ arg1
+ }
+}
+
+impl<T> Trait<T> for Struct {}
+
+fn main() {
+
+ // Is this really how to use these?
+ Trait::generic_static_default_method::<int, Struct, float>(1000, &(1, 2.5));
+ Trait::generic_static_default_method::<float, Struct, (int, int, int)>(2000, &(3.5, (4, 5, 6)));
+
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print union on
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print case1
+// gdb-check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
+
+// gdb-command:print case2
+// gdb-check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
+
+// gdb-command:print case3
+// gdb-check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
+
+// gdb-command:print univariant
+// gdb-check:$4 = {-1}
+
+
+// NOTE: This is a copy of the non-generic test case. The `Txx` type parameters have to be
+// substituted with something of size `xx` bits and the same alignment as an integer type of the
+// same size.
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular<T16, T32, T64> {
+ Case1(T64, T16, T16, T16, T16),
+ Case2(T64, T32, T32),
+ Case3(T64, T64)
+}
+
+enum Univariant<T64> {
+ TheOnlyCase(T64)
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let case1: Regular<u16, u32, u64> = Case1(0_u64, 31868_u16, 31868_u16, 31868_u16, 31868_u16);
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let case2: Regular<i16, i32, i64> = Case2(0_i64, 286331153_i32, 286331153_i32);
+
+ // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+ // 0b01011001010110010101100101011001 = 1499027801
+ // 0b0101100101011001 = 22873
+ // 0b01011001 = 89
+ let case3: Regular<i16, i32, i64> = Case3(0_i64, 6438275382588823897_i64);
+
+ let univariant = TheOnlyCase(-1_i64);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print string1.length
+// gdb-check:$1 = 48
+// gdb-command:print string2.length
+// gdb-check:$2 = 48
+// gdb-command:print string3.length
+// gdb-check:$3 = 48
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+// This test case makes sure that debug info does not ICE when include_str is
+// used multiple times (see issue #11322).
+
+fn main() {
+ let string1 = include_str!("text-to-include-1.txt");
+ let string2 = include_str!("text-to-include-2.txt");
+ let string3 = include_str!("text-to-include-3.txt");
+ zzz();
+}
+
+fn zzz() {()}
--- /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 was actually never run before because commands were only parsed up to the first
+// function definition but the test relied on the function being above the commands. Ignore for now.
+// ignore-test
+
+fn main() {
+ let args : ~[~str] = ::std::os::args();
+ ::std::io::println(args[0]);
+}
+
+// ignore-android: FIXME(#10381)
+
+// This test case checks whether compile unit names are set correctly, so that the correct default
+// source file can be found.
+
+// compile-flags:-g
+// gdb-command:list
+// gdb-check:1[...]fn main() {
+// gdb-check:2[...]let args : ~[~str] = ::std::os::args();
+// gdb-check:3[...]::std::io::println(args[0]);
+// gdb-check:4[...]}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:break issue12886.rs:29
+// gdb-command:run
+// gdb-command:next
+// gdb-check:[...]30[...]s
+// gdb-command:continue
+
+// IF YOU MODIFY THIS FILE, BE CAREFUL TO ADAPT THE LINE NUMBERS IN THE DEBUGGER COMMANDS
+
+// This test makes sure that gdb does not set unwanted breakpoints in inlined functions. If a
+// breakpoint existed in unwrap(), then calling `next` would (when stopped at line 27) would stop
+// in unwrap() instead of stepping over the function invocation. By making sure that `s` is
+// contained in the output, after calling `next` just once, we can be sure that we did not stop in
+// unwrap(). (The testing framework doesn't allow for checking that some text is *not* contained in
+// the output, which is why we have to make the test in this kind of roundabout way)
+fn bar() -> int {
+ let s = Some(5).unwrap();
+ s
+}
+
+fn main() {
+ let _ = bar();
+}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// aux-build:issue13213aux.rs
+extern crate issue13213aux;
+
+// compile-flags:-g
+
+// This tests make sure that we get no linker error when using a completely inlined static. Some
+// statics that are marked with AvailableExternallyLinkage in the importing crate, may actually not
+// be available because they have been optimized out from the exporting crate.
+fn main() {
+ let b: issue13213aux::S = issue13213aux::A;
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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:--debuginfo=1
+
+pub trait TraitWithDefaultMethod {
+ fn method(self) {
+ ()
+ }
+}
+
+struct MyStruct;
+
+impl TraitWithDefaultMethod for MyStruct { }
+
+pub fn main() {
+ MyStruct.method();
+}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// FIRST ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = -1
+// gdb-command:continue
+
+// SECOND ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 2
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = -2
+// gdb-command:continue
+
+// THIRD ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 3
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = -3
+// gdb-command:continue
+
+// AFTER LOOP
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = 1000000
+// gdb-command:continue
+
+fn main() {
+
+ let range = [1, 2, 3];
+
+ let x = 1000000; // wan meeeljen doollaars!
+
+ for &x in range.iter() {
+ zzz();
+ sentinel();
+
+ let x = -1 * x;
+
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// BEFORE if
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = 999
+// gdb-command:print y
+// gdb-check:$2 = -1
+// gdb-command:continue
+
+// AT BEGINNING of 'then' block
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 999
+// gdb-command:print y
+// gdb-check:$4 = -1
+// gdb-command:continue
+
+// AFTER 1st redeclaration of 'x'
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 1001
+// gdb-command:print y
+// gdb-check:$6 = -1
+// gdb-command:continue
+
+// AFTER 2st redeclaration of 'x'
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = 1002
+// gdb-command:print y
+// gdb-check:$8 = 1003
+// gdb-command:continue
+
+// AFTER 1st if expression
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$9 = 999
+// gdb-command:print y
+// gdb-check:$10 = -1
+// gdb-command:continue
+
+// BEGINNING of else branch
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$11 = 999
+// gdb-command:print y
+// gdb-check:$12 = -1
+// gdb-command:continue
+
+// BEGINNING of else branch
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$13 = 1004
+// gdb-command:print y
+// gdb-check:$14 = 1005
+// gdb-command:continue
+
+// BEGINNING of else branch
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$15 = 999
+// gdb-command:print y
+// gdb-check:$16 = -1
+// gdb-command:continue
+
+fn main() {
+
+ let x = 999;
+ let y = -1;
+
+ zzz();
+ sentinel();
+
+ if x < 1000 {
+ zzz();
+ sentinel();
+
+ let x = 1001;
+
+ zzz();
+ sentinel();
+
+ let x = 1002;
+ let y = 1003;
+ zzz();
+ sentinel();
+ } else {
+ unreachable!();
+ }
+
+ zzz();
+ sentinel();
+
+ if x > 1000 {
+ unreachable!();
+ } else {
+ zzz();
+ sentinel();
+
+ let x = 1004;
+ let y = 1005;
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$1 = 231
+// gdb-command:print not_shadowed
+// gdb-check:$2 = 232
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$3 = 233
+// gdb-command:print not_shadowed
+// gdb-check:$4 = 232
+// gdb-command:print local_to_arm
+// gdb-check:$5 = 234
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$6 = 236
+// gdb-command:print not_shadowed
+// gdb-check:$7 = 232
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$8 = 237
+// gdb-command:print not_shadowed
+// gdb-check:$9 = 232
+// gdb-command:print local_to_arm
+// gdb-check:$10 = 238
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$11 = 239
+// gdb-command:print not_shadowed
+// gdb-check:$12 = 232
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$13 = 241
+// gdb-command:print not_shadowed
+// gdb-check:$14 = 232
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$15 = 243
+// gdb-command:print *local_to_arm
+// gdb-check:$16 = 244
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print shadowed
+// gdb-check:$17 = 231
+// gdb-command:print not_shadowed
+// gdb-check:$18 = 232
+// gdb-command:continue
+
+struct Struct {
+ x: int,
+ y: int
+}
+
+fn main() {
+
+ let shadowed = 231;
+ let not_shadowed = 232;
+
+ zzz();
+ sentinel();
+
+ match (233, 234) {
+ (shadowed, local_to_arm) => {
+
+ zzz();
+ sentinel();
+ }
+ }
+
+ match (235, 236) {
+ // with literal
+ (235, shadowed) => {
+
+ zzz();
+ sentinel();
+ }
+ _ => {}
+ }
+
+ match Struct { x: 237, y: 238 } {
+ Struct { x: shadowed, y: local_to_arm } => {
+
+ zzz();
+ sentinel();
+ }
+ }
+
+ match Struct { x: 239, y: 240 } {
+ // ignored field
+ Struct { x: shadowed, .. } => {
+
+ zzz();
+ sentinel();
+ }
+ }
+
+ match Struct { x: 241, y: 242 } {
+ // with literal
+ Struct { x: shadowed, y: 242 } => {
+
+ zzz();
+ sentinel();
+ }
+ _ => {}
+ }
+
+ match (243, 244) {
+ (shadowed, ref local_to_arm) => {
+
+ zzz();
+ sentinel();
+ }
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:--debuginfo=1
+// gdb-command:run
+
+// Nothing to do here really, just make sure it compiles. See issue #8513.
+fn main() {
+ let _ = ||();
+ let _ = range(1u,3).map(|_| 5);
+}
+
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 1000
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = 2.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = false
+// gdb-command:continue
+
+fn main() {
+
+ let x = false;
+
+ zzz();
+ sentinel();
+
+ let stack_closure: |int| = |x| {
+ zzz();
+ sentinel();
+
+ let x = 2.5;
+
+ zzz();
+ sentinel();
+
+ let x = true;
+
+ zzz();
+ sentinel();
+ };
+
+ zzz();
+ sentinel();
+
+ stack_closure(1000);
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// FIRST ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = 0
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = 101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = -987
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = 101
+// gdb-command:continue
+
+
+// SECOND ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$8 = 2
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$9 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$10 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$11 = -987
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$12 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$13 = 2
+// gdb-command:continue
+
+fn main() {
+
+ let mut x = 0;
+
+ loop {
+ if x >= 2 {
+ break;
+ }
+
+ zzz();
+ sentinel();
+
+ x += 1;
+ zzz();
+ sentinel();
+
+ // Shadow x
+ let x = x + 100;
+ zzz();
+ sentinel();
+
+ // open scope within loop's top level scope
+ {
+ zzz();
+ sentinel();
+
+ let x = -987;
+
+ zzz();
+ sentinel();
+ }
+
+ // Check that we get the x before the inner scope again
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 1000
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = 2.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = false
+// gdb-command:continue
+
+fn main() {
+
+ let x = false;
+
+ zzz();
+ sentinel();
+
+ let unique_closure: proc(int) = proc(x) {
+ zzz();
+ sentinel();
+
+ let x = 2.5;
+
+ zzz();
+ sentinel();
+
+ let x = true;
+
+ zzz();
+ sentinel();
+ };
+
+ zzz();
+ sentinel();
+
+ unique_closure(1000);
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// FIRST ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = 0
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = 101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = -987
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = 101
+// gdb-command:continue
+
+
+// SECOND ITERATION
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = 1
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$8 = 2
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$9 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$10 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$11 = -987
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$12 = 102
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$13 = 2
+// gdb-command:continue
+
+fn main() {
+
+ let mut x = 0;
+
+ while x < 2 {
+ zzz();
+ sentinel();
+
+ x += 1;
+ zzz();
+ sentinel();
+
+ // Shadow x
+ let x = x + 100;
+ zzz();
+ sentinel();
+
+ // open scope within loop's top level scope
+ {
+ zzz();
+ sentinel();
+
+ let x = -987;
+
+ zzz();
+ sentinel();
+ }
+
+ // Check that we get the x before the inner scope again
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$1 = 10
+// gdb-command:print b
+// gdb-check:$2 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$3 = 890242
+// gdb-command:print b
+// gdb-check:$4 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$5 = 10
+// gdb-command:print b
+// gdb-check:$6 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$7 = 102
+// gdb-command:print b
+// gdb-check:$8 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$9 = 110
+// gdb-command:print b
+// gdb-check:$10 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$11 = 10
+// gdb-command:print b
+// gdb-check:$12 = 34
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$13 = 10
+// gdb-command:print b
+// gdb-check:$14 = 34
+// gdb-command:print c
+// gdb-check:$15 = 400
+// gdb-command:continue
+
+#![feature(macro_rules)]
+
+macro_rules! trivial(
+ ($e1:expr) => ($e1)
+)
+
+macro_rules! no_new_scope(
+ ($e1:expr) => (($e1 + 2) - 1)
+)
+
+macro_rules! new_scope(
+ () => ({
+ let a = 890242;
+ zzz();
+ sentinel();
+ })
+)
+
+macro_rules! shadow_within_macro(
+ ($e1:expr) => ({
+ let a = $e1 + 2;
+
+ zzz();
+ sentinel();
+
+ let a = $e1 + 10;
+
+ zzz();
+ sentinel();
+ })
+)
+
+
+macro_rules! dup_expr(
+ ($e1:expr) => (($e1) + ($e1))
+)
+
+
+fn main() {
+
+ let a = trivial!(10);
+ let b = no_new_scope!(33);
+
+ zzz();
+ sentinel();
+
+ new_scope!();
+
+ zzz();
+ sentinel();
+
+ shadow_within_macro!(100);
+
+ zzz();
+ sentinel();
+
+ let c = dup_expr!(10 * 20);
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$1 = 0
+
+// STRUCT EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$2 = -1
+// gdb-command:print ten
+// gdb-check:$3 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$4 = 11
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$5 = 1
+// gdb-command:print ten
+// gdb-check:$6 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$7 = -1
+// gdb-command:print ten
+// gdb-check:$8 = 10
+// gdb-command:continue
+
+// FUNCTION CALL
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$9 = -1
+// gdb-command:print ten
+// gdb-check:$10 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$11 = 12
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$12 = 2
+// gdb-command:print ten
+// gdb-check:$13 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$14 = -1
+// gdb-command:print ten
+// gdb-check:$15 = 10
+// gdb-command:continue
+
+// TUPLE EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$16 = -1
+// gdb-command:print ten
+// gdb-check:$17 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$18 = 13
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$19 = 3
+// gdb-command:print ten
+// gdb-check:$20 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$21 = -1
+// gdb-command:print ten
+// gdb-check:$22 = 10
+// gdb-command:continue
+
+// VEC EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$23 = -1
+// gdb-command:print ten
+// gdb-check:$24 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$25 = 14
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$26 = 4
+// gdb-command:print ten
+// gdb-check:$27 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$28 = -1
+// gdb-command:print ten
+// gdb-check:$29 = 10
+// gdb-command:continue
+
+// REPEAT VEC EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$30 = -1
+// gdb-command:print ten
+// gdb-check:$31 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$32 = 15
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$33 = 5
+// gdb-command:print ten
+// gdb-check:$34 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$35 = -1
+// gdb-command:print ten
+// gdb-check:$36 = 10
+// gdb-command:continue
+
+// ASSIGNMENT EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$37 = -1
+// gdb-command:print ten
+// gdb-check:$38 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$39 = 16
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$40 = 6
+// gdb-command:print ten
+// gdb-check:$41 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$42 = -1
+// gdb-command:print ten
+// gdb-check:$43 = 10
+// gdb-command:continue
+
+
+// ARITHMETIC EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$44 = -1
+// gdb-command:print ten
+// gdb-check:$45 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$46 = 17
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$47 = 7
+// gdb-command:print ten
+// gdb-check:$48 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$49 = -1
+// gdb-command:print ten
+// gdb-check:$50 = 10
+// gdb-command:continue
+
+// INDEX EXPRESSION
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$51 = -1
+// gdb-command:print ten
+// gdb-check:$52 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$53 = 18
+// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT'
+// gdb-check:$54 = 8
+// gdb-command:print ten
+// gdb-check:$55 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print val
+// gdb-check:$56 = -1
+// gdb-command:print ten
+// gdb-check:$57 = 10
+// gdb-command:continue
+
+#![allow(unused_variable)]
+#![allow(dead_assignment)]
+
+static mut MUT_INT: int = 0;
+
+struct Point {
+ x: int,
+ y: int
+}
+
+fn a_function(x: int) -> int {
+ x + 1
+}
+
+fn main() {
+
+ let val = -1;
+ let ten = 10;
+
+ // surrounded by struct expression
+ let point = Point {
+ x: {
+ zzz();
+ sentinel();
+
+ let val = ten + 1;
+ unsafe {MUT_INT = 1;};
+
+ zzz();
+ sentinel();
+
+ val
+ },
+ y: 10
+ };
+
+ zzz();
+ sentinel();
+
+ // surrounded by function call
+ let _ = a_function({
+ zzz();
+ sentinel();
+
+ let val = ten + 2;
+ unsafe {MUT_INT = 2;};
+
+ zzz();
+ sentinel();
+
+ val
+ });
+
+ zzz();
+ sentinel();
+
+
+ // surrounded by tup
+ let _ = ({
+ zzz();
+ sentinel();
+
+ let val = ten + 3;
+ unsafe {MUT_INT = 3;};
+
+ zzz();
+ sentinel();
+
+ val
+ }, 0);
+
+ zzz();
+ sentinel();
+
+ // surrounded by vec
+ let _ = [{
+ zzz();
+ sentinel();
+
+ let val = ten + 4;
+ unsafe {MUT_INT = 4;};
+
+ zzz();
+ sentinel();
+
+ val
+ }, 0, 0];
+
+ zzz();
+ sentinel();
+
+ // surrounded by repeat vec
+ let _ = [{
+ zzz();
+ sentinel();
+
+ let val = ten + 5;
+ unsafe {MUT_INT = 5;};
+
+ zzz();
+ sentinel();
+
+ val
+ }, ..10];
+
+ zzz();
+ sentinel();
+
+ // assignment expression
+ let mut var = 0;
+ var = {
+ zzz();
+ sentinel();
+
+ let val = ten + 6;
+ unsafe {MUT_INT = 6;};
+
+ zzz();
+ sentinel();
+
+ val
+ };
+
+ zzz();
+ sentinel();
+
+ // arithmetic expression
+ var = 10 + -{
+ zzz();
+ sentinel();
+
+ let val = ten + 7;
+ unsafe {MUT_INT = 7;};
+
+ zzz();
+ sentinel();
+
+ val
+ } * 5;
+
+ zzz();
+ sentinel();
+
+ // index expression
+ let a_vector = [10, ..20];
+ let _ = a_vector[{
+ zzz();
+ sentinel();
+
+ let val = ten + 8;
+ unsafe {MUT_INT = 8;};
+
+ zzz();
+ sentinel();
+
+ val as uint
+ }];
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:--debuginfo=1
+
+// Make sure functions have proper names
+// gdb-command:info functions
+// gdb-check:[...]void[...]main([...]);
+// gdb-check:[...]void[...]some_function([...]);
+// gdb-check:[...]void[...]some_other_function([...]);
+// gdb-check:[...]void[...]zzz([...]);
+
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// Make sure there is no information about locals
+// gdb-command:finish
+// gdb-command:info locals
+// gdb-check:No locals.
+// gdb-command:continue
+
+
+#![allow(unused_variable)]
+
+struct Struct {
+ a: i64,
+ b: i32
+}
+
+fn main() {
+ some_function(101, 202);
+ some_other_function(1, 2);
+}
+
+
+fn zzz() {()}
+
+fn some_function(a: int, b: int) {
+ let some_variable = Struct { a: 11, b: 22 };
+ let some_other_variable = 23;
+ zzz();
+}
+
+fn some_other_function(a: int, b: int) -> bool { true }
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print the_a->val
+// gdb-check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// gdb-command:print the_b->val
+// gdb-check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// gdb-command:print univariant->val
+// gdb-check:$3 = {-9747455}
+
+#![allow(unused_variable)]
+#![feature(struct_variant, managed_boxes)]
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+ TheA { x: i64, y: i64 },
+ TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+ TheOnlyCase(i64)
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let the_a = @TheA { x: 0, y: 8970181431921507452 };
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let the_b = @TheB (0, 286331153, 286331153);
+
+ let univariant = @TheOnlyCase(-9747455);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print unique.ptr[0]->val
+// gdb-check:$1 = 10
+
+// gdb-command:print unique.ptr[1]->val
+// gdb-check:$2 = 11
+
+// gdb-command:print unique.ptr[2]->val
+// gdb-check:$3 = 12
+
+// gdb-command:print unique.ptr[3]->val
+// gdb-check:$4 = 13
+
+#![allow(unused_variable)]
+
+fn main() {
+
+ let unique: Vec<@i64> = vec!(@10, @11, @12, @13);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *ordinary_unique
+// gdb-check:$1 = {-1, -2}
+
+// gdb-command:print managed_within_unique->x
+// gdb-check:$2 = -3
+
+// gdb-command:print managed_within_unique->y->val
+// gdb-check:$3 = -4
+
+#![allow(unused_variable)]
+
+struct ContainsManaged {
+ x: int,
+ y: @int
+}
+
+fn main() {
+ let ordinary_unique = box() (-1, -2);
+
+ let managed_within_unique = box ContainsManaged { x: -3, y: @-4 };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {{Variant2, [...]}, {Variant2, 117901063}}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {{Variant2, [...]}, {Variant2, 117901063}}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {{Variant1, x = 1799, y = 1799}, {Variant1, [...]}}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+#![feature(struct_variant)]
+
+enum Enum {
+ Variant1 { x: u16, y: u16 },
+ Variant2 (u32)
+}
+
+impl Enum {
+
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+}
+
+fn main() {
+ let stack = Variant2(117901063);
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box Variant1{ x: 1799, y: 1799 };
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = {8888, -8888}}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = {8888, -8888}}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 1234.5}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+struct Struct<T> {
+ x: T
+}
+
+impl<T> Struct<T> {
+
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+}
+
+fn main() {
+ let stack = Struct { x: (8888_u32, -8888_i32) };
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box Struct { x: 1234.5 };
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+struct Struct {
+ x: int
+}
+
+impl Struct {
+
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+}
+
+fn main() {
+ let stack = Struct { x: 100 };
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box Struct { x: 200 };
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+struct Struct {
+ x: int
+}
+
+trait Trait {
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int;
+ fn self_by_val(self, arg1: int, arg2: int) -> int;
+ fn self_owned(~self, arg1: int, arg2: int) -> int;
+}
+
+impl Trait for Struct {
+
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ self.x + arg1 + arg2
+ }
+}
+
+fn main() {
+ let stack = Struct { x: 100 };
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box Struct { x: 200 };
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {100, -100.5}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {100, -100.5}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {200, -200.5}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {200, -200.5}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {200, -200.5}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+struct TupleStruct(int, f64);
+
+impl TupleStruct {
+
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+}
+
+fn main() {
+ let stack = TupleStruct(100, -100.5);
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box TupleStruct(200, -200.5);
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print abc
+// gdb-check:$1 = 10101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print abc
+// gdb-check:$2 = 20202
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print abc
+// gdb-check:$3 = 30303
+
+#![allow(unused_variable)]
+
+fn function_one() {
+ let abc = 10101;
+ zzz();
+}
+
+fn function_two() {
+ let abc = 20202;
+ zzz();
+}
+
+
+fn function_three() {
+ let abc = 30303;
+ zzz();
+}
+
+
+fn main() {
+ function_one();
+ function_two();
+ function_three();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print a
+// gdb-check:$1 = 10101
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print b
+// gdb-check:$2 = 20202
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print c
+// gdb-check:$3 = 30303
+
+#![allow(unused_variable)]
+
+fn function_one() {
+ let a = 10101;
+ zzz();
+}
+
+fn function_two() {
+ let b = 20202;
+ zzz();
+}
+
+
+fn function_three() {
+ let c = 30303;
+ zzz();
+}
+
+
+fn main() {
+ function_one();
+ function_two();
+ function_three();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:print y
+// gdb-check:$2 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 10
+// gdb-command:print y
+// gdb-check:$4 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 10.5
+// gdb-command:print y
+// gdb-check:$6 = 20
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = true
+// gdb-command:print y
+// gdb-check:$8 = 2220
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$9 = 203203.5
+// gdb-command:print y
+// gdb-check:$10 = 2220
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$11 = 10.5
+// gdb-command:print y
+// gdb-check:$12 = 20
+// gdb-command:continue
+
+fn main() {
+ let x = false;
+ let y = true;
+
+ zzz();
+ sentinel();
+
+ let x = 10;
+
+ zzz();
+ sentinel();
+
+ let x = 10.5;
+ let y = 20;
+
+ zzz();
+ sentinel();
+
+ {
+ let x = true;
+ let y = 2220;
+
+ zzz();
+ sentinel();
+
+ let x = 203203.5;
+
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print first
+// gdb-check:$1 = {<No data fields>}
+
+// gdb-command:print second
+// gdb-check:$2 = {<No data fields>}
+
+#![allow(unused_variable)]
+
+enum ANilEnum {}
+enum AnotherNilEnum {}
+
+// I (mw) am not sure this test case makes much sense...
+// Also, it relies on some implementation details:
+// 1. That empty enums as well as '()' are represented as empty structs
+// 2. That gdb prints the string "{<No data fields>}" for empty structs (which may change some time)
+fn main() {
+ unsafe {
+ let first: ANilEnum = std::cast::transmute(());
+ let second: AnotherNilEnum = std::cast::transmute(());
+
+ zzz();
+ }
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print some
+// gdb-check:$1 = {0x12345678}
+
+// gdb-command:print none
+// gdb-check:$2 = {0x0}
+
+// gdb-command:print full
+// gdb-check:$3 = {454545, 0x87654321, 9988}
+
+// gdb-command:print empty->discr
+// gdb-check:$4 = (int *) 0x0
+
+// gdb-command:print droid
+// gdb-check:$5 = {id = 675675, range = 10000001, internals = 0x43218765}
+
+// gdb-command:print void_droid->internals
+// gdb-check:$6 = (int *) 0x0
+
+// gdb-command:continue
+
+#![feature(struct_variant)]
+
+// If a struct has exactly two variants, one of them is empty, and the other one
+// contains a non-nullable pointer, then this value is used as the discriminator.
+// The test cases in this file make sure that something readable is generated for
+// this kind of types.
+// Unfortunately (for these test cases) the content of the non-discriminant fields
+// in the null-case is not defined. So we just read the discriminator field in
+// this case (by casting the value to a memory-equivalent struct).
+
+enum MoreFields<'a> {
+ Full(u32, &'a int, i16),
+ Empty
+}
+
+struct MoreFieldsRepr<'a> {
+ a: u32,
+ discr: &'a int,
+ b: i16
+}
+
+enum NamedFields<'a> {
+ Droid { id: i32, range: i64, internals: &'a int },
+ Void
+}
+
+struct NamedFieldsRepr<'a> {
+ id: i32,
+ range: i64,
+ internals: &'a int
+}
+
+fn main() {
+
+ let some: Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) });
+ let none: Option<&u32> = None;
+
+ let full = Full(454545, unsafe { std::cast::transmute(0x87654321) }, 9988);
+
+ let int_val = 0;
+ let empty: &MoreFieldsRepr = unsafe { std::cast::transmute(&Empty) };
+
+ let droid = Droid {
+ id: 675675,
+ range: 10000001,
+ internals: unsafe { std::cast::transmute(0x43218765) }
+ };
+
+ let void_droid: &NamedFieldsRepr = unsafe { std::cast::transmute(&Void) };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print packed
+// gdb-check:$1 = {x = 123, y = 234, z = 345}
+
+// gdb-command:print packedInPacked
+// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
+
+// gdb-command:print packedInUnpacked
+// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
+
+// gdb-command:print unpackedInPacked
+// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210}
+
+
+// gdb-command:print packedInPackedWithDrop
+// gdb-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}}
+
+// gdb-command:print packedInUnpackedWithDrop
+// gdb-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}}
+
+// gdb-command:print unpackedInPackedWithDrop
+// gdb-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21}
+
+// gdb-command:print deeplyNested
+// gdb-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}}
+
+#![allow(unused_variable)]
+
+#[packed]
+struct Packed {
+ x: i16,
+ y: i32,
+ z: i64
+}
+
+impl Drop for Packed {
+ fn drop(&mut self) {}
+}
+
+#[packed]
+struct PackedInPacked {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+struct PackedInUnpacked {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+struct Unpacked {
+ x: i64,
+ y: i32,
+ z: i16
+}
+
+impl Drop for Unpacked {
+ fn drop(&mut self) {}
+}
+
+#[packed]
+struct UnpackedInPacked {
+ a: i16,
+ b: Unpacked,
+ c: Unpacked,
+ d: i64
+}
+
+#[packed]
+struct PackedInPackedWithDrop {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+impl Drop for PackedInPackedWithDrop {
+ fn drop(&mut self) {}
+}
+
+struct PackedInUnpackedWithDrop {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+impl Drop for PackedInUnpackedWithDrop {
+ fn drop(&mut self) {}
+}
+
+#[packed]
+struct UnpackedInPackedWithDrop {
+ a: i16,
+ b: Unpacked,
+ c: Unpacked,
+ d: i64
+}
+
+impl Drop for UnpackedInPackedWithDrop {
+ fn drop(&mut self) {}
+}
+
+struct DeeplyNested {
+ a: PackedInPacked,
+ b: UnpackedInPackedWithDrop,
+ c: PackedInUnpacked,
+ d: PackedInUnpackedWithDrop,
+ e: UnpackedInPacked,
+ f: PackedInPackedWithDrop
+}
+
+fn main() {
+ let packed = Packed { x: 123, y: 234, z: 345 };
+
+ let packedInPacked = PackedInPacked {
+ a: 1111,
+ b: Packed { x: 2222, y: 3333, z: 4444 },
+ c: 5555,
+ d: Packed { x: 6666, y: 7777, z: 8888 }
+ };
+
+ let packedInUnpacked = PackedInUnpacked {
+ a: -1111,
+ b: Packed { x: -2222, y: -3333, z: -4444 },
+ c: -5555,
+ d: Packed { x: -6666, y: -7777, z: -8888 }
+ };
+
+ let unpackedInPacked = UnpackedInPacked {
+ a: 987,
+ b: Unpacked { x: 876, y: 765, z: 654 },
+ c: Unpacked { x: 543, y: 432, z: 321 },
+ d: 210
+ };
+
+ let packedInPackedWithDrop = PackedInPackedWithDrop {
+ a: 11,
+ b: Packed { x: 22, y: 33, z: 44 },
+ c: 55,
+ d: Packed { x: 66, y: 77, z: 88 }
+ };
+
+ let packedInUnpackedWithDrop = PackedInUnpackedWithDrop {
+ a: -11,
+ b: Packed { x: -22, y: -33, z: -44 },
+ c: -55,
+ d: Packed { x: -66, y: -77, z: -88 }
+ };
+
+ let unpackedInPackedWithDrop = UnpackedInPackedWithDrop {
+ a: 98,
+ b: Unpacked { x: 87, y: 76, z: 65 },
+ c: Unpacked { x: 54, y: 43, z: 32 },
+ d: 21
+ };
+
+ let deeplyNested = DeeplyNested {
+ a: PackedInPacked {
+ a: 1,
+ b: Packed { x: 2, y: 3, z: 4 },
+ c: 5,
+ d: Packed { x: 6, y: 7, z: 8 }
+ },
+ b: UnpackedInPackedWithDrop {
+ a: 9,
+ b: Unpacked { x: 10, y: 11, z: 12 },
+ c: Unpacked { x: 13, y: 14, z: 15 },
+ d: 16
+ },
+ c: PackedInUnpacked {
+ a: 17,
+ b: Packed { x: 18, y: 19, z: 20 },
+ c: 21,
+ d: Packed { x: 22, y: 23, z: 24 }
+ },
+ d: PackedInUnpackedWithDrop {
+ a: 25,
+ b: Packed { x: 26, y: 27, z: 28 },
+ c: 29,
+ d: Packed { x: 30, y: 31, z: 32 }
+ },
+ e: UnpackedInPacked {
+ a: 33,
+ b: Unpacked { x: 34, y: 35, z: 36 },
+ c: Unpacked { x: 37, y: 38, z: 39 },
+ d: 40
+ },
+ f: PackedInPackedWithDrop {
+ a: 41,
+ b: Packed { x: 42, y: 43, z: 44 },
+ c: 45,
+ d: Packed { x: 46, y: 47, z: 48 }
+ }
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print packed
+// gdb-check:$1 = {x = 123, y = 234, z = 345}
+
+// gdb-command:print packedInPacked
+// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
+
+// gdb-command:print packedInUnpacked
+// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
+
+// gdb-command:print unpackedInPacked
+// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98}
+
+// gdb-command:print sizeof(packed)
+// gdb-check:$5 = 14
+
+// gdb-command:print sizeof(packedInPacked)
+// gdb-check:$6 = 40
+
+#![allow(unused_variable)]
+
+#[packed]
+struct Packed {
+ x: i16,
+ y: i32,
+ z: i64
+}
+
+#[packed]
+struct PackedInPacked {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+// layout (64 bit): aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd..
+struct PackedInUnpacked {
+ a: i32,
+ b: Packed,
+ c: i64,
+ d: Packed
+}
+
+// layout (64 bit): xx.. yyyy zz.. .... wwww wwww
+struct Unpacked {
+ x: i16,
+ y: i32,
+ z: i16,
+ w: i64
+}
+
+// layout (64 bit): aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd
+#[packed]
+struct UnpackedInPacked {
+ a: i16,
+ b: Unpacked,
+ c: Unpacked,
+ d: i64
+}
+
+fn main() {
+ let packed = Packed { x: 123, y: 234, z: 345 };
+
+ let packedInPacked = PackedInPacked {
+ a: 1111,
+ b: Packed { x: 2222, y: 3333, z: 4444 },
+ c: 5555,
+ d: Packed { x: 6666, y: 7777, z: 8888 }
+ };
+
+ let packedInUnpacked = PackedInUnpacked {
+ a: -1111,
+ b: Packed { x: -2222, y: -3333, z: -4444 },
+ c: -5555,
+ d: Packed { x: -6666, y: -7777, z: -8888 }
+ };
+
+ let unpackedInPacked = UnpackedInPacked {
+ a: 987,
+ b: Unpacked { x: 876, y: 765, z: 654, w: 543 },
+ c: Unpacked { x: 432, y: 321, z: 210, w: 109 },
+ d: -98
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:run
+
+// Test whether compiling a recursive enum definition crashes debug info generation. The test case
+// is taken from issue #11083.
+
+#![allow(unused_variable)]
+
+pub struct Window<'a> {
+ callbacks: WindowCallbacks<'a>
+}
+
+struct WindowCallbacks<'a> {
+ pos_callback: Option<WindowPosCallback<'a>>,
+}
+
+pub type WindowPosCallback<'a> = |&Window, i32, i32|: 'a;
+
+fn main() {
+ let x = WindowCallbacks { pos_callback: None };
+}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+#![feature(managed_boxes)]
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print stack_unique.value
+// gdb-check:$1 = 0
+// gdb-command:print stack_unique.next.val->value
+// gdb-check:$2 = 1
+
+// gdb-command:print unique_unique->value
+// gdb-check:$3 = 2
+// gdb-command:print unique_unique->next.val->value
+// gdb-check:$4 = 3
+
+// gdb-command:print box_unique->val.value
+// gdb-check:$5 = 4
+// gdb-command:print box_unique->val.next.val->value
+// gdb-check:$6 = 5
+
+// gdb-command:print vec_unique[0].value
+// gdb-check:$7 = 6.5
+// gdb-command:print vec_unique[0].next.val->value
+// gdb-check:$8 = 7.5
+
+// gdb-command:print borrowed_unique->value
+// gdb-check:$9 = 8.5
+// gdb-command:print borrowed_unique->next.val->value
+// gdb-check:$10 = 9.5
+
+// MANAGED
+// gdb-command:print stack_managed.value
+// gdb-check:$11 = 10
+// gdb-command:print stack_managed.next.val->val.value
+// gdb-check:$12 = 11
+
+// gdb-command:print unique_managed->value
+// gdb-check:$13 = 12
+// gdb-command:print unique_managed->next.val->val.value
+// gdb-check:$14 = 13
+
+// gdb-command:print box_managed->val.value
+// gdb-check:$15 = 14
+// gdb-command:print box_managed->val.next.val->val.value
+// gdb-check:$16 = 15
+
+// gdb-command:print vec_managed[0].value
+// gdb-check:$17 = 16.5
+// gdb-command:print vec_managed[0].next.val->val.value
+// gdb-check:$18 = 17.5
+
+// gdb-command:print borrowed_managed->value
+// gdb-check:$19 = 18.5
+// gdb-command:print borrowed_managed->next.val->val.value
+// gdb-check:$20 = 19.5
+
+// LONG CYCLE
+// gdb-command:print long_cycle1.value
+// gdb-check:$21 = 20
+// gdb-command:print long_cycle1.next->value
+// gdb-check:$22 = 21
+// gdb-command:print long_cycle1.next->next->value
+// gdb-check:$23 = 22
+// gdb-command:print long_cycle1.next->next->next->value
+// gdb-check:$24 = 23
+
+// gdb-command:print long_cycle2.value
+// gdb-check:$25 = 24
+// gdb-command:print long_cycle2.next->value
+// gdb-check:$26 = 25
+// gdb-command:print long_cycle2.next->next->value
+// gdb-check:$27 = 26
+
+// gdb-command:print long_cycle3.value
+// gdb-check:$28 = 27
+// gdb-command:print long_cycle3.next->value
+// gdb-check:$29 = 28
+
+// gdb-command:print long_cycle4.value
+// gdb-check:$30 = 29.5
+
+// gdb-command:print (*****long_cycle_w_anonymous_types).value
+// gdb-check:$31 = 30
+
+// gdb-command:print (*****((*****long_cycle_w_anonymous_types).next.val)).value
+// gdb-check:$32 = 31
+
+// gdb-command:continue
+
+#![allow(unused_variable)]
+#![feature(struct_variant)]
+
+
+enum Opt<T> {
+ Empty,
+ Val { val: T }
+}
+
+struct UniqueNode<T> {
+ next: Opt<Box<UniqueNode<T>>>,
+ value: T
+}
+
+struct ManagedNode<T> {
+ next: Opt<@ManagedNode<T>>,
+ value: T
+}
+
+struct LongCycle1<T> {
+ next: Box<LongCycle2<T>>,
+ value: T,
+}
+
+struct LongCycle2<T> {
+ next: Box<LongCycle3<T>>,
+ value: T,
+}
+
+struct LongCycle3<T> {
+ next: Box<LongCycle4<T>>,
+ value: T,
+}
+
+struct LongCycle4<T> {
+ next: Option<Box<LongCycle1<T>>>,
+ value: T,
+}
+
+struct LongCycleWithAnonymousTypes {
+ next: Opt<Box<Box<Box<Box<Box<LongCycleWithAnonymousTypes>>>>>>,
+ value: uint,
+}
+
+// This test case makes sure that recursive structs are properly described. The Node structs are
+// generic so that we can have a new type (that newly needs to be described) for the different
+// cases. The potential problem with recursive types is that the DI generation algorithm gets
+// trapped in an endless loop. To make sure, we actually test this in the different cases, we have
+// to operate on a new type each time, otherwise we would just hit the DI cache for all but the
+// first case.
+
+// The different cases below (stack_*, unique_*, box_*, etc) are set up so that the type description
+// algorithm will enter the type reference cycle that is created by a recursive definition from a
+// different context each time.
+
+// The "long cycle" cases are constructed to span a longer, indirect recursion cycle between types.
+// The different locals will cause the DI algorithm to enter the type reference cycle at different
+// points.
+
+fn main() {
+ let stack_unique: UniqueNode<u16> = UniqueNode {
+ next: Val {
+ val: box UniqueNode {
+ next: Empty,
+ value: 1_u16,
+ }
+ },
+ value: 0_u16,
+ };
+
+ let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
+ next: Val {
+ val: box UniqueNode {
+ next: Empty,
+ value: 3,
+ }
+ },
+ value: 2,
+ };
+
+ let box_unique: @UniqueNode<u64> = @UniqueNode {
+ next: Val {
+ val: box UniqueNode {
+ next: Empty,
+ value: 5,
+ }
+ },
+ value: 4,
+ };
+
+ let vec_unique: [UniqueNode<f32>, ..1] = [UniqueNode {
+ next: Val {
+ val: box UniqueNode {
+ next: Empty,
+ value: 7.5,
+ }
+ },
+ value: 6.5,
+ }];
+
+ let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
+ next: Val {
+ val: box UniqueNode {
+ next: Empty,
+ value: 9.5,
+ }
+ },
+ value: 8.5,
+ };
+
+ let stack_managed: ManagedNode<u16> = ManagedNode {
+ next: Val {
+ val: @ManagedNode {
+ next: Empty,
+ value: 11,
+ }
+ },
+ value: 10,
+ };
+
+ let unique_managed: Box<ManagedNode<u32>> = box ManagedNode {
+ next: Val {
+ val: @ManagedNode {
+ next: Empty,
+ value: 13,
+ }
+ },
+ value: 12,
+ };
+
+ let box_managed: @ManagedNode<u64> = @ManagedNode {
+ next: Val {
+ val: @ManagedNode {
+ next: Empty,
+ value: 15,
+ }
+ },
+ value: 14,
+ };
+
+ let vec_managed: [ManagedNode<f32>, ..1] = [ManagedNode {
+ next: Val {
+ val: @ManagedNode {
+ next: Empty,
+ value: 17.5,
+ }
+ },
+ value: 16.5,
+ }];
+
+ let borrowed_managed: &ManagedNode<f64> = &ManagedNode {
+ next: Val {
+ val: @ManagedNode {
+ next: Empty,
+ value: 19.5,
+ }
+ },
+ value: 18.5,
+ };
+
+ // LONG CYCLE
+ let long_cycle1: LongCycle1<u16> = LongCycle1 {
+ next: box LongCycle2 {
+ next: box LongCycle3 {
+ next: box LongCycle4 {
+ next: None,
+ value: 23,
+ },
+ value: 22,
+ },
+ value: 21
+ },
+ value: 20
+ };
+
+ let long_cycle2: LongCycle2<u32> = LongCycle2 {
+ next: box LongCycle3 {
+ next: box LongCycle4 {
+ next: None,
+ value: 26,
+ },
+ value: 25,
+ },
+ value: 24
+ };
+
+ let long_cycle3: LongCycle3<u64> = LongCycle3 {
+ next: box LongCycle4 {
+ next: None,
+ value: 28,
+ },
+ value: 27,
+ };
+
+ let long_cycle4: LongCycle4<f32> = LongCycle4 {
+ next: None,
+ value: 29.5,
+ };
+
+ // It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
+ // `box` chain.
+ let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
+ next: Val {
+ val: box box box box box LongCycleWithAnonymousTypes {
+ next: Empty,
+ value: 31,
+ }
+ },
+ value: 30
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
+
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = 100}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 200}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10
+// gdb-command:continue
+
+struct Struct {
+ x: int
+}
+
+trait Trait {
+ fn self_by_ref(&self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_by_val(self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+
+ fn self_owned(~self, arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+}
+
+impl Trait for Struct {}
+
+fn main() {
+ let stack = Struct { x: 100 };
+ let _ = stack.self_by_ref(-1, -2);
+ let _ = stack.self_by_val(-3, -4);
+
+ let owned = box Struct { x: 200 };
+ let _ = owned.self_by_ref(-5, -6);
+ let _ = owned.self_by_val(-7, -8);
+ let _ = owned.self_owned(-9, -10);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STACK BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$1 = {x = 987}
+// gdb-command:print arg1
+// gdb-check:$2 = -1
+// gdb-command:print/d arg2
+// gdb-check:$3 = -2
+// gdb-command:continue
+
+// STACK BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$4 = {x = 987}
+// gdb-command:print arg1
+// gdb-check:$5 = -3
+// gdb-command:print arg2
+// gdb-check:$6 = -4
+// gdb-command:continue
+
+// OWNED BY REF
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$7 = {x = 879}
+// gdb-command:print arg1
+// gdb-check:$8 = -5
+// gdb-command:print arg2
+// gdb-check:$9 = -6
+// gdb-command:continue
+
+// OWNED BY VAL
+// gdb-command:finish
+// gdb-command:print self
+// gdb-check:$10 = {x = 879}
+// gdb-command:print arg1
+// gdb-check:$11 = -7
+// gdb-command:print arg2
+// gdb-check:$12 = -8
+// gdb-command:continue
+
+// OWNED MOVED
+// gdb-command:finish
+// gdb-command:print *self
+// gdb-check:$13 = {x = 879}
+// gdb-command:print arg1
+// gdb-check:$14 = -9
+// gdb-command:print arg2
+// gdb-check:$15 = -10.5
+// gdb-command:continue
+
+struct Struct {
+ x: int
+}
+
+trait Trait {
+
+ fn self_by_ref<T>(&self, arg1: int, arg2: T) -> int {
+ zzz();
+ arg1
+ }
+
+ fn self_by_val<T>(self, arg1: int, arg2: T) -> int {
+ zzz();
+ arg1
+ }
+
+ fn self_owned<T>(~self, arg1: int, arg2: T) -> int {
+ zzz();
+ arg1
+ }
+}
+
+impl Trait for Struct {}
+
+fn main() {
+ let stack = Struct { x: 987 };
+ let _ = stack.self_by_ref(-1, -2_i8);
+ let _ = stack.self_by_val(-3, -4_i16);
+
+ let owned = box Struct { x: 879 };
+ let _ = owned.self_by_ref(-5, -6_i32);
+ let _ = owned.self_by_val(-7, -8_i64);
+ let _ = owned.self_owned(-9, -10.5_f32);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:print y
+// gdb-check:$2 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 10
+// gdb-command:print y
+// gdb-check:$4 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 10.5
+// gdb-command:print y
+// gdb-check:$6 = 20
+// gdb-command:continue
+
+fn a_function(x: bool, y: bool) {
+ zzz();
+ sentinel();
+
+ let x = 10;
+
+ zzz();
+ sentinel();
+
+ let x = 10.5;
+ let y = 20;
+
+ zzz();
+ sentinel();
+}
+
+fn main() {
+ a_function(false, true);
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:print y
+// gdb-check:$2 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 10
+// gdb-command:print y
+// gdb-check:$4 = true
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 10.5
+// gdb-command:print y
+// gdb-check:$6 = 20
+// gdb-command:continue
+
+fn main() {
+ let x = false;
+ let y = true;
+
+ zzz();
+ sentinel();
+
+ let x = 10;
+
+ zzz();
+ sentinel();
+
+ let x = 10.5;
+ let y = 20;
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print/d i8x16
+// gdb-check:$1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
+// gdb-command:print/d i16x8
+// gdb-check:$2 = {16, 17, 18, 19, 20, 21, 22, 23}
+// gdb-command:print/d i32x4
+// gdb-check:$3 = {24, 25, 26, 27}
+// gdb-command:print/d i64x2
+// gdb-check:$4 = {28, 29}
+
+// gdb-command:print/d u8x16
+// gdb-check:$5 = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}
+// gdb-command:print/d u16x8
+// gdb-check:$6 = {46, 47, 48, 49, 50, 51, 52, 53}
+// gdb-command:print/d u32x4
+// gdb-check:$7 = {54, 55, 56, 57}
+// gdb-command:print/d u64x2
+// gdb-check:$8 = {58, 59}
+
+// gdb-command:print f32x4
+// gdb-check:$9 = {60.5, 61.5, 62.5, 63.5}
+// gdb-command:print f64x2
+// gdb-check:$10 = {64.5, 65.5}
+
+// gdb-command:continue
+
+#![allow(experimental)]
+#![allow(unused_variable)]
+
+use std::unstable::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
+
+fn main() {
+
+ let i8x16 = i8x16(0i8, 1i8, 2i8, 3i8, 4i8, 5i8, 6i8, 7i8,
+ 8i8, 9i8, 10i8, 11i8, 12i8, 13i8, 14i8, 15i8);
+
+ let i16x8 = i16x8(16i16, 17i16, 18i16, 19i16, 20i16, 21i16, 22i16, 23i16);
+ let i32x4 = i32x4(24i32, 25i32, 26i32, 27i32);
+ let i64x2 = i64x2(28i64, 29i64);
+
+ let u8x16 = u8x16(30u8, 31u8, 32u8, 33u8, 34u8, 35u8, 36u8, 37u8,
+ 38u8, 39u8, 40u8, 41u8, 42u8, 43u8, 44u8, 45u8);
+ let u16x8 = u16x8(46u16, 47u16, 48u16, 49u16, 50u16, 51u16, 52u16, 53u16);
+ let u32x4 = u32x4(54u32, 55u32, 56u32, 57u32);
+ let u64x2 = u64x2(58u64, 59u64);
+
+ let f32x4 = f32x4(60.5f32, 61.5f32, 62.5f32, 63.5f32);
+ let f64x2 = f64x2(64.5f64, 65.5f64);
+
+ zzz();
+}
+
+#[inline(never)]
+fn zzz() { () }
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$1 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$2 = false
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$3 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$4 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$5 = 10.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$6 = 10
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print x
+// gdb-check:$7 = false
+// gdb-command:continue
+
+
+fn main() {
+ let x = false;
+
+ zzz();
+ sentinel();
+
+ {
+ zzz();
+ sentinel();
+
+ let x = 10;
+
+ zzz();
+ sentinel();
+
+ {
+ zzz();
+ sentinel();
+
+ let x = 10.5;
+
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+ }
+
+ zzz();
+ sentinel();
+}
+
+fn zzz() {()}
+fn sentinel() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+
+// gdb-command:print 'simple-struct::NO_PADDING_16'
+// gdb-check:$1 = {x = 1000, y = -1001}
+
+// gdb-command:print 'simple-struct::NO_PADDING_32'
+// gdb-check:$2 = {x = 1, y = 2, z = 3}
+
+// gdb-command:print 'simple-struct::NO_PADDING_64'
+// gdb-check:$3 = {x = 4, y = 5, z = 6}
+
+// gdb-command:print 'simple-struct::NO_PADDING_163264'
+// gdb-check:$4 = {a = 7, b = 8, c = 9, d = 10}
+
+// gdb-command:print 'simple-struct::INTERNAL_PADDING'
+// gdb-check:$5 = {x = 11, y = 12}
+
+// gdb-command:print 'simple-struct::PADDING_AT_END'
+// gdb-check:$6 = {x = 13, y = 14}
+
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print no_padding16
+// gdb-check:$7 = {x = 10000, y = -10001}
+
+// gdb-command:print no_padding32
+// gdb-check:$8 = {x = -10002, y = -10003.5, z = 10004}
+
+// gdb-command:print no_padding64
+// gdb-check:$9 = {x = -10005.5, y = 10006, z = 10007}
+
+// gdb-command:print no_padding163264
+// gdb-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011}
+
+// gdb-command:print internal_padding
+// gdb-check:$11 = {x = 10012, y = -10013}
+
+// gdb-command:print padding_at_end
+// gdb-check:$12 = {x = -10014, y = 10015}
+
+// gdb-command:print 'simple-struct::NO_PADDING_16'
+// gdb-check:$13 = {x = 100, y = -101}
+
+// gdb-command:print 'simple-struct::NO_PADDING_32'
+// gdb-check:$14 = {x = -15, y = -16, z = 17}
+
+// gdb-command:print 'simple-struct::NO_PADDING_64'
+// gdb-check:$15 = {x = -18, y = 19, z = 20}
+
+// gdb-command:print 'simple-struct::NO_PADDING_163264'
+// gdb-check:$16 = {a = -21, b = 22, c = 23, d = 24}
+
+// gdb-command:print 'simple-struct::INTERNAL_PADDING'
+// gdb-check:$17 = {x = 25, y = -26}
+
+// gdb-command:print 'simple-struct::PADDING_AT_END'
+// gdb-check:$18 = {x = -27, y = 28}
+
+// gdb-command:print inheriting
+// gdb-check:$19 = {a = 10019, b = -10020, x = -10016, y = -10017.5, z = 10018}
+
+
+#![feature(struct_inherit)];
+#![allow(unused_variable)];
+#![allow(dead_code)];
+
+struct NoPadding16 {
+ x: u16,
+ y: i16
+}
+
+virtual struct NoPadding32 {
+ x: i32,
+ y: f32,
+ z: u32
+}
+
+struct NoPadding64 {
+ x: f64,
+ y: i64,
+ z: u64
+}
+
+struct NoPadding163264 {
+ a: i16,
+ b: u16,
+ c: i32,
+ d: u64
+}
+
+struct InternalPadding {
+ x: u16,
+ y: i64
+}
+
+struct PaddingAtEnd {
+ x: i64,
+ y: u16
+}
+
+static mut NO_PADDING_16: NoPadding16 = NoPadding16 {
+ x: 1000,
+ y: -1001
+};
+
+static mut NO_PADDING_32: NoPadding32 = NoPadding32 {
+ x: 1,
+ y: 2.0,
+ z: 3
+};
+
+static mut NO_PADDING_64: NoPadding64 = NoPadding64 {
+ x: 4.0,
+ y: 5,
+ z: 6
+};
+
+static mut NO_PADDING_163264: NoPadding163264 = NoPadding163264 {
+ a: 7,
+ b: 8,
+ c: 9,
+ d: 10
+};
+
+static mut INTERNAL_PADDING: InternalPadding = InternalPadding {
+ x: 11,
+ y: 12
+};
+
+static mut PADDING_AT_END: PaddingAtEnd = PaddingAtEnd {
+ x: 13,
+ y: 14
+};
+
+struct Inheriting : NoPadding32 {
+ a: u16,
+ b: i16
+}
+
+fn main() {
+ let no_padding16 = NoPadding16 { x: 10000, y: -10001 };
+ let no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 };
+ let no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 };
+ let no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 };
+
+ let internal_padding = InternalPadding { x: 10012, y: -10013 };
+ let padding_at_end = PaddingAtEnd { x: -10014, y: 10015 };
+
+ let inheriting = Inheriting { a: 10019, b: -10020, x: -10016, y: -10017.5, z: 10018 };
+
+ unsafe {
+ NO_PADDING_16.x = 100;
+ NO_PADDING_16.y = -101;
+
+ NO_PADDING_32.x = -15;
+ NO_PADDING_32.y = -16.0;
+ NO_PADDING_32.z = 17;
+
+ NO_PADDING_64.x = -18.0;
+ NO_PADDING_64.y = 19;
+ NO_PADDING_64.z = 20;
+
+ NO_PADDING_163264.a = -21;
+ NO_PADDING_163264.b = 22;
+ NO_PADDING_163264.c = 23;
+ NO_PADDING_163264.d = 24;
+
+ INTERNAL_PADDING.x = 25;
+ INTERNAL_PADDING.y = -26;
+
+ PADDING_AT_END.x = -27;
+ PADDING_AT_END.y = 28;
+ }
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+
+// gdb-command:print/d 'simple-tuple::NO_PADDING_8'
+// gdb-check:$1 = {-50, 50}
+// gdb-command:print 'simple-tuple::NO_PADDING_16'
+// gdb-check:$2 = {-1, 2, 3}
+// gdb-command:print 'simple-tuple::NO_PADDING_32'
+// gdb-check:$3 = {4, 5, 6}
+// gdb-command:print 'simple-tuple::NO_PADDING_64'
+// gdb-check:$4 = {7, 8, 9}
+
+// gdb-command:print 'simple-tuple::INTERNAL_PADDING_1'
+// gdb-check:$5 = {10, 11}
+// gdb-command:print 'simple-tuple::INTERNAL_PADDING_2'
+// gdb-check:$6 = {12, 13, 14, 15}
+
+// gdb-command:print 'simple-tuple::PADDING_AT_END'
+// gdb-check:$7 = {16, 17}
+
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print/d noPadding8
+// gdb-check:$8 = {-100, 100}
+// gdb-command:print noPadding16
+// gdb-check:$9 = {0, 1, 2}
+// gdb-command:print noPadding32
+// gdb-check:$10 = {3, 4.5, 5}
+// gdb-command:print noPadding64
+// gdb-check:$11 = {6, 7.5, 8}
+
+// gdb-command:print internalPadding1
+// gdb-check:$12 = {9, 10}
+// gdb-command:print internalPadding2
+// gdb-check:$13 = {11, 12, 13, 14}
+
+// gdb-command:print paddingAtEnd
+// gdb-check:$14 = {15, 16}
+
+// gdb-command:print/d 'simple-tuple::NO_PADDING_8'
+// gdb-check:$15 = {-127, 127}
+// gdb-command:print 'simple-tuple::NO_PADDING_16'
+// gdb-check:$16 = {-10, 10, 9}
+// gdb-command:print 'simple-tuple::NO_PADDING_32'
+// gdb-check:$17 = {14, 15, 16}
+// gdb-command:print 'simple-tuple::NO_PADDING_64'
+// gdb-check:$18 = {17, 18, 19}
+
+// gdb-command:print 'simple-tuple::INTERNAL_PADDING_1'
+// gdb-check:$19 = {110, 111}
+// gdb-command:print 'simple-tuple::INTERNAL_PADDING_2'
+// gdb-check:$20 = {112, 113, 114, 115}
+
+// gdb-command:print 'simple-tuple::PADDING_AT_END'
+// gdb-check:$21 = {116, 117}
+
+#![allow(unused_variable)]
+#![allow(dead_code)]
+
+static mut NO_PADDING_8: (i8, u8) = (-50, 50);
+static mut NO_PADDING_16: (i16, i16, u16) = (-1, 2, 3);
+
+static mut NO_PADDING_32: (i32, f32, u32) = (4, 5.0, 6);
+static mut NO_PADDING_64: (i64, f64, u64) = (7, 8.0, 9);
+
+static mut INTERNAL_PADDING_1: (i16, i32) = (10, 11);
+static mut INTERNAL_PADDING_2: (i16, i32, u32, u64) = (12, 13, 14, 15);
+
+static mut PADDING_AT_END: (i32, i16) = (16, 17);
+
+fn main() {
+ let noPadding8: (i8, u8) = (-100, 100);
+ let noPadding16: (i16, i16, u16) = (0, 1, 2);
+ let noPadding32: (i32, f32, u32) = (3, 4.5, 5);
+ let noPadding64: (i64, f64, u64) = (6, 7.5, 8);
+
+ let internalPadding1: (i16, i32) = (9, 10);
+ let internalPadding2: (i16, i32, u32, u64) = (11, 12, 13, 14);
+
+ let paddingAtEnd: (i32, i16) = (15, 16);
+
+ unsafe {
+ NO_PADDING_8 = (-127, 127);
+ NO_PADDING_16 = (-10, 10, 9);
+
+ NO_PADDING_32 = (14, 15.0, 16);
+ NO_PADDING_64 = (17, 18.0, 19);
+
+ INTERNAL_PADDING_1 = (110, 111);
+ INTERNAL_PADDING_2 = (112, 113, 114, 115);
+
+ PADDING_AT_END = (116, 117);
+ }
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// STRUCT
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$1 = 1
+// gdb-command:print arg2
+// gdb-check:$2 = 2
+// gdb-command:continue
+
+// ENUM
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$3 = -3
+// gdb-command:print arg2
+// gdb-check:$4 = 4.5
+// gdb-command:print arg3
+// gdb-check:$5 = 5
+// gdb-command:continue
+
+#![feature(struct_variant)]
+
+struct Struct {
+ x: int
+}
+
+impl Struct {
+
+ fn static_method(arg1: int, arg2: int) -> int {
+ zzz();
+ arg1 + arg2
+ }
+}
+
+enum Enum {
+ Variant1 { x: int },
+ Variant2,
+ Variant3(f64, int, char),
+}
+
+impl Enum {
+
+ fn static_method(arg1: int, arg2: f64, arg3: uint) -> int {
+ zzz();
+ arg1
+ }
+}
+
+fn main() {
+ Struct::static_method(1, 2);
+ Enum::static_method(-3, 4.5, 5);
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print union on
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print case1
+// gdb-check:$1 = {{Case1, 0, {x = 2088533116, y = 2088533116, z = 31868}}, {Case1, 0, 8970181431921507452, 31868}}
+
+// gdb-command:print case2
+// gdb-check:$2 = {{Case2, 0, {x = 286331153, y = 286331153, z = 4369}}, {Case2, 0, 1229782938247303441, 4369}}
+
+// gdb-command:print univariant
+// gdb-check:$3 = {{x = 123, y = 456, z = 789}}
+
+#![allow(unused_variable)]
+
+struct Struct {
+ x: u32,
+ y: i32,
+ z: i16
+}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+ Case1(u64, Struct),
+ Case2(u64, u64, i16)
+}
+
+enum Univariant {
+ TheOnlyCase(Struct)
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let case1 = Case1(0, Struct { x: 2088533116, y: 2088533116, z: 31868 });
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let case2 = Case2(0, 1229782938247303441, 4369);
+
+ let univariant = TheOnlyCase(Struct { x: 123, y: 456, z: 789 });
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print three_simple_structs
+// gdb-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}}
+
+// gdb-command:print internal_padding_parent
+// gdb-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}}
+
+// gdb-command:print padding_at_end_parent
+// gdb-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}}
+
+#![allow(unused_variable)]
+
+struct Simple {
+ x: i32
+}
+
+struct InternalPadding {
+ x: i32,
+ y: i64
+}
+
+struct PaddingAtEnd {
+ x: i64,
+ y: i32
+}
+
+struct ThreeSimpleStructs {
+ x: Simple,
+ y: Simple,
+ z: Simple
+}
+
+struct InternalPaddingParent {
+ x: InternalPadding,
+ y: InternalPadding,
+ z: InternalPadding
+}
+
+struct PaddingAtEndParent {
+ x: PaddingAtEnd,
+ y: PaddingAtEnd,
+ z: PaddingAtEnd
+}
+
+struct Mixed {
+ x: PaddingAtEnd,
+ y: InternalPadding,
+ z: Simple,
+ w: i16
+}
+
+struct Bag {
+ x: Simple
+}
+
+struct BagInBag {
+ x: Bag
+}
+
+struct ThatsJustOverkill {
+ x: BagInBag
+}
+
+struct Tree {
+ x: Simple,
+ y: InternalPaddingParent,
+ z: BagInBag
+}
+
+fn main() {
+
+ let three_simple_structs = ThreeSimpleStructs {
+ x: Simple { x: 1 },
+ y: Simple { x: 2 },
+ z: Simple { x: 3 }
+ };
+
+ let internal_padding_parent = InternalPaddingParent {
+ x: InternalPadding { x: 4, y: 5 },
+ y: InternalPadding { x: 6, y: 7 },
+ z: InternalPadding { x: 8, y: 9 }
+ };
+
+ let padding_at_end_parent = PaddingAtEndParent {
+ x: PaddingAtEnd { x: 10, y: 11 },
+ y: PaddingAtEnd { x: 12, y: 13 },
+ z: PaddingAtEnd { x: 14, y: 15 }
+ };
+
+ let mixed = Mixed {
+ x: PaddingAtEnd { x: 16, y: 17 },
+ y: InternalPadding { x: 18, y: 19 },
+ z: Simple { x: 20 },
+ w: 21
+ };
+
+ let bag = Bag { x: Simple { x: 22 } };
+ let bag_in_bag = BagInBag {
+ x: Bag {
+ x: Simple { x: 23 }
+ }
+ };
+
+ let tjo = ThatsJustOverkill {
+ x: BagInBag {
+ x: Bag {
+ x: Simple { x: 24 }
+ }
+ }
+ };
+
+ let tree = Tree {
+ x: Simple { x: 25 },
+ y: InternalPaddingParent {
+ x: InternalPadding { x: 26, y: 27 },
+ y: InternalPadding { x: 28, y: 29 },
+ z: InternalPadding { x: 30, y: 31 }
+ },
+ z: BagInBag {
+ x: Bag {
+ x: Simple { x: 32 }
+ }
+ }
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print union on
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print case1
+// gdb-check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
+
+// gdb-command:print case2
+// gdb-check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
+
+// gdb-command:print case3
+// gdb-check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
+
+// gdb-command:print univariant
+// gdb-check:$4 = {a = -1}
+
+#![allow(unused_variable)]
+#![feature(struct_variant)]
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+ Case1 { a: u64, b: u16, c: u16, d: u16, e: u16},
+ Case2 { a: u64, b: u32, c: u32},
+ Case3 { a: u64, b: u64 }
+}
+
+enum Univariant {
+ TheOnlyCase { a: i64 }
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let case2 = Case2 { a: 0, b: 286331153, c: 286331153 };
+
+ // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+ // 0b01011001010110010101100101011001 = 1499027801
+ // 0b0101100101011001 = 22873
+ // 0b01011001 = 89
+ let case3 = Case3 { a: 0, b: 6438275382588823897 };
+
+ let univariant = TheOnlyCase { a: -1 };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print simple
+// gdb-check:$1 = {x = 10, y = 20}
+
+// gdb-command:print noDestructor
+// gdb-check:$2 = {a = {x = 10, y = 20}, guard = -1}
+
+// gdb-command:print withDestructor
+// gdb-check:$3 = {a = {x = 10, y = 20}, guard = -1}
+
+// gdb-command:print nested
+// gdb-check:$4 = {a = {a = {x = 7890, y = 9870}}}
+
+#![allow(unused_variable)]
+
+struct NoDestructor {
+ x: i32,
+ y: i64
+}
+
+struct WithDestructor {
+ x: i32,
+ y: i64
+}
+
+impl Drop for WithDestructor {
+ fn drop(&mut self) {}
+}
+
+struct NoDestructorGuarded {
+ a: NoDestructor,
+ guard: i64
+}
+
+struct WithDestructorGuarded {
+ a: WithDestructor,
+ guard: i64
+}
+
+struct NestedInner {
+ a: WithDestructor
+}
+
+impl Drop for NestedInner {
+ fn drop(&mut self) {}
+}
+
+struct NestedOuter {
+ a: NestedInner
+}
+
+
+// The compiler adds a 'destructed' boolean field to structs implementing Drop. This field is used
+// at runtime to prevent drop() to be executed more than once (see middle::trans::adt).
+// This field must be incorporated by the debug info generation. Otherwise the debugger assumes a
+// wrong size/layout for the struct.
+fn main() {
+
+ let simple = WithDestructor { x: 10, y: 20 };
+
+ let noDestructor = NoDestructorGuarded {
+ a: NoDestructor { x: 10, y: 20 },
+ guard: -1
+ };
+
+ // If the destructor flag field is not incorporated into the debug info for 'WithDestructor'
+ // then the debugger will have an invalid offset for the field 'guard' and thus should not be
+ // able to read its value correctly (dots are padding bytes, D is the boolean destructor flag):
+ //
+ // 64 bit
+ //
+ // NoDestructorGuarded = 0000....00000000FFFFFFFF
+ // <--------------><------>
+ // NoDestructor guard
+ //
+ //
+ // withDestructorGuarded = 0000....00000000D.......FFFFFFFF
+ // <--------------><------> // How debug info says it is
+ // WithDestructor guard
+ //
+ // <----------------------><------> // How it actually is
+ // WithDestructor guard
+ //
+ // 32 bit
+ //
+ // NoDestructorGuarded = 000000000000FFFFFFFF
+ // <----------><------>
+ // NoDestructor guard
+ //
+ //
+ // withDestructorGuarded = 000000000000D...FFFFFFFF
+ // <----------><------> // How debug info says it is
+ // WithDestructor guard
+ //
+ // <--------------><------> // How it actually is
+ // WithDestructor guard
+ //
+ let withDestructor = WithDestructorGuarded {
+ a: WithDestructor { x: 10, y: 20 },
+ guard: -1
+ };
+
+ // expected layout (64 bit) = xxxx....yyyyyyyyD.......D...
+ // <--WithDestructor------>
+ // <-------NestedInner-------->
+ // <-------NestedOuter-------->
+ let nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+some text to include in another file as string 1
\ No newline at end of file
--- /dev/null
+some text to include in another file as string 2
\ No newline at end of file
--- /dev/null
+some text to include in another file as string 3
\ No newline at end of file
--- /dev/null
+// ignore-test
+
+// 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.
+//
+// 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:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$1 = 1000
+// gdb-command:print arg2
+// gdb-check:$2 = 0.5
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print arg1
+// gdb-check:$3 = 2000
+// gdb-command:print *arg2
+// gdb-check:$4 = {1, 2, 3}
+// gdb-command:continue
+
+
+struct Struct {
+ x: int
+}
+
+trait Trait {
+ fn generic_static_default_method<T>(arg1: int, arg2: T) -> int {
+ zzz();
+ arg1
+ }
+}
+
+impl Trait for Struct {}
+
+fn main() {
+
+ // Is this really how to use these?
+ Trait::generic_static_default_method::<Struct, float>(1000, 0.5);
+ Trait::generic_static_default_method::<Struct, &(int, int, int)>(2000, &(1, 2, 3));
+
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:run
+
+#![allow(unused_variable)]
+
+
+trait Trait {
+ fn method(&self) -> int { 0 }
+}
+
+struct Struct {
+ a: int,
+ b: f64
+}
+
+impl Trait for Struct {}
+
+// There is no real test here yet. Just make sure that it compiles without crashing.
+fn main() {
+ let stack_struct = Struct { a:0, b: 1.0 };
+ let reference: &Trait = &stack_struct as &Trait;
+ let unique: Box<Trait> = box Struct { a:2, b: 3.0 } as Box<Trait>;
+}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print no_padding1
+// gdb-check:$1 = {x = {0, 1}, y = 2, z = {3, 4, 5}}
+// gdb-command:print no_padding2
+// gdb-check:$2 = {x = {6, 7}, y = {{8, 9}, 10}}
+
+// gdb-command:print tuple_internal_padding
+// gdb-check:$3 = {x = {11, 12}, y = {13, 14}}
+// gdb-command:print struct_internal_padding
+// gdb-check:$4 = {x = {15, 16}, y = {17, 18}}
+// gdb-command:print both_internally_padded
+// gdb-check:$5 = {x = {19, 20, 21}, y = {22, 23}}
+
+// gdb-command:print single_tuple
+// gdb-check:$6 = {x = {24, 25, 26}}
+
+// gdb-command:print tuple_padded_at_end
+// gdb-check:$7 = {x = {27, 28}, y = {29, 30}}
+// gdb-command:print struct_padded_at_end
+// gdb-check:$8 = {x = {31, 32}, y = {33, 34}}
+// gdb-command:print both_padded_at_end
+// gdb-check:$9 = {x = {35, 36, 37}, y = {38, 39}}
+
+// gdb-command:print mixed_padding
+// gdb-check:$10 = {x = {{40, 41, 42}, {43, 44}}, y = {45, 46, 47, 48}}
+
+#![allow(unused_variable)]
+
+struct NoPadding1 {
+ x: (i32, i32),
+ y: i32,
+ z: (i32, i32, i32)
+}
+
+struct NoPadding2 {
+ x: (i32, i32),
+ y: ((i32, i32), i32)
+}
+
+struct TupleInternalPadding {
+ x: (i16, i32),
+ y: (i32, i64)
+}
+
+struct StructInternalPadding {
+ x: (i16, i16),
+ y: (i64, i64)
+}
+
+struct BothInternallyPadded {
+ x: (i16, i32, i32),
+ y: (i32, i64)
+}
+
+struct SingleTuple {
+ x: (i16, i32, i64)
+}
+
+struct TuplePaddedAtEnd {
+ x: (i32, i16),
+ y: (i64, i32)
+}
+
+struct StructPaddedAtEnd {
+ x: (i64, i64),
+ y: (i16, i16)
+}
+
+struct BothPaddedAtEnd {
+ x: (i32, i32, i16),
+ y: (i64, i32)
+}
+
+// Data-layout (padding signified by dots, one column = 2 bytes):
+// [a.bbc...ddddee..ffffg.hhi...]
+struct MixedPadding {
+ x: ((i16, i32, i16), (i64, i32)),
+ y: (i64, i16, i32, i16)
+}
+
+
+fn main() {
+ let no_padding1 = NoPadding1 {
+ x: (0, 1),
+ y: 2,
+ z: (3, 4, 5)
+ };
+
+ let no_padding2 = NoPadding2 {
+ x: (6, 7),
+ y: ((8, 9), 10)
+ };
+
+ let tuple_internal_padding = TupleInternalPadding {
+ x: (11, 12),
+ y: (13, 14)
+ };
+
+ let struct_internal_padding = StructInternalPadding {
+ x: (15, 16),
+ y: (17, 18)
+ };
+
+ let both_internally_padded = BothInternallyPadded {
+ x: (19, 20, 21),
+ y: (22, 23)
+ };
+
+ let single_tuple = SingleTuple {
+ x: (24, 25, 26)
+ };
+
+ let tuple_padded_at_end = TuplePaddedAtEnd {
+ x: (27, 28),
+ y: (29, 30)
+ };
+
+ let struct_padded_at_end = StructPaddedAtEnd {
+ x: (31, 32),
+ y: (33, 34)
+ };
+
+ let both_padded_at_end = BothPaddedAtEnd {
+ x: (35, 36, 37),
+ y: (38, 39)
+ };
+
+ let mixed_padding = MixedPadding {
+ x: ((40, 41, 42), (43, 44)),
+ y: (45, 46, 47, 48)
+ };
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print no_padding1
+// gdb-check:$1 = {{0, 1}, 2, 3}
+// gdb-command:print no_padding2
+// gdb-check:$2 = {4, {5, 6}, 7}
+// gdb-command:print no_padding3
+// gdb-check:$3 = {8, 9, {10, 11}}
+
+// gdb-command:print internal_padding1
+// gdb-check:$4 = {12, {13, 14}}
+// gdb-command:print internal_padding2
+// gdb-check:$5 = {15, {16, 17}}
+
+// gdb-command:print padding_at_end1
+// gdb-check:$6 = {18, {19, 20}}
+// gdb-command:print padding_at_end2
+// gdb-check:$7 = {{21, 22}, 23}
+
+#![allow(unused_variable)]
+
+fn main() {
+ let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3);
+ let no_padding2: (u32, (u32, u32), u32) = (4, (5, 6), 7);
+ let no_padding3: (u32, u32, (u32, u32)) = (8, 9, (10, 11));
+
+ let internal_padding1: (i16, (i32, i32)) = (12, (13, 14));
+ let internal_padding2: (i16, (i16, i32)) = (15, (16, 17));
+
+ let padding_at_end1: (i32, (i32, i16)) = (18, (19, 20));
+ let padding_at_end2: ((i32, i16), i32) = ((21, 22), 23);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print no_padding16
+// gdb-check:$1 = {10000, -10001}
+
+// gdb-command:print no_padding32
+// gdb-check:$2 = {-10002, -10003.5, 10004}
+
+// gdb-command:print no_padding64
+// gdb-check:$3 = {-10005.5, 10006, 10007}
+
+// gdb-command:print no_padding163264
+// gdb-check:$4 = {-10008, 10009, 10010, 10011}
+
+// gdb-command:print internal_padding
+// gdb-check:$5 = {10012, -10013}
+
+// gdb-command:print padding_at_end
+// gdb-check:$6 = {-10014, 10015}
+
+
+// This test case mainly makes sure that no field names are generated for tuple structs (as opposed
+// to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
+// structs.
+
+struct NoPadding16(u16, i16);
+struct NoPadding32(i32, f32, u32);
+struct NoPadding64(f64, i64, u64);
+struct NoPadding163264(i16, u16, i32, u64);
+struct InternalPadding(u16, i64);
+struct PaddingAtEnd(i64, u16);
+
+fn main() {
+ let no_padding16 = NoPadding16(10000, -10001);
+ let no_padding32 = NoPadding32(-10002, -10003.5, 10004);
+ let no_padding64 = NoPadding64(-10005.5, 10006, 10007);
+ let no_padding163264 = NoPadding163264(-10008, 10009, 10010, 10011);
+
+ let internal_padding = InternalPadding(10012, -10013);
+ let padding_at_end = PaddingAtEnd(-10014, 10015);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-tidy-linelength
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print union on
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print case1
+// gdb-check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
+
+// gdb-command:print case2
+// gdb-check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
+
+// gdb-command:print case3
+// gdb-check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
+
+// gdb-command:print univariant
+// gdb-check:$4 = {-1}
+
+#![allow(unused_variable)]
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+ Case1(u64, u16, u16, u16, u16),
+ Case2(u64, u32, u32),
+ Case3(u64, u64)
+}
+
+enum Univariant {
+ TheOnlyCase(i64)
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let case1 = Case1(0, 31868, 31868, 31868, 31868);
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let case2 = Case2(0, 286331153, 286331153);
+
+ // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+ // 0b01011001010110010101100101011001 = 1499027801
+ // 0b0101100101011001 = 22873
+ // 0b01011001 = 89
+ let case3 = Case3(0, 6438275382588823897);
+
+ let univariant = TheOnlyCase(-1);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print *the_a
+// gdb-check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// gdb-command:print *the_b
+// gdb-check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// gdb-command:print *univariant
+// gdb-check:$3 = {123234}
+
+#![allow(unused_variable)]
+#![feature(struct_variant)]
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+ TheA { x: i64, y: i64 },
+ TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+ TheOnlyCase(i64)
+}
+
+fn main() {
+
+ // In order to avoid endianess trouble all of the following test values consist of a single
+ // repeated byte. This way each interpretation of the union should look the same, no matter if
+ // this is a big or little endian machine.
+
+ // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+ // 0b01111100011111000111110001111100 = 2088533116
+ // 0b0111110001111100 = 31868
+ // 0b01111100 = 124
+ let the_a = box TheA { x: 0, y: 8970181431921507452 };
+
+ // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+ // 0b00010001000100010001000100010001 = 286331153
+ // 0b0001000100010001 = 4369
+ // 0b00010001 = 17
+ let the_b = box TheB (0, 286331153, 286331153);
+
+ let univariant = box TheOnlyCase(123234);
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print variable
+// gdb-check:$1 = 1
+// gdb-command:print constant
+// gdb-check:$2 = 2
+// gdb-command:print a_struct
+// gdb-check:$3 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *struct_ref
+// gdb-check:$4 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *owned
+// gdb-check:$5 = 6
+// gdb-command:print managed->val
+// gdb-check:$6 = 7
+// gdb-command:print closure_local
+// gdb-check:$7 = 8
+// gdb-command:continue
+
+// gdb-command:finish
+// gdb-command:print variable
+// gdb-check:$8 = 1
+// gdb-command:print constant
+// gdb-check:$9 = 2
+// gdb-command:print a_struct
+// gdb-check:$10 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *struct_ref
+// gdb-check:$11 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *owned
+// gdb-check:$12 = 6
+// gdb-command:print managed->val
+// gdb-check:$13 = 7
+// gdb-command:print closure_local
+// gdb-check:$14 = 8
+// gdb-command:continue
+
+#![feature(managed_boxes)]
+#![allow(unused_variable)]
+
+struct Struct {
+ a: int,
+ b: f64,
+ c: uint
+}
+
+fn main() {
+ let mut variable = 1;
+ let constant = 2;
+
+ let a_struct = Struct {
+ a: -3,
+ b: 4.5,
+ c: 5
+ };
+
+ let struct_ref = &a_struct;
+ let owned = box 6;
+ let managed = @7;
+
+ let closure = || {
+ let closure_local = 8;
+
+ let nested_closure = || {
+ zzz();
+ variable = constant + a_struct.a + struct_ref.a + *owned + *managed + closure_local;
+ };
+
+ zzz();
+
+ nested_closure();
+ };
+
+ closure();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print constant
+// gdb-check:$1 = 1
+// gdb-command:print a_struct
+// gdb-check:$2 = {a = -2, b = 3.5, c = 4}
+// gdb-command:print *owned
+// gdb-check:$3 = 5
+
+#![allow(unused_variable)]
+
+struct Struct {
+ a: int,
+ b: f64,
+ c: uint
+}
+
+fn main() {
+ let constant = 1;
+
+ let a_struct = Struct {
+ a: -2,
+ b: 3.5,
+ c: 4
+ };
+
+ let owned = box 5;
+
+ let closure: proc() = proc() {
+ zzz();
+ do_something(&constant, &a_struct.a, owned);
+ };
+
+ closure();
+}
+
+fn do_something(_: &int, _:&int, _:&int) {
+
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// 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-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+// gdb-command:print variable
+// gdb-check:$1 = 1
+// gdb-command:print constant
+// gdb-check:$2 = 2
+// gdb-command:print a_struct
+// gdb-check:$3 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *struct_ref
+// gdb-check:$4 = {a = -3, b = 4.5, c = 5}
+// gdb-command:print *owned
+// gdb-check:$5 = 6
+// gdb-command:print managed->val
+// gdb-check:$6 = 7
+
+#![feature(managed_boxes)]
+#![allow(unused_variable)]
+
+struct Struct {
+ a: int,
+ b: f64,
+ c: uint
+}
+
+fn main() {
+ let mut variable = 1;
+ let constant = 2;
+
+ let a_struct = Struct {
+ a: -3,
+ b: 4.5,
+ c: 5
+ };
+
+ let struct_ref = &a_struct;
+ let owned = box 6;
+ let managed = @7;
+
+ let closure = || {
+ zzz();
+ variable = constant + a_struct.a + struct_ref.a + *owned + *managed;
+ };
+
+ closure();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print empty.length
+// gdb-check:$1 = 0
+
+// gdb-command:print singleton.length
+// gdb-check:$2 = 1
+// gdb-command:print *((int64_t[1]*)(singleton.data_ptr))
+// gdb-check:$3 = {1}
+
+// gdb-command:print multiple.length
+// gdb-check:$4 = 4
+// gdb-command:print *((int64_t[4]*)(multiple.data_ptr))
+// gdb-check:$5 = {2, 3, 4, 5}
+
+// gdb-command:print slice_of_slice.length
+// gdb-check:$6 = 2
+// gdb-command:print *((int64_t[2]*)(slice_of_slice.data_ptr))
+// gdb-check:$7 = {3, 4}
+
+// gdb-command:print padded_tuple.length
+// gdb-check:$8 = 2
+// gdb-command:print padded_tuple.data_ptr[0]
+// gdb-check:$9 = {6, 7}
+// gdb-command:print padded_tuple.data_ptr[1]
+// gdb-check:$10 = {8, 9}
+
+// gdb-command:print padded_struct.length
+// gdb-check:$11 = 2
+// gdb-command:print padded_struct.data_ptr[0]
+// gdb-check:$12 = {x = 10, y = 11, z = 12}
+// gdb-command:print padded_struct.data_ptr[1]
+// gdb-check:$13 = {x = 13, y = 14, z = 15}
+
+// gdb-command:print 'vec-slices::MUT_VECT_SLICE'.length
+// gdb-check:$14 = 2
+// gdb-command:print *((int64_t[2]*)('vec-slices::MUT_VECT_SLICE'.data_ptr))
+// gdb-check:$15 = {64, 65}
+
+#![allow(unused_variable)]
+
+struct AStruct {
+ x: i16,
+ y: i32,
+ z: i16
+}
+
+static VECT_SLICE: &'static [i64] = &[64, 65];
+static mut MUT_VECT_SLICE: &'static [i64] = &[32];
+
+fn main() {
+ let empty: &[i64] = &[];
+ let singleton: &[i64] = &[1];
+ let multiple: &[i64] = &[2, 3, 4, 5];
+ let slice_of_slice = multiple.slice(1,3);
+
+ let padded_tuple: &[(i32, i16)] = &[(6, 7), (8, 9)];
+
+ let padded_struct: &[AStruct] = &[
+ AStruct { x: 10, y: 11, z: 12 },
+ AStruct { x: 13, y: 14, z: 15 }
+ ];
+
+ unsafe {
+ MUT_VECT_SLICE = VECT_SLICE;
+ }
+
+ zzz();
+}
+
+fn zzz() {()}
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-win32: FIXME #13256
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:set print pretty off
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+// gdb-command:print a
+// gdb-check:$1 = {1, 2, 3}
+// gdb-command:print vec::VECT
+// gdb-check:$2 = {4, 5, 6}
+
+#![allow(unused_variable)]
+
+static mut VECT: [i32, ..3] = [1, 2, 3];
+
+fn main() {
+ let a = [1, 2, 3];
+
+ unsafe {
+ VECT[0] = 4;
+ VECT[1] = 5;
+ VECT[2] = 6;
+ }
+
+ zzz();
+}
+
+fn zzz() {()}
fn main() {
let args = os::args();
- let rustc = args[1].as_slice();
- let tmpdir = Path::new(args[2].as_slice());
+ let rustc = args.get(1).as_slice();
+ let tmpdir = Path::new(args.get(2).as_slice());
let main_file = tmpdir.join("unicode_input_multiple_files_main.rs");
let main_file_str = main_file.as_str().unwrap();
fn main() {
let args = os::args();
- let rustc = args[1].as_slice();
- let tmpdir = Path::new(args[2].as_slice());
+ let rustc = args.get(1).as_slice();
+ let tmpdir = Path::new(args.get(2).as_slice());
let main_file = tmpdir.join("span_main.rs");
let main_file_str = main_file.as_str().unwrap();
fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() >= 2 && args[1].as_slice() == "fail" {
foo();
} else if args.len() >= 2 && args[1].as_slice() == "double-fail" {
pub fn main() {
let args = os::args();
+ let args = args.as_slice();
// Here, the rvalue `"signal".to_owned()` requires cleanup. Older versions
// of the code had a problem that the cleanup scope for this
--- /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.
+
+unsafe extern fn foo() {}
+unsafe extern "C" fn bar() {}
+
+fn main() {
+ let _a: unsafe extern fn() = foo;
+ let _a: unsafe extern "C" fn() = foo;
+}
pub fn main () {
let args = os::args();
+ let args = args.as_slice();
if args.len() > 1 && args[1] == "child".to_owned() {
for _ in range(0, 1000) {
println!("hello?");
fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() > 1 && args[1].as_slice() == "child" {
if args[2].as_slice() == "green" {
child();
fn parent(flavor: ~str) {
let args = os::args();
+ let args = args.as_slice();
let mut p = io::Process::new(args[0].as_slice(), ["child".to_owned(), flavor]).unwrap();
p.stdin.get_mut_ref().write_str("test1\ntest2\ntest3").unwrap();
let out = p.wait_with_output();
fn parse_args() -> ~str {
let args = ::std::os::args();
+ let args = args.as_slice();
let mut n = 0;
while n < args.len() {
fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() > 1 && args[1].as_slice() == "child" {
debug!("foo");
debug!("bar");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::local_data;
-
local_data_key!(foo: int)
mod bar {
}
pub fn main() {
- local_data::get(foo, |x| assert!(x.is_none()));
- local_data::get(bar::baz, |y| assert!(y.is_none()));
+ assert!(foo.get().is_none());
+ assert!(bar::baz.get().is_none());
- local_data::set(foo, 3);
- local_data::set(bar::baz, -10.0);
+ foo.replace(Some(3));
+ bar::baz.replace(Some(-10.0));
- local_data::get(foo, |x| assert_eq!(*x.unwrap(), 3));
- local_data::get(bar::baz, |y| assert_eq!(*y.unwrap(), -10.0));
+ assert_eq!(*foo.get().unwrap(), 3);
+ assert_eq!(*bar::baz.get().unwrap(), -10.0);
}
fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() > 1 && args[1].as_slice() == "silent" {
silent_recurse();
} else if args.len() > 1 && args[1].as_slice() == "loud" {
assert!(map.pop(&Slice("foo")).is_some());
assert_eq!(map.move_iter().map(|(k, v)| k.to_str() + v.to_str())
- .collect::<~[~str]>()
+ .collect::<Vec<~str>>()
.concat(),
"abc50bcd51cde52def53".to_owned());
}
pub fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() >= 2 && args[1] == "signal".to_owned() {
// Raise a segfault.
unsafe { *(0 as *mut int) = 0; }
fn main() {
let args = os::args();
+ let args = args.as_slice();
if args.len() > 1 && args[1].as_slice() == "test" {
return test();
}
impl<T:to_str> to_str for Vec<T> {
fn to_string(&self) -> ~str {
- format!("[{}]", self.iter().map(|e| e.to_string()).collect::<~[~str]>().connect(", "))
+ format!("[{}]", self.iter().map(|e| e.to_string()).collect::<Vec<~str>>().connect(", "))
}
}