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