mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-27 22:34:14 +00:00
auto merge of #5797 : alexcrichton/rust/issue-1913, r=catamorphism
Closes #5487, #1913, and #4568 I tracked this by adding all used unsafe blocks/functions to a set on the `tcx` passed around, and then when the lint pass comes around if an unsafe block/function isn't listed in that set, it's unused. I also removed everything from the compiler that was unused, and up to stage2 is now compiling without any known unused unsafe blocks. I chose `unused_unsafe` as the name of the lint attribute, but there may be a better name...
This commit is contained in:
commit
4beebc427c
@ -30,36 +30,34 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] {
|
||||
}
|
||||
|
||||
fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] {
|
||||
unsafe {
|
||||
let error_tag = ~"//~";
|
||||
let mut idx;
|
||||
match str::find_str(line, error_tag) {
|
||||
None => return ~[],
|
||||
Some(nn) => { idx = (nn as uint) + str::len(error_tag); }
|
||||
}
|
||||
|
||||
// "//~^^^ kind msg" denotes a message expected
|
||||
// three lines above current line:
|
||||
let mut adjust_line = 0u;
|
||||
let len = str::len(line);
|
||||
while idx < len && line[idx] == ('^' as u8) {
|
||||
adjust_line += 1u;
|
||||
idx += 1u;
|
||||
}
|
||||
|
||||
// Extract kind:
|
||||
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
|
||||
let start_kind = idx;
|
||||
while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
|
||||
let kind = str::to_lower(str::slice(line, start_kind, idx).to_owned());
|
||||
|
||||
// Extract msg:
|
||||
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
|
||||
let msg = str::slice(line, idx, len).to_owned();
|
||||
|
||||
debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg);
|
||||
|
||||
return ~[ExpectedError{line: line_num - adjust_line, kind: kind,
|
||||
msg: msg}];
|
||||
let error_tag = ~"//~";
|
||||
let mut idx;
|
||||
match str::find_str(line, error_tag) {
|
||||
None => return ~[],
|
||||
Some(nn) => { idx = (nn as uint) + str::len(error_tag); }
|
||||
}
|
||||
|
||||
// "//~^^^ kind msg" denotes a message expected
|
||||
// three lines above current line:
|
||||
let mut adjust_line = 0u;
|
||||
let len = str::len(line);
|
||||
while idx < len && line[idx] == ('^' as u8) {
|
||||
adjust_line += 1u;
|
||||
idx += 1u;
|
||||
}
|
||||
|
||||
// Extract kind:
|
||||
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
|
||||
let start_kind = idx;
|
||||
while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
|
||||
let kind = str::to_lower(str::slice(line, start_kind, idx).to_owned());
|
||||
|
||||
// Extract msg:
|
||||
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
|
||||
let msg = str::slice(line, idx, len).to_owned();
|
||||
|
||||
debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg);
|
||||
|
||||
return ~[ExpectedError{line: line_num - adjust_line, kind: kind,
|
||||
msg: msg}];
|
||||
}
|
||||
|
@ -171,16 +171,14 @@ fn parse_name_directive(line: ~str, directive: ~str) -> bool {
|
||||
|
||||
fn parse_name_value_directive(line: ~str,
|
||||
directive: ~str) -> Option<~str> {
|
||||
unsafe {
|
||||
let keycolon = directive + ~":";
|
||||
match str::find_str(line, keycolon) {
|
||||
Some(colon) => {
|
||||
let value = str::slice(line, colon + str::len(keycolon),
|
||||
str::len(line)).to_owned();
|
||||
debug!("%s: %s", directive, value);
|
||||
Some(value)
|
||||
}
|
||||
None => None
|
||||
let keycolon = directive + ~":";
|
||||
match str::find_str(line, keycolon) {
|
||||
Some(colon) => {
|
||||
let value = str::slice(line, colon + str::len(keycolon),
|
||||
str::len(line)).to_owned();
|
||||
debug!("%s: %s", directive, value);
|
||||
Some(value)
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
@ -188,16 +188,14 @@ impl<T: Owned> Peekable<T> for Port<T> {
|
||||
|
||||
#[inline(always)]
|
||||
fn port_peek<T:Owned>(self: &Port<T>) -> bool {
|
||||
unsafe {
|
||||
let mut endp = None;
|
||||
endp <-> self.endp;
|
||||
let peek = match &endp {
|
||||
&Some(ref endp) => peek(endp),
|
||||
&None => fail!(~"peeking empty stream")
|
||||
};
|
||||
self.endp <-> endp;
|
||||
peek
|
||||
}
|
||||
let mut endp = None;
|
||||
endp <-> self.endp;
|
||||
let peek = match &endp {
|
||||
&Some(ref endp) => peek(endp),
|
||||
&None => fail!(~"peeking empty stream")
|
||||
};
|
||||
self.endp <-> endp;
|
||||
peek
|
||||
}
|
||||
|
||||
impl<T: Owned> Selectable for Port<T> {
|
||||
|
@ -1536,11 +1536,8 @@ pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
|
||||
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
||||
let mut v = with_bytes_writer(f);
|
||||
|
||||
// FIXME (#3758): This should not be needed.
|
||||
unsafe {
|
||||
// Make sure the vector has a trailing null and is proper utf8.
|
||||
v.push(0);
|
||||
}
|
||||
// Make sure the vector has a trailing null and is proper utf8.
|
||||
v.push(0);
|
||||
assert!(str::is_utf8(v));
|
||||
|
||||
unsafe { ::cast::transmute(v) }
|
||||
@ -1640,16 +1637,14 @@ pub mod fsync {
|
||||
// outer res
|
||||
pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
|
||||
blk: &fn(v: Res<*libc::FILE>)) {
|
||||
unsafe {
|
||||
blk(Res(Arg {
|
||||
val: file.f, opt_level: opt_level,
|
||||
fsync_fn: |file, l| {
|
||||
unsafe {
|
||||
os::fsync_fd(libc::fileno(file), l) as int
|
||||
}
|
||||
blk(Res(Arg {
|
||||
val: file.f, opt_level: opt_level,
|
||||
fsync_fn: |file, l| {
|
||||
unsafe {
|
||||
os::fsync_fd(libc::fileno(file), l) as int
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// fsync fd after executing blk
|
||||
|
@ -38,13 +38,13 @@ pub mod raw {
|
||||
#[inline(always)]
|
||||
pub fn ptr_eq<T>(a: @T, b: @T) -> bool {
|
||||
//! Determine if two shared boxes point to the same object
|
||||
unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) }
|
||||
ptr::addr_of(&(*a)) == ptr::addr_of(&(*b))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool {
|
||||
//! Determine if two mutable shared boxes point to the same object
|
||||
unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) }
|
||||
ptr::addr_of(&(*a)) == ptr::addr_of(&(*b))
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
|
@ -369,27 +369,27 @@ pub fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn abs(x: float) -> float {
|
||||
unsafe { f64::abs(x as f64) as float }
|
||||
f64::abs(x as f64) as float
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn sqrt(x: float) -> float {
|
||||
unsafe { f64::sqrt(x as f64) as float }
|
||||
f64::sqrt(x as f64) as float
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn atan(x: float) -> float {
|
||||
unsafe { f64::atan(x as f64) as float }
|
||||
f64::atan(x as f64) as float
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn sin(x: float) -> float {
|
||||
unsafe { f64::sin(x as f64) as float }
|
||||
f64::sin(x as f64) as float
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn cos(x: float) -> float {
|
||||
unsafe { f64::cos(x as f64) as float }
|
||||
f64::cos(x as f64) as float
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn tan(x: float) -> float {
|
||||
unsafe { f64::tan(x as f64) as float }
|
||||
f64::tan(x as f64) as float
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
|
@ -389,13 +389,11 @@ impl GenericPath for PosixPath {
|
||||
}
|
||||
|
||||
fn dirname(&self) -> ~str {
|
||||
unsafe {
|
||||
let s = self.dir_path().to_str();
|
||||
if s.len() == 0 {
|
||||
~"."
|
||||
} else {
|
||||
s
|
||||
}
|
||||
let s = self.dir_path().to_str();
|
||||
if s.len() == 0 {
|
||||
~"."
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,10 +437,8 @@ impl GenericPath for PosixPath {
|
||||
}
|
||||
|
||||
fn with_filename(&self, f: &str) -> PosixPath {
|
||||
unsafe {
|
||||
assert!(! str::any(f, |c| windows::is_sep(c as u8)));
|
||||
self.dir_path().push(f)
|
||||
}
|
||||
assert!(! str::any(f, |c| windows::is_sep(c as u8)));
|
||||
self.dir_path().push(f)
|
||||
}
|
||||
|
||||
fn with_filestem(&self, s: &str) -> PosixPath {
|
||||
@ -509,7 +505,7 @@ impl GenericPath for PosixPath {
|
||||
for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| {
|
||||
ss.push(s.to_owned())
|
||||
}
|
||||
unsafe { v.push_all_move(ss); }
|
||||
v.push_all_move(ss);
|
||||
}
|
||||
PosixPath { is_absolute: self.is_absolute,
|
||||
components: v }
|
||||
@ -521,14 +517,14 @@ impl GenericPath for PosixPath {
|
||||
for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| {
|
||||
ss.push(s.to_owned())
|
||||
}
|
||||
unsafe { v.push_all_move(ss); }
|
||||
v.push_all_move(ss);
|
||||
PosixPath { components: v, ..copy *self }
|
||||
}
|
||||
|
||||
fn pop(&self) -> PosixPath {
|
||||
let mut cs = copy self.components;
|
||||
if cs.len() != 0 {
|
||||
unsafe { cs.pop(); }
|
||||
cs.pop();
|
||||
}
|
||||
return PosixPath {
|
||||
is_absolute: self.is_absolute,
|
||||
@ -607,13 +603,11 @@ impl GenericPath for WindowsPath {
|
||||
}
|
||||
|
||||
fn dirname(&self) -> ~str {
|
||||
unsafe {
|
||||
let s = self.dir_path().to_str();
|
||||
if s.len() == 0 {
|
||||
~"."
|
||||
} else {
|
||||
s
|
||||
}
|
||||
let s = self.dir_path().to_str();
|
||||
if s.len() == 0 {
|
||||
~"."
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,7 +764,7 @@ impl GenericPath for WindowsPath {
|
||||
for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| {
|
||||
ss.push(s.to_owned())
|
||||
}
|
||||
unsafe { v.push_all_move(ss); }
|
||||
v.push_all_move(ss);
|
||||
}
|
||||
// tedious, but as-is, we can't use ..self
|
||||
return WindowsPath {
|
||||
@ -787,14 +781,14 @@ impl GenericPath for WindowsPath {
|
||||
for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| {
|
||||
ss.push(s.to_owned())
|
||||
}
|
||||
unsafe { v.push_all_move(ss); }
|
||||
v.push_all_move(ss);
|
||||
return WindowsPath { components: v, ..copy *self }
|
||||
}
|
||||
|
||||
fn pop(&self) -> WindowsPath {
|
||||
let mut cs = copy self.components;
|
||||
if cs.len() != 0 {
|
||||
unsafe { cs.pop(); }
|
||||
cs.pop();
|
||||
}
|
||||
return WindowsPath {
|
||||
host: copy self.host,
|
||||
@ -820,18 +814,14 @@ impl GenericPath for WindowsPath {
|
||||
|
||||
pub fn normalize(components: &[~str]) -> ~[~str] {
|
||||
let mut cs = ~[];
|
||||
unsafe {
|
||||
for components.each |c| {
|
||||
unsafe {
|
||||
if *c == ~"." && components.len() > 1 { loop; }
|
||||
if *c == ~"" { loop; }
|
||||
if *c == ~".." && cs.len() != 0 {
|
||||
cs.pop();
|
||||
loop;
|
||||
}
|
||||
cs.push(copy *c);
|
||||
}
|
||||
for components.each |c| {
|
||||
if *c == ~"." && components.len() > 1 { loop; }
|
||||
if *c == ~"" { loop; }
|
||||
if *c == ~".." && cs.len() != 0 {
|
||||
cs.pop();
|
||||
loop;
|
||||
}
|
||||
cs.push(copy *c);
|
||||
}
|
||||
cs
|
||||
}
|
||||
|
@ -55,17 +55,13 @@ pub fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
|
||||
/// Calculate the offset from a pointer
|
||||
#[inline(always)]
|
||||
pub fn offset<T>(ptr: *T, count: uint) -> *T {
|
||||
unsafe {
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
|
||||
/// Calculate the offset from a const pointer
|
||||
#[inline(always)]
|
||||
pub fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
|
||||
unsafe {
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
|
||||
/// Calculate the offset from a mut pointer
|
||||
|
@ -205,8 +205,6 @@ fn align_down(sp: *mut uint) -> *mut uint {
|
||||
#[inline(always)]
|
||||
pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
|
||||
use core::sys::size_of;
|
||||
unsafe {
|
||||
(ptr as int + count * (size_of::<T>() as int)) as *mut T
|
||||
}
|
||||
(ptr as int + count * (size_of::<T>() as int)) as *mut T
|
||||
}
|
||||
|
||||
|
@ -21,17 +21,17 @@ pub type Key = pthread_key_t;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub unsafe fn create(key: &mut Key) {
|
||||
unsafe { assert!(0 == pthread_key_create(key, null())); }
|
||||
assert!(0 == pthread_key_create(key, null()));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub unsafe fn set(key: Key, value: *mut c_void) {
|
||||
unsafe { assert!(0 == pthread_setspecific(key, value)); }
|
||||
assert!(0 == pthread_setspecific(key, value));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub unsafe fn get(key: Key) -> *mut c_void {
|
||||
unsafe { pthread_getspecific(key) }
|
||||
pthread_getspecific(key)
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
|
@ -382,64 +382,62 @@ pub struct ProgramOutput {status: int, out: ~str, err: ~str}
|
||||
* the contents of stdout and the contents of stderr.
|
||||
*/
|
||||
pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput {
|
||||
unsafe {
|
||||
let pipe_in = os::pipe();
|
||||
let pipe_out = os::pipe();
|
||||
let pipe_err = os::pipe();
|
||||
let pid = spawn_process(prog, args, &None, &None,
|
||||
pipe_in.in, pipe_out.out, pipe_err.out);
|
||||
|
||||
os::close(pipe_in.in);
|
||||
os::close(pipe_out.out);
|
||||
os::close(pipe_err.out);
|
||||
if pid == -1i32 {
|
||||
os::close(pipe_in.out);
|
||||
os::close(pipe_out.in);
|
||||
os::close(pipe_err.in);
|
||||
fail!();
|
||||
}
|
||||
let pipe_in = os::pipe();
|
||||
let pipe_out = os::pipe();
|
||||
let pipe_err = os::pipe();
|
||||
let pid = spawn_process(prog, args, &None, &None,
|
||||
pipe_in.in, pipe_out.out, pipe_err.out);
|
||||
|
||||
os::close(pipe_in.in);
|
||||
os::close(pipe_out.out);
|
||||
os::close(pipe_err.out);
|
||||
if pid == -1i32 {
|
||||
os::close(pipe_in.out);
|
||||
|
||||
// Spawn two entire schedulers to read both stdout and sterr
|
||||
// in parallel so we don't deadlock while blocking on one
|
||||
// or the other. FIXME (#2625): Surely there's a much more
|
||||
// clever way to do this.
|
||||
let (p, ch) = stream();
|
||||
let ch = SharedChan(ch);
|
||||
let ch_clone = ch.clone();
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
let errput = readclose(pipe_err.in);
|
||||
ch.send((2, errput));
|
||||
};
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
let output = readclose(pipe_out.in);
|
||||
ch_clone.send((1, output));
|
||||
};
|
||||
let status = run::waitpid(pid);
|
||||
let mut errs = ~"";
|
||||
let mut outs = ~"";
|
||||
let mut count = 2;
|
||||
while count > 0 {
|
||||
let stream = p.recv();
|
||||
match stream {
|
||||
(1, copy s) => {
|
||||
outs = s;
|
||||
}
|
||||
(2, copy s) => {
|
||||
errs = s;
|
||||
}
|
||||
(n, _) => {
|
||||
fail!(fmt!("program_output received an unexpected file \
|
||||
number: %u", n));
|
||||
}
|
||||
};
|
||||
count -= 1;
|
||||
};
|
||||
return ProgramOutput {status: status,
|
||||
out: outs,
|
||||
err: errs};
|
||||
os::close(pipe_out.in);
|
||||
os::close(pipe_err.in);
|
||||
fail!();
|
||||
}
|
||||
|
||||
os::close(pipe_in.out);
|
||||
|
||||
// Spawn two entire schedulers to read both stdout and sterr
|
||||
// in parallel so we don't deadlock while blocking on one
|
||||
// or the other. FIXME (#2625): Surely there's a much more
|
||||
// clever way to do this.
|
||||
let (p, ch) = stream();
|
||||
let ch = SharedChan(ch);
|
||||
let ch_clone = ch.clone();
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
let errput = readclose(pipe_err.in);
|
||||
ch.send((2, errput));
|
||||
};
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
let output = readclose(pipe_out.in);
|
||||
ch_clone.send((1, output));
|
||||
};
|
||||
let status = run::waitpid(pid);
|
||||
let mut errs = ~"";
|
||||
let mut outs = ~"";
|
||||
let mut count = 2;
|
||||
while count > 0 {
|
||||
let stream = p.recv();
|
||||
match stream {
|
||||
(1, copy s) => {
|
||||
outs = s;
|
||||
}
|
||||
(2, copy s) => {
|
||||
errs = s;
|
||||
}
|
||||
(n, _) => {
|
||||
fail!(fmt!("program_output received an unexpected file \
|
||||
number: %u", n));
|
||||
}
|
||||
};
|
||||
count -= 1;
|
||||
};
|
||||
return ProgramOutput {status: status,
|
||||
out: outs,
|
||||
err: errs};
|
||||
}
|
||||
|
||||
pub fn writeclose(fd: c_int, s: ~str) {
|
||||
|
@ -170,18 +170,16 @@ pub fn push_char(s: &mut ~str, ch: char) {
|
||||
/// Convert a char to a string
|
||||
pub fn from_char(ch: char) -> ~str {
|
||||
let mut buf = ~"";
|
||||
unsafe { push_char(&mut buf, ch); }
|
||||
push_char(&mut buf, ch);
|
||||
buf
|
||||
}
|
||||
|
||||
/// Convert a vector of chars to a string
|
||||
pub fn from_chars(chs: &[char]) -> ~str {
|
||||
let mut buf = ~"";
|
||||
unsafe {
|
||||
reserve(&mut buf, chs.len());
|
||||
for vec::each(chs) |ch| {
|
||||
push_char(&mut buf, *ch);
|
||||
}
|
||||
reserve(&mut buf, chs.len());
|
||||
for vec::each(chs) |ch| {
|
||||
push_char(&mut buf, *ch);
|
||||
}
|
||||
buf
|
||||
}
|
||||
@ -226,9 +224,7 @@ pub fn push_str(lhs: &mut ~str, rhs: &str) {
|
||||
#[inline(always)]
|
||||
pub fn append(lhs: ~str, rhs: &str) -> ~str {
|
||||
let mut v = lhs;
|
||||
unsafe {
|
||||
push_str_no_overallocate(&mut v, rhs);
|
||||
}
|
||||
push_str_no_overallocate(&mut v, rhs);
|
||||
v
|
||||
}
|
||||
|
||||
@ -236,7 +232,7 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str {
|
||||
pub fn concat(v: &[~str]) -> ~str {
|
||||
let mut s: ~str = ~"";
|
||||
for vec::each(v) |ss| {
|
||||
unsafe { push_str(&mut s, *ss) };
|
||||
push_str(&mut s, *ss);
|
||||
}
|
||||
s
|
||||
}
|
||||
@ -245,8 +241,8 @@ pub fn concat(v: &[~str]) -> ~str {
|
||||
pub fn connect(v: &[~str], sep: &str) -> ~str {
|
||||
let mut s = ~"", first = true;
|
||||
for vec::each(v) |ss| {
|
||||
if first { first = false; } else { unsafe { push_str(&mut s, sep); } }
|
||||
unsafe { push_str(&mut s, *ss) };
|
||||
if first { first = false; } else { push_str(&mut s, sep); }
|
||||
push_str(&mut s, *ss);
|
||||
}
|
||||
s
|
||||
}
|
||||
@ -255,8 +251,8 @@ pub fn connect(v: &[~str], sep: &str) -> ~str {
|
||||
pub fn connect_slices(v: &[&str], sep: &str) -> ~str {
|
||||
let mut s = ~"", first = true;
|
||||
for vec::each(v) |ss| {
|
||||
if first { first = false; } else { unsafe { push_str(&mut s, sep); } }
|
||||
unsafe { push_str(&mut s, *ss) };
|
||||
if first { first = false; } else { push_str(&mut s, sep); }
|
||||
push_str(&mut s, *ss);
|
||||
}
|
||||
s
|
||||
}
|
||||
@ -2251,16 +2247,14 @@ pub mod raw {
|
||||
assert!((end <= n));
|
||||
|
||||
let mut v = vec::with_capacity(end - begin + 1u);
|
||||
unsafe {
|
||||
do vec::as_imm_buf(v) |vbuf, _vlen| {
|
||||
let vbuf = ::cast::transmute_mut_unsafe(vbuf);
|
||||
let src = ptr::offset(sbuf, begin);
|
||||
ptr::copy_memory(vbuf, src, end - begin);
|
||||
}
|
||||
vec::raw::set_len(&mut v, end - begin);
|
||||
v.push(0u8);
|
||||
::cast::transmute(v)
|
||||
do vec::as_imm_buf(v) |vbuf, _vlen| {
|
||||
let vbuf = ::cast::transmute_mut_unsafe(vbuf);
|
||||
let src = ptr::offset(sbuf, begin);
|
||||
ptr::copy_memory(vbuf, src, end - begin);
|
||||
}
|
||||
vec::raw::set_len(&mut v, end - begin);
|
||||
v.push(0u8);
|
||||
::cast::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2304,7 +2298,7 @@ pub mod raw {
|
||||
}
|
||||
|
||||
/// Removes the last byte from a string and returns it. (Not UTF-8 safe).
|
||||
pub unsafe fn pop_byte(s: &mut ~str) -> u8 {
|
||||
pub fn pop_byte(s: &mut ~str) -> u8 {
|
||||
let len = len(*s);
|
||||
assert!((len > 0u));
|
||||
let b = s[len - 1u];
|
||||
@ -2313,7 +2307,7 @@ pub mod raw {
|
||||
}
|
||||
|
||||
/// Removes the first byte from a string and returns it. (Not UTF-8 safe).
|
||||
pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
|
||||
pub fn shift_byte(s: &mut ~str) -> u8 {
|
||||
let len = len(*s);
|
||||
assert!((len > 0u));
|
||||
let b = s[0];
|
||||
|
@ -127,10 +127,8 @@ pub fn refcount<T>(t: @T) -> uint {
|
||||
}
|
||||
|
||||
pub fn log_str<T>(t: &T) -> ~str {
|
||||
unsafe {
|
||||
do io::with_str_writer |wr| {
|
||||
repr::write_repr(wr, t)
|
||||
}
|
||||
do io::with_str_writer |wr| {
|
||||
repr::write_repr(wr, t)
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,10 +155,8 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
}
|
||||
|
||||
pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
|
||||
unsafe {
|
||||
let (msg, file) = (msg.to_owned(), file.to_owned());
|
||||
begin_unwind(~"assertion failed: " + msg, file, line)
|
||||
}
|
||||
let (msg, file) = (msg.to_owned(), file.to_owned());
|
||||
begin_unwind(~"assertion failed: " + msg, file, line)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -39,10 +39,9 @@ use result::Result;
|
||||
use comm::{stream, Chan, GenericChan, GenericPort, Port};
|
||||
use prelude::*;
|
||||
use result;
|
||||
use task::rt::{task_id, sched_id};
|
||||
use task::rt::{task_id, sched_id, rust_task};
|
||||
use util;
|
||||
use util::replace;
|
||||
use unstable::finally::Finally;
|
||||
|
||||
#[cfg(test)] use comm::SharedChan;
|
||||
|
||||
@ -566,28 +565,48 @@ pub fn get_scheduler() -> Scheduler {
|
||||
* ~~~
|
||||
*/
|
||||
pub unsafe fn unkillable<U>(f: &fn() -> U) -> U {
|
||||
unsafe {
|
||||
let t = rt::rust_get_task();
|
||||
rt::rust_task_inhibit_kill(t);
|
||||
do (|| {
|
||||
f()
|
||||
}).finally {
|
||||
rt::rust_task_allow_kill(t);
|
||||
struct AllowFailure {
|
||||
t: *rust_task,
|
||||
drop {
|
||||
unsafe {
|
||||
rt::rust_task_allow_kill(self.t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn AllowFailure(t: *rust_task) -> AllowFailure{
|
||||
AllowFailure {
|
||||
t: t
|
||||
}
|
||||
}
|
||||
|
||||
let t = rt::rust_get_task();
|
||||
let _allow_failure = AllowFailure(t);
|
||||
rt::rust_task_inhibit_kill(t);
|
||||
f()
|
||||
}
|
||||
|
||||
/// The inverse of unkillable. Only ever to be used nested in unkillable().
|
||||
pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
|
||||
unsafe {
|
||||
let t = rt::rust_get_task();
|
||||
rt::rust_task_allow_kill(t);
|
||||
do (|| {
|
||||
f()
|
||||
}).finally {
|
||||
rt::rust_task_inhibit_kill(t);
|
||||
struct DisallowFailure {
|
||||
t: *rust_task,
|
||||
drop {
|
||||
unsafe {
|
||||
rt::rust_task_inhibit_kill(self.t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn DisallowFailure(t: *rust_task) -> DisallowFailure {
|
||||
DisallowFailure {
|
||||
t: t
|
||||
}
|
||||
}
|
||||
|
||||
let t = rt::rust_get_task();
|
||||
let _allow_failure = DisallowFailure(t);
|
||||
rt::rust_task_allow_kill(t);
|
||||
f()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,17 +614,27 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
|
||||
* For use with exclusive ARCs, which use pthread mutexes directly.
|
||||
*/
|
||||
pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
|
||||
unsafe {
|
||||
let t = rt::rust_get_task();
|
||||
rt::rust_task_inhibit_kill(t);
|
||||
rt::rust_task_inhibit_yield(t);
|
||||
do (|| {
|
||||
f()
|
||||
}).finally {
|
||||
rt::rust_task_allow_yield(t);
|
||||
rt::rust_task_allow_kill(t);
|
||||
struct DeferInterrupts {
|
||||
t: *rust_task,
|
||||
drop {
|
||||
unsafe {
|
||||
rt::rust_task_allow_yield(self.t);
|
||||
rt::rust_task_allow_kill(self.t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn DeferInterrupts(t: *rust_task) -> DeferInterrupts {
|
||||
DeferInterrupts {
|
||||
t: t
|
||||
}
|
||||
}
|
||||
|
||||
let t = rt::rust_get_task();
|
||||
let _interrupts = DeferInterrupts(t);
|
||||
rt::rust_task_inhibit_kill(t);
|
||||
rt::rust_task_inhibit_yield(t);
|
||||
f()
|
||||
}
|
||||
|
||||
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||
|
@ -157,13 +157,13 @@ struct AncestorList(Option<unstable::Exclusive<AncestorNode>>);
|
||||
// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
|
||||
#[inline(always)]
|
||||
fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U {
|
||||
unsafe { x.with(blk) }
|
||||
x.with(blk)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn access_ancestors<U>(x: &unstable::Exclusive<AncestorNode>,
|
||||
blk: &fn(x: &mut AncestorNode) -> U) -> U {
|
||||
unsafe { x.with(blk) }
|
||||
x.with(blk)
|
||||
}
|
||||
|
||||
// Iterates over an ancestor list.
|
||||
|
@ -152,45 +152,37 @@ pub type SharedMutableState<T> = ArcDestruct<T>;
|
||||
pub unsafe fn shared_mutable_state<T:Owned>(data: T) ->
|
||||
SharedMutableState<T> {
|
||||
let data = ~ArcData { count: 1, data: Some(data) };
|
||||
unsafe {
|
||||
let ptr = cast::transmute(data);
|
||||
ArcDestruct(ptr)
|
||||
}
|
||||
let ptr = cast::transmute(data);
|
||||
ArcDestruct(ptr)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn get_shared_mutable_state<T:Owned>(
|
||||
rc: *SharedMutableState<T>) -> *mut T
|
||||
{
|
||||
unsafe {
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
assert!(ptr.count > 0);
|
||||
let r = cast::transmute(ptr.data.get_ref());
|
||||
cast::forget(ptr);
|
||||
return r;
|
||||
}
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
assert!(ptr.count > 0);
|
||||
let r = cast::transmute(ptr.data.get_ref());
|
||||
cast::forget(ptr);
|
||||
return r;
|
||||
}
|
||||
#[inline(always)]
|
||||
pub unsafe fn get_shared_immutable_state<'a,T:Owned>(
|
||||
rc: &'a SharedMutableState<T>) -> &'a T {
|
||||
unsafe {
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
assert!(ptr.count > 0);
|
||||
// Cast us back into the correct region
|
||||
let r = cast::transmute_region(ptr.data.get_ref());
|
||||
cast::forget(ptr);
|
||||
return r;
|
||||
}
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
assert!(ptr.count > 0);
|
||||
// Cast us back into the correct region
|
||||
let r = cast::transmute_region(ptr.data.get_ref());
|
||||
cast::forget(ptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
pub unsafe fn clone_shared_mutable_state<T:Owned>(rc: &SharedMutableState<T>)
|
||||
-> SharedMutableState<T> {
|
||||
unsafe {
|
||||
let mut ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1;
|
||||
assert!(new_count >= 2);
|
||||
cast::forget(ptr);
|
||||
}
|
||||
let mut ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1;
|
||||
assert!(new_count >= 2);
|
||||
cast::forget(ptr);
|
||||
ArcDestruct((*rc).data)
|
||||
}
|
||||
|
||||
|
@ -19,27 +19,25 @@ use ptr::null;
|
||||
use intrinsic::TyDesc;
|
||||
|
||||
pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
|
||||
unsafe {
|
||||
assert!(td.is_not_null());
|
||||
assert!(td.is_not_null());
|
||||
|
||||
let total_size = get_box_size(size, (*td).align);
|
||||
let p = c_malloc(total_size as size_t);
|
||||
assert!(p.is_not_null());
|
||||
let total_size = get_box_size(size, (*td).align);
|
||||
let p = c_malloc(total_size as size_t);
|
||||
assert!(p.is_not_null());
|
||||
|
||||
// FIXME #3475: Converting between our two different tydesc types
|
||||
let td: *TyDesc = transmute(td);
|
||||
// FIXME #3475: Converting between our two different tydesc types
|
||||
let td: *TyDesc = transmute(td);
|
||||
|
||||
let box: &mut BoxRepr = transmute(p);
|
||||
box.header.ref_count = -1; // Exchange values not ref counted
|
||||
box.header.type_desc = td;
|
||||
box.header.prev = null();
|
||||
box.header.next = null();
|
||||
let box: &mut BoxRepr = transmute(p);
|
||||
box.header.ref_count = -1; // Exchange values not ref counted
|
||||
box.header.type_desc = td;
|
||||
box.header.prev = null();
|
||||
box.header.next = null();
|
||||
|
||||
let exchange_count = &mut *rust_get_exchange_count_ptr();
|
||||
atomic_xadd(exchange_count, 1);
|
||||
let exchange_count = &mut *rust_get_exchange_count_ptr();
|
||||
atomic_xadd(exchange_count, 1);
|
||||
|
||||
return transmute(box);
|
||||
}
|
||||
return transmute(box);
|
||||
}
|
||||
/**
|
||||
Thin wrapper around libc::malloc, none of the box header
|
||||
|
@ -512,7 +512,7 @@ pub mod rt {
|
||||
None
|
||||
}
|
||||
} else { Some('-') };
|
||||
unsafe { pad(cv, s, head, PadSigned, buf) };
|
||||
pad(cv, s, head, PadSigned, buf);
|
||||
}
|
||||
pub fn conv_uint(cv: Conv, u: uint, buf: &mut ~str) {
|
||||
let prec = get_int_precision(cv);
|
||||
@ -524,7 +524,7 @@ pub mod rt {
|
||||
TyBits => uint_to_str_prec(u, 2, prec),
|
||||
TyOctal => uint_to_str_prec(u, 8, prec)
|
||||
};
|
||||
unsafe { pad(cv, rs, None, PadUnsigned, buf) };
|
||||
pad(cv, rs, None, PadUnsigned, buf);
|
||||
}
|
||||
pub fn conv_bool(cv: Conv, b: bool, buf: &mut ~str) {
|
||||
let s = if b { "true" } else { "false" };
|
||||
@ -533,7 +533,7 @@ pub mod rt {
|
||||
conv_str(cv, s, buf);
|
||||
}
|
||||
pub fn conv_char(cv: Conv, c: char, buf: &mut ~str) {
|
||||
unsafe { pad(cv, "", Some(c), PadNozero, buf) };
|
||||
pad(cv, "", Some(c), PadNozero, buf);
|
||||
}
|
||||
pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) {
|
||||
// For strings, precision is the maximum characters
|
||||
@ -546,14 +546,14 @@ pub mod rt {
|
||||
s
|
||||
}
|
||||
};
|
||||
unsafe { pad(cv, unpadded, None, PadNozero, buf) };
|
||||
pad(cv, unpadded, None, PadNozero, buf);
|
||||
}
|
||||
pub fn conv_float(cv: Conv, f: float, buf: &mut ~str) {
|
||||
let (to_str, digits) = match cv.precision {
|
||||
CountIs(c) => (float::to_str_exact, c as uint),
|
||||
CountImplied => (float::to_str_digits, 6u)
|
||||
};
|
||||
let mut s = unsafe { to_str(f, digits) };
|
||||
let mut s = to_str(f, digits);
|
||||
let head = if 0.0 <= f {
|
||||
if have_flag(cv.flags, flag_sign_always) {
|
||||
Some('+')
|
||||
@ -563,7 +563,7 @@ pub mod rt {
|
||||
None
|
||||
}
|
||||
} else { None };
|
||||
unsafe { pad(cv, s, head, PadFloat, buf) };
|
||||
pad(cv, s, head, PadFloat, buf);
|
||||
}
|
||||
pub fn conv_poly<T>(cv: Conv, v: &T, buf: &mut ~str) {
|
||||
let s = sys::log_str(v);
|
||||
|
@ -44,7 +44,7 @@ pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
}
|
||||
|
||||
#[lang="fail_bounds_check"]
|
||||
pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
pub fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
index: size_t, len: size_t) {
|
||||
let msg = fmt!("index out of bounds: the len is %d but the index is %d",
|
||||
len as int, index as int);
|
||||
@ -53,7 +53,7 @@ pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn fail_borrowed() {
|
||||
pub fn fail_borrowed() {
|
||||
let msg = "borrowed";
|
||||
do str::as_buf(msg) |msg_p, _| {
|
||||
do str::as_buf("???") |file_p, _| {
|
||||
|
@ -615,9 +615,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
|
||||
}
|
||||
|
||||
pub fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str {
|
||||
unsafe {
|
||||
symbol_hasher.result_str()
|
||||
}
|
||||
symbol_hasher.result_str()
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,6 +33,7 @@ use util::ppaux::ty_to_str;
|
||||
|
||||
use core::hashmap::HashSet;
|
||||
use core::uint;
|
||||
use core::util::with;
|
||||
use syntax::ast::m_mutbl;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
@ -40,13 +41,18 @@ use syntax::codemap::span;
|
||||
use syntax::print::pprust;
|
||||
use syntax::visit;
|
||||
|
||||
struct PurityState {
|
||||
def: ast::node_id,
|
||||
purity: ast::purity
|
||||
}
|
||||
|
||||
struct CheckLoanCtxt {
|
||||
bccx: @BorrowckCtxt,
|
||||
req_maps: ReqMaps,
|
||||
|
||||
reported: HashSet<ast::node_id>,
|
||||
|
||||
declared_purity: @mut ast::purity,
|
||||
declared_purity: @mut PurityState,
|
||||
fn_args: @mut @~[ast::node_id]
|
||||
}
|
||||
|
||||
@ -62,6 +68,16 @@ enum purity_cause {
|
||||
pc_cmt(bckerr)
|
||||
}
|
||||
|
||||
// if we're not pure, why?
|
||||
#[deriving(Eq)]
|
||||
enum impurity_cause {
|
||||
// some surrounding block was marked as 'unsafe'
|
||||
pc_unsafe,
|
||||
|
||||
// nothing was unsafe, and nothing was pure
|
||||
pc_default,
|
||||
}
|
||||
|
||||
pub fn check_loans(bccx: @BorrowckCtxt,
|
||||
+req_maps: ReqMaps,
|
||||
crate: @ast::crate) {
|
||||
@ -69,7 +85,8 @@ pub fn check_loans(bccx: @BorrowckCtxt,
|
||||
bccx: bccx,
|
||||
req_maps: req_maps,
|
||||
reported: HashSet::new(),
|
||||
declared_purity: @mut ast::impure_fn,
|
||||
declared_purity: @mut PurityState { purity: ast::impure_fn,
|
||||
def: 0 },
|
||||
fn_args: @mut @~[]
|
||||
};
|
||||
let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr,
|
||||
@ -106,16 +123,18 @@ pub impl assignment_type {
|
||||
pub impl CheckLoanCtxt {
|
||||
fn tcx(&self) -> ty::ctxt { self.bccx.tcx }
|
||||
|
||||
fn purity(&mut self, scope_id: ast::node_id) -> Option<purity_cause> {
|
||||
let default_purity = match *self.declared_purity {
|
||||
fn purity(&mut self, scope_id: ast::node_id)
|
||||
-> Either<purity_cause, impurity_cause>
|
||||
{
|
||||
let default_purity = match self.declared_purity.purity {
|
||||
// an unsafe declaration overrides all
|
||||
ast::unsafe_fn => return None,
|
||||
ast::unsafe_fn => return Right(pc_unsafe),
|
||||
|
||||
// otherwise, remember what was declared as the
|
||||
// default, but we must scan for requirements
|
||||
// imposed by the borrow check
|
||||
ast::pure_fn => Some(pc_pure_fn),
|
||||
ast::extern_fn | ast::impure_fn => None
|
||||
ast::pure_fn => Left(pc_pure_fn),
|
||||
ast::extern_fn | ast::impure_fn => Right(pc_default)
|
||||
};
|
||||
|
||||
// scan to see if this scope or any enclosing scope requires
|
||||
@ -125,7 +144,7 @@ pub impl CheckLoanCtxt {
|
||||
loop {
|
||||
match self.req_maps.pure_map.find(&scope_id) {
|
||||
None => (),
|
||||
Some(e) => return Some(pc_cmt(*e))
|
||||
Some(e) => return Left(pc_cmt(*e))
|
||||
}
|
||||
|
||||
match self.tcx().region_maps.opt_encl_scope(scope_id) {
|
||||
@ -171,7 +190,7 @@ pub impl CheckLoanCtxt {
|
||||
// overloaded operators the callee has an id but no expr.
|
||||
// annoying.
|
||||
fn check_pure_callee_or_arg(&mut self,
|
||||
pc: purity_cause,
|
||||
pc: Either<purity_cause, impurity_cause>,
|
||||
opt_expr: Option<@ast::expr>,
|
||||
callee_id: ast::node_id,
|
||||
callee_span: span) {
|
||||
@ -196,7 +215,7 @@ pub impl CheckLoanCtxt {
|
||||
match opt_expr {
|
||||
Some(expr) => {
|
||||
match expr.node {
|
||||
ast::expr_path(_) if pc == pc_pure_fn => {
|
||||
ast::expr_path(_) if pc == Left(pc_pure_fn) => {
|
||||
let def = *self.tcx().def_map.get(&expr.id);
|
||||
let did = ast_util::def_id_of_def(def);
|
||||
let is_fn_arg =
|
||||
@ -361,10 +380,10 @@ pub impl CheckLoanCtxt {
|
||||
// if this is a pure function, only loan-able state can be
|
||||
// assigned, because it is uniquely tied to this function and
|
||||
// is not visible from the outside
|
||||
match self.purity(ex.id) {
|
||||
None => (),
|
||||
Some(pc_cmt(_)) => {
|
||||
let purity = self.purity(ex.id).get();
|
||||
let purity = self.purity(ex.id);
|
||||
match purity {
|
||||
Right(_) => (),
|
||||
Left(pc_cmt(_)) => {
|
||||
// Subtle: Issue #3162. If we are enforcing purity
|
||||
// because there is a reference to aliasable, mutable data
|
||||
// that we require to be immutable, we can't allow writes
|
||||
@ -376,10 +395,10 @@ pub impl CheckLoanCtxt {
|
||||
ex.span,
|
||||
at.ing_form(self.bccx.cmt_to_str(cmt)));
|
||||
}
|
||||
Some(pc_pure_fn) => {
|
||||
Left(pc_pure_fn) => {
|
||||
if cmt.lp.is_none() {
|
||||
self.report_purity_error(
|
||||
pc_pure_fn, ex.span,
|
||||
purity, ex.span,
|
||||
at.ing_form(self.bccx.cmt_to_str(cmt)));
|
||||
}
|
||||
}
|
||||
@ -462,14 +481,23 @@ pub impl CheckLoanCtxt {
|
||||
}
|
||||
}
|
||||
|
||||
fn report_purity_error(&mut self, pc: purity_cause, sp: span, msg: ~str) {
|
||||
fn report_purity_error(&mut self, pc: Either<purity_cause, impurity_cause>,
|
||||
sp: span, msg: ~str) {
|
||||
match pc {
|
||||
pc_pure_fn => {
|
||||
Right(pc_default) => { fail!(~"pc_default should be filtered sooner") }
|
||||
Right(pc_unsafe) => {
|
||||
// this error was prevented by being marked as unsafe, so flag the
|
||||
// definition as having contributed to the validity of the program
|
||||
let def = self.declared_purity.def;
|
||||
debug!("flagging %? as a used unsafe source", def);
|
||||
self.tcx().used_unsafe.insert(def);
|
||||
}
|
||||
Left(pc_pure_fn) => {
|
||||
self.tcx().sess.span_err(
|
||||
sp,
|
||||
fmt!("%s prohibited in pure context", msg));
|
||||
}
|
||||
pc_cmt(ref e) => {
|
||||
Left(pc_cmt(ref e)) => {
|
||||
if self.reported.insert((*e).cmt.id) {
|
||||
self.tcx().sess.span_err(
|
||||
(*e).cmt.span,
|
||||
@ -556,16 +584,32 @@ pub impl CheckLoanCtxt {
|
||||
callee_id: ast::node_id,
|
||||
callee_span: span,
|
||||
args: &[@ast::expr]) {
|
||||
match self.purity(expr.id) {
|
||||
None => {}
|
||||
Some(ref pc) => {
|
||||
self.check_pure_callee_or_arg(
|
||||
(*pc), callee, callee_id, callee_span);
|
||||
for args.each |arg| {
|
||||
self.check_pure_callee_or_arg(
|
||||
(*pc), Some(*arg), arg.id, arg.span);
|
||||
let pc = self.purity(expr.id);
|
||||
match pc {
|
||||
// no purity, no need to check for anything
|
||||
Right(pc_default) => return,
|
||||
|
||||
// some form of purity, definitely need to check
|
||||
Left(_) => (),
|
||||
|
||||
// Unsafe trumped. To see if the unsafe is necessary, see what the
|
||||
// purity would have been without a trump, and if it's some form
|
||||
// of purity then we need to go ahead with the check
|
||||
Right(pc_unsafe) => {
|
||||
match do with(&mut self.declared_purity.purity,
|
||||
ast::impure_fn) { self.purity(expr.id) } {
|
||||
Right(pc_unsafe) => fail!(~"unsafe can't trump twice"),
|
||||
Right(pc_default) => return,
|
||||
Left(_) => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
self.check_pure_callee_or_arg(
|
||||
pc, callee, callee_id, callee_span);
|
||||
for args.each |arg| {
|
||||
self.check_pure_callee_or_arg(
|
||||
pc, Some(*arg), arg.id, arg.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -580,27 +624,32 @@ fn check_loans_in_fn(fk: &visit::fn_kind,
|
||||
let is_stack_closure = self.is_stack_closure(id);
|
||||
let fty = ty::node_id_to_type(self.tcx(), id);
|
||||
|
||||
let declared_purity;
|
||||
let declared_purity, src;
|
||||
match *fk {
|
||||
visit::fk_item_fn(*) | visit::fk_method(*) |
|
||||
visit::fk_dtor(*) => {
|
||||
declared_purity = ty::ty_fn_purity(fty);
|
||||
src = id;
|
||||
}
|
||||
|
||||
visit::fk_anon(*) | visit::fk_fn_block(*) => {
|
||||
let fty_sigil = ty::ty_closure_sigil(fty);
|
||||
check_moves_from_captured_variables(self, id, fty_sigil);
|
||||
declared_purity = ty::determine_inherited_purity(
|
||||
*self.declared_purity,
|
||||
ty::ty_fn_purity(fty),
|
||||
let pair = ty::determine_inherited_purity(
|
||||
(self.declared_purity.purity, self.declared_purity.def),
|
||||
(ty::ty_fn_purity(fty), id),
|
||||
fty_sigil);
|
||||
declared_purity = pair.first();
|
||||
src = pair.second();
|
||||
}
|
||||
}
|
||||
|
||||
debug!("purity on entry=%?", copy self.declared_purity);
|
||||
do save_and_restore_managed(self.declared_purity) {
|
||||
do save_and_restore_managed(self.fn_args) {
|
||||
*self.declared_purity = declared_purity;
|
||||
self.declared_purity = @mut PurityState {
|
||||
purity: declared_purity, def: src
|
||||
};
|
||||
|
||||
match *fk {
|
||||
visit::fk_anon(*) |
|
||||
@ -754,7 +803,10 @@ fn check_loans_in_block(blk: &ast::blk,
|
||||
ast::default_blk => {
|
||||
}
|
||||
ast::unsafe_blk => {
|
||||
*self.declared_purity = ast::unsafe_fn;
|
||||
*self.declared_purity = PurityState {
|
||||
purity: ast::unsafe_fn,
|
||||
def: blk.node.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ pub impl<'self> LanguageItemCollector<'self> {
|
||||
}
|
||||
|
||||
fn collect_local_language_items(&self) {
|
||||
let this = unsafe { ptr::addr_of(&self) };
|
||||
let this = ptr::addr_of(&self);
|
||||
visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor {
|
||||
visit_item: |item| {
|
||||
for item.attrs.each |attribute| {
|
||||
|
@ -75,6 +75,7 @@ pub enum lint {
|
||||
default_methods,
|
||||
deprecated_mutable_fields,
|
||||
deprecated_drop,
|
||||
unused_unsafe,
|
||||
foreign_mode,
|
||||
|
||||
managed_heap_memory,
|
||||
@ -256,6 +257,13 @@ pub fn get_lint_dict() -> LintDict {
|
||||
default: deny
|
||||
}),
|
||||
|
||||
(~"unused_unsafe",
|
||||
LintSpec {
|
||||
lint: unused_unsafe,
|
||||
desc: "unnecessary use of an \"unsafe\" block or function",
|
||||
default: warn
|
||||
}),
|
||||
|
||||
(~"unused_variable",
|
||||
LintSpec {
|
||||
lint: unused_variable,
|
||||
@ -490,6 +498,7 @@ fn check_item(i: @ast::item, cx: ty::ctxt) {
|
||||
check_item_default_methods(cx, i);
|
||||
check_item_deprecated_mutable_fields(cx, i);
|
||||
check_item_deprecated_drop(cx, i);
|
||||
check_item_unused_unsafe(cx, i);
|
||||
}
|
||||
|
||||
// Take a visitor, and modify it so that it will not proceed past subitems.
|
||||
@ -923,19 +932,55 @@ fn check_item_non_camel_case_types(cx: ty::ctxt, it: @ast::item) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_unused_unsafe(cx: ty::ctxt, it: @ast::item) {
|
||||
let visit_expr: @fn(@ast::expr) = |e| {
|
||||
match e.node {
|
||||
ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
|
||||
if !cx.used_unsafe.contains(&blk.node.id) {
|
||||
cx.sess.span_lint(unused_unsafe, blk.node.id, it.id,
|
||||
blk.span,
|
||||
~"unnecessary \"unsafe\" block");
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
};
|
||||
|
||||
let visit = item_stopping_visitor(
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_expr: visit_expr,
|
||||
.. *visit::default_simple_visitor()
|
||||
}));
|
||||
visit::visit_item(it, (), visit);
|
||||
}
|
||||
|
||||
fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl,
|
||||
_body: &ast::blk, span: span, id: ast::node_id) {
|
||||
debug!("lint check_fn fk=%? id=%?", fk, id);
|
||||
|
||||
// don't complain about blocks, since they tend to get their modes
|
||||
// specified from the outside
|
||||
// Check for an 'unsafe fn' which doesn't need to be unsafe
|
||||
match *fk {
|
||||
visit::fk_fn_block(*) => { return; }
|
||||
_ => {}
|
||||
visit::fk_item_fn(_, _, ast::unsafe_fn, _) => {
|
||||
if !tcx.used_unsafe.contains(&id) {
|
||||
tcx.sess.span_lint(unused_unsafe, id, id, span,
|
||||
~"unnecessary \"unsafe\" function");
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
// Check for deprecated modes
|
||||
match *fk {
|
||||
// don't complain about blocks, since they tend to get their modes
|
||||
// specified from the outside
|
||||
visit::fk_fn_block(*) => {}
|
||||
|
||||
_ => {
|
||||
let fn_ty = ty::node_id_to_type(tcx, id);
|
||||
check_fn_deprecated_modes(tcx, fn_ty, decl, span, id);
|
||||
}
|
||||
}
|
||||
|
||||
let fn_ty = ty::node_id_to_type(tcx, id);
|
||||
check_fn_deprecated_modes(tcx, fn_ty, decl, span, id);
|
||||
}
|
||||
|
||||
fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: &ast::fn_decl,
|
||||
|
@ -19,7 +19,7 @@ use metadata::csearch::get_type_name_if_impl;
|
||||
use metadata::cstore::find_extern_mod_stmt_cnum;
|
||||
use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
|
||||
use middle::lang_items::LanguageItems;
|
||||
use middle::lint::{deny, allow, forbid, level, unused_imports, warn};
|
||||
use middle::lint::{allow, level, unused_imports};
|
||||
use middle::lint::{get_lint_level, get_lint_settings_level};
|
||||
use middle::pat_util::pat_bindings;
|
||||
|
||||
@ -5212,17 +5212,11 @@ pub impl Resolver {
|
||||
import_resolution.span != dummy_sp() &&
|
||||
import_resolution.privacy != Public {
|
||||
import_resolution.state.warned = true;
|
||||
match self.unused_import_lint_level(module_) {
|
||||
warn => {
|
||||
self.session.span_warn(copy import_resolution.span,
|
||||
~"unused import");
|
||||
}
|
||||
deny | forbid => {
|
||||
self.session.span_err(copy import_resolution.span,
|
||||
~"unused import");
|
||||
}
|
||||
allow => ()
|
||||
}
|
||||
let span = import_resolution.span;
|
||||
self.session.span_lint_level(
|
||||
self.unused_import_lint_level(module_),
|
||||
span,
|
||||
~"unused import");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,10 +91,8 @@ pub struct icx_popper {
|
||||
#[unsafe_destructor]
|
||||
impl Drop for icx_popper {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
if self.ccx.sess.count_llvm_insns() {
|
||||
self.ccx.stats.llvm_insn_ctxt.pop();
|
||||
}
|
||||
if self.ccx.sess.count_llvm_insns() {
|
||||
self.ccx.stats.llvm_insn_ctxt.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,9 +143,7 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
|
||||
llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
|
||||
}
|
||||
});
|
||||
unsafe {
|
||||
lib::llvm::SetFunctionCallConv(llfn, cc);
|
||||
}
|
||||
lib::llvm::SetFunctionCallConv(llfn, cc);
|
||||
return llfn;
|
||||
}
|
||||
|
||||
@ -730,11 +726,9 @@ pub fn cast_shift_expr_rhs(cx: block, op: ast::binop,
|
||||
|
||||
pub fn cast_shift_const_rhs(op: ast::binop,
|
||||
lhs: ValueRef, rhs: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
cast_shift_rhs(op, lhs, rhs,
|
||||
|a, b| unsafe { llvm::LLVMConstTrunc(a, b) },
|
||||
|a, b| unsafe { llvm::LLVMConstZExt(a, b) })
|
||||
}
|
||||
cast_shift_rhs(op, lhs, rhs,
|
||||
|a, b| unsafe { llvm::LLVMConstTrunc(a, b) },
|
||||
|a, b| unsafe { llvm::LLVMConstZExt(a, b) })
|
||||
}
|
||||
|
||||
pub fn cast_shift_rhs(op: ast::binop,
|
||||
@ -2865,9 +2859,7 @@ pub fn create_module_map(ccx: @CrateContext) -> ValueRef {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
|
||||
}
|
||||
});
|
||||
unsafe {
|
||||
lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
|
||||
}
|
||||
lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
|
||||
let mut elts: ~[ValueRef] = ~[];
|
||||
for ccx.module_data.each |key, &val| {
|
||||
let elt = C_struct(~[p2i(ccx, C_cstr(ccx, @/*bad*/ copy *key)),
|
||||
|
@ -27,9 +27,7 @@ use core::str;
|
||||
use core::vec;
|
||||
|
||||
pub fn terminate(cx: block, _: &str) {
|
||||
unsafe {
|
||||
cx.terminated = true;
|
||||
}
|
||||
cx.terminated = true;
|
||||
}
|
||||
|
||||
pub fn check_not_terminated(cx: block) {
|
||||
|
@ -172,17 +172,15 @@ fn cast_safely<T:Copy,U>(val: T) -> U {
|
||||
}
|
||||
|
||||
fn md_from_metadata<T>(val: debug_metadata) -> T {
|
||||
unsafe {
|
||||
match val {
|
||||
file_metadata(md) => cast_safely(md),
|
||||
compile_unit_metadata(md) => cast_safely(md),
|
||||
subprogram_metadata(md) => cast_safely(md),
|
||||
local_var_metadata(md) => cast_safely(md),
|
||||
tydesc_metadata(md) => cast_safely(md),
|
||||
block_metadata(md) => cast_safely(md),
|
||||
argument_metadata(md) => cast_safely(md),
|
||||
retval_metadata(md) => cast_safely(md)
|
||||
}
|
||||
match val {
|
||||
file_metadata(md) => cast_safely(md),
|
||||
compile_unit_metadata(md) => cast_safely(md),
|
||||
subprogram_metadata(md) => cast_safely(md),
|
||||
local_var_metadata(md) => cast_safely(md),
|
||||
tydesc_metadata(md) => cast_safely(md),
|
||||
block_metadata(md) => cast_safely(md),
|
||||
argument_metadata(md) => cast_safely(md),
|
||||
retval_metadata(md) => cast_safely(md)
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,56 +188,52 @@ fn cached_metadata<T:Copy>(cache: metadata_cache,
|
||||
mdtag: int,
|
||||
eq_fn: &fn(md: T) -> bool)
|
||||
-> Option<T> {
|
||||
unsafe {
|
||||
if cache.contains_key(&mdtag) {
|
||||
let items = cache.get(&mdtag);
|
||||
for items.each |item| {
|
||||
let md: T = md_from_metadata::<T>(*item);
|
||||
if eq_fn(md) {
|
||||
return option::Some(md);
|
||||
}
|
||||
if cache.contains_key(&mdtag) {
|
||||
let items = cache.get(&mdtag);
|
||||
for items.each |item| {
|
||||
let md: T = md_from_metadata::<T>(*item);
|
||||
if eq_fn(md) {
|
||||
return option::Some(md);
|
||||
}
|
||||
}
|
||||
return option::None;
|
||||
}
|
||||
return option::None;
|
||||
}
|
||||
|
||||
fn create_compile_unit(cx: @CrateContext) -> @Metadata<CompileUnitMetadata> {
|
||||
unsafe {
|
||||
let cache = get_cache(cx);
|
||||
let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
|
||||
let tg = CompileUnitTag;
|
||||
match cached_metadata::<@Metadata<CompileUnitMetadata>>(cache, tg,
|
||||
|md| md.data.name == crate_name) {
|
||||
option::Some(md) => return md,
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
let (_, work_dir) = get_file_path_and_dir(
|
||||
cx.sess.working_dir.to_str(), crate_name);
|
||||
let unit_metadata = ~[lltag(tg),
|
||||
llunused(),
|
||||
lli32(DW_LANG_RUST),
|
||||
llstr(crate_name),
|
||||
llstr(work_dir),
|
||||
llstr(env!("CFG_VERSION")),
|
||||
lli1(true), // deprecated: main compile unit
|
||||
lli1(cx.sess.opts.optimize != session::No),
|
||||
llstr(~""), // flags (???)
|
||||
lli32(0) // runtime version (???)
|
||||
];
|
||||
let unit_node = llmdnode(unit_metadata);
|
||||
add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
|
||||
let mdval = @Metadata {
|
||||
node: unit_node,
|
||||
data: CompileUnitMetadata {
|
||||
name: crate_name
|
||||
}
|
||||
};
|
||||
update_cache(cache, tg, compile_unit_metadata(mdval));
|
||||
|
||||
return mdval;
|
||||
let cache = get_cache(cx);
|
||||
let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
|
||||
let tg = CompileUnitTag;
|
||||
match cached_metadata::<@Metadata<CompileUnitMetadata>>(cache, tg,
|
||||
|md| md.data.name == crate_name) {
|
||||
option::Some(md) => return md,
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
let (_, work_dir) = get_file_path_and_dir(
|
||||
cx.sess.working_dir.to_str(), crate_name);
|
||||
let unit_metadata = ~[lltag(tg),
|
||||
llunused(),
|
||||
lli32(DW_LANG_RUST),
|
||||
llstr(crate_name),
|
||||
llstr(work_dir),
|
||||
llstr(env!("CFG_VERSION")),
|
||||
lli1(true), // deprecated: main compile unit
|
||||
lli1(cx.sess.opts.optimize != session::No),
|
||||
llstr(~""), // flags (???)
|
||||
lli32(0) // runtime version (???)
|
||||
];
|
||||
let unit_node = llmdnode(unit_metadata);
|
||||
add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
|
||||
let mdval = @Metadata {
|
||||
node: unit_node,
|
||||
data: CompileUnitMetadata {
|
||||
name: crate_name
|
||||
}
|
||||
};
|
||||
update_cache(cache, tg, compile_unit_metadata(mdval));
|
||||
|
||||
return mdval;
|
||||
}
|
||||
|
||||
fn get_cache(cx: @CrateContext) -> metadata_cache {
|
||||
@ -710,114 +704,110 @@ fn create_var(type_tag: int, context: ValueRef, name: &str, file: ValueRef,
|
||||
|
||||
pub fn create_local_var(bcx: block, local: @ast::local)
|
||||
-> @Metadata<LocalVarMetadata> {
|
||||
unsafe {
|
||||
let cx = bcx.ccx();
|
||||
let cache = get_cache(cx);
|
||||
let tg = AutoVariableTag;
|
||||
match cached_metadata::<@Metadata<LocalVarMetadata>>(
|
||||
cache, tg, |md| md.data.id == local.node.id) {
|
||||
option::Some(md) => return md,
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
let name = match local.node.pat.node {
|
||||
ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
|
||||
// FIXME this should be handled (#2533)
|
||||
_ => fail!(~"no single variable name for local")
|
||||
};
|
||||
let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
|
||||
let ty = node_id_type(bcx, local.node.id);
|
||||
let tymd = create_ty(cx, ty, local.node.ty.span);
|
||||
let filemd = create_file(cx, /*bad*/copy loc.file.name);
|
||||
let context = match bcx.parent {
|
||||
None => create_function(bcx.fcx).node,
|
||||
Some(_) => create_block(bcx).node
|
||||
};
|
||||
let mdnode = create_var(tg, context, *cx.sess.str_of(name),
|
||||
filemd.node, loc.line as int, tymd.node);
|
||||
let mdval = @Metadata {
|
||||
node: mdnode,
|
||||
data: LocalVarMetadata {
|
||||
id: local.node.id
|
||||
}
|
||||
};
|
||||
update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
|
||||
|
||||
let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
|
||||
option::Some(&local_mem(v)) => v,
|
||||
option::Some(_) => {
|
||||
bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
|
||||
something weird");
|
||||
}
|
||||
option::None => {
|
||||
match *bcx.fcx.lllocals.get(&local.node.pat.id) {
|
||||
local_imm(v) => v,
|
||||
_ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
|
||||
something weird")
|
||||
}
|
||||
}
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return mdval;
|
||||
let cx = bcx.ccx();
|
||||
let cache = get_cache(cx);
|
||||
let tg = AutoVariableTag;
|
||||
match cached_metadata::<@Metadata<LocalVarMetadata>>(
|
||||
cache, tg, |md| md.data.id == local.node.id) {
|
||||
option::Some(md) => return md,
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
let name = match local.node.pat.node {
|
||||
ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
|
||||
// FIXME this should be handled (#2533)
|
||||
_ => fail!(~"no single variable name for local")
|
||||
};
|
||||
let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
|
||||
let ty = node_id_type(bcx, local.node.id);
|
||||
let tymd = create_ty(cx, ty, local.node.ty.span);
|
||||
let filemd = create_file(cx, /*bad*/copy loc.file.name);
|
||||
let context = match bcx.parent {
|
||||
None => create_function(bcx.fcx).node,
|
||||
Some(_) => create_block(bcx).node
|
||||
};
|
||||
let mdnode = create_var(tg, context, *cx.sess.str_of(name),
|
||||
filemd.node, loc.line as int, tymd.node);
|
||||
let mdval = @Metadata {
|
||||
node: mdnode,
|
||||
data: LocalVarMetadata {
|
||||
id: local.node.id
|
||||
}
|
||||
};
|
||||
update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
|
||||
|
||||
let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
|
||||
option::Some(&local_mem(v)) => v,
|
||||
option::Some(_) => {
|
||||
bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
|
||||
something weird");
|
||||
}
|
||||
option::None => {
|
||||
match *bcx.fcx.lllocals.get(&local.node.pat.id) {
|
||||
local_imm(v) => v,
|
||||
_ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
|
||||
something weird")
|
||||
}
|
||||
}
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return mdval;
|
||||
}
|
||||
|
||||
pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
|
||||
-> Option<@Metadata<ArgumentMetadata>> {
|
||||
unsafe {
|
||||
let fcx = bcx.fcx, cx = *fcx.ccx;
|
||||
let cache = get_cache(cx);
|
||||
let tg = ArgVariableTag;
|
||||
match cached_metadata::<@Metadata<ArgumentMetadata>>(
|
||||
cache, ArgVariableTag, |md| md.data.id == arg.id) {
|
||||
option::Some(md) => return Some(md),
|
||||
option::None => ()
|
||||
}
|
||||
let fcx = bcx.fcx, cx = *fcx.ccx;
|
||||
let cache = get_cache(cx);
|
||||
let tg = ArgVariableTag;
|
||||
match cached_metadata::<@Metadata<ArgumentMetadata>>(
|
||||
cache, ArgVariableTag, |md| md.data.id == arg.id) {
|
||||
option::Some(md) => return Some(md),
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
|
||||
if loc.file.name == ~"<intrinsic>" {
|
||||
let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
|
||||
if loc.file.name == ~"<intrinsic>" {
|
||||
return None;
|
||||
}
|
||||
let ty = node_id_type(bcx, arg.id);
|
||||
let tymd = create_ty(cx, ty, arg.ty.span);
|
||||
let filemd = create_file(cx, /*bad*/copy loc.file.name);
|
||||
let context = create_function(bcx.fcx);
|
||||
|
||||
match arg.pat.node {
|
||||
ast::pat_ident(_, path, _) => {
|
||||
// XXX: This is wrong; it should work for multiple bindings.
|
||||
let mdnode = create_var(
|
||||
tg,
|
||||
context.node,
|
||||
*cx.sess.str_of(*path.idents.last()),
|
||||
filemd.node,
|
||||
loc.line as int,
|
||||
tymd.node
|
||||
);
|
||||
|
||||
let mdval = @Metadata {
|
||||
node: mdnode,
|
||||
data: ArgumentMetadata {
|
||||
id: arg.id
|
||||
}
|
||||
};
|
||||
update_cache(cache, tg, argument_metadata(mdval));
|
||||
|
||||
let llptr = match *fcx.llargs.get(&arg.id) {
|
||||
local_mem(v) | local_imm(v) => v,
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx,
|
||||
*cx.intrinsics.get(&~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return Some(mdval);
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
let ty = node_id_type(bcx, arg.id);
|
||||
let tymd = create_ty(cx, ty, arg.ty.span);
|
||||
let filemd = create_file(cx, /*bad*/copy loc.file.name);
|
||||
let context = create_function(bcx.fcx);
|
||||
|
||||
match arg.pat.node {
|
||||
ast::pat_ident(_, path, _) => {
|
||||
// XXX: This is wrong; it should work for multiple bindings.
|
||||
let mdnode = create_var(
|
||||
tg,
|
||||
context.node,
|
||||
*cx.sess.str_of(*path.idents.last()),
|
||||
filemd.node,
|
||||
loc.line as int,
|
||||
tymd.node
|
||||
);
|
||||
|
||||
let mdval = @Metadata {
|
||||
node: mdnode,
|
||||
data: ArgumentMetadata {
|
||||
id: arg.id
|
||||
}
|
||||
};
|
||||
update_cache(cache, tg, argument_metadata(mdval));
|
||||
|
||||
let llptr = match *fcx.llargs.get(&arg.id) {
|
||||
local_mem(v) | local_imm(v) => v,
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx,
|
||||
*cx.intrinsics.get(&~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return Some(mdval);
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,11 @@ struct ctxt_ {
|
||||
destructors: @mut HashSet<ast::def_id>,
|
||||
|
||||
// Maps a trait onto a mapping from self-ty to impl
|
||||
trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>
|
||||
trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,
|
||||
|
||||
// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
|
||||
// present in this set can be warned about.
|
||||
used_unsafe: @mut HashSet<ast::node_id>,
|
||||
}
|
||||
|
||||
enum tbox_flag {
|
||||
@ -885,7 +889,8 @@ pub fn mk_ctxt(s: session::Session,
|
||||
supertraits: @mut HashMap::new(),
|
||||
destructor_for_type: @mut HashMap::new(),
|
||||
destructors: @mut HashSet::new(),
|
||||
trait_impls: @mut HashMap::new()
|
||||
trait_impls: @mut HashMap::new(),
|
||||
used_unsafe: @mut HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -4309,16 +4314,16 @@ pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint {
|
||||
}
|
||||
|
||||
// Determine what purity to check a nested function under
|
||||
pub fn determine_inherited_purity(parent_purity: ast::purity,
|
||||
child_purity: ast::purity,
|
||||
child_sigil: ast::Sigil)
|
||||
-> ast::purity {
|
||||
pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
|
||||
child: (ast::purity, ast::node_id),
|
||||
child_sigil: ast::Sigil)
|
||||
-> (ast::purity, ast::node_id) {
|
||||
// If the closure is a stack closure and hasn't had some non-standard
|
||||
// purity inferred for it, then check it under its parent's purity.
|
||||
// Otherwise, use its own
|
||||
match child_sigil {
|
||||
ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity,
|
||||
_ => child_purity
|
||||
ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
|
||||
_ => child
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,11 @@ pub enum FnKind {
|
||||
Vanilla
|
||||
}
|
||||
|
||||
struct PurityState {
|
||||
purity: ast::purity,
|
||||
from: ast::node_id,
|
||||
}
|
||||
|
||||
pub struct FnCtxt {
|
||||
// var_bindings, locals and next_var_id are shared
|
||||
// with any nested functions that capture the environment
|
||||
@ -187,7 +192,7 @@ pub struct FnCtxt {
|
||||
ret_ty: ty::t,
|
||||
// Used by loop bodies that return from the outer function
|
||||
indirect_ret_ty: Option<ty::t>,
|
||||
purity: ast::purity,
|
||||
ps: PurityState,
|
||||
|
||||
// Sometimes we generate region pointers where the precise region
|
||||
// to use is not known. For example, an expression like `&x.f`
|
||||
@ -238,7 +243,7 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
|
||||
@mut FnCtxt {
|
||||
ret_ty: rty,
|
||||
indirect_ret_ty: None,
|
||||
purity: ast::pure_fn,
|
||||
ps: PurityState { purity: ast::pure_fn, from: 0 },
|
||||
region_lb: region_bnd,
|
||||
in_scope_regions: @Nil,
|
||||
fn_kind: Vanilla,
|
||||
@ -265,7 +270,7 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
|
||||
ty::ty_bare_fn(ref fn_ty) => {
|
||||
let fcx =
|
||||
check_fn(ccx, self_info, fn_ty.purity,
|
||||
&fn_ty.sig, decl, body, Vanilla,
|
||||
&fn_ty.sig, decl, id, body, Vanilla,
|
||||
@Nil, blank_inherited(ccx));;
|
||||
|
||||
vtable::resolve_in_block(fcx, body);
|
||||
@ -282,6 +287,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
purity: ast::purity,
|
||||
fn_sig: &ty::FnSig,
|
||||
decl: &ast::fn_decl,
|
||||
id: ast::node_id,
|
||||
body: &ast::blk,
|
||||
fn_kind: FnKind,
|
||||
inherited_isr: isr_alist,
|
||||
@ -342,7 +348,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
@mut FnCtxt {
|
||||
ret_ty: ret_ty,
|
||||
indirect_ret_ty: indirect_ret_ty,
|
||||
purity: purity,
|
||||
ps: PurityState { purity: purity, from: id },
|
||||
region_lb: body.node.id,
|
||||
in_scope_regions: isr,
|
||||
fn_kind: fn_kind,
|
||||
@ -867,8 +873,12 @@ pub impl FnCtxt {
|
||||
}
|
||||
|
||||
fn require_unsafe(&self, sp: span, op: ~str) {
|
||||
match self.purity {
|
||||
ast::unsafe_fn => {/*ok*/}
|
||||
match self.ps.purity {
|
||||
ast::unsafe_fn => {
|
||||
// ok, but flag that we used the source of unsafeness
|
||||
debug!("flagging %? as a used unsafe source", self.ps.from);
|
||||
self.tcx().used_unsafe.insert(self.ps.from);
|
||||
}
|
||||
_ => {
|
||||
self.ccx.tcx.sess.span_err(
|
||||
sp,
|
||||
@ -1679,12 +1689,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
|
||||
fcx.write_ty(expr.id, fty);
|
||||
|
||||
let inherited_purity =
|
||||
ty::determine_inherited_purity(copy fcx.purity, purity,
|
||||
let (inherited_purity, id) =
|
||||
ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.from),
|
||||
(purity, expr.id),
|
||||
sigil);
|
||||
|
||||
check_fn(fcx.ccx, None, inherited_purity, &fty_sig,
|
||||
decl, body, fn_kind, fcx.in_scope_regions, fcx.inh);
|
||||
decl, id, body, fn_kind, fcx.in_scope_regions, fcx.inh);
|
||||
}
|
||||
|
||||
|
||||
@ -2923,8 +2934,11 @@ pub fn check_block_with_expected(fcx0: @mut FnCtxt,
|
||||
blk: &ast::blk,
|
||||
expected: Option<ty::t>) {
|
||||
let fcx = match blk.node.rules {
|
||||
ast::unsafe_blk => @mut FnCtxt {purity: ast::unsafe_fn,.. copy *fcx0},
|
||||
ast::default_blk => fcx0
|
||||
ast::unsafe_blk => @mut FnCtxt {
|
||||
ps: PurityState { purity: ast::unsafe_fn, from: blk.node.id },
|
||||
.. copy *fcx0
|
||||
},
|
||||
ast::default_blk => fcx0
|
||||
};
|
||||
do fcx.with_region_lb(blk.node.id) {
|
||||
let mut warned = false;
|
||||
|
@ -57,11 +57,9 @@ struct DtorRes {
|
||||
#[unsafe_destructor]
|
||||
impl Drop for DtorRes {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
match self.dtor {
|
||||
option::None => (),
|
||||
option::Some(f) => f()
|
||||
}
|
||||
match self.dtor {
|
||||
option::None => (),
|
||||
option::Some(f) => f()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +82,7 @@ fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
|
||||
* * base - A foreign pointer to a buffer
|
||||
* * len - The number of elements in the buffer
|
||||
*/
|
||||
pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
|
||||
pub fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
|
||||
return CVec{
|
||||
base: base,
|
||||
len: len,
|
||||
@ -103,7 +101,7 @@ pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
|
||||
* * dtor - A function to run when the value is destructed, useful
|
||||
* for freeing the buffer, etc.
|
||||
*/
|
||||
pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
|
||||
pub fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
|
||||
-> CVec<T> {
|
||||
return CVec{
|
||||
base: base,
|
||||
@ -144,7 +142,7 @@ pub fn set<T:Copy>(t: CVec<T>, ofs: uint, v: T) {
|
||||
pub fn len<T>(t: CVec<T>) -> uint { t.len }
|
||||
|
||||
/// Returns a pointer to the first element of the vector
|
||||
pub unsafe fn ptr<T>(t: CVec<T>) -> *mut T { t.base }
|
||||
pub fn ptr<T>(t: CVec<T>) -> *mut T { t.base }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -223,128 +223,126 @@ pub type Result = result::Result<Matches, Fail_>;
|
||||
* Use <fail_str> to get an error message.
|
||||
*/
|
||||
pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
|
||||
unsafe {
|
||||
let n_opts = opts.len();
|
||||
fn f(_x: uint) -> ~[Optval] { return ~[]; }
|
||||
let mut vals = vec::from_fn(n_opts, f);
|
||||
let mut free: ~[~str] = ~[];
|
||||
let l = args.len();
|
||||
let mut i = 0;
|
||||
while i < l {
|
||||
let cur = args[i];
|
||||
let curlen = cur.len();
|
||||
if !is_arg(cur) {
|
||||
free.push(cur);
|
||||
} else if cur == ~"--" {
|
||||
let mut j = i + 1;
|
||||
while j < l { free.push(args[j]); j += 1; }
|
||||
break;
|
||||
} else {
|
||||
let mut names;
|
||||
let mut i_arg = None;
|
||||
if cur[1] == '-' as u8 {
|
||||
let tail = str::slice(cur, 2, curlen).to_owned();
|
||||
let mut tail_eq = ~[];
|
||||
for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) }
|
||||
if tail_eq.len() <= 1 {
|
||||
names = ~[Long(tail)];
|
||||
} else {
|
||||
names =
|
||||
~[Long(tail_eq[0])];
|
||||
i_arg = Some(tail_eq[1]);
|
||||
}
|
||||
let n_opts = opts.len();
|
||||
fn f(_x: uint) -> ~[Optval] { return ~[]; }
|
||||
let mut vals = vec::from_fn(n_opts, f);
|
||||
let mut free: ~[~str] = ~[];
|
||||
let l = args.len();
|
||||
let mut i = 0;
|
||||
while i < l {
|
||||
let cur = args[i];
|
||||
let curlen = cur.len();
|
||||
if !is_arg(cur) {
|
||||
free.push(cur);
|
||||
} else if cur == ~"--" {
|
||||
let mut j = i + 1;
|
||||
while j < l { free.push(args[j]); j += 1; }
|
||||
break;
|
||||
} else {
|
||||
let mut names;
|
||||
let mut i_arg = None;
|
||||
if cur[1] == '-' as u8 {
|
||||
let tail = str::slice(cur, 2, curlen).to_owned();
|
||||
let mut tail_eq = ~[];
|
||||
for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) }
|
||||
if tail_eq.len() <= 1 {
|
||||
names = ~[Long(tail)];
|
||||
} else {
|
||||
let mut j = 1;
|
||||
let mut last_valid_opt_id = None;
|
||||
names = ~[];
|
||||
while j < curlen {
|
||||
let range = str::char_range_at(cur, j);
|
||||
let opt = Short(range.ch);
|
||||
|
||||
/* In a series of potential options (eg. -aheJ), if we
|
||||
see one which takes an argument, we assume all
|
||||
subsequent characters make up the argument. This
|
||||
allows options such as -L/usr/local/lib/foo to be
|
||||
interpreted correctly
|
||||
*/
|
||||
|
||||
match find_opt(opts, opt) {
|
||||
Some(id) => last_valid_opt_id = Some(id),
|
||||
None => {
|
||||
let arg_follows =
|
||||
last_valid_opt_id.is_some() &&
|
||||
match opts[last_valid_opt_id.get()]
|
||||
.hasarg {
|
||||
|
||||
Yes | Maybe => true,
|
||||
No => false
|
||||
};
|
||||
if arg_follows && j < curlen {
|
||||
i_arg = Some(cur.slice(j, curlen).to_owned());
|
||||
break;
|
||||
} else {
|
||||
last_valid_opt_id = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
names.push(opt);
|
||||
j = range.next;
|
||||
}
|
||||
names =
|
||||
~[Long(tail_eq[0])];
|
||||
i_arg = Some(tail_eq[1]);
|
||||
}
|
||||
let mut name_pos = 0;
|
||||
for names.each() |nm| {
|
||||
name_pos += 1;
|
||||
let optid = match find_opt(opts, *nm) {
|
||||
Some(id) => id,
|
||||
None => return Err(UnrecognizedOption(name_str(nm)))
|
||||
};
|
||||
match opts[optid].hasarg {
|
||||
No => {
|
||||
if !i_arg.is_none() {
|
||||
return Err(UnexpectedArgument(name_str(nm)));
|
||||
} else {
|
||||
let mut j = 1;
|
||||
let mut last_valid_opt_id = None;
|
||||
names = ~[];
|
||||
while j < curlen {
|
||||
let range = str::char_range_at(cur, j);
|
||||
let opt = Short(range.ch);
|
||||
|
||||
/* In a series of potential options (eg. -aheJ), if we
|
||||
see one which takes an argument, we assume all
|
||||
subsequent characters make up the argument. This
|
||||
allows options such as -L/usr/local/lib/foo to be
|
||||
interpreted correctly
|
||||
*/
|
||||
|
||||
match find_opt(opts, opt) {
|
||||
Some(id) => last_valid_opt_id = Some(id),
|
||||
None => {
|
||||
let arg_follows =
|
||||
last_valid_opt_id.is_some() &&
|
||||
match opts[last_valid_opt_id.get()]
|
||||
.hasarg {
|
||||
|
||||
Yes | Maybe => true,
|
||||
No => false
|
||||
};
|
||||
if arg_follows && j < curlen {
|
||||
i_arg = Some(cur.slice(j, curlen).to_owned());
|
||||
break;
|
||||
} else {
|
||||
last_valid_opt_id = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
names.push(opt);
|
||||
j = range.next;
|
||||
}
|
||||
}
|
||||
let mut name_pos = 0;
|
||||
for names.each() |nm| {
|
||||
name_pos += 1;
|
||||
let optid = match find_opt(opts, *nm) {
|
||||
Some(id) => id,
|
||||
None => return Err(UnrecognizedOption(name_str(nm)))
|
||||
};
|
||||
match opts[optid].hasarg {
|
||||
No => {
|
||||
if !i_arg.is_none() {
|
||||
return Err(UnexpectedArgument(name_str(nm)));
|
||||
}
|
||||
vals[optid].push(Given);
|
||||
}
|
||||
Maybe => {
|
||||
if !i_arg.is_none() {
|
||||
vals[optid].push(Val(i_arg.get()));
|
||||
} else if name_pos < names.len() ||
|
||||
i + 1 == l || is_arg(args[i + 1]) {
|
||||
vals[optid].push(Given);
|
||||
}
|
||||
Maybe => {
|
||||
if !i_arg.is_none() {
|
||||
vals[optid].push(Val(i_arg.get()));
|
||||
} else if name_pos < names.len() ||
|
||||
i + 1 == l || is_arg(args[i + 1]) {
|
||||
vals[optid].push(Given);
|
||||
} else { i += 1; vals[optid].push(Val(args[i])); }
|
||||
}
|
||||
Yes => {
|
||||
if !i_arg.is_none() {
|
||||
vals[optid].push(Val(i_arg.get()));
|
||||
} else if i + 1 == l {
|
||||
return Err(ArgumentMissing(name_str(nm)));
|
||||
} else { i += 1; vals[optid].push(Val(args[i])); }
|
||||
}
|
||||
}
|
||||
} else { i += 1; vals[optid].push(Val(args[i])); }
|
||||
}
|
||||
Yes => {
|
||||
if !i_arg.is_none() {
|
||||
vals[optid].push(Val(i_arg.get()));
|
||||
} else if i + 1 == l {
|
||||
return Err(ArgumentMissing(name_str(nm)));
|
||||
} else { i += 1; vals[optid].push(Val(args[i])); }
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
i = 0u;
|
||||
while i < n_opts {
|
||||
let n = vals[i].len();
|
||||
let occ = opts[i].occur;
|
||||
if occ == Req {
|
||||
if n == 0 {
|
||||
return Err(OptionMissing(name_str(&(opts[i].name))));
|
||||
}
|
||||
}
|
||||
if occ != Multi {
|
||||
if n > 1 {
|
||||
return Err(OptionDuplicated(name_str(&(opts[i].name))));
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return Ok(Matches {opts: vec::from_slice(opts),
|
||||
vals: vals,
|
||||
free: free});
|
||||
i += 1;
|
||||
}
|
||||
i = 0u;
|
||||
while i < n_opts {
|
||||
let n = vals[i].len();
|
||||
let occ = opts[i].occur;
|
||||
if occ == Req {
|
||||
if n == 0 {
|
||||
return Err(OptionMissing(name_str(&(opts[i].name))));
|
||||
}
|
||||
}
|
||||
if occ != Multi {
|
||||
if n > 1 {
|
||||
return Err(OptionDuplicated(name_str(&(opts[i].name))));
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return Ok(Matches {opts: vec::from_slice(opts),
|
||||
vals: vals,
|
||||
free: free});
|
||||
}
|
||||
|
||||
fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] {
|
||||
|
@ -116,35 +116,33 @@ pub fn get_addr(node: &str, iotask: &iotask)
|
||||
let mut output_ch = Some(SharedChan(output_ch));
|
||||
do str::as_buf(node) |node_ptr, len| {
|
||||
let output_ch = output_ch.swap_unwrap();
|
||||
unsafe {
|
||||
debug!("slice len %?", len);
|
||||
let handle = create_uv_getaddrinfo_t();
|
||||
let handle_ptr = ptr::addr_of(&handle);
|
||||
let handle_data = GetAddrData {
|
||||
output_ch: output_ch.clone()
|
||||
};
|
||||
let handle_data_ptr = ptr::addr_of(&handle_data);
|
||||
do interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
let result = uv_getaddrinfo(
|
||||
loop_ptr,
|
||||
handle_ptr,
|
||||
get_addr_cb,
|
||||
node_ptr,
|
||||
ptr::null(),
|
||||
ptr::null());
|
||||
match result {
|
||||
0i32 => {
|
||||
set_data_for_req(handle_ptr, handle_data_ptr);
|
||||
}
|
||||
_ => {
|
||||
output_ch.send(result::Err(GetAddrUnknownError));
|
||||
}
|
||||
debug!("slice len %?", len);
|
||||
let handle = create_uv_getaddrinfo_t();
|
||||
let handle_ptr = ptr::addr_of(&handle);
|
||||
let handle_data = GetAddrData {
|
||||
output_ch: output_ch.clone()
|
||||
};
|
||||
let handle_data_ptr = ptr::addr_of(&handle_data);
|
||||
do interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
let result = uv_getaddrinfo(
|
||||
loop_ptr,
|
||||
handle_ptr,
|
||||
get_addr_cb,
|
||||
node_ptr,
|
||||
ptr::null(),
|
||||
ptr::null());
|
||||
match result {
|
||||
0i32 => {
|
||||
set_data_for_req(handle_ptr, handle_data_ptr);
|
||||
}
|
||||
_ => {
|
||||
output_ch.send(result::Err(GetAddrUnknownError));
|
||||
}
|
||||
}
|
||||
};
|
||||
output_po.recv()
|
||||
}
|
||||
}
|
||||
};
|
||||
output_po.recv()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,7 @@ pub struct TcpSocket {
|
||||
#[unsafe_destructor]
|
||||
impl Drop for TcpSocket {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
tear_down_socket_data(self.socket_data)
|
||||
}
|
||||
tear_down_socket_data(self.socket_data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,11 +300,10 @@ pub fn connect(input_ip: ip::IpAddr, port: uint,
|
||||
* `TcpErrData` value as the `Err` variant
|
||||
*/
|
||||
pub fn write(sock: &TcpSocket, raw_write_data: ~[u8])
|
||||
-> result::Result<(), TcpErrData> {
|
||||
unsafe {
|
||||
let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
|
||||
write_common_impl(socket_data_ptr, raw_write_data)
|
||||
}
|
||||
-> result::Result<(), TcpErrData>
|
||||
{
|
||||
let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
|
||||
write_common_impl(socket_data_ptr, raw_write_data)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -341,13 +338,12 @@ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8])
|
||||
* value as the `Err` variant
|
||||
*/
|
||||
pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8])
|
||||
-> future::Future<result::Result<(), TcpErrData>> {
|
||||
unsafe {
|
||||
let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
|
||||
do future_spawn {
|
||||
let data_copy = copy(raw_write_data);
|
||||
write_common_impl(socket_data_ptr, data_copy)
|
||||
}
|
||||
-> future::Future<result::Result<(), TcpErrData>>
|
||||
{
|
||||
let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
|
||||
do future_spawn {
|
||||
let data_copy = copy(raw_write_data);
|
||||
write_common_impl(socket_data_ptr, data_copy)
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,10 +365,8 @@ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8])
|
||||
pub fn read_start(sock: &TcpSocket)
|
||||
-> result::Result<@Port<
|
||||
result::Result<~[u8], TcpErrData>>, TcpErrData> {
|
||||
unsafe {
|
||||
let socket_data = ptr::addr_of(&(*(sock.socket_data)));
|
||||
read_start_common_impl(socket_data)
|
||||
}
|
||||
let socket_data = ptr::addr_of(&(*(sock.socket_data)));
|
||||
read_start_common_impl(socket_data)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,12 +376,9 @@ pub fn read_start(sock: &TcpSocket)
|
||||
*
|
||||
* * `sock` - a `net::tcp::TcpSocket` that you wish to stop reading on
|
||||
*/
|
||||
pub fn read_stop(sock: &TcpSocket) ->
|
||||
result::Result<(), TcpErrData> {
|
||||
unsafe {
|
||||
let socket_data = ptr::addr_of(&(*sock.socket_data));
|
||||
read_stop_common_impl(socket_data)
|
||||
}
|
||||
pub fn read_stop(sock: &TcpSocket) -> result::Result<(), TcpErrData> {
|
||||
let socket_data = ptr::addr_of(&(*sock.socket_data));
|
||||
read_stop_common_impl(socket_data)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -654,150 +645,148 @@ fn listen_common(host_ip: ip::IpAddr,
|
||||
on_establish_cb: ~fn(SharedChan<Option<TcpErrData>>),
|
||||
on_connect_cb: ~fn(*uv::ll::uv_tcp_t))
|
||||
-> result::Result<(), TcpListenErrData> {
|
||||
unsafe {
|
||||
let (stream_closed_po, stream_closed_ch) = stream::<()>();
|
||||
let stream_closed_ch = SharedChan(stream_closed_ch);
|
||||
let (kill_po, kill_ch) = stream::<Option<TcpErrData>>();
|
||||
let kill_ch = SharedChan(kill_ch);
|
||||
let server_stream = uv::ll::tcp_t();
|
||||
let server_stream_ptr = ptr::addr_of(&server_stream);
|
||||
let server_data: TcpListenFcData = TcpListenFcData {
|
||||
server_stream_ptr: server_stream_ptr,
|
||||
stream_closed_ch: stream_closed_ch,
|
||||
kill_ch: kill_ch.clone(),
|
||||
on_connect_cb: on_connect_cb,
|
||||
iotask: iotask.clone(),
|
||||
ipv6: match &host_ip {
|
||||
&ip::Ipv4(_) => { false }
|
||||
&ip::Ipv6(_) => { true }
|
||||
},
|
||||
mut active: true
|
||||
};
|
||||
let server_data_ptr = ptr::addr_of(&server_data);
|
||||
let (stream_closed_po, stream_closed_ch) = stream::<()>();
|
||||
let stream_closed_ch = SharedChan(stream_closed_ch);
|
||||
let (kill_po, kill_ch) = stream::<Option<TcpErrData>>();
|
||||
let kill_ch = SharedChan(kill_ch);
|
||||
let server_stream = uv::ll::tcp_t();
|
||||
let server_stream_ptr = ptr::addr_of(&server_stream);
|
||||
let server_data: TcpListenFcData = TcpListenFcData {
|
||||
server_stream_ptr: server_stream_ptr,
|
||||
stream_closed_ch: stream_closed_ch,
|
||||
kill_ch: kill_ch.clone(),
|
||||
on_connect_cb: on_connect_cb,
|
||||
iotask: iotask.clone(),
|
||||
ipv6: match &host_ip {
|
||||
&ip::Ipv4(_) => { false }
|
||||
&ip::Ipv6(_) => { true }
|
||||
},
|
||||
mut active: true
|
||||
};
|
||||
let server_data_ptr = ptr::addr_of(&server_data);
|
||||
|
||||
let (setup_po, setup_ch) = stream();
|
||||
let (setup_po, setup_ch) = stream();
|
||||
|
||||
// this is to address a compiler warning about
|
||||
// an implicit copy.. it seems that double nested
|
||||
// will defeat a move sigil, as is done to the host_ip
|
||||
// arg above.. this same pattern works w/o complaint in
|
||||
// tcp::connect (because the iotask::interact cb isn't
|
||||
// nested within a core::comm::listen block)
|
||||
let loc_ip = copy(host_ip);
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
match uv::ll::tcp_init(loop_ptr, server_stream_ptr) {
|
||||
0i32 => {
|
||||
uv::ll::set_data_for_uv_handle(
|
||||
server_stream_ptr,
|
||||
server_data_ptr);
|
||||
let addr_str = ip::format_addr(&loc_ip);
|
||||
let bind_result = match loc_ip {
|
||||
ip::Ipv4(ref addr) => {
|
||||
debug!("addr: %?", addr);
|
||||
let in_addr = uv::ll::ip4_addr(
|
||||
addr_str,
|
||||
port as int);
|
||||
uv::ll::tcp_bind(server_stream_ptr,
|
||||
ptr::addr_of(&in_addr))
|
||||
}
|
||||
ip::Ipv6(ref addr) => {
|
||||
debug!("addr: %?", addr);
|
||||
let in_addr = uv::ll::ip6_addr(
|
||||
addr_str,
|
||||
port as int);
|
||||
uv::ll::tcp_bind6(server_stream_ptr,
|
||||
ptr::addr_of(&in_addr))
|
||||
}
|
||||
};
|
||||
match bind_result {
|
||||
0i32 => {
|
||||
match uv::ll::listen(
|
||||
server_stream_ptr,
|
||||
backlog as libc::c_int,
|
||||
tcp_lfc_on_connection_cb) {
|
||||
0i32 => setup_ch.send(None),
|
||||
_ => {
|
||||
debug!(
|
||||
"failure to uv_tcp_init");
|
||||
let err_data =
|
||||
uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
// this is to address a compiler warning about
|
||||
// an implicit copy.. it seems that double nested
|
||||
// will defeat a move sigil, as is done to the host_ip
|
||||
// arg above.. this same pattern works w/o complaint in
|
||||
// tcp::connect (because the iotask::interact cb isn't
|
||||
// nested within a core::comm::listen block)
|
||||
let loc_ip = copy(host_ip);
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
match uv::ll::tcp_init(loop_ptr, server_stream_ptr) {
|
||||
0i32 => {
|
||||
uv::ll::set_data_for_uv_handle(
|
||||
server_stream_ptr,
|
||||
server_data_ptr);
|
||||
let addr_str = ip::format_addr(&loc_ip);
|
||||
let bind_result = match loc_ip {
|
||||
ip::Ipv4(ref addr) => {
|
||||
debug!("addr: %?", addr);
|
||||
let in_addr = uv::ll::ip4_addr(
|
||||
addr_str,
|
||||
port as int);
|
||||
uv::ll::tcp_bind(server_stream_ptr,
|
||||
ptr::addr_of(&in_addr))
|
||||
}
|
||||
ip::Ipv6(ref addr) => {
|
||||
debug!("addr: %?", addr);
|
||||
let in_addr = uv::ll::ip6_addr(
|
||||
addr_str,
|
||||
port as int);
|
||||
uv::ll::tcp_bind6(server_stream_ptr,
|
||||
ptr::addr_of(&in_addr))
|
||||
}
|
||||
};
|
||||
match bind_result {
|
||||
0i32 => {
|
||||
match uv::ll::listen(
|
||||
server_stream_ptr,
|
||||
backlog as libc::c_int,
|
||||
tcp_lfc_on_connection_cb) {
|
||||
0i32 => setup_ch.send(None),
|
||||
_ => {
|
||||
debug!(
|
||||
"failure to uv_tcp_init");
|
||||
let err_data =
|
||||
uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
debug!("failure to uv_tcp_bind");
|
||||
let err_data = uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
debug!("failure to uv_tcp_bind");
|
||||
let err_data = uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
debug!("failure to uv_tcp_bind");
|
||||
let err_data = uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
debug!("failure to uv_tcp_bind");
|
||||
let err_data = uv::ll::get_last_err_data(
|
||||
loop_ptr);
|
||||
setup_ch.send(Some(err_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let setup_result = setup_po.recv();
|
||||
let setup_result = setup_po.recv();
|
||||
|
||||
match setup_result {
|
||||
Some(ref err_data) => {
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
debug!(
|
||||
"tcp::listen post-kill recv hl interact %?",
|
||||
loop_ptr);
|
||||
(*server_data_ptr).active = false;
|
||||
uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
|
||||
}
|
||||
};
|
||||
stream_closed_po.recv();
|
||||
match err_data.err_name {
|
||||
~"EACCES" => {
|
||||
debug!("Got EACCES error");
|
||||
result::Err(AccessDenied)
|
||||
}
|
||||
~"EADDRINUSE" => {
|
||||
debug!("Got EADDRINUSE error");
|
||||
result::Err(AddressInUse)
|
||||
}
|
||||
_ => {
|
||||
debug!("Got '%s' '%s' libuv error",
|
||||
err_data.err_name, err_data.err_msg);
|
||||
result::Err(
|
||||
GenericListenErr(err_data.err_name,
|
||||
err_data.err_msg))
|
||||
}
|
||||
match setup_result {
|
||||
Some(ref err_data) => {
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
debug!(
|
||||
"tcp::listen post-kill recv hl interact %?",
|
||||
loop_ptr);
|
||||
(*server_data_ptr).active = false;
|
||||
uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
|
||||
}
|
||||
};
|
||||
stream_closed_po.recv();
|
||||
match err_data.err_name {
|
||||
~"EACCES" => {
|
||||
debug!("Got EACCES error");
|
||||
result::Err(AccessDenied)
|
||||
}
|
||||
~"EADDRINUSE" => {
|
||||
debug!("Got EADDRINUSE error");
|
||||
result::Err(AddressInUse)
|
||||
}
|
||||
_ => {
|
||||
debug!("Got '%s' '%s' libuv error",
|
||||
err_data.err_name, err_data.err_msg);
|
||||
result::Err(
|
||||
GenericListenErr(err_data.err_name,
|
||||
err_data.err_msg))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
on_establish_cb(kill_ch.clone());
|
||||
let kill_result = kill_po.recv();
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
debug!(
|
||||
"tcp::listen post-kill recv hl interact %?",
|
||||
loop_ptr);
|
||||
(*server_data_ptr).active = false;
|
||||
uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
|
||||
}
|
||||
};
|
||||
stream_closed_po.recv();
|
||||
match kill_result {
|
||||
// some failure post bind/listen
|
||||
Some(ref err_data) => result::Err(GenericListenErr(
|
||||
err_data.err_name,
|
||||
err_data.err_msg)),
|
||||
// clean exit
|
||||
None => result::Ok(())
|
||||
}
|
||||
None => {
|
||||
on_establish_cb(kill_ch.clone());
|
||||
let kill_result = kill_po.recv();
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
debug!(
|
||||
"tcp::listen post-kill recv hl interact %?",
|
||||
loop_ptr);
|
||||
(*server_data_ptr).active = false;
|
||||
uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
|
||||
}
|
||||
};
|
||||
stream_closed_po.recv();
|
||||
match kill_result {
|
||||
// some failure post bind/listen
|
||||
Some(ref err_data) => result::Err(GenericListenErr(
|
||||
err_data.err_name,
|
||||
err_data.err_msg)),
|
||||
// clean exit
|
||||
None => result::Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1382,9 +1371,7 @@ extern fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) {
|
||||
}
|
||||
|
||||
extern fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) {
|
||||
unsafe {
|
||||
debug!("closed client tcp handle %?", handle);
|
||||
}
|
||||
debug!("closed client tcp handle %?", handle);
|
||||
}
|
||||
|
||||
extern fn tcp_connect_on_connect_cb(connect_req_ptr: *uv::ll::uv_connect_t,
|
||||
|
@ -118,8 +118,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
|
||||
* This function is compliant with RFC 3986.
|
||||
*/
|
||||
pub fn encode(s: &str) -> ~str {
|
||||
// FIXME(#3722): unsafe only because encode_inner does (string) IO
|
||||
unsafe {encode_inner(s, true)}
|
||||
encode_inner(s, true)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,8 +129,7 @@ pub fn encode(s: &str) -> ~str {
|
||||
*/
|
||||
|
||||
pub fn encode_component(s: &str) -> ~str {
|
||||
// FIXME(#3722): unsafe only because encode_inner does (string) IO
|
||||
unsafe {encode_inner(s, false)}
|
||||
encode_inner(s, false)
|
||||
}
|
||||
|
||||
fn decode_inner(s: &str, full_url: bool) -> ~str {
|
||||
@ -178,16 +176,14 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
|
||||
* This will only decode escape sequences generated by encode.
|
||||
*/
|
||||
pub fn decode(s: &str) -> ~str {
|
||||
// FIXME(#3722): unsafe only because decode_inner does (string) IO
|
||||
unsafe {decode_inner(s, true)}
|
||||
decode_inner(s, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a string encoded with percent encoding.
|
||||
*/
|
||||
pub fn decode_component(s: &str) -> ~str {
|
||||
// FIXME(#3722): unsafe only because decode_inner does (string) IO
|
||||
unsafe {decode_inner(s, false)}
|
||||
decode_inner(s, false)
|
||||
}
|
||||
|
||||
fn encode_plus(s: &str) -> ~str {
|
||||
@ -301,18 +297,15 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) {
|
||||
let len = str::len(s);
|
||||
let mut index = len;
|
||||
let mut mat = 0;
|
||||
// FIXME(#3722): unsafe only because decode_inner does (string) IO
|
||||
unsafe {
|
||||
do io::with_str_reader(s) |rdr| {
|
||||
let mut ch;
|
||||
while !rdr.eof() {
|
||||
ch = rdr.read_byte() as char;
|
||||
if ch == c {
|
||||
// found a match, adjust markers
|
||||
index = rdr.tell()-1;
|
||||
mat = 1;
|
||||
break;
|
||||
}
|
||||
do io::with_str_reader(s) |rdr| {
|
||||
let mut ch;
|
||||
while !rdr.eof() {
|
||||
ch = rdr.read_byte() as char;
|
||||
if ch == c {
|
||||
// found a match, adjust markers
|
||||
index = rdr.tell()-1;
|
||||
mat = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -346,29 +339,25 @@ fn query_from_str(rawquery: &str) -> Query {
|
||||
if str::len(rawquery) != 0 {
|
||||
for str::each_split_char(rawquery, '&') |p| {
|
||||
let (k, v) = split_char_first(p, '=');
|
||||
// FIXME(#3722): unsafe only because decode_inner does (string) IO
|
||||
unsafe {query.push((decode_component(k), decode_component(v)));}
|
||||
query.push((decode_component(k), decode_component(v)));
|
||||
};
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
pub fn query_to_str(query: &Query) -> ~str {
|
||||
unsafe {
|
||||
// FIXME(#3722): unsafe only because decode_inner does (string) IO
|
||||
let mut strvec = ~[];
|
||||
for query.each |kv| {
|
||||
match kv {
|
||||
&(ref k, ref v) => {
|
||||
strvec.push(fmt!("%s=%s",
|
||||
encode_component(*k),
|
||||
encode_component(*v))
|
||||
);
|
||||
}
|
||||
let mut strvec = ~[];
|
||||
for query.each |kv| {
|
||||
match kv {
|
||||
&(ref k, ref v) => {
|
||||
strvec.push(fmt!("%s=%s",
|
||||
encode_component(*k),
|
||||
encode_component(*v))
|
||||
);
|
||||
}
|
||||
}
|
||||
return str::connect(strvec, ~"&");
|
||||
}
|
||||
return str::connect(strvec, ~"&");
|
||||
}
|
||||
|
||||
// returns the scheme and the rest of the url, or a parsing error
|
||||
|
@ -59,12 +59,10 @@ pub unsafe fn load_history(file: ~str) -> bool {
|
||||
/// Print out a prompt and then wait for input and return it
|
||||
pub unsafe fn read(prompt: ~str) -> Option<~str> {
|
||||
do str::as_c_str(prompt) |buf| {
|
||||
unsafe {
|
||||
let line = rustrt::linenoise(buf);
|
||||
let line = rustrt::linenoise(buf);
|
||||
|
||||
if line.is_null() { None }
|
||||
else { Some(str::raw::from_c_str(line)) }
|
||||
}
|
||||
if line.is_null() { None }
|
||||
else { Some(str::raw::from_c_str(line)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,22 +72,20 @@ fn complete_key(_v: @CompletionCb) {}
|
||||
|
||||
/// Bind to the main completion callback
|
||||
pub unsafe fn complete(cb: CompletionCb) {
|
||||
unsafe {
|
||||
task::local_data::local_data_set(complete_key, @(cb));
|
||||
task::local_data::local_data_set(complete_key, @(cb));
|
||||
|
||||
extern fn callback(line: *c_char, completions: *()) {
|
||||
unsafe {
|
||||
let cb = *task::local_data::local_data_get(complete_key)
|
||||
.get();
|
||||
extern fn callback(line: *c_char, completions: *()) {
|
||||
unsafe {
|
||||
let cb = *task::local_data::local_data_get(complete_key)
|
||||
.get();
|
||||
|
||||
do cb(str::raw::from_c_str(line)) |suggestion| {
|
||||
do str::as_c_str(suggestion) |buf| {
|
||||
rustrt::linenoiseAddCompletion(completions, buf);
|
||||
}
|
||||
do cb(str::raw::from_c_str(line)) |suggestion| {
|
||||
do str::as_c_str(suggestion) |buf| {
|
||||
rustrt::linenoiseAddCompletion(completions, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rustrt::linenoiseSetCompletionCallback(callback);
|
||||
}
|
||||
|
||||
rustrt::linenoiseSetCompletionCallback(callback);
|
||||
}
|
||||
|
@ -862,17 +862,15 @@ pub mod node {
|
||||
* This function executes in linear time.
|
||||
*/
|
||||
pub fn flatten(node: @Node) -> @Node {
|
||||
unsafe {
|
||||
match (*node) {
|
||||
Leaf(_) => node,
|
||||
Concat(ref x) => {
|
||||
@Leaf(Leaf {
|
||||
byte_offset: 0u,
|
||||
byte_len: x.byte_len,
|
||||
char_len: x.char_len,
|
||||
content: @serialize_node(node),
|
||||
})
|
||||
}
|
||||
match (*node) {
|
||||
Leaf(_) => node,
|
||||
Concat(ref x) => {
|
||||
@Leaf(Leaf {
|
||||
byte_offset: 0u,
|
||||
byte_len: x.byte_len,
|
||||
char_len: x.char_len,
|
||||
content: @serialize_node(node),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,17 +101,15 @@ fn new_sem_and_signal(count: int, num_condvars: uint)
|
||||
pub impl<Q:Owned> Sem<Q> {
|
||||
fn acquire(&self) {
|
||||
let mut waiter_nobe = None;
|
||||
unsafe {
|
||||
do (**self).with |state| {
|
||||
state.count -= 1;
|
||||
if state.count < 0 {
|
||||
// Create waiter nobe.
|
||||
let (WaitEnd, SignalEnd) = comm::oneshot();
|
||||
// Tell outer scope we need to block.
|
||||
waiter_nobe = Some(WaitEnd);
|
||||
// Enqueue ourself.
|
||||
state.waiters.tail.send(SignalEnd);
|
||||
}
|
||||
do (**self).with |state| {
|
||||
state.count -= 1;
|
||||
if state.count < 0 {
|
||||
// Create waiter nobe.
|
||||
let (WaitEnd, SignalEnd) = comm::oneshot();
|
||||
// Tell outer scope we need to block.
|
||||
waiter_nobe = Some(WaitEnd);
|
||||
// Enqueue ourself.
|
||||
state.waiters.tail.send(SignalEnd);
|
||||
}
|
||||
}
|
||||
// Uncomment if you wish to test for sem races. Not valgrind-friendly.
|
||||
@ -122,12 +120,10 @@ pub impl<Q:Owned> Sem<Q> {
|
||||
}
|
||||
}
|
||||
fn release(&self) {
|
||||
unsafe {
|
||||
do (**self).with |state| {
|
||||
state.count += 1;
|
||||
if state.count <= 0 {
|
||||
signal_waitqueue(&state.waiters);
|
||||
}
|
||||
do (**self).with |state| {
|
||||
state.count += 1;
|
||||
if state.count <= 0 {
|
||||
signal_waitqueue(&state.waiters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,9 +165,7 @@ struct SemReleaseGeneric<'self, Q> { sem: &'self Sem<Q> }
|
||||
#[unsafe_destructor]
|
||||
impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
self.sem.release();
|
||||
}
|
||||
self.sem.release();
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,13 +285,11 @@ pub impl<'self> Condvar<'self> {
|
||||
fn signal_on(&self, condvar_id: uint) -> bool {
|
||||
let mut out_of_bounds = None;
|
||||
let mut result = false;
|
||||
unsafe {
|
||||
do (**self.sem).with |state| {
|
||||
if condvar_id < vec::len(state.blocked) {
|
||||
result = signal_waitqueue(&state.blocked[condvar_id]);
|
||||
} else {
|
||||
out_of_bounds = Some(vec::len(state.blocked));
|
||||
}
|
||||
do (**self.sem).with |state| {
|
||||
if condvar_id < vec::len(state.blocked) {
|
||||
result = signal_waitqueue(&state.blocked[condvar_id]);
|
||||
} else {
|
||||
out_of_bounds = Some(vec::len(state.blocked));
|
||||
}
|
||||
}
|
||||
do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
|
||||
@ -312,17 +304,15 @@ pub impl<'self> Condvar<'self> {
|
||||
fn broadcast_on(&self, condvar_id: uint) -> uint {
|
||||
let mut out_of_bounds = None;
|
||||
let mut queue = None;
|
||||
unsafe {
|
||||
do (**self.sem).with |state| {
|
||||
if condvar_id < vec::len(state.blocked) {
|
||||
// To avoid :broadcast_heavy, we make a new waitqueue,
|
||||
// swap it out with the old one, and broadcast on the
|
||||
// old one outside of the little-lock.
|
||||
queue = Some(util::replace(&mut state.blocked[condvar_id],
|
||||
new_waitqueue()));
|
||||
} else {
|
||||
out_of_bounds = Some(vec::len(state.blocked));
|
||||
}
|
||||
do (**self.sem).with |state| {
|
||||
if condvar_id < vec::len(state.blocked) {
|
||||
// To avoid :broadcast_heavy, we make a new waitqueue,
|
||||
// swap it out with the old one, and broadcast on the
|
||||
// old one outside of the little-lock.
|
||||
queue = Some(util::replace(&mut state.blocked[condvar_id],
|
||||
new_waitqueue()));
|
||||
} else {
|
||||
out_of_bounds = Some(vec::len(state.blocked));
|
||||
}
|
||||
}
|
||||
do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
|
||||
|
@ -42,47 +42,45 @@ pub fn delayed_send<T:Owned>(iotask: &IoTask,
|
||||
msecs: uint,
|
||||
ch: &Chan<T>,
|
||||
val: T) {
|
||||
let (timer_done_po, timer_done_ch) = stream::<()>();
|
||||
let timer_done_ch = SharedChan(timer_done_ch);
|
||||
let timer = uv::ll::timer_t();
|
||||
let timer_ptr = ptr::addr_of(&timer);
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
let (timer_done_po, timer_done_ch) = stream::<()>();
|
||||
let timer_done_ch = SharedChan(timer_done_ch);
|
||||
let timer = uv::ll::timer_t();
|
||||
let timer_ptr = ptr::addr_of(&timer);
|
||||
do iotask::interact(iotask) |loop_ptr| {
|
||||
unsafe {
|
||||
let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
|
||||
if (init_result == 0i32) {
|
||||
let start_result = uv::ll::timer_start(
|
||||
timer_ptr, delayed_send_cb, msecs, 0u);
|
||||
if (start_result == 0i32) {
|
||||
// Note: putting the channel into a ~
|
||||
// to cast to *c_void
|
||||
let timer_done_ch_clone = ~timer_done_ch.clone();
|
||||
let timer_done_ch_ptr = transmute::<
|
||||
~SharedChan<()>, *c_void>(
|
||||
timer_done_ch_clone);
|
||||
uv::ll::set_data_for_uv_handle(
|
||||
timer_ptr,
|
||||
timer_done_ch_ptr);
|
||||
} else {
|
||||
let error_msg = uv::ll::get_last_err_info(
|
||||
loop_ptr);
|
||||
fail!(~"timer::delayed_send() start failed: " +
|
||||
error_msg);
|
||||
}
|
||||
} else {
|
||||
let error_msg = uv::ll::get_last_err_info(loop_ptr);
|
||||
fail!(~"timer::delayed_send() init failed: " +
|
||||
error_msg);
|
||||
}
|
||||
let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
|
||||
if (init_result == 0i32) {
|
||||
let start_result = uv::ll::timer_start(
|
||||
timer_ptr, delayed_send_cb, msecs, 0u);
|
||||
if (start_result == 0i32) {
|
||||
// Note: putting the channel into a ~
|
||||
// to cast to *c_void
|
||||
let timer_done_ch_clone = ~timer_done_ch.clone();
|
||||
let timer_done_ch_ptr = transmute::<
|
||||
~SharedChan<()>, *c_void>(
|
||||
timer_done_ch_clone);
|
||||
uv::ll::set_data_for_uv_handle(
|
||||
timer_ptr,
|
||||
timer_done_ch_ptr);
|
||||
} else {
|
||||
let error_msg = uv::ll::get_last_err_info(
|
||||
loop_ptr);
|
||||
fail!(~"timer::delayed_send() start failed: " +
|
||||
error_msg);
|
||||
}
|
||||
};
|
||||
// delayed_send_cb has been processed by libuv
|
||||
timer_done_po.recv();
|
||||
// notify the caller immediately
|
||||
ch.send(val);
|
||||
// uv_close for this timer has been processed
|
||||
timer_done_po.recv();
|
||||
} else {
|
||||
let error_msg = uv::ll::get_last_err_info(loop_ptr);
|
||||
fail!(~"timer::delayed_send() init failed: " +
|
||||
error_msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
// delayed_send_cb has been processed by libuv
|
||||
timer_done_po.recv();
|
||||
// notify the caller immediately
|
||||
ch.send(val);
|
||||
// uv_close for this timer has been processed
|
||||
timer_done_po.recv();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ pub fn spawn_iotask(task: task::TaskBuilder) -> IoTask {
|
||||
* module. It is not safe to send the `loop_ptr` param to this callback out
|
||||
* via ports/chans.
|
||||
*/
|
||||
pub unsafe fn interact(iotask: &IoTask, cb: ~fn(*c_void)) {
|
||||
pub fn interact(iotask: &IoTask, cb: ~fn(*c_void)) {
|
||||
send_msg(iotask, Interaction(cb));
|
||||
}
|
||||
|
||||
@ -87,9 +87,7 @@ pub unsafe fn interact(iotask: &IoTask, cb: ~fn(*c_void)) {
|
||||
* closed, causing a failure otherwise.
|
||||
*/
|
||||
pub fn exit(iotask: &IoTask) {
|
||||
unsafe {
|
||||
send_msg(iotask, TeardownLoop);
|
||||
}
|
||||
send_msg(iotask, TeardownLoop);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1111,22 +1111,22 @@ pub unsafe fn freeaddrinfo(res: *addrinfo) {
|
||||
}
|
||||
|
||||
// libuv struct initializers
|
||||
pub unsafe fn tcp_t() -> uv_tcp_t {
|
||||
pub fn tcp_t() -> uv_tcp_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_tcp_t();
|
||||
}
|
||||
pub unsafe fn connect_t() -> uv_connect_t {
|
||||
pub fn connect_t() -> uv_connect_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_connect_t();
|
||||
}
|
||||
pub unsafe fn write_t() -> uv_write_t {
|
||||
pub fn write_t() -> uv_write_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_write_t();
|
||||
}
|
||||
pub unsafe fn async_t() -> uv_async_t {
|
||||
pub fn async_t() -> uv_async_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_async_t();
|
||||
}
|
||||
pub unsafe fn timer_t() -> uv_timer_t {
|
||||
pub fn timer_t() -> uv_timer_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_timer_t();
|
||||
}
|
||||
pub unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t {
|
||||
pub fn getaddrinfo_t() -> uv_getaddrinfo_t {
|
||||
return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t();
|
||||
}
|
||||
|
||||
|
@ -274,13 +274,11 @@ impl ToStr for Abi {
|
||||
|
||||
impl ToStr for AbiSet {
|
||||
fn to_str(&self) -> ~str {
|
||||
unsafe { // so we can push to strs.
|
||||
let mut strs = ~[];
|
||||
for self.each |abi| {
|
||||
strs.push(abi.data().name);
|
||||
}
|
||||
fmt!("\"%s\"", str::connect_slices(strs, " "))
|
||||
let mut strs = ~[];
|
||||
for self.each |abi| {
|
||||
strs.push(abi.data().name);
|
||||
}
|
||||
fmt!("\"%s\"", str::connect_slices(strs, " "))
|
||||
}
|
||||
}
|
||||
|
||||
|
44
src/test/compile-fail/unused-unsafe.rs
Normal file
44
src/test/compile-fail/unused-unsafe.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Exercise the unused_unsafe attribute in some positive and negative cases
|
||||
|
||||
#[deny(unused_unsafe)];
|
||||
|
||||
use core::libc;
|
||||
|
||||
fn callback<T>(_f: &fn() -> T) -> T { fail!() }
|
||||
|
||||
fn bad1() { unsafe {} } //~ ERROR: unnecessary "unsafe" block
|
||||
fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary "unsafe" block
|
||||
unsafe fn bad3() {} //~ ERROR: unnecessary "unsafe" function
|
||||
unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary "unsafe" function
|
||||
//~^ ERROR: unnecessary "unsafe" block
|
||||
fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary "unsafe" block
|
||||
|
||||
unsafe fn good0() { libc::exit(1) }
|
||||
fn good1() { unsafe { libc::exit(1) } }
|
||||
fn good2() {
|
||||
/* bug uncovered when implementing warning about unused unsafe blocks. Be
|
||||
sure that when purity is inherited that the source of the unsafe-ness
|
||||
is tracked correctly */
|
||||
unsafe {
|
||||
unsafe fn what() -> ~[~str] { libc::exit(2) }
|
||||
|
||||
do callback {
|
||||
what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_unsafe)] unsafe fn allowed0() {}
|
||||
#[allow(unused_unsafe)] fn allowed1() { unsafe {} }
|
||||
|
||||
fn main() { }
|
Loading…
Reference in New Issue
Block a user