Make ~fn non-copyable, make &fn copyable, split barefn/closure types,
correct handling of moves for struct-record update. Part of #3678. Fixes #2828, #3904, #4719.
This commit is contained in:
parent
82d7396333
commit
a32498d846
187 changed files with 2065 additions and 2373 deletions
|
@ -159,7 +159,7 @@ pub fn test_opts(config: config) -> test::TestOpts {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn make_tests(config: config) -> ~[test::TestDesc] {
|
||||
pub fn make_tests(config: config) -> ~[test::TestDescAndFn] {
|
||||
debug!("making tests from %s",
|
||||
config.src_base.to_str());
|
||||
let mut tests = ~[];
|
||||
|
@ -196,13 +196,14 @@ pub fn is_test(config: config, testfile: &Path) -> bool {
|
|||
return valid;
|
||||
}
|
||||
|
||||
pub fn make_test(config: config, testfile: &Path) ->
|
||||
test::TestDesc {
|
||||
test::TestDesc {
|
||||
name: make_test_name(config, testfile),
|
||||
pub fn make_test(config: config, testfile: &Path) -> test::TestDescAndFn {
|
||||
test::TestDescAndFn {
|
||||
desc: test::TestDesc {
|
||||
name: make_test_name(config, testfile),
|
||||
ignore: header::is_test_ignored(config, testfile),
|
||||
should_fail: false
|
||||
},
|
||||
testfn: make_test_closure(config, testfile),
|
||||
ignore: header::is_test_ignored(config, testfile),
|
||||
should_fail: false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Managed vectors
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::transmute;
|
||||
use kinds::Copy;
|
||||
use iter;
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Boolean logic
|
||||
|
||||
use bool;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unsafe operations
|
||||
#[forbid(deprecated_mode)]
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
fn forget<T>(-x: T);
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Utilities for manipulating the char type
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use char;
|
||||
use cmp::Eq;
|
||||
use option::{None, Option, Some};
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
#[doc(hidden)];
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use libc::{c_char, c_void, intptr_t, uintptr_t};
|
||||
use ptr::{mut_null, null, to_unsafe_ptr};
|
||||
use repr::BoxRepr;
|
||||
|
|
|
@ -20,10 +20,6 @@ and `Eq` to overload the `==` and `!=` operators.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/**
|
||||
* Trait for values that can be compared for equality
|
||||
* and inequality.
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
|
||||
//! Container traits
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use option::Option;
|
||||
|
||||
pub trait Container {
|
||||
|
|
|
@ -48,8 +48,6 @@ Implicitly, all crates behave as if they included the following prologue:
|
|||
// Don't link to core. We are core.
|
||||
#[no_core];
|
||||
|
||||
#[warn(deprecated_mode)];
|
||||
#[warn(deprecated_pattern)];
|
||||
#[warn(vecs_implicitly_copyable)];
|
||||
#[deny(non_camel_case_types)];
|
||||
#[allow(deprecated_self)];
|
||||
|
|
|
@ -18,10 +18,6 @@ Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use kinds::Copy;
|
||||
use managed;
|
||||
use option::{None, Option, Some};
|
||||
|
|
|
@ -19,10 +19,6 @@ Note that recursive use is not permitted.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast;
|
||||
use cast::reinterpret_cast;
|
||||
use prelude::*;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! A type that represents one of two alternatives
|
||||
|
||||
use cmp::Eq;
|
||||
|
|
|
@ -51,10 +51,6 @@
|
|||
//! * s - str (any flavor)
|
||||
//! * ? - arbitrary type (does not use the to_str trait)
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
// Transitional
|
||||
#[allow(structural_records)]; // Macros -- needs a snapshot
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@ Simple compression
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use libc;
|
||||
use libc::{c_void, size_t, c_int};
|
||||
use ptr;
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! The trait for types that can be created from strings
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use option::Option;
|
||||
|
||||
pub trait FromStr {
|
||||
|
|
|
@ -35,9 +35,6 @@ with destructors.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
// Transitional
|
||||
#[allow(structural_records)];
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/*!
|
||||
* Implementation of SipHash 2-4
|
||||
*
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Sendable hash maps.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use container::{Container, Mutable, Map, Set};
|
||||
use cmp::Eq;
|
||||
use hash::Hash;
|
||||
|
|
|
@ -14,9 +14,6 @@ Basic input/output
|
|||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use result::Result;
|
||||
|
||||
use cmp::Eq;
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
// workaround our lack of traits and lack of macros. See core.{rc,rs} for
|
||||
// how this file is used.
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
use iter::BaseIter;
|
||||
use iter;
|
||||
|
|
|
@ -14,9 +14,6 @@ The iteration traits and common implementation
|
|||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
use kinds::Copy;
|
||||
use option::{None, Option, Some};
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
/*!
|
||||
* Bindings for libc.
|
||||
*
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Logging
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::transmute;
|
||||
use io;
|
||||
use libc;
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Operations on managed box types
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::transmute;
|
||||
use cmp::{Eq, Ord};
|
||||
use managed::raw::BoxRepr;
|
||||
|
|
|
@ -18,8 +18,6 @@ dynamic checks: your program will fail if you attempt to perform
|
|||
mutation when the data structure should be immutable.
|
||||
|
||||
*/
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use util::with;
|
||||
use cast::transmute_immut;
|
||||
|
|
|
@ -14,10 +14,6 @@ Functions for the unit type.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
|
||||
#[cfg(notest)]
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#[doc(hidden)]; // FIXME #3538
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use libc::c_int;
|
||||
use libc::c_float;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Operations and constants for `f32`
|
||||
|
||||
use cmath;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Operations and constants for `f64`
|
||||
|
||||
use cmath;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Operations and constants for `float`
|
||||
|
||||
// Even though this module exports everything defined in it,
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use T = self::inst::T;
|
||||
|
||||
use char;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use T = self::inst::T;
|
||||
use T_SIGNED = self::inst::T_SIGNED;
|
||||
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
|
||||
// Core operators
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
#[lang="drop"]
|
||||
pub trait Drop {
|
||||
fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton
|
||||
|
|
|
@ -41,9 +41,6 @@ let unwrapped_msg = match move msg {
|
|||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
use kinds::Copy;
|
||||
use option;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
#[allow(structural_records)];
|
||||
|
||||
/*!
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Operations on unique pointer types
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
|
||||
#[cfg(notest)]
|
||||
|
|
|
@ -14,10 +14,6 @@ Cross-platform file path handling
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
use libc;
|
||||
use option::{None, Option, Some};
|
||||
|
|
|
@ -82,11 +82,6 @@ bounded and unbounded protocols allows for less code duplication.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// tjc: allowing deprecated modes due to function issue,
|
||||
// re-forbid after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
// Transitional -- needs snapshot
|
||||
#[allow(structural_records)];
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ pub use path::PosixPath;
|
|||
pub use path::WindowsPath;
|
||||
pub use pipes::{GenericChan, GenericPort};
|
||||
pub use ptr::Ptr;
|
||||
pub use str::{StrSlice, Trimmable};
|
||||
pub use str::{StrSlice, Trimmable, OwnedStr};
|
||||
pub use to_bytes::IterBytes;
|
||||
pub use to_str::ToStr;
|
||||
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// tjc: Re-forbid deprecated modes once a snapshot fixes the
|
||||
// function problem
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
#[doc(hidden)];
|
||||
|
||||
use cast;
|
||||
|
|
|
@ -26,10 +26,19 @@ do || {
|
|||
use ops::Drop;
|
||||
use task::{spawn, failing};
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub trait Finally<T> {
|
||||
fn finally(&self, +dtor: &fn()) -> T;
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
pub trait Finally<T> {
|
||||
fn finally(&self, dtor: &fn()) -> T;
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
impl<T> &fn() -> T: Finally<T> {
|
||||
// FIXME #4518: Should not require a mode here
|
||||
fn finally(&self, +dtor: &fn()) -> T {
|
||||
|
@ -41,6 +50,19 @@ impl<T> &fn() -> T: Finally<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
impl<T> &fn() -> T: Finally<T> {
|
||||
fn finally(&self, dtor: &fn()) -> T {
|
||||
let _d = Finallyalizer {
|
||||
dtor: dtor
|
||||
};
|
||||
|
||||
(*self)()
|
||||
}
|
||||
}
|
||||
|
||||
struct Finallyalizer {
|
||||
dtor: &fn()
|
||||
}
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
|
||||
//! Unsafe pointer utility functions
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast;
|
||||
use cmp::{Eq, Ord};
|
||||
use libc;
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Random number generation
|
||||
|
||||
// NB: transitional, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use int;
|
||||
use prelude::*;
|
||||
use str;
|
||||
|
|
|
@ -14,9 +14,6 @@ Runtime type reflection
|
|||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
|
||||
use libc::c_void;
|
||||
use sys;
|
||||
|
|
|
@ -14,9 +14,6 @@ More runtime type reflection
|
|||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::transmute;
|
||||
use cast;
|
||||
use char;
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp;
|
||||
use cmp::Eq;
|
||||
use either;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
//! Runtime calls emitted by the compiler.
|
||||
|
||||
use cast::transmute;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
#[allow(structural_records)];
|
||||
|
||||
//! Process spawning
|
||||
|
|
|
@ -11,12 +11,7 @@
|
|||
#[doc(hidden)]; // FIXME #3538
|
||||
|
||||
#[legacy_modes]; // tjc: remove after snapshot
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// FIXME #4425: Can't forbid this because frame_address needs a deprecated
|
||||
// mode.
|
||||
#[allow(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::reinterpret_cast;
|
||||
use ptr::offset;
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
* some heavy-duty uses, try std::rope.
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use at_vec;
|
||||
use cast;
|
||||
use char;
|
||||
|
@ -2314,6 +2311,21 @@ impl &str: StrSlice {
|
|||
pure fn char_at(i: uint) -> char { char_at(self, i) }
|
||||
}
|
||||
|
||||
pub trait OwnedStr {
|
||||
fn push_str(&mut self, v: &str);
|
||||
fn push_char(&mut self, c: char);
|
||||
}
|
||||
|
||||
pub impl ~str : OwnedStr {
|
||||
fn push_str(&mut self, v: &str) {
|
||||
push_str(self, v);
|
||||
}
|
||||
|
||||
fn push_char(&mut self, c: char) {
|
||||
push_char(self, c);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use char;
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
//! Misc low level stuff
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast;
|
||||
use cmp::{Eq, Ord};
|
||||
use gc;
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// tjc: Deprecated modes allowed because of function arg issue
|
||||
// in task::spawn. Re-forbid after snapshot.
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/*!
|
||||
* Task management.
|
||||
*
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
****************************************************************************/
|
||||
|
||||
#[doc(hidden)]; // FIXME #3538
|
||||
#[warn(deprecated_mode)];
|
||||
|
||||
use cast;
|
||||
use container::Map;
|
||||
|
|
|
@ -14,16 +14,12 @@ The `ToBytes` and `IterBytes` traits
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use io;
|
||||
use io::Writer;
|
||||
use option::{None, Option, Some};
|
||||
use str;
|
||||
|
||||
pub type Cb = fn(buf: &[const u8]) -> bool;
|
||||
pub type Cb = &fn(buf: &[const u8]) -> bool;
|
||||
|
||||
/**
|
||||
* A trait to implement in order to make a type hashable;
|
||||
|
|
|
@ -14,10 +14,6 @@ The `ToStr` trait for converting to strings
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use kinds::Copy;
|
||||
use str;
|
||||
use vec;
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Operations on tuples
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
#[doc(hidden)]; // FIXME #3538
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
pub mod general_category {
|
||||
pub pure fn Cc(c: char) -> bool {
|
||||
|
|
|
@ -14,10 +14,6 @@ Miscellaneous helpers for common patterns.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
use prelude::*;
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
//! Vectors
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
#[warn(non_camel_case_types)];
|
||||
|
||||
use container::{Container, Mutable};
|
||||
|
@ -841,14 +839,37 @@ pub pure fn map2<T: Copy, U: Copy, V>(v0: &[T], v1: &[U],
|
|||
u
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a function to each element of a vector and return the results
|
||||
*
|
||||
* If function `f` returns `none` then that element is excluded from
|
||||
* the resulting vector.
|
||||
*/
|
||||
pub pure fn filter_map<T, U: Copy>(v: &[T], f: fn(t: &T) -> Option<U>)
|
||||
-> ~[U] {
|
||||
pub fn filter_map<T, U>(
|
||||
v: ~[T],
|
||||
f: fn(t: T) -> Option<U>) -> ~[U]
|
||||
{
|
||||
/*!
|
||||
*
|
||||
* Apply a function to each element of a vector and return the results.
|
||||
* Consumes the input vector. If function `f` returns `None` then that
|
||||
* element is excluded from the resulting vector.
|
||||
*/
|
||||
|
||||
let mut result = ~[];
|
||||
do consume(v) |_, elem| {
|
||||
match f(elem) {
|
||||
None => {}
|
||||
Some(result_elem) => { result.push(result_elem); }
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub pure fn filter_mapped<T, U: Copy>(
|
||||
v: &[T],
|
||||
f: fn(t: &T) -> Option<U>) -> ~[U]
|
||||
{
|
||||
/*!
|
||||
*
|
||||
* Like `filter_map()`, but operates on a borrowed slice
|
||||
* and does not consume the input.
|
||||
*/
|
||||
|
||||
let mut result = ~[];
|
||||
for each(v) |elem| {
|
||||
match f(elem) {
|
||||
|
@ -1695,7 +1716,7 @@ pub trait ImmutableVector<T> {
|
|||
fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
|
||||
pure fn alli(&self, f: fn(uint, t: &T) -> bool) -> bool;
|
||||
pure fn flat_map<U>(&self, f: fn(t: &T) -> ~[U]) -> ~[U];
|
||||
pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U];
|
||||
pure fn filter_mapped<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U];
|
||||
}
|
||||
|
||||
/// Extension methods for vectors
|
||||
|
@ -1758,8 +1779,8 @@ impl<T> &[T]: ImmutableVector<T> {
|
|||
* the resulting vector.
|
||||
*/
|
||||
#[inline]
|
||||
pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U] {
|
||||
filter_map(*self, f)
|
||||
pure fn filter_mapped<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U] {
|
||||
filter_mapped(*self, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2439,10 +2460,14 @@ mod tests {
|
|||
|
||||
pure fn is_equal(x: &uint, y:&uint) -> bool { return *x == *y; }
|
||||
|
||||
fn square_if_odd(n: &uint) -> Option<uint> {
|
||||
fn square_if_odd_r(n: &uint) -> Option<uint> {
|
||||
return if *n % 2u == 1u { Some(*n * *n) } else { None };
|
||||
}
|
||||
|
||||
fn square_if_odd_v(n: uint) -> Option<uint> {
|
||||
return if n % 2u == 1u { Some(n * n) } else { None };
|
||||
}
|
||||
|
||||
fn add(x: uint, y: &uint) -> uint { return x + *y; }
|
||||
|
||||
#[test]
|
||||
|
@ -2775,17 +2800,17 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_map() {
|
||||
fn test_filter_mapped() {
|
||||
// Test on-stack filter-map.
|
||||
let mut v = ~[1u, 2u, 3u];
|
||||
let mut w = filter_map(v, square_if_odd);
|
||||
let mut w = filter_mapped(v, square_if_odd_r);
|
||||
assert (len(w) == 2u);
|
||||
assert (w[0] == 1u);
|
||||
assert (w[1] == 9u);
|
||||
|
||||
// Test on-heap filter-map.
|
||||
v = ~[1u, 2u, 3u, 4u, 5u];
|
||||
w = filter_map(v, square_if_odd);
|
||||
w = filter_mapped(v, square_if_odd_r);
|
||||
assert (len(w) == 3u);
|
||||
assert (w[0] == 1u);
|
||||
assert (w[1] == 9u);
|
||||
|
@ -2804,7 +2829,46 @@ mod tests {
|
|||
let all_odd2: ~[int] = ~[];
|
||||
let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
|
||||
let mix_dest: ~[int] = ~[1, 3, 0, 0];
|
||||
assert (filter_map(all_even, halve) == map(all_even, halve_for_sure));
|
||||
assert (filter_mapped(all_even, halve) ==
|
||||
map(all_even, halve_for_sure));
|
||||
assert (filter_mapped(all_odd1, halve) == ~[]);
|
||||
assert (filter_mapped(all_odd2, halve) == ~[]);
|
||||
assert (filter_mapped(mix, halve) == mix_dest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filter_map() {
|
||||
// Test on-stack filter-map.
|
||||
let mut v = ~[1u, 2u, 3u];
|
||||
let mut w = filter_map(v, square_if_odd_v);
|
||||
assert (len(w) == 2u);
|
||||
assert (w[0] == 1u);
|
||||
assert (w[1] == 9u);
|
||||
|
||||
// Test on-heap filter-map.
|
||||
v = ~[1u, 2u, 3u, 4u, 5u];
|
||||
w = filter_map(v, square_if_odd_v);
|
||||
assert (len(w) == 3u);
|
||||
assert (w[0] == 1u);
|
||||
assert (w[1] == 9u);
|
||||
assert (w[2] == 25u);
|
||||
|
||||
fn halve(i: int) -> Option<int> {
|
||||
if i % 2 == 0 {
|
||||
return option::Some::<int>(i / 2);
|
||||
} else {
|
||||
return option::None::<int>;
|
||||
}
|
||||
}
|
||||
fn halve_for_sure(i: &int) -> int { return *i / 2; }
|
||||
let all_even: ~[int] = ~[0, 2, 8, 6];
|
||||
let all_even0: ~[int] = copy all_even;
|
||||
let all_odd1: ~[int] = ~[1, 7, 3];
|
||||
let all_odd2: ~[int] = ~[];
|
||||
let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
|
||||
let mix_dest: ~[int] = ~[1, 3, 0, 0];
|
||||
assert (filter_map(all_even, halve) ==
|
||||
map(all_even0, halve_for_sure));
|
||||
assert (filter_map(all_odd1, halve) == ~[]);
|
||||
assert (filter_map(all_odd2, halve) == ~[]);
|
||||
assert (filter_map(mix, halve) == mix_dest);
|
||||
|
@ -3664,10 +3728,10 @@ mod tests {
|
|||
#[ignore(windows)]
|
||||
#[should_fail]
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn test_filter_map_fail() {
|
||||
fn test_filter_mapped_fail() {
|
||||
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
|
||||
let mut i = 0;
|
||||
do filter_map(v) |_elt| {
|
||||
do filter_mapped(v) |_elt| {
|
||||
if i == 2 {
|
||||
die!()
|
||||
}
|
||||
|
|
|
@ -64,12 +64,13 @@ fn filter_view_item(cx: ctxt, &&view_item: @ast::view_item
|
|||
}
|
||||
|
||||
fn fold_mod(cx: ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod {
|
||||
let filtered_items = vec::filter_map(m.items, |a| filter_item(cx, *a));
|
||||
let filtered_view_items = vec::filter_map(m.view_items,
|
||||
|a| filter_view_item(cx, *a));
|
||||
let filtered_items =
|
||||
m.items.filter_mapped(|a| filter_item(cx, *a));
|
||||
let filtered_view_items =
|
||||
m.view_items.filter_mapped(|a| filter_view_item(cx, *a));
|
||||
ast::_mod {
|
||||
view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)),
|
||||
items: filtered_items.filter_map(|x| fld.fold_item(*x)),
|
||||
items: vec::filter_map(filtered_items, |x| fld.fold_item(x))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,10 +86,10 @@ fn fold_foreign_mod(
|
|||
nm: ast::foreign_mod,
|
||||
fld: fold::ast_fold
|
||||
) -> ast::foreign_mod {
|
||||
let filtered_items = vec::filter_map(nm.items,
|
||||
|a| filter_foreign_item(cx, *a));
|
||||
let filtered_view_items = vec::filter_map(nm.view_items,
|
||||
|a| filter_view_item(cx, *a));
|
||||
let filtered_items =
|
||||
nm.items.filter_mapped(|a| filter_foreign_item(cx, *a));
|
||||
let filtered_view_items =
|
||||
nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
|
||||
ast::foreign_mod {
|
||||
sort: nm.sort,
|
||||
abi: nm.abi,
|
||||
|
@ -136,7 +137,8 @@ fn fold_block(
|
|||
b: ast::blk_,
|
||||
fld: fold::ast_fold
|
||||
) -> ast::blk_ {
|
||||
let filtered_stmts = vec::filter_map(b.stmts, |a| filter_stmt(cx, *a));
|
||||
let filtered_stmts =
|
||||
b.stmts.filter_mapped(|a| filter_stmt(cx, *a));
|
||||
ast::blk_ {
|
||||
view_items: /*bad*/copy b.view_items,
|
||||
stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)),
|
||||
|
@ -183,8 +185,9 @@ pub fn metas_in_cfg(cfg: ast::crate_cfg,
|
|||
// Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes,
|
||||
// so we can match against them. This is the list of configurations for
|
||||
// which the item is valid
|
||||
let cfg_metas = vec::concat(vec::filter_map(cfg_metas,
|
||||
|i| attr::get_meta_item_list(*i)));
|
||||
let cfg_metas =
|
||||
vec::concat(
|
||||
vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i)));
|
||||
|
||||
let has_cfg_metas = vec::len(cfg_metas) > 0u;
|
||||
if !has_cfg_metas { return true; }
|
||||
|
|
|
@ -168,9 +168,11 @@ fn is_test_fn(i: @ast::item) -> bool {
|
|||
fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool {
|
||||
let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
|
||||
let ignoreitems = attr::attr_metas(ignoreattrs);
|
||||
let cfg_metas = vec::concat(vec::filter_map(ignoreitems,
|
||||
|i| attr::get_meta_item_list(*i)));
|
||||
return if !ignoreitems.is_empty() {
|
||||
let cfg_metas =
|
||||
vec::concat(
|
||||
vec::filter_map(ignoreitems,
|
||||
|i| attr::get_meta_item_list(i)));
|
||||
config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
|
||||
} else {
|
||||
false
|
||||
|
@ -277,7 +279,7 @@ fn mk_std(cx: test_ctxt) -> @ast::view_item {
|
|||
}
|
||||
|
||||
fn mk_tests(cx: test_ctxt) -> @ast::item {
|
||||
let ret_ty = mk_test_desc_vec_ty(cx);
|
||||
let ret_ty = mk_test_desc_and_fn_vec_ty(cx);
|
||||
|
||||
let decl = ast::fn_decl {
|
||||
inputs: ~[],
|
||||
|
@ -286,7 +288,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
|
|||
};
|
||||
|
||||
// The vector of test_descs for this crate
|
||||
let test_descs = mk_test_desc_vec(cx);
|
||||
let test_descs = mk_test_desc_and_fn_vec(cx);
|
||||
|
||||
let body_: ast::blk_ =
|
||||
default_block(~[], option::Some(test_descs), cx.sess.next_node_id());
|
||||
|
@ -327,19 +329,21 @@ fn mk_path(cx: test_ctxt, +path: ~[ast::ident]) -> @ast::path {
|
|||
}
|
||||
}
|
||||
|
||||
// The ast::Ty of ~[std::test::test_desc]
|
||||
fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty {
|
||||
let test_desc_ty_path =
|
||||
// The ast::Ty of ~[std::test::TestDescAndFn]
|
||||
fn mk_test_desc_and_fn_vec_ty(cx: test_ctxt) -> @ast::Ty {
|
||||
let test_desc_and_fn_ty_path =
|
||||
mk_path(cx, ~[cx.sess.ident_of(~"test"),
|
||||
cx.sess.ident_of(~"TestDesc")]);
|
||||
cx.sess.ident_of(~"TestDescAndFn")]);
|
||||
|
||||
let test_desc_ty = ast::Ty {
|
||||
let test_desc_and_fn_ty = ast::Ty {
|
||||
id: cx.sess.next_node_id(),
|
||||
node: ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()),
|
||||
node: ast::ty_path(test_desc_and_fn_ty_path,
|
||||
cx.sess.next_node_id()),
|
||||
span: dummy_sp(),
|
||||
};
|
||||
|
||||
let vec_mt = ast::mt {ty: @test_desc_ty, mutbl: ast::m_imm};
|
||||
let vec_mt = ast::mt {ty: @test_desc_and_fn_ty,
|
||||
mutbl: ast::m_imm};
|
||||
|
||||
let inner_ty = @ast::Ty {
|
||||
id: cx.sess.next_node_id(),
|
||||
|
@ -354,11 +358,11 @@ fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty {
|
|||
}
|
||||
}
|
||||
|
||||
fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
|
||||
fn mk_test_desc_and_fn_vec(cx: test_ctxt) -> @ast::expr {
|
||||
debug!("building test vector from %u tests", cx.testfns.len());
|
||||
let mut descs = ~[];
|
||||
for cx.testfns.each |test| {
|
||||
descs.push(mk_test_desc_rec(cx, *test));
|
||||
descs.push(mk_test_desc_and_fn_rec(cx, *test));
|
||||
}
|
||||
|
||||
let inner_expr = @ast::expr {
|
||||
|
@ -376,7 +380,7 @@ fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
|
|||
}
|
||||
}
|
||||
|
||||
fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
|
||||
fn mk_test_desc_and_fn_rec(cx: test_ctxt, test: test) -> @ast::expr {
|
||||
let span = test.span;
|
||||
let path = /*bad*/copy test.path;
|
||||
|
||||
|
@ -407,23 +411,6 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
|
|||
expr: @name_expr,
|
||||
});
|
||||
|
||||
let fn_path = path_node_global(path);
|
||||
|
||||
let fn_expr = ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: ast::expr_path(fn_path),
|
||||
span: span,
|
||||
};
|
||||
|
||||
let fn_wrapper_expr = mk_test_wrapper(cx, fn_expr, span);
|
||||
|
||||
let fn_field = nospan(ast::field_ {
|
||||
mutbl: ast::m_imm,
|
||||
ident: cx.sess.ident_of(~"testfn"),
|
||||
expr: fn_wrapper_expr,
|
||||
});
|
||||
|
||||
let ignore_lit: ast::lit = nospan(ast::lit_bool(test.ignore));
|
||||
|
||||
let ignore_expr = ast::expr {
|
||||
|
@ -460,62 +447,52 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
|
|||
|
||||
let desc_rec_ = ast::expr_struct(
|
||||
test_desc_path,
|
||||
~[name_field, fn_field, ignore_field, fail_field],
|
||||
~[name_field, ignore_field, fail_field],
|
||||
option::None
|
||||
);
|
||||
|
||||
let desc_rec = ast::expr {
|
||||
let desc_rec = @ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: desc_rec_,
|
||||
span: span,
|
||||
};
|
||||
|
||||
return @desc_rec;
|
||||
}
|
||||
let desc_field = nospan(ast::field_ {
|
||||
mutbl: ast::m_imm,
|
||||
ident: cx.sess.ident_of(~"desc"),
|
||||
expr: desc_rec
|
||||
});
|
||||
|
||||
// Produces a bare function that wraps the test function
|
||||
let fn_path = path_node_global(path);
|
||||
|
||||
// FIXME (#1281): This can go away once fn is the type of bare function.
|
||||
fn mk_test_wrapper(cx: test_ctxt,
|
||||
+fn_path_expr: ast::expr,
|
||||
span: span) -> @ast::expr {
|
||||
let call_expr = ast::expr {
|
||||
let fn_expr = @ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: ast::expr_call(@fn_path_expr, ~[], false),
|
||||
node: ast::expr_path(fn_path),
|
||||
span: span,
|
||||
};
|
||||
|
||||
let call_stmt: ast::stmt = nospan(
|
||||
ast::stmt_semi(@call_expr, cx.sess.next_node_id()));
|
||||
|
||||
let wrapper_decl = ast::fn_decl {
|
||||
inputs: ~[],
|
||||
output: @ast::Ty {
|
||||
id: cx.sess.next_node_id(),
|
||||
node: ast::ty_nil,
|
||||
span: span,
|
||||
},
|
||||
cf: ast::return_val
|
||||
};
|
||||
|
||||
let wrapper_body = nospan(ast::blk_ {
|
||||
view_items: ~[],
|
||||
stmts: ~[@call_stmt],
|
||||
expr: option::None,
|
||||
id: cx.sess.next_node_id(),
|
||||
rules: ast::default_blk
|
||||
let fn_field = nospan(ast::field_ {
|
||||
mutbl: ast::m_imm,
|
||||
ident: cx.sess.ident_of(~"testfn"),
|
||||
expr: fn_expr,
|
||||
});
|
||||
|
||||
let wrapper_expr = ast::expr {
|
||||
let test_desc_and_fn_path =
|
||||
mk_path(cx, ~[cx.sess.ident_of(~"test"),
|
||||
cx.sess.ident_of(~"TestDescAndFn")]);
|
||||
|
||||
let desc_and_fn_rec = @ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @()),
|
||||
span: span
|
||||
node: ast::expr_struct(test_desc_and_fn_path,
|
||||
~[fn_field, desc_field],
|
||||
option::None),
|
||||
span: span,
|
||||
};
|
||||
|
||||
return @wrapper_expr;
|
||||
return desc_and_fn_rec;
|
||||
}
|
||||
|
||||
fn mk_main(cx: test_ctxt) -> @ast::item {
|
||||
|
@ -567,7 +544,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
|
|||
let args_call_expr = ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: ast::expr_call(@args_path_expr, ~[], false),
|
||||
node: ast::expr_call(@args_path_expr, ~[], ast::NoSugar),
|
||||
span: dummy_sp(),
|
||||
};
|
||||
|
||||
|
@ -584,7 +561,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
|
|||
let test_call_expr = ast::expr {
|
||||
id: cx.sess.next_node_id(),
|
||||
callee_id: cx.sess.next_node_id(),
|
||||
node: ast::expr_call(@test_path_expr, ~[], false),
|
||||
node: ast::expr_call(@test_path_expr, ~[], ast::NoSugar),
|
||||
span: dummy_sp(),
|
||||
};
|
||||
|
||||
|
@ -606,7 +583,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
|
|||
node: ast::expr_call(
|
||||
@test_main_path_expr,
|
||||
~[@args_call_expr, @test_call_expr],
|
||||
false
|
||||
ast::NoSugar
|
||||
),
|
||||
span: dummy_sp(),
|
||||
};
|
||||
|
|
|
@ -586,10 +586,8 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
|||
item, tcx, cdata);
|
||||
let name = item_name(intr, item);
|
||||
let arg_tys = match ty::get(ctor_ty).sty {
|
||||
ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty),
|
||||
|
||||
// Nullary enum variant.
|
||||
_ => ~[],
|
||||
ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty),
|
||||
_ => ~[], // Nullary enum variant.
|
||||
};
|
||||
match variant_disr_val(item) {
|
||||
Some(val) => { disr_val = val; }
|
||||
|
@ -705,11 +703,12 @@ pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
|||
let ty = doc_type(mth, tcx, cdata);
|
||||
let def_id = item_def_id(mth, cdata);
|
||||
let fty = match ty::get(ty).sty {
|
||||
ty::ty_fn(ref f) => (/*bad*/copy *f),
|
||||
_ => {
|
||||
tcx.diag.handler().bug(
|
||||
~"get_trait_methods: id has non-function type");
|
||||
} };
|
||||
ty::ty_bare_fn(ref f) => copy *f,
|
||||
_ => {
|
||||
tcx.diag.handler().bug(
|
||||
~"get_trait_methods: id has non-function type");
|
||||
}
|
||||
};
|
||||
let self_ty = get_self_ty(mth);
|
||||
result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
|
||||
vis: ast::public, def_id: def_id});
|
||||
|
@ -734,14 +733,13 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
|
|||
let name = item_name(intr, mth);
|
||||
let ty = doc_type(mth, tcx, cdata);
|
||||
|
||||
let fty;
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_fn(ref f) => fty = (/*bad*/copy *f),
|
||||
let fty = match ty::get(ty).sty {
|
||||
ty::ty_bare_fn(ref f) => copy *f,
|
||||
_ => {
|
||||
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
|
||||
has non-function type");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let self_ty = get_self_ty(mth);
|
||||
let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,
|
||||
|
|
|
@ -768,8 +768,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
|
|||
encode_name(ecx, ebml_w, mty.ident);
|
||||
encode_type_param_bounds(ebml_w, ecx,
|
||||
(*ty_m).tps);
|
||||
encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
|
||||
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
|
||||
encode_type(ecx, ebml_w,
|
||||
ty::mk_bare_fn(tcx, copy mty.fty));
|
||||
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
|
||||
encode_self_type(ebml_w, mty.self_ty);
|
||||
encode_method_sort(ebml_w, 'r');
|
||||
ebml_w.end_tag();
|
||||
|
@ -781,8 +782,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
|
|||
encode_def_id(ebml_w, local_def(m.id));
|
||||
encode_name(ecx, ebml_w, mty.ident);
|
||||
encode_type_param_bounds(ebml_w, ecx, m.tps);
|
||||
encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
|
||||
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
|
||||
encode_type(ecx, ebml_w,
|
||||
ty::mk_bare_fn(tcx, copy mty.fty));
|
||||
encode_family(ebml_w, purity_fn_family(mty.fty.purity));
|
||||
encode_self_type(ebml_w, mty.self_ty);
|
||||
encode_method_sort(ebml_w, 'p');
|
||||
ebml_w.end_tag();
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use middle::ty;
|
||||
use middle::ty::{FnTyBase, FnMeta, FnSig, arg, creader_cache_key, field};
|
||||
use middle::ty::{substs};
|
||||
|
||||
use core::io;
|
||||
use core::str;
|
||||
|
@ -124,17 +122,12 @@ fn parse_path(st: @pstate) -> @ast::path {
|
|||
};
|
||||
}
|
||||
|
||||
fn parse_ty_rust_fn(st: @pstate, conv: conv_did) -> ty::t {
|
||||
return ty::mk_fn(st.tcx, parse_ty_fn(st, conv));
|
||||
}
|
||||
|
||||
fn parse_proto(st: @pstate) -> ast::Proto {
|
||||
fn parse_sigil(st: @pstate) -> ast::Sigil {
|
||||
match next(st) {
|
||||
'_' => ast::ProtoBare,
|
||||
'@' => ast::ProtoBox,
|
||||
'~' => ast::ProtoUniq,
|
||||
'&' => ast::ProtoBorrowed,
|
||||
_ => die!(~"parse_proto(): bad input")
|
||||
'@' => ast::ManagedSigil,
|
||||
'~' => ast::OwnedSigil,
|
||||
'&' => ast::BorrowedSigil,
|
||||
c => st.tcx.sess.bug(fmt!("parse_sigil(): bad input '%c'", c))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +145,7 @@ fn parse_vstore(st: @pstate) -> ty::vstore {
|
|||
'~' => ty::vstore_uniq,
|
||||
'@' => ty::vstore_box,
|
||||
'&' => ty::vstore_slice(parse_region(st)),
|
||||
_ => die!(~"parse_vstore: bad input")
|
||||
c => st.tcx.sess.bug(fmt!("parse_vstore(): bad input '%c'", c))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +159,7 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs {
|
|||
while peek(st) != ']' { params.push(parse_ty(st, conv)); }
|
||||
st.pos = st.pos + 1u;
|
||||
|
||||
return substs {
|
||||
return ty::substs {
|
||||
self_r: self_r,
|
||||
self_ty: self_ty,
|
||||
tps: params
|
||||
|
@ -316,19 +309,24 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
|
|||
return ty::mk_tup(st.tcx, params);
|
||||
}
|
||||
'f' => {
|
||||
parse_ty_rust_fn(st, conv)
|
||||
return ty::mk_closure(st.tcx, parse_closure_ty(st, conv));
|
||||
}
|
||||
'F' => {
|
||||
return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, conv));
|
||||
}
|
||||
'Y' => return ty::mk_type(st.tcx),
|
||||
'C' => {
|
||||
let proto = parse_proto(st);
|
||||
return ty::mk_opaque_closure_ptr(st.tcx, proto);
|
||||
let sigil = parse_sigil(st);
|
||||
return ty::mk_opaque_closure_ptr(st.tcx, sigil);
|
||||
}
|
||||
'#' => {
|
||||
let pos = parse_hex(st);
|
||||
assert (next(st) == ':');
|
||||
let len = parse_hex(st);
|
||||
assert (next(st) == '#');
|
||||
let key = creader_cache_key { cnum: st.crate, pos: pos, len: len };
|
||||
let key = ty::creader_cache_key {cnum: st.crate,
|
||||
pos: pos,
|
||||
len: len };
|
||||
match st.tcx.rcache.find(&key) {
|
||||
Some(tt) => return tt,
|
||||
None => {
|
||||
|
@ -408,6 +406,13 @@ fn parse_purity(c: char) -> purity {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_abi(c: char) -> Abi {
|
||||
match c {
|
||||
'r' => ast::RustAbi,
|
||||
_ => die!(fmt!("parse_abi: bad ABI '%c'", c))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_onceness(c: char) -> ast::Onceness {
|
||||
match c {
|
||||
'o' => ast::Once,
|
||||
|
@ -430,12 +435,33 @@ fn parse_mode(st: @pstate) -> ast::mode {
|
|||
return m;
|
||||
}
|
||||
|
||||
fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
|
||||
let proto = parse_proto(st);
|
||||
fn parse_closure_ty(st: @pstate, conv: conv_did) -> ty::ClosureTy {
|
||||
let sigil = parse_sigil(st);
|
||||
let purity = parse_purity(next(st));
|
||||
let onceness = parse_onceness(next(st));
|
||||
let region = parse_region(st);
|
||||
let bounds = parse_bounds(st, conv);
|
||||
let sig = parse_sig(st, conv);
|
||||
ty::ClosureTy {
|
||||
purity: purity,
|
||||
sigil: sigil,
|
||||
onceness: onceness,
|
||||
region: region,
|
||||
sig: sig
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_bare_fn_ty(st: @pstate, conv: conv_did) -> ty::BareFnTy {
|
||||
let purity = parse_purity(next(st));
|
||||
let abi = parse_abi(next(st));
|
||||
let sig = parse_sig(st, conv);
|
||||
ty::BareFnTy {
|
||||
purity: purity,
|
||||
abi: abi,
|
||||
sig: sig
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_sig(st: @pstate, conv: conv_did) -> ty::FnSig {
|
||||
assert (next(st) == '[');
|
||||
let mut inputs: ~[ty::arg] = ~[];
|
||||
while peek(st) != ']' {
|
||||
|
@ -444,18 +470,9 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
|
|||
}
|
||||
st.pos += 1u; // eat the ']'
|
||||
let ret_ty = parse_ty(st, conv);
|
||||
return FnTyBase {
|
||||
meta: FnMeta {purity: purity,
|
||||
proto: proto,
|
||||
onceness: onceness,
|
||||
bounds: bounds,
|
||||
region: region},
|
||||
sig: FnSig {inputs: inputs,
|
||||
output: ret_ty}
|
||||
};
|
||||
ty::FnSig {inputs: inputs, output: ret_ty}
|
||||
}
|
||||
|
||||
|
||||
// Rust metadata parsing
|
||||
pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
|
||||
let mut colon_idx = 0u;
|
||||
|
|
|
@ -288,8 +288,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
|
|||
}
|
||||
w.write_char(']');
|
||||
}
|
||||
ty::ty_fn(ref f) => {
|
||||
enc_ty_fn(w, cx, (*f));
|
||||
ty::ty_closure(ref f) => {
|
||||
w.write_char('f');
|
||||
enc_closure_ty(w, cx, f);
|
||||
}
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
w.write_char('F');
|
||||
enc_bare_fn_ty(w, cx, f);
|
||||
}
|
||||
ty::ty_infer(_) => {
|
||||
cx.diag.handler().bug(~"Cannot encode inference variable types");
|
||||
|
@ -306,7 +311,7 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
|
|||
ty::ty_type => w.write_char('Y'),
|
||||
ty::ty_opaque_closure_ptr(p) => {
|
||||
w.write_str(&"C&");
|
||||
enc_proto(w, p);
|
||||
enc_sigil(w, p);
|
||||
}
|
||||
ty::ty_opaque_box => w.write_char('B'),
|
||||
ty::ty_struct(def, ref substs) => {
|
||||
|
@ -325,13 +330,11 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
|
|||
}
|
||||
}
|
||||
|
||||
fn enc_proto(w: io::Writer, proto: Proto) {
|
||||
w.write_str(&"f");
|
||||
match proto {
|
||||
ProtoBare => w.write_str(&"_"),
|
||||
ProtoBox => w.write_str(&"@"),
|
||||
ProtoUniq => w.write_str(&"~"),
|
||||
ProtoBorrowed => w.write_str(&"&"),
|
||||
fn enc_sigil(w: io::Writer, sigil: Sigil) {
|
||||
match sigil {
|
||||
ManagedSigil => w.write_str("@"),
|
||||
OwnedSigil => w.write_str("~"),
|
||||
BorrowedSigil => w.write_str("&"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,6 +360,12 @@ fn enc_purity(w: io::Writer, p: purity) {
|
|||
}
|
||||
}
|
||||
|
||||
fn enc_abi(w: io::Writer, a: Abi) {
|
||||
match a {
|
||||
RustAbi => w.write_char('r'),
|
||||
}
|
||||
}
|
||||
|
||||
fn enc_onceness(w: io::Writer, o: Onceness) {
|
||||
match o {
|
||||
Once => w.write_char('o'),
|
||||
|
@ -364,18 +373,27 @@ fn enc_onceness(w: io::Writer, o: Onceness) {
|
|||
}
|
||||
}
|
||||
|
||||
fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) {
|
||||
enc_proto(w, ft.meta.proto);
|
||||
enc_purity(w, ft.meta.purity);
|
||||
enc_onceness(w, ft.meta.onceness);
|
||||
enc_region(w, cx, ft.meta.region);
|
||||
enc_bounds(w, cx, ft.meta.bounds);
|
||||
fn enc_bare_fn_ty(w: io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
|
||||
enc_purity(w, ft.purity);
|
||||
enc_abi(w, ft.abi);
|
||||
enc_fn_sig(w, cx, &ft.sig);
|
||||
}
|
||||
|
||||
fn enc_closure_ty(w: io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
|
||||
enc_sigil(w, ft.sigil);
|
||||
enc_purity(w, ft.purity);
|
||||
enc_onceness(w, ft.onceness);
|
||||
enc_region(w, cx, ft.region);
|
||||
enc_fn_sig(w, cx, &ft.sig);
|
||||
}
|
||||
|
||||
fn enc_fn_sig(w: io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
|
||||
w.write_char('[');
|
||||
for ft.sig.inputs.each |arg| {
|
||||
for fsig.inputs.each |arg| {
|
||||
enc_arg(w, cx, *arg);
|
||||
}
|
||||
w.write_char(']');
|
||||
enc_ty(w, cx, ft.sig.output);
|
||||
enc_ty(w, cx, fsig.output);
|
||||
}
|
||||
|
||||
pub fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
|
||||
|
|
|
@ -221,18 +221,19 @@ impl check_loan_ctxt {
|
|||
|
||||
let callee_ty = ty::node_id_to_type(tcx, callee_id);
|
||||
match ty::get(callee_ty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
match fn_ty.meta.purity {
|
||||
ast::pure_fn => return, // case (c) above
|
||||
ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
|
||||
self.report_purity_error(
|
||||
pc, callee_span,
|
||||
fmt!("access to %s function",
|
||||
fn_ty.meta.purity.to_str()));
|
||||
}
|
||||
ty::ty_bare_fn(ty::BareFnTy {purity: purity, _}) |
|
||||
ty::ty_closure(ty::ClosureTy {purity: purity, _}) => {
|
||||
match purity {
|
||||
ast::pure_fn => return, // case (c) above
|
||||
ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
|
||||
self.report_purity_error(
|
||||
pc, callee_span,
|
||||
fmt!("access to %s function",
|
||||
purity.to_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return, // case (d) above
|
||||
_ => return, // case (d) above
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +241,11 @@ impl check_loan_ctxt {
|
|||
// The expression must be an expr_fn(*) or expr_fn_block(*)
|
||||
fn is_stack_closure(id: ast::node_id) -> bool {
|
||||
let fn_ty = ty::node_id_to_type(self.tcx(), id);
|
||||
let proto = ty::ty_fn_proto(fn_ty);
|
||||
return proto == ast::ProtoBorrowed;
|
||||
match ty::get(fn_ty).sty {
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
|
||||
_}) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_allowed_pure_arg(expr: @ast::expr) -> bool {
|
||||
|
@ -564,17 +568,27 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
|
|||
{
|
||||
let is_stack_closure = self.is_stack_closure(id);
|
||||
let fty = ty::node_id_to_type(self.tcx(), id);
|
||||
let fty_proto = ty::ty_fn_proto(fty);
|
||||
|
||||
check_moves_from_captured_variables(self, id, fty_proto);
|
||||
let declared_purity;
|
||||
match fk {
|
||||
visit::fk_item_fn(*) | visit::fk_method(*) |
|
||||
visit::fk_dtor(*) => {
|
||||
declared_purity = ty::ty_fn_purity(fty);
|
||||
}
|
||||
|
||||
visit::fk_anon(*) | visit::fk_fn_block(*) => {
|
||||
let fty_sigil = ty::ty_closure_sigil(fty);
|
||||
check_moves_from_captured_variables(self, id, fty_sigil);
|
||||
declared_purity = ty::determine_inherited_purity(
|
||||
copy self.declared_purity, ty::ty_fn_purity(fty),
|
||||
fty_sigil);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("purity on entry=%?", copy self.declared_purity);
|
||||
do save_and_restore(&mut(self.declared_purity)) {
|
||||
do save_and_restore(&mut(self.fn_args)) {
|
||||
self.declared_purity = ty::determine_inherited_purity(
|
||||
copy self.declared_purity,
|
||||
ty::ty_fn_purity(fty),
|
||||
fty_proto);
|
||||
self.declared_purity = declared_purity;
|
||||
|
||||
match fk {
|
||||
visit::fk_anon(*) |
|
||||
|
@ -608,10 +622,10 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
|
|||
|
||||
fn check_moves_from_captured_variables(&&self: check_loan_ctxt,
|
||||
id: ast::node_id,
|
||||
fty_proto: ast::Proto)
|
||||
fty_sigil: ast::Sigil)
|
||||
{
|
||||
match fty_proto {
|
||||
ast::ProtoBox | ast::ProtoUniq => {
|
||||
match fty_sigil {
|
||||
ast::ManagedSigil | ast::OwnedSigil => {
|
||||
let cap_vars = self.bccx.capture_map.get(&id);
|
||||
for cap_vars.each |cap_var| {
|
||||
match cap_var.mode {
|
||||
|
@ -646,7 +660,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
|
|||
}
|
||||
}
|
||||
|
||||
ast::ProtoBorrowed | ast::ProtoBare => {}
|
||||
ast::BorrowedSigil => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ pub fn check_expr(sess: Session,
|
|||
}
|
||||
}
|
||||
}
|
||||
expr_call(callee, _, false) => {
|
||||
expr_call(callee, _, NoSugar) => {
|
||||
match def_map.find(&callee.id) {
|
||||
Some(def_struct(*)) => {} // OK.
|
||||
Some(def_variant(*)) => {} // OK.
|
||||
|
|
|
@ -39,8 +39,8 @@ pub fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
|||
(v.visit_block)((*b), {in_loop: false, can_ret: false}, v);
|
||||
}
|
||||
expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => {
|
||||
let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e));
|
||||
let blk = (proto == ProtoBorrowed);
|
||||
let sigil = ty::ty_closure_sigil(ty::expr_ty(tcx, e));
|
||||
let blk = (sigil == BorrowedSigil);
|
||||
(v.visit_block)((*b), {in_loop: true, can_ret: blk}, v);
|
||||
}
|
||||
expr_break(_) => {
|
||||
|
|
|
@ -100,7 +100,7 @@ pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) {
|
|||
}
|
||||
_ => { /* We assume only enum types can be uninhabited */ }
|
||||
}
|
||||
let arms = vec::concat(vec::filter_map((*arms), unguarded_pat));
|
||||
let arms = vec::concat(arms.filter_mapped(unguarded_pat));
|
||||
check_exhaustive(cx, ex.span, arms);
|
||||
}
|
||||
_ => ()
|
||||
|
@ -255,7 +255,8 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful {
|
|||
}
|
||||
}
|
||||
Some(ref ctor) => {
|
||||
match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)),
|
||||
match is_useful(cx,
|
||||
vec::filter_map(m, |r| default(cx, r)),
|
||||
vec::tail(v)) {
|
||||
useful_ => useful(left_ty, (/*bad*/copy *ctor)),
|
||||
ref u => (/*bad*/copy *u)
|
||||
|
@ -277,8 +278,7 @@ pub fn is_useful_specialized(cx: @MatchCheckCtxt,
|
|||
arity: uint,
|
||||
lty: ty::t)
|
||||
-> useful {
|
||||
let ms = vec::filter_map(m, |r| specialize(cx, *r,
|
||||
ctor, arity, lty));
|
||||
let ms = m.filter_mapped(|r| specialize(cx, *r, ctor, arity, lty));
|
||||
let could_be_useful = is_useful(
|
||||
cx, ms, specialize(cx, v, ctor, arity, lty).get());
|
||||
match could_be_useful {
|
||||
|
@ -387,9 +387,9 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
|
|||
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
|
||||
|
||||
// Find the lengths and tails of all vector patterns.
|
||||
let vec_pat_lens = do m.filter_map |r| {
|
||||
match /*bad*/copy r[0].node {
|
||||
pat_vec(elems, tail) => {
|
||||
let vec_pat_lens = do m.filter_mapped |r| {
|
||||
match r[0].node {
|
||||
pat_vec(ref elems, ref tail) => {
|
||||
Some((elems.len(), tail.is_some()))
|
||||
}
|
||||
_ => None
|
||||
|
|
|
@ -48,10 +48,8 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk)
|
|||
|
||||
let walk_expr = fn@(expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
|
||||
match expr.node {
|
||||
ast::expr_fn(proto, _, _, _) => {
|
||||
if proto != ast::ProtoBare {
|
||||
visit::visit_expr(expr, depth + 1, v);
|
||||
}
|
||||
ast::expr_fn(_, _, _, _) => {
|
||||
visit::visit_expr(expr, depth + 1, v);
|
||||
}
|
||||
ast::expr_fn_block(*) => {
|
||||
visit::visit_expr(expr, depth + 1, v);
|
||||
|
|
|
@ -150,11 +150,23 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
|
|||
}
|
||||
|
||||
let fty = ty::node_id_to_type(cx.tcx, id);
|
||||
match ty::ty_fn_proto(fty) {
|
||||
ProtoUniq => b(check_for_uniq),
|
||||
ProtoBox => b(check_for_box),
|
||||
ProtoBare => b(check_for_bare),
|
||||
ProtoBorrowed => b(check_for_block),
|
||||
match ty::get(fty).sty {
|
||||
ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, _}) => {
|
||||
b(check_for_uniq)
|
||||
}
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, _}) => {
|
||||
b(check_for_box)
|
||||
}
|
||||
ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, _}) => {
|
||||
b(check_for_block)
|
||||
}
|
||||
ty::ty_bare_fn(_) => {
|
||||
b(check_for_bare)
|
||||
}
|
||||
ref s => {
|
||||
cx.tcx.sess.bug(
|
||||
fmt!("expect fn type in kind checker, not %?", s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,42 +252,6 @@ pub fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
|
|||
expr.span,
|
||||
"explicit copy requires a copyable argument");
|
||||
}
|
||||
expr_rec(ref fields, def) | expr_struct(_, ref fields, def) => {
|
||||
match def {
|
||||
Some(ex) => {
|
||||
// All noncopyable fields must be overridden
|
||||
let t = ty::expr_ty(cx.tcx, ex);
|
||||
let ty_fields = match ty::get(t).sty {
|
||||
ty::ty_rec(ref f) => {
|
||||
copy *f
|
||||
}
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
ty::struct_fields(cx.tcx, did, substs)
|
||||
}
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(
|
||||
ex.span,
|
||||
~"bad base expr type in record")
|
||||
}
|
||||
};
|
||||
for ty_fields.each |tf| {
|
||||
// If this field would not be copied, ok.
|
||||
if fields.any(|f| f.node.ident == tf.ident) { loop; }
|
||||
|
||||
// If this field is copyable, ok.
|
||||
let kind = ty::type_kind(cx.tcx, tf.mt.ty);
|
||||
if ty::kind_can_be_copied(kind) { loop; }
|
||||
|
||||
cx.tcx.sess.span_err(
|
||||
e.span,
|
||||
fmt!("cannot copy field `%s` of base expression, \
|
||||
which has a noncopyable type",
|
||||
*cx.tcx.sess.intr().get(tf.ident)));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
expr_repeat(element, count_expr, _) => {
|
||||
let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span);
|
||||
if count > 1 {
|
||||
|
|
|
@ -897,9 +897,10 @@ fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl,
|
|||
fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
|
||||
span: span, id: ast::node_id) {
|
||||
match ty::get(fn_ty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) |
|
||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) => {
|
||||
let mut counter = 0;
|
||||
for vec::each2(fn_ty.sig.inputs, decl.inputs) |arg_ty, arg_ast| {
|
||||
for vec::each2(sig.inputs, decl.inputs) |arg_ty, arg_ast| {
|
||||
counter += 1;
|
||||
debug!("arg %d, ty=%s, mode=%s",
|
||||
counter,
|
||||
|
@ -938,13 +939,14 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
|
|||
}
|
||||
|
||||
match ty::get(arg_ty.ty).sty {
|
||||
ty::ty_fn(*) => {
|
||||
ty::ty_closure(*) | ty::ty_bare_fn(*) => {
|
||||
let span = arg_ast.ty.span;
|
||||
// Recurse to check fn-type argument
|
||||
match arg_ast.ty.node {
|
||||
ast::ty_fn(f) => {
|
||||
ast::ty_closure(@ast::TyClosure{decl: ref d, _}) |
|
||||
ast::ty_bare_fn(@ast::TyBareFn{decl: ref d, _})=>{
|
||||
check_fn_deprecated_modes(tcx, arg_ty.ty,
|
||||
f.decl, span, id);
|
||||
*d, span, id);
|
||||
}
|
||||
ast::ty_path(*) => {
|
||||
// This is probably a typedef, so we can't
|
||||
|
@ -976,10 +978,11 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) {
|
|||
match it.node {
|
||||
ast::item_ty(ty, _) => {
|
||||
match ty.node {
|
||||
ast::ty_fn(f) => {
|
||||
ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
|
||||
ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
|
||||
let fn_ty = ty::node_id_to_type(tcx, it.id);
|
||||
check_fn_deprecated_modes(
|
||||
tcx, fn_ty, f.decl, ty.span, it.id)
|
||||
tcx, fn_ty, *decl, ty.span, it.id)
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
|
|
@ -146,63 +146,55 @@ pub enum deref_kind {deref_ptr(ptr_kind), deref_comp(comp_kind)}
|
|||
// pointer adjustment).
|
||||
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
Some(deref_ptr(uniq_ptr))
|
||||
}
|
||||
ty::ty_uniq(*) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_uniq) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
||||
Some(deref_ptr(uniq_ptr))
|
||||
}
|
||||
|
||||
ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoUniq => {
|
||||
Some(deref_ptr(uniq_ptr))
|
||||
}
|
||||
ty::ty_rptr(r, mt) |
|
||||
ty::ty_evec(mt, ty::vstore_slice(r)) => {
|
||||
Some(deref_ptr(region_ptr(mt.mutbl, r)))
|
||||
}
|
||||
|
||||
ty::ty_rptr(r, mt) |
|
||||
ty::ty_evec(mt, ty::vstore_slice(r)) => {
|
||||
Some(deref_ptr(region_ptr(mt.mutbl, r)))
|
||||
}
|
||||
ty::ty_estr(ty::vstore_slice(r)) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
|
||||
region: r, _}) => {
|
||||
Some(deref_ptr(region_ptr(ast::m_imm, r)))
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(r)) => {
|
||||
Some(deref_ptr(region_ptr(ast::m_imm, r)))
|
||||
}
|
||||
ty::ty_box(mt) |
|
||||
ty::ty_evec(mt, ty::vstore_box) => {
|
||||
Some(deref_ptr(gc_ptr(mt.mutbl)))
|
||||
}
|
||||
|
||||
ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBorrowed => {
|
||||
Some(deref_ptr(region_ptr(ast::m_imm, (*f).meta.region)))
|
||||
}
|
||||
ty::ty_estr(ty::vstore_box) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
|
||||
Some(deref_ptr(gc_ptr(ast::m_imm)))
|
||||
}
|
||||
|
||||
ty::ty_box(mt) |
|
||||
ty::ty_evec(mt, ty::vstore_box) => {
|
||||
Some(deref_ptr(gc_ptr(mt.mutbl)))
|
||||
}
|
||||
ty::ty_ptr(*) => {
|
||||
Some(deref_ptr(unsafe_ptr))
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
Some(deref_ptr(gc_ptr(ast::m_imm)))
|
||||
}
|
||||
ty::ty_enum(did, _) => {
|
||||
Some(deref_comp(comp_variant(did)))
|
||||
}
|
||||
|
||||
ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBox => {
|
||||
Some(deref_ptr(gc_ptr(ast::m_imm)))
|
||||
}
|
||||
ty::ty_struct(_, _) => {
|
||||
Some(deref_comp(comp_anon_field))
|
||||
}
|
||||
|
||||
ty::ty_ptr(*) => {
|
||||
Some(deref_ptr(unsafe_ptr))
|
||||
}
|
||||
ty::ty_evec(mt, ty::vstore_fixed(_)) => {
|
||||
Some(deref_comp(comp_index(t, mt.mutbl)))
|
||||
}
|
||||
|
||||
ty::ty_enum(did, _) => {
|
||||
Some(deref_comp(comp_variant(did)))
|
||||
}
|
||||
ty::ty_estr(ty::vstore_fixed(_)) => {
|
||||
Some(deref_comp(comp_index(t, m_imm)))
|
||||
}
|
||||
|
||||
ty::ty_struct(_, _) => {
|
||||
Some(deref_comp(comp_anon_field))
|
||||
}
|
||||
|
||||
ty::ty_evec(mt, ty::vstore_fixed(_)) => {
|
||||
Some(deref_comp(comp_index(t, mt.mutbl)))
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(_)) => {
|
||||
Some(deref_comp(comp_index(t, m_imm)))
|
||||
}
|
||||
|
||||
_ => None
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,9 +465,9 @@ pub impl &mem_categorization_ctxt {
|
|||
|
||||
ast::def_upvar(_, inner, fn_node_id, _) => {
|
||||
let ty = ty::node_id_to_type(self.tcx, fn_node_id);
|
||||
let proto = ty::ty_fn_proto(ty);
|
||||
match proto {
|
||||
ast::ProtoBorrowed => {
|
||||
let sigil = ty::ty_closure_sigil(ty);
|
||||
match sigil {
|
||||
ast::BorrowedSigil => {
|
||||
let upcmt = self.cat_def(id, span, expr_ty, *inner);
|
||||
@cmt_ {
|
||||
id:id,
|
||||
|
@ -486,7 +478,7 @@ pub impl &mem_categorization_ctxt {
|
|||
ty:upcmt.ty
|
||||
}
|
||||
}
|
||||
ast::ProtoUniq | ast::ProtoBox => {
|
||||
ast::OwnedSigil | ast::ManagedSigil => {
|
||||
// FIXME #2152 allow mutation of moved upvars
|
||||
@cmt_ {
|
||||
id:id,
|
||||
|
@ -497,11 +489,6 @@ pub impl &mem_categorization_ctxt {
|
|||
ty:expr_ty
|
||||
}
|
||||
}
|
||||
ast::ProtoBare => {
|
||||
self.tcx.sess.span_bug(
|
||||
span,
|
||||
fmt!("Upvar in a bare closure?"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -474,7 +474,35 @@ impl VisitContext {
|
|||
}
|
||||
|
||||
for opt_with.each |with_expr| {
|
||||
self.consume_expr(*with_expr, visitor);
|
||||
// If there are any fields whose type is move-by-default,
|
||||
// then `with` is consumed, otherwise it is only read
|
||||
let with_ty = ty::expr_ty(self.tcx, *with_expr);
|
||||
let with_fields = match ty::get(with_ty).sty {
|
||||
ty::ty_rec(ref f) => copy *f,
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
ty::struct_fields(self.tcx, did, substs)
|
||||
}
|
||||
ref r => {
|
||||
self.tcx.sess.span_bug(
|
||||
with_expr.span,
|
||||
fmt!("bad base expr type in record: %?", r))
|
||||
}
|
||||
};
|
||||
|
||||
// The `with` expr must be consumed if it contains
|
||||
// any fields which (1) were not explicitly
|
||||
// specified and (2) have a type that
|
||||
// moves-by-default:
|
||||
let consume_with = with_fields.any(|tf| {
|
||||
!fields.any(|f| f.node.ident == tf.ident) &&
|
||||
ty::type_implicitly_moves(self.tcx, tf.mt.ty)
|
||||
});
|
||||
|
||||
if consume_with {
|
||||
self.consume_expr(*with_expr, visitor);
|
||||
} else {
|
||||
self.use_expr(*with_expr, Read, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,9 +814,9 @@ impl VisitContext {
|
|||
let _indenter = indenter();
|
||||
|
||||
let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id);
|
||||
let proto = ty::ty_fn_proto(fn_ty);
|
||||
let sigil = ty::ty_closure_sigil(fn_ty);
|
||||
let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
|
||||
if proto == ProtoBorrowed {
|
||||
if sigil == BorrowedSigil {
|
||||
// &fn() captures everything by ref
|
||||
at_vec::from_fn(freevars.len(), |i| {
|
||||
let fvar = &freevars[i];
|
||||
|
|
|
@ -657,7 +657,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
|||
}
|
||||
}
|
||||
|
||||
ast::ty_fn(f) => {
|
||||
ast::ty_closure(ref f) => {
|
||||
debug!("referenced fn type: %s",
|
||||
pprust::ty_to_str(ty, cx.sess.intr()));
|
||||
match f.region {
|
||||
|
@ -668,7 +668,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
|||
}
|
||||
}
|
||||
None => {
|
||||
if f.proto == ast::ProtoBorrowed && cx.anon_implies_rp {
|
||||
if f.sigil == ast::BorrowedSigil && cx.anon_implies_rp {
|
||||
cx.add_rp(cx.item_id,
|
||||
cx.add_variance(rv_contravariant));
|
||||
}
|
||||
|
@ -732,18 +732,18 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
|||
}
|
||||
}
|
||||
|
||||
ast::ty_fn(f) => {
|
||||
ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
|
||||
ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
|
||||
// fn() binds the & region, so do not consider &T types that
|
||||
// appear *inside* a fn() type to affect the enclosing item:
|
||||
do cx.with(cx.item_id, false) {
|
||||
// parameters are contravariant
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for f.decl.inputs.each |a| {
|
||||
for decl.inputs.each |a| {
|
||||
(visitor.visit_ty)(a.ty, cx, visitor);
|
||||
}
|
||||
}
|
||||
visit::visit_ty_param_bounds(f.bounds, cx, visitor);
|
||||
(visitor.visit_ty)(f.decl.output, cx, visitor);
|
||||
(visitor.visit_ty)(decl.output, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1652,7 +1652,7 @@ pub fn trans_match_inner(scope_cx: block,
|
|||
// insert bindings into the lllocals map and add cleanups
|
||||
bcx = insert_lllocals(bcx, *arm_data, true);
|
||||
|
||||
bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest);
|
||||
bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest);
|
||||
bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
|
||||
arm_cxs.push(bcx);
|
||||
}
|
||||
|
|
|
@ -613,7 +613,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
|
|||
let ccx = cx.ccx();
|
||||
let mut cx = cx;
|
||||
match ty::get(fn_ty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
ty::ty_bare_fn(ref fn_ty) => {
|
||||
let mut j = 0u;
|
||||
let v_id = variant.id;
|
||||
for vec::each(fn_ty.sig.inputs) |a| {
|
||||
|
@ -777,10 +777,10 @@ pub fn trans_external_path(ccx: @crate_ctxt, did: ast::def_id, t: ty::t)
|
|||
-> ValueRef {
|
||||
let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad
|
||||
match ty::get(t).sty {
|
||||
ty::ty_fn(_) => {
|
||||
ty::ty_bare_fn(_) | ty::ty_closure(_) => {
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
return get_extern_fn(ccx.externs, ccx.llmod, name,
|
||||
lib::llvm::CCallConv, llty);
|
||||
lib::llvm::CCallConv, llty);
|
||||
}
|
||||
_ => {
|
||||
let llty = type_of(ccx, t);
|
||||
|
@ -1363,7 +1363,7 @@ pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<node_info>,
|
|||
DatumBlock {bcx: leave_block(bcx, scope_cx), datum: datum}
|
||||
}
|
||||
|
||||
pub fn block_locals(b: ast::blk, it: fn(@ast::local)) {
|
||||
pub fn block_locals(b: &ast::blk, it: fn(@ast::local)) {
|
||||
for vec::each(b.node.stmts) |s| {
|
||||
match s.node {
|
||||
ast::stmt_decl(d, _) => {
|
||||
|
@ -1727,8 +1727,8 @@ pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, }
|
|||
// returned.
|
||||
pub fn trans_closure(ccx: @crate_ctxt,
|
||||
+path: path,
|
||||
decl: ast::fn_decl,
|
||||
body: ast::blk,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::blk,
|
||||
llfndecl: ValueRef,
|
||||
ty_self: self_arg,
|
||||
+param_substs: Option<param_substs>,
|
||||
|
@ -1791,8 +1791,8 @@ pub fn trans_closure(ccx: @crate_ctxt,
|
|||
// function.
|
||||
pub fn trans_fn(ccx: @crate_ctxt,
|
||||
+path: path,
|
||||
decl: ast::fn_decl,
|
||||
body: ast::blk,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::blk,
|
||||
llfndecl: ValueRef,
|
||||
ty_self: self_arg,
|
||||
+param_substs: Option<param_substs>,
|
||||
|
@ -1935,7 +1935,7 @@ pub fn trans_tuple_struct(ccx: @crate_ctxt,
|
|||
|
||||
pub fn trans_struct_dtor(ccx: @crate_ctxt,
|
||||
+path: path,
|
||||
body: ast::blk,
|
||||
body: &ast::blk,
|
||||
dtor_id: ast::node_id,
|
||||
+psubsts: Option<param_substs>,
|
||||
hash_id: Option<mono_id>,
|
||||
|
@ -1966,8 +1966,9 @@ pub fn trans_struct_dtor(ccx: @crate_ctxt,
|
|||
ccx.monomorphized.insert(*h_id, lldecl);
|
||||
}
|
||||
/* Translate the dtor body */
|
||||
trans_fn(ccx, path, ast_util::dtor_dec(),
|
||||
body, lldecl, impl_self(class_ty), psubsts, dtor_id, None);
|
||||
let decl = ast_util::dtor_dec();
|
||||
trans_fn(ccx, path, &decl, body, lldecl,
|
||||
impl_self(class_ty), psubsts, dtor_id, None);
|
||||
lldecl
|
||||
}
|
||||
|
||||
|
@ -2013,20 +2014,19 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
|||
_ => die!(~"trans_item"),
|
||||
};
|
||||
match /*bad*/copy item.node {
|
||||
// XXX: Bad copies.
|
||||
ast::item_fn(copy decl, purity, copy tps, ref body) => {
|
||||
ast::item_fn(ref decl, purity, ref tps, ref body) => {
|
||||
if purity == ast::extern_fn {
|
||||
let llfndecl = get_item_val(ccx, item.id);
|
||||
foreign::trans_foreign_fn(ccx,
|
||||
vec::append(
|
||||
/*bad*/copy *path,
|
||||
~[path_name(item.ident)]),
|
||||
decl, (*body), llfndecl, item.id);
|
||||
decl, body, llfndecl, item.id);
|
||||
} else if tps.is_empty() {
|
||||
let llfndecl = get_item_val(ccx, item.id);
|
||||
trans_fn(ccx,
|
||||
vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
|
||||
decl, (*body), llfndecl, no_self, None, item.id, None);
|
||||
decl, body, llfndecl, no_self, None, item.id, None);
|
||||
} else {
|
||||
for vec::each((*body).node.stmts) |stmt| {
|
||||
match stmt.node {
|
||||
|
@ -2078,7 +2078,7 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
|
|||
id: ast::node_id) {
|
||||
// Translate the destructor.
|
||||
do option::iter(&struct_def.dtor) |dtor| {
|
||||
trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body,
|
||||
trans_struct_dtor(ccx, /*bad*/copy *path, &dtor.node.body,
|
||||
dtor.node.id, None, None, local_def(id));
|
||||
};
|
||||
|
||||
|
|
|
@ -627,18 +627,17 @@ pub fn trans_arg_expr(bcx: block,
|
|||
Some(_) => {
|
||||
match arg_expr.node {
|
||||
ast::expr_loop_body(
|
||||
// XXX: Bad copy.
|
||||
blk@@ast::expr {
|
||||
node: ast::expr_fn_block(copy decl, ref body),
|
||||
blk @ @ast::expr {
|
||||
node: ast::expr_fn_block(ref decl, ref body),
|
||||
_
|
||||
}) =>
|
||||
{
|
||||
let scratch_ty = expr_ty(bcx, arg_expr);
|
||||
let scratch = alloc_ty(bcx, scratch_ty);
|
||||
let arg_ty = expr_ty(bcx, arg_expr);
|
||||
let proto = ty::ty_fn_proto(arg_ty);
|
||||
let sigil = ty::ty_closure_sigil(arg_ty);
|
||||
let bcx = closure::trans_expr_fn(
|
||||
bcx, proto, decl, /*bad*/copy *body, arg_expr.id,
|
||||
bcx, sigil, decl, body, arg_expr.id,
|
||||
blk.id, Some(ret_flag), expr::SaveIn(scratch));
|
||||
DatumBlock {bcx: bcx,
|
||||
datum: Datum {val: scratch,
|
||||
|
|
|
@ -160,7 +160,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
|
|||
return cdata_ty;
|
||||
}
|
||||
|
||||
pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t)
|
||||
pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t)
|
||||
-> Result {
|
||||
let _icx = bcx.insn_ctxt("closure::allocate_cbox");
|
||||
let ccx = bcx.ccx(), tcx = ccx.tcx;
|
||||
|
@ -176,23 +176,19 @@ pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t)
|
|||
}
|
||||
|
||||
// Allocate and initialize the box:
|
||||
match proto {
|
||||
ast::ProtoBox => {
|
||||
match sigil {
|
||||
ast::ManagedSigil => {
|
||||
malloc_raw(bcx, cdata_ty, heap_shared)
|
||||
}
|
||||
ast::ProtoUniq => {
|
||||
ast::OwnedSigil => {
|
||||
malloc_raw(bcx, cdata_ty, heap_exchange)
|
||||
}
|
||||
ast::ProtoBorrowed => {
|
||||
ast::BorrowedSigil => {
|
||||
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
|
||||
let llbox = base::alloc_ty(bcx, cbox_ty);
|
||||
nuke_ref_count(bcx, llbox);
|
||||
rslt(bcx, llbox)
|
||||
}
|
||||
ast::ProtoBare => {
|
||||
let cdata_llty = type_of(bcx.ccx(), cdata_ty);
|
||||
rslt(bcx, C_null(cdata_llty))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +204,7 @@ pub type closure_result = {
|
|||
// Otherwise, it is stack allocated and copies pointers to the upvars.
|
||||
pub fn store_environment(bcx: block,
|
||||
bound_values: ~[EnvValue],
|
||||
proto: ast::Proto) -> closure_result {
|
||||
sigil: ast::Sigil) -> closure_result {
|
||||
let _icx = bcx.insn_ctxt("closure::store_environment");
|
||||
let ccx = bcx.ccx(), tcx = ccx.tcx;
|
||||
|
||||
|
@ -217,7 +213,7 @@ pub fn store_environment(bcx: block,
|
|||
let cdata_ty = mk_closure_tys(tcx, copy bound_values);
|
||||
|
||||
// allocate closure in the heap
|
||||
let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty);
|
||||
let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, sigil, cdata_ty);
|
||||
let mut temp_cleanups = ~[];
|
||||
|
||||
// cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
|
||||
|
@ -265,7 +261,7 @@ pub fn store_environment(bcx: block,
|
|||
// collects the upvars and packages them up for store_environment.
|
||||
pub fn build_closure(bcx0: block,
|
||||
cap_vars: &[moves::CaptureVar],
|
||||
proto: ast::Proto,
|
||||
sigil: ast::Sigil,
|
||||
include_ret_handle: Option<ValueRef>) -> closure_result {
|
||||
let _icx = bcx0.insn_ctxt("closure::build_closure");
|
||||
// If we need to, package up the iterator body to call
|
||||
|
@ -279,7 +275,7 @@ pub fn build_closure(bcx0: block,
|
|||
let datum = expr::trans_local_var(bcx, cap_var.def);
|
||||
match cap_var.mode {
|
||||
moves::CapRef => {
|
||||
assert proto == ast::ProtoBorrowed;
|
||||
assert sigil == ast::BorrowedSigil;
|
||||
env_vals.push(EnvValue {action: EnvRef,
|
||||
datum: datum});
|
||||
}
|
||||
|
@ -316,7 +312,7 @@ pub fn build_closure(bcx0: block,
|
|||
datum: ret_datum});
|
||||
}
|
||||
|
||||
return store_environment(bcx, env_vals, proto);
|
||||
return store_environment(bcx, env_vals, sigil);
|
||||
}
|
||||
|
||||
// Given an enclosing block context, a new function context, a closure type,
|
||||
|
@ -326,7 +322,7 @@ pub fn load_environment(fcx: fn_ctxt,
|
|||
cdata_ty: ty::t,
|
||||
cap_vars: &[moves::CaptureVar],
|
||||
load_ret_handle: bool,
|
||||
proto: ast::Proto) {
|
||||
sigil: ast::Sigil) {
|
||||
let _icx = fcx.insn_ctxt("closure::load_environment");
|
||||
|
||||
let llloadenv = match fcx.llloadenv {
|
||||
|
@ -352,9 +348,9 @@ pub fn load_environment(fcx: fn_ctxt,
|
|||
let mut i = 0u;
|
||||
for cap_vars.each |cap_var| {
|
||||
let mut upvarptr = GEPi(bcx, llcdata, [0u, i]);
|
||||
match proto {
|
||||
ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); }
|
||||
ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {}
|
||||
match sigil {
|
||||
ast::BorrowedSigil => { upvarptr = Load(bcx, upvarptr); }
|
||||
ast::ManagedSigil | ast::OwnedSigil => {}
|
||||
}
|
||||
let def_id = ast_util::def_id_of_def(cap_var.def);
|
||||
fcx.llupvars.insert(def_id.node, upvarptr);
|
||||
|
@ -369,9 +365,9 @@ pub fn load_environment(fcx: fn_ctxt,
|
|||
}
|
||||
|
||||
pub fn trans_expr_fn(bcx: block,
|
||||
proto: ast::Proto,
|
||||
+decl: ast::fn_decl,
|
||||
+body: ast::blk,
|
||||
sigil: ast::Sigil,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::blk,
|
||||
outer_id: ast::node_id,
|
||||
user_id: ast::node_id,
|
||||
is_loop_body: Option<Option<ValueRef>>,
|
||||
|
@ -381,7 +377,7 @@ pub fn trans_expr_fn(bcx: block,
|
|||
*
|
||||
* Translates the body of a closure expression.
|
||||
*
|
||||
* - `proto`
|
||||
* - `sigil`
|
||||
* - `decl`
|
||||
* - `body`
|
||||
* - `outer_id`: The id of the closure expression with the correct
|
||||
|
@ -417,18 +413,18 @@ pub fn trans_expr_fn(bcx: block,
|
|||
~"expr_fn");
|
||||
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
|
||||
|
||||
let Result {bcx: bcx, val: closure} = match proto {
|
||||
ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => {
|
||||
let Result {bcx: bcx, val: closure} = match sigil {
|
||||
ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => {
|
||||
let cap_vars = ccx.maps.capture_map.get(&user_id);
|
||||
let ret_handle = match is_loop_body {Some(x) => x,
|
||||
None => None};
|
||||
let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto,
|
||||
let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil,
|
||||
ret_handle);
|
||||
trans_closure(ccx, sub_path, decl,
|
||||
body, llfn, no_self,
|
||||
/*bad*/ copy bcx.fcx.param_substs, user_id, None,
|
||||
|fcx| load_environment(fcx, cdata_ty, cap_vars,
|
||||
ret_handle.is_some(), proto),
|
||||
ret_handle.is_some(), sigil),
|
||||
|bcx| {
|
||||
if is_loop_body.is_some() {
|
||||
Store(bcx, C_bool(true), bcx.fcx.llretptr);
|
||||
|
@ -436,34 +432,30 @@ pub fn trans_expr_fn(bcx: block,
|
|||
});
|
||||
rslt(bcx, llbox)
|
||||
}
|
||||
ast::ProtoBare => {
|
||||
trans_closure(ccx, sub_path, decl, body, llfn, no_self, None,
|
||||
user_id, None, |_fcx| { }, |_bcx| { });
|
||||
rslt(bcx, C_null(T_opaque_box_ptr(ccx)))
|
||||
}
|
||||
};
|
||||
fill_fn_pair(bcx, dest_addr, llfn, closure);
|
||||
|
||||
return bcx;
|
||||
}
|
||||
|
||||
pub fn make_fn_glue(cx: block,
|
||||
v: ValueRef,
|
||||
t: ty::t,
|
||||
glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block)
|
||||
-> block {
|
||||
let _icx = cx.insn_ctxt("closure::make_fn_glue");
|
||||
pub fn make_closure_glue(
|
||||
cx: block,
|
||||
v: ValueRef,
|
||||
t: ty::t,
|
||||
glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) -> block
|
||||
{
|
||||
let _icx = cx.insn_ctxt("closure::make_closure_glue");
|
||||
let bcx = cx;
|
||||
let tcx = cx.tcx();
|
||||
|
||||
let proto = ty::ty_fn_proto(t);
|
||||
match proto {
|
||||
ast::ProtoBare | ast::ProtoBorrowed => bcx,
|
||||
ast::ProtoUniq | ast::ProtoBox => {
|
||||
let sigil = ty::ty_closure_sigil(t);
|
||||
match sigil {
|
||||
ast::BorrowedSigil => bcx,
|
||||
ast::OwnedSigil | ast::ManagedSigil => {
|
||||
let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]);
|
||||
let box_ptr_v = Load(cx, box_cell_v);
|
||||
do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| {
|
||||
let closure_ty = ty::mk_opaque_closure_ptr(tcx, proto);
|
||||
let closure_ty = ty::mk_opaque_closure_ptr(tcx, sigil);
|
||||
glue_fn(bcx, box_cell_v, closure_ty)
|
||||
}
|
||||
}
|
||||
|
@ -472,20 +464,20 @@ pub fn make_fn_glue(cx: block,
|
|||
|
||||
pub fn make_opaque_cbox_take_glue(
|
||||
bcx: block,
|
||||
proto: ast::Proto,
|
||||
sigil: ast::Sigil,
|
||||
cboxptr: ValueRef) // ptr to ptr to the opaque closure
|
||||
-> block {
|
||||
// Easy cases:
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue");
|
||||
match proto {
|
||||
ast::ProtoBare | ast::ProtoBorrowed => {
|
||||
match sigil {
|
||||
ast::BorrowedSigil => {
|
||||
return bcx;
|
||||
}
|
||||
ast::ProtoBox => {
|
||||
ast::ManagedSigil => {
|
||||
glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr));
|
||||
return bcx;
|
||||
}
|
||||
ast::ProtoUniq => {
|
||||
ast::OwnedSigil => {
|
||||
/* hard case: fallthrough to code below */
|
||||
}
|
||||
}
|
||||
|
@ -531,36 +523,36 @@ pub fn make_opaque_cbox_take_glue(
|
|||
|
||||
pub fn make_opaque_cbox_drop_glue(
|
||||
bcx: block,
|
||||
proto: ast::Proto,
|
||||
sigil: ast::Sigil,
|
||||
cboxptr: ValueRef) // ptr to the opaque closure
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue");
|
||||
match proto {
|
||||
ast::ProtoBare | ast::ProtoBorrowed => bcx,
|
||||
ast::ProtoBox => {
|
||||
match sigil {
|
||||
ast::BorrowedSigil => bcx,
|
||||
ast::ManagedSigil => {
|
||||
glue::decr_refcnt_maybe_free(
|
||||
bcx, Load(bcx, cboxptr),
|
||||
ty::mk_opaque_closure_ptr(bcx.tcx(), proto))
|
||||
ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
|
||||
}
|
||||
ast::ProtoUniq => {
|
||||
ast::OwnedSigil => {
|
||||
glue::free_ty(
|
||||
bcx, cboxptr,
|
||||
ty::mk_opaque_closure_ptr(bcx.tcx(), proto))
|
||||
ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_opaque_cbox_free_glue(
|
||||
bcx: block,
|
||||
proto: ast::Proto,
|
||||
sigil: ast::Sigil,
|
||||
cbox: ValueRef) // ptr to ptr to the opaque closure
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue");
|
||||
match proto {
|
||||
ast::ProtoBare | ast::ProtoBorrowed => {
|
||||
match sigil {
|
||||
ast::BorrowedSigil => {
|
||||
return bcx;
|
||||
}
|
||||
ast::ProtoBox | ast::ProtoUniq => {
|
||||
ast::ManagedSigil | ast::OwnedSigil => {
|
||||
/* hard cases: fallthrough to code below */
|
||||
}
|
||||
}
|
||||
|
@ -580,10 +572,10 @@ pub fn make_opaque_cbox_free_glue(
|
|||
abi::tydesc_field_drop_glue, None);
|
||||
|
||||
// Free the ty descr (if necc) and the box itself
|
||||
match proto {
|
||||
ast::ProtoBox => glue::trans_free(bcx, cbox),
|
||||
ast::ProtoUniq => glue::trans_unique_free(bcx, cbox),
|
||||
ast::ProtoBare | ast::ProtoBorrowed => {
|
||||
match sigil {
|
||||
ast::ManagedSigil => glue::trans_free(bcx, cbox),
|
||||
ast::OwnedSigil => glue::trans_unique_free(bcx, cbox),
|
||||
ast::BorrowedSigil => {
|
||||
bcx.sess().bug(~"impossible")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn macros() {
|
|||
include!("macros.rs");
|
||||
}
|
||||
|
||||
pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block {
|
||||
pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_block");
|
||||
let mut bcx = bcx;
|
||||
do block_locals(b) |local| {
|
||||
|
@ -47,7 +47,7 @@ pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block {
|
|||
|
||||
pub fn trans_if(bcx: block,
|
||||
cond: @ast::expr,
|
||||
thn: ast::blk,
|
||||
thn: &ast::blk,
|
||||
els: Option<@ast::expr>,
|
||||
dest: expr::Dest)
|
||||
-> block {
|
||||
|
@ -82,10 +82,10 @@ pub fn trans_if(bcx: block,
|
|||
match elexpr.node {
|
||||
ast::expr_if(_, _, _) => {
|
||||
let elseif_blk = ast_util::block_from_expr(elexpr);
|
||||
trans_block(else_bcx_in, elseif_blk, dest)
|
||||
trans_block(else_bcx_in, &elseif_blk, dest)
|
||||
}
|
||||
ast::expr_block(ref blk) => {
|
||||
trans_block(else_bcx_in, (*blk), dest)
|
||||
trans_block(else_bcx_in, blk, dest)
|
||||
}
|
||||
// would be nice to have a constraint on ifs
|
||||
_ => bcx.tcx().sess.bug(~"strange alternative in if")
|
||||
|
@ -114,7 +114,7 @@ pub fn join_blocks(parent_bcx: block, in_cxs: ~[block]) -> block {
|
|||
return out;
|
||||
}
|
||||
|
||||
pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block {
|
||||
pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::blk) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_while");
|
||||
let next_bcx = sub_block(bcx, ~"while next");
|
||||
|
||||
|
@ -154,7 +154,7 @@ pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block {
|
|||
}
|
||||
|
||||
pub fn trans_loop(bcx:block,
|
||||
body: ast::blk,
|
||||
body: &ast::blk,
|
||||
opt_label: Option<ident>)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_loop");
|
||||
|
|
|
@ -475,10 +475,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
|
|||
return controlflow::trans_check_expr(bcx, expr, a, ~"Assertion");
|
||||
}
|
||||
ast::expr_while(cond, ref body) => {
|
||||
return controlflow::trans_while(bcx, cond, (*body));
|
||||
return controlflow::trans_while(bcx, cond, body);
|
||||
}
|
||||
ast::expr_loop(ref body, opt_label) => {
|
||||
return controlflow::trans_loop(bcx, (*body), opt_label);
|
||||
return controlflow::trans_loop(bcx, body, opt_label);
|
||||
}
|
||||
ast::expr_assign(dst, src) => {
|
||||
let src_datum = unpack_datum!(
|
||||
|
@ -530,7 +530,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
bcx.def(expr.id), dest);
|
||||
}
|
||||
ast::expr_if(cond, ref thn, els) => {
|
||||
return controlflow::trans_if(bcx, cond, *thn, els, dest);
|
||||
return controlflow::trans_if(bcx, cond, thn, els, dest);
|
||||
}
|
||||
ast::expr_match(discr, ref arms) => {
|
||||
return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms,
|
||||
|
@ -539,7 +539,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
ast::expr_block(ref blk) => {
|
||||
return do base::with_scope(bcx, blk.info(),
|
||||
~"block-expr body") |bcx| {
|
||||
controlflow::trans_block(bcx, (*blk), dest)
|
||||
controlflow::trans_block(bcx, blk, dest)
|
||||
};
|
||||
}
|
||||
ast::expr_rec(ref fields, base) |
|
||||
|
@ -562,58 +562,31 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
ast::expr_vec(*) | ast::expr_repeat(*) => {
|
||||
return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
|
||||
}
|
||||
// XXX: Bad copy.
|
||||
ast::expr_fn(proto, copy decl, ref body, _) => {
|
||||
// Don't use this function for anything real. Use the one in
|
||||
// astconv instead.
|
||||
return closure::trans_expr_fn(bcx, proto, decl,
|
||||
/*bad*/copy *body,
|
||||
ast::expr_fn(_, ref decl, ref body, _) |
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
let expr_ty = expr_ty(bcx, expr);
|
||||
let sigil = ty::ty_closure_sigil(expr_ty);
|
||||
debug!("translating fn_block %s with type %s",
|
||||
expr_to_str(expr, tcx.sess.intr()),
|
||||
ty_to_str(tcx, expr_ty));
|
||||
return closure::trans_expr_fn(bcx, sigil, decl, body,
|
||||
expr.id, expr.id,
|
||||
None, dest);
|
||||
}
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
let expr_ty = expr_ty(bcx, expr);
|
||||
match ty::get(expr_ty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
debug!("translating fn_block %s with type %s",
|
||||
expr_to_str(expr, tcx.sess.intr()),
|
||||
ty_to_str(tcx, expr_ty));
|
||||
return closure::trans_expr_fn(
|
||||
bcx, fn_ty.meta.proto, /*bad*/copy *decl,
|
||||
/*bad*/copy *body, expr.id, expr.id,
|
||||
None, dest);
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().impossible_case(
|
||||
expr.span, "fn_block has body with a non-fn type");
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_loop_body(blk) => {
|
||||
match ty::get(expr_ty(bcx, expr)).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
match blk.node {
|
||||
ast::expr_fn_block(copy decl, ref body) => {
|
||||
return closure::trans_expr_fn(
|
||||
bcx,
|
||||
fn_ty.meta.proto,
|
||||
decl,
|
||||
/*bad*/copy *body,
|
||||
expr.id,
|
||||
blk.id,
|
||||
Some(None),
|
||||
dest);
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().impossible_case(
|
||||
expr.span,
|
||||
"loop_body has the wrong kind of contents")
|
||||
}
|
||||
}
|
||||
let expr_ty = expr_ty(bcx, expr);
|
||||
let sigil = ty::ty_closure_sigil(expr_ty);
|
||||
match blk.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
return closure::trans_expr_fn(bcx, sigil,
|
||||
decl, body,
|
||||
expr.id, blk.id,
|
||||
Some(None), dest);
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().impossible_case(
|
||||
expr.span, "loop_body has body with a non-fn type")
|
||||
expr.span,
|
||||
"loop_body has the wrong kind of contents")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ use middle::trans::machine;
|
|||
use middle::trans::shape;
|
||||
use middle::trans::type_of::*;
|
||||
use middle::trans::type_of;
|
||||
use middle::ty::{FnTyBase, FnMeta, FnSig, arg};
|
||||
use middle::ty::{FnSig, arg};
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use core::libc::c_uint;
|
||||
|
@ -66,10 +66,8 @@ type c_stack_tys = {
|
|||
fn c_arg_and_ret_lltys(ccx: @crate_ctxt,
|
||||
id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) {
|
||||
match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
let llargtys = type_of_explicit_args(
|
||||
ccx,
|
||||
fn_ty.sig.inputs);
|
||||
ty::ty_bare_fn(ref fn_ty) => {
|
||||
let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs);
|
||||
let llretty = type_of::type_of(ccx, fn_ty.sig.output);
|
||||
(llargtys, llretty, fn_ty.sig.output)
|
||||
}
|
||||
|
@ -541,12 +539,11 @@ pub fn trans_intrinsic(ccx: @crate_ctxt,
|
|||
let star_u8 = ty::mk_imm_ptr(
|
||||
bcx.tcx(),
|
||||
ty::mk_mach_uint(bcx.tcx(), ast::ty_u8));
|
||||
let fty = ty::mk_fn(bcx.tcx(), FnTyBase {
|
||||
meta: FnMeta {purity: ast::impure_fn,
|
||||
proto: ast::ProtoBorrowed,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
bounds: @~[]},
|
||||
let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy {
|
||||
purity: ast::impure_fn,
|
||||
sigil: ast::BorrowedSigil,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy),
|
||||
ty: star_u8}],
|
||||
output: ty::mk_nil(bcx.tcx())}
|
||||
|
@ -843,14 +840,14 @@ pub fn trans_intrinsic(ccx: @crate_ctxt,
|
|||
|
||||
pub fn trans_foreign_fn(ccx: @crate_ctxt,
|
||||
+path: ast_map::path,
|
||||
decl: ast::fn_decl,
|
||||
body: ast::blk,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::blk,
|
||||
llwrapfn: ValueRef,
|
||||
id: ast::node_id) {
|
||||
let _icx = ccx.insn_ctxt("foreign::build_foreign_fn");
|
||||
|
||||
fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path,
|
||||
decl: ast::fn_decl, body: ast::blk,
|
||||
decl: &ast::fn_decl, body: &ast::blk,
|
||||
id: ast::node_id) -> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn");
|
||||
let t = ty::node_id_to_type(ccx.tcx, id);
|
||||
|
|
|
@ -172,7 +172,8 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
|||
|
||||
if field == abi::tydesc_field_free_glue {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_fn(*) |
|
||||
ty::ty_bare_fn(*) |
|
||||
ty::ty_closure(*) |
|
||||
ty::ty_box(*) |
|
||||
ty::ty_opaque_box |
|
||||
ty::ty_uniq(*) |
|
||||
|
@ -419,8 +420,8 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
|||
tvec::expand_boxed_vec_ty(bcx.tcx(), t));
|
||||
return;
|
||||
}
|
||||
ty::ty_fn(_) => {
|
||||
closure::make_fn_glue(bcx, v, t, free_ty)
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v, t, free_ty)
|
||||
}
|
||||
ty::ty_opaque_closure_ptr(ck) => {
|
||||
closure::make_opaque_cbox_free_glue(bcx, ck, v)
|
||||
|
@ -528,8 +529,8 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
|||
}
|
||||
}
|
||||
}
|
||||
ty::ty_fn(_) => {
|
||||
closure::make_fn_glue(bcx, v0, t, drop_ty)
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v0, t, drop_ty)
|
||||
}
|
||||
ty::ty_trait(_, _, ty::vstore_box) => {
|
||||
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
|
||||
|
@ -594,8 +595,8 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
|||
| ty::ty_estr(ty::vstore_slice(_)) => {
|
||||
bcx
|
||||
}
|
||||
ty::ty_fn(_) => {
|
||||
closure::make_fn_glue(bcx, v, t, take_ty)
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v, t, take_ty)
|
||||
}
|
||||
ty::ty_trait(_, _, ty::vstore_box) => {
|
||||
let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u]));
|
||||
|
|
|
@ -108,8 +108,8 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id,
|
|||
};
|
||||
trans_fn(ccx,
|
||||
path,
|
||||
mth.decl,
|
||||
mth.body,
|
||||
&mth.decl,
|
||||
&mth.body,
|
||||
llfn,
|
||||
self_kind,
|
||||
None,
|
||||
|
|
|
@ -34,8 +34,11 @@ pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
|
|||
ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
|
||||
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
|
||||
ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx),
|
||||
ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
|
||||
ty::ty_ptr(_) | ty::ty_rptr(*) => nilptr(tcx),
|
||||
|
||||
ty::ty_bare_fn(*) | // FIXME(#4804) Bare fn repr
|
||||
ty::ty_closure(*) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
|
||||
|
||||
ty::ty_evec(_, ty::vstore_slice(_)) |
|
||||
ty::ty_estr(ty::vstore_slice(_)) => {
|
||||
ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])
|
||||
|
|
|
@ -142,8 +142,8 @@ pub fn trans_method(ccx: @crate_ctxt,
|
|||
// generate the actual code
|
||||
trans_fn(ccx,
|
||||
path,
|
||||
method.decl,
|
||||
method.body,
|
||||
&method.decl,
|
||||
&method.body,
|
||||
llfn,
|
||||
self_arg,
|
||||
param_substs,
|
||||
|
@ -822,7 +822,7 @@ pub fn make_impl_vtable(ccx: @crate_ctxt,
|
|||
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
|
||||
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
|
||||
let fty = ty::subst_tps(tcx, substs, None,
|
||||
ty::mk_fn(tcx, copy im.fty));
|
||||
ty::mk_bare_fn(tcx, copy im.fty));
|
||||
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
|
||||
debug!("(making impl vtable) method has self or type params: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
|
|
|
@ -26,7 +26,7 @@ use middle::trans::shape;
|
|||
use middle::trans::type_of::type_of_fn_from_ty;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::type_use;
|
||||
use middle::ty::{FnTyBase, FnMeta, FnSig};
|
||||
use middle::ty::{FnSig};
|
||||
use middle::typeck;
|
||||
|
||||
use core::option;
|
||||
|
@ -166,12 +166,12 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
|
|||
let lldecl = match map_node {
|
||||
ast_map::node_item(i@@ast::item {
|
||||
// XXX: Bad copy.
|
||||
node: ast::item_fn(copy decl, _, _, ref body),
|
||||
node: ast::item_fn(ref decl, _, _, ref body),
|
||||
_
|
||||
}, _) => {
|
||||
let d = mk_lldecl();
|
||||
set_inline_hint_if_appr(/*bad*/copy i.attrs, d);
|
||||
trans_fn(ccx, pt, decl, *body, d, no_self, psubsts, fn_id.node, None);
|
||||
trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None);
|
||||
d
|
||||
}
|
||||
ast_map::node_item(*) => {
|
||||
|
@ -224,7 +224,7 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
|
|||
None => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \
|
||||
dtor")
|
||||
};
|
||||
trans_struct_dtor(ccx, /*bad*/copy *pt, dtor.node.body,
|
||||
trans_struct_dtor(ccx, /*bad*/copy *pt, &dtor.node.body,
|
||||
dtor.node.id, psubsts, Some(hash_id), parent_id)
|
||||
}
|
||||
ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
|
||||
|
@ -267,31 +267,34 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
|
|||
pub fn normalize_for_monomorphization(tcx: ty::ctxt,
|
||||
ty: ty::t) -> Option<ty::t> {
|
||||
// FIXME[mono] could do this recursively. is that worthwhile? (#2529)
|
||||
match ty::get(ty).sty {
|
||||
return match ty::get(ty).sty {
|
||||
ty::ty_box(*) => {
|
||||
Some(ty::mk_opaque_box(tcx))
|
||||
}
|
||||
ty::ty_fn(ref fty) => {
|
||||
Some(ty::mk_fn(
|
||||
ty::ty_bare_fn(_) => {
|
||||
Some(ty::mk_bare_fn(
|
||||
tcx,
|
||||
FnTyBase {meta: FnMeta {purity: ast::impure_fn,
|
||||
proto: fty.meta.proto,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_static,
|
||||
bounds: @~[]},
|
||||
sig: FnSig {inputs: ~[],
|
||||
output: ty::mk_nil(tcx)}}))
|
||||
ty::BareFnTy {
|
||||
purity: ast::impure_fn,
|
||||
abi: ast::RustAbi,
|
||||
sig: FnSig {inputs: ~[],
|
||||
output: ty::mk_nil(tcx)}}))
|
||||
}
|
||||
ty::ty_trait(_, _, _) => {
|
||||
Some(ty::mk_fn(
|
||||
tcx,
|
||||
FnTyBase {meta: FnMeta {purity: ast::impure_fn,
|
||||
proto: ast::ProtoBox,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_static,
|
||||
bounds: @~[]},
|
||||
sig: FnSig {inputs: ~[],
|
||||
output: ty::mk_nil(tcx)}}))
|
||||
ty::ty_closure(ref fty) => {
|
||||
Some(normalized_closure_ty(tcx, fty.sigil))
|
||||
}
|
||||
ty::ty_trait(_, _, ref vstore) => {
|
||||
let sigil = match *vstore {
|
||||
ty::vstore_uniq => ast::OwnedSigil,
|
||||
ty::vstore_box => ast::ManagedSigil,
|
||||
ty::vstore_slice(_) => ast::BorrowedSigil,
|
||||
ty::vstore_fixed(*) => {
|
||||
tcx.sess.bug(fmt!("ty_trait with vstore_fixed"));
|
||||
}
|
||||
};
|
||||
|
||||
// Traits have the same runtime representation as closures.
|
||||
Some(normalized_closure_ty(tcx, sigil))
|
||||
}
|
||||
ty::ty_ptr(_) => {
|
||||
Some(ty::mk_uint(tcx))
|
||||
|
@ -299,6 +302,20 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
|
|||
_ => {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
fn normalized_closure_ty(tcx: ty::ctxt,
|
||||
sigil: ast::Sigil) -> ty::t
|
||||
{
|
||||
ty::mk_closure(
|
||||
tcx,
|
||||
ty::ClosureTy {
|
||||
purity: ast::impure_fn,
|
||||
sigil: sigil,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_static,
|
||||
sig: ty::FnSig {inputs: ~[],
|
||||
output: ty::mk_nil(tcx)}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,8 @@ pub impl reflector {
|
|||
tcx.sess.ident_of(~"visit_" + ty_name),
|
||||
*self.visitor_methods).expect(fmt!("Couldn't find visit method \
|
||||
for %s", ty_name));
|
||||
let mth_ty = ty::mk_fn(
|
||||
tcx,
|
||||
/*bad*/copy self.visitor_methods[mth_idx].fty);
|
||||
let mth_ty =
|
||||
ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
|
||||
let v = self.visitor_val;
|
||||
debug!("passing %u args:", vec::len(args));
|
||||
let bcx = self.bcx;
|
||||
|
@ -211,39 +210,33 @@ pub impl reflector {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME (#2594): fetch constants out of intrinsic:: for the
|
||||
// numbers.
|
||||
ty::ty_fn(ref fty) => {
|
||||
let pureval = match fty.meta.purity {
|
||||
ast::pure_fn => 0u,
|
||||
ast::unsafe_fn => 1u,
|
||||
ast::impure_fn => 2u,
|
||||
ast::extern_fn => 3u
|
||||
};
|
||||
let protoval = ast_proto_constant(fty.meta.proto);
|
||||
// FIXME (#2594): fetch constants out of intrinsic
|
||||
// FIXME (#4809): visitor should break out bare fns from other fns
|
||||
ty::ty_closure(ref fty) => {
|
||||
let pureval = ast_purity_constant(fty.purity);
|
||||
let sigilval = ast_sigil_constant(fty.sigil);
|
||||
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
|
||||
let extra = ~[self.c_uint(pureval),
|
||||
self.c_uint(protoval),
|
||||
self.c_uint(sigilval),
|
||||
self.c_uint(vec::len(fty.sig.inputs)),
|
||||
self.c_uint(retval)];
|
||||
self.visit(~"enter_fn", copy extra); // XXX: Bad copy.
|
||||
for fty.sig.inputs.eachi |i, arg| {
|
||||
let modeval = match arg.mode {
|
||||
ast::infer(_) => 0u,
|
||||
ast::expl(e) => match e {
|
||||
ast::by_ref => 1u,
|
||||
ast::by_val => 2u,
|
||||
ast::by_copy => 5u
|
||||
}
|
||||
};
|
||||
self.visit(~"fn_input",
|
||||
~[self.c_uint(i),
|
||||
self.c_uint(modeval),
|
||||
self.c_tydesc(arg.ty)]);
|
||||
}
|
||||
self.visit(~"fn_output",
|
||||
~[self.c_uint(retval),
|
||||
self.c_tydesc(fty.sig.output)]);
|
||||
self.visit_sig(retval, &fty.sig);
|
||||
self.visit(~"leave_fn", extra);
|
||||
}
|
||||
|
||||
// FIXME (#2594): fetch constants out of intrinsic:: for the
|
||||
// numbers.
|
||||
ty::ty_bare_fn(ref fty) => {
|
||||
let pureval = ast_purity_constant(fty.purity);
|
||||
let sigilval = 0u;
|
||||
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
|
||||
let extra = ~[self.c_uint(pureval),
|
||||
self.c_uint(sigilval),
|
||||
self.c_uint(vec::len(fty.sig.inputs)),
|
||||
self.c_uint(retval)];
|
||||
self.visit(~"enter_fn", copy extra); // XXX: Bad copy.
|
||||
self.visit_sig(retval, &fty.sig);
|
||||
self.visit(~"leave_fn", extra);
|
||||
}
|
||||
|
||||
|
@ -302,11 +295,31 @@ pub impl reflector {
|
|||
ty::ty_type => self.leaf(~"type"),
|
||||
ty::ty_opaque_box => self.leaf(~"opaque_box"),
|
||||
ty::ty_opaque_closure_ptr(ck) => {
|
||||
let ckval = ast_proto_constant(ck);
|
||||
let ckval = ast_sigil_constant(ck);
|
||||
self.visit(~"closure_ptr", ~[self.c_uint(ckval)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_sig(&self, retval: uint, sig: &ty::FnSig) {
|
||||
for sig.inputs.eachi |i, arg| {
|
||||
let modeval = match arg.mode {
|
||||
ast::infer(_) => 0u,
|
||||
ast::expl(e) => match e {
|
||||
ast::by_ref => 1u,
|
||||
ast::by_val => 2u,
|
||||
ast::by_copy => 5u
|
||||
}
|
||||
};
|
||||
self.visit(~"fn_input",
|
||||
~[self.c_uint(i),
|
||||
self.c_uint(modeval),
|
||||
self.c_tydesc(arg.ty)]);
|
||||
}
|
||||
self.visit(~"fn_output",
|
||||
~[self.c_uint(retval),
|
||||
self.c_tydesc(sig.output)]);
|
||||
}
|
||||
}
|
||||
|
||||
// Emit a sequence of calls to visit_ty::visit_foo
|
||||
|
@ -332,12 +345,20 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
|
|||
return final;
|
||||
}
|
||||
|
||||
pub fn ast_proto_constant(proto: ast::Proto) -> uint {
|
||||
match proto {
|
||||
ast::ProtoBare => 0u,
|
||||
ast::ProtoUniq => 2u,
|
||||
ast::ProtoBox => 3u,
|
||||
ast::ProtoBorrowed => 4u,
|
||||
pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint {
|
||||
match sigil {
|
||||
ast::OwnedSigil => 2u,
|
||||
ast::ManagedSigil => 3u,
|
||||
ast::BorrowedSigil => 4u,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_purity_constant(purity: ast::purity) -> uint {
|
||||
match purity {
|
||||
ast::pure_fn => 0u,
|
||||
ast::unsafe_fn => 1u,
|
||||
ast::impure_fn => 2u,
|
||||
ast::extern_fn => 3u
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,13 @@ pub fn type_of_fn(cx: @crate_ctxt, inputs: &[ty::arg],
|
|||
|
||||
// Given a function type and a count of ty params, construct an llvm type
|
||||
pub fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
|
||||
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
|
||||
match ty::get(fty).sty {
|
||||
ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
_ => {
|
||||
cx.sess.bug(~"type_of_fn_from_ty given non-closure, non-bare-fn")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
|
||||
|
@ -170,7 +176,11 @@ pub fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
|
|||
// structs
|
||||
T_struct(~[T_struct(tys)])
|
||||
}
|
||||
ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
|
||||
// FIXME(#4804) Bare fn repr
|
||||
// ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_bare_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_closure(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
|
||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||
ty::ty_tup(elts) => {
|
||||
|
|
|
@ -69,8 +69,9 @@ pub fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
|||
|
||||
let cx = {ccx: ccx, uses: vec::cast_to_mut(vec::from_elem(n_tps, 0u))};
|
||||
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
for vec::each(fn_ty.sig.inputs) |arg| {
|
||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
|
||||
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
|
||||
for vec::each(sig.inputs) |arg| {
|
||||
match ty::resolved_mode(ccx.tcx, arg.mode) {
|
||||
by_val | by_copy => {
|
||||
type_needs(cx, use_repr, arg.ty);
|
||||
|
@ -197,8 +198,12 @@ pub fn type_needs_inner(cx: ctx,
|
|||
it, we depend on the drop glue for T (we have to write the
|
||||
right tydesc into the result)
|
||||
*/
|
||||
ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _)
|
||||
| ty::ty_trait(_, _, _) => false,
|
||||
ty::ty_closure(*) |
|
||||
ty::ty_bare_fn(*) |
|
||||
ty::ty_ptr(_) |
|
||||
ty::ty_rptr(_, _) |
|
||||
ty::ty_trait(_, _, _) => false,
|
||||
|
||||
ty::ty_enum(did, ref substs) => {
|
||||
if option::is_none(&list::find(enums_seen, |id| *id == did)) {
|
||||
let seen = @Cons(did, enums_seen);
|
||||
|
@ -287,15 +292,15 @@ pub fn mark_for_expr(cx: ctx, e: @expr) {
|
|||
}
|
||||
}
|
||||
expr_fn(*) | expr_fn_block(*) => {
|
||||
match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
|
||||
ast::ProtoBare | ast::ProtoUniq => {}
|
||||
ast::ProtoBox | ast::ProtoBorrowed => {
|
||||
for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| {
|
||||
let node_id = ast_util::def_id_of_def(fv.def).node;
|
||||
node_type_needs(cx, use_repr, node_id);
|
||||
}
|
||||
match ty::ty_closure_sigil(ty::expr_ty(cx.ccx.tcx, e)) {
|
||||
ast::OwnedSigil => {}
|
||||
ast::BorrowedSigil | ast::ManagedSigil => {
|
||||
for freevars::get_freevars(cx.ccx.tcx, e.id).each |fv| {
|
||||
let node_id = ast_util::def_id_of_def(fv.def).node;
|
||||
node_type_needs(cx, use_repr, node_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
|
||||
expr_ret(Some(val)) => {
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[warn(deprecated_pattern)];
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use driver::session;
|
||||
|
@ -27,7 +25,7 @@ use middle;
|
|||
use session::Session;
|
||||
use util::ppaux::{note_and_explain_region, bound_region_to_str};
|
||||
use util::ppaux::{region_to_str, explain_region, vstore_to_str};
|
||||
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
|
||||
use util::ppaux::{ty_to_str, tys_to_str};
|
||||
|
||||
use core::cast;
|
||||
use core::cmp;
|
||||
|
@ -73,7 +71,7 @@ pub type param_bounds = @~[param_bound];
|
|||
pub type method = {
|
||||
ident: ast::ident,
|
||||
tps: @~[param_bounds],
|
||||
fty: FnTy,
|
||||
fty: BareFnTy,
|
||||
self_ty: ast::self_ty_,
|
||||
vis: ast::visibility,
|
||||
def_id: ast::def_id
|
||||
|
@ -344,22 +342,20 @@ pub pure fn type_contains_err(t: t) -> bool {
|
|||
pub pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
|
||||
pub pure fn type_id(t: t) -> uint { get(t).id }
|
||||
|
||||
/**
|
||||
* Meta information about a closure.
|
||||
*
|
||||
* - `purity` is the function's effect (pure, impure, unsafe).
|
||||
* - `proto` is the protocol (fn@, fn~, etc).
|
||||
* - `onceness` indicates whether the function can be called one time or many
|
||||
* times.
|
||||
* - `region` is the region bound on the function's upvars (often &static).
|
||||
* - `bounds` is the parameter bounds on the function's upvars. */
|
||||
#[deriving_eq]
|
||||
pub struct FnMeta {
|
||||
pub struct BareFnTy {
|
||||
purity: ast::purity,
|
||||
proto: ast::Proto,
|
||||
abi: Abi,
|
||||
sig: FnSig
|
||||
}
|
||||
|
||||
#[deriving_eq]
|
||||
pub struct ClosureTy {
|
||||
purity: ast::purity,
|
||||
sigil: ast::Sigil,
|
||||
onceness: ast::Onceness,
|
||||
region: Region,
|
||||
bounds: @~[param_bound]
|
||||
sig: FnSig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -374,24 +370,18 @@ pub struct FnSig {
|
|||
output: t
|
||||
}
|
||||
|
||||
/**
|
||||
* Function type: combines the meta information and the
|
||||
* type signature. This particular type is parameterized
|
||||
* by the meta information because, in some cases, the
|
||||
* meta information is inferred. */
|
||||
#[deriving_eq]
|
||||
pub struct FnTyBase<M> {
|
||||
meta: M, // Either FnMeta or FnVid
|
||||
sig: FnSig // Types of arguments/return type
|
||||
}
|
||||
|
||||
impl<M: to_bytes::IterBytes> FnTyBase<M> : to_bytes::IterBytes {
|
||||
impl BareFnTy : to_bytes::IterBytes {
|
||||
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
|
||||
to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f)
|
||||
to_bytes::iter_bytes_3(&self.purity, &self.abi, &self.sig, lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub type FnTy = FnTyBase<FnMeta>;
|
||||
impl ClosureTy : to_bytes::IterBytes {
|
||||
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
|
||||
to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness,
|
||||
&self.region, &self.sig, lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving_eq]
|
||||
pub struct param_ty {
|
||||
|
@ -491,6 +481,7 @@ pub struct substs {
|
|||
|
||||
// NB: If you change this, you'll probably want to change the corresponding
|
||||
// AST structure in libsyntax/ast.rs as well.
|
||||
#[deriving_eq]
|
||||
pub enum sty {
|
||||
ty_nil,
|
||||
ty_bot,
|
||||
|
@ -506,7 +497,8 @@ pub enum sty {
|
|||
ty_ptr(mt),
|
||||
ty_rptr(Region, mt),
|
||||
ty_rec(~[field]),
|
||||
ty_fn(FnTy),
|
||||
ty_bare_fn(BareFnTy),
|
||||
ty_closure(ClosureTy),
|
||||
ty_trait(def_id, substs, vstore),
|
||||
ty_struct(def_id, substs),
|
||||
ty_tup(~[t]),
|
||||
|
@ -522,7 +514,7 @@ pub enum sty {
|
|||
// "Fake" types, used for trans purposes
|
||||
ty_type, // type_desc*
|
||||
ty_opaque_box, // used by monomorphizer to represent any @ box
|
||||
ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~
|
||||
ty_opaque_closure_ptr(Sigil), // ptr to env for fn, fn@, fn~
|
||||
ty_unboxed_vec(mt),
|
||||
}
|
||||
|
||||
|
@ -546,8 +538,9 @@ pub enum type_err {
|
|||
terr_mismatch,
|
||||
terr_purity_mismatch(expected_found<purity>),
|
||||
terr_onceness_mismatch(expected_found<Onceness>),
|
||||
terr_abi_mismatch(expected_found<ast::Abi>),
|
||||
terr_mutability,
|
||||
terr_proto_mismatch(expected_found<ast::Proto>),
|
||||
terr_sigil_mismatch(expected_found<ast::Sigil>),
|
||||
terr_box_mutability,
|
||||
terr_ptr_mutability,
|
||||
terr_ref_mutability,
|
||||
|
@ -744,6 +737,15 @@ pub impl RegionVid : to_bytes::IterBytes {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn kind_to_param_bounds(kind: Kind) -> param_bounds {
|
||||
let mut bounds = ~[];
|
||||
if kind_can_be_copied(kind) { bounds.push(bound_copy); }
|
||||
if kind_can_be_sent(kind) { bounds.push(bound_owned); }
|
||||
else if kind_is_durable(kind) { bounds.push(bound_durable); }
|
||||
if kind_is_const(kind) { bounds.push(bound_const); }
|
||||
return @bounds;
|
||||
}
|
||||
|
||||
pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
|
||||
let mut kind = kind_noncopyable();
|
||||
for vec::each(*bounds) |bound| {
|
||||
|
@ -925,8 +927,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
|
|||
}
|
||||
&ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
|
||||
&ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
|
||||
&ty_fn(ref f) => {
|
||||
flags |= rflags(f.meta.region);
|
||||
&ty_bare_fn(ref f) => {
|
||||
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
|
||||
flags |= get(f.sig.output).flags;
|
||||
}
|
||||
&ty_closure(ref f) => {
|
||||
flags |= rflags(f.region);
|
||||
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
|
||||
flags |= get(f.sig.output).flags;
|
||||
}
|
||||
|
@ -1044,8 +1050,25 @@ pub fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
|
|||
|
||||
pub fn mk_tup(cx: ctxt, +ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
|
||||
|
||||
// take a copy because we want to own the various vectors inside
|
||||
pub fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) }
|
||||
pub fn mk_closure(cx: ctxt, +fty: ClosureTy) -> t {
|
||||
mk_t(cx, ty_closure(fty))
|
||||
}
|
||||
|
||||
pub fn mk_bare_fn(cx: ctxt, +fty: BareFnTy) -> t {
|
||||
mk_t(cx, ty_bare_fn(fty))
|
||||
}
|
||||
|
||||
pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
|
||||
let input_args = input_tys.map(|t| arg {mode: ast::expl(ast::by_copy),
|
||||
ty: *t});
|
||||
mk_bare_fn(cx,
|
||||
BareFnTy {
|
||||
purity: ast::pure_fn,
|
||||
abi: ast::RustAbi,
|
||||
sig: FnSig {inputs: input_args,
|
||||
output: output}})
|
||||
}
|
||||
|
||||
|
||||
pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
|
||||
-> t {
|
||||
|
@ -1074,8 +1097,8 @@ pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
|
|||
|
||||
pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
|
||||
|
||||
pub fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t {
|
||||
mk_t(cx, ty_opaque_closure_ptr(proto))
|
||||
pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
|
||||
mk_t(cx, ty_opaque_closure_ptr(sigil))
|
||||
}
|
||||
|
||||
pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
|
||||
|
@ -1097,13 +1120,11 @@ pub pure fn mach_sty(cfg: @session::config, t: t) -> sty {
|
|||
pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
|
||||
// FIXME(#2202) --- We retain by-ref for fn& things to workaround a
|
||||
// memory leak that otherwise results when @fn is upcast to &fn.
|
||||
if type_is_fn(ty) {
|
||||
match ty_fn_proto(ty) {
|
||||
ast::ProtoBorrowed => {
|
||||
return ast::by_ref;
|
||||
}
|
||||
_ => {}
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_closure(ClosureTy {sigil: ast::BorrowedSigil, _}) => {
|
||||
return ast::by_ref;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return if tcx.legacy_modes {
|
||||
if type_is_borrowed(ty) {
|
||||
|
@ -1119,13 +1140,6 @@ pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
|
|||
ast::by_copy
|
||||
};
|
||||
|
||||
fn type_is_fn(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_fn(*) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn type_is_borrowed(ty: t) -> bool {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_rptr(*) => true,
|
||||
|
@ -1171,7 +1185,11 @@ pub fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
|
|||
for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
|
||||
}
|
||||
ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
|
||||
ty_fn(ref ft) => {
|
||||
ty_bare_fn(ref ft) => {
|
||||
for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
|
||||
maybe_walk_ty(ft.sig.output, f);
|
||||
}
|
||||
ty_closure(ref ft) => {
|
||||
for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
|
||||
maybe_walk_ty(ft.sig.output, f);
|
||||
}
|
||||
|
@ -1235,9 +1253,13 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
|
|||
let new_ts = vec::map(ts, |tt| fldop(*tt));
|
||||
ty_tup(new_ts)
|
||||
}
|
||||
ty_fn(ref f) => {
|
||||
ty_bare_fn(ref f) => {
|
||||
let sig = fold_sig(&f.sig, fldop);
|
||||
ty_fn(FnTyBase {meta: f.meta, sig: sig})
|
||||
ty_bare_fn(BareFnTy {sig: sig, abi: f.abi, purity: f.purity})
|
||||
}
|
||||
ty_closure(ref f) => {
|
||||
let sig = fold_sig(&f.sig, fldop);
|
||||
ty_closure(ClosureTy {sig: sig, ..copy *f})
|
||||
}
|
||||
ty_rptr(r, tm) => {
|
||||
ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
|
||||
|
@ -1318,10 +1340,14 @@ pub fn fold_regions_and_ty(
|
|||
ty_trait(def_id, ref substs, vst) => {
|
||||
ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
|
||||
}
|
||||
ty_fn(ref f) => {
|
||||
ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region),
|
||||
..f.meta},
|
||||
sig: fold_sig(&f.sig, fldfnt)})
|
||||
ty_bare_fn(ref f) => {
|
||||
ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
|
||||
..copy *f})
|
||||
}
|
||||
ty_closure(ref f) => {
|
||||
ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
|
||||
sig: fold_sig(&f.sig, fldfnt),
|
||||
..copy *f})
|
||||
}
|
||||
ref sty => {
|
||||
fold_sty_to_ty(cx, sty, |t| fldt(t))
|
||||
|
@ -1329,30 +1355,6 @@ pub fn fold_regions_and_ty(
|
|||
}
|
||||
}
|
||||
|
||||
/* A little utility: it often happens that I have a `fn_ty`,
|
||||
* but I want to use some function like `fold_regions_and_ty()`
|
||||
* that is defined over all types. This utility converts to
|
||||
* a full type and back. It's not the best way to do this (somewhat
|
||||
* inefficient to do the conversion), it would be better to refactor
|
||||
* all this folding business. However, I've been waiting on that
|
||||
* until trait support is improved. */
|
||||
pub fn apply_op_on_t_to_ty_fn(
|
||||
cx: ctxt,
|
||||
f: &FnTy,
|
||||
t_op: fn(t) -> t) -> FnTy
|
||||
{
|
||||
let t0 = ty::mk_fn(cx, /*bad*/copy *f);
|
||||
let t1 = t_op(t0);
|
||||
match ty::get(t1).sty {
|
||||
ty::ty_fn(copy f) => {
|
||||
move f
|
||||
}
|
||||
_ => {
|
||||
cx.sess.bug(~"`t_op` did not return a function type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// n.b. this function is intended to eventually replace fold_region() below,
|
||||
// that is why its name is so similar.
|
||||
pub fn fold_regions(
|
||||
|
@ -1372,41 +1374,6 @@ pub fn fold_regions(
|
|||
do_fold(cx, ty, false, fldr)
|
||||
}
|
||||
|
||||
pub fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t {
|
||||
fn do_fold(cx: ctxt, t0: t, under_r: bool,
|
||||
fldop: fn(Region, bool) -> Region) -> t {
|
||||
let tb = get(t0);
|
||||
if !tbox_has_flag(tb, has_regions) { return t0; }
|
||||
match tb.sty {
|
||||
ty_rptr(r, mt {ty: t1, mutbl: m}) => {
|
||||
let m_r = fldop(r, under_r);
|
||||
let m_t1 = do_fold(cx, t1, true, fldop);
|
||||
ty::mk_rptr(cx, m_r, mt {ty: m_t1, mutbl: m})
|
||||
}
|
||||
ty_estr(vstore_slice(r)) => {
|
||||
let m_r = fldop(r, under_r);
|
||||
ty::mk_estr(cx, vstore_slice(m_r))
|
||||
}
|
||||
ty_evec(mt {ty: t1, mutbl: m}, vstore_slice(r)) => {
|
||||
let m_r = fldop(r, under_r);
|
||||
let m_t1 = do_fold(cx, t1, true, fldop);
|
||||
ty::mk_evec(cx, mt {ty: m_t1, mutbl: m}, vstore_slice(m_r))
|
||||
}
|
||||
ty_fn(_) => {
|
||||
// do not recurse into functions, which introduce fresh bindings
|
||||
t0
|
||||
}
|
||||
ref sty => {
|
||||
do fold_sty_to_ty(cx, sty) |t| {
|
||||
do_fold(cx, t, under_r, fldop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_fold(cx, t0, false, fldop)
|
||||
}
|
||||
|
||||
// Substitute *only* type parameters. Used in trans where regions are erased.
|
||||
pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
|
||||
if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
|
||||
|
@ -1529,7 +1496,9 @@ pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
|
|||
|
||||
pub fn type_is_structural(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
|
||||
ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) |
|
||||
ty_closure(_) |
|
||||
ty_bare_fn(_) | // FIXME(#4804) Bare fn repr
|
||||
ty_trait(*) |
|
||||
ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
|
||||
ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
|
||||
|
@ -1715,10 +1684,11 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
|||
}
|
||||
accum
|
||||
}
|
||||
ty_fn(ref fty) => {
|
||||
match fty.meta.proto {
|
||||
ast::ProtoBare | ast::ProtoBorrowed => false,
|
||||
ast::ProtoBox | ast::ProtoUniq => true,
|
||||
ty_bare_fn(*) => false,
|
||||
ty_closure(ref fty) => {
|
||||
match fty.sigil {
|
||||
ast::BorrowedSigil => false,
|
||||
ast::ManagedSigil | ast::OwnedSigil => true,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1813,7 +1783,7 @@ pub enum Kind { kind_(u32) }
|
|||
const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32;
|
||||
|
||||
/// no shared box, borrowed ptr (must imply DURABLE)
|
||||
const KIND_MASK_OWNED : u32 = 0b000000000000000000000000010_u32;
|
||||
const KIND_MASK_OWNED : u32 = 0b000000000000000000000000010_u32;
|
||||
|
||||
/// is durable (no borrowed ptrs)
|
||||
const KIND_MASK_DURABLE : u32 = 0b000000000000000000000000100_u32;
|
||||
|
@ -1942,20 +1912,25 @@ pub pure fn kind_is_durable(k: Kind) -> bool {
|
|||
*k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
|
||||
}
|
||||
|
||||
pub fn meta_kind(p: FnMeta) -> Kind {
|
||||
match p.proto { // XXX consider the kind bounds!
|
||||
ast::ProtoBare => {
|
||||
kind_safe_for_default_mode_send() | kind_const() | kind_durable()
|
||||
}
|
||||
ast::ProtoBorrowed => {
|
||||
kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE)
|
||||
}
|
||||
ast::ProtoBox => {
|
||||
kind_safe_for_default_mode() | kind_durable()
|
||||
}
|
||||
ast::ProtoUniq => {
|
||||
kind_owned_copy() | kind_durable()
|
||||
}
|
||||
pure fn kind_is_const(k: Kind) -> bool {
|
||||
*k & KIND_MASK_CONST == KIND_MASK_CONST
|
||||
}
|
||||
|
||||
fn closure_kind(cty: &ClosureTy) -> Kind {
|
||||
let kind = match cty.sigil {
|
||||
ast::BorrowedSigil => kind_implicitly_copyable(),
|
||||
ast::ManagedSigil => kind_implicitly_copyable(),
|
||||
ast::OwnedSigil => kind_owned_only() | kind_durable(),
|
||||
};
|
||||
|
||||
let kind = match cty.region {
|
||||
re_static => kind | kind_durable(),
|
||||
_ => kind - kind_owned_only() - kind_durable()
|
||||
};
|
||||
|
||||
match cty.onceness {
|
||||
ast::Once => kind - kind_implicitly_copyable(),
|
||||
ast::Many => kind
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2022,7 +1997,7 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
|
|||
let mut result = match /*bad*/copy get(ty).sty {
|
||||
// Scalar and unique types are sendable, constant, and owned
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_ptr(_) => {
|
||||
ty_bare_fn(_) | ty_ptr(_) => {
|
||||
kind_safe_for_default_mode_send() | kind_const() | kind_durable()
|
||||
}
|
||||
|
||||
|
@ -2035,8 +2010,9 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
|
|||
}
|
||||
}
|
||||
|
||||
// functions depend on the protocol
|
||||
ty_fn(ref f) => meta_kind(f.meta),
|
||||
ty_closure(ref c) => {
|
||||
closure_kind(c)
|
||||
}
|
||||
|
||||
// Those with refcounts raise noncopyable to copyable,
|
||||
// lower sendable to copyable. Therefore just set result to copyable.
|
||||
|
@ -2215,7 +2191,8 @@ fn type_size(cx: ctxt, ty: t) -> uint {
|
|||
|
||||
ty_evec(_, vstore_slice(_)) |
|
||||
ty_estr(vstore_slice(_)) |
|
||||
ty_fn(_) => {
|
||||
ty_bare_fn(*) |
|
||||
ty_closure(*) => {
|
||||
2
|
||||
}
|
||||
|
||||
|
@ -2297,7 +2274,8 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
|||
ty_uint(_) |
|
||||
ty_float(_) |
|
||||
ty_estr(_) |
|
||||
ty_fn(_) |
|
||||
ty_bare_fn(_) |
|
||||
ty_closure(_) |
|
||||
ty_infer(_) |
|
||||
ty_err |
|
||||
ty_param(_) |
|
||||
|
@ -2472,9 +2450,9 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
|
|||
match /*bad*/copy get(ty).sty {
|
||||
// Scalar types
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
|
||||
ty_type | ty_ptr(_) => result = true,
|
||||
ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
|
||||
// Boxed types
|
||||
ty_box(_) | ty_uniq(_) | ty_fn(_) |
|
||||
ty_box(_) | ty_uniq(_) | ty_closure(_) |
|
||||
ty_estr(vstore_uniq) | ty_estr(vstore_box) |
|
||||
ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
|
||||
ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
|
||||
|
@ -2700,14 +2678,9 @@ impl arg : to_bytes::IterBytes {
|
|||
}
|
||||
}
|
||||
|
||||
impl FnMeta : to_bytes::IterBytes {
|
||||
impl Kind : to_bytes::IterBytes {
|
||||
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
|
||||
to_bytes::iter_bytes_5(&self.purity,
|
||||
&self.proto,
|
||||
&self.onceness,
|
||||
&self.region,
|
||||
&self.bounds,
|
||||
lsb0, f);
|
||||
(**self).iter_bytes(lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2755,7 +2728,7 @@ impl sty : to_bytes::IterBytes {
|
|||
ty_rec(ref fs) =>
|
||||
to_bytes::iter_bytes_2(&11u8, fs, lsb0, f),
|
||||
|
||||
ty_fn(ref ft) =>
|
||||
ty_bare_fn(ref ft) =>
|
||||
to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
|
||||
|
||||
ty_self => 13u8.iter_bytes(lsb0, f),
|
||||
|
@ -2789,7 +2762,10 @@ impl sty : to_bytes::IterBytes {
|
|||
ty_rptr(ref r, ref mt) =>
|
||||
to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
|
||||
|
||||
ty_err => 25u8.iter_bytes(lsb0, f)
|
||||
ty_err => 25u8.iter_bytes(lsb0, f),
|
||||
|
||||
ty_closure(ref ct) =>
|
||||
to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2823,36 +2799,48 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
|
|||
// Type accessors for substructures of types
|
||||
pub fn ty_fn_args(fty: t) -> ~[arg] {
|
||||
match get(fty).sty {
|
||||
ty_fn(ref f) => /*bad*/copy f.sig.inputs,
|
||||
_ => die!(~"ty_fn_args() called on non-fn type")
|
||||
ty_bare_fn(ref f) => copy f.sig.inputs,
|
||||
ty_closure(ref f) => copy f.sig.inputs,
|
||||
ref s => {
|
||||
die!(fmt!("ty_fn_args() called on non-fn type: %?", s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_fn_proto(fty: t) -> Proto {
|
||||
pub fn ty_closure_sigil(fty: t) -> Sigil {
|
||||
match get(fty).sty {
|
||||
ty_fn(ref f) => f.meta.proto,
|
||||
_ => die!(~"ty_fn_proto() called on non-fn type")
|
||||
ty_closure(ref f) => f.sigil,
|
||||
ref s => {
|
||||
die!(fmt!("ty_closure_sigil() called on non-closure type: %?", s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_fn_purity(fty: t) -> ast::purity {
|
||||
match get(fty).sty {
|
||||
ty_fn(ref f) => f.meta.purity,
|
||||
_ => die!(~"ty_fn_purity() called on non-fn type")
|
||||
ty_bare_fn(ref f) => f.purity,
|
||||
ty_closure(ref f) => f.purity,
|
||||
ref s => {
|
||||
die!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub pure fn ty_fn_ret(fty: t) -> t {
|
||||
match get(fty).sty {
|
||||
ty_fn(ref f) => f.sig.output,
|
||||
_ => die!(~"ty_fn_ret() called on non-fn type")
|
||||
ty_bare_fn(ref f) => f.sig.output,
|
||||
ty_closure(ref f) => f.sig.output,
|
||||
ref s => {
|
||||
die!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_fn_ty(fty: t) -> bool {
|
||||
match get(fty).sty {
|
||||
ty_fn(_) => true,
|
||||
_ => false
|
||||
ty_bare_fn(_) => true,
|
||||
ty_closure(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2874,17 +2862,17 @@ pub fn ty_region(ty: t) -> Region {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
|
||||
pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
|
||||
/*!
|
||||
*
|
||||
* Returns a new function type based on `fn_type` but returning a value of
|
||||
* type `ret_type` instead. */
|
||||
|
||||
match ty::get(fn_type).sty {
|
||||
ty::ty_fn(ref fty) => {
|
||||
ty::mk_fn(tcx, FnTyBase {
|
||||
meta: fty.meta,
|
||||
sig: FnSig {output: ret_type, ..copy fty.sig}
|
||||
ty::ty_closure(ref fty) => {
|
||||
ty::mk_closure(tcx, ClosureTy {
|
||||
sig: FnSig {output: ret_type, ..copy fty.sig},
|
||||
..copy *fty
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
|
@ -2900,12 +2888,6 @@ pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
|
|||
vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
|
||||
}
|
||||
|
||||
// Just checks whether it's a fn that returns bool,
|
||||
// not its purity.
|
||||
pub fn is_pred_ty(fty: t) -> bool {
|
||||
is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
|
||||
}
|
||||
|
||||
// Type accessors for AST nodes
|
||||
pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
|
||||
return node_id_to_type(cx, b.node.id);
|
||||
|
@ -3023,11 +3005,12 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
|
|||
fn borrow_fn(cx: ctxt, expr: @ast::expr,
|
||||
autoref: &AutoRef, ty: ty::t) -> ty::t {
|
||||
match get(ty).sty {
|
||||
ty_fn(ref fty) => {
|
||||
ty::mk_fn(cx, FnTyBase {meta: FnMeta {proto: ProtoBorrowed,
|
||||
region: autoref.region,
|
||||
..copy fty.meta},
|
||||
sig: copy fty.sig})
|
||||
ty_closure(ref fty) => {
|
||||
ty::mk_closure(cx, ClosureTy {
|
||||
sigil: BorrowedSigil,
|
||||
region: autoref.region,
|
||||
..copy *fty
|
||||
})
|
||||
}
|
||||
|
||||
ref s => {
|
||||
|
@ -3417,7 +3400,8 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
|
|||
ty_ptr(_) => ~"*-ptr",
|
||||
ty_rptr(_, _) => ~"&-ptr",
|
||||
ty_rec(_) => ~"record",
|
||||
ty_fn(_) => ~"fn",
|
||||
ty_bare_fn(_) => ~"extern fn",
|
||||
ty_closure(_) => ~"fn",
|
||||
ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
|
||||
ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
|
||||
ty_tup(_) => ~"tuple",
|
||||
|
@ -3455,14 +3439,18 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
|
|||
fmt!("expected %s fn but found %s fn",
|
||||
values.expected.to_str(), values.found.to_str())
|
||||
}
|
||||
terr_abi_mismatch(values) => {
|
||||
fmt!("expected %s fn but found %s fn",
|
||||
values.expected.to_str(), values.found.to_str())
|
||||
}
|
||||
terr_onceness_mismatch(values) => {
|
||||
fmt!("expected %s fn but found %s fn",
|
||||
values.expected.to_str(), values.found.to_str())
|
||||
}
|
||||
terr_proto_mismatch(values) => {
|
||||
terr_sigil_mismatch(values) => {
|
||||
fmt!("expected %s closure, found %s closure",
|
||||
proto_ty_to_str(cx, values.expected, false),
|
||||
proto_ty_to_str(cx, values.found, false))
|
||||
values.expected.to_str(),
|
||||
values.found.to_str())
|
||||
}
|
||||
terr_mutability => ~"values differ in mutability",
|
||||
terr_box_mutability => ~"boxed values differ in mutability",
|
||||
|
@ -4232,13 +4220,10 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
|
|||
// This type has a region. Get rid of it
|
||||
mk_rptr(cx, re_static, normalize_mt(cx, mt)),
|
||||
|
||||
ty_fn(ref fn_ty) => {
|
||||
mk_fn(cx, FnTyBase {
|
||||
meta: FnMeta {
|
||||
region: ty::re_static,
|
||||
..fn_ty.meta
|
||||
},
|
||||
sig: /*bad*/copy fn_ty.sig
|
||||
ty_closure(ref closure_ty) => {
|
||||
mk_closure(cx, ClosureTy {
|
||||
region: ty::re_static,
|
||||
..copy *closure_ty
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -4310,13 +4295,13 @@ pub fn eval_repeat_count(tcx: ctxt,
|
|||
// Determine what purity to check a nested function under
|
||||
pub pure fn determine_inherited_purity(parent_purity: ast::purity,
|
||||
child_purity: ast::purity,
|
||||
child_proto: ast::Proto)
|
||||
child_sigil: ast::Sigil)
|
||||
-> ast::purity {
|
||||
// If the closure is a stack closure and hasn't had some non-standard
|
||||
// purity inferred for it, then check it under its parent's purity.
|
||||
// Otherwise, use its own
|
||||
match child_proto {
|
||||
ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity,
|
||||
match child_sigil {
|
||||
ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity,
|
||||
_ => child_purity
|
||||
}
|
||||
}
|
||||
|
@ -4526,171 +4511,6 @@ impl bound_region : cmp::Eq {
|
|||
pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
|
||||
}
|
||||
|
||||
impl sty : cmp::Eq {
|
||||
pure fn eq(&self, other: &sty) -> bool {
|
||||
match (/*bad*/copy *self) {
|
||||
ty_nil => {
|
||||
match (*other) {
|
||||
ty_nil => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_bot => {
|
||||
match (*other) {
|
||||
ty_bot => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_bool => {
|
||||
match (*other) {
|
||||
ty_bool => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_int(e0a) => {
|
||||
match (*other) {
|
||||
ty_int(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_uint(e0a) => {
|
||||
match (*other) {
|
||||
ty_uint(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_float(e0a) => {
|
||||
match (*other) {
|
||||
ty_float(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_estr(e0a) => {
|
||||
match (*other) {
|
||||
ty_estr(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_enum(e0a, ref e1a) => {
|
||||
match (*other) {
|
||||
ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_box(e0a) => {
|
||||
match (*other) {
|
||||
ty_box(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_uniq(e0a) => {
|
||||
match (*other) {
|
||||
ty_uniq(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_evec(e0a, e1a) => {
|
||||
match (*other) {
|
||||
ty_evec(e0b, e1b) => e0a == e0b && e1a == e1b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_ptr(e0a) => {
|
||||
match (*other) {
|
||||
ty_ptr(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_rptr(e0a, e1a) => {
|
||||
match (*other) {
|
||||
ty_rptr(e0b, e1b) => e0a == e0b && e1a == e1b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_rec(e0a) => {
|
||||
match (/*bad*/copy *other) {
|
||||
ty_rec(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_fn(ref e0a) => {
|
||||
match (*other) {
|
||||
ty_fn(ref e0b) => (*e0a) == (*e0b),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_trait(e0a, ref e1a, e2a) => {
|
||||
match (*other) {
|
||||
ty_trait(e0b, ref e1b, e2b) =>
|
||||
e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_struct(e0a, ref e1a) => {
|
||||
match (*other) {
|
||||
ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_tup(e0a) => {
|
||||
match (/*bad*/copy *other) {
|
||||
ty_tup(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_infer(ref e0a) => {
|
||||
match (*other) {
|
||||
ty_infer(ref e0b) => *e0a == *e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_err => {
|
||||
match (*other) {
|
||||
ty_err => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_param(e0a) => {
|
||||
match (*other) {
|
||||
ty_param(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_self => {
|
||||
match (*other) {
|
||||
ty_self => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_type => {
|
||||
match (*other) {
|
||||
ty_type => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_opaque_box => {
|
||||
match (*other) {
|
||||
ty_opaque_box => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_opaque_closure_ptr(e0a) => {
|
||||
match (*other) {
|
||||
ty_opaque_closure_ptr(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ty_unboxed_vec(e0a) => {
|
||||
match (*other) {
|
||||
ty_unboxed_vec(e0b) => e0a == e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pure fn ne(&self, other: &sty) -> bool { !(*self).eq(other) }
|
||||
}
|
||||
|
||||
impl param_bound : cmp::Eq {
|
||||
pure fn eq(&self, other: ¶m_bound) -> bool {
|
||||
match (*self) {
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use middle::pat_util::pat_id_map;
|
||||
use middle::ty::{FnTyBase, FnMeta, FnSig, arg, field, substs};
|
||||
use middle::ty::{arg, field, substs};
|
||||
use middle::ty::{ty_param_substs_and_ty};
|
||||
use middle::ty;
|
||||
use middle::typeck::check::fn_ctxt;
|
||||
|
@ -70,7 +70,7 @@ use core::vec;
|
|||
use syntax::ast;
|
||||
use syntax::codemap::span;
|
||||
use syntax::print::pprust::path_to_str;
|
||||
use util::common::indent;
|
||||
use util::common::indenter;
|
||||
|
||||
pub trait ast_conv {
|
||||
fn tcx() -> ty::ctxt;
|
||||
|
@ -321,13 +321,16 @@ pub fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Durable>(
|
|||
};
|
||||
ty::mk_rec(tcx, flds)
|
||||
}
|
||||
ast::ty_fn(f) => {
|
||||
let bounds = collect::compute_bounds(self.ccx(), f.bounds);
|
||||
let fn_decl = ty_of_fn_decl(self, rscope, f.proto,
|
||||
f.purity, f.onceness,
|
||||
bounds, f.region, f.decl, None,
|
||||
ast_ty.span);
|
||||
ty::mk_fn(tcx, fn_decl)
|
||||
ast::ty_bare_fn(bf) => {
|
||||
ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity,
|
||||
bf.abi, bf.decl))
|
||||
}
|
||||
ast::ty_closure(f) => {
|
||||
let fn_decl = ty_of_closure(self, rscope, f.sigil,
|
||||
f.purity, f.onceness,
|
||||
f.region, f.decl, None,
|
||||
ast_ty.span);
|
||||
ty::mk_closure(tcx, fn_decl)
|
||||
}
|
||||
ast::ty_path(path, id) => {
|
||||
let a_def = match tcx.def_map.find(&id) {
|
||||
|
@ -452,71 +455,92 @@ pub fn ty_of_arg<AC: ast_conv, RS: region_scope Copy Durable>(
|
|||
arg {mode: mode, ty: ty}
|
||||
}
|
||||
|
||||
pub type expected_tys = Option<{inputs: ~[ty::arg],
|
||||
output: ty::t}>;
|
||||
|
||||
pub fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Durable>(
|
||||
pub fn ty_of_bare_fn<AC: ast_conv, RS: region_scope Copy Durable>(
|
||||
self: AC, rscope: RS,
|
||||
ast_proto: ast::Proto,
|
||||
purity: ast::purity,
|
||||
onceness: ast::Onceness,
|
||||
bounds: @~[ty::param_bound],
|
||||
opt_region: Option<@ast::region>,
|
||||
decl: ast::fn_decl,
|
||||
expected_tys: expected_tys,
|
||||
span: span) -> ty::FnTy {
|
||||
abi: ast::Abi,
|
||||
decl: ast::fn_decl) -> ty::BareFnTy
|
||||
{
|
||||
debug!("ty_of_fn_decl");
|
||||
do indent {
|
||||
// resolve the function bound region in the original region
|
||||
// scope `rscope`, not the scope of the function parameters
|
||||
let bound_region = match opt_region {
|
||||
Some(region) => {
|
||||
ast_region_to_region(self, rscope, span, region)
|
||||
}
|
||||
None => {
|
||||
match ast_proto {
|
||||
ast::ProtoBare | ast::ProtoUniq | ast::ProtoBox => {
|
||||
// @fn(), ~fn() default to static as the bound
|
||||
// on their upvars:
|
||||
ty::re_static
|
||||
}
|
||||
ast::ProtoBorrowed => {
|
||||
// &fn() defaults to an anonymous region:
|
||||
let r_result = rscope.anon_region(span);
|
||||
get_region_reporting_err(self.tcx(), span, r_result)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// new region names that appear inside of the fn decl are bound to
|
||||
// that function type
|
||||
let rb = in_binding_rscope(rscope);
|
||||
// new region names that appear inside of the fn decl are bound to
|
||||
// that function type
|
||||
let rb = in_binding_rscope(rscope);
|
||||
|
||||
let input_tys = do decl.inputs.mapi |i, a| {
|
||||
let expected_arg_ty = do expected_tys.chain_ref |e| {
|
||||
// no guarantee that the correct number of expected args
|
||||
// were supplied
|
||||
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
|
||||
};
|
||||
ty_of_arg(self, rb, *a, expected_arg_ty)
|
||||
};
|
||||
let input_tys = decl.inputs.map(|a| ty_of_arg(self, rb, *a, None));
|
||||
let output_ty = match decl.output.node {
|
||||
ast::ty_infer => self.ty_infer(decl.output.span),
|
||||
_ => ast_ty_to_ty(self, rb, decl.output)
|
||||
};
|
||||
|
||||
let expected_ret_ty = expected_tys.map(|e| e.output);
|
||||
let output_ty = match decl.output.node {
|
||||
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
|
||||
ast::ty_infer => self.ty_infer(decl.output.span),
|
||||
_ => ast_ty_to_ty(self, rb, decl.output)
|
||||
};
|
||||
|
||||
FnTyBase {
|
||||
meta: FnMeta {purity: purity,
|
||||
proto: ast_proto,
|
||||
onceness: onceness,
|
||||
region: bound_region,
|
||||
bounds: bounds},
|
||||
sig: FnSig {inputs: input_tys,
|
||||
output: output_ty}
|
||||
}
|
||||
ty::BareFnTy {
|
||||
purity: purity,
|
||||
abi: abi,
|
||||
sig: ty::FnSig {inputs: input_tys, output: output_ty}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_closure<AC: ast_conv, RS: region_scope Copy Durable>(
|
||||
self: AC, rscope: RS,
|
||||
sigil: ast::Sigil,
|
||||
purity: ast::purity,
|
||||
onceness: ast::Onceness,
|
||||
opt_region: Option<@ast::region>,
|
||||
decl: ast::fn_decl,
|
||||
expected_tys: Option<ty::FnSig>,
|
||||
span: span) -> ty::ClosureTy
|
||||
{
|
||||
debug!("ty_of_fn_decl");
|
||||
let _i = indenter();
|
||||
|
||||
// resolve the function bound region in the original region
|
||||
// scope `rscope`, not the scope of the function parameters
|
||||
let bound_region = match opt_region {
|
||||
Some(region) => {
|
||||
ast_region_to_region(self, rscope, span, region)
|
||||
}
|
||||
None => {
|
||||
match sigil {
|
||||
ast::OwnedSigil | ast::ManagedSigil => {
|
||||
// @fn(), ~fn() default to static as the bound
|
||||
// on their upvars:
|
||||
ty::re_static
|
||||
}
|
||||
ast::BorrowedSigil => {
|
||||
// &fn() defaults to an anonymous region:
|
||||
let r_result = rscope.anon_region(span);
|
||||
get_region_reporting_err(self.tcx(), span, r_result)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// new region names that appear inside of the fn decl are bound to
|
||||
// that function type
|
||||
let rb = in_binding_rscope(rscope);
|
||||
|
||||
let input_tys = do decl.inputs.mapi |i, a| {
|
||||
let expected_arg_ty = do expected_tys.chain_ref |e| {
|
||||
// no guarantee that the correct number of expected args
|
||||
// were supplied
|
||||
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
|
||||
};
|
||||
ty_of_arg(self, rb, *a, expected_arg_ty)
|
||||
};
|
||||
|
||||
let expected_ret_ty = expected_tys.map(|e| e.output);
|
||||
let output_ty = match decl.output.node {
|
||||
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
|
||||
ast::ty_infer => self.ty_infer(decl.output.span),
|
||||
_ => ast_ty_to_ty(self, rb, decl.output)
|
||||
};
|
||||
|
||||
ty::ClosureTy {
|
||||
purity: purity,
|
||||
sigil: sigil,
|
||||
onceness: onceness,
|
||||
region: bound_region,
|
||||
sig: ty::FnSig {inputs: input_tys,
|
||||
output: output_ty}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -883,7 +883,7 @@ pub impl LookupContext {
|
|||
})
|
||||
}
|
||||
|
||||
ty_trait(*) | ty_fn(*) => {
|
||||
ty_trait(*) | ty_closure(*) => {
|
||||
// NDM---eventually these should be some variant of autoref
|
||||
None
|
||||
}
|
||||
|
@ -906,14 +906,14 @@ pub impl LookupContext {
|
|||
|
||||
let tcx = self.tcx();
|
||||
match ty::get(self_ty).sty {
|
||||
ty_box(*) | ty_uniq(*) | ty_rptr(*) |
|
||||
ty_bare_fn(*) | ty_box(*) | ty_uniq(*) | ty_rptr(*) |
|
||||
ty_infer(IntVar(_)) |
|
||||
ty_infer(FloatVar(_)) |
|
||||
ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
|
||||
ty_int(*) | ty_uint(*) |
|
||||
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) |
|
||||
ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) |
|
||||
ty_trait(*) | ty_fn(*) => {
|
||||
ty_trait(*) | ty_closure(*) => {
|
||||
self.search_for_some_kind_of_autorefd_method(
|
||||
AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
|
||||
|m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
|
||||
|
@ -1212,7 +1212,7 @@ pub impl LookupContext {
|
|||
trait_did: def_id,
|
||||
method_num: uint) -> ty::t {
|
||||
let trait_methods = ty::trait_methods(tcx, trait_did);
|
||||
ty::mk_fn(tcx, /*bad*/copy trait_methods[method_num].fty)
|
||||
ty::mk_bare_fn(tcx, copy trait_methods[method_num].fty)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ use core::prelude::*;
|
|||
use middle::const_eval;
|
||||
use middle::pat_util::pat_id_map;
|
||||
use middle::pat_util;
|
||||
use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field};
|
||||
use middle::ty::{TyVid, Vid, FnSig, VariantInfo_, field};
|
||||
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
|
||||
use middle::ty::{re_bound, br_cap_avoid, substs, arg, param_ty};
|
||||
use middle::ty;
|
||||
|
@ -90,7 +90,6 @@ use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
|
|||
use middle::typeck::astconv;
|
||||
use middle::typeck::check::_match::pat_ctxt;
|
||||
use middle::typeck::check::method::TransformTypeNormally;
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_ty;
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::vtable::{LocationInfo, VtableContext};
|
||||
use middle::typeck::crate_ctxt;
|
||||
|
@ -248,8 +247,9 @@ pub fn check_bare_fn(ccx: @crate_ctxt,
|
|||
self_info: Option<self_info>) {
|
||||
let fty = ty::node_id_to_type(ccx.tcx, id);
|
||||
match ty::get(fty).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
check_fn(ccx, self_info, fn_ty, decl, body, Vanilla, None)
|
||||
ty::ty_bare_fn(ref fn_ty) => {
|
||||
check_fn(ccx, self_info, fn_ty.purity, None,
|
||||
&fn_ty.sig, decl, body, Vanilla, None)
|
||||
}
|
||||
_ => ccx.tcx.sess.impossible_case(body.span,
|
||||
"check_bare_fn: function type expected")
|
||||
|
@ -258,12 +258,14 @@ pub fn check_bare_fn(ccx: @crate_ctxt,
|
|||
|
||||
pub fn check_fn(ccx: @crate_ctxt,
|
||||
self_info: Option<self_info>,
|
||||
fn_ty: &ty::FnTy,
|
||||
purity: ast::purity,
|
||||
sigil: Option<ast::Sigil>,
|
||||
fn_sig: &ty::FnSig,
|
||||
decl: &ast::fn_decl,
|
||||
body: ast::blk,
|
||||
fn_kind: FnKind,
|
||||
old_fcx: Option<@fn_ctxt>) {
|
||||
|
||||
old_fcx: Option<@fn_ctxt>)
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
let indirect_ret = match fn_kind {
|
||||
ForLoop => true, _ => false
|
||||
|
@ -277,7 +279,7 @@ pub fn check_fn(ccx: @crate_ctxt,
|
|||
let {isr, self_info, fn_sig} = {
|
||||
let old_isr = option::map_default(&old_fcx, @Nil,
|
||||
|fcx| fcx.in_scope_regions);
|
||||
replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig,
|
||||
replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, fn_sig,
|
||||
|br| ty::re_free(body.node.id, br))
|
||||
};
|
||||
|
||||
|
@ -294,13 +296,10 @@ pub fn check_fn(ccx: @crate_ctxt,
|
|||
// in the case of function expressions, based on the outer context.
|
||||
let fcx: @fn_ctxt = {
|
||||
let (purity, inherited) = match old_fcx {
|
||||
None => {
|
||||
(fn_ty.meta.purity,
|
||||
blank_inherited(ccx))
|
||||
}
|
||||
None => (purity, blank_inherited(ccx)),
|
||||
Some(fcx) => {
|
||||
(ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity,
|
||||
fn_ty.meta.proto),
|
||||
(ty::determine_inherited_purity(fcx.purity, purity,
|
||||
sigil.get()),
|
||||
fcx.inh)
|
||||
}
|
||||
};
|
||||
|
@ -1092,8 +1091,9 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
in_fty: ty::t,
|
||||
callee_expr: @ast::expr,
|
||||
args: ~[@ast::expr],
|
||||
deref_args: DerefArgs) -> {fty: ty::t, bot: bool} {
|
||||
|
||||
sugar: ast::CallSugar,
|
||||
deref_args: DerefArgs) -> (ty::t, bool)
|
||||
{
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let mut bot = false;
|
||||
|
||||
|
@ -1103,62 +1103,72 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
debug!("check_call_inner: before universal quant., in_fty=%s",
|
||||
fcx.infcx().ty_to_str(in_fty));
|
||||
|
||||
let mut formal_tys;
|
||||
let formal_tys;
|
||||
|
||||
// This is subtle: we expect `fty` to be a function type, which
|
||||
// normally introduce a level of binding. In this case, we want to
|
||||
// process the types bound by the function but not by any nested
|
||||
// functions. Therefore, we match one level of structure.
|
||||
let fty =
|
||||
match structure_of(fcx, sp, in_fty) {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
let fn_ty =
|
||||
/*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil,
|
||||
None, fn_ty, |_br| fcx.infcx().next_region_var(sp,
|
||||
call_expr_id)).fn_ty;
|
||||
let ret_ty = match structure_of(fcx, sp, in_fty) {
|
||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
|
||||
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
|
||||
let {fn_sig: sig, _} =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, @Nil, None, sig,
|
||||
|_br| fcx.infcx().next_region_var(
|
||||
sp, call_expr_id));
|
||||
|
||||
let supplied_arg_count = args.len();
|
||||
let supplied_arg_count = args.len();
|
||||
|
||||
bot |= ty::type_is_bot(fn_ty.sig.output);
|
||||
bot |= ty::type_is_bot(sig.output);
|
||||
|
||||
// Grab the argument types, supplying fresh type variables
|
||||
// if the wrong number of arguments were supplied
|
||||
let expected_arg_count = fn_ty.sig.inputs.len();
|
||||
formal_tys = if expected_arg_count == supplied_arg_count {
|
||||
fn_ty.sig.inputs.map(|a| a.ty)
|
||||
} else {
|
||||
tcx.sess.span_err(
|
||||
sp, fmt!("this function takes %u parameter%s but \
|
||||
%u parameter%s supplied",
|
||||
// Grab the argument types, supplying fresh type variables
|
||||
// if the wrong number of arguments were supplied
|
||||
let expected_arg_count = sig.inputs.len();
|
||||
formal_tys = if expected_arg_count == supplied_arg_count {
|
||||
sig.inputs.map(|a| a.ty)
|
||||
} else {
|
||||
let suffix = match sugar {
|
||||
ast::NoSugar => "",
|
||||
ast::DoSugar => " (including the closure passed by \
|
||||
the `do` keyword)",
|
||||
ast::ForSugar => " (including the closure passed by \
|
||||
the `for` keyword)"
|
||||
};
|
||||
let msg = fmt!("this function takes %u parameter%s but \
|
||||
%u parameter%s supplied%s",
|
||||
expected_arg_count,
|
||||
if expected_arg_count == 1 {
|
||||
~""
|
||||
} else {
|
||||
~"s"
|
||||
},
|
||||
if expected_arg_count == 1 {""}
|
||||
else {"s"},
|
||||
supplied_arg_count,
|
||||
if supplied_arg_count == 1 {
|
||||
~" was"
|
||||
} else {
|
||||
~"s were"
|
||||
}));
|
||||
fcx.infcx().next_ty_vars(supplied_arg_count)
|
||||
};
|
||||
ty::mk_fn(tcx, fn_ty)
|
||||
}
|
||||
_ => {
|
||||
fcx.type_error_message(sp, |actual| {
|
||||
fmt!("expected function or foreign function but \
|
||||
found `%s`", actual) }, in_fty, None);
|
||||
// check each arg against "error", in order to set up
|
||||
// all the node type bindings
|
||||
formal_tys = args.map(|_x| ty::mk_err(tcx));
|
||||
ty::mk_err(tcx)
|
||||
}
|
||||
};
|
||||
if supplied_arg_count == 1 {" was"}
|
||||
else {"s were"},
|
||||
suffix);
|
||||
|
||||
debug!("check_call_inner: after universal quant., fty=%s",
|
||||
fcx.infcx().ty_to_str(fty));
|
||||
tcx.sess.span_err(sp, msg);
|
||||
|
||||
vec::from_fn(expected_arg_count, |_| ty::mk_err(tcx))
|
||||
};
|
||||
|
||||
sig.output
|
||||
}
|
||||
|
||||
_ => {
|
||||
fcx.type_error_message(sp, |actual| {
|
||||
fmt!("expected function or foreign function but \
|
||||
found `%s`", actual) }, in_fty, None);
|
||||
|
||||
// check each arg against "error", in order to set up
|
||||
// all the node type bindings
|
||||
formal_tys = args.map(|_x| ty::mk_err(tcx));
|
||||
ty::mk_err(tcx)
|
||||
}
|
||||
};
|
||||
|
||||
debug!("check_call_inner: after universal quant., \
|
||||
formal_tys=%? ret_ty=%s",
|
||||
formal_tys.map(|t| fcx.infcx().ty_to_str(*t)),
|
||||
fcx.infcx().ty_to_str(ret_ty));
|
||||
|
||||
// Check the arguments.
|
||||
// We do this in a pretty awful way: first we typecheck any arguments
|
||||
|
@ -1209,7 +1219,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
}
|
||||
}
|
||||
|
||||
{fty: fty, bot: bot}
|
||||
(ret_ty, bot)
|
||||
}
|
||||
|
||||
// A generic function for checking assignment expressions
|
||||
|
@ -1233,36 +1243,26 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
fn_ty: ty::t,
|
||||
expr: @ast::expr,
|
||||
+args: ~[@ast::expr],
|
||||
bot: bool)
|
||||
-> bool {
|
||||
bot: bool,
|
||||
sugar: ast::CallSugar) -> bool
|
||||
{
|
||||
let mut bot = bot;
|
||||
|
||||
// Call the generic checker.
|
||||
let fty = {
|
||||
let r = check_call_inner(fcx, sp, call_expr_id,
|
||||
fn_ty, expr, args, DontDerefArgs);
|
||||
bot |= r.bot;
|
||||
r.fty
|
||||
};
|
||||
let (ret_ty, b) = check_call_inner(fcx, sp, call_expr_id,
|
||||
fn_ty, expr, args, sugar,
|
||||
DontDerefArgs);
|
||||
bot |= b;
|
||||
|
||||
// Pull the return type out of the type of the function.
|
||||
match structure_of(fcx, sp, fty) {
|
||||
ty::ty_fn(ref f) => {
|
||||
fcx.write_ty(call_expr_id, f.sig.output);
|
||||
return bot;
|
||||
}
|
||||
_ => {
|
||||
fcx.write_ty(call_expr_id, ty::mk_err(fcx.ccx.tcx));
|
||||
fcx.type_error_message(sp, |_actual| {
|
||||
~"expected function"}, fty, None);
|
||||
return bot;
|
||||
}
|
||||
}
|
||||
fcx.write_ty(call_expr_id, ret_ty);
|
||||
return bot;
|
||||
}
|
||||
|
||||
// A generic function for doing all of the checking for call expressions
|
||||
fn check_call(fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id,
|
||||
f: @ast::expr, +args: ~[@ast::expr]) -> bool {
|
||||
f: @ast::expr, +args: ~[@ast::expr],
|
||||
sugar: ast::CallSugar) -> bool {
|
||||
// Index expressions need to be handled separately, to inform them
|
||||
// that they appear in call position.
|
||||
let mut bot = match /*bad*/copy f.node {
|
||||
|
@ -1278,7 +1278,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
fcx.expr_ty(f),
|
||||
f,
|
||||
args,
|
||||
bot)
|
||||
bot,
|
||||
sugar)
|
||||
}
|
||||
|
||||
// Checks a method call.
|
||||
|
@ -1287,7 +1288,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
rcvr: @ast::expr,
|
||||
method_name: ast::ident,
|
||||
+args: ~[@ast::expr],
|
||||
tps: ~[@ast::Ty])
|
||||
tps: ~[@ast::Ty],
|
||||
sugar: ast::CallSugar)
|
||||
-> bool {
|
||||
let bot = check_expr(fcx, rcvr);
|
||||
let expr_t = structurally_resolved_type(fcx,
|
||||
|
@ -1329,7 +1331,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
fcx.node_ty(expr.callee_id),
|
||||
expr,
|
||||
args,
|
||||
bot)
|
||||
bot,
|
||||
sugar)
|
||||
}
|
||||
|
||||
// A generic function for checking for or for-each loops
|
||||
|
@ -1378,13 +1381,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
op_ex.callee_id, opname, self_t, ~[],
|
||||
deref_args) {
|
||||
Some(ref origin) => {
|
||||
let {fty: method_ty, bot: bot} = {
|
||||
let method_ty = fcx.node_ty(op_ex.callee_id);
|
||||
check_call_inner(fcx, op_ex.span, op_ex.id,
|
||||
method_ty, op_ex, args, deref_args)
|
||||
};
|
||||
fcx.ccx.method_map.insert(op_ex.id, (*origin));
|
||||
Some((ty::ty_fn_ret(method_ty), bot))
|
||||
let method_ty = fcx.node_ty(op_ex.callee_id);
|
||||
fcx.ccx.method_map.insert(op_ex.id, *origin);
|
||||
Some(check_call_inner(fcx, op_ex.span, op_ex.id,
|
||||
method_ty, op_ex, args,
|
||||
ast::NoSugar, deref_args))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
|
@ -1472,13 +1473,14 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
// If the or operator is used it might be that the user forgot to
|
||||
// supply the do keyword. Let's be more helpful in that situation.
|
||||
if op == ast::or {
|
||||
match ty::get(lhs_resolved_t).sty {
|
||||
ty::ty_fn(_) => {
|
||||
tcx.sess.span_note(
|
||||
ex.span, ~"did you forget the `do` keyword for the call?");
|
||||
match ty::get(lhs_resolved_t).sty {
|
||||
ty::ty_bare_fn(_) | ty::ty_closure(_) => {
|
||||
tcx.sess.span_note(
|
||||
ex.span, ~"did you forget the `do` keyword \
|
||||
for the call?");
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
(lhs_resolved_t, false)
|
||||
|
@ -1523,7 +1525,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
|
||||
fn check_expr_fn(fcx: @fn_ctxt,
|
||||
expr: @ast::expr,
|
||||
ast_proto_opt: Option<ast::Proto>,
|
||||
ast_sigil_opt: Option<ast::Sigil>,
|
||||
decl: &ast::fn_decl,
|
||||
body: ast::blk,
|
||||
fn_kind: FnKind,
|
||||
|
@ -1534,50 +1536,44 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
// avoid capture of bound regions in the expected type. See
|
||||
// def'n of br_cap_avoid() for a more lengthy explanation of
|
||||
// what's going on here.
|
||||
// Also try to pick up inferred purity and proto, defaulting
|
||||
// Also try to pick up inferred purity and sigil, defaulting
|
||||
// to impure and block. Note that we only will use those for
|
||||
// block syntax lambdas; that is, lambdas without explicit
|
||||
// protos.
|
||||
// sigils.
|
||||
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
|
||||
let (expected_tys,
|
||||
expected_purity,
|
||||
expected_proto,
|
||||
expected_sigil,
|
||||
expected_onceness) = {
|
||||
match expected_sty {
|
||||
Some(ty::ty_fn(ref fn_ty)) => {
|
||||
Some(ty::ty_closure(ref cenv)) => {
|
||||
let id = expr.id;
|
||||
let {fn_ty: fn_ty, _} =
|
||||
replace_bound_regions_in_fn_ty(
|
||||
tcx, @Nil, None, fn_ty,
|
||||
let {fn_sig: sig, _} =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, @Nil, None, &cenv.sig,
|
||||
|br| ty::re_bound(ty::br_cap_avoid(id, @br)));
|
||||
(Some({inputs: /*bad*/copy fn_ty.sig.inputs,
|
||||
output: fn_ty.sig.output}),
|
||||
fn_ty.meta.purity,
|
||||
fn_ty.meta.proto,
|
||||
fn_ty.meta.onceness)
|
||||
(Some(sig), cenv.purity, cenv.sigil, cenv.onceness)
|
||||
}
|
||||
_ => {
|
||||
(None, ast::impure_fn, ast::ProtoBorrowed, ast::Many)
|
||||
(None, ast::impure_fn, ast::BorrowedSigil, ast::Many)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If the proto is specified, use that, otherwise select a
|
||||
// proto based on inference.
|
||||
let (proto, purity) = match ast_proto_opt {
|
||||
let (sigil, purity) = match ast_sigil_opt {
|
||||
Some(p) => (p, ast::impure_fn),
|
||||
None => (expected_proto, expected_purity)
|
||||
None => (expected_sigil, expected_purity)
|
||||
};
|
||||
|
||||
// construct the function type
|
||||
let mut fn_ty = astconv::ty_of_fn_decl(
|
||||
let mut fn_ty = astconv::ty_of_closure(
|
||||
fcx, fcx,
|
||||
proto, purity, expected_onceness,
|
||||
/*bounds:*/ @~[], /*opt_region:*/ None,
|
||||
*decl, expected_tys, expr.span);
|
||||
sigil, purity, expected_onceness,
|
||||
None, *decl, expected_tys, expr.span);
|
||||
|
||||
// XXX: Bad copy.
|
||||
let fty = ty::mk_fn(tcx, copy fn_ty);
|
||||
let fty = ty::mk_closure(tcx, copy fn_ty);
|
||||
|
||||
debug!("check_expr_fn_with_unifier %s fty=%s",
|
||||
fcx.expr_to_str(expr),
|
||||
|
@ -1587,8 +1583,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
|
||||
// We inherit the same self info as the enclosing scope,
|
||||
// since the function we're checking might capture `self`
|
||||
check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body,
|
||||
fn_kind, Some(fcx));
|
||||
check_fn(fcx.ccx, fcx.self_info, fn_ty.purity, Some(fn_ty.sigil),
|
||||
&fn_ty.sig, decl, body, fn_kind, Some(fcx));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1913,6 +1909,119 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
return bot;
|
||||
}
|
||||
|
||||
fn check_loop_body(fcx: @fn_ctxt,
|
||||
expr: @ast::expr,
|
||||
expected: Option<ty::t>,
|
||||
loop_body: @ast::expr)
|
||||
{
|
||||
// a loop body is the special argument to a `for` loop. We know that
|
||||
// there will be an expected type in this context because it can only
|
||||
// appear in the context of a call, so we get the expected type of the
|
||||
// parameter. The catch here is that we need to validate two things:
|
||||
// 1. a closure that returns a bool is expected
|
||||
// 2. the closure that was given returns unit
|
||||
let tcx = fcx.tcx();
|
||||
let mut err_happened = false;
|
||||
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
|
||||
let inner_ty = match expected_sty {
|
||||
Some(ty::ty_closure(ref fty)) => {
|
||||
match fcx.mk_subty(false, expr.span,
|
||||
fty.sig.output, ty::mk_bool(tcx)) {
|
||||
result::Ok(_) => {
|
||||
ty::mk_closure(tcx, ty::ClosureTy {
|
||||
sig: FnSig {output: ty::mk_nil(tcx),
|
||||
..copy fty.sig},
|
||||
..copy *fty
|
||||
})
|
||||
}
|
||||
result::Err(_) => {
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
let did_you_mean = {
|
||||
if ty::type_is_nil(fty.sig.output) {
|
||||
"\nDid you mean to use \
|
||||
`do` instead of `for`?"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
};
|
||||
fmt!("A `for` loop iterator should expect a \
|
||||
closure that returns `bool`. This \
|
||||
iterator expects a closure that \
|
||||
returns `%s`.%s",
|
||||
actual, did_you_mean)
|
||||
},
|
||||
fty.sig.output,
|
||||
None);
|
||||
err_happened = true;
|
||||
|
||||
// Kind of a hack: create a function type with
|
||||
// the result replaced with ty_err, to
|
||||
// suppress derived errors.
|
||||
let t = ty::replace_closure_return_type(
|
||||
tcx, ty::mk_closure(tcx, copy *fty),
|
||||
ty::mk_err(tcx));
|
||||
fcx.write_ty(expr.id, ty::mk_err(tcx));
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match expected {
|
||||
Some(expected_t) => {
|
||||
fcx.type_error_message(
|
||||
expr.span,
|
||||
|actual| {
|
||||
fmt!("last argument in `for` call \
|
||||
has non-closure type: %s",
|
||||
actual)
|
||||
},
|
||||
expected_t, None);
|
||||
let err_ty = ty::mk_err(tcx);
|
||||
fcx.write_ty(expr.id, err_ty);
|
||||
err_happened = true;
|
||||
err_ty
|
||||
}
|
||||
None => fcx.tcx().sess.impossible_case(
|
||||
expr.span,
|
||||
~"loop body must have an expected type")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match loop_body.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
// If an error occurred, we pretend this isn't a for
|
||||
// loop, so as to assign types to all nodes while also
|
||||
// propagating ty_err throughout so as to suppress
|
||||
// derived errors. If we passed in ForLoop in the
|
||||
// error case, we'd potentially emit a spurious error
|
||||
// message because of the indirect_ret_ty.
|
||||
let fn_kind = if err_happened {Vanilla} else {ForLoop};
|
||||
check_expr_fn(fcx, loop_body, None,
|
||||
decl, *body, fn_kind, Some(inner_ty));
|
||||
demand::suptype(fcx, loop_body.span,
|
||||
inner_ty, fcx.expr_ty(loop_body));
|
||||
}
|
||||
ref n => {
|
||||
die!(fmt!(
|
||||
"check_loop_body expected expr_fn_block, not %?", n))
|
||||
}
|
||||
}
|
||||
|
||||
let block_ty = structurally_resolved_type(
|
||||
fcx, expr.span, fcx.node_ty(loop_body.id));
|
||||
if err_happened {
|
||||
fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
|
||||
} else {
|
||||
let loop_body_ty =
|
||||
ty::replace_closure_return_type(
|
||||
tcx, block_ty, ty::mk_bool(tcx));
|
||||
fcx.write_ty(expr.id, loop_body_ty);
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let id = expr.id;
|
||||
let mut bot = false;
|
||||
|
@ -2153,121 +2262,38 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
ast::expr_match(discrim, ref arms) => {
|
||||
bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms));
|
||||
}
|
||||
ast::expr_fn(proto, ref decl, ref body, _) => {
|
||||
check_expr_fn(fcx, expr, Some(proto),
|
||||
ast::expr_fn(sigil, ref decl, ref body, _) => {
|
||||
check_expr_fn(fcx, expr, Some(sigil),
|
||||
decl, (*body), Vanilla, expected);
|
||||
}
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
check_expr_fn(fcx, expr, None,
|
||||
decl, (*body), Vanilla, expected);
|
||||
}
|
||||
ast::expr_loop_body(b) => {
|
||||
// a loop body is the special argument to a `for` loop. We know that
|
||||
// there will be an expected type in this context because it can only
|
||||
// appear in the context of a call, so we get the expected type of the
|
||||
// parameter. The catch here is that we need to validate two things:
|
||||
// 1. a closure that returns a bool is expected
|
||||
// 2. the closure that was given returns unit
|
||||
let mut err_happened = false;
|
||||
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
|
||||
let inner_ty = match expected_sty {
|
||||
Some(ty::ty_fn(ref fty)) => {
|
||||
match fcx.mk_subty(false, expr.span,
|
||||
(*fty).sig.output, ty::mk_bool(tcx)) {
|
||||
result::Ok(_) =>
|
||||
ty::mk_fn(tcx, FnTyBase {
|
||||
meta: (*fty).meta,
|
||||
sig: FnSig {output: ty::mk_nil(tcx),
|
||||
../*bad*/copy (*fty).sig}
|
||||
}),
|
||||
result::Err(_) => {
|
||||
fcx.type_error_message(expr.span,
|
||||
|actual| {
|
||||
fmt!("A `for` loop iterator should expect a \
|
||||
closure that returns `bool`. This iterator \
|
||||
expects a closure that returns `%s`. %s",
|
||||
actual, if ty::type_is_nil((*fty).sig.output) {
|
||||
"\nDid you mean to use `do` instead of \
|
||||
`for`?" } else { "" } )
|
||||
},
|
||||
(*fty).sig.output, None);
|
||||
err_happened = true;
|
||||
// Kind of a hack: create a function type with the result
|
||||
// replaced with ty_err, to suppress derived errors.
|
||||
let t = ty::replace_fn_return_type(tcx, ty::mk_fn(tcx,
|
||||
copy *fty),
|
||||
ty::mk_err(tcx));
|
||||
fcx.write_ty(id, ty::mk_err(tcx));
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
_ =>
|
||||
match expected {
|
||||
Some(expected_t) => {
|
||||
fcx.type_error_message(expr.span, |actual| {
|
||||
fmt!("a `loop` function's last \
|
||||
argument should be of function \
|
||||
type, not `%s`",
|
||||
actual)
|
||||
},
|
||||
expected_t, None);
|
||||
let err_ty = ty::mk_err(tcx);
|
||||
fcx.write_ty(id, err_ty);
|
||||
err_happened = true;
|
||||
err_ty
|
||||
}
|
||||
None => fcx.tcx().sess.impossible_case(expr.span,
|
||||
~"loop body must have an expected type")
|
||||
}
|
||||
};
|
||||
match b.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
// If an error occurred, we pretend this isn't a for
|
||||
// loop, so as to assign types to all nodes while also
|
||||
// propagating ty_err throughout so as to suppress
|
||||
// derived errors. If we passed in ForLoop in the
|
||||
// error case, we'd potentially emit a spurious error
|
||||
// message because of the indirect_ret_ty.
|
||||
let fn_kind = if err_happened { Vanilla }
|
||||
else { ForLoop };
|
||||
check_expr_fn(fcx, b, None,
|
||||
decl, *body, fn_kind, Some(inner_ty));
|
||||
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
|
||||
}
|
||||
// argh
|
||||
_ => die!(~"expr_fn_block")
|
||||
}
|
||||
let block_ty = structurally_resolved_type(
|
||||
fcx, expr.span, fcx.node_ty(b.id));
|
||||
if err_happened {
|
||||
fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
|
||||
} else {
|
||||
let loop_body_ty = ty::replace_fn_return_type(tcx, block_ty,
|
||||
ty::mk_bool(tcx));
|
||||
fcx.write_ty(expr.id, loop_body_ty);
|
||||
}
|
||||
ast::expr_loop_body(loop_body) => {
|
||||
check_loop_body(fcx, expr, expected, loop_body);
|
||||
}
|
||||
ast::expr_do_body(b) => {
|
||||
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
|
||||
let inner_ty = match expected_sty {
|
||||
Some(ty::ty_fn(ref fty)) => {
|
||||
ty::mk_fn(tcx, (/*bad*/copy *fty))
|
||||
}
|
||||
_ => match expected {
|
||||
Some(expected_t) => {
|
||||
fcx.type_error_message(expr.span, |_actual| {
|
||||
~"Non-function passed to a `do` \
|
||||
function as its last argument, or wrong number \
|
||||
of arguments passed to a `do` function"
|
||||
}, expected_t, None);
|
||||
let err_ty = ty::mk_err(tcx);
|
||||
fcx.write_ty(id, err_ty);
|
||||
err_ty
|
||||
}
|
||||
None => fcx.tcx().sess.impossible_case(expr.span,
|
||||
~"do body must have expected type")
|
||||
}
|
||||
Some(ty::ty_closure(_)) => expected.get(),
|
||||
_ => match expected {
|
||||
Some(expected_t) => {
|
||||
fcx.type_error_message(expr.span, |actual| {
|
||||
fmt!("last argument in `do` call \
|
||||
has non-closure type: %s",
|
||||
actual)
|
||||
}, expected_t, None);
|
||||
let err_ty = ty::mk_err(tcx);
|
||||
fcx.write_ty(id, err_ty);
|
||||
err_ty
|
||||
}
|
||||
None => {
|
||||
fcx.tcx().sess.impossible_case(
|
||||
expr.span,
|
||||
~"do body must have expected type")
|
||||
}
|
||||
}
|
||||
};
|
||||
match b.node {
|
||||
ast::expr_fn_block(ref decl, ref body) => {
|
||||
|
@ -2290,11 +2316,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
};
|
||||
fcx.write_ty(id, typ);
|
||||
}
|
||||
ast::expr_call(f, args, _) => {
|
||||
bot = check_call(fcx, expr.span, expr.id, f, args);
|
||||
ast::expr_call(f, args, sugar) => {
|
||||
bot = check_call(fcx, expr.span, expr.id, f, args, sugar);
|
||||
}
|
||||
ast::expr_method_call(rcvr, ident, tps, args, _) => {
|
||||
bot = check_method_call(fcx, expr, rcvr, ident, args, tps);
|
||||
ast::expr_method_call(rcvr, ident, tps, args, sugar) => {
|
||||
bot = check_method_call(fcx, expr, rcvr, ident, args, tps, sugar);
|
||||
}
|
||||
ast::expr_cast(e, t) => {
|
||||
bot = check_expr(fcx, e);
|
||||
|
@ -3088,20 +3114,18 @@ pub fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
|||
arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
|
||||
}
|
||||
~"frame_address" => {
|
||||
let fty = ty::mk_fn(ccx.tcx, FnTyBase {
|
||||
meta: FnMeta {purity: ast::impure_fn,
|
||||
proto: ast::ProtoBorrowed,
|
||||
onceness: ast::Once,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
bounds: @~[]},
|
||||
sig: FnSig {
|
||||
inputs: ~[arg {
|
||||
mode: ast::expl(ast::by_val),
|
||||
ty: ty::mk_imm_ptr(
|
||||
ccx.tcx,
|
||||
ty::mk_mach_uint(ccx.tcx, ast::ty_u8))
|
||||
}],
|
||||
output: ty::mk_nil(ccx.tcx)}
|
||||
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
|
||||
purity: ast::impure_fn,
|
||||
sigil: ast::BorrowedSigil,
|
||||
onceness: ast::Once,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
sig: ty::FnSig {
|
||||
inputs: ~[arg {mode: ast::expl(ast::by_val),
|
||||
ty: ty::mk_imm_ptr(
|
||||
ccx.tcx,
|
||||
ty::mk_mach_uint(ccx.tcx, ast::ty_u8))}],
|
||||
output: ty::mk_nil(ccx.tcx)
|
||||
}
|
||||
});
|
||||
(0u, ~[arg(ast::by_ref, fty)], ty::mk_nil(tcx))
|
||||
}
|
||||
|
@ -3324,12 +3348,9 @@ pub fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
|||
return;
|
||||
}
|
||||
};
|
||||
let fty = ty::mk_fn(tcx, FnTyBase {
|
||||
meta: FnMeta {purity: ast::unsafe_fn,
|
||||
proto: ast::ProtoBare,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_static,
|
||||
bounds: @~[]},
|
||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||
purity: ast::unsafe_fn,
|
||||
abi: ast::RustAbi,
|
||||
sig: FnSig {inputs: inputs,
|
||||
output: output}
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ use core::prelude::*;
|
|||
use middle::freevars::get_freevars;
|
||||
use middle::pat_util::{pat_bindings, pat_is_binding};
|
||||
use middle::ty::{encl_region, re_scope};
|
||||
use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice};
|
||||
use middle::ty::{vstore_box, vstore_fixed, vstore_slice};
|
||||
use middle::ty::{vstore_uniq};
|
||||
use middle::ty;
|
||||
use middle::typeck::check::fn_ctxt;
|
||||
|
@ -42,7 +42,7 @@ use middle::typeck::infer::{resolve_type};
|
|||
use util::ppaux::{note_and_explain_region, ty_to_str};
|
||||
|
||||
use core::result;
|
||||
use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed};
|
||||
use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil};
|
||||
use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::span;
|
||||
|
@ -59,10 +59,9 @@ pub fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region {
|
|||
def_self(node_id, _) | def_binding(node_id, _) =>
|
||||
return encl_region(tcx, node_id),
|
||||
def_upvar(_, subdef, closure_id, body_id) => {
|
||||
match ty_fn_proto(fcx.node_ty(closure_id)) {
|
||||
ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"),
|
||||
ProtoBorrowed => encl_region_of_def(fcx, *subdef),
|
||||
ProtoBox | ProtoUniq => re_scope(body_id)
|
||||
match ty::ty_closure_sigil(fcx.node_ty(closure_id)) {
|
||||
BorrowedSigil => encl_region_of_def(fcx, *subdef),
|
||||
ManagedSigil | OwnedSigil => re_scope(body_id)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -278,11 +277,9 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
|
|||
ast::expr_fn(*) | ast::expr_fn_block(*) => {
|
||||
let function_type = rcx.resolve_node_type(expr.id);
|
||||
match ty::get(function_type).sty {
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
if fn_ty.meta.proto == ast::ProtoBorrowed {
|
||||
constrain_free_variables(
|
||||
rcx, fn_ty.meta.region, expr);
|
||||
}
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
|
||||
region: region, _}) => {
|
||||
constrain_free_variables(rcx, region, expr);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
use core::prelude::*;
|
||||
|
||||
use middle::ty::{FnTyBase};
|
||||
use middle::ty;
|
||||
use middle::typeck::check::self_info;
|
||||
use middle::typeck::isr_alist;
|
||||
|
@ -27,22 +26,6 @@ use syntax::print::pprust::{expr_to_str};
|
|||
|
||||
// Helper functions related to manipulating region types.
|
||||
|
||||
pub fn replace_bound_regions_in_fn_ty(
|
||||
tcx: ty::ctxt,
|
||||
isr: isr_alist,
|
||||
self_info: Option<self_info>,
|
||||
fn_ty: &ty::FnTy,
|
||||
mapf: fn(ty::bound_region) -> ty::Region) ->
|
||||
{isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} {
|
||||
let {isr, self_info, fn_sig} =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, isr, self_info, &fn_ty.sig, mapf);
|
||||
{isr: isr,
|
||||
self_info: self_info,
|
||||
fn_ty: FnTyBase {meta: fn_ty.meta,
|
||||
sig: fn_sig}}
|
||||
}
|
||||
|
||||
pub fn replace_bound_regions_in_fn_sig(
|
||||
tcx: ty::ctxt,
|
||||
isr: isr_alist,
|
||||
|
|
|
@ -233,7 +233,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
|
|||
relate_trait_tys(vcx, location_info, trait_ty, ty);
|
||||
if !allow_unsafe && !is_early {
|
||||
for vec::each(*ty::trait_methods(tcx, did)) |m| {
|
||||
if ty::type_has_self(ty::mk_fn(tcx, /*bad*/copy m.fty)) {
|
||||
if ty::type_has_self(ty::mk_bare_fn(tcx, copy m.fty)) {
|
||||
tcx.sess.span_err(
|
||||
location_info.span,
|
||||
~"a boxed trait with self types may not be \
|
||||
|
|
|
@ -26,10 +26,10 @@ use middle::resolve::{Impl, MethodInfo};
|
|||
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
|
||||
use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst};
|
||||
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
|
||||
use middle::ty::{ty_rec, ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
|
||||
use middle::ty::{ty_type, ty_uint, ty_uniq};
|
||||
use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure};
|
||||
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
|
||||
use middle::ty::{type_is_ty_var};
|
||||
use middle::ty;
|
||||
|
@ -108,7 +108,7 @@ pub fn get_base_type(inference_context: @InferCtxt,
|
|||
|
||||
ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
|
||||
ty_estr(*) | ty_evec(*) | ty_rec(*) |
|
||||
ty_fn(*) | ty_tup(*) | ty_infer(*) |
|
||||
ty_bare_fn(*) | ty_closure(*) | ty_tup(*) | ty_infer(*) |
|
||||
ty_param(*) | ty_self | ty_type | ty_opaque_box |
|
||||
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => {
|
||||
debug!("(getting base type) no base type; found %?",
|
||||
|
|
|
@ -33,10 +33,10 @@ are represented as `ty_param()` instances.
|
|||
use core::prelude::*;
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::ty::{FnMeta, FnSig, FnTyBase, InstantiatedTraitRef, arg};
|
||||
use middle::ty::{InstantiatedTraitRef, arg};
|
||||
use middle::ty::{substs, ty_param_substs_and_ty};
|
||||
use middle::ty;
|
||||
use middle::typeck::astconv::{ast_conv, ty_of_fn_decl, ty_of_arg};
|
||||
use middle::typeck::astconv::{ast_conv, ty_of_arg};
|
||||
use middle::typeck::astconv::{ast_ty_to_ty};
|
||||
use middle::typeck::astconv;
|
||||
use middle::typeck::infer;
|
||||
|
@ -153,9 +153,10 @@ pub impl @crate_ctxt: ast_conv {
|
|||
|
||||
pub fn get_enum_variant_types(ccx: @crate_ctxt,
|
||||
enum_ty: ty::t,
|
||||
variants: ~[ast::variant],
|
||||
ty_params: ~[ast::ty_param],
|
||||
rp: Option<ty::region_variance>) {
|
||||
variants: &[ast::variant],
|
||||
ty_params: &[ast::ty_param],
|
||||
rp: Option<ty::region_variance>)
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
// Create a set of parameter types shared among all the variants.
|
||||
|
@ -166,58 +167,35 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt,
|
|||
match variant.node.kind {
|
||||
ast::tuple_variant_kind(ref args) if args.len() > 0 => {
|
||||
let rs = type_rscope(rp);
|
||||
let args = args.map(|va| {
|
||||
let arg_ty = ccx.to_ty(rs, va.ty);
|
||||
arg { mode: ast::expl(ast::by_copy), ty: arg_ty }
|
||||
});
|
||||
result_ty = Some(ty::mk_fn(tcx, FnTyBase {
|
||||
meta: FnMeta {purity: ast::pure_fn,
|
||||
proto: ast::ProtoBare,
|
||||
onceness: ast::Many,
|
||||
bounds: @~[],
|
||||
region: ty::re_static},
|
||||
sig: FnSig {inputs: args,
|
||||
output: enum_ty}
|
||||
}));
|
||||
let input_tys = args.map(|va| ccx.to_ty(rs, va.ty));
|
||||
result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
|
||||
}
|
||||
|
||||
ast::tuple_variant_kind(_) => {
|
||||
result_ty = Some(enum_ty);
|
||||
}
|
||||
|
||||
ast::struct_variant_kind(struct_def) => {
|
||||
// XXX: Merge with computation of the the same value below?
|
||||
let tpt = {
|
||||
bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
|
||||
region_param: rp,
|
||||
ty: enum_ty
|
||||
};
|
||||
convert_struct(
|
||||
ccx,
|
||||
rp,
|
||||
struct_def,
|
||||
/*bad*/copy ty_params,
|
||||
tpt,
|
||||
variant.node.id);
|
||||
// Compute the ctor arg types from the struct fields
|
||||
let struct_fields = do struct_def.fields.map |struct_field| {
|
||||
arg {
|
||||
mode: ast::expl(ast::by_val),
|
||||
ty: ty::node_id_to_type(ccx.tcx, struct_field.node.id)
|
||||
}
|
||||
};
|
||||
result_ty = Some(ty::mk_fn(tcx, FnTyBase {
|
||||
meta: FnMeta {purity: ast::pure_fn,
|
||||
proto: ast::ProtoBare,
|
||||
onceness: ast::Many,
|
||||
bounds: @~[],
|
||||
region: ty::re_static},
|
||||
sig: FnSig {inputs: struct_fields, output: enum_ty }}));
|
||||
let tpt = {bounds: ty_param_bounds(ccx, ty_params),
|
||||
region_param: rp,
|
||||
ty: enum_ty};
|
||||
|
||||
convert_struct(ccx,
|
||||
rp,
|
||||
struct_def,
|
||||
ty_params.to_vec(),
|
||||
tpt,
|
||||
variant.node.id);
|
||||
|
||||
let input_tys = struct_def.fields.map(
|
||||
|f| ty::node_id_to_type(ccx.tcx, f.node.id));
|
||||
result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
|
||||
}
|
||||
|
||||
ast::enum_variant_kind(ref enum_definition) => {
|
||||
get_enum_variant_types(ccx,
|
||||
enum_ty,
|
||||
/*bad*/copy enum_definition.variants,
|
||||
/*bad*/copy ty_params,
|
||||
rp);
|
||||
get_enum_variant_types(ccx, enum_ty,
|
||||
enum_definition.variants,
|
||||
ty_params, rp);
|
||||
result_ty = None;
|
||||
}
|
||||
};
|
||||
|
@ -225,11 +203,9 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt,
|
|||
match result_ty {
|
||||
None => {}
|
||||
Some(result_ty) => {
|
||||
let tpt = {
|
||||
bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
|
||||
region_param: rp,
|
||||
ty: result_ty
|
||||
};
|
||||
let tpt = {bounds: ty_param_bounds(ccx, ty_params),
|
||||
region_param: rp,
|
||||
ty: result_ty};
|
||||
tcx.tcache.insert(local_def(variant.node.id), tpt);
|
||||
write_ty_to_tcx(tcx, variant.node.id, result_ty);
|
||||
}
|
||||
|
@ -279,7 +255,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt,
|
|||
};
|
||||
let ty = ty::subst(ccx.tcx,
|
||||
&substs,
|
||||
ty::mk_fn(ccx.tcx, /*bad*/copy m.fty));
|
||||
ty::mk_bare_fn(ccx.tcx, copy m.fty));
|
||||
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
|
||||
+ *m.tps);
|
||||
ccx.tcx.tcache.insert(local_def(am.id),
|
||||
|
@ -305,7 +281,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt,
|
|||
ast::provided(method) => def_id = local_def(method.id)
|
||||
}
|
||||
|
||||
let trait_bounds = ty_param_bounds(ccx, copy *params);
|
||||
let trait_bounds = ty_param_bounds(ccx, *params);
|
||||
let ty_m = trait_method_to_ty_method(*m);
|
||||
let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
|
||||
if ty_m.self_ty.node == ast::sty_static {
|
||||
|
@ -458,7 +434,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
|||
// that correspond to the parameters we will find on the impl
|
||||
// - replace self region with a fresh, dummy region
|
||||
let impl_fty = {
|
||||
let impl_fty = ty::mk_fn(tcx, /*bad*/copy impl_m.fty);
|
||||
let impl_fty = ty::mk_bare_fn(tcx, copy impl_m.fty);
|
||||
debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty));
|
||||
replace_bound_self(tcx, impl_fty, dummy_self_r)
|
||||
};
|
||||
|
@ -476,7 +452,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
|||
self_ty: Some(self_ty),
|
||||
tps: vec::append(trait_tps, dummy_tps)
|
||||
};
|
||||
let trait_fty = ty::mk_fn(tcx, /*bad*/copy trait_m.fty);
|
||||
let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty);
|
||||
debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty));
|
||||
ty::subst(tcx, &substs, trait_fty)
|
||||
};
|
||||
|
@ -583,9 +559,9 @@ pub fn convert_methods(ccx: @crate_ctxt,
|
|||
|
||||
let tcx = ccx.tcx;
|
||||
do vec::map(ms) |m| {
|
||||
let bounds = ty_param_bounds(ccx, /*bad*/copy m.tps);
|
||||
let bounds = ty_param_bounds(ccx, m.tps);
|
||||
let mty = ty_of_method(ccx, *m, rp);
|
||||
let fty = ty::mk_fn(tcx, /*bad*/copy mty.fty);
|
||||
let fty = ty::mk_bare_fn(tcx, copy mty.fty);
|
||||
tcx.tcache.insert(
|
||||
local_def(m.id),
|
||||
|
||||
|
@ -626,13 +602,11 @@ pub fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
|||
ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration");
|
||||
let tpt = ty_of_item(ccx, it);
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
get_enum_variant_types(ccx,
|
||||
tpt.ty,
|
||||
/*bad*/copy (*enum_definition).variants,
|
||||
/*bad*/copy *ty_params, rp);
|
||||
get_enum_variant_types(ccx, tpt.ty, enum_definition.variants,
|
||||
*ty_params, rp);
|
||||
}
|
||||
ast::item_impl(ref tps, trait_ref, selfty, ref ms) => {
|
||||
let i_bounds = ty_param_bounds(ccx, /*bad*/copy *tps);
|
||||
let i_bounds = ty_param_bounds(ccx, *tps);
|
||||
let selfty = ccx.to_ty(type_rscope(rp), selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
tcx.tcache.insert(local_def(it.id),
|
||||
|
@ -695,13 +669,12 @@ pub fn convert_struct(ccx: @crate_ctxt,
|
|||
|
||||
do option::iter(&struct_def.dtor) |dtor| {
|
||||
// Write the dtor type
|
||||
let t_dtor = ty::mk_fn(
|
||||
let t_dtor = ty::mk_bare_fn(
|
||||
tcx,
|
||||
ty_of_fn_decl(
|
||||
ccx, type_rscope(rp), ast::ProtoBare,
|
||||
ast::impure_fn, ast::Many,
|
||||
/*bounds:*/ @~[], /*opt_region:*/ None,
|
||||
ast_util::dtor_dec(), None, dtor.span));
|
||||
astconv::ty_of_bare_fn(
|
||||
ccx, type_rscope(rp),
|
||||
ast::impure_fn, ast::RustAbi,
|
||||
ast_util::dtor_dec()));
|
||||
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
|
||||
tcx.tcache.insert(local_def(dtor.node.id),
|
||||
{bounds: tpt.bounds,
|
||||
|
@ -727,25 +700,11 @@ pub fn convert_struct(ccx: @crate_ctxt,
|
|||
tcx.tcache.insert(local_def(ctor_id), tpt);
|
||||
} else if struct_def.fields[0].node.kind == ast::unnamed_field {
|
||||
// Tuple-like.
|
||||
let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase {
|
||||
meta: FnMeta {
|
||||
purity: ast::pure_fn,
|
||||
proto: ast::ProtoBare,
|
||||
onceness: ast::Many,
|
||||
bounds: @~[],
|
||||
region: ty::re_static
|
||||
},
|
||||
sig: FnSig {
|
||||
inputs: do struct_def.fields.map |field| {
|
||||
arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
ty: ccx.tcx.tcache.get
|
||||
(&local_def(field.node.id)).ty
|
||||
}
|
||||
},
|
||||
output: selfty
|
||||
}
|
||||
});
|
||||
let inputs =
|
||||
struct_def.fields.map(
|
||||
|field| ccx.tcx.tcache.get(
|
||||
&local_def(field.node.id)).ty);
|
||||
let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
|
||||
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
|
||||
tcx.tcache.insert(local_def(ctor_id), {
|
||||
bounds: tpt.bounds,
|
||||
|
@ -770,11 +729,9 @@ pub fn ty_of_method(ccx: @crate_ctxt,
|
|||
m: @ast::method,
|
||||
rp: Option<ty::region_variance>) -> ty::method {
|
||||
{ident: m.ident,
|
||||
tps: ty_param_bounds(ccx, /*bad*/copy m.tps),
|
||||
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare,
|
||||
m.purity, ast::Many,
|
||||
/*bounds:*/ @~[], /*opt_region:*/ None,
|
||||
m.decl, None, m.span),
|
||||
tps: ty_param_bounds(ccx, m.tps),
|
||||
fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity,
|
||||
ast::RustAbi, m.decl),
|
||||
self_ty: m.self_ty.node,
|
||||
vis: m.vis,
|
||||
def_id: local_def(m.id)}
|
||||
|
@ -785,11 +742,9 @@ pub fn ty_of_ty_method(self: @crate_ctxt,
|
|||
rp: Option<ty::region_variance>,
|
||||
id: ast::def_id) -> ty::method {
|
||||
{ident: m.ident,
|
||||
tps: ty_param_bounds(self, /*bad*/copy m.tps),
|
||||
fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare,
|
||||
m.purity, ast::Many,
|
||||
/*bounds:*/ @~[], /*opt_region:*/ None,
|
||||
m.decl, None, m.span),
|
||||
tps: ty_param_bounds(self, m.tps),
|
||||
fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity,
|
||||
ast::RustAbi, m.decl),
|
||||
// assume public, because this is only invoked on trait methods
|
||||
self_ty: m.self_ty.node,
|
||||
vis: ast::public,
|
||||
|
@ -844,13 +799,11 @@ pub fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
|||
}
|
||||
ast::item_fn(decl, purity, tps, _) => {
|
||||
let bounds = ty_param_bounds(ccx, tps);
|
||||
let tofd = ty_of_fn_decl(ccx, empty_rscope,
|
||||
ast::ProtoBare, purity, ast::Many,
|
||||
/*bounds:*/ @~[], /*opt_region:*/ None,
|
||||
decl, None, it.span);
|
||||
let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity,
|
||||
ast::RustAbi, decl);
|
||||
let tpt = {bounds: bounds,
|
||||
region_param: None,
|
||||
ty: ty::mk_fn(ccx.tcx, tofd)};
|
||||
ty: ty::mk_bare_fn(ccx.tcx, tofd)};
|
||||
debug!("type of %s (id %d) is %s",
|
||||
tcx.sess.str_of(it.ident),
|
||||
it.id,
|
||||
|
@ -976,7 +929,7 @@ pub fn compute_bounds(ccx: @crate_ctxt,
|
|||
}
|
||||
|
||||
pub fn ty_param_bounds(ccx: @crate_ctxt,
|
||||
params: ~[ast::ty_param]) -> @~[ty::param_bounds] {
|
||||
params: &[ast::ty_param]) -> @~[ty::param_bounds] {
|
||||
@do params.map |param| {
|
||||
match ccx.tcx.ty_param_bounds.find(¶m.id) {
|
||||
Some(bs) => bs,
|
||||
|
@ -999,15 +952,13 @@ pub fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
|
|||
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, *a, None) );
|
||||
let output_ty = ast_ty_to_ty(ccx, rb, decl.output);
|
||||
|
||||
let t_fn = ty::mk_fn(ccx.tcx, FnTyBase {
|
||||
meta: FnMeta {purity: ast::unsafe_fn,
|
||||
onceness: ast::Many,
|
||||
proto: ast::ProtoBare,
|
||||
bounds: @~[],
|
||||
region: ty::re_static},
|
||||
sig: FnSig {inputs: input_tys,
|
||||
output: output_ty}
|
||||
});
|
||||
let t_fn = ty::mk_bare_fn(
|
||||
ccx.tcx,
|
||||
ty::BareFnTy {
|
||||
abi: ast::RustAbi,
|
||||
purity: ast::unsafe_fn,
|
||||
sig: ty::FnSig {inputs: input_tys, output: output_ty}
|
||||
});
|
||||
let tpt = {bounds: bounds, region_param: None, ty: t_fn};
|
||||
ccx.tcx.tcache.insert(def_id, tpt);
|
||||
return tpt;
|
||||
|
@ -1017,8 +968,7 @@ pub fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param])
|
|||
-> {bounds: @~[ty::param_bounds], params: ~[ty::t]} {
|
||||
|
||||
let mut i = 0u;
|
||||
// XXX: Bad copy.
|
||||
let bounds = ty_param_bounds(ccx, copy atps);
|
||||
let bounds = ty_param_bounds(ccx, atps);
|
||||
{bounds: bounds,
|
||||
params: vec::map(atps, |atp| {
|
||||
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
|
||||
|
|
|
@ -69,7 +69,7 @@ use core::prelude::*;
|
|||
use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn};
|
||||
use middle::ty::{AutoAdjustment, AutoRef};
|
||||
use middle::ty::{vstore_slice, vstore_box, vstore_uniq, vstore_fixed};
|
||||
use middle::ty::{FnMeta, FnTyBase, mt};
|
||||
use middle::ty::{mt};
|
||||
use middle::ty;
|
||||
use middle::typeck::infer::{CoerceResult, resolve_type};
|
||||
use middle::typeck::infer::combine::CombineFields;
|
||||
|
@ -117,7 +117,7 @@ impl Coerce {
|
|||
};
|
||||
}
|
||||
|
||||
ty::ty_fn(ref b_f) if b_f.meta.proto == ast::ProtoBorrowed => {
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, _}) => {
|
||||
return do self.unpack_actual_value(a) |sty_a| {
|
||||
self.coerce_borrowed_fn(a, sty_a, b)
|
||||
};
|
||||
|
@ -134,7 +134,7 @@ impl Coerce {
|
|||
|
||||
do self.unpack_actual_value(a) |sty_a| {
|
||||
match *sty_a {
|
||||
ty::ty_fn(ref a_f) if a_f.meta.proto == ast::ProtoBare => {
|
||||
ty::ty_bare_fn(ref a_f) => {
|
||||
// Bare functions are coercable to any closure type.
|
||||
//
|
||||
// FIXME(#3320) this should go away and be
|
||||
|
@ -289,9 +289,9 @@ impl Coerce {
|
|||
b.inf_str(self.infcx));
|
||||
|
||||
let fn_ty = match *sty_a {
|
||||
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBox => {f}
|
||||
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoUniq => {f}
|
||||
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBare => {
|
||||
ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil => copy *f,
|
||||
ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => copy *f,
|
||||
ty::ty_bare_fn(ref f) => {
|
||||
return self.coerce_from_bare_fn(a, f, b);
|
||||
}
|
||||
_ => {
|
||||
|
@ -300,12 +300,13 @@ impl Coerce {
|
|||
};
|
||||
|
||||
let r_borrow = self.infcx.next_region_var_nb(self.span);
|
||||
let meta = FnMeta {proto: ast::ProtoBorrowed,
|
||||
region: r_borrow,
|
||||
..fn_ty.meta};
|
||||
let a_borrowed = ty::mk_fn(self.infcx.tcx,
|
||||
FnTyBase {meta: meta,
|
||||
sig: copy fn_ty.sig});
|
||||
let a_borrowed = ty::mk_closure(
|
||||
self.infcx.tcx,
|
||||
ty::ClosureTy {
|
||||
sigil: ast::BorrowedSigil,
|
||||
region: r_borrow,
|
||||
..fn_ty
|
||||
});
|
||||
|
||||
if_ok!(self.subtype(a_borrowed, b));
|
||||
Ok(Some(@AutoAdjustment {
|
||||
|
@ -320,7 +321,7 @@ impl Coerce {
|
|||
|
||||
fn coerce_from_bare_fn(&self,
|
||||
a: ty::t,
|
||||
fn_ty_a: &ty::FnTy,
|
||||
fn_ty_a: &ty::BareFnTy,
|
||||
b: ty::t) -> CoerceResult
|
||||
{
|
||||
do self.unpack_actual_value(b) |sty_b| {
|
||||
|
@ -330,7 +331,7 @@ impl Coerce {
|
|||
|
||||
fn coerce_from_bare_fn_post_unpack(&self,
|
||||
a: ty::t,
|
||||
fn_ty_a: &ty::FnTy,
|
||||
fn_ty_a: &ty::BareFnTy,
|
||||
b: ty::t,
|
||||
sty_b: &ty::sty) -> CoerceResult
|
||||
{
|
||||
|
@ -338,18 +339,18 @@ impl Coerce {
|
|||
a.inf_str(self.infcx), b.inf_str(self.infcx));
|
||||
|
||||
let fn_ty_b = match *sty_b {
|
||||
ty::ty_fn(ref f) if f.meta.proto != ast::ProtoBare => {f}
|
||||
ty::ty_closure(ref f) => {copy *f}
|
||||
_ => {
|
||||
return self.subtype(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
// for now, bare fn and closures have the same
|
||||
// representation
|
||||
let a_adapted = ty::mk_fn(self.infcx.tcx,
|
||||
FnTyBase {meta: copy fn_ty_b.meta,
|
||||
sig: copy fn_ty_a.sig});
|
||||
self.subtype(a_adapted, b)
|
||||
// for now, bare fn and closures have the same
|
||||
// representation
|
||||
let a_closure = ty::mk_closure(
|
||||
self.infcx.tcx,
|
||||
ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b});
|
||||
self.subtype(a_closure, b)
|
||||
}
|
||||
|
||||
fn coerce_unsafe_ptr(&self,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue