/** -> ///
This is considered good convention.
This commit is contained in:
parent
689ef2dabf
commit
f38e4e6d97
45 changed files with 1361 additions and 1658 deletions
|
@ -42,27 +42,25 @@ impl<E:CLike+fmt::Show> fmt::Show for EnumSet<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// An interface for casting C-like enum to uint and back.
|
||||||
An interface for casting C-like enum to uint and back.
|
/// A typically implementation is as below.
|
||||||
A typically implementation is as below.
|
///
|
||||||
|
/// ```{rust,ignore}
|
||||||
```{rust,ignore}
|
/// #[repr(uint)]
|
||||||
#[repr(uint)]
|
/// enum Foo {
|
||||||
enum Foo {
|
/// A, B, C
|
||||||
A, B, C
|
/// }
|
||||||
}
|
///
|
||||||
|
/// impl CLike for Foo {
|
||||||
impl CLike for Foo {
|
/// fn to_uint(&self) -> uint {
|
||||||
fn to_uint(&self) -> uint {
|
/// *self as uint
|
||||||
*self as uint
|
/// }
|
||||||
}
|
///
|
||||||
|
/// fn from_uint(v: uint) -> Foo {
|
||||||
fn from_uint(v: uint) -> Foo {
|
/// unsafe { mem::transmute(v) }
|
||||||
unsafe { mem::transmute(v) }
|
/// }
|
||||||
}
|
/// }
|
||||||
}
|
/// ```
|
||||||
```
|
|
||||||
*/
|
|
||||||
pub trait CLike {
|
pub trait CLike {
|
||||||
/// Converts a C-like enum to a `uint`.
|
/// Converts a C-like enum to a `uint`.
|
||||||
fn to_uint(&self) -> uint;
|
fn to_uint(&self) -> uint;
|
||||||
|
|
|
@ -58,38 +58,36 @@ impl<T> Finally<T> for fn() -> T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The most general form of the `finally` functions. The function
|
||||||
* The most general form of the `finally` functions. The function
|
/// `try_fn` will be invoked first; whether or not it panics, the
|
||||||
* `try_fn` will be invoked first; whether or not it panics, the
|
/// function `finally_fn` will be invoked next. The two parameters
|
||||||
* function `finally_fn` will be invoked next. The two parameters
|
/// `mutate` and `drop` are used to thread state through the two
|
||||||
* `mutate` and `drop` are used to thread state through the two
|
/// closures. `mutate` is used for any shared, mutable state that both
|
||||||
* closures. `mutate` is used for any shared, mutable state that both
|
/// closures require access to; `drop` is used for any state that the
|
||||||
* closures require access to; `drop` is used for any state that the
|
/// `try_fn` requires ownership of.
|
||||||
* `try_fn` requires ownership of.
|
///
|
||||||
*
|
/// **WARNING:** While shared, mutable state between the try and finally
|
||||||
* **WARNING:** While shared, mutable state between the try and finally
|
/// function is often necessary, one must be very careful; the `try`
|
||||||
* function is often necessary, one must be very careful; the `try`
|
/// function could have panicked at any point, so the values of the shared
|
||||||
* function could have panicked at any point, so the values of the shared
|
/// state may be inconsistent.
|
||||||
* state may be inconsistent.
|
///
|
||||||
*
|
/// # Example
|
||||||
* # Example
|
///
|
||||||
*
|
/// ```
|
||||||
* ```
|
/// use std::finally::try_finally;
|
||||||
* use std::finally::try_finally;
|
///
|
||||||
*
|
/// struct State<'a> { buffer: &'a mut [u8], len: uint }
|
||||||
* struct State<'a> { buffer: &'a mut [u8], len: uint }
|
/// # let mut buf = [];
|
||||||
* # let mut buf = [];
|
/// let mut state = State { buffer: &mut buf, len: 0 };
|
||||||
* let mut state = State { buffer: &mut buf, len: 0 };
|
/// try_finally(
|
||||||
* try_finally(
|
/// &mut state, (),
|
||||||
* &mut state, (),
|
/// |state, ()| {
|
||||||
* |state, ()| {
|
/// // use state.buffer, state.len
|
||||||
* // use state.buffer, state.len
|
/// },
|
||||||
* },
|
/// |state| {
|
||||||
* |state| {
|
/// // use state.buffer, state.len to cleanup
|
||||||
* // use state.buffer, state.len to cleanup
|
/// })
|
||||||
* })
|
/// ```
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
pub fn try_finally<T,U,R>(mutate: &mut T,
|
pub fn try_finally<T,U,R>(mutate: &mut T,
|
||||||
drop: U,
|
drop: U,
|
||||||
try_fn: |&mut T, U| -> R,
|
try_fn: |&mut T, U| -> R,
|
||||||
|
|
|
@ -54,36 +54,36 @@ pub enum SignFormat {
|
||||||
|
|
||||||
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
|
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
|
||||||
|
|
||||||
/**
|
/// Converts a number to its string representation as a byte vector.
|
||||||
* Converts a number to its string representation as a byte vector.
|
/// This is meant to be a common base implementation for all numeric string
|
||||||
* This is meant to be a common base implementation for all numeric string
|
/// conversion functions like `to_string()` or `to_str_radix()`.
|
||||||
* conversion functions like `to_string()` or `to_str_radix()`.
|
///
|
||||||
*
|
/// # Arguments
|
||||||
* # Arguments
|
///
|
||||||
* - `num` - The number to convert. Accepts any number that
|
/// - `num` - The number to convert. Accepts any number that
|
||||||
* implements the numeric traits.
|
/// implements the numeric traits.
|
||||||
* - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
|
/// - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
|
||||||
* is used, then this base is only used for the significand. The exponent
|
/// is used, then this base is only used for the significand. The exponent
|
||||||
* itself always printed using a base of 10.
|
/// itself always printed using a base of 10.
|
||||||
* - `negative_zero` - Whether to treat the special value `-0` as
|
/// - `negative_zero` - Whether to treat the special value `-0` as
|
||||||
* `-0` or as `+0`.
|
/// `-0` or as `+0`.
|
||||||
* - `sign` - How to emit the sign. See `SignFormat`.
|
/// - `sign` - How to emit the sign. See `SignFormat`.
|
||||||
* - `digits` - The amount of digits to use for emitting the fractional
|
/// - `digits` - The amount of digits to use for emitting the fractional
|
||||||
* part, if any. See `SignificantDigits`.
|
/// part, if any. See `SignificantDigits`.
|
||||||
* - `exp_format` - Whether or not to use the exponential (scientific) notation.
|
/// - `exp_format` - Whether or not to use the exponential (scientific) notation.
|
||||||
* See `ExponentFormat`.
|
/// See `ExponentFormat`.
|
||||||
* - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
|
/// - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
|
||||||
* exponential notation is desired.
|
/// exponential notation is desired.
|
||||||
* - `f` - A closure to invoke with the bytes representing the
|
/// - `f` - A closure to invoke with the bytes representing the
|
||||||
* float.
|
/// float.
|
||||||
*
|
///
|
||||||
* # Panics
|
/// # Panics
|
||||||
* - Panics if `radix` < 2 or `radix` > 36.
|
///
|
||||||
* - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
|
/// - Panics if `radix` < 2 or `radix` > 36.
|
||||||
* between digit and exponent sign `'e'`.
|
/// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
|
||||||
* - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
|
/// between digit and exponent sign `'e'`.
|
||||||
* between digit and exponent sign `'p'`.
|
/// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
|
||||||
*/
|
/// between digit and exponent sign `'p'`.
|
||||||
pub fn float_to_str_bytes_common<T: Float, U>(
|
pub fn float_to_str_bytes_common<T: Float, U>(
|
||||||
num: T,
|
num: T,
|
||||||
radix: uint,
|
radix: uint,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1634,9 +1634,7 @@ impl BinarySearchResult {
|
||||||
// Free functions
|
// Free functions
|
||||||
//
|
//
|
||||||
|
|
||||||
/**
|
/// Converts a pointer to A into a slice of length 1 (without copying).
|
||||||
* Converts a pointer to A into a slice of length 1 (without copying).
|
|
||||||
*/
|
|
||||||
#[unstable = "waiting for DST"]
|
#[unstable = "waiting for DST"]
|
||||||
pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
|
pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1644,9 +1642,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Converts a pointer to A into a slice of length 1 (without copying).
|
||||||
* Converts a pointer to A into a slice of length 1 (without copying).
|
|
||||||
*/
|
|
||||||
#[unstable = "waiting for DST"]
|
#[unstable = "waiting for DST"]
|
||||||
pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
|
pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1710,10 +1706,8 @@ pub mod raw {
|
||||||
use raw::Slice;
|
use raw::Slice;
|
||||||
use option::{None, Option, Some};
|
use option::{None, Option, Some};
|
||||||
|
|
||||||
/**
|
/// Form a slice from a pointer and length (as a number of units,
|
||||||
* Form a slice from a pointer and length (as a number of units,
|
/// not bytes).
|
||||||
* not bytes).
|
|
||||||
*/
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "renamed to slice::from_raw_buf"]
|
#[deprecated = "renamed to slice::from_raw_buf"]
|
||||||
pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U)
|
pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U)
|
||||||
|
@ -1724,10 +1718,8 @@ pub mod raw {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Form a slice from a pointer and length (as a number of units,
|
||||||
* Form a slice from a pointer and length (as a number of units,
|
/// not bytes).
|
||||||
* not bytes).
|
|
||||||
*/
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "renamed to slice::from_raw_mut_buf"]
|
#[deprecated = "renamed to slice::from_raw_mut_buf"]
|
||||||
pub unsafe fn mut_buf_as_slice<T,
|
pub unsafe fn mut_buf_as_slice<T,
|
||||||
|
@ -1742,11 +1734,9 @@ pub mod raw {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a pointer to first element in slice and adjusts
|
||||||
* Returns a pointer to first element in slice and adjusts
|
/// slice so it no longer contains that element. Returns None
|
||||||
* slice so it no longer contains that element. Returns None
|
/// if the slice is empty. O(1).
|
||||||
* if the slice is empty. O(1).
|
|
||||||
*/
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "inspect `Slice::{data, len}` manually (increment data by 1)"]
|
#[deprecated = "inspect `Slice::{data, len}` manually (increment data by 1)"]
|
||||||
pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
|
pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
|
||||||
|
@ -1757,11 +1747,9 @@ pub mod raw {
|
||||||
Some(head)
|
Some(head)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a pointer to last element in slice and adjusts
|
||||||
* Returns a pointer to last element in slice and adjusts
|
/// slice so it no longer contains that element. Returns None
|
||||||
* slice so it no longer contains that element. Returns None
|
/// if the slice is empty. O(1).
|
||||||
* if the slice is empty. O(1).
|
|
||||||
*/
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "inspect `Slice::{data, len}` manually (decrement len by 1)"]
|
#[deprecated = "inspect `Slice::{data, len}` manually (decrement len by 1)"]
|
||||||
pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
|
pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
|
||||||
|
|
|
@ -329,20 +329,18 @@ pub mod types {
|
||||||
// Standard types that are opaque or common, so are not per-target.
|
// Standard types that are opaque or common, so are not per-target.
|
||||||
pub mod common {
|
pub mod common {
|
||||||
pub mod c95 {
|
pub mod c95 {
|
||||||
/**
|
/// Type used to construct void pointers for use with C.
|
||||||
Type used to construct void pointers for use with C.
|
///
|
||||||
|
/// This type is only useful as a pointer target. Do not use it as a
|
||||||
This type is only useful as a pointer target. Do not use it as a
|
/// return type for FFI functions which have the `void` return type in
|
||||||
return type for FFI functions which have the `void` return type in
|
/// C. Use the unit type `()` or omit the return type instead.
|
||||||
C. Use the unit type `()` or omit the return type instead.
|
///
|
||||||
|
/// For LLVM to recognize the void pointer type and by extension
|
||||||
For LLVM to recognize the void pointer type and by extension
|
/// functions like malloc(), we need to have it represented as i8* in
|
||||||
functions like malloc(), we need to have it represented as i8* in
|
/// LLVM bitcode. The enum used here ensures this and prevents misuse
|
||||||
LLVM bitcode. The enum used here ensures this and prevents misuse
|
/// of the "raw" type by only having private variants.. We need two
|
||||||
of the "raw" type by only having private variants.. We need two
|
/// variants, because the compiler complains about the repr attribute
|
||||||
variants, because the compiler complains about the repr attribute
|
/// otherwise.
|
||||||
otherwise.
|
|
||||||
*/
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum c_void {
|
pub enum c_void {
|
||||||
__variant1,
|
__variant1,
|
||||||
|
|
|
@ -464,11 +464,9 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
|
||||||
self.lookup_and_emit(lint, Some(span), msg);
|
self.lookup_and_emit(lint, Some(span), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Merge the lints specified by any lint attributes into the
|
||||||
* Merge the lints specified by any lint attributes into the
|
/// current lint context, call the provided function, then reset the
|
||||||
* current lint context, call the provided function, then reset the
|
/// lints in effect to their previous state.
|
||||||
* lints in effect to their previous state.
|
|
||||||
*/
|
|
||||||
fn with_lint_attrs(&mut self,
|
fn with_lint_attrs(&mut self,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
f: |&mut Context|) {
|
f: |&mut Context|) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use syntax::ast;
|
||||||
|
|
||||||
use self::SimplifiedType::*;
|
use self::SimplifiedType::*;
|
||||||
|
|
||||||
/** See `simplify_type */
|
/// See `simplify_type
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash)]
|
#[deriving(Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum SimplifiedType {
|
pub enum SimplifiedType {
|
||||||
BoolSimplifiedType,
|
BoolSimplifiedType,
|
||||||
|
|
|
@ -266,24 +266,22 @@ pub struct MemCategorizationContext<'t,TYPER:'t> {
|
||||||
|
|
||||||
pub type McResult<T> = Result<T, ()>;
|
pub type McResult<T> = Result<T, ()>;
|
||||||
|
|
||||||
/**
|
/// The `Typer` trait provides the interface for the mem-categorization
|
||||||
* The `Typer` trait provides the interface for the mem-categorization
|
/// module to the results of the type check. It can be used to query
|
||||||
* module to the results of the type check. It can be used to query
|
/// the type assigned to an expression node, to inquire after adjustments,
|
||||||
* the type assigned to an expression node, to inquire after adjustments,
|
/// and so on.
|
||||||
* and so on.
|
///
|
||||||
*
|
/// This interface is needed because mem-categorization is used from
|
||||||
* This interface is needed because mem-categorization is used from
|
/// two places: `regionck` and `borrowck`. `regionck` executes before
|
||||||
* two places: `regionck` and `borrowck`. `regionck` executes before
|
/// type inference is complete, and hence derives types and so on from
|
||||||
* type inference is complete, and hence derives types and so on from
|
/// intermediate tables. This also implies that type errors can occur,
|
||||||
* intermediate tables. This also implies that type errors can occur,
|
/// and hence `node_ty()` and friends return a `Result` type -- any
|
||||||
* and hence `node_ty()` and friends return a `Result` type -- any
|
/// error will propagate back up through the mem-categorization
|
||||||
* error will propagate back up through the mem-categorization
|
/// routines.
|
||||||
* routines.
|
///
|
||||||
*
|
/// In the borrow checker, in contrast, type checking is complete and we
|
||||||
* In the borrow checker, in contrast, type checking is complete and we
|
/// know that no errors have occurred, so we simply consult the tcx and we
|
||||||
* know that no errors have occurred, so we simply consult the tcx and we
|
/// can be sure that only `Ok` results will occur.
|
||||||
* can be sure that only `Ok` results will occur.
|
|
||||||
*/
|
|
||||||
pub trait Typer<'tcx> {
|
pub trait Typer<'tcx> {
|
||||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||||
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
|
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
|
||||||
|
|
|
@ -72,46 +72,44 @@ impl CodeExtent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
The region maps encode information about region relationships.
|
The region maps encode information about region relationships.
|
||||||
|
|
||||||
- `scope_map` maps from a scope id to the enclosing scope id; this is
|
/// - `scope_map` maps from a scope id to the enclosing scope id; this is
|
||||||
usually corresponding to the lexical nesting, though in the case of
|
/// usually corresponding to the lexical nesting, though in the case of
|
||||||
closures the parent scope is the innermost conditional expression or repeating
|
/// closures the parent scope is the innermost conditional expression or repeating
|
||||||
block
|
/// block
|
||||||
|
///
|
||||||
- `var_map` maps from a variable or binding id to the block in which
|
/// - `var_map` maps from a variable or binding id to the block in which
|
||||||
that variable is declared.
|
/// that variable is declared.
|
||||||
|
///
|
||||||
- `free_region_map` maps from a free region `a` to a list of free
|
/// - `free_region_map` maps from a free region `a` to a list of free
|
||||||
regions `bs` such that `a <= b for all b in bs`
|
/// regions `bs` such that `a <= b for all b in bs`
|
||||||
- the free region map is populated during type check as we check
|
/// - the free region map is populated during type check as we check
|
||||||
each function. See the function `relate_free_regions` for
|
/// each function. See the function `relate_free_regions` for
|
||||||
more information.
|
/// more information.
|
||||||
|
///
|
||||||
- `rvalue_scopes` includes entries for those expressions whose cleanup
|
/// - `rvalue_scopes` includes entries for those expressions whose cleanup
|
||||||
scope is larger than the default. The map goes from the expression
|
/// scope is larger than the default. The map goes from the expression
|
||||||
id to the cleanup scope id. For rvalues not present in this table,
|
/// id to the cleanup scope id. For rvalues not present in this table,
|
||||||
the appropriate cleanup scope is the innermost enclosing statement,
|
/// the appropriate cleanup scope is the innermost enclosing statement,
|
||||||
conditional expression, or repeating block (see `terminating_scopes`).
|
/// conditional expression, or repeating block (see `terminating_scopes`).
|
||||||
|
///
|
||||||
- `terminating_scopes` is a set containing the ids of each statement,
|
/// - `terminating_scopes` is a set containing the ids of each statement,
|
||||||
or conditional/repeating expression. These scopes are calling "terminating
|
/// or conditional/repeating expression. These scopes are calling "terminating
|
||||||
scopes" because, when attempting to find the scope of a temporary, by
|
/// scopes" because, when attempting to find the scope of a temporary, by
|
||||||
default we search up the enclosing scopes until we encounter the
|
/// default we search up the enclosing scopes until we encounter the
|
||||||
terminating scope. A conditional/repeating
|
/// terminating scope. A conditional/repeating
|
||||||
expression is one which is not guaranteed to execute exactly once
|
/// expression is one which is not guaranteed to execute exactly once
|
||||||
upon entering the parent scope. This could be because the expression
|
/// upon entering the parent scope. This could be because the expression
|
||||||
only executes conditionally, such as the expression `b` in `a && b`,
|
/// only executes conditionally, such as the expression `b` in `a && b`,
|
||||||
or because the expression may execute many times, such as a loop
|
/// or because the expression may execute many times, such as a loop
|
||||||
body. The reason that we distinguish such expressions is that, upon
|
/// body. The reason that we distinguish such expressions is that, upon
|
||||||
exiting the parent scope, we cannot statically know how many times
|
/// exiting the parent scope, we cannot statically know how many times
|
||||||
the expression executed, and thus if the expression creates
|
/// the expression executed, and thus if the expression creates
|
||||||
temporaries we cannot know statically how many such temporaries we
|
/// temporaries we cannot know statically how many such temporaries we
|
||||||
would have to cleanup. Therefore we ensure that the temporaries never
|
/// would have to cleanup. Therefore we ensure that the temporaries never
|
||||||
outlast the conditional/repeating expression, preventing the need
|
/// outlast the conditional/repeating expression, preventing the need
|
||||||
for dynamic checks and/or arbitrary amounts of stack space.
|
/// for dynamic checks and/or arbitrary amounts of stack space.
|
||||||
*/
|
|
||||||
pub struct RegionMaps {
|
pub struct RegionMaps {
|
||||||
scope_map: RefCell<FnvHashMap<CodeExtent, CodeExtent>>,
|
scope_map: RefCell<FnvHashMap<CodeExtent, CodeExtent>>,
|
||||||
var_map: RefCell<NodeMap<CodeExtent>>,
|
var_map: RefCell<NodeMap<CodeExtent>>,
|
||||||
|
|
|
@ -761,10 +761,8 @@ impl NameBindings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns the module node. Panics if this node does not have a module
|
||||||
* Returns the module node. Panics if this node does not have a module
|
/// definition.
|
||||||
* definition.
|
|
||||||
*/
|
|
||||||
fn get_module(&self) -> Rc<Module> {
|
fn get_module(&self) -> Rc<Module> {
|
||||||
match self.get_module_if_available() {
|
match self.get_module_if_available() {
|
||||||
None => {
|
None => {
|
||||||
|
@ -1098,18 +1096,16 @@ impl<'a> Resolver<'a> {
|
||||||
visit::walk_crate(&mut visitor, krate);
|
visit::walk_crate(&mut visitor, krate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Adds a new child item to the module definition of the parent node and
|
||||||
* Adds a new child item to the module definition of the parent node and
|
/// returns its corresponding name bindings as well as the current parent.
|
||||||
* returns its corresponding name bindings as well as the current parent.
|
/// Or, if we're inside a block, creates (or reuses) an anonymous module
|
||||||
* Or, if we're inside a block, creates (or reuses) an anonymous module
|
/// corresponding to the innermost block ID and returns the name bindings
|
||||||
* corresponding to the innermost block ID and returns the name bindings
|
/// as well as the newly-created parent.
|
||||||
* as well as the newly-created parent.
|
///
|
||||||
*
|
/// # Panics
|
||||||
* # Panics
|
///
|
||||||
*
|
/// Panics if this node does not have a module definition and we are not inside
|
||||||
* Panics if this node does not have a module definition and we are not inside
|
/// a block.
|
||||||
* a block.
|
|
||||||
*/
|
|
||||||
fn add_child(&self,
|
fn add_child(&self,
|
||||||
name: Name,
|
name: Name,
|
||||||
reduced_graph_parent: ReducedGraphParent,
|
reduced_graph_parent: ReducedGraphParent,
|
||||||
|
|
|
@ -24,22 +24,19 @@ use syntax::codemap::{Span, DUMMY_SP};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/// A substitution mapping type/region parameters to new values. We
|
||||||
* A substitution mapping type/region parameters to new values. We
|
/// identify each in-scope parameter by an *index* and a *parameter
|
||||||
* identify each in-scope parameter by an *index* and a *parameter
|
/// space* (which indices where the parameter is defined; see
|
||||||
* space* (which indices where the parameter is defined; see
|
/// `ParamSpace`).
|
||||||
* `ParamSpace`).
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct Substs<'tcx> {
|
pub struct Substs<'tcx> {
|
||||||
pub types: VecPerParamSpace<Ty<'tcx>>,
|
pub types: VecPerParamSpace<Ty<'tcx>>,
|
||||||
pub regions: RegionSubsts,
|
pub regions: RegionSubsts,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Represents the values to use when substituting lifetime parameters.
|
||||||
* Represents the values to use when substituting lifetime parameters.
|
/// If the value is `ErasedRegions`, then this subst is occurring during
|
||||||
* If the value is `ErasedRegions`, then this subst is occurring during
|
/// trans, and all region parameters will be replaced with `ty::ReStatic`.
|
||||||
* trans, and all region parameters will be replaced with `ty::ReStatic`. */
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub enum RegionSubsts {
|
pub enum RegionSubsts {
|
||||||
ErasedRegions,
|
ErasedRegions,
|
||||||
|
@ -226,11 +223,9 @@ impl ParamSpace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Vector of things sorted by param space. Used to keep
|
||||||
* Vector of things sorted by param space. Used to keep
|
/// the set of things declared on the type, self, or method
|
||||||
* the set of things declared on the type, self, or method
|
/// distinct.
|
||||||
* distinct.
|
|
||||||
*/
|
|
||||||
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
|
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
|
||||||
pub struct VecPerParamSpace<T> {
|
pub struct VecPerParamSpace<T> {
|
||||||
// This was originally represented as a tuple with one Vec<T> for
|
// This was originally represented as a tuple with one Vec<T> for
|
||||||
|
@ -250,10 +245,8 @@ pub struct VecPerParamSpace<T> {
|
||||||
content: Vec<T>,
|
content: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The `split` function converts one `VecPerParamSpace` into this
|
||||||
* The `split` function converts one `VecPerParamSpace` into this
|
/// `SeparateVecsPerParamSpace` structure.
|
||||||
* `SeparateVecsPerParamSpace` structure.
|
|
||||||
*/
|
|
||||||
pub struct SeparateVecsPerParamSpace<T> {
|
pub struct SeparateVecsPerParamSpace<T> {
|
||||||
pub types: Vec<T>,
|
pub types: Vec<T>,
|
||||||
pub selfs: Vec<T>,
|
pub selfs: Vec<T>,
|
||||||
|
|
|
@ -19,18 +19,16 @@ use super::FulfillmentError;
|
||||||
use super::CodeSelectionError;
|
use super::CodeSelectionError;
|
||||||
use super::select::SelectionContext;
|
use super::select::SelectionContext;
|
||||||
|
|
||||||
/**
|
/// The fulfillment context is used to drive trait resolution. It
|
||||||
* The fulfillment context is used to drive trait resolution. It
|
/// consists of a list of obligations that must be (eventually)
|
||||||
* consists of a list of obligations that must be (eventually)
|
/// satisfied. The job is to track which are satisfied, which yielded
|
||||||
* satisfied. The job is to track which are satisfied, which yielded
|
/// errors, and which are still pending. At any point, users can call
|
||||||
* errors, and which are still pending. At any point, users can call
|
/// `select_where_possible`, and the fulfilment context will try to do
|
||||||
* `select_where_possible`, and the fulfilment context will try to do
|
/// selection, retaining only those obligations that remain
|
||||||
* selection, retaining only those obligations that remain
|
/// ambiguous. This may be helpful in pushing type inference
|
||||||
* ambiguous. This may be helpful in pushing type inference
|
/// along. Once all type inference constraints have been generated, the
|
||||||
* along. Once all type inference constraints have been generated, the
|
/// method `select_all_or_error` can be used to report any remaining
|
||||||
* method `select_all_or_error` can be used to report any remaining
|
/// ambiguous cases as errors.
|
||||||
* ambiguous cases as errors.
|
|
||||||
*/
|
|
||||||
pub struct FulfillmentContext<'tcx> {
|
pub struct FulfillmentContext<'tcx> {
|
||||||
// A list of all obligations that have been registered with this
|
// A list of all obligations that have been registered with this
|
||||||
// fulfillment context.
|
// fulfillment context.
|
||||||
|
|
|
@ -42,14 +42,12 @@ mod fulfill;
|
||||||
mod select;
|
mod select;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
/**
|
/// An `Obligation` represents some trait reference (e.g. `int:Eq`) for
|
||||||
* An `Obligation` represents some trait reference (e.g. `int:Eq`) for
|
/// which the vtable must be found. The process of finding a vtable is
|
||||||
* which the vtable must be found. The process of finding a vtable is
|
/// called "resolving" the `Obligation`. This process consists of
|
||||||
* called "resolving" the `Obligation`. This process consists of
|
/// either identifying an `impl` (e.g., `impl Eq for int`) that
|
||||||
* either identifying an `impl` (e.g., `impl Eq for int`) that
|
/// provides the required vtable, or else finding a bound that is in
|
||||||
* provides the required vtable, or else finding a bound that is in
|
/// scope. The eventual result is usually a `Selection` (defined below).
|
||||||
* scope. The eventual result is usually a `Selection` (defined below).
|
|
||||||
*/
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct Obligation<'tcx> {
|
pub struct Obligation<'tcx> {
|
||||||
pub cause: ObligationCause<'tcx>,
|
pub cause: ObligationCause<'tcx>,
|
||||||
|
@ -57,9 +55,7 @@ pub struct Obligation<'tcx> {
|
||||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Why did we incur this obligation? Used for error reporting.
|
||||||
* Why did we incur this obligation? Used for error reporting.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ObligationCause<'tcx> {
|
pub struct ObligationCause<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
@ -121,57 +117,53 @@ pub enum FulfillmentErrorCode<'tcx> {
|
||||||
CodeAmbiguity,
|
CodeAmbiguity,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// When performing resolution, it is typically the case that there
|
||||||
* When performing resolution, it is typically the case that there
|
/// can be one of three outcomes:
|
||||||
* can be one of three outcomes:
|
///
|
||||||
*
|
/// - `Ok(Some(r))`: success occurred with result `r`
|
||||||
* - `Ok(Some(r))`: success occurred with result `r`
|
/// - `Ok(None)`: could not definitely determine anything, usually due
|
||||||
* - `Ok(None)`: could not definitely determine anything, usually due
|
/// to inconclusive type inference.
|
||||||
* to inconclusive type inference.
|
/// - `Err(e)`: error `e` occurred
|
||||||
* - `Err(e)`: error `e` occurred
|
|
||||||
*/
|
|
||||||
pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
|
pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
|
||||||
|
|
||||||
/**
|
/// Given the successful resolution of an obligation, the `Vtable`
|
||||||
* Given the successful resolution of an obligation, the `Vtable`
|
/// indicates where the vtable comes from. Note that while we call this
|
||||||
* indicates where the vtable comes from. Note that while we call this
|
/// a "vtable", it does not necessarily indicate dynamic dispatch at
|
||||||
* a "vtable", it does not necessarily indicate dynamic dispatch at
|
/// runtime. `Vtable` instances just tell the compiler where to find
|
||||||
* runtime. `Vtable` instances just tell the compiler where to find
|
/// methods, but in generic code those methods are typically statically
|
||||||
* methods, but in generic code those methods are typically statically
|
/// dispatched -- only when an object is constructed is a `Vtable`
|
||||||
* dispatched -- only when an object is constructed is a `Vtable`
|
/// instance reified into an actual vtable.
|
||||||
* instance reified into an actual vtable.
|
///
|
||||||
*
|
/// For example, the vtable may be tied to a specific impl (case A),
|
||||||
* For example, the vtable may be tied to a specific impl (case A),
|
/// or it may be relative to some bound that is in scope (case B).
|
||||||
* or it may be relative to some bound that is in scope (case B).
|
///
|
||||||
*
|
///
|
||||||
*
|
/// ```
|
||||||
* ```
|
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
||||||
* impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
||||||
* impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
/// impl Clone for int { ... } // Impl_3
|
||||||
* impl Clone for int { ... } // Impl_3
|
///
|
||||||
*
|
/// fn foo<T:Clone>(concrete: Option<Box<int>>,
|
||||||
* fn foo<T:Clone>(concrete: Option<Box<int>>,
|
/// param: T,
|
||||||
* param: T,
|
/// mixed: Option<T>) {
|
||||||
* mixed: Option<T>) {
|
///
|
||||||
*
|
/// // Case A: Vtable points at a specific impl. Only possible when
|
||||||
* // Case A: Vtable points at a specific impl. Only possible when
|
/// // type is concretely known. If the impl itself has bounded
|
||||||
* // type is concretely known. If the impl itself has bounded
|
/// // type parameters, Vtable will carry resolutions for those as well:
|
||||||
* // type parameters, Vtable will carry resolutions for those as well:
|
/// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
|
||||||
* concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
|
///
|
||||||
*
|
/// // Case B: Vtable must be provided by caller. This applies when
|
||||||
* // Case B: Vtable must be provided by caller. This applies when
|
/// // type is a type parameter.
|
||||||
* // type is a type parameter.
|
/// param.clone(); // VtableParam(Oblig_1)
|
||||||
* param.clone(); // VtableParam(Oblig_1)
|
///
|
||||||
*
|
/// // Case C: A mix of cases A and B.
|
||||||
* // Case C: A mix of cases A and B.
|
/// mixed.clone(); // Vtable(Impl_1, [VtableParam(Oblig_1)])
|
||||||
* mixed.clone(); // Vtable(Impl_1, [VtableParam(Oblig_1)])
|
/// }
|
||||||
* }
|
/// ```
|
||||||
* ```
|
///
|
||||||
*
|
/// ### The type parameter `N`
|
||||||
* ### The type parameter `N`
|
///
|
||||||
*
|
/// See explanation on `VtableImplData`.
|
||||||
* See explanation on `VtableImplData`.
|
|
||||||
*/
|
|
||||||
#[deriving(Show,Clone)]
|
#[deriving(Show,Clone)]
|
||||||
pub enum Vtable<'tcx, N> {
|
pub enum Vtable<'tcx, N> {
|
||||||
/// Vtable identifying a particular impl.
|
/// Vtable identifying a particular impl.
|
||||||
|
@ -191,18 +183,16 @@ pub enum Vtable<'tcx, N> {
|
||||||
VtableBuiltin(VtableBuiltinData<N>),
|
VtableBuiltin(VtableBuiltinData<N>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Identifies a particular impl in the source, along with a set of
|
||||||
* Identifies a particular impl in the source, along with a set of
|
/// substitutions from the impl's type/lifetime parameters. The
|
||||||
* substitutions from the impl's type/lifetime parameters. The
|
/// `nested` vector corresponds to the nested obligations attached to
|
||||||
* `nested` vector corresponds to the nested obligations attached to
|
/// the impl's type parameters.
|
||||||
* the impl's type parameters.
|
///
|
||||||
*
|
/// The type parameter `N` indicates the type used for "nested
|
||||||
* The type parameter `N` indicates the type used for "nested
|
/// obligations" that are required by the impl. During type check, this
|
||||||
* obligations" that are required by the impl. During type check, this
|
/// is `Obligation`, as one might expect. During trans, however, this
|
||||||
* is `Obligation`, as one might expect. During trans, however, this
|
/// is `()`, because trans only requires a shallow resolution of an
|
||||||
* is `()`, because trans only requires a shallow resolution of an
|
/// impl, and nested obligations are satisfied later.
|
||||||
* impl, and nested obligations are satisfied later.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct VtableImplData<'tcx, N> {
|
pub struct VtableImplData<'tcx, N> {
|
||||||
pub impl_def_id: ast::DefId,
|
pub impl_def_id: ast::DefId,
|
||||||
|
@ -215,11 +205,9 @@ pub struct VtableBuiltinData<N> {
|
||||||
pub nested: subst::VecPerParamSpace<N>
|
pub nested: subst::VecPerParamSpace<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// A vtable provided as a parameter by the caller. For example, in a
|
||||||
* A vtable provided as a parameter by the caller. For example, in a
|
/// function like `fn foo<T:Eq>(...)`, if the `eq()` method is invoked
|
||||||
* function like `fn foo<T:Eq>(...)`, if the `eq()` method is invoked
|
/// on an instance of `T`, the vtable would be of type `VtableParam`.
|
||||||
* on an instance of `T`, the vtable would be of type `VtableParam`.
|
|
||||||
*/
|
|
||||||
#[deriving(PartialEq,Eq,Clone)]
|
#[deriving(PartialEq,Eq,Clone)]
|
||||||
pub struct VtableParamData<'tcx> {
|
pub struct VtableParamData<'tcx> {
|
||||||
// In the above example, this would `Eq`
|
// In the above example, this would `Eq`
|
||||||
|
|
|
@ -102,32 +102,30 @@ pub enum MethodMatchedData {
|
||||||
CoerciveMethodMatch(/* impl we matched */ ast::DefId)
|
CoerciveMethodMatch(/* impl we matched */ ast::DefId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The selection process begins by considering all impls, where
|
||||||
* The selection process begins by considering all impls, where
|
/// clauses, and so forth that might resolve an obligation. Sometimes
|
||||||
* clauses, and so forth that might resolve an obligation. Sometimes
|
/// we'll be able to say definitively that (e.g.) an impl does not
|
||||||
* we'll be able to say definitively that (e.g.) an impl does not
|
/// apply to the obligation: perhaps it is defined for `uint` but the
|
||||||
* apply to the obligation: perhaps it is defined for `uint` but the
|
/// obligation is for `int`. In that case, we drop the impl out of the
|
||||||
* obligation is for `int`. In that case, we drop the impl out of the
|
/// list. But the other cases are considered *candidates*.
|
||||||
* list. But the other cases are considered *candidates*.
|
///
|
||||||
*
|
/// Candidates can either be definitive or ambiguous. An ambiguous
|
||||||
* Candidates can either be definitive or ambiguous. An ambiguous
|
/// candidate is one that might match or might not, depending on how
|
||||||
* candidate is one that might match or might not, depending on how
|
/// type variables wind up being resolved. This only occurs during inference.
|
||||||
* type variables wind up being resolved. This only occurs during inference.
|
///
|
||||||
*
|
/// For selection to suceed, there must be exactly one non-ambiguous
|
||||||
* For selection to suceed, there must be exactly one non-ambiguous
|
/// candidate. Usually, it is not possible to have more than one
|
||||||
* candidate. Usually, it is not possible to have more than one
|
/// definitive candidate, due to the coherence rules. However, there is
|
||||||
* definitive candidate, due to the coherence rules. However, there is
|
/// one case where it could occur: if there is a blanket impl for a
|
||||||
* one case where it could occur: if there is a blanket impl for a
|
/// trait (that is, an impl applied to all T), and a type parameter
|
||||||
* trait (that is, an impl applied to all T), and a type parameter
|
/// with a where clause. In that case, we can have a candidate from the
|
||||||
* with a where clause. In that case, we can have a candidate from the
|
/// where clause and a second candidate from the impl. This is not a
|
||||||
* where clause and a second candidate from the impl. This is not a
|
/// problem because coherence guarantees us that the impl which would
|
||||||
* problem because coherence guarantees us that the impl which would
|
/// be used to satisfy the where clause is the same one that we see
|
||||||
* be used to satisfy the where clause is the same one that we see
|
/// now. To resolve this issue, therefore, we ignore impls if we find a
|
||||||
* now. To resolve this issue, therefore, we ignore impls if we find a
|
/// matching where clause. Part of the reason for this is that where
|
||||||
* matching where clause. Part of the reason for this is that where
|
/// clauses can give additional information (like, the types of output
|
||||||
* clauses can give additional information (like, the types of output
|
/// parameters) that would have to be inferred from the impl.
|
||||||
* parameters) that would have to be inferred from the impl.
|
|
||||||
*/
|
|
||||||
#[deriving(PartialEq,Eq,Show,Clone)]
|
#[deriving(PartialEq,Eq,Show,Clone)]
|
||||||
enum Candidate<'tcx> {
|
enum Candidate<'tcx> {
|
||||||
BuiltinCandidate(ty::BuiltinBound),
|
BuiltinCandidate(ty::BuiltinBound),
|
||||||
|
|
|
@ -743,18 +743,16 @@ impl<'tcx> FnOutput<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Signature of a function type, which I have arbitrarily
|
||||||
* Signature of a function type, which I have arbitrarily
|
/// decided to use to refer to the input/output types.
|
||||||
* decided to use to refer to the input/output types.
|
///
|
||||||
*
|
/// - `inputs` is the list of arguments and their modes.
|
||||||
* - `inputs` is the list of arguments and their modes.
|
/// - `output` is the return type.
|
||||||
* - `output` is the return type.
|
/// - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
|
||||||
* - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
|
///
|
||||||
*
|
/// Note that a `FnSig` introduces a level of region binding, to
|
||||||
* Note that a `FnSig` introduces a level of region binding, to
|
/// account for late-bound parameters that appear in the types of the
|
||||||
* account for late-bound parameters that appear in the types of the
|
/// fn's arguments or the fn's return type.
|
||||||
* fn's arguments or the fn's return type.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash)]
|
#[deriving(Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct FnSig<'tcx> {
|
pub struct FnSig<'tcx> {
|
||||||
pub inputs: Vec<Ty<'tcx>>,
|
pub inputs: Vec<Ty<'tcx>>,
|
||||||
|
@ -769,47 +767,45 @@ pub struct ParamTy {
|
||||||
pub def_id: DefId
|
pub def_id: DefId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// A [De Bruijn index][dbi] is a standard means of representing
|
||||||
* A [De Bruijn index][dbi] is a standard means of representing
|
/// regions (and perhaps later types) in a higher-ranked setting. In
|
||||||
* regions (and perhaps later types) in a higher-ranked setting. In
|
/// particular, imagine a type like this:
|
||||||
* particular, imagine a type like this:
|
///
|
||||||
*
|
/// for<'a> fn(for<'b> fn(&'b int, &'a int), &'a char)
|
||||||
* for<'a> fn(for<'b> fn(&'b int, &'a int), &'a char)
|
/// ^ ^ | | |
|
||||||
* ^ ^ | | |
|
/// | | | | |
|
||||||
* | | | | |
|
/// | +------------+ 1 | |
|
||||||
* | +------------+ 1 | |
|
/// | | |
|
||||||
* | | |
|
/// +--------------------------------+ 2 |
|
||||||
* +--------------------------------+ 2 |
|
/// | |
|
||||||
* | |
|
/// +------------------------------------------+ 1
|
||||||
* +------------------------------------------+ 1
|
///
|
||||||
*
|
/// In this type, there are two binders (the outer fn and the inner
|
||||||
* In this type, there are two binders (the outer fn and the inner
|
/// fn). We need to be able to determine, for any given region, which
|
||||||
* fn). We need to be able to determine, for any given region, which
|
/// fn type it is bound by, the inner or the outer one. There are
|
||||||
* fn type it is bound by, the inner or the outer one. There are
|
/// various ways you can do this, but a De Bruijn index is one of the
|
||||||
* various ways you can do this, but a De Bruijn index is one of the
|
/// more convenient and has some nice properties. The basic idea is to
|
||||||
* more convenient and has some nice properties. The basic idea is to
|
/// count the number of binders, inside out. Some examples should help
|
||||||
* count the number of binders, inside out. Some examples should help
|
/// clarify what I mean.
|
||||||
* clarify what I mean.
|
///
|
||||||
*
|
/// Let's start with the reference type `&'b int` that is the first
|
||||||
* Let's start with the reference type `&'b int` that is the first
|
/// argument to the inner function. This region `'b` is assigned a De
|
||||||
* argument to the inner function. This region `'b` is assigned a De
|
/// Bruijn index of 1, meaning "the innermost binder" (in this case, a
|
||||||
* Bruijn index of 1, meaning "the innermost binder" (in this case, a
|
/// fn). The region `'a` that appears in the second argument type (`&'a
|
||||||
* fn). The region `'a` that appears in the second argument type (`&'a
|
/// int`) would then be assigned a De Bruijn index of 2, meaning "the
|
||||||
* int`) would then be assigned a De Bruijn index of 2, meaning "the
|
/// second-innermost binder". (These indices are written on the arrays
|
||||||
* second-innermost binder". (These indices are written on the arrays
|
/// in the diagram).
|
||||||
* in the diagram).
|
///
|
||||||
*
|
/// What is interesting is that De Bruijn index attached to a particular
|
||||||
* What is interesting is that De Bruijn index attached to a particular
|
/// variable will vary depending on where it appears. For example,
|
||||||
* variable will vary depending on where it appears. For example,
|
/// the final type `&'a char` also refers to the region `'a` declared on
|
||||||
* the final type `&'a char` also refers to the region `'a` declared on
|
/// the outermost fn. But this time, this reference is not nested within
|
||||||
* the outermost fn. But this time, this reference is not nested within
|
/// any other binders (i.e., it is not an argument to the inner fn, but
|
||||||
* any other binders (i.e., it is not an argument to the inner fn, but
|
/// rather the outer one). Therefore, in this case, it is assigned a
|
||||||
* rather the outer one). Therefore, in this case, it is assigned a
|
/// De Bruijn index of 1, because the innermost binder in that location
|
||||||
* De Bruijn index of 1, because the innermost binder in that location
|
/// is the outer fn.
|
||||||
* is the outer fn.
|
///
|
||||||
*
|
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
|
||||||
* [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
|
||||||
pub struct DebruijnIndex {
|
pub struct DebruijnIndex {
|
||||||
// We maintain the invariant that this is never 0. So 1 indicates
|
// We maintain the invariant that this is never 0. So 1 indicates
|
||||||
|
@ -856,11 +852,9 @@ pub enum Region {
|
||||||
ReEmpty,
|
ReEmpty,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Upvars do not get their own node-id. Instead, we use the pair of
|
||||||
* Upvars do not get their own node-id. Instead, we use the pair of
|
/// the original var id (that is, the root variable that is referenced
|
||||||
* the original var id (that is, the root variable that is referenced
|
/// by the upvar) and the id of the closure expression.
|
||||||
* by the upvar) and the id of the closure expression.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct UpvarId {
|
pub struct UpvarId {
|
||||||
pub var_id: ast::NodeId,
|
pub var_id: ast::NodeId,
|
||||||
|
@ -913,55 +907,53 @@ pub enum BorrowKind {
|
||||||
MutBorrow
|
MutBorrow
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Information describing the borrowing of an upvar. This is computed
|
||||||
* Information describing the borrowing of an upvar. This is computed
|
/// during `typeck`, specifically by `regionck`. The general idea is
|
||||||
* during `typeck`, specifically by `regionck`. The general idea is
|
/// that the compiler analyses treat closures like:
|
||||||
* that the compiler analyses treat closures like:
|
///
|
||||||
*
|
/// let closure: &'e fn() = || {
|
||||||
* let closure: &'e fn() = || {
|
/// x = 1; // upvar x is assigned to
|
||||||
* x = 1; // upvar x is assigned to
|
/// use(y); // upvar y is read
|
||||||
* use(y); // upvar y is read
|
/// foo(&z); // upvar z is borrowed immutably
|
||||||
* foo(&z); // upvar z is borrowed immutably
|
/// };
|
||||||
* };
|
///
|
||||||
*
|
/// as if they were "desugared" to something loosely like:
|
||||||
* as if they were "desugared" to something loosely like:
|
///
|
||||||
*
|
/// struct Vars<'x,'y,'z> { x: &'x mut int,
|
||||||
* struct Vars<'x,'y,'z> { x: &'x mut int,
|
/// y: &'y const int,
|
||||||
* y: &'y const int,
|
/// z: &'z int }
|
||||||
* z: &'z int }
|
/// let closure: &'e fn() = {
|
||||||
* let closure: &'e fn() = {
|
/// fn f(env: &Vars) {
|
||||||
* fn f(env: &Vars) {
|
/// *env.x = 1;
|
||||||
* *env.x = 1;
|
/// use(*env.y);
|
||||||
* use(*env.y);
|
/// foo(env.z);
|
||||||
* foo(env.z);
|
/// }
|
||||||
* }
|
/// let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
|
||||||
* let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
|
/// y: &'y const y,
|
||||||
* y: &'y const y,
|
/// z: &'z z };
|
||||||
* z: &'z z };
|
/// (env, f)
|
||||||
* (env, f)
|
/// };
|
||||||
* };
|
///
|
||||||
*
|
/// This is basically what happens at runtime. The closure is basically
|
||||||
* This is basically what happens at runtime. The closure is basically
|
/// an existentially quantified version of the `(env, f)` pair.
|
||||||
* an existentially quantified version of the `(env, f)` pair.
|
///
|
||||||
*
|
/// This data structure indicates the region and mutability of a single
|
||||||
* This data structure indicates the region and mutability of a single
|
/// one of the `x...z` borrows.
|
||||||
* one of the `x...z` borrows.
|
///
|
||||||
*
|
/// It may not be obvious why each borrowed variable gets its own
|
||||||
* It may not be obvious why each borrowed variable gets its own
|
/// lifetime (in the desugared version of the example, these are indicated
|
||||||
* lifetime (in the desugared version of the example, these are indicated
|
/// by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
|
||||||
* by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
|
/// Each such lifetime must encompass the lifetime `'e` of the closure itself,
|
||||||
* Each such lifetime must encompass the lifetime `'e` of the closure itself,
|
/// but need not be identical to it. The reason that this makes sense:
|
||||||
* but need not be identical to it. The reason that this makes sense:
|
///
|
||||||
*
|
/// - Callers are only permitted to invoke the closure, and hence to
|
||||||
* - Callers are only permitted to invoke the closure, and hence to
|
/// use the pointers, within the lifetime `'e`, so clearly `'e` must
|
||||||
* use the pointers, within the lifetime `'e`, so clearly `'e` must
|
/// be a sublifetime of `'x...'z`.
|
||||||
* be a sublifetime of `'x...'z`.
|
/// - The closure creator knows which upvars were borrowed by the closure
|
||||||
* - The closure creator knows which upvars were borrowed by the closure
|
/// and thus `x...z` will be reserved for `'x...'z` respectively.
|
||||||
* and thus `x...z` will be reserved for `'x...'z` respectively.
|
/// - Through mutation, the borrowed upvars can actually escape
|
||||||
* - Through mutation, the borrowed upvars can actually escape
|
/// the closure, so sometimes it is necessary for them to be larger
|
||||||
* the closure, so sometimes it is necessary for them to be larger
|
/// than the closure lifetime itself.
|
||||||
* than the closure lifetime itself.
|
|
||||||
*/
|
|
||||||
#[deriving(PartialEq, Clone, Encodable, Decodable, Show)]
|
#[deriving(PartialEq, Clone, Encodable, Decodable, Show)]
|
||||||
pub struct UpvarBorrow {
|
pub struct UpvarBorrow {
|
||||||
pub kind: BorrowKind,
|
pub kind: BorrowKind,
|
||||||
|
@ -1111,37 +1103,33 @@ pub struct TyTrait<'tcx> {
|
||||||
pub bounds: ExistentialBounds
|
pub bounds: ExistentialBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||||
* A complete reference to a trait. These take numerous guises in syntax,
|
/// but perhaps the most recognizable form is in a where clause:
|
||||||
* but perhaps the most recognizable form is in a where clause:
|
///
|
||||||
*
|
/// T : Foo<U>
|
||||||
* T : Foo<U>
|
///
|
||||||
*
|
/// This would be represented by a trait-reference where the def-id is the
|
||||||
* This would be represented by a trait-reference where the def-id is the
|
/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
|
||||||
* def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
|
/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
|
||||||
* `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
|
///
|
||||||
*
|
/// Trait references also appear in object types like `Foo<U>`, but in
|
||||||
* Trait references also appear in object types like `Foo<U>`, but in
|
/// that case the `Self` parameter is absent from the substitutions.
|
||||||
* that case the `Self` parameter is absent from the substitutions.
|
///
|
||||||
*
|
/// Note that a `TraitRef` introduces a level of region binding, to
|
||||||
* Note that a `TraitRef` introduces a level of region binding, to
|
/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
|
||||||
* account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
|
/// U>` or higher-ranked object types.
|
||||||
* U>` or higher-ranked object types.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct TraitRef<'tcx> {
|
pub struct TraitRef<'tcx> {
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
pub substs: Substs<'tcx>,
|
pub substs: Substs<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Binder serves as a synthetic binder for lifetimes. It is used when
|
||||||
* Binder serves as a synthetic binder for lifetimes. It is used when
|
/// we wish to replace the escaping higher-ranked lifetimes in a type
|
||||||
* we wish to replace the escaping higher-ranked lifetimes in a type
|
/// or something else that is not itself a binder (this is because the
|
||||||
* or something else that is not itself a binder (this is because the
|
/// `replace_late_bound_regions` function replaces all lifetimes bound
|
||||||
* `replace_late_bound_regions` function replaces all lifetimes bound
|
/// by the binder supplied to it; but a type is not a binder, so you
|
||||||
* by the binder supplied to it; but a type is not a binder, so you
|
/// must introduce an artificial one).
|
||||||
* must introduce an artificial one).
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct Binder<T> {
|
pub struct Binder<T> {
|
||||||
pub value: T
|
pub value: T
|
||||||
|
@ -1425,27 +1413,25 @@ impl<'tcx> Generics<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Represents the bounds declared on a particular set of type
|
||||||
* Represents the bounds declared on a particular set of type
|
/// parameters. Should eventually be generalized into a flag list of
|
||||||
* parameters. Should eventually be generalized into a flag list of
|
/// where clauses. You can obtain a `GenericBounds` list from a
|
||||||
* where clauses. You can obtain a `GenericBounds` list from a
|
/// `Generics` by using the `to_bounds` method. Note that this method
|
||||||
* `Generics` by using the `to_bounds` method. Note that this method
|
/// reflects an important semantic invariant of `GenericBounds`: while
|
||||||
* reflects an important semantic invariant of `GenericBounds`: while
|
/// the bounds in a `Generics` are expressed in terms of the bound type
|
||||||
* the bounds in a `Generics` are expressed in terms of the bound type
|
/// parameters of the impl/trait/whatever, a `GenericBounds` instance
|
||||||
* parameters of the impl/trait/whatever, a `GenericBounds` instance
|
/// represented a set of bounds for some particular instantiation,
|
||||||
* represented a set of bounds for some particular instantiation,
|
/// meaning that the generic parameters have been substituted with
|
||||||
* meaning that the generic parameters have been substituted with
|
/// their values.
|
||||||
* their values.
|
///
|
||||||
*
|
/// Example:
|
||||||
* Example:
|
///
|
||||||
*
|
/// struct Foo<T,U:Bar<T>> { ... }
|
||||||
* struct Foo<T,U:Bar<T>> { ... }
|
///
|
||||||
*
|
/// Here, the `Generics` for `Foo` would contain a list of bounds like
|
||||||
* Here, the `Generics` for `Foo` would contain a list of bounds like
|
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
|
||||||
* `[[], [U:Bar<T>]]`. Now if there were some particular reference
|
/// like `Foo<int,uint>`, then the `GenericBounds` would be `[[],
|
||||||
* like `Foo<int,uint>`, then the `GenericBounds` would be `[[],
|
/// [uint:Bar<int>]]`.
|
||||||
* [uint:Bar<int>]]`.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, Show)]
|
#[deriving(Clone, Show)]
|
||||||
pub struct GenericBounds<'tcx> {
|
pub struct GenericBounds<'tcx> {
|
||||||
pub types: VecPerParamSpace<ParamBounds<'tcx>>,
|
pub types: VecPerParamSpace<ParamBounds<'tcx>>,
|
||||||
|
@ -2455,18 +2441,16 @@ pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Type contents is how the type checker reasons about kinds.
|
||||||
* Type contents is how the type checker reasons about kinds.
|
/// They track what kinds of things are found within a type. You can
|
||||||
* They track what kinds of things are found within a type. You can
|
/// think of them as kind of an "anti-kind". They track the kinds of values
|
||||||
* think of them as kind of an "anti-kind". They track the kinds of values
|
/// and thinks that are contained in types. Having a larger contents for
|
||||||
* and thinks that are contained in types. Having a larger contents for
|
/// a type tends to rule that type *out* from various kinds. For example,
|
||||||
* a type tends to rule that type *out* from various kinds. For example,
|
/// a type that contains a reference is not sendable.
|
||||||
* a type that contains a reference is not sendable.
|
///
|
||||||
*
|
/// The reason we compute type contents and not kinds is that it is
|
||||||
* The reason we compute type contents and not kinds is that it is
|
/// easier for me (nmatsakis) to think about what is contained within
|
||||||
* easier for me (nmatsakis) to think about what is contained within
|
/// a type than to think about what is *not* contained within a type.
|
||||||
* a type than to think about what is *not* contained within a type.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct TypeContents {
|
pub struct TypeContents {
|
||||||
pub bits: u64
|
pub bits: u64
|
||||||
|
|
|
@ -701,9 +701,7 @@ pub fn super_fold_obligation<'tcx, T:TypeFolder<'tcx>>(this: &mut T,
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Higher-ranked things
|
// Higher-ranked things
|
||||||
|
|
||||||
/**
|
/// Designates a "binder" for late-bound regions.
|
||||||
* Designates a "binder" for late-bound regions.
|
|
||||||
*/
|
|
||||||
pub trait HigherRankedFoldable<'tcx>: Repr<'tcx> {
|
pub trait HigherRankedFoldable<'tcx>: Repr<'tcx> {
|
||||||
/// Folds the contents of `self`, ignoring the region binder created
|
/// Folds the contents of `self`, ignoring the region binder created
|
||||||
/// by `self`.
|
/// by `self`.
|
||||||
|
|
|
@ -897,19 +897,17 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Checks that a method from an impl conforms to the signature of
|
||||||
* Checks that a method from an impl conforms to the signature of
|
/// the same method as declared in the trait.
|
||||||
* the same method as declared in the trait.
|
///
|
||||||
*
|
/// # Parameters
|
||||||
* # Parameters
|
///
|
||||||
*
|
/// - impl_generics: the generics declared on the impl itself (not the method!)
|
||||||
* - impl_generics: the generics declared on the impl itself (not the method!)
|
/// - impl_m: type of the method we are checking
|
||||||
* - impl_m: type of the method we are checking
|
/// - impl_m_span: span to use for reporting errors
|
||||||
* - impl_m_span: span to use for reporting errors
|
/// - impl_m_body_id: id of the method body
|
||||||
* - impl_m_body_id: id of the method body
|
/// - trait_m: the method in the trait
|
||||||
* - trait_m: the method in the trait
|
/// - trait_to_impl_substs: the substitutions used on the type of the trait
|
||||||
* - trait_to_impl_substs: the substitutions used on the type of the trait
|
|
||||||
*/
|
|
||||||
fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
impl_m: &ty::Method<'tcx>,
|
impl_m: &ty::Method<'tcx>,
|
||||||
impl_m_span: Span,
|
impl_m_span: Span,
|
||||||
|
|
|
@ -694,13 +694,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// This function performs the actual region resolution. It must be
|
||||||
This function performs the actual region resolution. It must be
|
/// called after all constraints have been added. It performs a
|
||||||
called after all constraints have been added. It performs a
|
/// fixed-point iteration to find region values which satisfy all
|
||||||
fixed-point iteration to find region values which satisfy all
|
/// constraints, assuming such values can be found; if they cannot,
|
||||||
constraints, assuming such values can be found; if they cannot,
|
/// errors are reported.
|
||||||
errors are reported.
|
|
||||||
*/
|
|
||||||
pub fn resolve_regions(&self) -> Vec<RegionResolutionError<'tcx>> {
|
pub fn resolve_regions(&self) -> Vec<RegionResolutionError<'tcx>> {
|
||||||
debug!("RegionVarBindings: resolve_regions()");
|
debug!("RegionVarBindings: resolve_regions()");
|
||||||
let mut errors = vec!();
|
let mut errors = vec!();
|
||||||
|
|
|
@ -22,85 +22,68 @@ use syntax::ast;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
use util::snapshot_vec as sv;
|
use util::snapshot_vec as sv;
|
||||||
|
|
||||||
/**
|
/// This trait is implemented by any type that can serve as a type
|
||||||
* This trait is implemented by any type that can serve as a type
|
/// variable. We call such variables *unification keys*. For example,
|
||||||
* variable. We call such variables *unification keys*. For example,
|
/// this trait is implemented by `IntVid`, which represents integral
|
||||||
* this trait is implemented by `IntVid`, which represents integral
|
/// variables.
|
||||||
* variables.
|
///
|
||||||
*
|
/// Each key type has an associated value type `V`. For example, for
|
||||||
* Each key type has an associated value type `V`. For example, for
|
/// `IntVid`, this is `Option<IntVarValue>`, representing some
|
||||||
* `IntVid`, this is `Option<IntVarValue>`, representing some
|
/// (possibly not yet known) sort of integer.
|
||||||
* (possibly not yet known) sort of integer.
|
///
|
||||||
*
|
/// Implementations of this trait are at the end of this file.
|
||||||
* Implementations of this trait are at the end of this file.
|
|
||||||
*/
|
|
||||||
pub trait UnifyKey<'tcx, V> : Clone + Show + PartialEq + Repr<'tcx> {
|
pub trait UnifyKey<'tcx, V> : Clone + Show + PartialEq + Repr<'tcx> {
|
||||||
fn index(&self) -> uint;
|
fn index(&self) -> uint;
|
||||||
|
|
||||||
fn from_index(u: uint) -> Self;
|
fn from_index(u: uint) -> Self;
|
||||||
|
|
||||||
/**
|
// Given an inference context, returns the unification table
|
||||||
* Given an inference context, returns the unification table
|
// appropriate to this key type.
|
||||||
* appropriate to this key type.
|
|
||||||
*/
|
|
||||||
fn unification_table<'v>(infcx: &'v InferCtxt)
|
fn unification_table<'v>(infcx: &'v InferCtxt)
|
||||||
-> &'v RefCell<UnificationTable<Self,V>>;
|
-> &'v RefCell<UnificationTable<Self,V>>;
|
||||||
|
|
||||||
fn tag(k: Option<Self>) -> &'static str;
|
fn tag(k: Option<Self>) -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Trait for valid types that a type variable can be set to. Note that
|
||||||
* Trait for valid types that a type variable can be set to. Note that
|
/// this is typically not the end type that the value will take on, but
|
||||||
* this is typically not the end type that the value will take on, but
|
/// rather an `Option` wrapper (where `None` represents a variable
|
||||||
* rather an `Option` wrapper (where `None` represents a variable
|
/// whose value is not yet set).
|
||||||
* whose value is not yet set).
|
///
|
||||||
*
|
/// Implementations of this trait are at the end of this file.
|
||||||
* Implementations of this trait are at the end of this file.
|
|
||||||
*/
|
|
||||||
pub trait UnifyValue<'tcx> : Clone + Repr<'tcx> + PartialEq {
|
pub trait UnifyValue<'tcx> : Clone + Repr<'tcx> + PartialEq {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Value of a unification key. We implement Tarjan's union-find
|
||||||
* Value of a unification key. We implement Tarjan's union-find
|
/// algorithm: when two keys are unified, one of them is converted
|
||||||
* algorithm: when two keys are unified, one of them is converted
|
/// into a "redirect" pointing at the other. These redirects form a
|
||||||
* into a "redirect" pointing at the other. These redirects form a
|
/// DAG: the roots of the DAG (nodes that are not redirected) are each
|
||||||
* DAG: the roots of the DAG (nodes that are not redirected) are each
|
/// associated with a value of type `V` and a rank. The rank is used
|
||||||
* associated with a value of type `V` and a rank. The rank is used
|
/// to keep the DAG relatively balanced, which helps keep the running
|
||||||
* to keep the DAG relatively balanced, which helps keep the running
|
/// time of the algorithm under control. For more information, see
|
||||||
* time of the algorithm under control. For more information, see
|
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
|
||||||
* <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
|
|
||||||
*/
|
|
||||||
#[deriving(PartialEq,Clone)]
|
#[deriving(PartialEq,Clone)]
|
||||||
pub enum VarValue<K,V> {
|
pub enum VarValue<K,V> {
|
||||||
Redirect(K),
|
Redirect(K),
|
||||||
Root(V, uint),
|
Root(V, uint),
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Table of unification keys and their values.
|
||||||
* Table of unification keys and their values.
|
|
||||||
*/
|
|
||||||
pub struct UnificationTable<K,V> {
|
pub struct UnificationTable<K,V> {
|
||||||
/**
|
/// Indicates the current value of each key.
|
||||||
* Indicates the current value of each key.
|
|
||||||
*/
|
|
||||||
|
|
||||||
values: sv::SnapshotVec<VarValue<K,V>,(),Delegate>,
|
values: sv::SnapshotVec<VarValue<K,V>,(),Delegate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// At any time, users may snapshot a unification table. The changes
|
||||||
* At any time, users may snapshot a unification table. The changes
|
/// made during the snapshot may either be *committed* or *rolled back*.
|
||||||
* made during the snapshot may either be *committed* or *rolled back*.
|
|
||||||
*/
|
|
||||||
pub struct Snapshot<K> {
|
pub struct Snapshot<K> {
|
||||||
// Link snapshot to the key type `K` of the table.
|
// Link snapshot to the key type `K` of the table.
|
||||||
marker: marker::CovariantType<K>,
|
marker: marker::CovariantType<K>,
|
||||||
snapshot: sv::Snapshot,
|
snapshot: sv::Snapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Internal type used to represent the result of a `get()` operation.
|
||||||
* Internal type used to represent the result of a `get()` operation.
|
/// Conveys the current root and value of the key.
|
||||||
* Conveys the current root and value of the key.
|
|
||||||
*/
|
|
||||||
pub struct Node<K,V> {
|
pub struct Node<K,V> {
|
||||||
pub key: K,
|
pub key: K,
|
||||||
pub value: V,
|
pub value: V,
|
||||||
|
@ -121,28 +104,22 @@ impl<'tcx, V:PartialEq+Clone+Repr<'tcx>, K:UnifyKey<'tcx, V>> UnificationTable<K
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Starts a new snapshot. Each snapshot must be either
|
||||||
* Starts a new snapshot. Each snapshot must be either
|
/// rolled back or committed in a "LIFO" (stack) order.
|
||||||
* rolled back or committed in a "LIFO" (stack) order.
|
|
||||||
*/
|
|
||||||
pub fn snapshot(&mut self) -> Snapshot<K> {
|
pub fn snapshot(&mut self) -> Snapshot<K> {
|
||||||
Snapshot { marker: marker::CovariantType::<K>,
|
Snapshot { marker: marker::CovariantType::<K>,
|
||||||
snapshot: self.values.start_snapshot() }
|
snapshot: self.values.start_snapshot() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Reverses all changes since the last snapshot. Also
|
||||||
* Reverses all changes since the last snapshot. Also
|
/// removes any keys that have been created since then.
|
||||||
* removes any keys that have been created since then.
|
|
||||||
*/
|
|
||||||
pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
|
pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
|
||||||
debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
|
debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
|
||||||
self.values.rollback_to(snapshot.snapshot);
|
self.values.rollback_to(snapshot.snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Commits all changes since the last snapshot. Of course, they
|
||||||
* Commits all changes since the last snapshot. Of course, they
|
/// can still be undone if there is a snapshot further out.
|
||||||
* can still be undone if there is a snapshot further out.
|
|
||||||
*/
|
|
||||||
pub fn commit(&mut self, snapshot: Snapshot<K>) {
|
pub fn commit(&mut self, snapshot: Snapshot<K>) {
|
||||||
debug!("{}: commit()", UnifyKey::tag(None::<K>));
|
debug!("{}: commit()", UnifyKey::tag(None::<K>));
|
||||||
self.values.commit(snapshot.snapshot);
|
self.values.commit(snapshot.snapshot);
|
||||||
|
@ -255,10 +232,8 @@ impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
|
||||||
// Code to handle simple keys like ints, floats---anything that
|
// Code to handle simple keys like ints, floats---anything that
|
||||||
// doesn't have a subtyping relationship we need to worry about.
|
// doesn't have a subtyping relationship we need to worry about.
|
||||||
|
|
||||||
/**
|
/// Indicates a type that does not have any kind of subtyping
|
||||||
* Indicates a type that does not have any kind of subtyping
|
/// relationship.
|
||||||
* relationship.
|
|
||||||
*/
|
|
||||||
pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> {
|
pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> {
|
||||||
fn to_type(&self) -> Ty<'tcx>;
|
fn to_type(&self) -> Ty<'tcx>;
|
||||||
fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
|
fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
|
||||||
|
|
|
@ -150,20 +150,18 @@ pub struct MethodCallee<'tcx> {
|
||||||
pub substs: subst::Substs<'tcx>
|
pub substs: subst::Substs<'tcx>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// With method calls, we store some extra information in
|
||||||
* With method calls, we store some extra information in
|
/// side tables (i.e method_map). We use
|
||||||
* side tables (i.e method_map). We use
|
/// MethodCall as a key to index into these tables instead of
|
||||||
* MethodCall as a key to index into these tables instead of
|
/// just directly using the expression's NodeId. The reason
|
||||||
* just directly using the expression's NodeId. The reason
|
/// for this being that we may apply adjustments (coercions)
|
||||||
* for this being that we may apply adjustments (coercions)
|
/// with the resulting expression also needing to use the
|
||||||
* with the resulting expression also needing to use the
|
/// side tables. The problem with this is that we don't
|
||||||
* side tables. The problem with this is that we don't
|
/// assign a separate NodeId to this new expression
|
||||||
* assign a separate NodeId to this new expression
|
/// and so it would clash with the base expression if both
|
||||||
* and so it would clash with the base expression if both
|
/// needed to add to the side tables. Thus to disambiguate
|
||||||
* needed to add to the side tables. Thus to disambiguate
|
/// we also keep track of whether there's an adjustment in
|
||||||
* we also keep track of whether there's an adjustment in
|
/// our key.
|
||||||
* our key.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct MethodCall {
|
pub struct MethodCall {
|
||||||
pub expr_id: ast::NodeId,
|
pub expr_id: ast::NodeId,
|
||||||
|
|
|
@ -219,18 +219,16 @@ pub fn infer_variance(tcx: &ty::ctxt) {
|
||||||
tcx.variance_computed.set(true);
|
tcx.variance_computed.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
// Representing terms
|
||||||
* Representing terms
|
//
|
||||||
*
|
// Terms are structured as a straightforward tree. Rather than rely on
|
||||||
* Terms are structured as a straightforward tree. Rather than rely on
|
// GC, we allocate terms out of a bounded arena (the lifetime of this
|
||||||
* GC, we allocate terms out of a bounded arena (the lifetime of this
|
// arena is the lifetime 'a that is threaded around).
|
||||||
* arena is the lifetime 'a that is threaded around).
|
//
|
||||||
*
|
// We assign a unique index to each type/region parameter whose variance
|
||||||
* We assign a unique index to each type/region parameter whose variance
|
// is to be inferred. We refer to such variables as "inferreds". An
|
||||||
* is to be inferred. We refer to such variables as "inferreds". An
|
// `InferredIndex` is a newtype'd int representing the index of such
|
||||||
* `InferredIndex` is a newtype'd int representing the index of such
|
// a variable.
|
||||||
* a variable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
|
type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
|
||||||
|
|
||||||
|
@ -253,9 +251,7 @@ impl<'a> fmt::Show for VarianceTerm<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
// The first pass over the crate simply builds up the set of inferreds.
|
||||||
* The first pass over the crate simply builds up the set of inferreds.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct TermsContext<'a, 'tcx: 'a> {
|
struct TermsContext<'a, 'tcx: 'a> {
|
||||||
tcx: &'a ty::ctxt<'tcx>,
|
tcx: &'a ty::ctxt<'tcx>,
|
||||||
|
@ -399,12 +395,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
// Constraint construction and representation
|
||||||
* Constraint construction and representation
|
//
|
||||||
*
|
// The second pass over the AST determines the set of constraints.
|
||||||
* The second pass over the AST determines the set of constraints.
|
// We walk the set of items and, for each member, generate new constraints.
|
||||||
* We walk the set of items and, for each member, generate new constraints.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct ConstraintContext<'a, 'tcx: 'a> {
|
struct ConstraintContext<'a, 'tcx: 'a> {
|
||||||
terms_cx: TermsContext<'a, 'tcx>,
|
terms_cx: TermsContext<'a, 'tcx>,
|
||||||
|
@ -944,14 +938,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
// Constraint solving
|
||||||
* Constraint solving
|
//
|
||||||
*
|
// The final phase iterates over the constraints, refining the variance
|
||||||
* The final phase iterates over the constraints, refining the variance
|
// for each inferred until a fixed point is reached. This will be the
|
||||||
* for each inferred until a fixed point is reached. This will be the
|
// optimal solution to the constraints. The final variance for each
|
||||||
* optimal solution to the constraints. The final variance for each
|
// inferred is then written into the `variance_map` in the tcx.
|
||||||
* inferred is then written into the `variance_map` in the tcx.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct SolveContext<'a, 'tcx: 'a> {
|
struct SolveContext<'a, 'tcx: 'a> {
|
||||||
terms_cx: TermsContext<'a, 'tcx>,
|
terms_cx: TermsContext<'a, 'tcx>,
|
||||||
|
@ -1086,9 +1078,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
// Miscellany transformations on variance
|
||||||
* Miscellany transformations on variance
|
|
||||||
*/
|
|
||||||
|
|
||||||
trait Xform {
|
trait Xform {
|
||||||
fn xform(self, v: Self) -> Self;
|
fn xform(self, v: Self) -> Self;
|
||||||
|
|
|
@ -177,10 +177,8 @@ impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
|
||||||
assert!(self.undo_log.len() == snapshot.length);
|
assert!(self.undo_log.len() == snapshot.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Commits all changes since the last snapshot. Of course, they
|
||||||
* Commits all changes since the last snapshot. Of course, they
|
/// can still be undone if there is a snapshot further out.
|
||||||
* can still be undone if there is a snapshot further out.
|
|
||||||
*/
|
|
||||||
pub fn commit(&mut self, snapshot: Snapshot) {
|
pub fn commit(&mut self, snapshot: Snapshot) {
|
||||||
debug!("commit({})", snapshot.length);
|
debug!("commit({})", snapshot.length);
|
||||||
|
|
||||||
|
|
|
@ -520,24 +520,24 @@ extern {
|
||||||
pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
|
pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
|
||||||
pub fn LLVMDisposeModule(M: ModuleRef);
|
pub fn LLVMDisposeModule(M: ModuleRef);
|
||||||
|
|
||||||
/** Data layout. See Module::getDataLayout. */
|
/// Data layout. See Module::getDataLayout.
|
||||||
pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
|
pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char;
|
||||||
pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
|
pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char);
|
||||||
|
|
||||||
/** Target triple. See Module::getTargetTriple. */
|
/// Target triple. See Module::getTargetTriple.
|
||||||
pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
|
pub fn LLVMGetTarget(M: ModuleRef) -> *const c_char;
|
||||||
pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
|
pub fn LLVMSetTarget(M: ModuleRef, Triple: *const c_char);
|
||||||
|
|
||||||
/** See Module::dump. */
|
/// See Module::dump.
|
||||||
pub fn LLVMDumpModule(M: ModuleRef);
|
pub fn LLVMDumpModule(M: ModuleRef);
|
||||||
|
|
||||||
/** See Module::setModuleInlineAsm. */
|
/// See Module::setModuleInlineAsm.
|
||||||
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
|
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
|
||||||
|
|
||||||
/** See llvm::LLVMTypeKind::getTypeID. */
|
/// See llvm::LLVMTypeKind::getTypeID.
|
||||||
pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
|
pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
|
||||||
|
|
||||||
/** See llvm::LLVMType::getContext. */
|
/// See llvm::LLVMType::getContext.
|
||||||
pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
|
pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
|
||||||
|
|
||||||
/* Operations on integer types */
|
/* Operations on integer types */
|
||||||
|
@ -1460,30 +1460,29 @@ extern {
|
||||||
pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
|
pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
|
||||||
pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
|
pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef;
|
||||||
|
|
||||||
/** Writes a module to the specified path. Returns 0 on success. */
|
/// Writes a module to the specified path. Returns 0 on success.
|
||||||
pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
|
pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int;
|
||||||
|
|
||||||
/** Creates target data from a target layout string. */
|
/// Creates target data from a target layout string.
|
||||||
pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
|
pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
|
||||||
/// Adds the target data to the given pass manager. The pass manager
|
/// Adds the target data to the given pass manager. The pass manager
|
||||||
/// references the target data only weakly.
|
/// references the target data only weakly.
|
||||||
pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
|
pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
|
||||||
/** Number of bytes clobbered when doing a Store to *T. */
|
/// Number of bytes clobbered when doing a Store to *T.
|
||||||
pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
|
pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
|
||||||
-> c_ulonglong;
|
-> c_ulonglong;
|
||||||
|
|
||||||
/** Number of bytes clobbered when doing a Store to *T. */
|
/// Number of bytes clobbered when doing a Store to *T.
|
||||||
pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
|
pub fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
|
||||||
-> c_ulonglong;
|
-> c_ulonglong;
|
||||||
|
|
||||||
/** Distance between successive elements in an array of T.
|
/// Distance between successive elements in an array of T. Includes ABI padding.
|
||||||
Includes ABI padding. */
|
|
||||||
pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
|
pub fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
|
||||||
|
|
||||||
/** Returns the preferred alignment of a type. */
|
/// Returns the preferred alignment of a type.
|
||||||
pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
pub fn LLVMPreferredAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
/** Returns the minimum alignment of a type. */
|
/// Returns the minimum alignment of a type.
|
||||||
pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
pub fn LLVMABIAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
|
|
||||||
|
@ -1494,41 +1493,39 @@ extern {
|
||||||
Element: c_uint)
|
Element: c_uint)
|
||||||
-> c_ulonglong;
|
-> c_ulonglong;
|
||||||
|
|
||||||
/**
|
/// Returns the minimum alignment of a type when part of a call frame.
|
||||||
* Returns the minimum alignment of a type when part of a call frame.
|
|
||||||
*/
|
|
||||||
pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
pub fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef, Ty: TypeRef)
|
||||||
-> c_uint;
|
-> c_uint;
|
||||||
|
|
||||||
/** Disposes target data. */
|
/// Disposes target data.
|
||||||
pub fn LLVMDisposeTargetData(TD: TargetDataRef);
|
pub fn LLVMDisposeTargetData(TD: TargetDataRef);
|
||||||
|
|
||||||
/** Creates a pass manager. */
|
/// Creates a pass manager.
|
||||||
pub fn LLVMCreatePassManager() -> PassManagerRef;
|
pub fn LLVMCreatePassManager() -> PassManagerRef;
|
||||||
|
|
||||||
/** Creates a function-by-function pass manager */
|
/// Creates a function-by-function pass manager
|
||||||
pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
|
pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef)
|
||||||
-> PassManagerRef;
|
-> PassManagerRef;
|
||||||
|
|
||||||
/** Disposes a pass manager. */
|
/// Disposes a pass manager.
|
||||||
pub fn LLVMDisposePassManager(PM: PassManagerRef);
|
pub fn LLVMDisposePassManager(PM: PassManagerRef);
|
||||||
|
|
||||||
/** Runs a pass manager on a module. */
|
/// Runs a pass manager on a module.
|
||||||
pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
|
pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
|
||||||
|
|
||||||
/** Runs the function passes on the provided function. */
|
/// Runs the function passes on the provided function.
|
||||||
pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
|
pub fn LLVMRunFunctionPassManager(FPM: PassManagerRef, F: ValueRef)
|
||||||
-> Bool;
|
-> Bool;
|
||||||
|
|
||||||
/** Initializes all the function passes scheduled in the manager */
|
/// Initializes all the function passes scheduled in the manager
|
||||||
pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
|
pub fn LLVMInitializeFunctionPassManager(FPM: PassManagerRef) -> Bool;
|
||||||
|
|
||||||
/** Finalizes all the function passes scheduled in the manager */
|
/// Finalizes all the function passes scheduled in the manager
|
||||||
pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
|
pub fn LLVMFinalizeFunctionPassManager(FPM: PassManagerRef) -> Bool;
|
||||||
|
|
||||||
pub fn LLVMInitializePasses();
|
pub fn LLVMInitializePasses();
|
||||||
|
|
||||||
/** Adds a verification pass. */
|
/// Adds a verification pass.
|
||||||
pub fn LLVMAddVerifierPass(PM: PassManagerRef);
|
pub fn LLVMAddVerifierPass(PM: PassManagerRef);
|
||||||
|
|
||||||
pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
|
pub fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
|
||||||
|
@ -1598,38 +1595,38 @@ extern {
|
||||||
Internalize: Bool,
|
Internalize: Bool,
|
||||||
RunInliner: Bool);
|
RunInliner: Bool);
|
||||||
|
|
||||||
/** Destroys a memory buffer. */
|
/// Destroys a memory buffer.
|
||||||
pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
|
pub fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
|
||||||
|
|
||||||
|
|
||||||
/* Stuff that's in rustllvm/ because it's not upstream yet. */
|
/* Stuff that's in rustllvm/ because it's not upstream yet. */
|
||||||
|
|
||||||
/** Opens an object file. */
|
/// Opens an object file.
|
||||||
pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
|
pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
|
||||||
/** Closes an object file. */
|
/// Closes an object file.
|
||||||
pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
|
pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
|
||||||
|
|
||||||
/** Enumerates the sections in an object file. */
|
/// Enumerates the sections in an object file.
|
||||||
pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
|
pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
|
||||||
/** Destroys a section iterator. */
|
/// Destroys a section iterator.
|
||||||
pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
|
pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
|
||||||
/** Returns true if the section iterator is at the end of the section
|
/// Returns true if the section iterator is at the end of the section
|
||||||
list: */
|
/// list:
|
||||||
pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
|
pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
|
||||||
SI: SectionIteratorRef)
|
SI: SectionIteratorRef)
|
||||||
-> Bool;
|
-> Bool;
|
||||||
/** Moves the section iterator to point to the next section. */
|
/// Moves the section iterator to point to the next section.
|
||||||
pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
|
pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
|
||||||
/** Returns the current section size. */
|
/// Returns the current section size.
|
||||||
pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
|
pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
|
||||||
/** Returns the current section contents as a string buffer. */
|
/// Returns the current section contents as a string buffer.
|
||||||
pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
|
pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char;
|
||||||
|
|
||||||
/** Reads the given file and returns it as a memory buffer. Use
|
/// Reads the given file and returns it as a memory buffer. Use
|
||||||
LLVMDisposeMemoryBuffer() to get rid of it. */
|
/// LLVMDisposeMemoryBuffer() to get rid of it.
|
||||||
pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
|
pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char)
|
||||||
-> MemoryBufferRef;
|
-> MemoryBufferRef;
|
||||||
/** Borrows the contents of the memory buffer (doesn't copy it) */
|
/// Borrows the contents of the memory buffer (doesn't copy it)
|
||||||
pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
|
pub fn LLVMCreateMemoryBufferWithMemoryRange(InputData: *const c_char,
|
||||||
InputDataLength: size_t,
|
InputDataLength: size_t,
|
||||||
BufferName: *const c_char,
|
BufferName: *const c_char,
|
||||||
|
@ -1643,8 +1640,7 @@ extern {
|
||||||
pub fn LLVMIsMultithreaded() -> Bool;
|
pub fn LLVMIsMultithreaded() -> Bool;
|
||||||
pub fn LLVMStartMultithreaded() -> Bool;
|
pub fn LLVMStartMultithreaded() -> Bool;
|
||||||
|
|
||||||
/** Returns a string describing the last error caused by an LLVMRust*
|
/// Returns a string describing the last error caused by an LLVMRust* call.
|
||||||
call. */
|
|
||||||
pub fn LLVMRustGetLastError() -> *const c_char;
|
pub fn LLVMRustGetLastError() -> *const c_char;
|
||||||
|
|
||||||
/// Print the pass timings since static dtors aren't picking them up.
|
/// Print the pass timings since static dtors aren't picking them up.
|
||||||
|
@ -1662,10 +1658,10 @@ extern {
|
||||||
Count: c_uint)
|
Count: c_uint)
|
||||||
-> ValueRef;
|
-> ValueRef;
|
||||||
|
|
||||||
/** Enables LLVM debug output. */
|
/// Enables LLVM debug output.
|
||||||
pub fn LLVMSetDebug(Enabled: c_int);
|
pub fn LLVMSetDebug(Enabled: c_int);
|
||||||
|
|
||||||
/** Prepares inline assembly. */
|
/// Prepares inline assembly.
|
||||||
pub fn LLVMInlineAsm(Ty: TypeRef,
|
pub fn LLVMInlineAsm(Ty: TypeRef,
|
||||||
AsmString: *const c_char,
|
AsmString: *const c_char,
|
||||||
Constraints: *const c_char,
|
Constraints: *const c_char,
|
||||||
|
|
|
@ -98,10 +98,8 @@ pub fn compile_input(sess: Session,
|
||||||
phase_6_link_output(&sess, &trans, &outputs);
|
phase_6_link_output(&sess, &trans, &outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The name used for source code that doesn't originate in a file
|
||||||
* The name used for source code that doesn't originate in a file
|
/// (e.g. source from stdin or a string)
|
||||||
* (e.g. source from stdin or a string)
|
|
||||||
*/
|
|
||||||
pub fn anon_src() -> String {
|
pub fn anon_src() -> String {
|
||||||
"<anon>".to_string()
|
"<anon>".to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,14 +325,13 @@ pub enum TransBindingMode {
|
||||||
TrByRef,
|
TrByRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Information about a pattern binding:
|
||||||
* Information about a pattern binding:
|
/// - `llmatch` is a pointer to a stack slot. The stack slot contains a
|
||||||
* - `llmatch` is a pointer to a stack slot. The stack slot contains a
|
/// pointer into the value being matched. Hence, llmatch has type `T**`
|
||||||
* pointer into the value being matched. Hence, llmatch has type `T**`
|
/// where `T` is the value being matched.
|
||||||
* where `T` is the value being matched.
|
/// - `trmode` is the trans binding mode
|
||||||
* - `trmode` is the trans binding mode
|
/// - `id` is the node id of the binding
|
||||||
* - `id` is the node id of the binding
|
/// - `ty` is the Rust type of the binding
|
||||||
* - `ty` is the Rust type of the binding */
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct BindingInfo<'tcx> {
|
pub struct BindingInfo<'tcx> {
|
||||||
pub llmatch: ValueRef,
|
pub llmatch: ValueRef,
|
||||||
|
@ -350,12 +349,10 @@ struct ArmData<'p, 'blk, 'tcx: 'blk> {
|
||||||
bindings_map: BindingsMap<'tcx>
|
bindings_map: BindingsMap<'tcx>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Info about Match.
|
||||||
* Info about Match.
|
/// If all `pats` are matched then arm `data` will be executed.
|
||||||
* If all `pats` are matched then arm `data` will be executed.
|
/// As we proceed `bound_ptrs` are filled with pointers to values to be bound,
|
||||||
* As we proceed `bound_ptrs` are filled with pointers to values to be bound,
|
/// these pointers are stored in llmatch variables just before executing `data` arm.
|
||||||
* these pointers are stored in llmatch variables just before executing `data` arm.
|
|
||||||
*/
|
|
||||||
struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
|
struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
|
||||||
pats: Vec<&'p ast::Pat>,
|
pats: Vec<&'p ast::Pat>,
|
||||||
data: &'a ArmData<'p, 'blk, 'tcx>,
|
data: &'a ArmData<'p, 'blk, 'tcx>,
|
||||||
|
|
|
@ -79,46 +79,38 @@ type Hint = attr::ReprAttr;
|
||||||
pub enum Repr<'tcx> {
|
pub enum Repr<'tcx> {
|
||||||
/// C-like enums; basically an int.
|
/// C-like enums; basically an int.
|
||||||
CEnum(IntType, Disr, Disr), // discriminant range (signedness based on the IntType)
|
CEnum(IntType, Disr, Disr), // discriminant range (signedness based on the IntType)
|
||||||
/**
|
/// Single-case variants, and structs/tuples/records.
|
||||||
* Single-case variants, and structs/tuples/records.
|
///
|
||||||
*
|
/// Structs with destructors need a dynamic destroyedness flag to
|
||||||
* Structs with destructors need a dynamic destroyedness flag to
|
/// avoid running the destructor too many times; this is included
|
||||||
* avoid running the destructor too many times; this is included
|
/// in the `Struct` if present.
|
||||||
* in the `Struct` if present.
|
|
||||||
*/
|
|
||||||
Univariant(Struct<'tcx>, bool),
|
Univariant(Struct<'tcx>, bool),
|
||||||
/**
|
/// General-case enums: for each case there is a struct, and they
|
||||||
* General-case enums: for each case there is a struct, and they
|
/// all start with a field for the discriminant.
|
||||||
* all start with a field for the discriminant.
|
///
|
||||||
*
|
/// Types with destructors need a dynamic destroyedness flag to
|
||||||
* Types with destructors need a dynamic destroyedness flag to
|
/// avoid running the destructor too many times; the last argument
|
||||||
* avoid running the destructor too many times; the last argument
|
/// indicates whether such a flag is present.
|
||||||
* indicates whether such a flag is present.
|
|
||||||
*/
|
|
||||||
General(IntType, Vec<Struct<'tcx>>, bool),
|
General(IntType, Vec<Struct<'tcx>>, bool),
|
||||||
/**
|
/// Two cases distinguished by a nullable pointer: the case with discriminant
|
||||||
* Two cases distinguished by a nullable pointer: the case with discriminant
|
/// `nndiscr` must have single field which is known to be nonnull due to its type.
|
||||||
* `nndiscr` must have single field which is known to be nonnull due to its type.
|
/// The other case is known to be zero sized. Hence we represent the enum
|
||||||
* The other case is known to be zero sized. Hence we represent the enum
|
/// as simply a nullable pointer: if not null it indicates the `nndiscr` variant,
|
||||||
* as simply a nullable pointer: if not null it indicates the `nndiscr` variant,
|
/// otherwise it indicates the other case.
|
||||||
* otherwise it indicates the other case.
|
|
||||||
*/
|
|
||||||
RawNullablePointer {
|
RawNullablePointer {
|
||||||
nndiscr: Disr,
|
nndiscr: Disr,
|
||||||
nnty: Ty<'tcx>,
|
nnty: Ty<'tcx>,
|
||||||
nullfields: Vec<Ty<'tcx>>
|
nullfields: Vec<Ty<'tcx>>
|
||||||
},
|
},
|
||||||
/**
|
/// Two cases distinguished by a nullable pointer: the case with discriminant
|
||||||
* Two cases distinguished by a nullable pointer: the case with discriminant
|
/// `nndiscr` is represented by the struct `nonnull`, where the `ptrfield`th
|
||||||
* `nndiscr` is represented by the struct `nonnull`, where the `ptrfield`th
|
/// field is known to be nonnull due to its type; if that field is null, then
|
||||||
* field is known to be nonnull due to its type; if that field is null, then
|
/// it represents the other case, which is inhabited by at most one value
|
||||||
* it represents the other case, which is inhabited by at most one value
|
/// (and all other fields are undefined/unused).
|
||||||
* (and all other fields are undefined/unused).
|
///
|
||||||
*
|
/// For example, `std::option::Option` instantiated at a safe pointer type
|
||||||
* For example, `std::option::Option` instantiated at a safe pointer type
|
/// is represented such that `None` is a null pointer and `Some` is the
|
||||||
* is represented such that `None` is a null pointer and `Some` is the
|
/// identity function.
|
||||||
* identity function.
|
|
||||||
*/
|
|
||||||
StructWrappedNullablePointer {
|
StructWrappedNullablePointer {
|
||||||
nonnull: Struct<'tcx>,
|
nonnull: Struct<'tcx>,
|
||||||
nndiscr: Disr,
|
nndiscr: Disr,
|
||||||
|
@ -139,11 +131,9 @@ pub struct Struct<'tcx> {
|
||||||
pub fields: Vec<Ty<'tcx>>
|
pub fields: Vec<Ty<'tcx>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Convenience for `represent_type`. There should probably be more or
|
||||||
* Convenience for `represent_type`. There should probably be more or
|
/// these, for places in trans where the `Ty` isn't directly
|
||||||
* these, for places in trans where the `Ty` isn't directly
|
/// available.
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
node: ast::NodeId) -> Rc<Repr<'tcx>> {
|
node: ast::NodeId) -> Rc<Repr<'tcx>> {
|
||||||
represent_type(bcx.ccx(), node_id_type(bcx, node))
|
represent_type(bcx.ccx(), node_id_type(bcx, node))
|
||||||
|
@ -514,16 +504,14 @@ fn ensure_enum_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/// LLVM-level types are a little complicated.
|
||||||
* LLVM-level types are a little complicated.
|
///
|
||||||
*
|
/// C-like enums need to be actual ints, not wrapped in a struct,
|
||||||
* C-like enums need to be actual ints, not wrapped in a struct,
|
/// because that changes the ABI on some platforms (see issue #10308).
|
||||||
* because that changes the ABI on some platforms (see issue #10308).
|
///
|
||||||
*
|
/// For nominal types, in some cases, we need to use LLVM named structs
|
||||||
* For nominal types, in some cases, we need to use LLVM named structs
|
/// and fill in the actual contents in a second pass to prevent
|
||||||
* and fill in the actual contents in a second pass to prevent
|
/// unbounded recursion; see also the comments in `trans::type_of`.
|
||||||
* unbounded recursion; see also the comments in `trans::type_of`.
|
|
||||||
*/
|
|
||||||
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>) -> Type {
|
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>) -> Type {
|
||||||
generic_type_of(cx, r, None, false, false)
|
generic_type_of(cx, r, None, false, false)
|
||||||
}
|
}
|
||||||
|
@ -620,12 +608,10 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Obtain a representation of the discriminant sufficient to translate
|
||||||
* Obtain a representation of the discriminant sufficient to translate
|
/// destructuring; this may or may not involve the actual discriminant.
|
||||||
* destructuring; this may or may not involve the actual discriminant.
|
///
|
||||||
*
|
/// This should ideally be less tightly tied to `_match`.
|
||||||
* This should ideally be less tightly tied to `_match`.
|
|
||||||
*/
|
|
||||||
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
r: &Repr<'tcx>, scrutinee: ValueRef)
|
r: &Repr<'tcx>, scrutinee: ValueRef)
|
||||||
-> (_match::BranchKind, Option<ValueRef>) {
|
-> (_match::BranchKind, Option<ValueRef>) {
|
||||||
|
@ -713,12 +699,10 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Yield information about how to dispatch a case of the
|
||||||
* Yield information about how to dispatch a case of the
|
/// discriminant-like value returned by `trans_switch`.
|
||||||
* discriminant-like value returned by `trans_switch`.
|
///
|
||||||
*
|
/// This should ideally be less tightly tied to `_match`.
|
||||||
* This should ideally be less tightly tied to `_match`.
|
|
||||||
*/
|
|
||||||
pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
|
pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
|
||||||
-> _match::OptResult<'blk, 'tcx> {
|
-> _match::OptResult<'blk, 'tcx> {
|
||||||
match *r {
|
match *r {
|
||||||
|
@ -741,10 +725,8 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Set the discriminant for a new value of the given case of the given
|
||||||
* Set the discriminant for a new value of the given case of the given
|
/// representation.
|
||||||
* representation.
|
|
||||||
*/
|
|
||||||
pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
|
pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
|
||||||
val: ValueRef, discr: Disr) {
|
val: ValueRef, discr: Disr) {
|
||||||
match *r {
|
match *r {
|
||||||
|
@ -799,10 +781,8 @@ fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The number of fields in a given case; for use when obtaining this
|
||||||
* The number of fields in a given case; for use when obtaining this
|
/// information from the type or definition is less convenient.
|
||||||
* information from the type or definition is less convenient.
|
|
||||||
*/
|
|
||||||
pub fn num_args(r: &Repr, discr: Disr) -> uint {
|
pub fn num_args(r: &Repr, discr: Disr) -> uint {
|
||||||
match *r {
|
match *r {
|
||||||
CEnum(..) => 0,
|
CEnum(..) => 0,
|
||||||
|
@ -946,27 +926,25 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Construct a constant value, suitable for initializing a
|
||||||
* Construct a constant value, suitable for initializing a
|
/// GlobalVariable, given a case and constant values for its fields.
|
||||||
* GlobalVariable, given a case and constant values for its fields.
|
/// Note that this may have a different LLVM type (and different
|
||||||
* Note that this may have a different LLVM type (and different
|
/// alignment!) from the representation's `type_of`, so it needs a
|
||||||
* alignment!) from the representation's `type_of`, so it needs a
|
/// pointer cast before use.
|
||||||
* pointer cast before use.
|
///
|
||||||
*
|
/// The LLVM type system does not directly support unions, and only
|
||||||
* The LLVM type system does not directly support unions, and only
|
/// pointers can be bitcast, so a constant (and, by extension, the
|
||||||
* pointers can be bitcast, so a constant (and, by extension, the
|
/// GlobalVariable initialized by it) will have a type that can vary
|
||||||
* GlobalVariable initialized by it) will have a type that can vary
|
/// depending on which case of an enum it is.
|
||||||
* depending on which case of an enum it is.
|
///
|
||||||
*
|
/// To understand the alignment situation, consider `enum E { V64(u64),
|
||||||
* To understand the alignment situation, consider `enum E { V64(u64),
|
/// V32(u32, u32) }` on Windows. The type has 8-byte alignment to
|
||||||
* V32(u32, u32) }` on Windows. The type has 8-byte alignment to
|
/// accommodate the u64, but `V32(x, y)` would have LLVM type `{i32,
|
||||||
* accommodate the u64, but `V32(x, y)` would have LLVM type `{i32,
|
/// i32, i32}`, which is 4-byte aligned.
|
||||||
* i32, i32}`, which is 4-byte aligned.
|
///
|
||||||
*
|
/// Currently the returned value has the same size as the type, but
|
||||||
* Currently the returned value has the same size as the type, but
|
/// this could be changed in the future to avoid allocating unnecessary
|
||||||
* this could be changed in the future to avoid allocating unnecessary
|
/// space after values of shorter-than-maximum cases.
|
||||||
* space after values of shorter-than-maximum cases.
|
|
||||||
*/
|
|
||||||
pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr: Disr,
|
pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr: Disr,
|
||||||
vals: &[ValueRef]) -> ValueRef {
|
vals: &[ValueRef]) -> ValueRef {
|
||||||
match *r {
|
match *r {
|
||||||
|
@ -1019,9 +997,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Compute struct field offsets relative to struct begin.
|
||||||
* Compute struct field offsets relative to struct begin.
|
|
||||||
*/
|
|
||||||
fn compute_struct_field_offsets<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
fn compute_struct_field_offsets<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
st: &Struct<'tcx>) -> Vec<u64> {
|
st: &Struct<'tcx>) -> Vec<u64> {
|
||||||
let mut offsets = vec!();
|
let mut offsets = vec!();
|
||||||
|
@ -1040,16 +1016,14 @@ fn compute_struct_field_offsets<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
offsets
|
offsets
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Building structs is a little complicated, because we might need to
|
||||||
* Building structs is a little complicated, because we might need to
|
/// insert padding if a field's value is less aligned than its type.
|
||||||
* insert padding if a field's value is less aligned than its type.
|
///
|
||||||
*
|
/// Continuing the example from `trans_const`, a value of type `(u32,
|
||||||
* Continuing the example from `trans_const`, a value of type `(u32,
|
/// E)` should have the `E` at offset 8, but if that field's
|
||||||
* E)` should have the `E` at offset 8, but if that field's
|
/// initializer is 4-byte aligned then simply translating the tuple as
|
||||||
* initializer is 4-byte aligned then simply translating the tuple as
|
/// a two-element struct will locate it at offset 4, and accesses to it
|
||||||
* a two-element struct will locate it at offset 4, and accesses to it
|
/// will read the wrong memory.
|
||||||
* will read the wrong memory.
|
|
||||||
*/
|
|
||||||
fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
st: &Struct<'tcx>, vals: &[ValueRef])
|
st: &Struct<'tcx>, vals: &[ValueRef])
|
||||||
-> Vec<ValueRef> {
|
-> Vec<ValueRef> {
|
||||||
|
@ -1130,13 +1104,11 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Extract a field of a constant value, as appropriate for its
|
||||||
* Extract a field of a constant value, as appropriate for its
|
/// representation.
|
||||||
* representation.
|
///
|
||||||
*
|
/// (Not to be confused with `common::const_get_elt`, which operates on
|
||||||
* (Not to be confused with `common::const_get_elt`, which operates on
|
/// raw LLVM-level structs and arrays.)
|
||||||
* raw LLVM-level structs and arrays.)
|
|
||||||
*/
|
|
||||||
pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
|
pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
|
||||||
_discr: Disr, ix: uint) -> ValueRef {
|
_discr: Disr, ix: uint) -> ValueRef {
|
||||||
match *r {
|
match *r {
|
||||||
|
|
|
@ -17,9 +17,7 @@ pub struct BasicBlock(pub BasicBlockRef);
|
||||||
|
|
||||||
pub type Preds<'a> = Map<'a, Value, BasicBlock, Filter<'a, Value, Users>>;
|
pub type Preds<'a> = Map<'a, Value, BasicBlock, Filter<'a, Value, Users>>;
|
||||||
|
|
||||||
/**
|
/// Wrapper for LLVM BasicBlockRef
|
||||||
* Wrapper for LLVM BasicBlockRef
|
|
||||||
*/
|
|
||||||
impl BasicBlock {
|
impl BasicBlock {
|
||||||
pub fn get(&self) -> BasicBlockRef {
|
pub fn get(&self) -> BasicBlockRef {
|
||||||
let BasicBlock(v) = *self; v
|
let BasicBlock(v) = *self; v
|
||||||
|
|
|
@ -31,12 +31,10 @@ use util::ppaux::{ty_to_string};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
/**
|
/// A `Datum` encapsulates the result of evaluating an expression. It
|
||||||
* A `Datum` encapsulates the result of evaluating an expression. It
|
/// describes where the value is stored, what Rust type the value has,
|
||||||
* describes where the value is stored, what Rust type the value has,
|
/// whether it is addressed by reference, and so forth. Please refer
|
||||||
* whether it is addressed by reference, and so forth. Please refer
|
/// the section on datums in `doc.rs` for more details.
|
||||||
* the section on datums in `doc.rs` for more details.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct Datum<'tcx, K> {
|
pub struct Datum<'tcx, K> {
|
||||||
/// The llvm value. This is either a pointer to the Rust value or
|
/// The llvm value. This is either a pointer to the Rust value or
|
||||||
|
@ -190,25 +188,19 @@ fn add_rvalue_clean<'a, 'tcx>(mode: RvalueMode,
|
||||||
|
|
||||||
pub trait KindOps {
|
pub trait KindOps {
|
||||||
|
|
||||||
/**
|
/// Take appropriate action after the value in `datum` has been
|
||||||
* Take appropriate action after the value in `datum` has been
|
/// stored to a new location.
|
||||||
* stored to a new location.
|
|
||||||
*/
|
|
||||||
fn post_store<'blk, 'tcx>(&self,
|
fn post_store<'blk, 'tcx>(&self,
|
||||||
bcx: Block<'blk, 'tcx>,
|
bcx: Block<'blk, 'tcx>,
|
||||||
val: ValueRef,
|
val: ValueRef,
|
||||||
ty: Ty<'tcx>)
|
ty: Ty<'tcx>)
|
||||||
-> Block<'blk, 'tcx>;
|
-> Block<'blk, 'tcx>;
|
||||||
|
|
||||||
/**
|
/// True if this mode is a reference mode, meaning that the datum's
|
||||||
* True if this mode is a reference mode, meaning that the datum's
|
/// val field is a pointer to the actual value
|
||||||
* val field is a pointer to the actual value
|
|
||||||
*/
|
|
||||||
fn is_by_ref(&self) -> bool;
|
fn is_by_ref(&self) -> bool;
|
||||||
|
|
||||||
/**
|
/// Converts to an Expr kind
|
||||||
* Converts to an Expr kind
|
|
||||||
*/
|
|
||||||
fn to_expr_kind(self) -> Expr;
|
fn to_expr_kind(self) -> Expr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -361,14 +353,12 @@ impl<'tcx> Datum<'tcx, Rvalue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Methods suitable for "expr" datums that could be either lvalues or
|
||||||
* Methods suitable for "expr" datums that could be either lvalues or
|
/// rvalues. These include coercions into lvalues/rvalues but also a number
|
||||||
* rvalues. These include coercions into lvalues/rvalues but also a number
|
/// of more general operations. (Some of those operations could be moved to
|
||||||
* of more general operations. (Some of those operations could be moved to
|
/// the more general `impl<K> Datum<K>`, but it's convenient to have them
|
||||||
* the more general `impl<K> Datum<K>`, but it's convenient to have them
|
/// here since we can `match self.kind` rather than having to implement
|
||||||
* here since we can `match self.kind` rather than having to implement
|
/// generic methods in `KindOps`.)
|
||||||
* generic methods in `KindOps`.)
|
|
||||||
*/
|
|
||||||
impl<'tcx> Datum<'tcx, Expr> {
|
impl<'tcx> Datum<'tcx, Expr> {
|
||||||
fn match_kind<R>(self,
|
fn match_kind<R>(self,
|
||||||
if_lvalue: |Datum<'tcx, Lvalue>| -> R,
|
if_lvalue: |Datum<'tcx, Lvalue>| -> R,
|
||||||
|
@ -494,12 +484,10 @@ impl<'tcx> Datum<'tcx, Expr> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Methods suitable only for lvalues. These include the various
|
||||||
* Methods suitable only for lvalues. These include the various
|
/// operations to extract components out of compound data structures,
|
||||||
* operations to extract components out of compound data structures,
|
/// such as extracting the field from a struct or a particular element
|
||||||
* such as extracting the field from a struct or a particular element
|
/// from an array.
|
||||||
* from an array.
|
|
||||||
*/
|
|
||||||
impl<'tcx> Datum<'tcx, Lvalue> {
|
impl<'tcx> Datum<'tcx, Lvalue> {
|
||||||
pub fn to_llref(self) -> ValueRef {
|
pub fn to_llref(self) -> ValueRef {
|
||||||
/*!
|
/*!
|
||||||
|
@ -542,9 +530,7 @@ impl<'tcx> Datum<'tcx, Lvalue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Generic methods applicable to any sort of datum.
|
||||||
* Generic methods applicable to any sort of datum.
|
|
||||||
*/
|
|
||||||
impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
|
impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
|
||||||
pub fn new(val: ValueRef, ty: Ty<'tcx>, kind: K) -> Datum<'tcx, K> {
|
pub fn new(val: ValueRef, ty: Ty<'tcx>, kind: K) -> Datum<'tcx, K> {
|
||||||
Datum { val: val, ty: ty, kind: kind }
|
Datum { val: val, ty: ty, kind: kind }
|
||||||
|
|
|
@ -1377,14 +1377,12 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Information that `trans_adt` needs in order to fill in the fields
|
||||||
* Information that `trans_adt` needs in order to fill in the fields
|
/// of a struct copied from a base struct (e.g., from an expression
|
||||||
* of a struct copied from a base struct (e.g., from an expression
|
/// like `Foo { a: b, ..base }`.
|
||||||
* like `Foo { a: b, ..base }`.
|
///
|
||||||
*
|
/// Note that `fields` may be empty; the base expression must always be
|
||||||
* Note that `fields` may be empty; the base expression must always be
|
/// evaluated for side-effects.
|
||||||
* evaluated for side-effects.
|
|
||||||
*/
|
|
||||||
pub struct StructBaseInfo<'a, 'tcx> {
|
pub struct StructBaseInfo<'a, 'tcx> {
|
||||||
/// The base expression; will be evaluated after all explicit fields.
|
/// The base expression; will be evaluated after all explicit fields.
|
||||||
expr: &'a ast::Expr,
|
expr: &'a ast::Expr,
|
||||||
|
@ -1392,16 +1390,14 @@ pub struct StructBaseInfo<'a, 'tcx> {
|
||||||
fields: Vec<(uint, Ty<'tcx>)>
|
fields: Vec<(uint, Ty<'tcx>)>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Constructs an ADT instance:
|
||||||
* Constructs an ADT instance:
|
///
|
||||||
*
|
/// - `fields` should be a list of field indices paired with the
|
||||||
* - `fields` should be a list of field indices paired with the
|
/// expression to store into that field. The initializers will be
|
||||||
* expression to store into that field. The initializers will be
|
/// evaluated in the order specified by `fields`.
|
||||||
* evaluated in the order specified by `fields`.
|
///
|
||||||
*
|
/// - `optbase` contains information on the base struct (if any) from
|
||||||
* - `optbase` contains information on the base struct (if any) from
|
/// which remaining fields are copied; see comments on `StructBaseInfo`.
|
||||||
* which remaining fields are copied; see comments on `StructBaseInfo`.
|
|
||||||
*/
|
|
||||||
pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
discr: ty::Disr,
|
discr: ty::Disr,
|
||||||
|
|
|
@ -46,12 +46,10 @@ use syntax::codemap::DUMMY_SP;
|
||||||
// drop_glue pointer, size, align.
|
// drop_glue pointer, size, align.
|
||||||
static VTABLE_OFFSET: uint = 3;
|
static VTABLE_OFFSET: uint = 3;
|
||||||
|
|
||||||
/**
|
/// The main "translation" pass for methods. Generates code
|
||||||
The main "translation" pass for methods. Generates code
|
/// for non-monomorphized methods only. Other methods will
|
||||||
for non-monomorphized methods only. Other methods will
|
/// be generated once they are invoked with specific type parameters,
|
||||||
be generated once they are invoked with specific type parameters,
|
/// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
|
||||||
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
|
|
||||||
*/
|
|
||||||
pub fn trans_impl(ccx: &CrateContext,
|
pub fn trans_impl(ccx: &CrateContext,
|
||||||
name: ast::Ident,
|
name: ast::Ident,
|
||||||
impl_items: &[ast::ImplItem],
|
impl_items: &[ast::ImplItem],
|
||||||
|
|
|
@ -35,9 +35,7 @@ macro_rules! ty (
|
||||||
($e:expr) => ( Type::from_ref(unsafe { $e }))
|
($e:expr) => ( Type::from_ref(unsafe { $e }))
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/// Wrapper for LLVM TypeRef
|
||||||
* Wrapper for LLVM TypeRef
|
|
||||||
*/
|
|
||||||
impl Type {
|
impl Type {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_ref(r: TypeRef) -> Type {
|
pub fn from_ref(r: TypeRef) -> Type {
|
||||||
|
|
|
@ -25,9 +25,7 @@ macro_rules! opt_val ( ($e:expr) => (
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
||||||
/**
|
/// Wrapper for LLVM ValueRef
|
||||||
* Wrapper for LLVM ValueRef
|
|
||||||
*/
|
|
||||||
impl Value {
|
impl Value {
|
||||||
/// Returns the native ValueRef
|
/// Returns the native ValueRef
|
||||||
pub fn get(&self) -> ValueRef {
|
pub fn get(&self) -> ValueRef {
|
||||||
|
@ -127,9 +125,7 @@ impl Value {
|
||||||
|
|
||||||
pub struct Use(UseRef);
|
pub struct Use(UseRef);
|
||||||
|
|
||||||
/**
|
/// Wrapper for LLVM UseRef
|
||||||
* Wrapper for LLVM UseRef
|
|
||||||
*/
|
|
||||||
impl Use {
|
impl Use {
|
||||||
pub fn get(&self) -> UseRef {
|
pub fn get(&self) -> UseRef {
|
||||||
let Use(v) = *self; v
|
let Use(v) = *self; v
|
||||||
|
|
|
@ -64,21 +64,19 @@ pub trait ToBase64 for Sized? {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToBase64 for [u8] {
|
impl ToBase64 for [u8] {
|
||||||
/**
|
/// Turn a vector of `u8` bytes into a base64 string.
|
||||||
* Turn a vector of `u8` bytes into a base64 string.
|
///
|
||||||
*
|
/// # Example
|
||||||
* # Example
|
///
|
||||||
*
|
/// ```rust
|
||||||
* ```rust
|
/// extern crate serialize;
|
||||||
* extern crate serialize;
|
/// use serialize::base64::{ToBase64, STANDARD};
|
||||||
* use serialize::base64::{ToBase64, STANDARD};
|
///
|
||||||
*
|
/// fn main () {
|
||||||
* fn main () {
|
/// let str = [52,32].to_base64(STANDARD);
|
||||||
* let str = [52,32].to_base64(STANDARD);
|
/// println!("base 64 output: {}", str);
|
||||||
* println!("base 64 output: {}", str);
|
/// }
|
||||||
* }
|
/// ```
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
fn to_base64(&self, config: Config) -> String {
|
fn to_base64(&self, config: Config) -> String {
|
||||||
let bytes = match config.char_set {
|
let bytes = match config.char_set {
|
||||||
Standard => STANDARD_CHARS,
|
Standard => STANDARD_CHARS,
|
||||||
|
@ -194,34 +192,32 @@ impl error::Error for FromBase64Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromBase64 for str {
|
impl FromBase64 for str {
|
||||||
/**
|
/// Convert any base64 encoded string (literal, `@`, `&`, or `~`)
|
||||||
* Convert any base64 encoded string (literal, `@`, `&`, or `~`)
|
/// to the byte values it encodes.
|
||||||
* to the byte values it encodes.
|
///
|
||||||
*
|
/// You can use the `String::from_utf8` function to turn a `Vec<u8>` into a
|
||||||
* You can use the `String::from_utf8` function to turn a `Vec<u8>` into a
|
/// string with characters corresponding to those values.
|
||||||
* string with characters corresponding to those values.
|
///
|
||||||
*
|
/// # Example
|
||||||
* # Example
|
///
|
||||||
*
|
/// This converts a string literal to base64 and back.
|
||||||
* This converts a string literal to base64 and back.
|
///
|
||||||
*
|
/// ```rust
|
||||||
* ```rust
|
/// extern crate serialize;
|
||||||
* extern crate serialize;
|
/// use serialize::base64::{ToBase64, FromBase64, STANDARD};
|
||||||
* use serialize::base64::{ToBase64, FromBase64, STANDARD};
|
///
|
||||||
*
|
/// fn main () {
|
||||||
* fn main () {
|
/// let hello_str = b"Hello, World".to_base64(STANDARD);
|
||||||
* let hello_str = b"Hello, World".to_base64(STANDARD);
|
/// println!("base64 output: {}", hello_str);
|
||||||
* println!("base64 output: {}", hello_str);
|
/// let res = hello_str.as_slice().from_base64();
|
||||||
* let res = hello_str.as_slice().from_base64();
|
/// if res.is_ok() {
|
||||||
* if res.is_ok() {
|
/// let opt_bytes = String::from_utf8(res.unwrap());
|
||||||
* let opt_bytes = String::from_utf8(res.unwrap());
|
/// if opt_bytes.is_ok() {
|
||||||
* if opt_bytes.is_ok() {
|
/// println!("decoded from base64: {}", opt_bytes.unwrap());
|
||||||
* println!("decoded from base64: {}", opt_bytes.unwrap());
|
/// }
|
||||||
* }
|
/// }
|
||||||
* }
|
/// }
|
||||||
* }
|
/// ```
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
|
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
|
||||||
self.as_bytes().from_base64()
|
self.as_bytes().from_base64()
|
||||||
|
|
|
@ -27,21 +27,19 @@ pub trait ToHex for Sized? {
|
||||||
static CHARS: &'static[u8] = b"0123456789abcdef";
|
static CHARS: &'static[u8] = b"0123456789abcdef";
|
||||||
|
|
||||||
impl ToHex for [u8] {
|
impl ToHex for [u8] {
|
||||||
/**
|
/// Turn a vector of `u8` bytes into a hexadecimal string.
|
||||||
* Turn a vector of `u8` bytes into a hexadecimal string.
|
///
|
||||||
*
|
/// # Example
|
||||||
* # Example
|
///
|
||||||
*
|
/// ```rust
|
||||||
* ```rust
|
/// extern crate serialize;
|
||||||
* extern crate serialize;
|
/// use serialize::hex::ToHex;
|
||||||
* use serialize::hex::ToHex;
|
///
|
||||||
*
|
/// fn main () {
|
||||||
* fn main () {
|
/// let str = [52,32].to_hex();
|
||||||
* let str = [52,32].to_hex();
|
/// println!("{}", str);
|
||||||
* println!("{}", str);
|
/// }
|
||||||
* }
|
/// ```
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
fn to_hex(&self) -> String {
|
fn to_hex(&self) -> String {
|
||||||
let mut v = Vec::with_capacity(self.len() * 2);
|
let mut v = Vec::with_capacity(self.len() * 2);
|
||||||
for &byte in self.iter() {
|
for &byte in self.iter() {
|
||||||
|
@ -95,31 +93,29 @@ impl error::Error for FromHexError {
|
||||||
|
|
||||||
|
|
||||||
impl FromHex for str {
|
impl FromHex for str {
|
||||||
/**
|
/// Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
|
||||||
* Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
|
/// to the byte values it encodes.
|
||||||
* to the byte values it encodes.
|
///
|
||||||
*
|
/// You can use the `String::from_utf8` function to turn a
|
||||||
* You can use the `String::from_utf8` function to turn a
|
/// `Vec<u8>` into a string with characters corresponding to those values.
|
||||||
* `Vec<u8>` into a string with characters corresponding to those values.
|
///
|
||||||
*
|
/// # Example
|
||||||
* # Example
|
///
|
||||||
*
|
/// This converts a string literal to hexadecimal and back.
|
||||||
* This converts a string literal to hexadecimal and back.
|
///
|
||||||
*
|
/// ```rust
|
||||||
* ```rust
|
/// extern crate serialize;
|
||||||
* extern crate serialize;
|
/// use serialize::hex::{FromHex, ToHex};
|
||||||
* use serialize::hex::{FromHex, ToHex};
|
///
|
||||||
*
|
/// fn main () {
|
||||||
* fn main () {
|
/// let hello_str = "Hello, World".as_bytes().to_hex();
|
||||||
* let hello_str = "Hello, World".as_bytes().to_hex();
|
/// println!("{}", hello_str);
|
||||||
* println!("{}", hello_str);
|
/// let bytes = hello_str.as_slice().from_hex().unwrap();
|
||||||
* let bytes = hello_str.as_slice().from_hex().unwrap();
|
/// println!("{}", bytes);
|
||||||
* println!("{}", bytes);
|
/// let result_str = String::from_utf8(bytes).unwrap();
|
||||||
* let result_str = String::from_utf8(bytes).unwrap();
|
/// println!("{}", result_str);
|
||||||
* println!("{}", result_str);
|
/// }
|
||||||
* }
|
/// ```
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
|
fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
|
||||||
// This may be an overestimate if there is any whitespace
|
// This may be an overestimate if there is any whitespace
|
||||||
let mut b = Vec::with_capacity(self.len() / 2);
|
let mut b = Vec::with_capacity(self.len() / 2);
|
||||||
|
|
|
@ -67,31 +67,32 @@ pub enum SignFormat {
|
||||||
SignAll,
|
SignAll,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Converts an integral number to its string representation as a byte vector.
|
||||||
* Converts an integral number to its string representation as a byte vector.
|
/// This is meant to be a common base implementation for all integral string
|
||||||
* This is meant to be a common base implementation for all integral string
|
/// conversion functions like `to_string()` or `to_str_radix()`.
|
||||||
* conversion functions like `to_string()` or `to_str_radix()`.
|
///
|
||||||
*
|
/// # Arguments
|
||||||
* # Arguments
|
///
|
||||||
* - `num` - The number to convert. Accepts any number that
|
/// - `num` - The number to convert. Accepts any number that
|
||||||
* implements the numeric traits.
|
/// implements the numeric traits.
|
||||||
* - `radix` - Base to use. Accepts only the values 2-36.
|
/// - `radix` - Base to use. Accepts only the values 2-36.
|
||||||
* - `sign` - How to emit the sign. Options are:
|
/// - `sign` - How to emit the sign. Options are:
|
||||||
* - `SignNone`: No sign at all. Basically emits `abs(num)`.
|
/// - `SignNone`: No sign at all. Basically emits `abs(num)`.
|
||||||
* - `SignNeg`: Only `-` on negative values.
|
/// - `SignNeg`: Only `-` on negative values.
|
||||||
* - `SignAll`: Both `+` on positive, and `-` on negative numbers.
|
/// - `SignAll`: Both `+` on positive, and `-` on negative numbers.
|
||||||
* - `f` - a callback which will be invoked for each ascii character
|
/// - `f` - a callback which will be invoked for each ascii character
|
||||||
* which composes the string representation of this integer
|
/// which composes the string representation of this integer
|
||||||
*
|
///
|
||||||
* # Return value
|
/// # Return value
|
||||||
* A tuple containing the byte vector, and a boolean flag indicating
|
///
|
||||||
* whether it represents a special value like `inf`, `-inf`, `NaN` or not.
|
/// A tuple containing the byte vector, and a boolean flag indicating
|
||||||
* It returns a tuple because there can be ambiguity between a special value
|
/// whether it represents a special value like `inf`, `-inf`, `NaN` or not.
|
||||||
* and a number representation at higher bases.
|
/// It returns a tuple because there can be ambiguity between a special value
|
||||||
*
|
/// and a number representation at higher bases.
|
||||||
* # Panics
|
///
|
||||||
* - Panics if `radix` < 2 or `radix` > 36.
|
/// # Panics
|
||||||
*/
|
///
|
||||||
|
/// - Panics if `radix` < 2 or `radix` > 36.
|
||||||
fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
|
fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
|
||||||
assert!(2 <= radix && radix <= 36);
|
assert!(2 <= radix && radix <= 36);
|
||||||
|
|
||||||
|
|
|
@ -788,18 +788,16 @@ pub fn homedir() -> Option<Path> {
|
||||||
_homedir()
|
_homedir()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns the path to a temporary directory.
|
||||||
* Returns the path to a temporary directory.
|
///
|
||||||
*
|
/// On Unix, returns the value of the 'TMPDIR' environment variable if it is
|
||||||
* On Unix, returns the value of the 'TMPDIR' environment variable if it is
|
/// set, otherwise for non-Android it returns '/tmp'. If Android, since there
|
||||||
* set, otherwise for non-Android it returns '/tmp'. If Android, since there
|
/// is no global temporary folder (it is usually allocated per-app), we return
|
||||||
* is no global temporary folder (it is usually allocated per-app), we return
|
/// '/data/local/tmp'.
|
||||||
* '/data/local/tmp'.
|
///
|
||||||
*
|
/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
||||||
* On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
/// 'USERPROFILE' environment variable if any are set and not the empty
|
||||||
* 'USERPROFILE' environment variable if any are set and not the empty
|
/// string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||||
* string. Otherwise, tmpdir returns the path to the Windows directory.
|
|
||||||
*/
|
|
||||||
pub fn tmpdir() -> Path {
|
pub fn tmpdir() -> Path {
|
||||||
return lookup();
|
return lookup();
|
||||||
|
|
||||||
|
@ -933,16 +931,14 @@ pub fn last_os_error() -> String {
|
||||||
|
|
||||||
static EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT;
|
static EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT;
|
||||||
|
|
||||||
/**
|
/// Sets the process exit code
|
||||||
* Sets the process exit code
|
///
|
||||||
*
|
/// Sets the exit code returned by the process if all supervised tasks
|
||||||
* Sets the exit code returned by the process if all supervised tasks
|
/// terminate successfully (without panicking). If the current root task panics
|
||||||
* terminate successfully (without panicking). If the current root task panics
|
/// and is supervised by the scheduler then any user-specified exit status is
|
||||||
* and is supervised by the scheduler then any user-specified exit status is
|
/// ignored and the process exits with the default panic status.
|
||||||
* ignored and the process exits with the default panic status.
|
///
|
||||||
*
|
/// Note that this is not synchronized against modifications of other threads.
|
||||||
* Note that this is not synchronized against modifications of other threads.
|
|
||||||
*/
|
|
||||||
pub fn set_exit_status(code: int) {
|
pub fn set_exit_status(code: int) {
|
||||||
EXIT_STATUS.store(code, SeqCst)
|
EXIT_STATUS.store(code, SeqCst)
|
||||||
}
|
}
|
||||||
|
@ -963,11 +959,9 @@ unsafe fn load_argc_and_argv(argc: int,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns the command line arguments
|
||||||
* Returns the command line arguments
|
///
|
||||||
*
|
/// Returns a list of the command line arguments.
|
||||||
* Returns a list of the command line arguments.
|
|
||||||
*/
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn real_args_as_bytes() -> Vec<Vec<u8>> {
|
fn real_args_as_bytes() -> Vec<Vec<u8>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -29,9 +29,7 @@ use rustrt::task::Task;
|
||||||
|
|
||||||
use super::raw;
|
use super::raw;
|
||||||
|
|
||||||
/****************************************************************************
|
// Poisoning helpers
|
||||||
* Poisoning helpers
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
struct PoisonOnFail<'a> {
|
struct PoisonOnFail<'a> {
|
||||||
flag: &'a mut bool,
|
flag: &'a mut bool,
|
||||||
|
@ -67,9 +65,7 @@ impl<'a> Drop for PoisonOnFail<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
// Condvar
|
||||||
* Condvar
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
enum Inner<'a> {
|
enum Inner<'a> {
|
||||||
InnerMutex(raw::MutexGuard<'a>),
|
InnerMutex(raw::MutexGuard<'a>),
|
||||||
|
@ -147,10 +143,6 @@ impl<'a> Condvar<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Mutex
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/// A wrapper type which provides synchronized access to the underlying data, of
|
/// A wrapper type which provides synchronized access to the underlying data, of
|
||||||
/// type `T`. A mutex always provides exclusive access, and concurrent requests
|
/// type `T`. A mutex always provides exclusive access, and concurrent requests
|
||||||
/// will block while the mutex is already locked.
|
/// will block while the mutex is already locked.
|
||||||
|
@ -249,10 +241,6 @@ impl<'a, T: Send> DerefMut<T> for MutexGuard<'a, T> {
|
||||||
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* R/W lock protected lock
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/// A dual-mode reader-writer lock. The data can be accessed mutably or
|
/// A dual-mode reader-writer lock. The data can be accessed mutably or
|
||||||
/// immutably, and immutably-accessing tasks may run concurrently.
|
/// immutably, and immutably-accessing tasks may run concurrently.
|
||||||
///
|
///
|
||||||
|
@ -387,10 +375,6 @@ impl<'a, T: Send + Sync> DerefMut<T> for RWLockWriteGuard<'a, T> {
|
||||||
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Barrier
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/// A barrier enables multiple tasks to synchronize the beginning
|
/// A barrier enables multiple tasks to synchronize the beginning
|
||||||
/// of some computation.
|
/// of some computation.
|
||||||
///
|
///
|
||||||
|
@ -452,10 +436,6 @@ impl Barrier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Tests
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
@ -795,9 +775,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Barrier tests
|
|
||||||
************************************************************************/
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_barrier() {
|
fn test_barrier() {
|
||||||
let barrier = Arc::new(Barrier::new(10));
|
let barrier = Arc::new(Barrier::new(10));
|
||||||
|
|
|
@ -32,10 +32,6 @@ use vec::Vec;
|
||||||
use super::mutex;
|
use super::mutex;
|
||||||
use comm::{Receiver, Sender, channel};
|
use comm::{Receiver, Sender, channel};
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Internals
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
// Each waiting task receives on one of these.
|
// Each waiting task receives on one of these.
|
||||||
type WaitEnd = Receiver<()>;
|
type WaitEnd = Receiver<()>;
|
||||||
type SignalEnd = Sender<()>;
|
type SignalEnd = Sender<()>;
|
||||||
|
@ -353,10 +349,6 @@ struct SemCondGuard<'a> {
|
||||||
cvar: Condvar<'a>,
|
cvar: Condvar<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Semaphores
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/// A counting, blocking, bounded-waiting semaphore.
|
/// A counting, blocking, bounded-waiting semaphore.
|
||||||
pub struct Semaphore {
|
pub struct Semaphore {
|
||||||
sem: Sem<()>,
|
sem: Sem<()>,
|
||||||
|
@ -394,10 +386,6 @@ impl Semaphore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Mutexes
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/// A blocking, bounded-waiting, mutual exclusion lock with an associated
|
/// A blocking, bounded-waiting, mutual exclusion lock with an associated
|
||||||
/// FIFO condition variable.
|
/// FIFO condition variable.
|
||||||
///
|
///
|
||||||
|
@ -441,10 +429,6 @@ impl Mutex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Reader-writer locks
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
// NB: Wikipedia - Readers-writers_problem#The_third_readers-writers_problem
|
// NB: Wikipedia - Readers-writers_problem#The_third_readers-writers_problem
|
||||||
|
|
||||||
/// A blocking, no-starvation, reader-writer lock with an associated condvar.
|
/// A blocking, no-starvation, reader-writer lock with an associated condvar.
|
||||||
|
@ -618,10 +602,6 @@ impl<'a> Drop for RWLockReadGuard<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Tests
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
pub use self::RWLockMode::*;
|
pub use self::RWLockMode::*;
|
||||||
|
@ -634,9 +614,6 @@ mod tests {
|
||||||
use result;
|
use result;
|
||||||
use task;
|
use task;
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* Semaphore tests
|
|
||||||
************************************************************************/
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_acquire_release() {
|
fn test_sem_acquire_release() {
|
||||||
let s = Semaphore::new(1);
|
let s = Semaphore::new(1);
|
||||||
|
@ -644,16 +621,19 @@ mod tests {
|
||||||
s.release();
|
s.release();
|
||||||
s.acquire();
|
s.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_basic() {
|
fn test_sem_basic() {
|
||||||
let s = Semaphore::new(1);
|
let s = Semaphore::new(1);
|
||||||
let _g = s.access();
|
let _g = s.access();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn test_sem_basic2() {
|
fn test_sem_basic2() {
|
||||||
Semaphore::new(-1);
|
Semaphore::new(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_as_mutex() {
|
fn test_sem_as_mutex() {
|
||||||
let s = Arc::new(Semaphore::new(1));
|
let s = Arc::new(Semaphore::new(1));
|
||||||
|
@ -665,6 +645,7 @@ mod tests {
|
||||||
let _g = s.access();
|
let _g = s.access();
|
||||||
for _ in range(0u, 5) { task::deschedule(); }
|
for _ in range(0u, 5) { task::deschedule(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_as_cvar() {
|
fn test_sem_as_cvar() {
|
||||||
/* Child waits and parent signals */
|
/* Child waits and parent signals */
|
||||||
|
@ -691,6 +672,7 @@ mod tests {
|
||||||
s.acquire();
|
s.acquire();
|
||||||
tx.send(());
|
tx.send(());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_multi_resource() {
|
fn test_sem_multi_resource() {
|
||||||
// Parent and child both get in the critical section at the same
|
// Parent and child both get in the critical section at the same
|
||||||
|
@ -708,6 +690,7 @@ mod tests {
|
||||||
tx2.send(());
|
tx2.send(());
|
||||||
let _ = rx1.recv();
|
let _ = rx1.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sem_runtime_friendly_blocking() {
|
fn test_sem_runtime_friendly_blocking() {
|
||||||
// Force the runtime to schedule two threads on the same sched_loop.
|
// Force the runtime to schedule two threads on the same sched_loop.
|
||||||
|
@ -727,9 +710,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
rx.recv(); // wait for child to be done
|
rx.recv(); // wait for child to be done
|
||||||
}
|
}
|
||||||
/************************************************************************
|
|
||||||
* Mutex tests
|
|
||||||
************************************************************************/
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_lock() {
|
fn test_mutex_lock() {
|
||||||
// Unsafely achieve shared state, and do the textbook
|
// Unsafely achieve shared state, and do the textbook
|
||||||
|
@ -761,6 +742,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_cond_wait() {
|
fn test_mutex_cond_wait() {
|
||||||
let m = Arc::new(Mutex::new());
|
let m = Arc::new(Mutex::new());
|
||||||
|
@ -820,14 +802,17 @@ mod tests {
|
||||||
// wait until all children wake up
|
// wait until all children wake up
|
||||||
for rx in rxs.iter_mut() { rx.recv(); }
|
for rx in rxs.iter_mut() { rx.recv(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_cond_broadcast() {
|
fn test_mutex_cond_broadcast() {
|
||||||
test_mutex_cond_broadcast_helper(12);
|
test_mutex_cond_broadcast_helper(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_cond_broadcast_none() {
|
fn test_mutex_cond_broadcast_none() {
|
||||||
test_mutex_cond_broadcast_helper(0);
|
test_mutex_cond_broadcast_helper(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_cond_no_waiter() {
|
fn test_mutex_cond_no_waiter() {
|
||||||
let m = Arc::new(Mutex::new());
|
let m = Arc::new(Mutex::new());
|
||||||
|
@ -838,6 +823,7 @@ mod tests {
|
||||||
let lock = m2.lock();
|
let lock = m2.lock();
|
||||||
assert!(!lock.cond.signal());
|
assert!(!lock.cond.signal());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_killed_simple() {
|
fn test_mutex_killed_simple() {
|
||||||
use any::Any;
|
use any::Any;
|
||||||
|
@ -854,6 +840,7 @@ mod tests {
|
||||||
// child task must have finished by the time try returns
|
// child task must have finished by the time try returns
|
||||||
drop(m.lock());
|
drop(m.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_cond_signal_on_0() {
|
fn test_mutex_cond_signal_on_0() {
|
||||||
// Tests that signal_on(0) is equivalent to signal().
|
// Tests that signal_on(0) is equivalent to signal().
|
||||||
|
@ -866,6 +853,7 @@ mod tests {
|
||||||
});
|
});
|
||||||
lock.cond.wait();
|
lock.cond.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutex_no_condvars() {
|
fn test_mutex_no_condvars() {
|
||||||
let result = task::try(proc() {
|
let result = task::try(proc() {
|
||||||
|
@ -884,11 +872,10 @@ mod tests {
|
||||||
});
|
});
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
/************************************************************************
|
|
||||||
* Reader/writer lock tests
|
|
||||||
************************************************************************/
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub enum RWLockMode { Read, Write, Downgrade, DowngradeRead }
|
pub enum RWLockMode { Read, Write, Downgrade, DowngradeRead }
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn lock_rwlock_in_mode(x: &Arc<RWLock>, mode: RWLockMode, blk: ||) {
|
fn lock_rwlock_in_mode(x: &Arc<RWLock>, mode: RWLockMode, blk: ||) {
|
||||||
match mode {
|
match mode {
|
||||||
|
@ -898,6 +885,7 @@ mod tests {
|
||||||
DowngradeRead => { let _g = x.write().downgrade(); blk() }
|
DowngradeRead => { let _g = x.write().downgrade(); blk() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_rwlock_exclusion(x: Arc<RWLock>,
|
fn test_rwlock_exclusion(x: Arc<RWLock>,
|
||||||
mode1: RWLockMode,
|
mode1: RWLockMode,
|
||||||
|
@ -934,6 +922,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_readers_wont_modify_the_data() {
|
fn test_rwlock_readers_wont_modify_the_data() {
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), Read, Write);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), Read, Write);
|
||||||
|
@ -943,6 +932,7 @@ mod tests {
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), Write, DowngradeRead);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), Write, DowngradeRead);
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), DowngradeRead, Write);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), DowngradeRead, Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_writers_and_writers() {
|
fn test_rwlock_writers_and_writers() {
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), Write, Write);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), Write, Write);
|
||||||
|
@ -950,6 +940,7 @@ mod tests {
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), Downgrade, Write);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), Downgrade, Write);
|
||||||
test_rwlock_exclusion(Arc::new(RWLock::new()), Downgrade, Downgrade);
|
test_rwlock_exclusion(Arc::new(RWLock::new()), Downgrade, Downgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_rwlock_handshake(x: Arc<RWLock>,
|
fn test_rwlock_handshake(x: Arc<RWLock>,
|
||||||
mode1: RWLockMode,
|
mode1: RWLockMode,
|
||||||
|
@ -982,6 +973,7 @@ mod tests {
|
||||||
rx1.recv();
|
rx1.recv();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_readers_and_readers() {
|
fn test_rwlock_readers_and_readers() {
|
||||||
test_rwlock_handshake(Arc::new(RWLock::new()), Read, Read, false);
|
test_rwlock_handshake(Arc::new(RWLock::new()), Read, Read, false);
|
||||||
|
@ -991,6 +983,7 @@ mod tests {
|
||||||
test_rwlock_handshake(Arc::new(RWLock::new()), Read, DowngradeRead, true);
|
test_rwlock_handshake(Arc::new(RWLock::new()), Read, DowngradeRead, true);
|
||||||
// Two downgrade_reads can never both end up reading at the same time.
|
// Two downgrade_reads can never both end up reading at the same time.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_downgrade_unlock() {
|
fn test_rwlock_downgrade_unlock() {
|
||||||
// Tests that downgrade can unlock the lock in both modes
|
// Tests that downgrade can unlock the lock in both modes
|
||||||
|
@ -1001,12 +994,14 @@ mod tests {
|
||||||
lock_rwlock_in_mode(&y, DowngradeRead, || { });
|
lock_rwlock_in_mode(&y, DowngradeRead, || { });
|
||||||
test_rwlock_exclusion(y, Write, Write);
|
test_rwlock_exclusion(y, Write, Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_read_recursive() {
|
fn test_rwlock_read_recursive() {
|
||||||
let x = RWLock::new();
|
let x = RWLock::new();
|
||||||
let _g1 = x.read();
|
let _g1 = x.read();
|
||||||
let _g2 = x.read();
|
let _g2 = x.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_cond_wait() {
|
fn test_rwlock_cond_wait() {
|
||||||
// As test_mutex_cond_wait above.
|
// As test_mutex_cond_wait above.
|
||||||
|
@ -1040,6 +1035,7 @@ mod tests {
|
||||||
rx.recv(); // Wait until child wakes up
|
rx.recv(); // Wait until child wakes up
|
||||||
drop(x.read()); // Just for good measure
|
drop(x.read()); // Just for good measure
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn test_rwlock_cond_broadcast_helper(num_waiters: uint) {
|
fn test_rwlock_cond_broadcast_helper(num_waiters: uint) {
|
||||||
// Much like the mutex broadcast test. Downgrade-enabled.
|
// Much like the mutex broadcast test. Downgrade-enabled.
|
||||||
|
@ -1073,11 +1069,13 @@ mod tests {
|
||||||
// wait until all children wake up
|
// wait until all children wake up
|
||||||
for rx in rxs.iter_mut() { let _ = rx.recv(); }
|
for rx in rxs.iter_mut() { let _ = rx.recv(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_cond_broadcast() {
|
fn test_rwlock_cond_broadcast() {
|
||||||
test_rwlock_cond_broadcast_helper(0);
|
test_rwlock_cond_broadcast_helper(0);
|
||||||
test_rwlock_cond_broadcast_helper(12);
|
test_rwlock_cond_broadcast_helper(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
|
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
|
||||||
use any::Any;
|
use any::Any;
|
||||||
|
@ -1095,22 +1093,27 @@ mod tests {
|
||||||
// child task must have finished by the time try returns
|
// child task must have finished by the time try returns
|
||||||
lock_rwlock_in_mode(&x, mode2, || { })
|
lock_rwlock_in_mode(&x, mode2, || { })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_reader_killed_writer() {
|
fn test_rwlock_reader_killed_writer() {
|
||||||
rwlock_kill_helper(Read, Write);
|
rwlock_kill_helper(Read, Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_writer_killed_reader() {
|
fn test_rwlock_writer_killed_reader() {
|
||||||
rwlock_kill_helper(Write, Read);
|
rwlock_kill_helper(Write, Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_reader_killed_reader() {
|
fn test_rwlock_reader_killed_reader() {
|
||||||
rwlock_kill_helper(Read, Read);
|
rwlock_kill_helper(Read, Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_writer_killed_writer() {
|
fn test_rwlock_writer_killed_writer() {
|
||||||
rwlock_kill_helper(Write, Write);
|
rwlock_kill_helper(Write, Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rwlock_kill_downgrader() {
|
fn test_rwlock_kill_downgrader() {
|
||||||
rwlock_kill_helper(Downgrade, Read);
|
rwlock_kill_helper(Downgrade, Read);
|
||||||
|
|
|
@ -33,13 +33,11 @@ use string::String;
|
||||||
|
|
||||||
pub use sys_common::ProcessConfig;
|
pub use sys_common::ProcessConfig;
|
||||||
|
|
||||||
/**
|
/// A value representing a child process.
|
||||||
* A value representing a child process.
|
///
|
||||||
*
|
/// The lifetime of this value is linked to the lifetime of the actual
|
||||||
* The lifetime of this value is linked to the lifetime of the actual
|
/// process - the Process destructor calls self.finish() which waits
|
||||||
* process - the Process destructor calls self.finish() which waits
|
/// for the process to terminate.
|
||||||
* for the process to terminate.
|
|
||||||
*/
|
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
/// The unique id of the process (this should never be negative).
|
/// The unique id of the process (this should never be negative).
|
||||||
pid: pid_t,
|
pid: pid_t,
|
||||||
|
@ -263,16 +261,14 @@ impl Process {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Waits for a process to exit and returns the exit code, failing
|
||||||
* Waits for a process to exit and returns the exit code, failing
|
/// if there is no process with the specified id.
|
||||||
* if there is no process with the specified id.
|
///
|
||||||
*
|
/// Note that this is private to avoid race conditions on unix where if
|
||||||
* Note that this is private to avoid race conditions on unix where if
|
/// a user calls waitpid(some_process.get_id()) then some_process.finish()
|
||||||
* a user calls waitpid(some_process.get_id()) then some_process.finish()
|
/// and some_process.destroy() and some_process.finalize() will then either
|
||||||
* and some_process.destroy() and some_process.finalize() will then either
|
/// operate on a none-existent process or, even worse, on a newer process
|
||||||
* operate on a none-existent process or, even worse, on a newer process
|
/// with the same id.
|
||||||
* with the same id.
|
|
||||||
*/
|
|
||||||
pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
|
pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
|
||||||
use libc::types::os::arch::extra::DWORD;
|
use libc::types::os::arch::extra::DWORD;
|
||||||
use libc::consts::os::extra::{
|
use libc::consts::os::extra::{
|
||||||
|
|
|
@ -83,12 +83,10 @@ impl Sub<CharPos,CharPos> for CharPos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Spans represent a region of code, used for error reporting. Positions in spans
|
||||||
Spans represent a region of code, used for error reporting. Positions in spans
|
/// are *absolute* positions from the beginning of the codemap, not positions
|
||||||
are *absolute* positions from the beginning of the codemap, not positions
|
/// relative to FileMaps. Methods on the CodeMap can be used to relate spans back
|
||||||
relative to FileMaps. Methods on the CodeMap can be used to relate spans back
|
/// to the original source.
|
||||||
to the original source.
|
|
||||||
*/
|
|
||||||
#[deriving(Clone, Show, Hash)]
|
#[deriving(Clone, Show, Hash)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub lo: BytePos,
|
pub lo: BytePos,
|
||||||
|
|
|
@ -17,16 +17,12 @@ use parse::token::*;
|
||||||
use parse::token;
|
use parse::token;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
/**
|
//! Quasiquoting works via token trees.
|
||||||
*
|
//!
|
||||||
* Quasiquoting works via token trees.
|
//! This is registered as a set of expression syntax extension called quote!
|
||||||
*
|
//! that lifts its argument token-tree to an AST representing the
|
||||||
* This is registered as a set of expression syntax extension called quote!
|
//! construction of the same token tree, with token::SubstNt interpreted
|
||||||
* that lifts its argument token-tree to an AST representing the
|
//! as antiquotes (splices).
|
||||||
* construction of the same token tree, with token::SubstNt interpreted
|
|
||||||
* as antiquotes (splices).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub mod rt {
|
pub mod rt {
|
||||||
use ast;
|
use ast;
|
||||||
|
|
|
@ -421,13 +421,11 @@ macro_rules! declare_special_idents_and_keywords {(
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// All the valid words that have meaning in the Rust language.
|
||||||
* All the valid words that have meaning in the Rust language.
|
///
|
||||||
*
|
/// Rust keywords are either 'strict' or 'reserved'. Strict keywords may not
|
||||||
* Rust keywords are either 'strict' or 'reserved'. Strict keywords may not
|
/// appear as identifiers at all. Reserved keywords are not used anywhere in
|
||||||
* appear as identifiers at all. Reserved keywords are not used anywhere in
|
/// the language and may not appear as identifiers.
|
||||||
* the language and may not appear as identifiers.
|
|
||||||
*/
|
|
||||||
pub mod keywords {
|
pub mod keywords {
|
||||||
pub use self::Keyword::*;
|
pub use self::Keyword::*;
|
||||||
use ast;
|
use ast;
|
||||||
|
|
|
@ -80,17 +80,15 @@ impl Variables {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Expand a parameterized capability
|
||||||
Expand a parameterized capability
|
///
|
||||||
|
/// # Arguments
|
||||||
# Arguments
|
/// * `cap` - string to expand
|
||||||
* `cap` - string to expand
|
/// * `params` - vector of params for %p1 etc
|
||||||
* `params` - vector of params for %p1 etc
|
/// * `vars` - Variables struct for %Pa etc
|
||||||
* `vars` - Variables struct for %Pa etc
|
///
|
||||||
|
/// To be compatible with ncurses, `vars` should be the same between calls to `expand` for
|
||||||
To be compatible with ncurses, `vars` should be the same between calls to `expand` for
|
/// multiple capabilities for the same terminal.
|
||||||
multiple capabilities for the same terminal.
|
|
||||||
*/
|
|
||||||
pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
|
pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
|
||||||
-> Result<Vec<u8> , String> {
|
-> Result<Vec<u8> , String> {
|
||||||
let mut state = Nothing;
|
let mut state = Nothing;
|
||||||
|
|
|
@ -123,10 +123,8 @@ impl Sub<Timespec, Duration> for Timespec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns the current time as a `timespec` containing the seconds and
|
||||||
* Returns the current time as a `timespec` containing the seconds and
|
/// nanoseconds since 1970-01-01T00:00:00Z.
|
||||||
* nanoseconds since 1970-01-01T00:00:00Z.
|
|
||||||
*/
|
|
||||||
pub fn get_time() -> Timespec {
|
pub fn get_time() -> Timespec {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (sec, nsec) = os_get_time();
|
let (sec, nsec) = os_get_time();
|
||||||
|
@ -171,10 +169,8 @@ pub fn get_time() -> Timespec {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/// Returns the current value of a high-resolution performance counter
|
||||||
* Returns the current value of a high-resolution performance counter
|
/// in nanoseconds since an unspecified epoch.
|
||||||
* in nanoseconds since an unspecified epoch.
|
|
||||||
*/
|
|
||||||
pub fn precise_time_ns() -> u64 {
|
pub fn precise_time_ns() -> u64 {
|
||||||
return os_precise_time_ns();
|
return os_precise_time_ns();
|
||||||
|
|
||||||
|
@ -218,10 +214,8 @@ pub fn precise_time_ns() -> u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/// Returns the current value of a high-resolution performance counter
|
||||||
* Returns the current value of a high-resolution performance counter
|
/// in seconds since an unspecified epoch.
|
||||||
* in seconds since an unspecified epoch.
|
|
||||||
*/
|
|
||||||
pub fn precise_time_s() -> f64 {
|
pub fn precise_time_s() -> f64 {
|
||||||
return (precise_time_ns() as f64) / 1000000000.;
|
return (precise_time_ns() as f64) / 1000000000.;
|
||||||
}
|
}
|
||||||
|
@ -346,12 +340,10 @@ impl Tm {
|
||||||
at_utc(self.to_timespec())
|
at_utc(self.to_timespec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a TmFmt that outputs according to the `asctime` format in ISO
|
||||||
* Returns a TmFmt that outputs according to the `asctime` format in ISO
|
/// C, in the local timezone.
|
||||||
* C, in the local timezone.
|
///
|
||||||
*
|
/// Example: "Thu Jan 1 00:00:00 1970"
|
||||||
* Example: "Thu Jan 1 00:00:00 1970"
|
|
||||||
*/
|
|
||||||
pub fn ctime(&self) -> TmFmt {
|
pub fn ctime(&self) -> TmFmt {
|
||||||
TmFmt {
|
TmFmt {
|
||||||
tm: self,
|
tm: self,
|
||||||
|
@ -359,12 +351,10 @@ impl Tm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a TmFmt that outputs according to the `asctime` format in ISO
|
||||||
* Returns a TmFmt that outputs according to the `asctime` format in ISO
|
/// C.
|
||||||
* C.
|
///
|
||||||
*
|
/// Example: "Thu Jan 1 00:00:00 1970"
|
||||||
* Example: "Thu Jan 1 00:00:00 1970"
|
|
||||||
*/
|
|
||||||
pub fn asctime(&self) -> TmFmt {
|
pub fn asctime(&self) -> TmFmt {
|
||||||
TmFmt {
|
TmFmt {
|
||||||
tm: self,
|
tm: self,
|
||||||
|
@ -380,12 +370,10 @@ impl Tm {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a TmFmt that outputs according to RFC 822.
|
||||||
* Returns a TmFmt that outputs according to RFC 822.
|
///
|
||||||
*
|
/// local: "Thu, 22 Mar 2012 07:53:18 PST"
|
||||||
* local: "Thu, 22 Mar 2012 07:53:18 PST"
|
/// utc: "Thu, 22 Mar 2012 14:53:18 GMT"
|
||||||
* utc: "Thu, 22 Mar 2012 14:53:18 GMT"
|
|
||||||
*/
|
|
||||||
pub fn rfc822(&self) -> TmFmt {
|
pub fn rfc822(&self) -> TmFmt {
|
||||||
if self.tm_gmtoff == 0_i32 {
|
if self.tm_gmtoff == 0_i32 {
|
||||||
TmFmt {
|
TmFmt {
|
||||||
|
@ -400,12 +388,10 @@ impl Tm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a TmFmt that outputs according to RFC 822 with Zulu time.
|
||||||
* Returns a TmFmt that outputs according to RFC 822 with Zulu time.
|
///
|
||||||
*
|
/// local: "Thu, 22 Mar 2012 07:53:18 -0700"
|
||||||
* local: "Thu, 22 Mar 2012 07:53:18 -0700"
|
/// utc: "Thu, 22 Mar 2012 14:53:18 -0000"
|
||||||
* utc: "Thu, 22 Mar 2012 14:53:18 -0000"
|
|
||||||
*/
|
|
||||||
pub fn rfc822z(&self) -> TmFmt {
|
pub fn rfc822z(&self) -> TmFmt {
|
||||||
TmFmt {
|
TmFmt {
|
||||||
tm: self,
|
tm: self,
|
||||||
|
@ -413,13 +399,11 @@ impl Tm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Returns a TmFmt that outputs according to RFC 3339. RFC 3339 is
|
||||||
* Returns a TmFmt that outputs according to RFC 3339. RFC 3339 is
|
/// compatible with ISO 8601.
|
||||||
* compatible with ISO 8601.
|
///
|
||||||
*
|
/// local: "2012-02-22T07:53:18-07:00"
|
||||||
* local: "2012-02-22T07:53:18-07:00"
|
/// utc: "2012-02-22T14:53:18Z"
|
||||||
* utc: "2012-02-22T14:53:18Z"
|
|
||||||
*/
|
|
||||||
pub fn rfc3339<'a>(&'a self) -> TmFmt {
|
pub fn rfc3339<'a>(&'a self) -> TmFmt {
|
||||||
TmFmt {
|
TmFmt {
|
||||||
tm: self,
|
tm: self,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue