1
Fork 0

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:
Niko Matsakis 2013-01-31 17:12:29 -08:00
parent 82d7396333
commit a32498d846
187 changed files with 2065 additions and 2373 deletions

View file

@ -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", debug!("making tests from %s",
config.src_base.to_str()); config.src_base.to_str());
let mut tests = ~[]; let mut tests = ~[];
@ -196,13 +196,14 @@ pub fn is_test(config: config, testfile: &Path) -> bool {
return valid; return valid;
} }
pub fn make_test(config: config, testfile: &Path) -> pub fn make_test(config: config, testfile: &Path) -> test::TestDescAndFn {
test::TestDesc { test::TestDescAndFn {
test::TestDesc { desc: test::TestDesc {
name: make_test_name(config, testfile), name: make_test_name(config, testfile),
ignore: header::is_test_ignored(config, testfile),
should_fail: false
},
testfn: make_test_closure(config, testfile), testfn: make_test_closure(config, testfile),
ignore: header::is_test_ignored(config, testfile),
should_fail: false
} }
} }

View file

@ -10,10 +10,6 @@
//! Managed vectors //! Managed vectors
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::transmute; use cast::transmute;
use kinds::Copy; use kinds::Copy;
use iter; use iter;

View file

@ -9,10 +9,6 @@
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Boolean logic //! Boolean logic
use bool; use bool;

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
//! Unsafe operations
#[forbid(deprecated_mode)]
#[abi = "rust-intrinsic"] #[abi = "rust-intrinsic"]
extern mod rusti { extern mod rusti {
fn forget<T>(-x: T); fn forget<T>(-x: T);

View file

@ -10,10 +10,6 @@
//! Utilities for manipulating the char type //! Utilities for manipulating the char type
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use char; use char;
use cmp::Eq; use cmp::Eq;
use option::{None, Option, Some}; use option::{None, Option, Some};

View file

@ -10,10 +10,6 @@
#[doc(hidden)]; #[doc(hidden)];
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use libc::{c_char, c_void, intptr_t, uintptr_t}; use libc::{c_char, c_void, intptr_t, uintptr_t};
use ptr::{mut_null, null, to_unsafe_ptr}; use ptr::{mut_null, null, to_unsafe_ptr};
use repr::BoxRepr; use repr::BoxRepr;

View file

@ -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 * Trait for values that can be compared for equality
* and inequality. * and inequality.

View file

@ -10,9 +10,6 @@
//! Container traits //! Container traits
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use option::Option; use option::Option;
pub trait Container { pub trait Container {

View file

@ -48,8 +48,6 @@ Implicitly, all crates behave as if they included the following prologue:
// Don't link to core. We are core. // Don't link to core. We are core.
#[no_core]; #[no_core];
#[warn(deprecated_mode)];
#[warn(deprecated_pattern)];
#[warn(vecs_implicitly_copyable)]; #[warn(vecs_implicitly_copyable)];
#[deny(non_camel_case_types)]; #[deny(non_camel_case_types)];
#[allow(deprecated_self)]; #[allow(deprecated_self)];

View file

@ -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 kinds::Copy;
use managed; use managed;
use option::{None, Option, Some}; use option::{None, Option, Some};

View file

@ -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;
use cast::reinterpret_cast; use cast::reinterpret_cast;
use prelude::*; use prelude::*;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! A type that represents one of two alternatives //! A type that represents one of two alternatives
use cmp::Eq; use cmp::Eq;

View file

@ -51,10 +51,6 @@
//! * s - str (any flavor) //! * s - str (any flavor)
//! * ? - arbitrary type (does not use the to_str trait) //! * ? - arbitrary type (does not use the to_str trait)
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
// Transitional // Transitional
#[allow(structural_records)]; // Macros -- needs a snapshot #[allow(structural_records)]; // Macros -- needs a snapshot

View file

@ -14,10 +14,6 @@ Simple compression
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use libc; use libc;
use libc::{c_void, size_t, c_int}; use libc::{c_void, size_t, c_int};
use ptr; use ptr;

View file

@ -10,10 +10,6 @@
//! The trait for types that can be created from strings //! The trait for types that can be created from strings
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use option::Option; use option::Option;
pub trait FromStr { pub trait FromStr {

View file

@ -35,9 +35,6 @@ with destructors.
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
// Transitional // Transitional
#[allow(structural_records)]; #[allow(structural_records)];

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
/*! /*!
* Implementation of SipHash 2-4 * Implementation of SipHash 2-4
* *

View file

@ -10,10 +10,6 @@
//! Sendable hash maps. //! Sendable hash maps.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use container::{Container, Mutable, Map, Set}; use container::{Container, Mutable, Map, Set};
use cmp::Eq; use cmp::Eq;
use hash::Hash; use hash::Hash;

View file

@ -14,9 +14,6 @@ Basic input/output
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use result::Result; use result::Result;
use cmp::Eq; use cmp::Eq;

View file

@ -12,9 +12,6 @@
// workaround our lack of traits and lack of macros. See core.{rc,rs} for // workaround our lack of traits and lack of macros. See core.{rc,rs} for
// how this file is used. // how this file is used.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
use iter::BaseIter; use iter::BaseIter;
use iter; use iter;

View file

@ -14,9 +14,6 @@ The iteration traits and common implementation
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
use kinds::Copy; use kinds::Copy;
use option::{None, Option, Some}; use option::{None, Option, Some};

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
/*! /*!
* Bindings for libc. * Bindings for libc.
* *

View file

@ -10,10 +10,6 @@
//! Logging //! Logging
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::transmute; use cast::transmute;
use io; use io;
use libc; use libc;

View file

@ -10,10 +10,6 @@
//! Operations on managed box types //! Operations on managed box types
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::transmute; use cast::transmute;
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
use managed::raw::BoxRepr; use managed::raw::BoxRepr;

View file

@ -18,8 +18,6 @@ dynamic checks: your program will fail if you attempt to perform
mutation when the data structure should be immutable. mutation when the data structure should be immutable.
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use util::with; use util::with;
use cast::transmute_immut; use cast::transmute_immut;

View file

@ -14,10 +14,6 @@ Functions for the unit type.
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
#[cfg(notest)] #[cfg(notest)]

View file

@ -9,9 +9,6 @@
// except according to those terms. // except according to those terms.
#[doc(hidden)]; // FIXME #3538 #[doc(hidden)]; // FIXME #3538
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use libc::c_int; use libc::c_int;
use libc::c_float; use libc::c_float;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Operations and constants for `f32` //! Operations and constants for `f32`
use cmath; use cmath;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Operations and constants for `f64` //! Operations and constants for `f64`
use cmath; use cmath;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Operations and constants for `float` //! Operations and constants for `float`
// Even though this module exports everything defined in it, // Even though this module exports everything defined in it,

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use T = self::inst::T; use T = self::inst::T;
use char; use char;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use T = self::inst::T; use T = self::inst::T;
use T_SIGNED = self::inst::T_SIGNED; use T_SIGNED = self::inst::T_SIGNED;

View file

@ -10,9 +10,6 @@
// Core operators // Core operators
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
#[lang="drop"] #[lang="drop"]
pub trait Drop { pub trait Drop {
fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton

View file

@ -41,9 +41,6 @@ let unwrapped_msg = match move msg {
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq; use cmp::Eq;
use kinds::Copy; use kinds::Copy;
use option; use option;

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
#[allow(structural_records)]; #[allow(structural_records)];
/*! /*!

View file

@ -10,10 +10,6 @@
//! Operations on unique pointer types //! Operations on unique pointer types
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
#[cfg(notest)] #[cfg(notest)]

View file

@ -14,10 +14,6 @@ Cross-platform file path handling
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq; use cmp::Eq;
use libc; use libc;
use option::{None, Option, Some}; use option::{None, Option, Some};

View file

@ -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 // Transitional -- needs snapshot
#[allow(structural_records)]; #[allow(structural_records)];

View file

@ -36,7 +36,7 @@ pub use path::PosixPath;
pub use path::WindowsPath; pub use path::WindowsPath;
pub use pipes::{GenericChan, GenericPort}; pub use pipes::{GenericChan, GenericPort};
pub use ptr::Ptr; pub use ptr::Ptr;
pub use str::{StrSlice, Trimmable}; pub use str::{StrSlice, Trimmable, OwnedStr};
pub use to_bytes::IterBytes; pub use to_bytes::IterBytes;
pub use to_str::ToStr; pub use to_str::ToStr;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};

View file

@ -8,11 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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)]; #[doc(hidden)];
use cast; use cast;

View file

@ -26,10 +26,19 @@ do || {
use ops::Drop; use ops::Drop;
use task::{spawn, failing}; use task::{spawn, failing};
#[cfg(stage0)]
pub trait Finally<T> { pub trait Finally<T> {
fn finally(&self, +dtor: &fn()) -> 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> { impl<T> &fn() -> T: Finally<T> {
// FIXME #4518: Should not require a mode here // FIXME #4518: Should not require a mode here
fn finally(&self, +dtor: &fn()) -> T { 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 { struct Finallyalizer {
dtor: &fn() dtor: &fn()
} }

View file

@ -10,9 +10,6 @@
//! Unsafe pointer utility functions //! Unsafe pointer utility functions
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast; use cast;
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
use libc; use libc;

View file

@ -10,10 +10,6 @@
//! Random number generation //! Random number generation
// NB: transitional, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use int; use int;
use prelude::*; use prelude::*;
use str; use str;

View file

@ -14,9 +14,6 @@ Runtime type reflection
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
use libc::c_void; use libc::c_void;
use sys; use sys;

View file

@ -14,9 +14,6 @@ More runtime type reflection
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::transmute; use cast::transmute;
use cast; use cast;
use char; use char;

View file

@ -12,9 +12,6 @@
// NB: transitionary, de-mode-ing. // NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp; use cmp;
use cmp::Eq; use cmp::Eq;
use either; use either;

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Runtime calls emitted by the compiler. //! Runtime calls emitted by the compiler.
use cast::transmute; use cast::transmute;

View file

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
#[allow(structural_records)]; #[allow(structural_records)];
//! Process spawning //! Process spawning

View file

@ -11,12 +11,7 @@
#[doc(hidden)]; // FIXME #3538 #[doc(hidden)]; // FIXME #3538
#[legacy_modes]; // tjc: remove after snapshot #[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)]; #[allow(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::reinterpret_cast; use cast::reinterpret_cast;
use ptr::offset; use ptr::offset;

View file

@ -17,9 +17,6 @@
* some heavy-duty uses, try std::rope. * some heavy-duty uses, try std::rope.
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use at_vec; use at_vec;
use cast; use cast;
use char; use char;
@ -2314,6 +2311,21 @@ impl &str: StrSlice {
pure fn char_at(i: uint) -> char { char_at(self, i) } 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)] #[cfg(test)]
mod tests { mod tests {
use char; use char;

View file

@ -10,10 +10,6 @@
//! Misc low level stuff //! Misc low level stuff
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast; use cast;
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};
use gc; use gc;

View file

@ -8,11 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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. * Task management.
* *

View file

@ -71,7 +71,6 @@
****************************************************************************/ ****************************************************************************/
#[doc(hidden)]; // FIXME #3538 #[doc(hidden)]; // FIXME #3538
#[warn(deprecated_mode)];
use cast; use cast;
use container::Map; use container::Map;

View file

@ -14,16 +14,12 @@ The `ToBytes` and `IterBytes` traits
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use io; use io;
use io::Writer; use io::Writer;
use option::{None, Option, Some}; use option::{None, Option, Some};
use str; 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; * A trait to implement in order to make a type hashable;

View file

@ -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 kinds::Copy;
use str; use str;
use vec; use vec;

View file

@ -8,10 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Operations on tuples //! Operations on tuples
use cmp::{Eq, Ord}; use cmp::{Eq, Ord};

View file

@ -9,9 +9,6 @@
// except according to those terms. // except according to those terms.
#[doc(hidden)]; // FIXME #3538 #[doc(hidden)]; // FIXME #3538
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
pub mod general_category { pub mod general_category {
pub pure fn Cc(c: char) -> bool { pub pure fn Cc(c: char) -> bool {

View file

@ -14,10 +14,6 @@ Miscellaneous helpers for common patterns.
*/ */
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq; use cmp::Eq;
use prelude::*; use prelude::*;

View file

@ -10,8 +10,6 @@
//! Vectors //! Vectors
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
#[warn(non_camel_case_types)]; #[warn(non_camel_case_types)];
use container::{Container, Mutable}; use container::{Container, Mutable};
@ -841,14 +839,37 @@ pub pure fn map2<T: Copy, U: Copy, V>(v0: &[T], v1: &[U],
u u
} }
/** pub fn filter_map<T, U>(
* Apply a function to each element of a vector and return the results v: ~[T],
* f: fn(t: T) -> Option<U>) -> ~[U]
* 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>) * Apply a function to each element of a vector and return the results.
-> ~[U] { * 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 = ~[]; let mut result = ~[];
for each(v) |elem| { for each(v) |elem| {
match f(elem) { match f(elem) {
@ -1695,7 +1716,7 @@ pub trait ImmutableVector<T> {
fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U]; fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
pure fn alli(&self, f: fn(uint, t: &T) -> bool) -> bool; 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 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 /// Extension methods for vectors
@ -1758,8 +1779,8 @@ impl<T> &[T]: ImmutableVector<T> {
* the resulting vector. * the resulting vector.
*/ */
#[inline] #[inline]
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] {
filter_map(*self, f) filter_mapped(*self, f)
} }
} }
@ -2439,10 +2460,14 @@ mod tests {
pure fn is_equal(x: &uint, y:&uint) -> bool { return *x == *y; } 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 }; 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; } fn add(x: uint, y: &uint) -> uint { return x + *y; }
#[test] #[test]
@ -2775,17 +2800,17 @@ mod tests {
} }
#[test] #[test]
fn test_filter_map() { fn test_filter_mapped() {
// Test on-stack filter-map. // Test on-stack filter-map.
let mut v = ~[1u, 2u, 3u]; 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 (len(w) == 2u);
assert (w[0] == 1u); assert (w[0] == 1u);
assert (w[1] == 9u); assert (w[1] == 9u);
// Test on-heap filter-map. // Test on-heap filter-map.
v = ~[1u, 2u, 3u, 4u, 5u]; 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 (len(w) == 3u);
assert (w[0] == 1u); assert (w[0] == 1u);
assert (w[1] == 9u); assert (w[1] == 9u);
@ -2804,7 +2829,46 @@ mod tests {
let all_odd2: ~[int] = ~[]; let all_odd2: ~[int] = ~[];
let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3]; let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
let mix_dest: ~[int] = ~[1, 3, 0, 0]; 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_odd1, halve) == ~[]);
assert (filter_map(all_odd2, halve) == ~[]); assert (filter_map(all_odd2, halve) == ~[]);
assert (filter_map(mix, halve) == mix_dest); assert (filter_map(mix, halve) == mix_dest);
@ -3664,10 +3728,10 @@ mod tests {
#[ignore(windows)] #[ignore(windows)]
#[should_fail] #[should_fail]
#[allow(non_implicitly_copyable_typarams)] #[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 v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
let mut i = 0; let mut i = 0;
do filter_map(v) |_elt| { do filter_mapped(v) |_elt| {
if i == 2 { if i == 2 {
die!() die!()
} }

View file

@ -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 { 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_items =
let filtered_view_items = vec::filter_map(m.view_items, m.items.filter_mapped(|a| filter_item(cx, *a));
|a| filter_view_item(cx, *a)); let filtered_view_items =
m.view_items.filter_mapped(|a| filter_view_item(cx, *a));
ast::_mod { ast::_mod {
view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)), 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, nm: ast::foreign_mod,
fld: fold::ast_fold fld: fold::ast_fold
) -> ast::foreign_mod { ) -> ast::foreign_mod {
let filtered_items = vec::filter_map(nm.items, let filtered_items =
|a| filter_foreign_item(cx, *a)); nm.items.filter_mapped(|a| filter_foreign_item(cx, *a));
let filtered_view_items = vec::filter_map(nm.view_items, let filtered_view_items =
|a| filter_view_item(cx, *a)); nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
ast::foreign_mod { ast::foreign_mod {
sort: nm.sort, sort: nm.sort,
abi: nm.abi, abi: nm.abi,
@ -136,7 +137,8 @@ fn fold_block(
b: ast::blk_, b: ast::blk_,
fld: fold::ast_fold fld: fold::ast_fold
) -> ast::blk_ { ) -> 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_ { ast::blk_ {
view_items: /*bad*/copy b.view_items, view_items: /*bad*/copy b.view_items,
stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)), 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, // Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes,
// so we can match against them. This is the list of configurations for // so we can match against them. This is the list of configurations for
// which the item is valid // which the item is valid
let cfg_metas = vec::concat(vec::filter_map(cfg_metas, let cfg_metas =
|i| attr::get_meta_item_list(*i))); vec::concat(
vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i)));
let has_cfg_metas = vec::len(cfg_metas) > 0u; let has_cfg_metas = vec::len(cfg_metas) > 0u;
if !has_cfg_metas { return true; } if !has_cfg_metas { return true; }

View file

@ -168,9 +168,11 @@ fn is_test_fn(i: @ast::item) -> bool {
fn is_ignored(cx: test_ctxt, 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 ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
let ignoreitems = attr::attr_metas(ignoreattrs); 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() { 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) config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
} else { } else {
false false
@ -277,7 +279,7 @@ fn mk_std(cx: test_ctxt) -> @ast::view_item {
} }
fn mk_tests(cx: test_ctxt) -> @ast::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 { let decl = ast::fn_decl {
inputs: ~[], inputs: ~[],
@ -286,7 +288,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
}; };
// The vector of test_descs for this crate // 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_ = let body_: ast::blk_ =
default_block(~[], option::Some(test_descs), cx.sess.next_node_id()); 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] // The ast::Ty of ~[std::test::TestDescAndFn]
fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty { fn mk_test_desc_and_fn_vec_ty(cx: test_ctxt) -> @ast::Ty {
let test_desc_ty_path = let test_desc_and_fn_ty_path =
mk_path(cx, ~[cx.sess.ident_of(~"test"), 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(), 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(), 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 { let inner_ty = @ast::Ty {
id: cx.sess.next_node_id(), 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()); debug!("building test vector from %u tests", cx.testfns.len());
let mut descs = ~[]; let mut descs = ~[];
for cx.testfns.each |test| { 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 { 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 span = test.span;
let path = /*bad*/copy test.path; 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, 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_lit: ast::lit = nospan(ast::lit_bool(test.ignore));
let ignore_expr = ast::expr { 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( let desc_rec_ = ast::expr_struct(
test_desc_path, test_desc_path,
~[name_field, fn_field, ignore_field, fail_field], ~[name_field, ignore_field, fail_field],
option::None option::None
); );
let desc_rec = ast::expr { let desc_rec = @ast::expr {
id: cx.sess.next_node_id(), id: cx.sess.next_node_id(),
callee_id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
node: desc_rec_, node: desc_rec_,
span: span, 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. let fn_expr = @ast::expr {
fn mk_test_wrapper(cx: test_ctxt,
+fn_path_expr: ast::expr,
span: span) -> @ast::expr {
let call_expr = ast::expr {
id: cx.sess.next_node_id(), id: cx.sess.next_node_id(),
callee_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, span: span,
}; };
let call_stmt: ast::stmt = nospan( let fn_field = nospan(ast::field_ {
ast::stmt_semi(@call_expr, cx.sess.next_node_id())); mutbl: ast::m_imm,
ident: cx.sess.ident_of(~"testfn"),
let wrapper_decl = ast::fn_decl { expr: fn_expr,
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 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(), id: cx.sess.next_node_id(),
callee_id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @()), node: ast::expr_struct(test_desc_and_fn_path,
span: span ~[fn_field, desc_field],
option::None),
span: span,
}; };
return @wrapper_expr; return desc_and_fn_rec;
} }
fn mk_main(cx: test_ctxt) -> @ast::item { 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 { let args_call_expr = ast::expr {
id: cx.sess.next_node_id(), id: cx.sess.next_node_id(),
callee_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(), span: dummy_sp(),
}; };
@ -584,7 +561,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
let test_call_expr = ast::expr { let test_call_expr = ast::expr {
id: cx.sess.next_node_id(), id: cx.sess.next_node_id(),
callee_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(), span: dummy_sp(),
}; };
@ -606,7 +583,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
node: ast::expr_call( node: ast::expr_call(
@test_main_path_expr, @test_main_path_expr,
~[@args_call_expr, @test_call_expr], ~[@args_call_expr, @test_call_expr],
false ast::NoSugar
), ),
span: dummy_sp(), span: dummy_sp(),
}; };

View file

@ -586,10 +586,8 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
item, tcx, cdata); item, tcx, cdata);
let name = item_name(intr, item); let name = item_name(intr, item);
let arg_tys = match ty::get(ctor_ty).sty { let arg_tys = match ty::get(ctor_ty).sty {
ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty), ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty),
_ => ~[], // Nullary enum variant.
// Nullary enum variant.
_ => ~[],
}; };
match variant_disr_val(item) { match variant_disr_val(item) {
Some(val) => { disr_val = val; } 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 ty = doc_type(mth, tcx, cdata);
let def_id = item_def_id(mth, cdata); let def_id = item_def_id(mth, cdata);
let fty = match ty::get(ty).sty { let fty = match ty::get(ty).sty {
ty::ty_fn(ref f) => (/*bad*/copy *f), ty::ty_bare_fn(ref f) => copy *f,
_ => { _ => {
tcx.diag.handler().bug( tcx.diag.handler().bug(
~"get_trait_methods: id has non-function type"); ~"get_trait_methods: id has non-function type");
} }; }
};
let self_ty = get_self_ty(mth); let self_ty = get_self_ty(mth);
result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty, result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
vis: ast::public, def_id: def_id}); 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 name = item_name(intr, mth);
let ty = doc_type(mth, tcx, cdata); let ty = doc_type(mth, tcx, cdata);
let fty; let fty = match ty::get(ty).sty {
match ty::get(ty).sty { ty::ty_bare_fn(ref f) => copy *f,
ty::ty_fn(ref f) => fty = (/*bad*/copy *f),
_ => { _ => {
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
has non-function type"); has non-function type");
} }
} };
let self_ty = get_self_ty(mth); let self_ty = get_self_ty(mth);
let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty, let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,

View file

@ -768,8 +768,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
encode_name(ecx, ebml_w, mty.ident); encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx, encode_type_param_bounds(ebml_w, ecx,
(*ty_m).tps); (*ty_m).tps);
encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty)); encode_type(ecx, ebml_w,
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); 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_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'r'); encode_method_sort(ebml_w, 'r');
ebml_w.end_tag(); 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_def_id(ebml_w, local_def(m.id));
encode_name(ecx, ebml_w, mty.ident); encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx, m.tps); encode_type_param_bounds(ebml_w, ecx, m.tps);
encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty)); encode_type(ecx, ebml_w,
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); 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_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'p'); encode_method_sort(ebml_w, 'p');
ebml_w.end_tag(); ebml_w.end_tag();

View file

@ -17,8 +17,6 @@
use core::prelude::*; use core::prelude::*;
use middle::ty; use middle::ty;
use middle::ty::{FnTyBase, FnMeta, FnSig, arg, creader_cache_key, field};
use middle::ty::{substs};
use core::io; use core::io;
use core::str; 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 { fn parse_sigil(st: @pstate) -> ast::Sigil {
return ty::mk_fn(st.tcx, parse_ty_fn(st, conv));
}
fn parse_proto(st: @pstate) -> ast::Proto {
match next(st) { match next(st) {
'_' => ast::ProtoBare, '@' => ast::ManagedSigil,
'@' => ast::ProtoBox, '~' => ast::OwnedSigil,
'~' => ast::ProtoUniq, '&' => ast::BorrowedSigil,
'&' => ast::ProtoBorrowed, c => st.tcx.sess.bug(fmt!("parse_sigil(): bad input '%c'", c))
_ => die!(~"parse_proto(): bad input")
} }
} }
@ -152,7 +145,7 @@ fn parse_vstore(st: @pstate) -> ty::vstore {
'~' => ty::vstore_uniq, '~' => ty::vstore_uniq,
'@' => ty::vstore_box, '@' => ty::vstore_box,
'&' => ty::vstore_slice(parse_region(st)), '&' => 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)); } while peek(st) != ']' { params.push(parse_ty(st, conv)); }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
return substs { return ty::substs {
self_r: self_r, self_r: self_r,
self_ty: self_ty, self_ty: self_ty,
tps: params tps: params
@ -316,19 +309,24 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
return ty::mk_tup(st.tcx, params); return ty::mk_tup(st.tcx, params);
} }
'f' => { '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), 'Y' => return ty::mk_type(st.tcx),
'C' => { 'C' => {
let proto = parse_proto(st); let sigil = parse_sigil(st);
return ty::mk_opaque_closure_ptr(st.tcx, proto); return ty::mk_opaque_closure_ptr(st.tcx, sigil);
} }
'#' => { '#' => {
let pos = parse_hex(st); let pos = parse_hex(st);
assert (next(st) == ':'); assert (next(st) == ':');
let len = parse_hex(st); let len = parse_hex(st);
assert (next(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) { match st.tcx.rcache.find(&key) {
Some(tt) => return tt, Some(tt) => return tt,
None => { 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 { fn parse_onceness(c: char) -> ast::Onceness {
match c { match c {
'o' => ast::Once, 'o' => ast::Once,
@ -430,12 +435,33 @@ fn parse_mode(st: @pstate) -> ast::mode {
return m; return m;
} }
fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { fn parse_closure_ty(st: @pstate, conv: conv_did) -> ty::ClosureTy {
let proto = parse_proto(st); let sigil = parse_sigil(st);
let purity = parse_purity(next(st)); let purity = parse_purity(next(st));
let onceness = parse_onceness(next(st)); let onceness = parse_onceness(next(st));
let region = parse_region(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) == '['); assert (next(st) == '[');
let mut inputs: ~[ty::arg] = ~[]; let mut inputs: ~[ty::arg] = ~[];
while peek(st) != ']' { while peek(st) != ']' {
@ -444,18 +470,9 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
} }
st.pos += 1u; // eat the ']' st.pos += 1u; // eat the ']'
let ret_ty = parse_ty(st, conv); let ret_ty = parse_ty(st, conv);
return FnTyBase { ty::FnSig {inputs: inputs, output: ret_ty}
meta: FnMeta {purity: purity,
proto: proto,
onceness: onceness,
bounds: bounds,
region: region},
sig: FnSig {inputs: inputs,
output: ret_ty}
};
} }
// Rust metadata parsing // Rust metadata parsing
pub fn parse_def_id(buf: &[u8]) -> ast::def_id { pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
let mut colon_idx = 0u; let mut colon_idx = 0u;

View file

@ -288,8 +288,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
} }
w.write_char(']'); w.write_char(']');
} }
ty::ty_fn(ref f) => { ty::ty_closure(ref f) => {
enc_ty_fn(w, cx, (*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(_) => { ty::ty_infer(_) => {
cx.diag.handler().bug(~"Cannot encode inference variable types"); 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_type => w.write_char('Y'),
ty::ty_opaque_closure_ptr(p) => { ty::ty_opaque_closure_ptr(p) => {
w.write_str(&"C&"); w.write_str(&"C&");
enc_proto(w, p); enc_sigil(w, p);
} }
ty::ty_opaque_box => w.write_char('B'), ty::ty_opaque_box => w.write_char('B'),
ty::ty_struct(def, ref substs) => { 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) { fn enc_sigil(w: io::Writer, sigil: Sigil) {
w.write_str(&"f"); match sigil {
match proto { ManagedSigil => w.write_str("@"),
ProtoBare => w.write_str(&"_"), OwnedSigil => w.write_str("~"),
ProtoBox => w.write_str(&"@"), BorrowedSigil => w.write_str("&"),
ProtoUniq => w.write_str(&"~"),
ProtoBorrowed => 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) { fn enc_onceness(w: io::Writer, o: Onceness) {
match o { match o {
Once => w.write_char('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) { fn enc_bare_fn_ty(w: io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
enc_proto(w, ft.meta.proto); enc_purity(w, ft.purity);
enc_purity(w, ft.meta.purity); enc_abi(w, ft.abi);
enc_onceness(w, ft.meta.onceness); enc_fn_sig(w, cx, &ft.sig);
enc_region(w, cx, ft.meta.region); }
enc_bounds(w, cx, ft.meta.bounds);
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('['); w.write_char('[');
for ft.sig.inputs.each |arg| { for fsig.inputs.each |arg| {
enc_arg(w, cx, *arg); enc_arg(w, cx, *arg);
} }
w.write_char(']'); 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]) { pub fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {

View file

@ -221,18 +221,19 @@ impl check_loan_ctxt {
let callee_ty = ty::node_id_to_type(tcx, callee_id); let callee_ty = ty::node_id_to_type(tcx, callee_id);
match ty::get(callee_ty).sty { match ty::get(callee_ty).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_bare_fn(ty::BareFnTy {purity: purity, _}) |
match fn_ty.meta.purity { ty::ty_closure(ty::ClosureTy {purity: purity, _}) => {
ast::pure_fn => return, // case (c) above match purity {
ast::impure_fn | ast::unsafe_fn | ast::extern_fn => { ast::pure_fn => return, // case (c) above
self.report_purity_error( ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
pc, callee_span, self.report_purity_error(
fmt!("access to %s function", pc, callee_span,
fn_ty.meta.purity.to_str())); 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(*) // The expression must be an expr_fn(*) or expr_fn_block(*)
fn is_stack_closure(id: ast::node_id) -> bool { fn is_stack_closure(id: ast::node_id) -> bool {
let fn_ty = ty::node_id_to_type(self.tcx(), id); let fn_ty = ty::node_id_to_type(self.tcx(), id);
let proto = ty::ty_fn_proto(fn_ty); match ty::get(fn_ty).sty {
return proto == ast::ProtoBorrowed; ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
_}) => true,
_ => false
}
} }
fn is_allowed_pure_arg(expr: @ast::expr) -> bool { 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 is_stack_closure = self.is_stack_closure(id);
let fty = ty::node_id_to_type(self.tcx(), 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); debug!("purity on entry=%?", copy self.declared_purity);
do save_and_restore(&mut(self.declared_purity)) { do save_and_restore(&mut(self.declared_purity)) {
do save_and_restore(&mut(self.fn_args)) { do save_and_restore(&mut(self.fn_args)) {
self.declared_purity = ty::determine_inherited_purity( self.declared_purity = declared_purity;
copy self.declared_purity,
ty::ty_fn_purity(fty),
fty_proto);
match fk { match fk {
visit::fk_anon(*) | 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, fn check_moves_from_captured_variables(&&self: check_loan_ctxt,
id: ast::node_id, id: ast::node_id,
fty_proto: ast::Proto) fty_sigil: ast::Sigil)
{ {
match fty_proto { match fty_sigil {
ast::ProtoBox | ast::ProtoUniq => { ast::ManagedSigil | ast::OwnedSigil => {
let cap_vars = self.bccx.capture_map.get(&id); let cap_vars = self.bccx.capture_map.get(&id);
for cap_vars.each |cap_var| { for cap_vars.each |cap_var| {
match cap_var.mode { 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 => {}
} }
} }
} }

View file

@ -150,7 +150,7 @@ pub fn check_expr(sess: Session,
} }
} }
} }
expr_call(callee, _, false) => { expr_call(callee, _, NoSugar) => {
match def_map.find(&callee.id) { match def_map.find(&callee.id) {
Some(def_struct(*)) => {} // OK. Some(def_struct(*)) => {} // OK.
Some(def_variant(*)) => {} // OK. Some(def_variant(*)) => {} // OK.

View file

@ -39,8 +39,8 @@ pub fn check_crate(tcx: ty::ctxt, crate: @crate) {
(v.visit_block)((*b), {in_loop: false, can_ret: false}, v); (v.visit_block)((*b), {in_loop: false, can_ret: false}, v);
} }
expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => { expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => {
let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e)); let sigil = ty::ty_closure_sigil(ty::expr_ty(tcx, e));
let blk = (proto == ProtoBorrowed); let blk = (sigil == BorrowedSigil);
(v.visit_block)((*b), {in_loop: true, can_ret: blk}, v); (v.visit_block)((*b), {in_loop: true, can_ret: blk}, v);
} }
expr_break(_) => { expr_break(_) => {

View file

@ -100,7 +100,7 @@ pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) {
} }
_ => { /* We assume only enum types can be uninhabited */ } _ => { /* 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); check_exhaustive(cx, ex.span, arms);
} }
_ => () _ => ()
@ -255,7 +255,8 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful {
} }
} }
Some(ref ctor) => { 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)) { vec::tail(v)) {
useful_ => useful(left_ty, (/*bad*/copy *ctor)), useful_ => useful(left_ty, (/*bad*/copy *ctor)),
ref u => (/*bad*/copy *u) ref u => (/*bad*/copy *u)
@ -277,8 +278,7 @@ pub fn is_useful_specialized(cx: @MatchCheckCtxt,
arity: uint, arity: uint,
lty: ty::t) lty: ty::t)
-> useful { -> useful {
let ms = vec::filter_map(m, |r| specialize(cx, *r, let ms = m.filter_mapped(|r| specialize(cx, *r, ctor, arity, lty));
ctor, arity, lty));
let could_be_useful = is_useful( let could_be_useful = is_useful(
cx, ms, specialize(cx, v, ctor, arity, lty).get()); cx, ms, specialize(cx, v, ctor, arity, lty).get());
match could_be_useful { match could_be_useful {
@ -387,9 +387,9 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => { ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
// Find the lengths and tails of all vector patterns. // Find the lengths and tails of all vector patterns.
let vec_pat_lens = do m.filter_map |r| { let vec_pat_lens = do m.filter_mapped |r| {
match /*bad*/copy r[0].node { match r[0].node {
pat_vec(elems, tail) => { pat_vec(ref elems, ref tail) => {
Some((elems.len(), tail.is_some())) Some((elems.len(), tail.is_some()))
} }
_ => None _ => None

View file

@ -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>) { let walk_expr = fn@(expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
match expr.node { match expr.node {
ast::expr_fn(proto, _, _, _) => { ast::expr_fn(_, _, _, _) => {
if proto != ast::ProtoBare { visit::visit_expr(expr, depth + 1, v);
visit::visit_expr(expr, depth + 1, v);
}
} }
ast::expr_fn_block(*) => { ast::expr_fn_block(*) => {
visit::visit_expr(expr, depth + 1, v); visit::visit_expr(expr, depth + 1, v);

View file

@ -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); let fty = ty::node_id_to_type(cx.tcx, id);
match ty::ty_fn_proto(fty) { match ty::get(fty).sty {
ProtoUniq => b(check_for_uniq), ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, _}) => {
ProtoBox => b(check_for_box), b(check_for_uniq)
ProtoBare => b(check_for_bare), }
ProtoBorrowed => b(check_for_block), 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, expr.span,
"explicit copy requires a copyable argument"); "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, _) => { expr_repeat(element, count_expr, _) => {
let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span); let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span);
if count > 1 { if count > 1 {

View file

@ -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, fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
span: span, id: ast::node_id) { span: span, id: ast::node_id) {
match ty::get(fn_ty).sty { 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; 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; counter += 1;
debug!("arg %d, ty=%s, mode=%s", debug!("arg %d, ty=%s, mode=%s",
counter, 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 { match ty::get(arg_ty.ty).sty {
ty::ty_fn(*) => { ty::ty_closure(*) | ty::ty_bare_fn(*) => {
let span = arg_ast.ty.span; let span = arg_ast.ty.span;
// Recurse to check fn-type argument // Recurse to check fn-type argument
match arg_ast.ty.node { 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, check_fn_deprecated_modes(tcx, arg_ty.ty,
f.decl, span, id); *d, span, id);
} }
ast::ty_path(*) => { ast::ty_path(*) => {
// This is probably a typedef, so we can't // 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 { match it.node {
ast::item_ty(ty, _) => { ast::item_ty(ty, _) => {
match ty.node { 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); let fn_ty = ty::node_id_to_type(tcx, it.id);
check_fn_deprecated_modes( check_fn_deprecated_modes(
tcx, fn_ty, f.decl, ty.span, it.id) tcx, fn_ty, *decl, ty.span, it.id)
} }
_ => () _ => ()
} }

View file

@ -146,63 +146,55 @@ pub enum deref_kind {deref_ptr(ptr_kind), deref_comp(comp_kind)}
// pointer adjustment). // pointer adjustment).
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> { pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
match ty::get(t).sty { match ty::get(t).sty {
ty::ty_uniq(*) | ty::ty_uniq(*) |
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) |
ty::ty_estr(ty::vstore_uniq) => { ty::ty_estr(ty::vstore_uniq) |
Some(deref_ptr(uniq_ptr)) ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
} Some(deref_ptr(uniq_ptr))
}
ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoUniq => { ty::ty_rptr(r, mt) |
Some(deref_ptr(uniq_ptr)) ty::ty_evec(mt, ty::vstore_slice(r)) => {
} Some(deref_ptr(region_ptr(mt.mutbl, r)))
}
ty::ty_rptr(r, mt) | ty::ty_estr(ty::vstore_slice(r)) |
ty::ty_evec(mt, ty::vstore_slice(r)) => { ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
Some(deref_ptr(region_ptr(mt.mutbl, r))) region: r, _}) => {
} Some(deref_ptr(region_ptr(ast::m_imm, r)))
}
ty::ty_estr(ty::vstore_slice(r)) => { ty::ty_box(mt) |
Some(deref_ptr(region_ptr(ast::m_imm, r))) 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 => { ty::ty_estr(ty::vstore_box) |
Some(deref_ptr(region_ptr(ast::m_imm, (*f).meta.region))) ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
} Some(deref_ptr(gc_ptr(ast::m_imm)))
}
ty::ty_box(mt) | ty::ty_ptr(*) => {
ty::ty_evec(mt, ty::vstore_box) => { Some(deref_ptr(unsafe_ptr))
Some(deref_ptr(gc_ptr(mt.mutbl))) }
}
ty::ty_estr(ty::vstore_box) => { ty::ty_enum(did, _) => {
Some(deref_ptr(gc_ptr(ast::m_imm))) Some(deref_comp(comp_variant(did)))
} }
ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBox => { ty::ty_struct(_, _) => {
Some(deref_ptr(gc_ptr(ast::m_imm))) Some(deref_comp(comp_anon_field))
} }
ty::ty_ptr(*) => { ty::ty_evec(mt, ty::vstore_fixed(_)) => {
Some(deref_ptr(unsafe_ptr)) Some(deref_comp(comp_index(t, mt.mutbl)))
} }
ty::ty_enum(did, _) => { ty::ty_estr(ty::vstore_fixed(_)) => {
Some(deref_comp(comp_variant(did))) Some(deref_comp(comp_index(t, m_imm)))
} }
ty::ty_struct(_, _) => { _ => None
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
} }
} }
@ -473,9 +465,9 @@ pub impl &mem_categorization_ctxt {
ast::def_upvar(_, inner, fn_node_id, _) => { ast::def_upvar(_, inner, fn_node_id, _) => {
let ty = ty::node_id_to_type(self.tcx, fn_node_id); let ty = ty::node_id_to_type(self.tcx, fn_node_id);
let proto = ty::ty_fn_proto(ty); let sigil = ty::ty_closure_sigil(ty);
match proto { match sigil {
ast::ProtoBorrowed => { ast::BorrowedSigil => {
let upcmt = self.cat_def(id, span, expr_ty, *inner); let upcmt = self.cat_def(id, span, expr_ty, *inner);
@cmt_ { @cmt_ {
id:id, id:id,
@ -486,7 +478,7 @@ pub impl &mem_categorization_ctxt {
ty:upcmt.ty ty:upcmt.ty
} }
} }
ast::ProtoUniq | ast::ProtoBox => { ast::OwnedSigil | ast::ManagedSigil => {
// FIXME #2152 allow mutation of moved upvars // FIXME #2152 allow mutation of moved upvars
@cmt_ { @cmt_ {
id:id, id:id,
@ -497,11 +489,6 @@ pub impl &mem_categorization_ctxt {
ty:expr_ty ty:expr_ty
} }
} }
ast::ProtoBare => {
self.tcx.sess.span_bug(
span,
fmt!("Upvar in a bare closure?"));
}
} }
} }

View file

@ -474,7 +474,35 @@ impl VisitContext {
} }
for opt_with.each |with_expr| { 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 _indenter = indenter();
let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id); 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); let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
if proto == ProtoBorrowed { if sigil == BorrowedSigil {
// &fn() captures everything by ref // &fn() captures everything by ref
at_vec::from_fn(freevars.len(), |i| { at_vec::from_fn(freevars.len(), |i| {
let fvar = &freevars[i]; let fvar = &freevars[i];

View file

@ -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", debug!("referenced fn type: %s",
pprust::ty_to_str(ty, cx.sess.intr())); pprust::ty_to_str(ty, cx.sess.intr()));
match f.region { match f.region {
@ -668,7 +668,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
} }
} }
None => { 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_rp(cx.item_id,
cx.add_variance(rv_contravariant)); 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 // fn() binds the & region, so do not consider &T types that
// appear *inside* a fn() type to affect the enclosing item: // appear *inside* a fn() type to affect the enclosing item:
do cx.with(cx.item_id, false) { do cx.with(cx.item_id, false) {
// parameters are contravariant // parameters are contravariant
do cx.with_ambient_variance(rv_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); (visitor.visit_ty)(a.ty, cx, visitor);
} }
} }
visit::visit_ty_param_bounds(f.bounds, cx, visitor); (visitor.visit_ty)(decl.output, cx, visitor);
(visitor.visit_ty)(f.decl.output, cx, visitor);
} }
} }

View file

@ -1652,7 +1652,7 @@ pub fn trans_match_inner(scope_cx: block,
// insert bindings into the lllocals map and add cleanups // insert bindings into the lllocals map and add cleanups
bcx = insert_lllocals(bcx, *arm_data, true); 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)); bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
arm_cxs.push(bcx); arm_cxs.push(bcx);
} }

View file

@ -613,7 +613,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
let ccx = cx.ccx(); let ccx = cx.ccx();
let mut cx = cx; let mut cx = cx;
match ty::get(fn_ty).sty { match ty::get(fn_ty).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
let mut j = 0u; let mut j = 0u;
let v_id = variant.id; let v_id = variant.id;
for vec::each(fn_ty.sig.inputs) |a| { 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 { -> ValueRef {
let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad
match ty::get(t).sty { match ty::get(t).sty {
ty::ty_fn(_) => { ty::ty_bare_fn(_) | ty::ty_closure(_) => {
let llty = type_of_fn_from_ty(ccx, t); let llty = type_of_fn_from_ty(ccx, t);
return get_extern_fn(ccx.externs, ccx.llmod, name, return get_extern_fn(ccx.externs, ccx.llmod, name,
lib::llvm::CCallConv, llty); lib::llvm::CCallConv, llty);
} }
_ => { _ => {
let llty = type_of(ccx, t); 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} 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| { for vec::each(b.node.stmts) |s| {
match s.node { match s.node {
ast::stmt_decl(d, _) => { ast::stmt_decl(d, _) => {
@ -1727,8 +1727,8 @@ pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, }
// returned. // returned.
pub fn trans_closure(ccx: @crate_ctxt, pub fn trans_closure(ccx: @crate_ctxt,
+path: path, +path: path,
decl: ast::fn_decl, decl: &ast::fn_decl,
body: ast::blk, body: &ast::blk,
llfndecl: ValueRef, llfndecl: ValueRef,
ty_self: self_arg, ty_self: self_arg,
+param_substs: Option<param_substs>, +param_substs: Option<param_substs>,
@ -1791,8 +1791,8 @@ pub fn trans_closure(ccx: @crate_ctxt,
// function. // function.
pub fn trans_fn(ccx: @crate_ctxt, pub fn trans_fn(ccx: @crate_ctxt,
+path: path, +path: path,
decl: ast::fn_decl, decl: &ast::fn_decl,
body: ast::blk, body: &ast::blk,
llfndecl: ValueRef, llfndecl: ValueRef,
ty_self: self_arg, ty_self: self_arg,
+param_substs: Option<param_substs>, +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, pub fn trans_struct_dtor(ccx: @crate_ctxt,
+path: path, +path: path,
body: ast::blk, body: &ast::blk,
dtor_id: ast::node_id, dtor_id: ast::node_id,
+psubsts: Option<param_substs>, +psubsts: Option<param_substs>,
hash_id: Option<mono_id>, hash_id: Option<mono_id>,
@ -1966,8 +1966,9 @@ pub fn trans_struct_dtor(ccx: @crate_ctxt,
ccx.monomorphized.insert(*h_id, lldecl); ccx.monomorphized.insert(*h_id, lldecl);
} }
/* Translate the dtor body */ /* Translate the dtor body */
trans_fn(ccx, path, ast_util::dtor_dec(), let decl = ast_util::dtor_dec();
body, lldecl, impl_self(class_ty), psubsts, dtor_id, None); trans_fn(ccx, path, &decl, body, lldecl,
impl_self(class_ty), psubsts, dtor_id, None);
lldecl lldecl
} }
@ -2013,20 +2014,19 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) {
_ => die!(~"trans_item"), _ => die!(~"trans_item"),
}; };
match /*bad*/copy item.node { match /*bad*/copy item.node {
// XXX: Bad copies. ast::item_fn(ref decl, purity, ref tps, ref body) => {
ast::item_fn(copy decl, purity, copy tps, ref body) => {
if purity == ast::extern_fn { if purity == ast::extern_fn {
let llfndecl = get_item_val(ccx, item.id); let llfndecl = get_item_val(ccx, item.id);
foreign::trans_foreign_fn(ccx, foreign::trans_foreign_fn(ccx,
vec::append( vec::append(
/*bad*/copy *path, /*bad*/copy *path,
~[path_name(item.ident)]), ~[path_name(item.ident)]),
decl, (*body), llfndecl, item.id); decl, body, llfndecl, item.id);
} else if tps.is_empty() { } else if tps.is_empty() {
let llfndecl = get_item_val(ccx, item.id); let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx, trans_fn(ccx,
vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), 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 { } else {
for vec::each((*body).node.stmts) |stmt| { for vec::each((*body).node.stmts) |stmt| {
match stmt.node { match stmt.node {
@ -2078,7 +2078,7 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
id: ast::node_id) { id: ast::node_id) {
// Translate the destructor. // Translate the destructor.
do option::iter(&struct_def.dtor) |dtor| { 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)); dtor.node.id, None, None, local_def(id));
}; };

View file

@ -627,18 +627,17 @@ pub fn trans_arg_expr(bcx: block,
Some(_) => { Some(_) => {
match arg_expr.node { match arg_expr.node {
ast::expr_loop_body( ast::expr_loop_body(
// XXX: Bad copy. blk @ @ast::expr {
blk@@ast::expr { node: ast::expr_fn_block(ref decl, ref body),
node: ast::expr_fn_block(copy decl, ref body),
_ _
}) => }) =>
{ {
let scratch_ty = expr_ty(bcx, arg_expr); let scratch_ty = expr_ty(bcx, arg_expr);
let scratch = alloc_ty(bcx, scratch_ty); let scratch = alloc_ty(bcx, scratch_ty);
let arg_ty = expr_ty(bcx, arg_expr); 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( 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)); blk.id, Some(ret_flag), expr::SaveIn(scratch));
DatumBlock {bcx: bcx, DatumBlock {bcx: bcx,
datum: Datum {val: scratch, datum: Datum {val: scratch,

View file

@ -160,7 +160,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
return cdata_ty; 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 { -> Result {
let _icx = bcx.insn_ctxt("closure::allocate_cbox"); let _icx = bcx.insn_ctxt("closure::allocate_cbox");
let ccx = bcx.ccx(), tcx = ccx.tcx; 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: // Allocate and initialize the box:
match proto { match sigil {
ast::ProtoBox => { ast::ManagedSigil => {
malloc_raw(bcx, cdata_ty, heap_shared) malloc_raw(bcx, cdata_ty, heap_shared)
} }
ast::ProtoUniq => { ast::OwnedSigil => {
malloc_raw(bcx, cdata_ty, heap_exchange) malloc_raw(bcx, cdata_ty, heap_exchange)
} }
ast::ProtoBorrowed => { ast::BorrowedSigil => {
let cbox_ty = tuplify_box_ty(tcx, cdata_ty); let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
let llbox = base::alloc_ty(bcx, cbox_ty); let llbox = base::alloc_ty(bcx, cbox_ty);
nuke_ref_count(bcx, llbox); nuke_ref_count(bcx, llbox);
rslt(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. // Otherwise, it is stack allocated and copies pointers to the upvars.
pub fn store_environment(bcx: block, pub fn store_environment(bcx: block,
bound_values: ~[EnvValue], bound_values: ~[EnvValue],
proto: ast::Proto) -> closure_result { sigil: ast::Sigil) -> closure_result {
let _icx = bcx.insn_ctxt("closure::store_environment"); let _icx = bcx.insn_ctxt("closure::store_environment");
let ccx = bcx.ccx(), tcx = ccx.tcx; 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); let cdata_ty = mk_closure_tys(tcx, copy bound_values);
// allocate closure in the heap // 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 = ~[]; let mut temp_cleanups = ~[];
// cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a // 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. // collects the upvars and packages them up for store_environment.
pub fn build_closure(bcx0: block, pub fn build_closure(bcx0: block,
cap_vars: &[moves::CaptureVar], cap_vars: &[moves::CaptureVar],
proto: ast::Proto, sigil: ast::Sigil,
include_ret_handle: Option<ValueRef>) -> closure_result { include_ret_handle: Option<ValueRef>) -> closure_result {
let _icx = bcx0.insn_ctxt("closure::build_closure"); let _icx = bcx0.insn_ctxt("closure::build_closure");
// If we need to, package up the iterator body to call // 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); let datum = expr::trans_local_var(bcx, cap_var.def);
match cap_var.mode { match cap_var.mode {
moves::CapRef => { moves::CapRef => {
assert proto == ast::ProtoBorrowed; assert sigil == ast::BorrowedSigil;
env_vals.push(EnvValue {action: EnvRef, env_vals.push(EnvValue {action: EnvRef,
datum: datum}); datum: datum});
} }
@ -316,7 +312,7 @@ pub fn build_closure(bcx0: block,
datum: ret_datum}); 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, // 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, cdata_ty: ty::t,
cap_vars: &[moves::CaptureVar], cap_vars: &[moves::CaptureVar],
load_ret_handle: bool, load_ret_handle: bool,
proto: ast::Proto) { sigil: ast::Sigil) {
let _icx = fcx.insn_ctxt("closure::load_environment"); let _icx = fcx.insn_ctxt("closure::load_environment");
let llloadenv = match fcx.llloadenv { let llloadenv = match fcx.llloadenv {
@ -352,9 +348,9 @@ pub fn load_environment(fcx: fn_ctxt,
let mut i = 0u; let mut i = 0u;
for cap_vars.each |cap_var| { for cap_vars.each |cap_var| {
let mut upvarptr = GEPi(bcx, llcdata, [0u, i]); let mut upvarptr = GEPi(bcx, llcdata, [0u, i]);
match proto { match sigil {
ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); } ast::BorrowedSigil => { upvarptr = Load(bcx, upvarptr); }
ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {} ast::ManagedSigil | ast::OwnedSigil => {}
} }
let def_id = ast_util::def_id_of_def(cap_var.def); let def_id = ast_util::def_id_of_def(cap_var.def);
fcx.llupvars.insert(def_id.node, upvarptr); 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, pub fn trans_expr_fn(bcx: block,
proto: ast::Proto, sigil: ast::Sigil,
+decl: ast::fn_decl, decl: &ast::fn_decl,
+body: ast::blk, body: &ast::blk,
outer_id: ast::node_id, outer_id: ast::node_id,
user_id: ast::node_id, user_id: ast::node_id,
is_loop_body: Option<Option<ValueRef>>, is_loop_body: Option<Option<ValueRef>>,
@ -381,7 +377,7 @@ pub fn trans_expr_fn(bcx: block,
* *
* Translates the body of a closure expression. * Translates the body of a closure expression.
* *
* - `proto` * - `sigil`
* - `decl` * - `decl`
* - `body` * - `body`
* - `outer_id`: The id of the closure expression with the correct * - `outer_id`: The id of the closure expression with the correct
@ -417,18 +413,18 @@ pub fn trans_expr_fn(bcx: block,
~"expr_fn"); ~"expr_fn");
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
let Result {bcx: bcx, val: closure} = match proto { let Result {bcx: bcx, val: closure} = match sigil {
ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => {
let cap_vars = ccx.maps.capture_map.get(&user_id); let cap_vars = ccx.maps.capture_map.get(&user_id);
let ret_handle = match is_loop_body {Some(x) => x, let ret_handle = match is_loop_body {Some(x) => x,
None => None}; 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); ret_handle);
trans_closure(ccx, sub_path, decl, trans_closure(ccx, sub_path, decl,
body, llfn, no_self, body, llfn, no_self,
/*bad*/ copy bcx.fcx.param_substs, user_id, None, /*bad*/ copy bcx.fcx.param_substs, user_id, None,
|fcx| load_environment(fcx, cdata_ty, cap_vars, |fcx| load_environment(fcx, cdata_ty, cap_vars,
ret_handle.is_some(), proto), ret_handle.is_some(), sigil),
|bcx| { |bcx| {
if is_loop_body.is_some() { if is_loop_body.is_some() {
Store(bcx, C_bool(true), bcx.fcx.llretptr); Store(bcx, C_bool(true), bcx.fcx.llretptr);
@ -436,34 +432,30 @@ pub fn trans_expr_fn(bcx: block,
}); });
rslt(bcx, llbox) 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); fill_fn_pair(bcx, dest_addr, llfn, closure);
return bcx; return bcx;
} }
pub fn make_fn_glue(cx: block, pub fn make_closure_glue(
v: ValueRef, cx: block,
t: ty::t, v: ValueRef,
glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) t: ty::t,
-> block { glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) -> block
let _icx = cx.insn_ctxt("closure::make_fn_glue"); {
let _icx = cx.insn_ctxt("closure::make_closure_glue");
let bcx = cx; let bcx = cx;
let tcx = cx.tcx(); let tcx = cx.tcx();
let proto = ty::ty_fn_proto(t); let sigil = ty::ty_closure_sigil(t);
match proto { match sigil {
ast::ProtoBare | ast::ProtoBorrowed => bcx, ast::BorrowedSigil => bcx,
ast::ProtoUniq | ast::ProtoBox => { ast::OwnedSigil | ast::ManagedSigil => {
let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]); let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]);
let box_ptr_v = Load(cx, box_cell_v); let box_ptr_v = Load(cx, box_cell_v);
do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| { 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) 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( pub fn make_opaque_cbox_take_glue(
bcx: block, bcx: block,
proto: ast::Proto, sigil: ast::Sigil,
cboxptr: ValueRef) // ptr to ptr to the opaque closure cboxptr: ValueRef) // ptr to ptr to the opaque closure
-> block { -> block {
// Easy cases: // Easy cases:
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue"); let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue");
match proto { match sigil {
ast::ProtoBare | ast::ProtoBorrowed => { ast::BorrowedSigil => {
return bcx; return bcx;
} }
ast::ProtoBox => { ast::ManagedSigil => {
glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr));
return bcx; return bcx;
} }
ast::ProtoUniq => { ast::OwnedSigil => {
/* hard case: fallthrough to code below */ /* hard case: fallthrough to code below */
} }
} }
@ -531,36 +523,36 @@ pub fn make_opaque_cbox_take_glue(
pub fn make_opaque_cbox_drop_glue( pub fn make_opaque_cbox_drop_glue(
bcx: block, bcx: block,
proto: ast::Proto, sigil: ast::Sigil,
cboxptr: ValueRef) // ptr to the opaque closure cboxptr: ValueRef) // ptr to the opaque closure
-> block { -> block {
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue"); let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue");
match proto { match sigil {
ast::ProtoBare | ast::ProtoBorrowed => bcx, ast::BorrowedSigil => bcx,
ast::ProtoBox => { ast::ManagedSigil => {
glue::decr_refcnt_maybe_free( glue::decr_refcnt_maybe_free(
bcx, Load(bcx, cboxptr), 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( glue::free_ty(
bcx, cboxptr, 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( pub fn make_opaque_cbox_free_glue(
bcx: block, bcx: block,
proto: ast::Proto, sigil: ast::Sigil,
cbox: ValueRef) // ptr to ptr to the opaque closure cbox: ValueRef) // ptr to ptr to the opaque closure
-> block { -> block {
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue"); let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue");
match proto { match sigil {
ast::ProtoBare | ast::ProtoBorrowed => { ast::BorrowedSigil => {
return bcx; return bcx;
} }
ast::ProtoBox | ast::ProtoUniq => { ast::ManagedSigil | ast::OwnedSigil => {
/* hard cases: fallthrough to code below */ /* hard cases: fallthrough to code below */
} }
} }
@ -580,10 +572,10 @@ pub fn make_opaque_cbox_free_glue(
abi::tydesc_field_drop_glue, None); abi::tydesc_field_drop_glue, None);
// Free the ty descr (if necc) and the box itself // Free the ty descr (if necc) and the box itself
match proto { match sigil {
ast::ProtoBox => glue::trans_free(bcx, cbox), ast::ManagedSigil => glue::trans_free(bcx, cbox),
ast::ProtoUniq => glue::trans_unique_free(bcx, cbox), ast::OwnedSigil => glue::trans_unique_free(bcx, cbox),
ast::ProtoBare | ast::ProtoBorrowed => { ast::BorrowedSigil => {
bcx.sess().bug(~"impossible") bcx.sess().bug(~"impossible")
} }
} }

View file

@ -23,7 +23,7 @@ pub fn macros() {
include!("macros.rs"); 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 _icx = bcx.insn_ctxt("trans_block");
let mut bcx = bcx; let mut bcx = bcx;
do block_locals(b) |local| { 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, pub fn trans_if(bcx: block,
cond: @ast::expr, cond: @ast::expr,
thn: ast::blk, thn: &ast::blk,
els: Option<@ast::expr>, els: Option<@ast::expr>,
dest: expr::Dest) dest: expr::Dest)
-> block { -> block {
@ -82,10 +82,10 @@ pub fn trans_if(bcx: block,
match elexpr.node { match elexpr.node {
ast::expr_if(_, _, _) => { ast::expr_if(_, _, _) => {
let elseif_blk = ast_util::block_from_expr(elexpr); 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) => { 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 // would be nice to have a constraint on ifs
_ => bcx.tcx().sess.bug(~"strange alternative in if") _ => 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; 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 _icx = bcx.insn_ctxt("trans_while");
let next_bcx = sub_block(bcx, ~"while next"); 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, pub fn trans_loop(bcx:block,
body: ast::blk, body: &ast::blk,
opt_label: Option<ident>) opt_label: Option<ident>)
-> block { -> block {
let _icx = bcx.insn_ctxt("trans_loop"); let _icx = bcx.insn_ctxt("trans_loop");

View file

@ -475,10 +475,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
return controlflow::trans_check_expr(bcx, expr, a, ~"Assertion"); return controlflow::trans_check_expr(bcx, expr, a, ~"Assertion");
} }
ast::expr_while(cond, ref body) => { 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) => { 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) => { ast::expr_assign(dst, src) => {
let src_datum = unpack_datum!( let src_datum = unpack_datum!(
@ -530,7 +530,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
bcx.def(expr.id), dest); bcx.def(expr.id), dest);
} }
ast::expr_if(cond, ref thn, els) => { 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) => { ast::expr_match(discr, ref arms) => {
return _match::trans_match(bcx, expr, discr, /*bad*/copy *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) => { ast::expr_block(ref blk) => {
return do base::with_scope(bcx, blk.info(), return do base::with_scope(bcx, blk.info(),
~"block-expr body") |bcx| { ~"block-expr body") |bcx| {
controlflow::trans_block(bcx, (*blk), dest) controlflow::trans_block(bcx, blk, dest)
}; };
} }
ast::expr_rec(ref fields, base) | 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(*) => { ast::expr_vec(*) | ast::expr_repeat(*) => {
return tvec::trans_fixed_vstore(bcx, expr, expr, dest); return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
} }
// XXX: Bad copy. ast::expr_fn(_, ref decl, ref body, _) |
ast::expr_fn(proto, copy decl, ref body, _) => { ast::expr_fn_block(ref decl, ref body) => {
// Don't use this function for anything real. Use the one in let expr_ty = expr_ty(bcx, expr);
// astconv instead. let sigil = ty::ty_closure_sigil(expr_ty);
return closure::trans_expr_fn(bcx, proto, decl, debug!("translating fn_block %s with type %s",
/*bad*/copy *body, 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, expr.id, expr.id,
None, dest); 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) => { ast::expr_loop_body(blk) => {
match ty::get(expr_ty(bcx, expr)).sty { let expr_ty = expr_ty(bcx, expr);
ty::ty_fn(ref fn_ty) => { let sigil = ty::ty_closure_sigil(expr_ty);
match blk.node { match blk.node {
ast::expr_fn_block(copy decl, ref body) => { ast::expr_fn_block(ref decl, ref body) => {
return closure::trans_expr_fn( return closure::trans_expr_fn(bcx, sigil,
bcx, decl, body,
fn_ty.meta.proto, expr.id, blk.id,
decl, Some(None), dest);
/*bad*/copy *body,
expr.id,
blk.id,
Some(None),
dest);
}
_ => {
bcx.sess().impossible_case(
expr.span,
"loop_body has the wrong kind of contents")
}
}
} }
_ => { _ => {
bcx.sess().impossible_case( 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")
} }
} }
} }

View file

@ -31,7 +31,7 @@ use middle::trans::machine;
use middle::trans::shape; use middle::trans::shape;
use middle::trans::type_of::*; use middle::trans::type_of::*;
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 util::ppaux::ty_to_str;
use core::libc::c_uint; use core::libc::c_uint;
@ -66,10 +66,8 @@ type c_stack_tys = {
fn c_arg_and_ret_lltys(ccx: @crate_ctxt, fn c_arg_and_ret_lltys(ccx: @crate_ctxt,
id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) { id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) {
match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty { match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
let llargtys = type_of_explicit_args( let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs);
ccx,
fn_ty.sig.inputs);
let llretty = type_of::type_of(ccx, fn_ty.sig.output); let llretty = type_of::type_of(ccx, fn_ty.sig.output);
(llargtys, llretty, 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( let star_u8 = ty::mk_imm_ptr(
bcx.tcx(), bcx.tcx(),
ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)); ty::mk_mach_uint(bcx.tcx(), ast::ty_u8));
let fty = ty::mk_fn(bcx.tcx(), FnTyBase { let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy {
meta: FnMeta {purity: ast::impure_fn, purity: ast::impure_fn,
proto: ast::ProtoBorrowed, sigil: ast::BorrowedSigil,
onceness: ast::Many, onceness: ast::Many,
region: ty::re_bound(ty::br_anon(0)), region: ty::re_bound(ty::br_anon(0)),
bounds: @~[]},
sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy), sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy),
ty: star_u8}], ty: star_u8}],
output: ty::mk_nil(bcx.tcx())} 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, pub fn trans_foreign_fn(ccx: @crate_ctxt,
+path: ast_map::path, +path: ast_map::path,
decl: ast::fn_decl, decl: &ast::fn_decl,
body: ast::blk, body: &ast::blk,
llwrapfn: ValueRef, llwrapfn: ValueRef,
id: ast::node_id) { id: ast::node_id) {
let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); let _icx = ccx.insn_ctxt("foreign::build_foreign_fn");
fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path, 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 { id: ast::node_id) -> ValueRef {
let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn"); let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn");
let t = ty::node_id_to_type(ccx.tcx, id); let t = ty::node_id_to_type(ccx.tcx, id);

View file

@ -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 { if field == abi::tydesc_field_free_glue {
match ty::get(t).sty { match ty::get(t).sty {
ty::ty_fn(*) | ty::ty_bare_fn(*) |
ty::ty_closure(*) |
ty::ty_box(*) | ty::ty_box(*) |
ty::ty_opaque_box | ty::ty_opaque_box |
ty::ty_uniq(*) | 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)); tvec::expand_boxed_vec_ty(bcx.tcx(), t));
return; return;
} }
ty::ty_fn(_) => { ty::ty_closure(_) => {
closure::make_fn_glue(bcx, v, t, free_ty) closure::make_closure_glue(bcx, v, t, free_ty)
} }
ty::ty_opaque_closure_ptr(ck) => { ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_free_glue(bcx, ck, v) 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(_) => { ty::ty_closure(_) => {
closure::make_fn_glue(bcx, v0, t, drop_ty) closure::make_closure_glue(bcx, v0, t, drop_ty)
} }
ty::ty_trait(_, _, ty::vstore_box) => { ty::ty_trait(_, _, ty::vstore_box) => {
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u])); 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(_)) => { | ty::ty_estr(ty::vstore_slice(_)) => {
bcx bcx
} }
ty::ty_fn(_) => { ty::ty_closure(_) => {
closure::make_fn_glue(bcx, v, t, take_ty) closure::make_closure_glue(bcx, v, t, take_ty)
} }
ty::ty_trait(_, _, ty::vstore_box) => { ty::ty_trait(_, _, ty::vstore_box) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u])); let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u]));

View file

@ -108,8 +108,8 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id,
}; };
trans_fn(ccx, trans_fn(ccx,
path, path,
mth.decl, &mth.decl,
mth.body, &mth.body,
llfn, llfn,
self_kind, self_kind,
None, None,

View file

@ -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_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) | 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_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx), ty::ty_ptr(_) | ty::ty_rptr(*) => nilptr(tcx),
ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), 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_evec(_, ty::vstore_slice(_)) |
ty::ty_estr(ty::vstore_slice(_)) => { ty::ty_estr(ty::vstore_slice(_)) => {
ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)]) ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])

View file

@ -142,8 +142,8 @@ pub fn trans_method(ccx: @crate_ctxt,
// generate the actual code // generate the actual code
trans_fn(ccx, trans_fn(ccx,
path, path,
method.decl, &method.decl,
method.body, &method.body,
llfn, llfn,
self_arg, self_arg,
param_substs, 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; 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| { make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
let fty = ty::subst_tps(tcx, substs, None, 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) { if (*im.tps).len() > 0u || ty::type_has_self(fty) {
debug!("(making impl vtable) method has self or type params: %s", debug!("(making impl vtable) method has self or type params: %s",
tcx.sess.str_of(im.ident)); tcx.sess.str_of(im.ident));

View file

@ -26,7 +26,7 @@ use middle::trans::shape;
use middle::trans::type_of::type_of_fn_from_ty; use middle::trans::type_of::type_of_fn_from_ty;
use middle::trans::type_of; use middle::trans::type_of;
use middle::trans::type_use; use middle::trans::type_use;
use middle::ty::{FnTyBase, FnMeta, FnSig}; use middle::ty::{FnSig};
use middle::typeck; use middle::typeck;
use core::option; use core::option;
@ -166,12 +166,12 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
let lldecl = match map_node { let lldecl = match map_node {
ast_map::node_item(i@@ast::item { ast_map::node_item(i@@ast::item {
// XXX: Bad copy. // XXX: Bad copy.
node: ast::item_fn(copy decl, _, _, ref body), node: ast::item_fn(ref decl, _, _, ref body),
_ _
}, _) => { }, _) => {
let d = mk_lldecl(); let d = mk_lldecl();
set_inline_hint_if_appr(/*bad*/copy i.attrs, d); 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 d
} }
ast_map::node_item(*) => { 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 \ None => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \
dtor") 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) dtor.node.id, psubsts, Some(hash_id), parent_id)
} }
ast_map::node_trait_method(@ast::provided(mth), _, pt) => { 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, pub fn normalize_for_monomorphization(tcx: ty::ctxt,
ty: ty::t) -> Option<ty::t> { ty: ty::t) -> Option<ty::t> {
// FIXME[mono] could do this recursively. is that worthwhile? (#2529) // FIXME[mono] could do this recursively. is that worthwhile? (#2529)
match ty::get(ty).sty { return match ty::get(ty).sty {
ty::ty_box(*) => { ty::ty_box(*) => {
Some(ty::mk_opaque_box(tcx)) Some(ty::mk_opaque_box(tcx))
} }
ty::ty_fn(ref fty) => { ty::ty_bare_fn(_) => {
Some(ty::mk_fn( Some(ty::mk_bare_fn(
tcx, tcx,
FnTyBase {meta: FnMeta {purity: ast::impure_fn, ty::BareFnTy {
proto: fty.meta.proto, purity: ast::impure_fn,
onceness: ast::Many, abi: ast::RustAbi,
region: ty::re_static, sig: FnSig {inputs: ~[],
bounds: @~[]}, output: ty::mk_nil(tcx)}}))
sig: FnSig {inputs: ~[],
output: ty::mk_nil(tcx)}}))
} }
ty::ty_trait(_, _, _) => { ty::ty_closure(ref fty) => {
Some(ty::mk_fn( Some(normalized_closure_ty(tcx, fty.sigil))
tcx, }
FnTyBase {meta: FnMeta {purity: ast::impure_fn, ty::ty_trait(_, _, ref vstore) => {
proto: ast::ProtoBox, let sigil = match *vstore {
onceness: ast::Many, ty::vstore_uniq => ast::OwnedSigil,
region: ty::re_static, ty::vstore_box => ast::ManagedSigil,
bounds: @~[]}, ty::vstore_slice(_) => ast::BorrowedSigil,
sig: FnSig {inputs: ~[], ty::vstore_fixed(*) => {
output: ty::mk_nil(tcx)}})) 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(_) => { ty::ty_ptr(_) => {
Some(ty::mk_uint(tcx)) Some(ty::mk_uint(tcx))
@ -299,6 +302,20 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
_ => { _ => {
None 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)}})
} }
} }

View file

@ -86,9 +86,8 @@ pub impl reflector {
tcx.sess.ident_of(~"visit_" + ty_name), tcx.sess.ident_of(~"visit_" + ty_name),
*self.visitor_methods).expect(fmt!("Couldn't find visit method \ *self.visitor_methods).expect(fmt!("Couldn't find visit method \
for %s", ty_name)); for %s", ty_name));
let mth_ty = ty::mk_fn( let mth_ty =
tcx, ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
/*bad*/copy self.visitor_methods[mth_idx].fty);
let v = self.visitor_val; let v = self.visitor_val;
debug!("passing %u args:", vec::len(args)); debug!("passing %u args:", vec::len(args));
let bcx = self.bcx; let bcx = self.bcx;
@ -211,39 +210,33 @@ pub impl reflector {
} }
} }
// FIXME (#2594): fetch constants out of intrinsic:: for the // FIXME (#2594): fetch constants out of intrinsic
// numbers. // FIXME (#4809): visitor should break out bare fns from other fns
ty::ty_fn(ref fty) => { ty::ty_closure(ref fty) => {
let pureval = match fty.meta.purity { let pureval = ast_purity_constant(fty.purity);
ast::pure_fn => 0u, let sigilval = ast_sigil_constant(fty.sigil);
ast::unsafe_fn => 1u,
ast::impure_fn => 2u,
ast::extern_fn => 3u
};
let protoval = ast_proto_constant(fty.meta.proto);
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
let extra = ~[self.c_uint(pureval), 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(vec::len(fty.sig.inputs)),
self.c_uint(retval)]; self.c_uint(retval)];
self.visit(~"enter_fn", copy extra); // XXX: Bad copy. self.visit(~"enter_fn", copy extra); // XXX: Bad copy.
for fty.sig.inputs.eachi |i, arg| { self.visit_sig(retval, &fty.sig);
let modeval = match arg.mode { self.visit(~"leave_fn", extra);
ast::infer(_) => 0u, }
ast::expl(e) => match e {
ast::by_ref => 1u, // FIXME (#2594): fetch constants out of intrinsic:: for the
ast::by_val => 2u, // numbers.
ast::by_copy => 5u ty::ty_bare_fn(ref fty) => {
} let pureval = ast_purity_constant(fty.purity);
}; let sigilval = 0u;
self.visit(~"fn_input", let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
~[self.c_uint(i), let extra = ~[self.c_uint(pureval),
self.c_uint(modeval), self.c_uint(sigilval),
self.c_tydesc(arg.ty)]); self.c_uint(vec::len(fty.sig.inputs)),
} self.c_uint(retval)];
self.visit(~"fn_output", self.visit(~"enter_fn", copy extra); // XXX: Bad copy.
~[self.c_uint(retval), self.visit_sig(retval, &fty.sig);
self.c_tydesc(fty.sig.output)]);
self.visit(~"leave_fn", extra); self.visit(~"leave_fn", extra);
} }
@ -302,11 +295,31 @@ pub impl reflector {
ty::ty_type => self.leaf(~"type"), ty::ty_type => self.leaf(~"type"),
ty::ty_opaque_box => self.leaf(~"opaque_box"), ty::ty_opaque_box => self.leaf(~"opaque_box"),
ty::ty_opaque_closure_ptr(ck) => { 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)]) 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 // 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; return final;
} }
pub fn ast_proto_constant(proto: ast::Proto) -> uint { pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint {
match proto { match sigil {
ast::ProtoBare => 0u, ast::OwnedSigil => 2u,
ast::ProtoUniq => 2u, ast::ManagedSigil => 3u,
ast::ProtoBox => 3u, ast::BorrowedSigil => 4u,
ast::ProtoBorrowed => 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
} }
} }

View file

@ -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 // 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 { 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 { 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 // structs
T_struct(~[T_struct(tys)]) 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_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
ty::ty_type => T_ptr(cx.tydesc_type), ty::ty_type => T_ptr(cx.tydesc_type),
ty::ty_tup(elts) => { ty::ty_tup(elts) => {

View file

@ -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))}; 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 { match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
for vec::each(fn_ty.sig.inputs) |arg| { ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for vec::each(sig.inputs) |arg| {
match ty::resolved_mode(ccx.tcx, arg.mode) { match ty::resolved_mode(ccx.tcx, arg.mode) {
by_val | by_copy => { by_val | by_copy => {
type_needs(cx, use_repr, arg.ty); 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 it, we depend on the drop glue for T (we have to write the
right tydesc into the result) right tydesc into the result)
*/ */
ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) ty::ty_closure(*) |
| ty::ty_trait(_, _, _) => false, ty::ty_bare_fn(*) |
ty::ty_ptr(_) |
ty::ty_rptr(_, _) |
ty::ty_trait(_, _, _) => false,
ty::ty_enum(did, ref substs) => { ty::ty_enum(did, ref substs) => {
if option::is_none(&list::find(enums_seen, |id| *id == did)) { if option::is_none(&list::find(enums_seen, |id| *id == did)) {
let seen = @Cons(did, enums_seen); let seen = @Cons(did, enums_seen);
@ -287,15 +292,15 @@ pub fn mark_for_expr(cx: ctx, e: @expr) {
} }
} }
expr_fn(*) | expr_fn_block(*) => { expr_fn(*) | expr_fn_block(*) => {
match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) { match ty::ty_closure_sigil(ty::expr_ty(cx.ccx.tcx, e)) {
ast::ProtoBare | ast::ProtoUniq => {} ast::OwnedSigil => {}
ast::ProtoBox | ast::ProtoBorrowed => { ast::BorrowedSigil | ast::ManagedSigil => {
for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| { for freevars::get_freevars(cx.ccx.tcx, e.id).each |fv| {
let node_id = ast_util::def_id_of_def(fv.def).node; let node_id = ast_util::def_id_of_def(fv.def).node;
node_type_needs(cx, use_repr, node_id); node_type_needs(cx, use_repr, node_id);
} }
}
} }
}
} }
expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
expr_ret(Some(val)) => { expr_ret(Some(val)) => {

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#[warn(deprecated_pattern)];
use core::prelude::*; use core::prelude::*;
use driver::session; use driver::session;
@ -27,7 +25,7 @@ use middle;
use session::Session; use session::Session;
use util::ppaux::{note_and_explain_region, bound_region_to_str}; 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::{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::cast;
use core::cmp; use core::cmp;
@ -73,7 +71,7 @@ pub type param_bounds = @~[param_bound];
pub type method = { pub type method = {
ident: ast::ident, ident: ast::ident,
tps: @~[param_bounds], tps: @~[param_bounds],
fty: FnTy, fty: BareFnTy,
self_ty: ast::self_ty_, self_ty: ast::self_ty_,
vis: ast::visibility, vis: ast::visibility,
def_id: ast::def_id 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_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
pub pure fn type_id(t: t) -> uint { get(t).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] #[deriving_eq]
pub struct FnMeta { pub struct BareFnTy {
purity: ast::purity, purity: ast::purity,
proto: ast::Proto, abi: Abi,
sig: FnSig
}
#[deriving_eq]
pub struct ClosureTy {
purity: ast::purity,
sigil: ast::Sigil,
onceness: ast::Onceness, onceness: ast::Onceness,
region: Region, region: Region,
bounds: @~[param_bound] sig: FnSig
} }
/** /**
@ -374,24 +370,18 @@ pub struct FnSig {
output: t output: t
} }
/** impl BareFnTy : to_bytes::IterBytes {
* 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 {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { 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] #[deriving_eq]
pub struct param_ty { pub struct param_ty {
@ -491,6 +481,7 @@ pub struct substs {
// NB: If you change this, you'll probably want to change the corresponding // NB: If you change this, you'll probably want to change the corresponding
// AST structure in libsyntax/ast.rs as well. // AST structure in libsyntax/ast.rs as well.
#[deriving_eq]
pub enum sty { pub enum sty {
ty_nil, ty_nil,
ty_bot, ty_bot,
@ -506,7 +497,8 @@ pub enum sty {
ty_ptr(mt), ty_ptr(mt),
ty_rptr(Region, mt), ty_rptr(Region, mt),
ty_rec(~[field]), ty_rec(~[field]),
ty_fn(FnTy), ty_bare_fn(BareFnTy),
ty_closure(ClosureTy),
ty_trait(def_id, substs, vstore), ty_trait(def_id, substs, vstore),
ty_struct(def_id, substs), ty_struct(def_id, substs),
ty_tup(~[t]), ty_tup(~[t]),
@ -522,7 +514,7 @@ pub enum sty {
// "Fake" types, used for trans purposes // "Fake" types, used for trans purposes
ty_type, // type_desc* ty_type, // type_desc*
ty_opaque_box, // used by monomorphizer to represent any @ box 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), ty_unboxed_vec(mt),
} }
@ -546,8 +538,9 @@ pub enum type_err {
terr_mismatch, terr_mismatch,
terr_purity_mismatch(expected_found<purity>), terr_purity_mismatch(expected_found<purity>),
terr_onceness_mismatch(expected_found<Onceness>), terr_onceness_mismatch(expected_found<Onceness>),
terr_abi_mismatch(expected_found<ast::Abi>),
terr_mutability, terr_mutability,
terr_proto_mismatch(expected_found<ast::Proto>), terr_sigil_mismatch(expected_found<ast::Sigil>),
terr_box_mutability, terr_box_mutability,
terr_ptr_mutability, terr_ptr_mutability,
terr_ref_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 { pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
let mut kind = kind_noncopyable(); let mut kind = kind_noncopyable();
for vec::each(*bounds) |bound| { 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_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_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
&ty_fn(ref f) => { &ty_bare_fn(ref f) => {
flags |= rflags(f.meta.region); 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; } for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
flags |= get(f.sig.output).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)) } 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_closure(cx: ctxt, +fty: ClosureTy) -> t {
pub fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) } 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) pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
-> t { -> 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_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
pub fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t { pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
mk_t(cx, ty_opaque_closure_ptr(proto)) mk_t(cx, ty_opaque_closure_ptr(sigil))
} }
pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } 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 { 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 // FIXME(#2202) --- We retain by-ref for fn& things to workaround a
// memory leak that otherwise results when @fn is upcast to &fn. // memory leak that otherwise results when @fn is upcast to &fn.
if type_is_fn(ty) { match ty::get(ty).sty {
match ty_fn_proto(ty) { ty::ty_closure(ClosureTy {sigil: ast::BorrowedSigil, _}) => {
ast::ProtoBorrowed => { return ast::by_ref;
return ast::by_ref;
}
_ => {}
} }
_ => {}
} }
return if tcx.legacy_modes { return if tcx.legacy_modes {
if type_is_borrowed(ty) { 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 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 { fn type_is_borrowed(ty: t) -> bool {
match ty::get(ty).sty { match ty::get(ty).sty {
ty::ty_rptr(*) => true, 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); } for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
} }
ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, 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); } for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
maybe_walk_ty(ft.sig.output, 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)); let new_ts = vec::map(ts, |tt| fldop(*tt));
ty_tup(new_ts) ty_tup(new_ts)
} }
ty_fn(ref f) => { ty_bare_fn(ref f) => {
let sig = fold_sig(&f.sig, fldop); 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, tm) => {
ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl}) 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_trait(def_id, ref substs, vst) => {
ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
} }
ty_fn(ref f) => { ty_bare_fn(ref f) => {
ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region), ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
..f.meta}, ..copy *f})
sig: fold_sig(&f.sig, fldfnt)}) }
ty_closure(ref f) => {
ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
sig: fold_sig(&f.sig, fldfnt),
..copy *f})
} }
ref sty => { ref sty => {
fold_sty_to_ty(cx, sty, |t| fldt(t)) 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, // n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar. // that is why its name is so similar.
pub fn fold_regions( pub fn fold_regions(
@ -1372,41 +1374,6 @@ pub fn fold_regions(
do_fold(cx, ty, false, fldr) 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. // 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 { 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; } 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 { pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty { 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_trait(*) |
ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) | ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
@ -1715,10 +1684,11 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
} }
accum accum
} }
ty_fn(ref fty) => { ty_bare_fn(*) => false,
match fty.meta.proto { ty_closure(ref fty) => {
ast::ProtoBare | ast::ProtoBorrowed => false, match fty.sigil {
ast::ProtoBox | ast::ProtoUniq => true, ast::BorrowedSigil => false,
ast::ManagedSigil | ast::OwnedSigil => true,
} }
} }
}; };
@ -1813,7 +1783,7 @@ pub enum Kind { kind_(u32) }
const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32; const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32;
/// no shared box, borrowed ptr (must imply DURABLE) /// 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) /// is durable (no borrowed ptrs)
const KIND_MASK_DURABLE : u32 = 0b000000000000000000000000100_u32; 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 *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
} }
pub fn meta_kind(p: FnMeta) -> Kind { pure fn kind_is_const(k: Kind) -> bool {
match p.proto { // XXX consider the kind bounds! *k & KIND_MASK_CONST == KIND_MASK_CONST
ast::ProtoBare => { }
kind_safe_for_default_mode_send() | kind_const() | kind_durable()
} fn closure_kind(cty: &ClosureTy) -> Kind {
ast::ProtoBorrowed => { let kind = match cty.sigil {
kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE) ast::BorrowedSigil => kind_implicitly_copyable(),
} ast::ManagedSigil => kind_implicitly_copyable(),
ast::ProtoBox => { ast::OwnedSigil => kind_owned_only() | kind_durable(),
kind_safe_for_default_mode() | kind_durable() };
}
ast::ProtoUniq => { let kind = match cty.region {
kind_owned_copy() | kind_durable() 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 { let mut result = match /*bad*/copy get(ty).sty {
// Scalar and unique types are sendable, constant, and owned // Scalar and unique types are sendable, constant, and owned
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | 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() 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_closure(ref c) => {
ty_fn(ref f) => meta_kind(f.meta), closure_kind(c)
}
// Those with refcounts raise noncopyable to copyable, // Those with refcounts raise noncopyable to copyable,
// lower sendable to copyable. Therefore just set result 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_evec(_, vstore_slice(_)) |
ty_estr(vstore_slice(_)) | ty_estr(vstore_slice(_)) |
ty_fn(_) => { ty_bare_fn(*) |
ty_closure(*) => {
2 2
} }
@ -2297,7 +2274,8 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
ty_uint(_) | ty_uint(_) |
ty_float(_) | ty_float(_) |
ty_estr(_) | ty_estr(_) |
ty_fn(_) | ty_bare_fn(_) |
ty_closure(_) |
ty_infer(_) | ty_infer(_) |
ty_err | ty_err |
ty_param(_) | ty_param(_) |
@ -2472,9 +2450,9 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
match /*bad*/copy get(ty).sty { match /*bad*/copy get(ty).sty {
// Scalar types // Scalar types
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | 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 // Boxed types
ty_box(_) | ty_uniq(_) | ty_fn(_) | ty_box(_) | ty_uniq(_) | ty_closure(_) |
ty_estr(vstore_uniq) | ty_estr(vstore_box) | ty_estr(vstore_uniq) | ty_estr(vstore_box) |
ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) | ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false, 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) { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_5(&self.purity, (**self).iter_bytes(lsb0, f)
&self.proto,
&self.onceness,
&self.region,
&self.bounds,
lsb0, f);
} }
} }
@ -2755,7 +2728,7 @@ impl sty : to_bytes::IterBytes {
ty_rec(ref fs) => ty_rec(ref fs) =>
to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), 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), to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
ty_self => 13u8.iter_bytes(lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f),
@ -2789,7 +2762,10 @@ impl sty : to_bytes::IterBytes {
ty_rptr(ref r, ref mt) => ty_rptr(ref r, ref mt) =>
to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f), 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 // Type accessors for substructures of types
pub fn ty_fn_args(fty: t) -> ~[arg] { pub fn ty_fn_args(fty: t) -> ~[arg] {
match get(fty).sty { match get(fty).sty {
ty_fn(ref f) => /*bad*/copy f.sig.inputs, ty_bare_fn(ref f) => copy f.sig.inputs,
_ => die!(~"ty_fn_args() called on non-fn type") 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 { match get(fty).sty {
ty_fn(ref f) => f.meta.proto, ty_closure(ref f) => f.sigil,
_ => die!(~"ty_fn_proto() called on non-fn type") ref s => {
die!(fmt!("ty_closure_sigil() called on non-closure type: %?", s))
}
} }
} }
pub fn ty_fn_purity(fty: t) -> ast::purity { pub fn ty_fn_purity(fty: t) -> ast::purity {
match get(fty).sty { match get(fty).sty {
ty_fn(ref f) => f.meta.purity, ty_bare_fn(ref f) => f.purity,
_ => die!(~"ty_fn_purity() called on non-fn type") 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 { pub pure fn ty_fn_ret(fty: t) -> t {
match get(fty).sty { match get(fty).sty {
ty_fn(ref f) => f.sig.output, ty_bare_fn(ref f) => f.sig.output,
_ => die!(~"ty_fn_ret() called on non-fn type") 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 { fn is_fn_ty(fty: t) -> bool {
match get(fty).sty { match get(fty).sty {
ty_fn(_) => true, ty_bare_fn(_) => true,
_ => false 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 * Returns a new function type based on `fn_type` but returning a value of
* type `ret_type` instead. */ * type `ret_type` instead. */
match ty::get(fn_type).sty { match ty::get(fn_type).sty {
ty::ty_fn(ref fty) => { ty::ty_closure(ref fty) => {
ty::mk_fn(tcx, FnTyBase { ty::mk_closure(tcx, ClosureTy {
meta: fty.meta, sig: FnSig {output: ret_type, ..copy fty.sig},
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) 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 // Type accessors for AST nodes
pub fn block_ty(cx: ctxt, b: &ast::blk) -> t { pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
return node_id_to_type(cx, b.node.id); 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, fn borrow_fn(cx: ctxt, expr: @ast::expr,
autoref: &AutoRef, ty: ty::t) -> ty::t { autoref: &AutoRef, ty: ty::t) -> ty::t {
match get(ty).sty { match get(ty).sty {
ty_fn(ref fty) => { ty_closure(ref fty) => {
ty::mk_fn(cx, FnTyBase {meta: FnMeta {proto: ProtoBorrowed, ty::mk_closure(cx, ClosureTy {
region: autoref.region, sigil: BorrowedSigil,
..copy fty.meta}, region: autoref.region,
sig: copy fty.sig}) ..copy *fty
})
} }
ref s => { ref s => {
@ -3417,7 +3400,8 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
ty_ptr(_) => ~"*-ptr", ty_ptr(_) => ~"*-ptr",
ty_rptr(_, _) => ~"&-ptr", ty_rptr(_, _) => ~"&-ptr",
ty_rec(_) => ~"record", 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_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)), ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
ty_tup(_) => ~"tuple", 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", fmt!("expected %s fn but found %s fn",
values.expected.to_str(), values.found.to_str()) 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) => { terr_onceness_mismatch(values) => {
fmt!("expected %s fn but found %s fn", fmt!("expected %s fn but found %s fn",
values.expected.to_str(), values.found.to_str()) values.expected.to_str(), values.found.to_str())
} }
terr_proto_mismatch(values) => { terr_sigil_mismatch(values) => {
fmt!("expected %s closure, found %s closure", fmt!("expected %s closure, found %s closure",
proto_ty_to_str(cx, values.expected, false), values.expected.to_str(),
proto_ty_to_str(cx, values.found, false)) values.found.to_str())
} }
terr_mutability => ~"values differ in mutability", terr_mutability => ~"values differ in mutability",
terr_box_mutability => ~"boxed 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 // This type has a region. Get rid of it
mk_rptr(cx, re_static, normalize_mt(cx, mt)), mk_rptr(cx, re_static, normalize_mt(cx, mt)),
ty_fn(ref fn_ty) => { ty_closure(ref closure_ty) => {
mk_fn(cx, FnTyBase { mk_closure(cx, ClosureTy {
meta: FnMeta { region: ty::re_static,
region: ty::re_static, ..copy *closure_ty
..fn_ty.meta
},
sig: /*bad*/copy fn_ty.sig
}) })
} }
@ -4310,13 +4295,13 @@ pub fn eval_repeat_count(tcx: ctxt,
// Determine what purity to check a nested function under // Determine what purity to check a nested function under
pub pure fn determine_inherited_purity(parent_purity: ast::purity, pub pure fn determine_inherited_purity(parent_purity: ast::purity,
child_purity: ast::purity, child_purity: ast::purity,
child_proto: ast::Proto) child_sigil: ast::Sigil)
-> ast::purity { -> ast::purity {
// If the closure is a stack closure and hasn't had some non-standard // 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. // purity inferred for it, then check it under its parent's purity.
// Otherwise, use its own // Otherwise, use its own
match child_proto { match child_sigil {
ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity, ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity,
_ => child_purity _ => child_purity
} }
} }
@ -4526,171 +4511,6 @@ impl bound_region : cmp::Eq {
pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) } 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 { impl param_bound : cmp::Eq {
pure fn eq(&self, other: &param_bound) -> bool { pure fn eq(&self, other: &param_bound) -> bool {
match (*self) { match (*self) {

View file

@ -55,7 +55,7 @@
use core::prelude::*; use core::prelude::*;
use middle::pat_util::pat_id_map; 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::{ty_param_substs_and_ty};
use middle::ty; use middle::ty;
use middle::typeck::check::fn_ctxt; use middle::typeck::check::fn_ctxt;
@ -70,7 +70,7 @@ use core::vec;
use syntax::ast; use syntax::ast;
use syntax::codemap::span; use syntax::codemap::span;
use syntax::print::pprust::path_to_str; use syntax::print::pprust::path_to_str;
use util::common::indent; use util::common::indenter;
pub trait ast_conv { pub trait ast_conv {
fn tcx() -> ty::ctxt; 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) ty::mk_rec(tcx, flds)
} }
ast::ty_fn(f) => { ast::ty_bare_fn(bf) => {
let bounds = collect::compute_bounds(self.ccx(), f.bounds); ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity,
let fn_decl = ty_of_fn_decl(self, rscope, f.proto, bf.abi, bf.decl))
f.purity, f.onceness, }
bounds, f.region, f.decl, None, ast::ty_closure(f) => {
ast_ty.span); let fn_decl = ty_of_closure(self, rscope, f.sigil,
ty::mk_fn(tcx, fn_decl) f.purity, f.onceness,
f.region, f.decl, None,
ast_ty.span);
ty::mk_closure(tcx, fn_decl)
} }
ast::ty_path(path, id) => { ast::ty_path(path, id) => {
let a_def = match tcx.def_map.find(&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} arg {mode: mode, ty: ty}
} }
pub type expected_tys = Option<{inputs: ~[ty::arg], pub fn ty_of_bare_fn<AC: ast_conv, RS: region_scope Copy Durable>(
output: ty::t}>;
pub fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Durable>(
self: AC, rscope: RS, self: AC, rscope: RS,
ast_proto: ast::Proto,
purity: ast::purity, purity: ast::purity,
onceness: ast::Onceness, abi: ast::Abi,
bounds: @~[ty::param_bound], decl: ast::fn_decl) -> ty::BareFnTy
opt_region: Option<@ast::region>, {
decl: ast::fn_decl,
expected_tys: expected_tys,
span: span) -> ty::FnTy {
debug!("ty_of_fn_decl"); 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 // new region names that appear inside of the fn decl are bound to
// that function type // that function type
let rb = in_binding_rscope(rscope); let rb = in_binding_rscope(rscope);
let input_tys = do decl.inputs.mapi |i, a| { let input_tys = decl.inputs.map(|a| ty_of_arg(self, rb, *a, None));
let expected_arg_ty = do expected_tys.chain_ref |e| { let output_ty = match decl.output.node {
// no guarantee that the correct number of expected args ast::ty_infer => self.ty_infer(decl.output.span),
// were supplied _ => ast_ty_to_ty(self, rb, decl.output)
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); ty::BareFnTy {
let output_ty = match decl.output.node { purity: purity,
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(), abi: abi,
ast::ty_infer => self.ty_infer(decl.output.span), sig: ty::FnSig {inputs: input_tys, output: output_ty}
_ => ast_ty_to_ty(self, rb, decl.output) }
}; }
FnTyBase { pub fn ty_of_closure<AC: ast_conv, RS: region_scope Copy Durable>(
meta: FnMeta {purity: purity, self: AC, rscope: RS,
proto: ast_proto, sigil: ast::Sigil,
onceness: onceness, purity: ast::purity,
region: bound_region, onceness: ast::Onceness,
bounds: bounds}, opt_region: Option<@ast::region>,
sig: FnSig {inputs: input_tys, decl: ast::fn_decl,
output: output_ty} 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}
} }
} }

View file

@ -883,7 +883,7 @@ pub impl LookupContext {
}) })
} }
ty_trait(*) | ty_fn(*) => { ty_trait(*) | ty_closure(*) => {
// NDM---eventually these should be some variant of autoref // NDM---eventually these should be some variant of autoref
None None
} }
@ -906,14 +906,14 @@ pub impl LookupContext {
let tcx = self.tcx(); let tcx = self.tcx();
match ty::get(self_ty).sty { 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(IntVar(_)) |
ty_infer(FloatVar(_)) | ty_infer(FloatVar(_)) |
ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool | ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
ty_int(*) | ty_uint(*) | ty_int(*) | ty_uint(*) |
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) | ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) |
ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) | ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) |
ty_trait(*) | ty_fn(*) => { ty_trait(*) | ty_closure(*) => {
self.search_for_some_kind_of_autorefd_method( self.search_for_some_kind_of_autorefd_method(
AutoPtr, autoderefs, [m_const, m_imm, m_mutbl], AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
|m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m})) |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, trait_did: def_id,
method_num: uint) -> ty::t { method_num: uint) -> ty::t {
let trait_methods = ty::trait_methods(tcx, trait_did); 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)
} }
} }

View file

@ -81,7 +81,7 @@ use core::prelude::*;
use middle::const_eval; use middle::const_eval;
use middle::pat_util::pat_id_map; use middle::pat_util::pat_id_map;
use middle::pat_util; 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::{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::{re_bound, br_cap_avoid, substs, arg, param_ty};
use middle::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::astconv;
use middle::typeck::check::_match::pat_ctxt; use middle::typeck::check::_match::pat_ctxt;
use middle::typeck::check::method::TransformTypeNormally; 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::regionmanip::replace_bound_regions_in_fn_sig;
use middle::typeck::check::vtable::{LocationInfo, VtableContext}; use middle::typeck::check::vtable::{LocationInfo, VtableContext};
use middle::typeck::crate_ctxt; use middle::typeck::crate_ctxt;
@ -248,8 +247,9 @@ pub fn check_bare_fn(ccx: @crate_ctxt,
self_info: Option<self_info>) { self_info: Option<self_info>) {
let fty = ty::node_id_to_type(ccx.tcx, id); let fty = ty::node_id_to_type(ccx.tcx, id);
match ty::get(fty).sty { match ty::get(fty).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
check_fn(ccx, self_info, fn_ty, decl, body, Vanilla, None) check_fn(ccx, self_info, fn_ty.purity, None,
&fn_ty.sig, decl, body, Vanilla, None)
} }
_ => ccx.tcx.sess.impossible_case(body.span, _ => ccx.tcx.sess.impossible_case(body.span,
"check_bare_fn: function type expected") "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, pub fn check_fn(ccx: @crate_ctxt,
self_info: Option<self_info>, self_info: Option<self_info>,
fn_ty: &ty::FnTy, purity: ast::purity,
sigil: Option<ast::Sigil>,
fn_sig: &ty::FnSig,
decl: &ast::fn_decl, decl: &ast::fn_decl,
body: ast::blk, body: ast::blk,
fn_kind: FnKind, fn_kind: FnKind,
old_fcx: Option<@fn_ctxt>) { old_fcx: Option<@fn_ctxt>)
{
let tcx = ccx.tcx; let tcx = ccx.tcx;
let indirect_ret = match fn_kind { let indirect_ret = match fn_kind {
ForLoop => true, _ => false ForLoop => true, _ => false
@ -277,7 +279,7 @@ pub fn check_fn(ccx: @crate_ctxt,
let {isr, self_info, fn_sig} = { let {isr, self_info, fn_sig} = {
let old_isr = option::map_default(&old_fcx, @Nil, let old_isr = option::map_default(&old_fcx, @Nil,
|fcx| fcx.in_scope_regions); |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)) |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. // in the case of function expressions, based on the outer context.
let fcx: @fn_ctxt = { let fcx: @fn_ctxt = {
let (purity, inherited) = match old_fcx { let (purity, inherited) = match old_fcx {
None => { None => (purity, blank_inherited(ccx)),
(fn_ty.meta.purity,
blank_inherited(ccx))
}
Some(fcx) => { Some(fcx) => {
(ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity, (ty::determine_inherited_purity(fcx.purity, purity,
fn_ty.meta.proto), sigil.get()),
fcx.inh) fcx.inh)
} }
}; };
@ -1092,8 +1091,9 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
in_fty: ty::t, in_fty: ty::t,
callee_expr: @ast::expr, callee_expr: @ast::expr,
args: ~[@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 tcx = fcx.ccx.tcx;
let mut bot = false; 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", debug!("check_call_inner: before universal quant., in_fty=%s",
fcx.infcx().ty_to_str(in_fty)); 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 // This is subtle: we expect `fty` to be a function type, which
// normally introduce a level of binding. In this case, we want to // normally introduce a level of binding. In this case, we want to
// process the types bound by the function but not by any nested // process the types bound by the function but not by any nested
// functions. Therefore, we match one level of structure. // functions. Therefore, we match one level of structure.
let fty = let ret_ty = match structure_of(fcx, sp, in_fty) {
match structure_of(fcx, sp, in_fty) { ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_fn(ref fn_ty) => { ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
let fn_ty = let {fn_sig: sig, _} =
/*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil, replace_bound_regions_in_fn_sig(
None, fn_ty, |_br| fcx.infcx().next_region_var(sp, tcx, @Nil, None, sig,
call_expr_id)).fn_ty; |_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 // Grab the argument types, supplying fresh type variables
// if the wrong number of arguments were supplied // if the wrong number of arguments were supplied
let expected_arg_count = fn_ty.sig.inputs.len(); let expected_arg_count = sig.inputs.len();
formal_tys = if expected_arg_count == supplied_arg_count { formal_tys = if expected_arg_count == supplied_arg_count {
fn_ty.sig.inputs.map(|a| a.ty) sig.inputs.map(|a| a.ty)
} else { } else {
tcx.sess.span_err( let suffix = match sugar {
sp, fmt!("this function takes %u parameter%s but \ ast::NoSugar => "",
%u parameter%s supplied", 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, expected_arg_count,
if expected_arg_count == 1 { if expected_arg_count == 1 {""}
~"" else {"s"},
} else {
~"s"
},
supplied_arg_count, supplied_arg_count,
if supplied_arg_count == 1 { if supplied_arg_count == 1 {" was"}
~" was" else {"s were"},
} else { suffix);
~"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)
}
};
debug!("check_call_inner: after universal quant., fty=%s", tcx.sess.span_err(sp, msg);
fcx.infcx().ty_to_str(fty));
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. // Check the arguments.
// We do this in a pretty awful way: first we typecheck any 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 // A generic function for checking assignment expressions
@ -1233,36 +1243,26 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
fn_ty: ty::t, fn_ty: ty::t,
expr: @ast::expr, expr: @ast::expr,
+args: ~[@ast::expr], +args: ~[@ast::expr],
bot: bool) bot: bool,
-> bool { sugar: ast::CallSugar) -> bool
{
let mut bot = bot; let mut bot = bot;
// Call the generic checker. // Call the generic checker.
let fty = { let (ret_ty, b) = check_call_inner(fcx, sp, call_expr_id,
let r = check_call_inner(fcx, sp, call_expr_id, fn_ty, expr, args, sugar,
fn_ty, expr, args, DontDerefArgs); DontDerefArgs);
bot |= r.bot; bot |= b;
r.fty
};
// Pull the return type out of the type of the function. // Pull the return type out of the type of the function.
match structure_of(fcx, sp, fty) { fcx.write_ty(call_expr_id, ret_ty);
ty::ty_fn(ref f) => { return bot;
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;
}
}
} }
// A generic function for doing all of the checking for call expressions // 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, 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 // Index expressions need to be handled separately, to inform them
// that they appear in call position. // that they appear in call position.
let mut bot = match /*bad*/copy f.node { 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), fcx.expr_ty(f),
f, f,
args, args,
bot) bot,
sugar)
} }
// Checks a method call. // Checks a method call.
@ -1287,7 +1288,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
rcvr: @ast::expr, rcvr: @ast::expr,
method_name: ast::ident, method_name: ast::ident,
+args: ~[@ast::expr], +args: ~[@ast::expr],
tps: ~[@ast::Ty]) tps: ~[@ast::Ty],
sugar: ast::CallSugar)
-> bool { -> bool {
let bot = check_expr(fcx, rcvr); let bot = check_expr(fcx, rcvr);
let expr_t = structurally_resolved_type(fcx, 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), fcx.node_ty(expr.callee_id),
expr, expr,
args, args,
bot) bot,
sugar)
} }
// A generic function for checking for or for-each loops // 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, ~[], op_ex.callee_id, opname, self_t, ~[],
deref_args) { deref_args) {
Some(ref origin) => { Some(ref origin) => {
let {fty: method_ty, bot: bot} = { let method_ty = fcx.node_ty(op_ex.callee_id);
let method_ty = fcx.node_ty(op_ex.callee_id); fcx.ccx.method_map.insert(op_ex.id, *origin);
check_call_inner(fcx, op_ex.span, op_ex.id, Some(check_call_inner(fcx, op_ex.span, op_ex.id,
method_ty, op_ex, args, deref_args) method_ty, op_ex, args,
}; ast::NoSugar, deref_args))
fcx.ccx.method_map.insert(op_ex.id, (*origin));
Some((ty::ty_fn_ret(method_ty), bot))
} }
_ => None _ => 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 // 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. // supply the do keyword. Let's be more helpful in that situation.
if op == ast::or { if op == ast::or {
match ty::get(lhs_resolved_t).sty { match ty::get(lhs_resolved_t).sty {
ty::ty_fn(_) => { ty::ty_bare_fn(_) | ty::ty_closure(_) => {
tcx.sess.span_note( tcx.sess.span_note(
ex.span, ~"did you forget the `do` keyword for the call?"); ex.span, ~"did you forget the `do` keyword \
for the call?");
}
_ => ()
} }
_ => ()
}
} }
(lhs_resolved_t, false) (lhs_resolved_t, false)
@ -1523,7 +1525,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
fn check_expr_fn(fcx: @fn_ctxt, fn check_expr_fn(fcx: @fn_ctxt,
expr: @ast::expr, expr: @ast::expr,
ast_proto_opt: Option<ast::Proto>, ast_sigil_opt: Option<ast::Sigil>,
decl: &ast::fn_decl, decl: &ast::fn_decl,
body: ast::blk, body: ast::blk,
fn_kind: FnKind, 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 // avoid capture of bound regions in the expected type. See
// def'n of br_cap_avoid() for a more lengthy explanation of // def'n of br_cap_avoid() for a more lengthy explanation of
// what's going on here. // 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 // to impure and block. Note that we only will use those for
// block syntax lambdas; that is, lambdas without explicit // block syntax lambdas; that is, lambdas without explicit
// protos. // sigils.
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let (expected_tys, let (expected_tys,
expected_purity, expected_purity,
expected_proto, expected_sigil,
expected_onceness) = { expected_onceness) = {
match expected_sty { match expected_sty {
Some(ty::ty_fn(ref fn_ty)) => { Some(ty::ty_closure(ref cenv)) => {
let id = expr.id; let id = expr.id;
let {fn_ty: fn_ty, _} = let {fn_sig: sig, _} =
replace_bound_regions_in_fn_ty( replace_bound_regions_in_fn_sig(
tcx, @Nil, None, fn_ty, tcx, @Nil, None, &cenv.sig,
|br| ty::re_bound(ty::br_cap_avoid(id, @br))); |br| ty::re_bound(ty::br_cap_avoid(id, @br)));
(Some({inputs: /*bad*/copy fn_ty.sig.inputs, (Some(sig), cenv.purity, cenv.sigil, cenv.onceness)
output: fn_ty.sig.output}),
fn_ty.meta.purity,
fn_ty.meta.proto,
fn_ty.meta.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 // If the proto is specified, use that, otherwise select a
// proto based on inference. // proto based on inference.
let (proto, purity) = match ast_proto_opt { let (sigil, purity) = match ast_sigil_opt {
Some(p) => (p, ast::impure_fn), Some(p) => (p, ast::impure_fn),
None => (expected_proto, expected_purity) None => (expected_sigil, expected_purity)
}; };
// construct the function type // construct the function type
let mut fn_ty = astconv::ty_of_fn_decl( let mut fn_ty = astconv::ty_of_closure(
fcx, fcx, fcx, fcx,
proto, purity, expected_onceness, sigil, purity, expected_onceness,
/*bounds:*/ @~[], /*opt_region:*/ None, None, *decl, expected_tys, expr.span);
*decl, expected_tys, expr.span);
// XXX: Bad copy. let fty = ty::mk_closure(tcx, copy fn_ty);
let fty = ty::mk_fn(tcx, copy fn_ty);
debug!("check_expr_fn_with_unifier %s fty=%s", debug!("check_expr_fn_with_unifier %s fty=%s",
fcx.expr_to_str(expr), 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, // We inherit the same self info as the enclosing scope,
// since the function we're checking might capture `self` // since the function we're checking might capture `self`
check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body, check_fn(fcx.ccx, fcx.self_info, fn_ty.purity, Some(fn_ty.sigil),
fn_kind, Some(fcx)); &fn_ty.sig, decl, body, fn_kind, Some(fcx));
} }
@ -1913,6 +1909,119 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
return bot; 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 tcx = fcx.ccx.tcx;
let id = expr.id; let id = expr.id;
let mut bot = false; let mut bot = false;
@ -2153,121 +2262,38 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
ast::expr_match(discrim, ref arms) => { ast::expr_match(discrim, ref arms) => {
bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms)); bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms));
} }
ast::expr_fn(proto, ref decl, ref body, _) => { ast::expr_fn(sigil, ref decl, ref body, _) => {
check_expr_fn(fcx, expr, Some(proto), check_expr_fn(fcx, expr, Some(sigil),
decl, (*body), Vanilla, expected); decl, (*body), Vanilla, expected);
} }
ast::expr_fn_block(ref decl, ref body) => { ast::expr_fn_block(ref decl, ref body) => {
check_expr_fn(fcx, expr, None, check_expr_fn(fcx, expr, None,
decl, (*body), Vanilla, expected); decl, (*body), Vanilla, expected);
} }
ast::expr_loop_body(b) => { ast::expr_loop_body(loop_body) => {
// a loop body is the special argument to a `for` loop. We know that check_loop_body(fcx, expr, expected, loop_body);
// 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_do_body(b) => { ast::expr_do_body(b) => {
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let inner_ty = match expected_sty { let inner_ty = match expected_sty {
Some(ty::ty_fn(ref fty)) => { Some(ty::ty_closure(_)) => expected.get(),
ty::mk_fn(tcx, (/*bad*/copy *fty)) _ => match expected {
} Some(expected_t) => {
_ => match expected { fcx.type_error_message(expr.span, |actual| {
Some(expected_t) => { fmt!("last argument in `do` call \
fcx.type_error_message(expr.span, |_actual| { has non-closure type: %s",
~"Non-function passed to a `do` \ actual)
function as its last argument, or wrong number \ }, expected_t, None);
of arguments passed to a `do` function" let err_ty = ty::mk_err(tcx);
}, expected_t, None); fcx.write_ty(id, err_ty);
let err_ty = ty::mk_err(tcx); err_ty
fcx.write_ty(id, err_ty); }
err_ty None => {
} fcx.tcx().sess.impossible_case(
None => fcx.tcx().sess.impossible_case(expr.span, expr.span,
~"do body must have expected type") ~"do body must have expected type")
} }
}
}; };
match b.node { match b.node {
ast::expr_fn_block(ref decl, ref body) => { 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); fcx.write_ty(id, typ);
} }
ast::expr_call(f, args, _) => { ast::expr_call(f, args, sugar) => {
bot = check_call(fcx, expr.span, expr.id, f, args); bot = check_call(fcx, expr.span, expr.id, f, args, sugar);
} }
ast::expr_method_call(rcvr, ident, tps, args, _) => { ast::expr_method_call(rcvr, ident, tps, args, sugar) => {
bot = check_method_call(fcx, expr, rcvr, ident, args, tps); bot = check_method_call(fcx, expr, rcvr, ident, args, tps, sugar);
} }
ast::expr_cast(e, t) => { ast::expr_cast(e, t) => {
bot = check_expr(fcx, e); 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)) arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
} }
~"frame_address" => { ~"frame_address" => {
let fty = ty::mk_fn(ccx.tcx, FnTyBase { let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
meta: FnMeta {purity: ast::impure_fn, purity: ast::impure_fn,
proto: ast::ProtoBorrowed, sigil: ast::BorrowedSigil,
onceness: ast::Once, onceness: ast::Once,
region: ty::re_bound(ty::br_anon(0)), region: ty::re_bound(ty::br_anon(0)),
bounds: @~[]}, sig: ty::FnSig {
sig: FnSig { inputs: ~[arg {mode: ast::expl(ast::by_val),
inputs: ~[arg { ty: ty::mk_imm_ptr(
mode: ast::expl(ast::by_val), ccx.tcx,
ty: ty::mk_imm_ptr( ty::mk_mach_uint(ccx.tcx, ast::ty_u8))}],
ccx.tcx, output: ty::mk_nil(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)) (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; return;
} }
}; };
let fty = ty::mk_fn(tcx, FnTyBase { let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
meta: FnMeta {purity: ast::unsafe_fn, purity: ast::unsafe_fn,
proto: ast::ProtoBare, abi: ast::RustAbi,
onceness: ast::Many,
region: ty::re_static,
bounds: @~[]},
sig: FnSig {inputs: inputs, sig: FnSig {inputs: inputs,
output: output} output: output}
}); });

View file

@ -32,7 +32,7 @@ use core::prelude::*;
use middle::freevars::get_freevars; use middle::freevars::get_freevars;
use middle::pat_util::{pat_bindings, pat_is_binding}; use middle::pat_util::{pat_bindings, pat_is_binding};
use middle::ty::{encl_region, re_scope}; 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::{vstore_uniq};
use middle::ty; use middle::ty;
use middle::typeck::check::fn_ctxt; 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 util::ppaux::{note_and_explain_region, ty_to_str};
use core::result; 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::{def_arg, def_binding, def_local, def_self, def_upvar};
use syntax::ast; use syntax::ast;
use syntax::codemap::span; 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, _) => def_self(node_id, _) | def_binding(node_id, _) =>
return encl_region(tcx, node_id), return encl_region(tcx, node_id),
def_upvar(_, subdef, closure_id, body_id) => { def_upvar(_, subdef, closure_id, body_id) => {
match ty_fn_proto(fcx.node_ty(closure_id)) { match ty::ty_closure_sigil(fcx.node_ty(closure_id)) {
ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"), BorrowedSigil => encl_region_of_def(fcx, *subdef),
ProtoBorrowed => encl_region_of_def(fcx, *subdef), ManagedSigil | OwnedSigil => re_scope(body_id)
ProtoBox | ProtoUniq => 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(*) => { ast::expr_fn(*) | ast::expr_fn_block(*) => {
let function_type = rcx.resolve_node_type(expr.id); let function_type = rcx.resolve_node_type(expr.id);
match ty::get(function_type).sty { match ty::get(function_type).sty {
ty::ty_fn(ref fn_ty) => { ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
if fn_ty.meta.proto == ast::ProtoBorrowed { region: region, _}) => {
constrain_free_variables( constrain_free_variables(rcx, region, expr);
rcx, fn_ty.meta.region, expr);
}
} }
_ => () _ => ()
} }

View file

@ -12,7 +12,6 @@
use core::prelude::*; use core::prelude::*;
use middle::ty::{FnTyBase};
use middle::ty; use middle::ty;
use middle::typeck::check::self_info; use middle::typeck::check::self_info;
use middle::typeck::isr_alist; use middle::typeck::isr_alist;
@ -27,22 +26,6 @@ use syntax::print::pprust::{expr_to_str};
// Helper functions related to manipulating region types. // 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( pub fn replace_bound_regions_in_fn_sig(
tcx: ty::ctxt, tcx: ty::ctxt,
isr: isr_alist, isr: isr_alist,

View file

@ -233,7 +233,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
relate_trait_tys(vcx, location_info, trait_ty, ty); relate_trait_tys(vcx, location_info, trait_ty, ty);
if !allow_unsafe && !is_early { if !allow_unsafe && !is_early {
for vec::each(*ty::trait_methods(tcx, did)) |m| { 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( tcx.sess.span_err(
location_info.span, location_info.span,
~"a boxed trait with self types may not be \ ~"a boxed trait with self types may not be \

View file

@ -26,10 +26,10 @@ use middle::resolve::{Impl, MethodInfo};
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get}; use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst}; 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::{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_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_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::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
use middle::ty::{type_is_ty_var}; use middle::ty::{type_is_ty_var};
use middle::ty; 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_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
ty_estr(*) | ty_evec(*) | ty_rec(*) | 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_param(*) | ty_self | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => { ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => {
debug!("(getting base type) no base type; found %?", debug!("(getting base type) no base type; found %?",

View file

@ -33,10 +33,10 @@ are represented as `ty_param()` instances.
use core::prelude::*; use core::prelude::*;
use metadata::csearch; 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::{substs, ty_param_substs_and_ty};
use middle::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::{ast_ty_to_ty};
use middle::typeck::astconv; use middle::typeck::astconv;
use middle::typeck::infer; use middle::typeck::infer;
@ -153,9 +153,10 @@ pub impl @crate_ctxt: ast_conv {
pub fn get_enum_variant_types(ccx: @crate_ctxt, pub fn get_enum_variant_types(ccx: @crate_ctxt,
enum_ty: ty::t, enum_ty: ty::t,
variants: ~[ast::variant], variants: &[ast::variant],
ty_params: ~[ast::ty_param], ty_params: &[ast::ty_param],
rp: Option<ty::region_variance>) { rp: Option<ty::region_variance>)
{
let tcx = ccx.tcx; let tcx = ccx.tcx;
// Create a set of parameter types shared among all the variants. // 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 { match variant.node.kind {
ast::tuple_variant_kind(ref args) if args.len() > 0 => { ast::tuple_variant_kind(ref args) if args.len() > 0 => {
let rs = type_rscope(rp); let rs = type_rscope(rp);
let args = args.map(|va| { let input_tys = args.map(|va| ccx.to_ty(rs, va.ty));
let arg_ty = ccx.to_ty(rs, va.ty); result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_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}
}));
} }
ast::tuple_variant_kind(_) => { ast::tuple_variant_kind(_) => {
result_ty = Some(enum_ty); result_ty = Some(enum_ty);
} }
ast::struct_variant_kind(struct_def) => { ast::struct_variant_kind(struct_def) => {
// XXX: Merge with computation of the the same value below? let tpt = {bounds: ty_param_bounds(ccx, ty_params),
let tpt = { region_param: rp,
bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), ty: enum_ty};
region_param: rp,
ty: enum_ty convert_struct(ccx,
}; rp,
convert_struct( struct_def,
ccx, ty_params.to_vec(),
rp, tpt,
struct_def, variant.node.id);
/*bad*/copy ty_params,
tpt, let input_tys = struct_def.fields.map(
variant.node.id); |f| ty::node_id_to_type(ccx.tcx, f.node.id));
// Compute the ctor arg types from the struct fields result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
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 }}));
} }
ast::enum_variant_kind(ref enum_definition) => { ast::enum_variant_kind(ref enum_definition) => {
get_enum_variant_types(ccx, get_enum_variant_types(ccx, enum_ty,
enum_ty, enum_definition.variants,
/*bad*/copy enum_definition.variants, ty_params, rp);
/*bad*/copy ty_params,
rp);
result_ty = None; result_ty = None;
} }
}; };
@ -225,11 +203,9 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt,
match result_ty { match result_ty {
None => {} None => {}
Some(result_ty) => { Some(result_ty) => {
let tpt = { let tpt = {bounds: ty_param_bounds(ccx, ty_params),
bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), region_param: rp,
region_param: rp, ty: result_ty};
ty: result_ty
};
tcx.tcache.insert(local_def(variant.node.id), tpt); tcx.tcache.insert(local_def(variant.node.id), tpt);
write_ty_to_tcx(tcx, variant.node.id, result_ty); 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, let ty = ty::subst(ccx.tcx,
&substs, &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)]] let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
+ *m.tps); + *m.tps);
ccx.tcx.tcache.insert(local_def(am.id), 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) 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 ty_m = trait_method_to_ty_method(*m);
let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
if ty_m.self_ty.node == ast::sty_static { 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 // that correspond to the parameters we will find on the impl
// - replace self region with a fresh, dummy region // - replace self region with a fresh, dummy region
let impl_fty = { 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)); debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty));
replace_bound_self(tcx, impl_fty, dummy_self_r) 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), self_ty: Some(self_ty),
tps: vec::append(trait_tps, dummy_tps) 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)); debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty));
ty::subst(tcx, &substs, trait_fty) ty::subst(tcx, &substs, trait_fty)
}; };
@ -583,9 +559,9 @@ pub fn convert_methods(ccx: @crate_ctxt,
let tcx = ccx.tcx; let tcx = ccx.tcx;
do vec::map(ms) |m| { 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 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( tcx.tcache.insert(
local_def(m.id), 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"); ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration");
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx, get_enum_variant_types(ccx, tpt.ty, enum_definition.variants,
tpt.ty, *ty_params, rp);
/*bad*/copy (*enum_definition).variants,
/*bad*/copy *ty_params, rp);
} }
ast::item_impl(ref tps, trait_ref, selfty, ref ms) => { 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); let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, selfty); write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id), 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| { do option::iter(&struct_def.dtor) |dtor| {
// Write the dtor type // Write the dtor type
let t_dtor = ty::mk_fn( let t_dtor = ty::mk_bare_fn(
tcx, tcx,
ty_of_fn_decl( astconv::ty_of_bare_fn(
ccx, type_rscope(rp), ast::ProtoBare, ccx, type_rscope(rp),
ast::impure_fn, ast::Many, ast::impure_fn, ast::RustAbi,
/*bounds:*/ @~[], /*opt_region:*/ None, ast_util::dtor_dec()));
ast_util::dtor_dec(), None, dtor.span));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor); write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id), tcx.tcache.insert(local_def(dtor.node.id),
{bounds: tpt.bounds, {bounds: tpt.bounds,
@ -727,25 +700,11 @@ pub fn convert_struct(ccx: @crate_ctxt,
tcx.tcache.insert(local_def(ctor_id), tpt); tcx.tcache.insert(local_def(ctor_id), tpt);
} else if struct_def.fields[0].node.kind == ast::unnamed_field { } else if struct_def.fields[0].node.kind == ast::unnamed_field {
// Tuple-like. // Tuple-like.
let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase { let inputs =
meta: FnMeta { struct_def.fields.map(
purity: ast::pure_fn, |field| ccx.tcx.tcache.get(
proto: ast::ProtoBare, &local_def(field.node.id)).ty);
onceness: ast::Many, let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
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
}
});
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
tcx.tcache.insert(local_def(ctor_id), { tcx.tcache.insert(local_def(ctor_id), {
bounds: tpt.bounds, bounds: tpt.bounds,
@ -770,11 +729,9 @@ pub fn ty_of_method(ccx: @crate_ctxt,
m: @ast::method, m: @ast::method,
rp: Option<ty::region_variance>) -> ty::method { rp: Option<ty::region_variance>) -> ty::method {
{ident: m.ident, {ident: m.ident,
tps: ty_param_bounds(ccx, /*bad*/copy m.tps), tps: ty_param_bounds(ccx, m.tps),
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare, fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity,
m.purity, ast::Many, ast::RustAbi, m.decl),
/*bounds:*/ @~[], /*opt_region:*/ None,
m.decl, None, m.span),
self_ty: m.self_ty.node, self_ty: m.self_ty.node,
vis: m.vis, vis: m.vis,
def_id: local_def(m.id)} def_id: local_def(m.id)}
@ -785,11 +742,9 @@ pub fn ty_of_ty_method(self: @crate_ctxt,
rp: Option<ty::region_variance>, rp: Option<ty::region_variance>,
id: ast::def_id) -> ty::method { id: ast::def_id) -> ty::method {
{ident: m.ident, {ident: m.ident,
tps: ty_param_bounds(self, /*bad*/copy m.tps), tps: ty_param_bounds(self, m.tps),
fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare, fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity,
m.purity, ast::Many, ast::RustAbi, m.decl),
/*bounds:*/ @~[], /*opt_region:*/ None,
m.decl, None, m.span),
// assume public, because this is only invoked on trait methods // assume public, because this is only invoked on trait methods
self_ty: m.self_ty.node, self_ty: m.self_ty.node,
vis: ast::public, vis: ast::public,
@ -844,13 +799,11 @@ pub fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
} }
ast::item_fn(decl, purity, tps, _) => { ast::item_fn(decl, purity, tps, _) => {
let bounds = ty_param_bounds(ccx, tps); let bounds = ty_param_bounds(ccx, tps);
let tofd = ty_of_fn_decl(ccx, empty_rscope, let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity,
ast::ProtoBare, purity, ast::Many, ast::RustAbi, decl);
/*bounds:*/ @~[], /*opt_region:*/ None,
decl, None, it.span);
let tpt = {bounds: bounds, let tpt = {bounds: bounds,
region_param: None, 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", debug!("type of %s (id %d) is %s",
tcx.sess.str_of(it.ident), tcx.sess.str_of(it.ident),
it.id, it.id,
@ -976,7 +929,7 @@ pub fn compute_bounds(ccx: @crate_ctxt,
} }
pub fn ty_param_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| { @do params.map |param| {
match ccx.tcx.ty_param_bounds.find(&param.id) { match ccx.tcx.ty_param_bounds.find(&param.id) {
Some(bs) => bs, 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 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 output_ty = ast_ty_to_ty(ccx, rb, decl.output);
let t_fn = ty::mk_fn(ccx.tcx, FnTyBase { let t_fn = ty::mk_bare_fn(
meta: FnMeta {purity: ast::unsafe_fn, ccx.tcx,
onceness: ast::Many, ty::BareFnTy {
proto: ast::ProtoBare, abi: ast::RustAbi,
bounds: @~[], purity: ast::unsafe_fn,
region: ty::re_static}, sig: ty::FnSig {inputs: input_tys, output: output_ty}
sig: FnSig {inputs: input_tys, });
output: output_ty}
});
let tpt = {bounds: bounds, region_param: None, ty: t_fn}; let tpt = {bounds: bounds, region_param: None, ty: t_fn};
ccx.tcx.tcache.insert(def_id, tpt); ccx.tcx.tcache.insert(def_id, tpt);
return 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]} { -> {bounds: @~[ty::param_bounds], params: ~[ty::t]} {
let mut i = 0u; let mut i = 0u;
// XXX: Bad copy. let bounds = ty_param_bounds(ccx, atps);
let bounds = ty_param_bounds(ccx, copy atps);
{bounds: bounds, {bounds: bounds,
params: vec::map(atps, |atp| { params: vec::map(atps, |atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));

View file

@ -69,7 +69,7 @@ use core::prelude::*;
use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn}; use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn};
use middle::ty::{AutoAdjustment, AutoRef}; use middle::ty::{AutoAdjustment, AutoRef};
use middle::ty::{vstore_slice, vstore_box, vstore_uniq, vstore_fixed}; 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::ty;
use middle::typeck::infer::{CoerceResult, resolve_type}; use middle::typeck::infer::{CoerceResult, resolve_type};
use middle::typeck::infer::combine::CombineFields; 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| { return do self.unpack_actual_value(a) |sty_a| {
self.coerce_borrowed_fn(a, sty_a, b) self.coerce_borrowed_fn(a, sty_a, b)
}; };
@ -134,7 +134,7 @@ impl Coerce {
do self.unpack_actual_value(a) |sty_a| { do self.unpack_actual_value(a) |sty_a| {
match *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. // Bare functions are coercable to any closure type.
// //
// FIXME(#3320) this should go away and be // FIXME(#3320) this should go away and be
@ -289,9 +289,9 @@ impl Coerce {
b.inf_str(self.infcx)); b.inf_str(self.infcx));
let fn_ty = match *sty_a { let fn_ty = match *sty_a {
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBox => {f} ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil => copy *f,
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoUniq => {f} ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => copy *f,
ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBare => { ty::ty_bare_fn(ref f) => {
return self.coerce_from_bare_fn(a, f, b); 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 r_borrow = self.infcx.next_region_var_nb(self.span);
let meta = FnMeta {proto: ast::ProtoBorrowed, let a_borrowed = ty::mk_closure(
region: r_borrow, self.infcx.tcx,
..fn_ty.meta}; ty::ClosureTy {
let a_borrowed = ty::mk_fn(self.infcx.tcx, sigil: ast::BorrowedSigil,
FnTyBase {meta: meta, region: r_borrow,
sig: copy fn_ty.sig}); ..fn_ty
});
if_ok!(self.subtype(a_borrowed, b)); if_ok!(self.subtype(a_borrowed, b));
Ok(Some(@AutoAdjustment { Ok(Some(@AutoAdjustment {
@ -320,7 +321,7 @@ impl Coerce {
fn coerce_from_bare_fn(&self, fn coerce_from_bare_fn(&self,
a: ty::t, a: ty::t,
fn_ty_a: &ty::FnTy, fn_ty_a: &ty::BareFnTy,
b: ty::t) -> CoerceResult b: ty::t) -> CoerceResult
{ {
do self.unpack_actual_value(b) |sty_b| { do self.unpack_actual_value(b) |sty_b| {
@ -330,7 +331,7 @@ impl Coerce {
fn coerce_from_bare_fn_post_unpack(&self, fn coerce_from_bare_fn_post_unpack(&self,
a: ty::t, a: ty::t,
fn_ty_a: &ty::FnTy, fn_ty_a: &ty::BareFnTy,
b: ty::t, b: ty::t,
sty_b: &ty::sty) -> CoerceResult sty_b: &ty::sty) -> CoerceResult
{ {
@ -338,18 +339,18 @@ impl Coerce {
a.inf_str(self.infcx), b.inf_str(self.infcx)); a.inf_str(self.infcx), b.inf_str(self.infcx));
let fn_ty_b = match *sty_b { 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); return self.subtype(a, b);
} }
}; };
// for now, bare fn and closures have the same // for now, bare fn and closures have the same
// representation // representation
let a_adapted = ty::mk_fn(self.infcx.tcx, let a_closure = ty::mk_closure(
FnTyBase {meta: copy fn_ty_b.meta, self.infcx.tcx,
sig: copy fn_ty_a.sig}); ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b});
self.subtype(a_adapted, b) self.subtype(a_closure, b)
} }
fn coerce_unsafe_ptr(&self, fn coerce_unsafe_ptr(&self,

Some files were not shown because too many files have changed in this diff Show more