]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #26725 - tshepang:patch-2, r=bluss
authorbors <bors@rust-lang.org>
Thu, 2 Jul 2015 21:56:28 +0000 (21:56 +0000)
committerbors <bors@rust-lang.org>
Thu, 2 Jul 2015 21:56:28 +0000 (21:56 +0000)
113 files changed:
configure
mk/cfg/x86_64-unknown-netbsd.mk [new file with mode: 0644]
src/compiletest/util.rs
src/doc/reference.md
src/etc/snapshot.py
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcore/any.rs
src/liblibc/lib.rs
src/librustc/ast_map/mod.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/middle/astencode.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_rvalues.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/implicator.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/util/common.rs
src/librustc/util/ppaux.rs
src/librustc_back/arm.rs
src/librustc_back/mips.rs
src/librustc_back/mipsel.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/netbsd_base.rs [new file with mode: 0644]
src/librustc_back/target/x86_64_unknown_netbsd.rs [new file with mode: 0644]
src/librustc_back/x86.rs
src/librustc_back/x86_64.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/attributes.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/debuginfo/gdb.rs
src/librustc_trans/trans/debuginfo/metadata.rs
src/librustc_trans/trans/debuginfo/mod.rs
src/librustc_trans/trans/debuginfo/namespace.rs
src/librustc_trans/trans/debuginfo/type_names.rs
src/librustc_trans/trans/declare.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_trans/trans/type_of.rs
src/librustc_typeck/check/assoc.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/flock.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/os/mod.rs
src/libstd/os/netbsd/mod.rs [new file with mode: 0644]
src/libstd/os/netbsd/raw.rs [new file with mode: 0644]
src/libstd/rt/args.rs
src/libstd/rt/libunwind.rs
src/libstd/rtdeps.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sys/common/stack.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/sync.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/thread_local.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/net.rs
src/libstd/thread/scoped_tls.rs
src/libsyntax/abi.rs
src/test/compile-fail/issue-8640.rs [new file with mode: 0644]
src/test/parse-fail/issue-5806.rs
src/test/run-pass/dst-coerce-rc.rs
src/test/run-pass/intrinsic-alignment.rs
src/test/run-pass/rec-align-u64.rs
src/test/run-pass/tcp-stress.rs
src/test/run-pass/x86stdcall.rs

index 5d4a017b6fbfaa8f9624dd5f1c76dc7b975b7abb..1d3611f88f0a9bf77e400359c02676b85f1541e4 100755 (executable)
--- a/configure
+++ b/configure
@@ -405,6 +405,10 @@ case $CFG_OSTYPE in
         CFG_OSTYPE=unknown-openbsd
        ;;
 
+    NetBSD)
+           CFG_OSTYPE=unknown-netbsd
+           ;;
+
     Darwin)
         CFG_OSTYPE=apple-darwin
         ;;
diff --git a/mk/cfg/x86_64-unknown-netbsd.mk b/mk/cfg/x86_64-unknown-netbsd.mk
new file mode 100644 (file)
index 0000000..401b0fb
--- /dev/null
@@ -0,0 +1,22 @@
+# x86_64-unknown-netbsd configuration
+CC_x86_64-unknown-netbsd=$(CC)
+CXX_x86_64-unknown-netbsd=$(CXX)
+CPP_x86_64-unknown-netbsd=$(CPP)
+AR_x86_64-unknown-netbsd=$(AR)
+CFG_LIB_NAME_x86_64-unknown-netbsd=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-netbsd=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread  -lrt
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
+CFG_INSTALL_NAME_x86_64-unknown-netbsd =
+CFG_EXE_SUFFIX_x86_64-unknown-netbsd :=
+CFG_WINDOWSY_x86_64-unknown-netbsd :=
+CFG_UNIXY_x86_64-unknown-netbsd := 1
+CFG_LDPATH_x86_64-unknown-netbsd :=
+CFG_RUN_x86_64-unknown-netbsd=$(2)
+CFG_RUN_TARG_x86_64-unknown-netbsd=$(call CFG_RUN_x86_64-unknown-netbsd,,$(2))
+CFG_GNU_TRIPLE_x86_64-unknown-netbsd := x86_64-unknown-netbsd
index 184d62db45114682d21ffe8303424c89e7f5405e..13d6c029ff58458900dc57c34fc02fba75dab871 100644 (file)
@@ -21,6 +21,7 @@
     ("ios", "ios"),
     ("linux", "linux"),
     ("mingw32", "windows"),
+    ("netbsd", "netbsd"),
     ("openbsd", "openbsd"),
     ("win32", "windows"),
     ("windows", "windows"),
index 7e28651c6aafb1246283932cdb92e9ce83132595..650e1d5541ecf173ab20bcfd48549ace5221fff4 100644 (file)
@@ -2023,7 +2023,7 @@ The following configurations must be defined by the implementation:
   as a configuration itself, like `unix` or `windows`.
 * `target_os = "..."`. Operating system of the target, examples include
   `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
-  `"bitrig"` or `"openbsd"`.
+  `"bitrig"` , `"openbsd"` or `"netbsd"`.
 * `target_pointer_width = "..."`. Target pointer width in bits. This is set
   to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
   64-bit pointers.
index 0349ccf9b66408bf80833afe3d4b96d68dd6ceef..6d62a45c703a23561379d40467cb8337aa6efe40 100644 (file)
@@ -41,13 +41,14 @@ download_dir_base = "dl"
 download_unpack_base = os.path.join(download_dir_base, "unpack")
 
 snapshot_files = {
+        "bitrig": ["bin/rustc"],
+        "dragonfly": ["bin/rustc"],
+        "freebsd": ["bin/rustc"],
         "linux": ["bin/rustc"],
         "macos": ["bin/rustc"],
-        "winnt": ["bin/rustc.exe"],
-        "freebsd": ["bin/rustc"],
-        "dragonfly": ["bin/rustc"],
-        "bitrig": ["bin/rustc"],
+        "netbsd": ["bin/rustc"],
         "openbsd": ["bin/rustc"],
+        "winnt": ["bin/rustc.exe"],
         }
 
 winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"]
@@ -103,6 +104,8 @@ def get_kernel(triple):
         return "dragonfly"
     if os_name == "bitrig":
         return "bitrig"
+    if os_name == "netbsd":
+        return "netbsd"
     if os_name == "openbsd":
         return "openbsd"
     return "linux"
index dd9c1d1fd188556cc89a78808411b9c89ef8dfd6..c84649f92e7ff6b18b22d504732743b9f58b0237 100644 (file)
@@ -145,6 +145,8 @@ pub struct Weak<T: ?Sized> {
 unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
 unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
 
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
index 3dfafd0a378b90bef31771c17dbb43d28f069b78..d461eeea0b7ebbef617707c72a5f5d86b24dcc1e 100644 (file)
@@ -734,6 +734,8 @@ pub struct Weak<T: ?Sized> {
 impl<T: ?Sized> !marker::Send for Weak<T> {}
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
+impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+
 #[unstable(feature = "rc_weak",
            reason = "Weak pointers may not belong in this module.")]
 impl<T: ?Sized> Weak<T> {
index 38221f76c4de5a0a3a19e5357cb2ae53d2a57df1..e7b39c11f4c1bb98ae30a29310485f8c4d8fcaae 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Traits for dynamic typing of any `'static` type (through runtime reflection)
-//!
 //! This module implements the `Any` trait, which enables dynamic typing
 //! of any `'static` type through runtime reflection.
 //!
index 6e01796ad82279b9f1f6305e4a04e65858700edc..f66811e561adf359d0e19ef75314a90fd6a156c3 100644 (file)
@@ -1322,7 +1322,7 @@ pub mod extra {
         }
     }
 
-    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os ="openbsd"))]
     pub mod os {
         pub mod common {
             pub mod posix01 {
@@ -1351,7 +1351,7 @@ pub mod posix01 {
                     pub __unused7: *mut c_void,
                 }
 
-                #[cfg(target_os = "openbsd")]
+                #[cfg(any(target_os = "netbsd", target_os="openbsd"))]
                 #[repr(C)]
                 #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  c_int,
@@ -4323,7 +4323,7 @@ pub mod sysconf {
         }
     }
 
-    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
@@ -5568,6 +5568,7 @@ pub mod mman {
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd",
               target_os = "nacl"))]
     pub mod posix88 {
@@ -5584,6 +5585,7 @@ pub mod stat_ {
                           target_os = "freebsd",
                           target_os = "dragonfly",
                           target_os = "bitrig",
+                          target_os = "netbsd",
                           target_os = "openbsd",
                           target_os = "android",
                           target_os = "ios",
@@ -5602,6 +5604,7 @@ pub mod stat_ {
                           target_os = "freebsd",
                           target_os = "dragonfly",
                           target_os = "bitrig",
+                          target_os = "netbsd",
                           target_os = "openbsd",
                           target_os = "android",
                           target_os = "ios",
@@ -5889,6 +5892,7 @@ pub mod net {
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd",
               target_os = "nacl"))]
     pub mod posix01 {
@@ -5901,6 +5905,7 @@ pub mod stat_ {
                           target_os = "freebsd",
                           target_os = "dragonfly",
                           target_os = "bitrig",
+                          target_os = "netbsd",
                           target_os = "openbsd",
                           target_os = "android",
                           target_os = "ios",
@@ -6019,16 +6024,17 @@ pub mod net {
     }
 
 
-    #[cfg(any(target_os = "windows",
-              target_os = "linux",
-              target_os = "android",
-              target_os = "macos",
+    #[cfg(any(target_os = "android",
+              target_os = "bitrig",
+              target_os = "dragonfly",
               target_os = "ios",
               target_os = "freebsd",
-              target_os = "dragonfly",
-              target_os = "bitrig",
+              target_os = "linux",
+              target_os = "macos",
+              target_os = "nacl",
+              target_os = "netbsd",
               target_os = "openbsd",
-              target_os = "nacl"))]
+              target_os = "windows"))]
     pub mod posix08 {
         pub mod unistd {
         }
@@ -6115,6 +6121,7 @@ pub fn sendto(socket: SOCKET, buf: *const c_void, len: c_int,
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     pub mod bsd44 {
         use types::common::c95::{c_void};
@@ -6192,6 +6199,7 @@ pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32)
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     pub mod extra {
     }
index 06d87f5333ad3fddf2549ddf6fa5b938655ffc54..3205141e604c2769d9b4721822d8fb21f4ffbfc2 100644 (file)
@@ -121,7 +121,7 @@ pub enum Node<'ast> {
     NodeLifetime(&'ast Lifetime),
 }
 
-/// Represents an entry and its parent Node ID
+/// Represents an entry and its parent NodeID.
 /// The odd layout is to bring down the total size.
 #[derive(Copy, Debug)]
 enum MapEntry<'ast> {
@@ -179,7 +179,7 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
         }
     }
 
-    fn parent(self) -> Option<NodeId> {
+    fn parent_node(self) -> Option<NodeId> {
         Some(match self {
             EntryItem(id, _) => id,
             EntryForeignItem(id, _) => id,
@@ -283,10 +283,88 @@ pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
         self.find_entry(id).and_then(|x| x.to_node())
     }
 
-    /// Retrieve the parent NodeId for `id`, or `id` itself if no
-    /// parent is registered in this map.
+    /// Similar to get_parent, returns the parent node id or id if there is no
+    /// parent.
+    /// This function returns the immediate parent in the AST, whereas get_parent
+    /// returns the enclosing item. Note that this might not be the actual parent
+    /// node in the AST - some kinds of nodes are not in the map and these will
+    /// never appear as the parent_node. So you can always walk the parent_nodes
+    /// from a node to the root of the ast (unless you get the same id back here
+    /// that can happen if the id is not in the map itself or is just weird).
+    pub fn get_parent_node(&self, id: NodeId) -> NodeId {
+        self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
+    }
+
+    /// If there is some error when walking the parents (e.g., a node does not
+    /// have a parent in the map or a node can't be found), then we return the
+    /// last good node id we found. Note that reaching the crate root (id == 0),
+    /// is not an error, since items in the crate module have the crate root as
+    /// parent.
+    fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
+        where F: Fn(&Node<'ast>) -> bool
+    {
+        let mut id = start_id;
+        loop {
+            let parent_node = self.get_parent_node(id);
+            if parent_node == 0 {
+                return Ok(0);
+            }
+            if parent_node == id {
+                return Err(id);
+            }
+
+            let node = self.find_entry(parent_node);
+            if node.is_none() {
+                return Err(id);
+            }
+            let node = node.unwrap().to_node();
+            match node {
+                Some(ref node) => {
+                    if found(node) {
+                        return Ok(parent_node);
+                    }
+                }
+                None => {
+                    return Err(parent_node);
+                }
+            }
+            id = parent_node;
+        }
+    }
+
+    /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
+    /// parent item is in this map. The "parent item" is the closest parent node
+    /// in the AST which is recorded by the map and is an item, either an item
+    /// in a module, trait, or impl.
     pub fn get_parent(&self, id: NodeId) -> NodeId {
-        self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
+        match self.walk_parent_nodes(id, |node| match *node {
+            NodeItem(_) |
+            NodeForeignItem(_) |
+            NodeTraitItem(_) |
+            NodeImplItem(_) => true,
+            _ => false,
+        }) {
+            Ok(id) => id,
+            Err(id) => id,
+        }
+    }
+
+    /// Returns the nearest enclosing scope. A scope is an item or block.
+    /// FIXME it is not clear to me that all items qualify as scopes - statics
+    /// and associated types probably shouldn't, for example. Behaviour in this
+    /// regard should be expected to be highly unstable.
+    pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
+        match self.walk_parent_nodes(id, |node| match *node {
+            NodeItem(_) |
+            NodeForeignItem(_) |
+            NodeTraitItem(_) |
+            NodeImplItem(_) |
+            NodeBlock(_) => true,
+            _ => false,
+        }) {
+            Ok(id) => Some(id),
+            Err(_) => None,
+        }
     }
 
     pub fn get_parent_did(&self, id: NodeId) -> DefId {
@@ -590,15 +668,15 @@ fn next(&mut self) -> Option<NodeId> {
                 return None;
             }
             self.idx += 1;
-            let (p, name) = match self.map.find_entry(idx) {
-                Some(EntryItem(p, n))       => (p, n.name()),
-                Some(EntryForeignItem(p, n))=> (p, n.name()),
-                Some(EntryTraitItem(p, n))  => (p, n.name()),
-                Some(EntryImplItem(p, n))   => (p, n.name()),
-                Some(EntryVariant(p, n))    => (p, n.name()),
+            let name = match self.map.find_entry(idx) {
+                Some(EntryItem(_, n))       => n.name(),
+                Some(EntryForeignItem(_, n))=> n.name(),
+                Some(EntryTraitItem(_, n))  => n.name(),
+                Some(EntryImplItem(_, n))   => n.name(),
+                Some(EntryVariant(_, n))    => n.name(),
                 _ => continue,
             };
-            if self.matches_names(p, name) {
+            if self.matches_names(self.map.get_parent(idx), name) {
                 return Some(idx)
             }
         }
@@ -647,8 +725,7 @@ fn new_span(&mut self, span: Span) -> Span {
 /// A Visitor that walks over an AST and collects Node's into an AST Map.
 struct NodeCollector<'ast> {
     map: Vec<MapEntry<'ast>>,
-    /// The node in which we are currently mapping (an item or a method).
-    parent: NodeId
+    parent_node: NodeId,
 }
 
 impl<'ast> NodeCollector<'ast> {
@@ -662,7 +739,7 @@ fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
     }
 
     fn insert(&mut self, id: NodeId, node: Node<'ast>) {
-        let entry = MapEntry::from_node(self.parent, node);
+        let entry = MapEntry::from_node(self.parent_node, node);
         self.insert_entry(id, entry);
     }
 
@@ -676,8 +753,10 @@ fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     fn visit_item(&mut self, i: &'ast Item) {
         self.insert(i.id, NodeItem(i));
-        let parent = self.parent;
-        self.parent = i.id;
+
+        let parent_node = self.parent_node;
+        self.parent_node = i.id;
+
         match i.node {
             ItemImpl(_, _, _, _, _, ref impl_items) => {
                 for ii in impl_items {
@@ -727,21 +806,23 @@ fn visit_item(&mut self, i: &'ast Item) {
             _ => {}
         }
         visit::walk_item(self, i);
-        self.parent = parent;
+        self.parent_node = parent_node;
     }
 
     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let parent = self.parent;
-        self.parent = ti.id;
+        let parent_node = self.parent_node;
+        self.parent_node = ti.id;
         visit::walk_trait_item(self, ti);
-        self.parent = parent;
+        self.parent_node = parent_node;
     }
 
     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let parent = self.parent;
-        self.parent = ii.id;
+        let parent_node = self.parent_node;
+        self.parent_node = ii.id;
+
         visit::walk_impl_item(self, ii);
-        self.parent = parent;
+
+        self.parent_node = parent_node;
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
@@ -750,26 +831,42 @@ fn visit_pat(&mut self, pat: &'ast Pat) {
             PatIdent(..) => NodeLocal(pat),
             _ => NodePat(pat)
         });
+
+        let parent_node = self.parent_node;
+        self.parent_node = pat.id;
         visit::walk_pat(self, pat);
+        self.parent_node = parent_node;
     }
 
     fn visit_expr(&mut self, expr: &'ast Expr) {
         self.insert(expr.id, NodeExpr(expr));
+        let parent_node = self.parent_node;
+        self.parent_node = expr.id;
         visit::walk_expr(self, expr);
+        self.parent_node = parent_node;
     }
 
     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
+        let id = ast_util::stmt_id(stmt);
+        self.insert(id, NodeStmt(stmt));
+        let parent_node = self.parent_node;
+        self.parent_node = id;
         visit::walk_stmt(self, stmt);
+        self.parent_node = parent_node;
     }
 
     fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: &'ast Block, s: Span, _: NodeId) {
+                b: &'ast Block, s: Span, id: NodeId) {
+        let parent_node = self.parent_node;
+        self.parent_node = id;
         self.visit_fn_decl(fd);
         visit::walk_fn(self, fk, fd, b, s);
+        self.parent_node = parent_node;
     }
 
     fn visit_ty(&mut self, ty: &'ast Ty) {
+        let parent_node = self.parent_node;
+        self.parent_node = ty.id;
         match ty.node {
             TyBareFn(ref fd) => {
                 self.visit_fn_decl(&*fd.decl);
@@ -777,11 +874,15 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
             _ => {}
         }
         visit::walk_ty(self, ty);
+        self.parent_node = parent_node;
     }
 
     fn visit_block(&mut self, block: &'ast Block) {
         self.insert(block.id, NodeBlock(block));
+        let parent_node = self.parent_node;
+        self.parent_node = block.id;
         visit::walk_block(self, block);
+        self.parent_node = parent_node;
     }
 
     fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
@@ -809,7 +910,7 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map
 
     let mut collector = NodeCollector {
         map: vec![],
-        parent: CRATE_NODE_ID
+        parent_node: CRATE_NODE_ID,
     };
     collector.insert_entry(CRATE_NODE_ID, RootCrate);
     visit::walk_crate(&mut collector, &forest.krate);
@@ -864,11 +965,11 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
         ii: ii
     });
 
+    let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
     let mut collector = NodeCollector {
         map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
-        parent: fld.new_id(DUMMY_NODE_ID)
+        parent_node: ii_parent_id,
     };
-    let ii_parent_id = collector.parent;
     collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
     visit::walk_inlined_item(&mut collector, &ii_parent.ii);
 
index 68ca0eac37a5dbcf556242416262a8914937fdb1..04725916e7a0fee08abb676da347539e895a1ca4 100644 (file)
@@ -602,15 +602,47 @@ fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
 
 E0267: r##"
 This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Break and continue can be used as normal inside
-closures as long as they are also contained within a loop. To halt the execution
-of a closure you should instead use a return statement.
+closure but outside of any loop. Erroneous code example:
+
+```
+let w = || { break; }; // error: `break` inside of a closure
+```
+
+`break` and `continue` keywords can be used as normal inside closures as long as
+they are also contained within a loop. To halt the execution of a closure you
+should instead use a return statement. Example:
+
+```
+let w = || {
+    for _ in 0..10 {
+        break;
+    }
+};
+
+w();
+```
 "##,
 
 E0268: r##"
 This error indicates the use of a loop keyword (`break` or `continue`) outside
 of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken.
+be taken. Erroneous code example:
+
+```
+fn some_func() {
+    break; // error: `break` outside of loop
+}
+```
+
+Please verify that you are using `break` and `continue` only in loops. Example:
+
+```
+fn some_func() {
+    for _ in 0..10 {
+        break; // ok!
+    }
+}
+```
 "##,
 
 E0271: r##"
@@ -749,6 +781,54 @@ fn foo<T>(t: T) where T: Trait<AssociatedType = &'static str> {
 ```
 "##,
 
+E0277: r##"
+You tried to use a type which doesn't implement some trait in a place which
+expected that trait. Erroneous code example:
+
+```
+// here we declare the Foo trait with a bar method
+trait Foo {
+    fn bar(&self);
+}
+
+// we now declare a function which takes an object with Foo trait implemented
+// as parameter
+fn some_func<T: Foo>(foo: T) {
+    foo.bar();
+}
+
+fn main() {
+    // we now call the method with the i32 type, which doesn't implement
+    // the Foo trait
+    some_func(5i32); // error: the trait `Foo` is not implemented for the
+                     //     type `i32`
+}
+```
+
+In order to fix this error, verify that the type you're using does implement
+the trait. Example:
+
+```
+trait Foo {
+    fn bar(&self);
+}
+
+fn some_func<T: Foo>(foo: T) {
+    foo.bar(); // we can now use this method since i32 implements the
+               // Foo trait
+}
+
+// we implement the trait on the i32 type
+impl Foo for i32 {
+    fn bar(&self) {}
+}
+
+fn main() {
+    some_func(5i32); // ok!
+}
+```
+"##,
+
 E0282: r##"
 This error indicates that type inference did not result in one unique possible
 type, and extra information is required. In most cases this can be provided
@@ -1103,7 +1183,6 @@ fn bar(&self) -> i32 { self.0 }
     E0274, // rustc_on_unimplemented must have a value
     E0275, // overflow evaluating requirement
     E0276, // requirement appears on impl method but not on corresponding trait method
-    E0277, // trait is not implemented for type
     E0278, // requirement is not satisfied
     E0279, // requirement is not satisfied
     E0280, // requirement is not satisfied
index 2cec42b76bce3359e8f772ea1bda80a492cbabd3..e4e7459f8c60581557b7285f14a241acba3684a7 100644 (file)
@@ -62,6 +62,7 @@
 #![feature(vec_push_all)]
 #![feature(wrapping)]
 #![feature(cell_extras)]
+#![feature(page_size)]
 #![cfg_attr(test, feature(test))]
 
 #![allow(trivial_casts)]
index d2c79e1d820bf98751cb81b562eda485f0f5006d..03e5ac5c3811e36d37267026c6264bc3e417f943 100644 (file)
@@ -26,7 +26,6 @@
 use metadata::tyencode;
 use middle::cast;
 use middle::check_const::ConstQualif;
-use middle::mem_categorization::Typer;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst;
 use middle::subst::VecPerParamSpace;
@@ -1656,7 +1655,7 @@ fn decode_side_tables(dcx: &DecodeContext,
                     c::tag_table_tcache => {
                         let type_scheme = val_dsr.read_type_scheme(dcx);
                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
-                        dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme);
+                        dcx.tcx.register_item_type(lid, type_scheme);
                     }
                     c::tag_table_param_defs => {
                         let bounds = val_dsr.read_type_param_def(dcx);
index 8bbb6ae757fc1e1f0c63cd31dc9e7e791b79809d..19b688e5ccfb48092a0f50de371efea8cb2dbe71 100644 (file)
@@ -110,14 +110,16 @@ fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
     }
 
     fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
-        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'tcx,
-                                    ty::ParameterEnvironment<'a, 'tcx>>) -> R,
+        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
     {
         let param_env = match item_id {
             Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
             None => self.tcx.empty_parameter_environment()
         };
-        f(&mut euv::ExprUseVisitor::new(self, &param_env))
+
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), false);
+
+        f(&mut euv::ExprUseVisitor::new(self, &infcx))
     }
 
     fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
@@ -283,11 +285,11 @@ fn check_static_mut_type(&self, e: &ast::Expr) {
 
     fn check_static_type(&self, e: &ast::Expr) {
         let ty = self.tcx.node_id_to_type(e.id);
-        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
-        let mut fulfill_cx = traits::FulfillmentContext::new(false);
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
         let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+        let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
         fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
-        match fulfill_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+        match fulfill_cx.select_all_or_error(&infcx) {
             Ok(()) => { },
             Err(ref errors) => {
                 traits::report_fulfillment_errors(&infcx, errors);
index f61884e213666046ba54f91ec1897c1543a22c49..a303c49bf8db7d08565aac54d07f9cd44ab4b520 100644 (file)
@@ -20,7 +20,8 @@
 use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
 use middle::expr_use_visitor::WriteAndRead;
 use middle::expr_use_visitor as euv;
-use middle::mem_categorization::{cmt, Typer};
+use middle::infer;
+use middle::mem_categorization::{cmt};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
@@ -1111,7 +1112,12 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                 match p.node {
                     ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
                         let pat_ty = tcx.node_id_to_type(p.id);
-                        if cx.param_env.type_moves_by_default(pat_ty, pat.span) {
+                        //FIXME: (@jroesch) this code should be floated up as well
+                        let infcx = infer::new_infer_ctxt(cx.tcx,
+                                                          &cx.tcx.tables,
+                                                          Some(cx.param_env.clone()),
+                                                          false);
+                        if infcx.type_moves_by_default(pat_ty, pat.span) {
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
@@ -1139,8 +1145,13 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
     let mut checker = MutationChecker {
         cx: cx,
     };
-    let mut visitor = ExprUseVisitor::new(&mut checker,
-                                          &checker.cx.param_env);
+
+    let infcx = infer::new_infer_ctxt(cx.tcx,
+                                      &cx.tcx.tables,
+                                      Some(checker.cx.param_env.clone()),
+                                      false);
+
+    let mut visitor = ExprUseVisitor::new(&mut checker, &infcx);
     visitor.walk_expr(guard);
 }
 
index 1489e946fe2ce57f090612399c3c9114ad42ab4c..c9017432473a7b5c8e100eec0fbd53583eefbb18 100644 (file)
@@ -12,6 +12,7 @@
 // is the public starting point.
 
 use middle::expr_use_visitor as euv;
+use middle::infer;
 use middle::mem_categorization as mc;
 use middle::ty::ParameterEnvironment;
 use middle::ty;
@@ -38,9 +39,14 @@ fn visit_fn(&mut self,
                 s: Span,
                 fn_id: ast::NodeId) {
         {
+            // FIXME (@jroesch) change this to be an inference context
             let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+            let infcx = infer::new_infer_ctxt(self.tcx,
+                                              &self.tcx.tables,
+                                              Some(param_env.clone()),
+                                              false);
             let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
-            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &param_env);
+            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
             euv.walk_fn(fd, b);
         }
         visit::walk_fn(self, fk, fd, b, s)
index a6b7d7f832a3cce31680729552231baafebbf60c..7d54b8c284f1ff8137e4c186d923b6ac52712e47 100644 (file)
@@ -1031,9 +1031,9 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                                               substs: trait_substs });
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
 
-    let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+    let mut selcx = traits::SelectionContext::new(&infcx);
     let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
                                              trait_ref.to_poly_trait_predicate());
     let selection = match selcx.select(&obligation) {
index 25728c50c61f4a6784ae7fccd8d52aa3c7634970..3edf0490214b9ff41a8eff1dff7c3a0da02f5125 100644 (file)
@@ -21,8 +21,8 @@
 use self::OverloadedCallType::*;
 
 use middle::{def, region, pat_util};
+use middle::infer;
 use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
 use middle::ty::{self};
 use middle::ty::{MethodCall, MethodObject, MethodTraitObject};
 use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
@@ -291,9 +291,9 @@ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
 // supplies types from the tree. After type checking is complete, you
 // can just use the tcx as the typer.
 
-pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> {
-    typer: &'t TYPER,
-    mc: mc::MemCategorizationContext<'t,TYPER>,
+pub struct ExprUseVisitor<'d,'t,'a: 't, 'tcx:'a> {
+    typer: &'t infer::InferCtxt<'a, 'tcx>,
+    mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
     delegate: &'d mut (Delegate<'tcx>+'d),
 }
 
@@ -319,10 +319,10 @@ enum PassArgs {
     ByRef,
 }
 
-impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     pub fn new(delegate: &'d mut Delegate<'tcx>,
-               typer: &'t TYPER)
-               -> ExprUseVisitor<'d,'t,'tcx,TYPER> {
+               typer: &'t infer::InferCtxt<'a, 'tcx>)
+               -> ExprUseVisitor<'d,'t,'a, 'tcx> {
         ExprUseVisitor {
             typer: typer,
             mc: mc::MemCategorizationContext::new(typer),
@@ -355,7 +355,7 @@ fn walk_arg_patterns(&mut self,
     }
 
     fn tcx(&self) -> &'t ty::ctxt<'tcx> {
-        self.typer.tcx()
+        self.typer.tcx
     }
 
     fn delegate_consume(&mut self,
@@ -690,7 +690,7 @@ fn walk_local(&mut self, local: &ast::Local) {
         match local.init {
             None => {
                 let delegate = &mut self.delegate;
-                pat_util::pat_bindings(&self.typer.tcx().def_map, &*local.pat,
+                pat_util::pat_bindings(&self.typer.tcx.def_map, &*local.pat,
                                        |_, id, span, _| {
                     delegate.decl_without_init(id, span);
                 })
@@ -1052,7 +1052,7 @@ fn walk_pat(&mut self,
         let delegate = &mut self.delegate;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
             if pat_util::pat_is_binding(def_map, pat) {
-                let tcx = typer.tcx();
+                let tcx = typer.tcx;
 
                 debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
                        cmt_pat,
@@ -1139,7 +1139,7 @@ fn walk_pat(&mut self,
         // the leaves of the pattern tree structure.
         return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
             let def_map = def_map.borrow();
-            let tcx = typer.tcx();
+            let tcx = typer.tcx;
 
             match pat.node {
                 ast::PatEnum(_, _) | ast::PatQPath(..) |
@@ -1278,7 +1278,7 @@ fn cat_captured_var(&mut self,
     }
 }
 
-fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
+fn copy_or_move<'a, 'tcx>(typer: &infer::InferCtxt<'a, 'tcx>,
                       cmt: &mc::cmt<'tcx>,
                       move_reason: MoveReason)
                       -> ConsumeMode
index d5fa885b16ab50cf08a08c41de13218967fe60cb..3e097578857e94d4336079f378809762e1322eb2 100644 (file)
@@ -34,7 +34,6 @@ pub enum Implication<'tcx> {
 
 struct Implicator<'a, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a,'tcx>,
-    closure_typer: &'a (ty::ClosureTyper<'tcx>+'a),
     body_id: ast::NodeId,
     stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
     span: Span,
@@ -46,7 +45,6 @@ struct Implicator<'a, 'tcx: 'a> {
 /// appear in a context with lifetime `outer_region`
 pub fn implications<'a,'tcx>(
     infcx: &'a InferCtxt<'a,'tcx>,
-    closure_typer: &ty::ClosureTyper<'tcx>,
     body_id: ast::NodeId,
     ty: Ty<'tcx>,
     outer_region: ty::Region,
@@ -60,8 +58,7 @@ pub fn implications<'a,'tcx>(
 
     let mut stack = Vec::new();
     stack.push((outer_region, None));
-    let mut wf = Implicator { closure_typer: closure_typer,
-                              infcx: infcx,
+    let mut wf = Implicator { infcx: infcx,
                               body_id: body_id,
                               span: span,
                               stack: stack,
@@ -404,7 +401,6 @@ fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
     {
         let value =
             traits::fully_normalize(self.infcx,
-                                    self.closure_typer,
                                     traits::ObligationCause::misc(self.span, self.body_id),
                                     value);
         match value {
index c355e8b82a6ef9f201b8fe8b982ded75db45cff6..7df37bdae07dbe0e16d04c903796bd4e8c4f01eb 100644 (file)
@@ -29,7 +29,8 @@
 use middle::subst;
 use middle::subst::Substs;
 use middle::subst::Subst;
-use middle::traits;
+use middle::traits::{self, FulfillmentContext, Normalized,
+                     SelectionContext, ObligationCause};
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
@@ -39,7 +40,7 @@
 use std::fmt;
 use syntax::ast;
 use syntax::codemap;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use self::combine::CombineFields;
@@ -87,6 +88,8 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
 
     pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>,
 
+    pub fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+
     // This is a temporary field used for toggling on normalization in the inference context,
     // as we move towards the approach described here:
     // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
@@ -327,9 +330,16 @@ pub fn fixup_err_to_string(f: fixup_err) -> String {
     }
 }
 
+/// errors_will_be_reported is required to proxy to the fulfillment context
+/// FIXME -- a better option would be to hold back on modifying
+/// the global cache until we know that all dependent obligations
+/// are also satisfied. In that case, we could actually remove
+/// this boolean flag, and we'd also avoid the problem of squelching
+/// duplicate errors that occur across fns.
 pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
                                 tables: &'a RefCell<ty::Tables<'tcx>>,
-                                param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
+                                param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
+                                errors_will_be_reported: bool)
                                 -> InferCtxt<'a, 'tcx> {
     InferCtxt {
         tcx: tcx,
@@ -339,11 +349,20 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
         float_unification_table: RefCell::new(UnificationTable::new()),
         region_vars: RegionVarBindings::new(tcx),
         parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
+        fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
         normalize: false,
         err_count_on_creation: tcx.sess.err_count()
     }
 }
 
+pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
+                                        tables: &'a RefCell<ty::Tables<'tcx>>)
+                                        -> InferCtxt<'a, 'tcx> {
+    let mut infcx = new_infer_ctxt(tcx, tables, None, false);
+    infcx.normalize = true;
+    infcx
+}
+
 /// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
 /// returns ty::err.
 pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -455,123 +474,145 @@ pub struct CombinedSnapshot {
     region_vars_snapshot: RegionSnapshot,
 }
 
-impl<'a, 'tcx> mc::Typer<'tcx> for InferCtxt<'a, 'tcx> {
-    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
-        let ty = self.node_ty(id);
-        self.resolve_type_vars_or_error(&ty)
-    }
+pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
+    where T : TypeFoldable<'tcx> + HasTypeFlags
+{
+    debug!("normalize_associated_type(t={:?})", value);
 
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
-        let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
-        self.resolve_type_vars_or_error(&ty)
-    }
+    let value = erase_regions(tcx, value);
 
-    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        let ty = self.resolve_type_vars_if_possible(&ty);
-        !traits::type_known_to_meet_builtin_bound(self, self, ty, ty::BoundCopy, span)
+    if !value.has_projection_types() {
+        return value;
     }
 
-    fn node_method_ty(&self, method_call: ty::MethodCall)
-                      -> Option<Ty<'tcx>> {
-        self.tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| method.ty)
-            .map(|ty| self.resolve_type_vars_if_possible(&ty))
-    }
+    let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut selcx = traits::SelectionContext::new(&infcx);
+    let cause = traits::ObligationCause::dummy();
+    let traits::Normalized { value: result, obligations } =
+        traits::normalize(&mut selcx, cause, &value);
 
-    fn node_method_origin(&self, method_call: ty::MethodCall)
-                          -> Option<ty::MethodOrigin<'tcx>>
-    {
-        self.tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| method.origin.clone())
-    }
+    debug!("normalize_associated_type: result={:?} obligations={:?}",
+           result,
+           obligations);
 
-    fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
-        fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
-                                        -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
-            &tables.adjustments
-        }
+    let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
 
-        Ref::map(self.tables.borrow(), project_adjustments)
+    for obligation in obligations {
+        fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
 
-    fn is_method_call(&self, id: ast::NodeId) -> bool {
-        self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
-    }
+    let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
 
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
-        self.parameter_environment.temporary_scope(rvalue_id)
-    }
+    result
+}
 
-    fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
-        self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
+                                                infcx: &InferCtxt<'a,'tcx>,
+                                                fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                                result: &T)
+                                                -> T
+    where T : TypeFoldable<'tcx>
+{
+    match drain_fulfillment_cx(infcx, fulfill_cx, result) {
+        Ok(v) => v,
+        Err(errors) => {
+            infcx.tcx.sess.span_bug(
+                span,
+                &format!("Encountered errors `{:?}` fulfilling during trans",
+                         errors));
+        }
     }
 }
 
-impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
-    fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
-        &self.parameter_environment
+/// Finishes processes any obligations that remain in the fulfillment
+/// context, and then "freshens" and returns `result`. This is
+/// primarily used during normalization and other cases where
+/// processing the obligations in `fulfill_cx` may cause type
+/// inference variables that appear in `result` to be unified, and
+/// hence we need to process those obligations to get the complete
+/// picture of the type.
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+                                       fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                       result: &T)
+                                       -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
+    where T : TypeFoldable<'tcx>
+{
+    debug!("drain_fulfillment_cx(result={:?})",
+           result);
+
+    // In principle, we only need to do this so long as `result`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    match fulfill_cx.select_all_or_error(infcx) {
+        Ok(()) => { }
+        Err(errors) => {
+            return Err(errors);
+        }
     }
 
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>
-    {
-        self.tables.borrow().closure_kinds.get(&def_id).cloned()
-    }
+    // Use freshen to simultaneously replace all type variables with
+    // their bindings and replace all regions with 'static.  This is
+    // sort of overkill because we do not expect there to be any
+    // unbound type variables, hence no `TyFresh` types should ever be
+    // inserted.
+    Ok(result.fold_with(&mut infcx.freshener()))
+}
 
-    fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>
-    {
+/// Returns an equivalent value with all free regions removed (note
+/// that late-bound regions remain, because they are important for
+/// subtyping, but they are anonymized and normalized as well). This
+/// is a stronger, caching version of `ty_fold::erase_regions`.
+pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
+    where T : TypeFoldable<'tcx>
+{
+    let value1 = value.fold_with(&mut RegionEraser(cx));
+    debug!("erase_regions({:?}) = {:?}",
+           value, value1);
+    return value1;
 
-        let closure_ty = self.tables
-                             .borrow()
-                             .closure_tys
-                             .get(&def_id)
-                             .unwrap()
-                             .subst(self.tcx, substs);
+    struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
 
-        if self.normalize {
-            // NOTE: this flag is currently *always* set to false, we are slowly folding
-            // normalization into this trait and will come back to remove this in the near
-            // future.
-
-            // code from NormalizingClosureTyper:
-            // the substitutions in `substs` are already monomorphized,
-            // but we still must normalize associated types
-            // normalize_associated_type(self.param_env.tcx, &closure_ty)
-            panic!("see issue 26597: fufillment context refactor must occur")
-        } else {
-            closure_ty
+    impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
+        fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
+
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+            match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
+                None => {}
+                Some(u) => return u
+            }
+
+            let t_norm = ty_fold::super_fold_ty(self, ty);
+            self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
+            return t_norm;
         }
-    }
 
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ty::ClosureUpvar<'tcx>>>
-    {
-        let result = ty::ctxt::closure_upvars(self, def_id, substs);
+        fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+            where T : TypeFoldable<'tcx>
+        {
+            let u = self.tcx().anonymize_late_bound_regions(t);
+            ty_fold::super_fold_binder(self, &u)
+        }
 
-        if self.normalize {
-            // NOTE: this flag is currently *always* set to false, we are slowly folding
-            // normalization into this trait and will come back to remove this in the near
-            // future.
-
-            // code from NormalizingClosureTyper:
-            // the substitutions in `substs` are already monomorphized,
-            // but we still must normalize associated types
-            // monomorphize::normalize_associated_type(self.param_env.tcx, &result)
-            panic!("see issue 26597: fufillment context refactor must occur")
-        } else {
-            result
+        fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+            // because late-bound regions affect subtyping, we can't
+            // erase the bound/free distinction, but we can replace
+            // all free regions with 'static.
+            //
+            // Note that we *CAN* replace early-bound regions -- the
+            // type system never "sees" those, they get substituted
+            // away. In trans, they will always be erased to 'static
+            // whenever a substitution occurs.
+            match r {
+                ty::ReLateBound(..) => r,
+                _ => ty::ReStatic
+            }
+        }
+
+        fn fold_substs(&mut self,
+                       substs: &subst::Substs<'tcx>)
+                       -> subst::Substs<'tcx> {
+            subst::Substs { regions: subst::ErasedRegions,
+                            types: substs.types.fold_with(self) }
         }
     }
 }
@@ -1017,7 +1058,7 @@ pub fn adjust_expr_ty(&self,
                                         .map(|method| resolve_ty(method.ty)))
     }
 
-    pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+    pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
         match self.tables.borrow().node_types.get(&id) {
             Some(&t) => t,
             // FIXME
@@ -1263,6 +1304,109 @@ pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx>
             self.equate(true, trace).relate(a, b)
         }).map(|_| ())
     }
+
+    pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
+        let ty = self.node_type(id);
+        self.resolve_type_vars_or_error(&ty)
+    }
+
+    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+        let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
+        self.resolve_type_vars_or_error(&ty)
+    }
+
+    pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+        let ty = self.resolve_type_vars_if_possible(&ty);
+        !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
+        // FIXME(@jroesch): should be able to use:
+        // ty.moves_by_default(&self.parameter_environment, span)
+    }
+
+    pub fn node_method_ty(&self, method_call: ty::MethodCall)
+                      -> Option<Ty<'tcx>> {
+        self.tables
+            .borrow()
+            .method_map
+            .get(&method_call)
+            .map(|method| method.ty)
+            .map(|ty| self.resolve_type_vars_if_possible(&ty))
+    }
+
+    pub fn node_method_origin(&self, method_call: ty::MethodCall)
+                          -> Option<ty::MethodOrigin<'tcx>>
+    {
+        self.tables
+            .borrow()
+            .method_map
+            .get(&method_call)
+            .map(|method| method.origin.clone())
+    }
+
+    pub fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
+        fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
+                                        -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
+            &tables.adjustments
+        }
+
+        Ref::map(self.tables.borrow(), project_adjustments)
+    }
+
+    pub fn is_method_call(&self, id: ast::NodeId) -> bool {
+        self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
+    }
+
+    pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
+        self.tcx.region_maps.temporary_scope(rvalue_id)
+    }
+
+    pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
+        self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
+    }
+
+    pub fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
+        &self.parameter_environment
+    }
+
+    pub fn closure_kind(&self,
+                        def_id: ast::DefId)
+                        -> Option<ty::ClosureKind>
+    {
+        self.tables.borrow().closure_kinds.get(&def_id).cloned()
+    }
+
+    pub fn closure_type(&self,
+                    def_id: ast::DefId,
+                    substs: &subst::Substs<'tcx>)
+                    -> ty::ClosureTy<'tcx>
+    {
+
+        let closure_ty = self.tables
+                             .borrow()
+                             .closure_tys
+                             .get(&def_id)
+                             .unwrap()
+                             .subst(self.tcx, substs);
+
+        if self.normalize {
+            normalize_associated_type(&self.tcx, &closure_ty)
+        } else {
+            closure_ty
+        }
+    }
+
+    pub fn closure_upvars(&self,
+                          def_id: ast::DefId,
+                          substs: &Substs<'tcx>)
+                          -> Option<Vec<ty::ClosureUpvar<'tcx>>>
+    {
+        let result = ty::ctxt::closure_upvars(self, def_id, substs);
+
+        if self.normalize {
+            normalize_associated_type(&self.tcx, &result)
+        } else {
+            result
+        }
+    }
 }
 
 impl<'tcx> TypeTrace<'tcx> {
index 7d237a511c4a173240da94101c01a582c85f6dae..68001ae1564ab038d384111edbc2090e0bdb7b76 100644 (file)
 use self::VarKind::*;
 
 use middle::def::*;
-use middle::mem_categorization::Typer;
 use middle::pat_util;
 use middle::region;
 use middle::ty;
-use middle::ty::ClosureTyper;
 use lint;
 use util::nodemap::NodeMap;
 
index 13e127e9126139caed875c100b53c51d17c7b09c..f506de525ff9c644e1761e460ab52c21cd04fc71 100644 (file)
 use self::Aliasability::*;
 
 use ast_map;
+use middle::infer;
 use middle::check_const;
 use middle::def;
 use middle::region;
 use middle::ty::{self, Ty};
-use util::nodemap::NodeMap;
 
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
 use syntax::codemap::Span;
 
-use std::cell::Ref;
 use std::fmt;
 use std::rc::Rc;
 
@@ -255,46 +254,13 @@ fn id(&self) -> ast::NodeId { self.id }
     fn span(&self) -> Span { self.span }
 }
 
-pub struct MemCategorizationContext<'t,TYPER:'t> {
-    typer: &'t TYPER
-}
-
-impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
-impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> {
-    fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self }
+#[derive(Copy, Clone)]
+pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
+    pub typer: &'t infer::InferCtxt<'a, 'tcx>,
 }
 
 pub type McResult<T> = Result<T, ()>;
 
-/// The `Typer` trait provides the interface for the mem-categorization
-/// module to the results of the type check. It can be used to query
-/// the type assigned to an expression node, to inquire after adjustments,
-/// and so on.
-///
-/// This interface is needed because mem-categorization is used from
-/// two places: `regionck` and `borrowck`. `regionck` executes before
-/// type inference is complete, and hence derives types and so on from
-/// intermediate tables.  This also implies that type errors can occur,
-/// and hence `node_ty()` and friends return a `Result` type -- any
-/// error will propagate back up through the mem-categorization
-/// routines.
-///
-/// In the borrow checker, in contrast, type checking is complete and we
-/// know that no errors have occurred, so we simply consult the tcx and we
-/// can be sure that only `Ok` results will occur.
-pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> {
-    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
-    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool;
-    fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
-    fn node_method_origin(&self, method_call: ty::MethodCall)
-                          -> Option<ty::MethodOrigin<'tcx>>;
-    fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>>;
-    fn is_method_call(&self, id: ast::NodeId) -> bool;
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
-    fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture>;
-}
-
 impl MutabilityCategory {
     pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
         let ret = match m {
@@ -391,13 +357,13 @@ pub fn to_user_str(&self) -> &'static str {
     }
 }
 
-impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
-    pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
+impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
+    pub fn new(typer: &'t infer::InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> {
         MemCategorizationContext { typer: typer }
     }
 
-    fn tcx(&self) -> &'t ty::ctxt<'tcx> {
-        self.typer.tcx()
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+        self.typer.tcx
     }
 
     fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
@@ -1175,7 +1141,7 @@ pub fn cat_downcast<N:ast_node>(&self,
     }
 
     pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()>
-        where F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+        where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
     {
         self.cat_pattern_(cmt, pat, &mut op)
     }
@@ -1183,7 +1149,7 @@ pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McRes
     // FIXME(#19596) This is a workaround, but there should be a better way to do this
     fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
                        -> McResult<()>
-        where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+        where F : FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &ast::Pat),
     {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
index 371b5c309a85067016b756ec8c3a55fb4b8b112f..977d0577e480f47beb5d76851380dc6f38f6b96b 100644 (file)
@@ -38,8 +38,7 @@ pub fn overlapping_impls(infcx: &InferCtxt,
            impl1_def_id,
            impl2_def_id);
 
-    let param_env = &infcx.tcx.empty_parameter_environment();
-    let selcx = &mut SelectionContext::intercrate(infcx, param_env);
+    let selcx = &mut SelectionContext::intercrate(infcx);
     infcx.probe(|_| {
         overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
     })
index dc3ccd417b8f7be506eaf267c7f179731a87f7b1..08cb3e5701569d0ddefbe8121d21dbc545b336d2 100644 (file)
@@ -85,7 +85,7 @@ pub struct FulfillmentContext<'tcx> {
     // particular node-id).
     region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
 
-    errors_will_be_reported: bool,
+    pub errors_will_be_reported: bool,
 }
 
 #[derive(Clone)]
@@ -132,7 +132,6 @@ pub fn new(errors_will_be_reported: bool) -> FulfillmentContext<'tcx> {
     /// `projection_ty` again.
     pub fn normalize_projection_type<'a>(&mut self,
                                          infcx: &InferCtxt<'a,'tcx>,
-                                         typer: &ty::ClosureTyper<'tcx>,
                                          projection_ty: ty::ProjectionTy<'tcx>,
                                          cause: ObligationCause<'tcx>)
                                          -> Ty<'tcx>
@@ -144,7 +143,7 @@ pub fn normalize_projection_type<'a>(&mut self,
 
         // FIXME(#20304) -- cache
 
-        let mut selcx = SelectionContext::new(infcx, typer);
+        let mut selcx = SelectionContext::new(infcx);
         let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
 
         for obligation in normalized.obligations {
@@ -208,11 +207,10 @@ pub fn region_obligations(&self,
     }
 
     pub fn select_all_or_error<'a>(&mut self,
-                                   infcx: &InferCtxt<'a,'tcx>,
-                                   typer: &ty::ClosureTyper<'tcx>)
+                                   infcx: &InferCtxt<'a,'tcx>)
                                    -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
-        try!(self.select_where_possible(infcx, typer));
+        try!(self.select_where_possible(infcx));
 
         // Anything left is ambiguous.
         let errors: Vec<FulfillmentError> =
@@ -233,20 +231,18 @@ pub fn select_all_or_error<'a>(&mut self,
     /// gaining type information. It'd be equally valid to use `select_where_possible` but it
     /// results in `O(n^2)` performance (#18208).
     pub fn select_new_obligations<'a>(&mut self,
-                                      infcx: &InferCtxt<'a,'tcx>,
-                                      typer: &ty::ClosureTyper<'tcx>)
+                                      infcx: &InferCtxt<'a,'tcx>)
                                       -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
-        let mut selcx = SelectionContext::new(infcx, typer);
+        let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx, true)
     }
 
     pub fn select_where_possible<'a>(&mut self,
-                                     infcx: &InferCtxt<'a,'tcx>,
-                                     typer: &ty::ClosureTyper<'tcx>)
+                                     infcx: &InferCtxt<'a,'tcx>)
                                      -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
-        let mut selcx = SelectionContext::new(infcx, typer);
+        let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx, false)
     }
 
index 9df6ed5d68126cf7923bf2d0a6d02b1f3c7b708b..5126a549887eda690c5236bc4c794b701609aa64 100644 (file)
@@ -312,7 +312,6 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
 /// conservative towards *no impl*, which is the opposite of the
 /// `evaluate` methods).
 pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                                                 typer: &ty::ClosureTyper<'tcx>,
                                                  ty: Ty<'tcx>,
                                                  bound: ty::BuiltinBound,
                                                  span: Span)
@@ -334,7 +333,7 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     // Note: we only assume something is `Copy` if we can
     // *definitively* show that it implements `Copy`. Otherwise,
     // assume it is move; linear is always ok.
-    match fulfill_cx.select_all_or_error(infcx, typer) {
+    match fulfill_cx.select_all_or_error(infcx) {
         Ok(()) => {
             debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success",
                    ty,
@@ -397,8 +396,8 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
 
     let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
-    let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause,
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), false);
+    let predicates = match fully_normalize(&infcx, cause,
                                            &infcx.parameter_environment.caller_bounds) {
         Ok(predicates) => predicates,
         Err(errors) => {
@@ -429,7 +428,6 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
 }
 
 pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
-                                  closure_typer: &ty::ClosureTyper<'tcx>,
                                   cause: ObligationCause<'tcx>,
                                   value: &T)
                                   -> Result<T, Vec<FulfillmentError<'tcx>>>
@@ -437,8 +435,22 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 {
     debug!("normalize_param_env(value={:?})", value);
 
-    let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
+    let mut selcx = &mut SelectionContext::new(infcx);
+    // FIXME (@jroesch) ISSUE 26721
+    // I'm not sure if this is a bug or not, needs further investigation.
+    // It appears that by reusing the fulfillment_cx here we incur more
+    // obligations and later trip an asssertion on regionck.rs line 337.
+    //
+    // The two possibilities I see is:
+    //      - normalization is not actually fully happening and we
+    //        have a bug else where
+    //      - we are adding a duplicate bound into the list causing
+    //        its size to change.
+    //
+    // I think we should probably land this refactor and then come
+    // back to this is a follow-up patch.
     let mut fulfill_cx = FulfillmentContext::new(false);
+
     let Normalized { value: normalized_value, obligations } =
         project::normalize(selcx, cause, value);
     debug!("normalize_param_env: normalized_value={:?} obligations={:?}",
@@ -447,7 +459,8 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     for obligation in obligations {
         fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
     }
-    try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
+
+    try!(fulfill_cx.select_all_or_error(infcx));
     let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
     debug!("normalize_param_env: resolved_value={:?}", resolved_value);
     Ok(resolved_value)
index ae15c8aa8e028379eda46f5a0d62f57fdd6d86e1..3bc4fd0c0a14e8fc0fc35e20f35c9b63a6ffef14 100644 (file)
@@ -55,8 +55,6 @@
 pub struct SelectionContext<'cx, 'tcx:'cx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
 
-    closure_typer: &'cx (ty::ClosureTyper<'tcx>+'cx),
-
     /// Freshener used specifically for skolemizing entries on the
     /// obligation stack. This ensures that all entries on the stack
     /// at one time will have the same set of skolemized entries,
@@ -244,23 +242,19 @@ enum EvaluationResult<'tcx> {
 }
 
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>,
-               closure_typer: &'cx ty::ClosureTyper<'tcx>)
+    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>)
                -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx: infcx,
-            closure_typer: closure_typer,
             freshener: infcx.freshener(),
             intercrate: false,
         }
     }
 
-    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
-                      closure_typer: &'cx ty::ClosureTyper<'tcx>)
+    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>)
                       -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx: infcx,
-            closure_typer: closure_typer,
             freshener: infcx.freshener(),
             intercrate: true,
         }
@@ -275,11 +269,11 @@ pub fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
     }
 
     pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'cx, 'tcx> {
-        self.closure_typer.param_env()
+        self.infcx.param_env()
     }
 
-    pub fn closure_typer(&self) -> &'cx (ty::ClosureTyper<'tcx>+'cx) {
-        self.closure_typer
+    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+        self.infcx
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -1163,7 +1157,7 @@ fn assemble_closure_candidates(&mut self,
                kind,
                obligation);
 
-        match self.closure_typer.closure_kind(closure_def_id) {
+        match self.infcx.closure_kind(closure_def_id) {
             Some(closure_kind) => {
                 debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
                 if closure_kind.extends(kind) {
@@ -1727,7 +1721,7 @@ fn builtin_bound(&mut self,
                     return ok_if(Vec::new());
                 }
 
-                match self.closure_typer.closure_upvars(def_id, substs) {
+                match self.infcx.closure_upvars(def_id, substs) {
                     Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()),
                     None => {
                         debug!("assemble_builtin_bound_candidates: no upvar types available yet");
@@ -1865,7 +1859,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
             ty::TyClosure(def_id, substs) => {
                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
-                match self.closure_typer.closure_upvars(def_id, substs) {
+                match self.infcx.closure_upvars(def_id, substs) {
                     Some(upvars) => {
                         Some(upvars.iter().map(|c| c.ty).collect())
                     }
@@ -2844,7 +2838,7 @@ fn closure_trait_ref_unnormalized(&mut self,
                                       substs: &Substs<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
+        let closure_type = self.infcx.closure_type(closure_def_id, substs);
         let ty::Binder((trait_ref, _)) =
             util::closure_trait_ref_and_return_type(self.tcx(),
                                                     obligation.predicate.def_id(),
index fe52fba49c6e5459e060f2b8f8c328d69d53da1a..91a038813b86826e02b4b310110cfd3c62bdcc93 100644 (file)
@@ -52,8 +52,6 @@
 use middle::fast_reject;
 use middle::free_region::FreeRegionMap;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
 use middle::region;
 use middle::resolve_lifetime;
 use middle::infer;
@@ -2919,11 +2917,14 @@ pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span)
                                    -> Result<(),CopyImplementationError> {
         let tcx = self.tcx;
 
+        // FIXME: (@jroesch) float this code up
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false);
+
         let did = match self_type.sty {
             ty::TyStruct(struct_did, substs) => {
                 let fields = tcx.struct_fields(struct_did, substs);
                 for field in &fields {
-                    if self.type_moves_by_default(field.mt.ty, span) {
+                    if infcx.type_moves_by_default(field.mt.ty, span) {
                         return Err(FieldDoesNotImplementCopy(field.name))
                     }
                 }
@@ -2935,7 +2936,7 @@ pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span)
                     for variant_arg_type in &variant.args {
                         let substd_arg_type =
                             variant_arg_type.subst(tcx, substs);
-                        if self.type_moves_by_default(substd_arg_type, span) {
+                        if infcx.type_moves_by_default(substd_arg_type, span) {
                             return Err(VariantDoesNotImplementCopy(variant.name))
                         }
                     }
@@ -3177,41 +3178,12 @@ pub fn extends(self, other: ty::ClosureKind) -> bool {
     }
 }
 
-pub trait ClosureTyper<'tcx> {
-    fn tcx(&self) -> &ctxt<'tcx> {
-        self.param_env().tcx
-    }
-
-    fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>;
-
-    /// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck,
-    /// returns `None` if the kind of this closure has not yet been
-    /// inferred.
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>;
-
-    /// Returns the argument/return types of this closure.
-    fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>;
-
-    /// Returns the set of all upvars and their transformed
-    /// types. During typeck, maybe return `None` if the upvar types
-    /// have not yet been inferred.
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ClosureUpvar<'tcx>>>;
-}
-
 impl<'tcx> CommonTypes<'tcx> {
     fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
-           interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
+           interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
            -> CommonTypes<'tcx>
     {
-        let mut mk = |sty| ctxt::intern_ty(arena, interner, sty);
+        let mk = |sty| ctxt::intern_ty(arena, interner, sty);
         CommonTypes {
             bool: mk(TyBool),
             char: mk(TyChar),
@@ -3440,12 +3412,12 @@ pub fn create_and_enter<F, R>(s: Session,
                                  f: F) -> (Session, R)
                                  where F: FnOnce(&ctxt<'tcx>) -> R
     {
-        let mut interner = FnvHashMap();
-        let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+        let interner = RefCell::new(FnvHashMap());
+        let common_types = CommonTypes::new(&arenas.type_, &interner);
 
         tls::enter(ctxt {
             arenas: arenas,
-            interner: RefCell::new(interner),
+            interner: interner,
             substs_interner: RefCell::new(FnvHashMap()),
             bare_fn_interner: RefCell::new(FnvHashMap()),
             region_interner: RefCell::new(FnvHashMap()),
@@ -3573,35 +3545,37 @@ pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability
     }
 
     fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
-                 interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+                 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
                  st: TypeVariants<'tcx>)
                  -> Ty<'tcx> {
-        match interner.get(&st) {
-            Some(ty) => return *ty,
-            _ => ()
-        }
+        let ty: Ty /* don't be &mut TyS */ = {
+            let mut interner = interner.borrow_mut();
+            match interner.get(&st) {
+                Some(ty) => return *ty,
+                _ => ()
+            }
+
+            let flags = FlagComputation::for_sty(&st);
 
-        let flags = FlagComputation::for_sty(&st);
+            let ty = match () {
+                () => type_arena.alloc(TyS { sty: st,
+                                             flags: Cell::new(flags.flags),
+                                             region_depth: flags.depth, }),
+            };
 
-        let ty = match () {
-            () => type_arena.alloc(TyS { sty: st,
-                                        flags: Cell::new(flags.flags),
-                                        region_depth: flags.depth, }),
+            interner.insert(InternedTy { ty: ty }, ty);
+            ty
         };
 
         debug!("Interned type: {:?} Pointer: {:?}",
             ty, ty as *const TyS);
-
-        interner.insert(InternedTy { ty: ty }, ty);
-
         ty
     }
 
     // Interns a type/name combination, stores the resulting box in cx.interner,
     // and returns the box as cast to an unsafe ptr (see comments for Ty above).
     pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
-        let mut interner = self.interner.borrow_mut();
-        ctxt::intern_ty(&self.arenas.type_, &mut *interner, st)
+        ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
     }
 
     pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
@@ -4272,7 +4246,8 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 TyClosure(did, substs) => {
                     // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
                     let param_env = cx.empty_parameter_environment();
-                    let upvars = param_env.closure_upvars(did, substs).unwrap();
+                    let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
+                    let upvars = infcx.closure_upvars(did, substs).unwrap();
                     TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
                 }
 
@@ -4400,10 +4375,10 @@ fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
                        span: Span)
                        -> bool
     {
-        let tcx = param_env.tcx();
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()));
+        let tcx = param_env.tcx;
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false);
 
-        let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env,
+        let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
                                                                 self, bound, span);
 
         debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
@@ -4412,7 +4387,8 @@ fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
         is_impld
     }
 
-    fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+    // FIXME (@jroesch): I made this public to use it, not sure if should be private
+    pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
                            span: Span) -> bool {
         if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
             return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
@@ -5940,6 +5916,10 @@ pub fn enum_variant_with_id(&self,
                                    .clone()
     }
 
+    // Register a given item type
+    pub fn register_item_type(&self, did: ast::DefId, ty: TypeScheme<'tcx>) {
+        self.tcache.borrow_mut().insert(did, ty);
+    }
 
     // If the given item is in an external crate, looks up its type and adds it to
     // the type cache. Returns the type parameters and type.
@@ -6016,8 +5996,8 @@ pub fn lookup_field_type_unsubstituted(&self,
         if id.krate == ast::LOCAL_CRATE {
             self.node_id_to_type(id.node)
         } else {
-            let mut tcache = self.tcache.borrow_mut();
-            tcache.entry(id).or_insert_with(|| csearch::get_field_type(self, struct_id, id)).ty
+            memoized(&self.tcache, id,
+                     |id| csearch::get_field_type(self, struct_id, id)).ty
         }
     }
 
@@ -6112,7 +6092,7 @@ pub fn struct_lockstep_tails(&self,
     }
 
     // Returns a list of `ClosureUpvar`s for each upvar.
-    pub fn closure_upvars(typer: &Typer<'tcx>,
+    pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
                           closure_id: ast::DefId,
                           substs: &Substs<'tcx>)
                           -> Option<Vec<ClosureUpvar<'tcx>>>
@@ -6123,7 +6103,7 @@ pub fn closure_upvars(typer: &Typer<'tcx>,
         // This may change if abstract return types of some sort are
         // implemented.
         assert!(closure_id.krate == ast::LOCAL_CRATE);
-        let tcx = typer.tcx();
+        let tcx = typer.tcx;
         match tcx.freevars.borrow().get(&closure_id.node) {
             None => Some(vec![]),
             Some(ref freevars) => {
@@ -6711,79 +6691,6 @@ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
     }
 }
 
-impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
-    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        Ok(self.tcx.node_id_to_type(id))
-    }
-
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
-        Ok(self.tcx.expr_ty_adjusted(expr))
-    }
-
-    fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
-        self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.ty)
-    }
-
-    fn node_method_origin(&self, method_call: ty::MethodCall)
-                          -> Option<ty::MethodOrigin<'tcx>>
-    {
-        self.tcx.tables.borrow().method_map.get(&method_call).map(|method| method.origin.clone())
-    }
-
-    fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
-        fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
-            &tables.adjustments
-        }
-
-        Ref::map(self.tcx.tables.borrow(), projection)
-    }
-
-    fn is_method_call(&self, id: ast::NodeId) -> bool {
-        self.tcx.is_method_call(id)
-    }
-
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
-        self.tcx.region_maps.temporary_scope(rvalue_id)
-    }
-
-    fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
-        self.tcx.upvar_capture(upvar_id)
-    }
-
-    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        ty.moves_by_default(self, span)
-    }
-}
-
-impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> {
-    fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
-        self
-    }
-
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>
-    {
-        Some(self.tcx.closure_kind(def_id))
-    }
-
-    fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>
-    {
-        self.tcx.closure_type(def_id, substs)
-    }
-
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ClosureUpvar<'tcx>>> {
-        ctxt::closure_upvars(self, def_id, substs)
-    }
-}
-
-
 /// The category of explicit self.
 #[derive(Clone, Copy, Eq, PartialEq, Debug)]
 pub enum ExplicitSelfCategory {
index 8d5357fa6e4170a2285c57bf3650e61c946e94a9..162bf6ed9a97f5dbfb6c8393fb51b299e812249c 100644 (file)
@@ -59,14 +59,50 @@ pub fn time<T, U, F>(do_it: bool, what: &str, u: U, f: F) -> T where
     const NANOS_PER_SEC: f64 = 1_000_000_000.0;
     let secs = dur.secs() as f64;
     let secs = secs + dur.extra_nanos() as f64 / NANOS_PER_SEC;
-    println!("{}time: {:.3} \t{}", repeat("  ").take(old).collect::<String>(),
-             secs, what);
+
+    let mem_string = match get_resident() {
+        Some(n) => {
+            let mb = n as f64 / 1_000_000.0;
+            format!("; rss: {}MB", mb.round() as usize)
+        }
+        None => "".to_owned(),
+    };
+    println!("{}time: {:.3}{}\t{}", repeat("  ").take(old).collect::<String>(),
+             secs, mem_string, what);
 
     DEPTH.with(|slot| slot.set(old));
 
     rv
 }
 
+// Memory reporting
+fn get_resident() -> Option<usize> {
+    if cfg!(unix) {
+        get_proc_self_statm_field(1)
+    } else {
+        None
+    }
+}
+
+// Like std::macros::try!, but for Option<>.
+macro_rules! option_try(
+    ($e:expr) => (match $e { Some(e) => e, None => return None })
+);
+
+fn get_proc_self_statm_field(field: usize) -> Option<usize> {
+    use std::fs::File;
+    use std::io::Read;
+
+    assert!(cfg!(unix));
+
+    let mut f = option_try!(File::open("/proc/self/statm").ok());
+    let mut contents = String::new();
+    option_try!(f.read_to_string(&mut contents).ok());
+    let s = option_try!(contents.split_whitespace().nth(field));
+    let npages = option_try!(s.parse::<usize>().ok());
+    Some(npages * ::std::env::page_size())
+}
+
 pub fn indent<R, F>(op: F) -> R where
     R: Debug,
     F: FnOnce() -> R,
index de2f33e8a4ac9dd3233639804f2428759eec7e17..91b547e967952b2d8646da9dd5d4f98730b822b9 100644 (file)
@@ -680,8 +680,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             TyError => write!(f, "[type error]"),
             TyParam(ref param_ty) => write!(f, "{}", param_ty),
             TyEnum(did, substs) | TyStruct(did, substs) => {
-                parameterized(f, substs, did, &[],
-                              |tcx| tcx.lookup_item_type(did).generics)
+                ty::tls::with(|tcx| {
+                    if did.krate == ast::LOCAL_CRATE &&
+                          !tcx.tcache.borrow().contains_key(&did) {
+                        write!(f, "{}<..>", tcx.item_path_str(did))
+                    } else {
+                        parameterized(f, substs, did, &[],
+                                      |tcx| tcx.lookup_item_type(did).generics)
+                    }
+                })
             }
             TyTrait(ref data) => write!(f, "{}", data),
             ty::TyProjection(ref data) => write!(f, "{}", data),
index 7325e4e7a2ece9aa4a15bee6e35c2820e4159a0c..9e288f6ddb2bfaa7b985831bba59939b47a03f31 100644 (file)
@@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index b46150f75d084516102e96252fc7017489955254..e1edff817d6c1f27cf9e37285a5a4e4c1f58bb38 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+          abi::OsBitrig | abi::OsDragonfly | abi::OsFreebsd | abi::OsNetbsd | abi::OsOpenbsd => {
             "E-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index c7fa7aa879ac272c440982fe5ece76fadd3a70c0..ca52a9e56ff52978b7ed9c68801219182fe98249 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index a42f861d19056d6d55d00ec613d243ede9a58693..bc5f306cd3568b8ad8a5521a5172eac59f9997fa 100644 (file)
@@ -58,6 +58,7 @@
 mod freebsd_base;
 mod linux_base;
 mod openbsd_base;
+mod netbsd_base;
 mod windows_base;
 mod windows_msvc_base;
 
@@ -368,6 +369,7 @@ macro_rules! load_specific {
 
             x86_64_unknown_bitrig,
             x86_64_unknown_openbsd,
+            x86_64_unknown_netbsd,
 
             x86_64_apple_darwin,
             i686_apple_darwin,
diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_back/target/netbsd_base.rs
new file mode 100644 (file)
index 0000000..0f2ab32
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::TargetOptions;
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        linker: "cc".to_string(),
+        dynamic_linking: true,
+        executables: true,
+        morestack: false,
+        linker_is_gnu: true,
+        has_rpath: true,
+        pre_link_args: vec!(
+            // GNU-style linkers will use this to omit linking to libraries
+            // which don't actually fulfill any relocations, but only for
+            // libraries which follow this flag.  Thus, use it before
+            // specifying libraries to link to.
+            "-Wl,--as-needed".to_string(),
+        ),
+        position_independent_executables: true,
+        .. Default::default()
+    }
+}
diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_back/target/x86_64_unknown_netbsd.rs
new file mode 100644 (file)
index 0000000..3f5bd39
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::netbsd_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+
+    Target {
+        data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
+                     s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
+        llvm_target: "x86_64-unknown-netbsd".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "netbsd".to_string(),
+        target_env: "".to_string(),
+        options: base,
+    }
+}
index 1c6eacc355947850044b035fb5d6db4f8690a1c9..46e0a83ac033b681387cdc07c188c676cdefc3d8 100644 (file)
@@ -45,7 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
             "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd | abi::OsNetbsd => {
             "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
           }
 
index d016bd12c698fdd5646cafbf4f5c7e298ba10c7a..abdcd56444213e121fbb7f023a6df1674716d554 100644 (file)
@@ -47,7 +47,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
+          abi::OsBitrig | abi::OsDragonfly | abi::OsFreebsd | abi::OsNetbsd | abi::OsOpenbsd => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
                 f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
index 9d4fb4c994d404bd18fa2046567282aa8b7f8dcc..7c2318eef9cdd067157a9a2068582ce94ec9eb79 100644 (file)
@@ -21,6 +21,7 @@
 use borrowck::*;
 use borrowck::InteriorKind::{InteriorElement, InteriorField};
 use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty;
@@ -198,17 +199,18 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     debug!("check_loans(body id={})", body.id);
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
+    let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
 
     let mut clcx = CheckLoanCtxt {
         bccx: bccx,
         dfcx_loans: dfcx_loans,
         move_data: move_data,
         all_loans: all_loans,
-        param_env: &param_env,
+        param_env: &infcx.parameter_environment
     };
 
     {
-        let mut euv = euv::ExprUseVisitor::new(&mut clcx, &param_env);
+        let mut euv = euv::ExprUseVisitor::new(&mut clcx, &infcx);
         euv.walk_fn(decl, body);
     }
 }
index 44a4a0d250402ec8c2493b15f374eef1d8275c09..432d6289efec5a017d8d1144cc7662578138bb9a 100644 (file)
@@ -19,6 +19,7 @@
 use borrowck::*;
 use borrowck::move_data::MoveData;
 use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
 use rustc::middle::ty;
@@ -49,9 +50,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     };
 
     let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
-
+    let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env), false);
     {
-        let mut euv = euv::ExprUseVisitor::new(&mut glcx, &param_env);
+        let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx);
         euv.walk_fn(decl, body);
     }
 
@@ -490,8 +491,8 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> {
 impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &Expr) {
         if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
-            let param_env = self.bccx.tcx.empty_parameter_environment();
-            let mc = mc::MemCategorizationContext::new(&param_env);
+            let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None, false);
+            let mc = mc::MemCategorizationContext::new(&infcx);
             let base_cmt = mc.cat_expr(&**base).unwrap();
             let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
             // Check that we don't allow borrows of unsafe static items.
index 4f726044a1bac866f385396a1608beec40076175..3a4318527fb4036263d1c400ede0092bf2d26c7e 100644 (file)
@@ -30,7 +30,6 @@
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::mem_categorization as mc;
-use rustc::middle::mem_categorization::Typer;
 use rustc::middle::region;
 use rustc::middle::ty::{self, Ty};
 
@@ -747,7 +746,7 @@ fn move_suggestion<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
                                     -> (&'static str, &'static str) {
             match ty.sty {
                 _ => {
-                    if param_env.type_moves_by_default(ty, span) {
+                    if ty.moves_by_default(param_env, span) {
                         ("non-copyable",
                          "perhaps you meant to use `clone()`?")
                     } else {
index fb2f6b2b08db8e8e2f6d2644d6f8416ef96eee4f..128b0b7baabc09835e89b619fba28a7774b8b5bd 100644 (file)
@@ -140,7 +140,7 @@ fn test_env<F>(source_string: &str,
                                lang_items,
                                stability::Index::new(krate),
                                |tcx| {
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
         body(Env { infcx: &infcx });
         let free_regions = FreeRegionMap::new();
         infcx.resolve_regions_and_report_errors(&free_regions, ast::CRATE_NODE_ID);
index 903ade7cc84cefef3f0cb98d7dce96b2692d0ba8..8845bd06a0667f2a1eb1a6aa72a1c85d045365bc 100644 (file)
@@ -33,7 +33,6 @@
 
 use metadata::{csearch, decoder};
 use middle::def::*;
-use middle::mem_categorization::Typer;
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use middle::{def, pat_util, stability};
@@ -1709,7 +1708,9 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
             _ => return,
         };
         let parameter_environment = cx.tcx.empty_parameter_environment();
-        if !parameter_environment.type_moves_by_default(ty, item.span) {
+        // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
+        // method
+        if !ty.moves_by_default(&parameter_environment, item.span) {
             return;
         }
         if parameter_environment.can_type_implement_copy(ty, item.span).is_ok() {
index dc692b0e765dd5e9949a920067bdf687ebc99bc4..bb7e95cd4ae44d7eb4db5f05c0c62d4953a35286 100644 (file)
@@ -43,7 +43,6 @@
 #![feature(unicode)]
 #![feature(unicode)]
 #![feature(vec_push_all)]
-#![feature(cell_extras)]
 
 #![allow(trivial_casts)]
 
index 27805b9d8330b90066a29234a60cd9ba521bc5ef..9d66e99df3057fd82265ab4f1ca9694812be2b8d 100644 (file)
@@ -172,7 +172,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
                     qualname: qualname,
                     declaration: None,
                     span: sub_span.unwrap(),
-                    scope: self.tcx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
                 })
             }
             ast::ItemStatic(ref typ, mt, ref expr) => {
@@ -191,7 +191,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
                     name: get_ident(item.ident).to_string(),
                     qualname: qualname,
                     span: sub_span.unwrap(),
-                    scope: self.tcx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
                     value: value,
                     type_value: ty_to_string(&typ),
                 })
@@ -205,7 +205,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
                     name: get_ident(item.ident).to_string(),
                     qualname: qualname,
                     span: sub_span.unwrap(),
-                    scope: self.tcx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
                     value: self.span_utils.snippet(expr.span),
                     type_value: ty_to_string(&typ),
                 })
@@ -223,7 +223,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
                     name: get_ident(item.ident).to_string(),
                     qualname: qualname,
                     span: sub_span.unwrap(),
-                    scope: self.tcx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
                     filename: filename,
                 })
             },
@@ -237,14 +237,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Data {
                     value: val,
                     span: sub_span.unwrap(),
                     qualname: enum_name,
-                    scope: self.tcx.map.get_parent(item.id),
+                    scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
                 })
             },
             ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
                 let mut type_data = None;
                 let sub_span;
 
-                let parent = self.tcx.map.get_parent(item.id);
+                let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0);
 
                 match typ.node {
                     // Common case impl for a struct or something basic.
@@ -337,7 +337,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                                 return Some(Data::VariableRefData(VariableRefData {
                                     name: get_ident(ident.node).to_string(),
                                     span: sub_span.unwrap(),
-                                    scope: self.tcx.map.get_parent(expr.id),
+                                    scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
                                     ref_id: f.id,
                                 }));
                             }
@@ -360,7 +360,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
                         Some(Data::TypeRefData(TypeRefData {
                             span: sub_span.unwrap(),
-                            scope: self.tcx.map.get_parent(expr.id),
+                            scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
                             ref_id: def_id,
                         }))
                     }
index 47c2a5e579d941556252aca22000b49cff86c105..c2397ec31cffab8abaa9adf1d79e6b71d594ad8b 100644 (file)
 use middle::const_eval;
 use middle::def::{self, DefMap};
 use middle::expr_use_visitor as euv;
+use middle::infer;
 use middle::lang_items::StrEqFnLangItem;
 use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
 use middle::pat_util::*;
 use trans::adt;
 use trans::base::*;
 use trans::tvec;
 use trans::type_of;
 use middle::ty::{self, Ty};
-use session::config::{NoDebugInfo, FullDebugInfo};
+use session::config::NoDebugInfo;
 use util::common::indenter;
 use util::nodemap::FnvHashMap;
 use util::ppaux;
@@ -1351,7 +1351,8 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool
         reassigned: false
     };
     {
-        let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx);
+        let infcx = infer::new_infer_ctxt(bcx.tcx(), &bcx.tcx().tables, None, false);
+        let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx);
         visitor.walk_expr(body);
     }
     rc.reassigned
@@ -1416,7 +1417,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
         let trmode;
         match bm {
             ast::BindByValue(_)
-                if !param_env.type_moves_by_default(variable_ty, span) || reassigned =>
+                if !variable_ty.moves_by_default(&param_env, span) || reassigned =>
             {
                 llmatch = alloca_no_lifetime(bcx,
                                  llvariable_ty.ptr_to(),
@@ -1599,54 +1600,6 @@ fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     }
 }
 
-/// Generates code for argument patterns like `fn foo(<pat>: T)`.
-/// Creates entries in the `lllocals` map for each of the bindings
-/// in `pat`.
-///
-/// # Arguments
-///
-/// - `pat` is the argument pattern
-/// - `llval` is a pointer to the argument value (in other words,
-///   if the argument type is `T`, then `llval` is a `T*`). In some
-///   cases, this code may zero out the memory `llval` points at.
-pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                             pat: &ast::Pat,
-                             arg: Datum<'tcx, Rvalue>,
-                             arg_scope: cleanup::ScopeId)
-                             -> Block<'blk, 'tcx> {
-    let _icx = push_ctxt("match::store_arg");
-
-    match simple_identifier(&*pat) {
-        Some(ident) => {
-            // Generate nicer LLVM for the common case of fn a pattern
-            // like `x: T`
-            let arg_ty = node_id_type(bcx, pat.id);
-            if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
-                && bcx.sess().opts.debuginfo != FullDebugInfo {
-                // Don't copy an indirect argument to an alloca, the caller
-                // already put it in a temporary alloca and gave it up, unless
-                // we emit extra-debug-info, which requires local allocas :(.
-                let arg_val = arg.add_clean(bcx.fcx, arg_scope);
-                bcx.fcx.lllocals.borrow_mut()
-                   .insert(pat.id, Datum::new(arg_val, arg_ty, Lvalue));
-                bcx
-            } else {
-                mk_binding_alloca(
-                    bcx, pat.id, ident.name, arg_scope, arg,
-                    |arg, bcx, llval, _| arg.store_to(bcx, llval))
-            }
-        }
-
-        None => {
-            // General path. Copy out the values that are used in the
-            // pattern.
-            let arg = unpack_datum!(
-                bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope));
-            bind_irrefutable_pat(bcx, pat, arg.val, arg_scope)
-        }
-    }
-}
-
 fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
                                        p_id: ast::NodeId,
                                        name: ast::Name,
@@ -1686,7 +1639,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
 /// - bcx: starting basic block context
 /// - pat: the irrefutable pattern being matched.
 /// - val: the value being matched -- must be an lvalue (by ref, with cleanup)
-fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     pat: &ast::Pat,
                                     val: ValueRef,
                                     cleanup_scope: cleanup::ScopeId)
index 3ce76167e85171b08425da88a9d34406e769acbb..eca9891c57cb70e1611caea53efcc2fda3f16718 100644 (file)
@@ -50,7 +50,8 @@
 use llvm::{ValueRef, True, IntEQ, IntNE};
 use back::abi::FAT_PTR_ADDR;
 use middle::subst;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::infer;
+use middle::ty::{self, Ty};
 use middle::ty::Disr;
 use syntax::ast;
 use syntax::attr;
@@ -223,8 +224,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor))
         }
         ty::TyClosure(def_id, substs) => {
-            let typer = NormalizingClosureTyper::new(cx.tcx());
-            let upvars = typer.closure_upvars(def_id, substs).unwrap();
+            let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+            let upvars = infcx.closure_upvars(def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
             Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
         }
@@ -443,8 +444,8 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
         // Perhaps one of the upvars of this struct is non-zero
         // Let's recurse and find out!
         ty::TyClosure(def_id, substs) => {
-            let typer = NormalizingClosureTyper::new(tcx);
-            let upvars = typer.closure_upvars(def_id, substs).unwrap();
+            let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+            let upvars = infcx.closure_upvars(def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
 
             for (j, &ty) in upvar_types.iter().enumerate() {
index b432560bc4b3c2c8c96f2de4d6b85eef8f26b371..25cde149df109502a3d3db6d27fb96c20743e00f 100644 (file)
@@ -11,7 +11,8 @@
 
 use libc::{c_uint, c_ulonglong};
 use llvm::{self, ValueRef, AttrHelper};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
 use session::config::NoDebugInfo;
 use syntax::abi;
 use syntax::ast;
@@ -145,8 +146,8 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
     let (fn_sig, abi, env_ty) = match fn_type.sty {
         ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
         ty::TyClosure(closure_did, substs) => {
-            let typer = common::NormalizingClosureTyper::new(ccx.tcx());
-            function_type = typer.closure_type(closure_did, substs);
+            let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+            function_type = infcx.closure_type(closure_did, substs);
             let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
             (&function_type.sig, abi::RustCall, Some(self_type))
         }
index 0cd6bbad03aa9206dfbc3789c62f0f15277e89ac..edb61b0d3cf384cfb8aaf882a05e452c8e65c290 100644 (file)
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
 use middle::cfg;
+use middle::infer;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
+use middle::pat_util::simple_identifier;
 use middle::subst::Substs;
-use middle::ty::{self, Ty, ClosureTyper, HasTypeFlags};
+use middle::ty::{self, Ty, HasTypeFlags};
 use rustc::ast_map;
-use session::config::{self, NoDebugInfo};
+use session::config::{self, NoDebugInfo, FullDebugInfo};
 use session::Session;
 use trans::_match;
 use trans::adt;
@@ -434,8 +436,8 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
       }
       ty::TyClosure(def_id, substs) => {
           let repr = adt::represent_type(cx.ccx(), t);
-          let typer = common::NormalizingClosureTyper::new(cx.tcx());
-          let upvars = typer.closure_upvars(def_id, substs).unwrap();
+          let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+          let upvars = infcx.closure_upvars(def_id, substs).unwrap();
           for (i, upvar) in upvars.iter().enumerate() {
               let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
               cx = f(cx, llupvar, upvar.ty);
@@ -1034,6 +1036,13 @@ pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef {
     Alloca(cx, ty, name)
 }
 
+pub fn set_value_name(val: ValueRef, name: &str) {
+    unsafe {
+        let name = CString::new(name).unwrap();
+        llvm::LLVMSetValueName(val, name.as_ptr());
+    }
+}
+
 // Creates the alloca slot which holds the pointer to the slot for the final return value
 pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
                                           output_type: Ty<'tcx>) -> ValueRef {
@@ -1296,78 +1305,70 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
     }
 }
 
-// work around bizarre resolve errors
-pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
-
-// create_datums_for_fn_args: creates rvalue datums for each of the
-// incoming function arguments. These will later be stored into
-// appropriate lvalue datums.
-pub fn create_datums_for_fn_args<'a, 'tcx>(bcx: Block<'a, 'tcx>,
-                                           arg_tys: &[Ty<'tcx>])
-                                           -> Vec<RvalueDatum<'tcx>> {
+// create_datums_for_fn_args: creates lvalue datums for each of the
+// incoming function arguments.
+pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
+                                           args: &[ast::Arg],
+                                           arg_tys: &[Ty<'tcx>],
+                                           has_tupled_arg: bool,
+                                           arg_scope: cleanup::CustomScopeIndex)
+                                           -> Block<'a, 'tcx> {
     let _icx = push_ctxt("create_datums_for_fn_args");
     let fcx = bcx.fcx;
+    let arg_scope_id = cleanup::CustomScope(arg_scope);
 
     // Return an array wrapping the ValueRefs that we get from `get_param` for
     // each argument into datums.
-    let mut i = fcx.arg_offset() as c_uint;
-    arg_tys.iter().map(|&arg_ty| {
-        if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
-            let llty = type_of::type_of(bcx.ccx(), arg_ty);
-            let data = get_param(fcx.llfn, i);
-            let extra = get_param(fcx.llfn, i + 1);
-            let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
-            i += 2;
-            datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
-        } else {
-            let llarg = get_param(fcx.llfn, i);
-            i += 1;
-            datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty))
-        }
-    }).collect()
-}
-
-/// Creates rvalue datums for each of the incoming function arguments and
-/// tuples the arguments. These will later be stored into appropriate lvalue
-/// datums.
-///
-/// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
-fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
-        mut bcx: Block<'blk, 'tcx>,
-        arg_scope: cleanup::CustomScopeIndex,
-        arg_tys: &[Ty<'tcx>])
-        -> Vec<RvalueDatum<'tcx>> {
-    let mut result = Vec::new();
-    let mut idx = bcx.fcx.arg_offset() as c_uint;
+    //
+    // For certain mode/type combinations, the raw llarg values are passed
+    // by value.  However, within the fn body itself, we want to always
+    // have all locals and arguments be by-ref so that we can cancel the
+    // cleanup and for better interaction with LLVM's debug info.  So, if
+    // the argument would be passed by value, we store it into an alloca.
+    // This alloca should be optimized away by LLVM's mem-to-reg pass in
+    // the event it's not truly needed.
+    let mut idx = fcx.arg_offset() as c_uint;
     for (i, &arg_ty) in arg_tys.iter().enumerate() {
-        if i < arg_tys.len() - 1 {
-            // Regular argument.
-            result.push(if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
-                let llty = type_of::type_of(bcx.ccx(), arg_ty);
-                let data = get_param(bcx.fcx.llfn, idx);
-                let extra = get_param(bcx.fcx.llfn, idx + 1);
+        let arg_datum = if !has_tupled_arg || i < arg_tys.len() - 1 {
+            if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
+                    && bcx.sess().opts.debuginfo != FullDebugInfo {
+                // Don't copy an indirect argument to an alloca, the caller
+                // already put it in a temporary alloca and gave it up, unless
+                // we emit extra-debug-info, which requires local allocas :(.
+                let llarg = get_param(fcx.llfn, idx);
+                idx += 1;
+                bcx.fcx.schedule_lifetime_end(arg_scope_id, llarg);
+                bcx.fcx.schedule_drop_mem(arg_scope_id, llarg, arg_ty);
+
+                datum::Datum::new(llarg, arg_ty, datum::Lvalue)
+            } else if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+                let data = get_param(fcx.llfn, idx);
+                let extra = get_param(fcx.llfn, idx + 1);
                 idx += 2;
-                let fat_ptr = expr::make_fat_ptr(bcx, llty, data, extra);
-                datum::Datum::new(fat_ptr, arg_ty, datum::Rvalue { mode: datum::ByValue })
+                unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
+                                                        arg_scope_id, (data, extra),
+                                                        |(data, extra), bcx, dst| {
+                    Store(bcx, data, expr::get_dataptr(bcx, dst));
+                    Store(bcx, extra, expr::get_len(bcx, dst));
+                    bcx
+                }))
             } else {
-                let val = get_param(bcx.fcx.llfn, idx);
+                let llarg = get_param(fcx.llfn, idx);
                 idx += 1;
-                datum::Datum::new(val, arg_ty, arg_kind(bcx.fcx, arg_ty))
-            });
-
-            continue
-        }
-
-        // This is the last argument. Tuple it.
-        match arg_ty.sty {
-            ty::TyTuple(ref tupled_arg_tys) => {
-                let tuple_args_scope_id = cleanup::CustomScope(arg_scope);
-                let tuple =
+                let tmp = datum::Datum::new(llarg, arg_ty, arg_kind(fcx, arg_ty));
+                unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
+                                                           arg_scope_id, tmp,
+                                                           |tmp, bcx, dst| tmp.store_to(bcx, dst)))
+            }
+        } else {
+            // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
+            match arg_ty.sty {
+                ty::TyTuple(ref tupled_arg_tys) => {
                     unpack_datum!(bcx,
                                   datum::lvalue_scratch_datum(bcx,
                                                               arg_ty,
                                                               "tupled_args",
-                                                              tuple_args_scope_id,
+                                                              arg_scope_id,
                                                               (),
                                                               |(),
                                                                mut bcx,
@@ -1391,46 +1392,27 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
                             };
                         }
                         bcx
-                    }));
-                let tuple = unpack_datum!(bcx,
-                                          tuple.to_expr_datum()
-                                               .to_rvalue_datum(bcx,
-                                                                "argtuple"));
-                result.push(tuple);
-            }
-            _ => {
-                bcx.tcx().sess.bug("last argument of a function with \
-                                    `rust-call` ABI isn't a tuple?!")
+                    }))
+                }
+                _ => {
+                    bcx.tcx().sess.bug("last argument of a function with \
+                                        `rust-call` ABI isn't a tuple?!")
+                }
             }
         };
 
-    }
-
-    result
-}
-
-fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    arg_scope: cleanup::CustomScopeIndex,
-                                    args: &[ast::Arg],
-                                    arg_datums: Vec<RvalueDatum<'tcx>>)
-                                    -> Block<'blk, 'tcx> {
-    debug!("copy_args_to_allocas");
-
-    let _icx = push_ctxt("copy_args_to_allocas");
-    let mut bcx = bcx;
-
-    let arg_scope_id = cleanup::CustomScope(arg_scope);
-
-    for (i, arg_datum) in arg_datums.into_iter().enumerate() {
-        // For certain mode/type combinations, the raw llarg values are passed
-        // by value.  However, within the fn body itself, we want to always
-        // have all locals and arguments be by-ref so that we can cancel the
-        // cleanup and for better interaction with LLVM's debug info.  So, if
-        // the argument would be passed by value, we store it into an alloca.
-        // This alloca should be optimized away by LLVM's mem-to-reg pass in
-        // the event it's not truly needed.
-
-        bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
+        let pat = &*args[i].pat;
+        bcx = if let Some(ident) = simple_identifier(&*pat) {
+            // Generate nicer LLVM for the common case of fn a pattern
+            // like `x: T`
+            set_value_name(arg_datum.val, &bcx.name(ident.name));
+            bcx.fcx.lllocals.borrow_mut().insert(pat.id, arg_datum);
+            bcx
+        } else {
+            // General path. Copy out the values that are used in the
+            // pattern.
+            _match::bind_irrefutable_pat(bcx, pat, arg_datum.val, arg_scope_id)
+        };
         debuginfo::create_argument_metadata(bcx, &args[i]);
     }
 
@@ -1577,16 +1559,6 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         decl.inputs.iter()
                    .map(|arg| node_id_type(bcx, arg.id))
                    .collect::<Vec<_>>();
-    let monomorphized_arg_types = match closure_env {
-        closure::ClosureEnv::NotClosure => {
-            monomorphized_arg_types
-        }
-
-        // Tuple up closure argument types for the "rust-call" ABI.
-        closure::ClosureEnv::Closure(_) => {
-            vec![ccx.tcx().mk_tup(monomorphized_arg_types)]
-        }
-    };
     for monomorphized_arg_type in &monomorphized_arg_types {
         debug!("trans_closure: monomorphized_arg_type: {:?}",
                monomorphized_arg_type);
@@ -1594,17 +1566,13 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     debug!("trans_closure: function lltype: {}",
            bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn));
 
-    let arg_datums = match closure_env {
-        closure::ClosureEnv::NotClosure if abi == RustCall => {
-            create_datums_for_fn_args_under_call_abi(bcx, arg_scope, &monomorphized_arg_types[..])
-        }
-        _ => {
-            let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi);
-            create_datums_for_fn_args(bcx, &arg_tys)
-        }
+    let has_tupled_arg = match closure_env {
+        closure::ClosureEnv::NotClosure => abi == RustCall,
+        _ => false
     };
 
-    bcx = copy_args_to_allocas(bcx, arg_scope, &decl.inputs, arg_datums);
+    bcx = create_datums_for_fn_args(bcx, &decl.inputs, &monomorphized_arg_types,
+                                    has_tupled_arg, arg_scope);
 
     bcx = closure_env.load(bcx, cleanup::CustomScope(arg_scope));
 
@@ -1805,18 +1773,30 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
 
     let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());
 
-    let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
-
     if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
         let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
         let repr = adt::represent_type(ccx, result_ty.unwrap());
-        for (i, arg_datum) in arg_datums.into_iter().enumerate() {
+        let mut llarg_idx = fcx.arg_offset() as c_uint;
+        for (i, arg_ty) in arg_tys.into_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
                                                  &*repr,
                                                  dest,
                                                  disr,
                                                  i);
-            arg_datum.store_to(bcx, lldestptr);
+            if common::type_is_fat_ptr(bcx.tcx(), arg_ty) {
+                Store(bcx, get_param(fcx.llfn, llarg_idx), expr::get_dataptr(bcx, lldestptr));
+                Store(bcx, get_param(fcx.llfn, llarg_idx + 1), expr::get_len(bcx, lldestptr));
+                llarg_idx += 2;
+            } else {
+                let arg = get_param(fcx.llfn, llarg_idx);
+                llarg_idx += 1;
+
+                if arg_is_indirect(ccx, arg_ty) {
+                    memcpy_ty(bcx, lldestptr, arg, arg_ty);
+                } else {
+                    store_ty(bcx, arg, lldestptr, arg_ty);
+                }
+            }
         }
         adt::trans_set_discr(bcx, &*repr, dest, disr);
     }
index b6378062855400c5b885961feede03c4ca34f11a..5fd0f92400f843f10d260eee5f3fc23ce7fd8fc7 100644 (file)
@@ -11,7 +11,7 @@
 use arena::TypedArena;
 use back::link::{self, mangle_internal_name_by_path_and_seq};
 use llvm::{ValueRef, get_params};
-use middle::mem_categorization::Typer;
+use middle::infer;
 use trans::adt;
 use trans::attributes;
 use trans::base::*;
@@ -25,7 +25,7 @@
 use trans::expr;
 use trans::monomorphize::{self, MonoId};
 use trans::type_of::*;
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
 use middle::subst::Substs;
 use session::config::FullDebugInfo;
 
@@ -214,8 +214,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // takes the same set of type arguments as the enclosing fn, and
     // this function (`trans_closure`) is invoked at the point
     // of the closure expression.
-    let typer = NormalizingClosureTyper::new(tcx);
-    let function_type = typer.closure_type(closure_id, param_substs);
+
+    let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+    let function_type = infcx.closure_type(closure_id, param_substs);
 
     let freevars: Vec<ty::Freevar> =
         tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
@@ -358,7 +359,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
            ccx.tn().val_to_string(llreffn));
 
     let tcx = ccx.tcx();
-    let typer = NormalizingClosureTyper::new(tcx);
+    let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
 
     // Find a version of the closure type. Substitute static for the
     // region since it doesn't really matter.
@@ -367,7 +368,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
 
     // Make a version with the type of by-ref closure.
-    let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
+    let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
     sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
     let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
                                                                abi: abi,
index 9c2aea1e67adfda878defeefcd57fe62a184df98..96564277cdc1de8352675cd916259fe6e5bebe77 100644 (file)
@@ -22,9 +22,6 @@
 use middle::def;
 use middle::infer;
 use middle::lang_items::LangItem;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Typer;
-use middle::region;
 use middle::subst::{self, Substs};
 use trans::base;
 use trans::build;
@@ -47,7 +44,7 @@
 use arena::TypedArena;
 use libc::{c_uint, c_char};
 use std::ffi::CString;
-use std::cell::{Cell, RefCell, Ref};
+use std::cell::{Cell, RefCell};
 use std::result::Result as StdResult;
 use std::vec::Vec;
 use syntax::ast;
@@ -153,7 +150,7 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
     // normalized version of the type, and therefore will definitely
     // know whether the type implements Copy (and thus needs no
     // cleanup/drop/zeroing) ...
-    let implements_copy = !param_env.type_moves_by_default(ty, DUMMY_SP);
+    let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP);
 
     if implements_copy { return false; }
 
@@ -576,95 +573,6 @@ pub fn monomorphize<T>(&self, value: &T) -> T
     }
 }
 
-impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
-    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        Ok(node_id_type(self, id))
-    }
-
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
-        Ok(expr_ty_adjusted(self, expr))
-    }
-
-    fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
-        self.tcx()
-            .tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| monomorphize_type(self, method.ty))
-    }
-
-    fn node_method_origin(&self, method_call: ty::MethodCall)
-                          -> Option<ty::MethodOrigin<'tcx>>
-    {
-        self.tcx()
-            .tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| method.origin.clone())
-    }
-
-    fn adjustments<'a>(&'a self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
-        // FIXME (@jroesch): this is becuase we currently have a HR inference problem
-        // in the snapshot that causes this code not to work.
-        fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) ->
-            &'a NodeMap<ty::AutoAdjustment<'tcx>> {
-            &tables.adjustments
-        }
-
-        Ref::map(self.tcx().tables.borrow(), project_adjustments)
-    }
-
-    fn is_method_call(&self, id: ast::NodeId) -> bool {
-        self.tcx().tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
-    }
-
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
-        self.tcx().region_maps.temporary_scope(rvalue_id)
-    }
-
-    fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
-        Some(self.tcx().tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
-    }
-
-    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        self.fcx.param_env.type_moves_by_default(ty, span)
-    }
-}
-
-impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
-    fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> {
-        &self.fcx.param_env
-    }
-
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>
-    {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_kind(def_id)
-    }
-
-    fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>
-    {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_type(def_id, substs)
-    }
-
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ty::ClosureUpvar<'tcx>>>
-    {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_upvars(def_id, substs)
-    }
-}
-
 pub struct Result<'blk, 'tcx: 'blk> {
     pub bcx: Block<'blk, 'tcx>,
     pub val: ValueRef
@@ -957,12 +865,12 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            trait_ref, trait_ref.def_id());
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+    let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+    let mut selcx = traits::SelectionContext::new(&infcx);
+
     let obligation =
         traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
                                 trait_ref.to_poly_trait_predicate());
@@ -994,7 +902,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // Currently, we use a fulfillment context to completely resolve
     // all nested obligations. This is because they can inform the
     // inference of the impl's type parameters.
-    let mut fulfill_cx = traits::FulfillmentContext::new(true);
+    let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
     let vtable = selection.map(|predicate| {
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
     });
@@ -1019,10 +927,9 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            predicates);
 
     let tcx = ccx.tcx();
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
-    let mut fulfill_cx = traits::FulfillmentContext::new(false);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut selcx = traits::SelectionContext::new(&infcx);
+    let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: predicates, obligations } =
         traits::normalize(&mut selcx, cause.clone(), &predicates);
@@ -1036,57 +943,6 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
 }
 
-// NOTE: here is another use of parameter environment without an InferCtxt,
-// this is obviously related to the typer interface requiring a parameter env.
-// We should pay attention to this when refactoring
-// - @jroesch
-pub struct NormalizingClosureTyper<'a,'tcx:'a> {
-    param_env: ty::ParameterEnvironment<'a, 'tcx>
-}
-
-impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> {
-    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> {
-        // Parameter environment is used to give details about type parameters,
-        // but since we are in trans, everything is fully monomorphized.
-        NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() }
-    }
-}
-
-impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> {
-    fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
-        &self.param_env
-    }
-
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>
-    {
-        self.param_env.closure_kind(def_id)
-    }
-
-    fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>
-    {
-        // the substitutions in `substs` are already monomorphized,
-        // but we still must normalize associated types
-        let closure_ty = self.param_env.tcx.closure_type(def_id, substs);
-        monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
-    }
-
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ty::ClosureUpvar<'tcx>>>
-    {
-        // the substitutions in `substs` are already monomorphized,
-        // but we still must normalize associated types
-        let result = self.param_env.closure_upvars(def_id, substs);
-        monomorphize::normalize_associated_type(self.param_env.tcx, &result)
-    }
-}
-
 pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
                                                 infcx: &infer::InferCtxt<'a,'tcx>,
                                                 fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
@@ -1124,8 +980,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    let typer = NormalizingClosureTyper::new(infcx.tcx);
-    match fulfill_cx.select_all_or_error(infcx, &typer) {
+    match fulfill_cx.select_all_or_error(infcx) {
         Ok(()) => { }
         Err(errors) => {
             return Err(errors);
index 2c539b67cb6274c282e6c1de5651412274d6020c..c0ebffb58afcf088ed10c9fab0cf63167261eda0 100644 (file)
 use trans::expr;
 use trans::tvec;
 use trans::type_of;
-use middle::mem_categorization::Typer;
 use middle::ty::Ty;
 
 use std::fmt;
@@ -606,8 +605,8 @@ pub fn shallow_copy<'blk>(&self,
          * affine values (since they must never be duplicated).
          */
 
-        assert!(!bcx.tcx().empty_parameter_environment()
-                          .type_moves_by_default(self.ty, DUMMY_SP));
+        assert!(!self.ty
+                     .moves_by_default(&bcx.tcx().empty_parameter_environment(), DUMMY_SP));
         self.shallow_copy_raw(bcx, dst)
     }
 
index a6f1199d0ffe7354997e18371da1e768a47626fc..f7b0f37c9ff78bbbb337417310adede676f60942 100644 (file)
@@ -16,7 +16,6 @@
 use trans::common::{C_bytes, CrateContext};
 use trans::declare;
 use trans::type_::Type;
-use middle::ty::ClosureTyper;
 use session::config::NoDebugInfo;
 
 use std::ffi::CString;
index 1fbbf0763aa53ba293c5f394a0167047ca0a6b58..45349969a0b3e33000f5570f3bfe36e8a3d5cd57 100644 (file)
 use metadata::csearch;
 use middle::pat_util;
 use middle::subst::{self, Substs};
+use middle::infer;
 use rustc::ast_map;
 use trans::{type_of, adt, machine, monomorphize};
-use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
+use trans::common::{self, CrateContext, FunctionContext, Block};
 use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
 use trans::type_::Type;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
 use session::config::{self, FullDebugInfo};
 use util::nodemap::FnvHashMap;
 use util::common::path2cstr;
@@ -287,8 +288,8 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                 }
             },
             ty::TyClosure(def_id, substs) => {
-                let typer = NormalizingClosureTyper::new(cx.tcx());
-                let closure_ty = typer.closure_type(def_id, substs);
+                let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+                let closure_ty = infcx.closure_type(def_id, substs);
                 self.get_unique_type_id_of_closure_type(cx,
                                                         closure_ty,
                                                         &mut unique_type_id);
@@ -796,8 +797,8 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
         }
         ty::TyClosure(def_id, substs) => {
-            let typer = NormalizingClosureTyper::new(cx.tcx());
-            let sig = typer.closure_type(def_id, substs).sig;
+            let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+            let sig = infcx.closure_type(def_id, substs).sig;
             subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
         }
         ty::TyStruct(def_id, substs) => {
index 7487e8d331bf55f47af81de1a7fca74fbb4b66fa..3d1b384c2d91517967ec362f33b4e3029070c512 100644 (file)
@@ -30,7 +30,7 @@
 use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
 use trans;
 use trans::monomorphize;
-use middle::ty::{Ty, ClosureTyper};
+use middle::ty::Ty;
 use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
 
index 2e5943a248a5f81bbfd6b128d58f00b80fa86635..8b33acdee8e25db5e1517d2b409039aeeef41325 100644 (file)
@@ -16,7 +16,6 @@
 use llvm::debuginfo::DIScope;
 use rustc::ast_map;
 use trans::common::CrateContext;
-use middle::ty::ClosureTyper;
 
 use std::ffi::CString;
 use std::ptr;
index 6ea43d7392c944e19793905f49b9d3f5a9429802..f411688319981a72bc551ed8e6c317d8f9f5fb55 100644 (file)
@@ -14,7 +14,7 @@
 
 use trans::common::CrateContext;
 use middle::subst::{self, Substs};
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
 
 use syntax::ast;
 use syntax::parse::token;
@@ -225,4 +225,3 @@ fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         output.push('>');
     }
 }
-
index 646ca6733c3b61864c8b2bacc7483f47542ae341..b29da9d560fea89a6eda936982b4ab4f67f341f8 100644 (file)
 //! * Use define_* family of methods when you might be defining the ValueRef.
 //! * When in doubt, define.
 use llvm::{self, ValueRef};
-use middle::ty::{self, ClosureTyper};
+use middle::ty;
+use middle::infer;
 use syntax::abi;
 use trans::attributes;
 use trans::base;
-use trans::common;
 use trans::context::CrateContext;
 use trans::monomorphize;
 use trans::type_::Type;
@@ -117,8 +117,8 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
             (&f.sig, f.abi, None)
         }
         ty::TyClosure(closure_did, substs) => {
-            let typer = common::NormalizingClosureTyper::new(ccx.tcx());
-            function_type = typer.closure_type(closure_did, substs);
+            let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+            function_type = infcx.closure_type(closure_did, substs);
             let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
             let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
             debug!("declare_rust_fn function_type={:?} self_type={:?}",
index 045cc69bf954b26c357015ed0e80c5edce398d88..d7ce50082f1d3fea0f9d4d833899ff46592b9507 100644 (file)
@@ -56,7 +56,6 @@
 use middle::check_const;
 use middle::def;
 use middle::lang_items::CoerceUnsizedTraitLangItem;
-use middle::mem_categorization::Typer;
 use middle::subst::{Substs, VecPerParamSpace};
 use middle::traits;
 use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
@@ -292,9 +291,6 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
     GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
 }
 
-pub fn make_fat_ptr(bcx: Block, ty: Type, data: ValueRef, extra: ValueRef) -> ValueRef {
-    InsertValue(bcx, InsertValue(bcx, C_undef(ty), data, 0), extra, 1)
-}
 pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
     Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
     Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));
index e46c3b5fab1f784e7a34ebbc55f5a3e4c44ca580..1b01fb6c7f86d903d06d45209f4fa43d96ff8a98 100644 (file)
@@ -17,7 +17,6 @@
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
-use middle::ty::ClosureTyper;
 use rustc::ast_map;
 use trans::base::*;
 use trans::build::*;
index 67ccf64621a854cf0e17037738e2ee0993657462..3ef72e2c4af3ab7218cf9e7f4e4c078f4f56a78c 100644 (file)
@@ -322,11 +322,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
     }
 
     // FIXME(#20304) -- cache
-    // NOTE: @jroesch
-    // Here is of an example where we do not use a param_env but use a typer instead.
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+    let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+    let mut selcx = traits::SelectionContext::new(&infcx);
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: result, obligations } =
         traits::normalize(&mut selcx, cause, &value);
@@ -335,7 +332,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
            result,
            obligations);
 
-    let mut fulfill_cx = traits::FulfillmentContext::new(true);
+    let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+
     for obligation in obligations {
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
index 20d25518e2700c8a7dd2b5d5081dad22229b285c..4359a8d270da260c7283fc320cf2b21be8338fbd 100644 (file)
@@ -54,17 +54,11 @@ pub fn type_of_explicit_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-/// Yields the types of the "real" arguments for this function. For most
-/// functions, these are simply the types of the arguments. For functions with
-/// the `RustCall` ABI, however, this untuples the arguments of the function.
-pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                                inputs: &[Ty<'tcx>],
-                                                abi: abi::Abi)
-                                                -> Vec<Ty<'tcx>> {
-    if abi != abi::RustCall {
-        return inputs.iter().cloned().collect()
-    }
-
+/// Yields the types of the "real" arguments for a function using the `RustCall`
+/// ABI by untupling the arguments of the function.
+pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                   inputs: &[Ty<'tcx>])
+                                   -> Vec<Ty<'tcx>> {
     if inputs.is_empty() {
         return Vec::new()
     }
@@ -78,7 +72,7 @@ pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     match inputs[inputs.len() - 1].sty {
         ty::TyTuple(ref tupled_arguments) => {
-            debug!("untuple_arguments_if_necessary(): untupling arguments");
+            debug!("untuple_arguments(): untupling arguments");
             for &tupled_argument in tupled_arguments {
                 result.push(tupled_argument);
             }
@@ -108,7 +102,11 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let mut atys: Vec<Type> = Vec::new();
 
     // First, munge the inputs, if this has the `rust-call` ABI.
-    let inputs = untuple_arguments_if_necessary(cx, &sig.inputs, abi);
+    let inputs = &if abi == abi::RustCall {
+        untuple_arguments(cx, &sig.inputs)
+    } else {
+        sig.inputs
+    };
 
     // Arg 0: Output pointer.
     // (if the output type is non-immediate)
@@ -136,7 +134,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     // ... then explicit args.
-    for input in &inputs {
+    for input in inputs {
         let arg_ty = type_of_explicit_arg(cx, input);
 
         if type_is_fat_ptr(cx.tcx(), input) {
index 4eafbaaf794d21914b5aef521b1f9eb121d79d4d..c80c48a96922dd7dd3c63df3b705918a86dcc1d6 100644 (file)
 use middle::infer::InferCtxt;
 use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
                      SelectionContext, ObligationCause};
-use middle::ty::{self, HasTypeFlags};
+use middle::ty::HasTypeFlags;
 use middle::ty_fold::TypeFoldable;
 use syntax::ast;
 use syntax::codemap::Span;
 
+//FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
 pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
-                                                typer: &(ty::ClosureTyper<'tcx>+'a),
                                                 fulfillment_cx: &mut FulfillmentContext<'tcx>,
                                                 span: Span,
                                                 body_id: ast::NodeId,
@@ -26,7 +26,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     debug!("normalize_associated_types_in(value={:?})", value);
-    let mut selcx = SelectionContext::new(infcx, typer);
+    let mut selcx = SelectionContext::new(infcx);
     let cause = ObligationCause::new(span, body_id, MiscObligation);
     let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
     debug!("normalize_associated_types_in: result={:?} predicates={:?}",
index d29c0494572cb4d3e9b098bc6b029e7f59912c0c..f32a4fe43d6964da162e8a9835aa47350c1b9ac8 100644 (file)
@@ -27,7 +27,7 @@
 
 use CrateCtxt;
 use middle::infer;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty};
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token;
index b5ee46ece94be16d505654aaa7dc5f7d68b6bf8b..6d1e9dfacf2816e55e6035e818bb03a8e58acfc8 100644 (file)
@@ -125,7 +125,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
     expected_vid: ty::TyVid)
     -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
 {
-    let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+    let fulfillment_cx = fcx.inh.infcx.fulfillment_cx.borrow();
     // Here `expected_ty` is known to be a type inference variable.
 
     let expected_sig =
index b38b6884a98ad639688ca6e2ed0cc970bf113562..a0abef74907037156fb69f7567b939a5e98d0b3a 100644 (file)
@@ -273,7 +273,7 @@ fn coerce_unsized(&self,
         };
         let source = source.adjust_for_autoref(self.tcx(), reborrow);
 
-        let mut selcx = traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+        let mut selcx = traits::SelectionContext::new(self.fcx.infcx());
 
         // Use a FIFO queue for this custom fulfillment procedure.
         let mut queue = VecDeque::new();
index f62411e85828de96c2fcabc219d83d19b55052d6..7926394ebb5176cfe976064870d0e4813bc8f3f9 100644 (file)
@@ -43,8 +43,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
            impl_trait_ref);
 
-    let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
-    let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+    let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
 
     let trait_to_impl_substs = &impl_trait_ref.substs;
 
@@ -246,7 +246,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_impl_method: trait_bounds={:?}",
         infcx.parameter_environment.caller_bounds);
 
-    let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
+    let mut selcx = traits::SelectionContext::new(&infcx);
 
     for predicate in impl_pred.fns {
         let traits::Normalized { value: predicate, .. } =
@@ -293,7 +293,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             impl_sig.subst(tcx, impl_to_skol_substs);
         let impl_sig =
             assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
                                                  &mut fulfillment_cx,
                                                  impl_m_span,
                                                  impl_m_body_id,
@@ -312,7 +311,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             trait_sig.subst(tcx, &trait_to_skol_substs);
         let trait_sig =
             assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
                                                  &mut fulfillment_cx,
                                                  impl_m_span,
                                                  impl_m_body_id,
@@ -347,7 +345,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     // Check that all obligations are satisfied by the implementation's
     // version.
-    match fulfillment_cx.select_all_or_error(&infcx, &infcx.parameter_environment) {
+    match fulfillment_cx.select_all_or_error(&infcx) {
         Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
         Ok(_) => {}
     }
@@ -419,8 +417,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_const_impl(impl_trait_ref={:?})",
            impl_trait_ref);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
-    let mut fulfillment_cx = traits::FulfillmentContext::new(true);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut fulfillment_cx = infcx.fulfillment_cx.borrow_mut();
 
     // The below is for the most part highly similar to the procedure
     // for methods above. It is simpler in many respects, especially
@@ -456,21 +454,21 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
         // There is no "body" here, so just pass dummy id.
         let impl_ty =
             assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
                                                  &mut fulfillment_cx,
                                                  impl_c_span,
                                                  0,
                                                  &impl_ty);
+
         debug!("compare_const_impl: impl_ty={:?}",
                impl_ty);
 
         let trait_ty =
             assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
                                                  &mut fulfillment_cx,
                                                  impl_c_span,
                                                  0,
                                                  &trait_ty);
+
         debug!("compare_const_impl: trait_ty={:?}",
                trait_ty);
 
index 6f0fbfebf46cc8fd37192d5b5a6833c7a1452b5b..7d911cf8b03bc3c4d217d5254e1a58e6761ae3fd 100644 (file)
@@ -93,7 +93,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
                          ty: named_type } =
         tcx.lookup_item_type(self_type_did);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
 
     infcx.commit_if_ok(|snapshot| {
         let (named_type_to_skolem, skol_map) =
index 9c2d1c4a34df1dbd9a3d9337b5054229eb5410fb..7a887fac9d402b3d0a9a92e634899fe82bb7f569 100644 (file)
@@ -12,7 +12,6 @@
 
 use check::{self, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
 use check::UnresolvedTypeAction;
-use middle::mem_categorization::Typer;
 use middle::subst::{self};
 use middle::traits;
 use middle::ty::{self, Ty};
index f312db9c4dcf2b75ff48925020a294cb16c6699f..7ed5c69ad61577ea02c93c69b0e0af14aa77afd0 100644 (file)
@@ -195,7 +195,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                               poly_trait_ref.to_predicate());
 
     // Now we want to know if this can be matched
-    let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+    let mut selcx = traits::SelectionContext::new(fcx.infcx());
     if !selcx.evaluate_obligation(&obligation) {
         debug!("--> Cannot match obligation");
         return None; // Cannot be matched, no such method resolution is possible.
index 94a2050829dfa3213f332ab7a579f7f7cfa3d503..8eb4716cb2a690ea13b251d027401fdcf155b9be 100644 (file)
@@ -421,7 +421,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
         // We can't use normalize_associated_types_in as it will pollute the
         // fcx's fulfillment context after this probe is over.
         let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
-        let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+        let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
         let traits::Normalized { value: xform_self_ty, obligations } =
             traits::normalize(selcx, cause, &xform_self_ty);
         debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
@@ -681,7 +681,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
             // as it will pollute the fcx's fulfillment context after this probe
             // is over.
             let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
-            let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx.infcx());
+            let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx());
             let traits::Normalized { value: xform_self_ty, obligations } =
                 traits::normalize(selcx, cause, &xform_self_ty);
 
@@ -1076,7 +1076,7 @@ fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>,
             match probe.kind {
                 InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
                 ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
-                    let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx.infcx());
+                    let selcx = &mut traits::SelectionContext::new(self.infcx());
                     let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
                     // Check whether the impl imposes obligations we have to worry about.
index b81b672e684a5aa76f740a2e25615e60f25920c7..d6a8b3583f8ca74ff54b5cce6eecf8a597529679 100644 (file)
@@ -102,7 +102,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                             let obligation = Obligation::misc(span,
                                                               fcx.body_id,
                                                               poly_trait_ref.to_predicate());
-                            let mut selcx = SelectionContext::new(infcx, fcx.infcx());
+                            let mut selcx = SelectionContext::new(infcx);
 
                             if selcx.evaluate_obligation(&obligation) {
                                 span_stored_function();
index 2db1598db4bee02fb758a85e544e21163f6230e5..c6975982c8747013003e39154389a009400ccb70 100644 (file)
@@ -158,9 +158,6 @@ pub struct Inherited<'a, 'tcx: 'a> {
     // one is never copied into the tcx: it is only used by regionck.
     fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
 
-    // Tracks trait obligations incurred during this function body.
-    fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
-
     // When we process a call like `c()` where `c` is a closure type,
     // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
     // `FnOnce` closure. In that case, we defer full resolution of the
@@ -295,28 +292,26 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
            -> Inherited<'a, 'tcx> {
 
         Inherited {
-            infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
+            infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
             locals: RefCell::new(NodeMap()),
             tables: tables,
             fn_sig_map: RefCell::new(NodeMap()),
-            fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
         }
     }
 
     fn normalize_associated_types_in<T>(&self,
-                                        typer: &ty::ClosureTyper<'tcx>,
                                         span: Span,
                                         body_id: ast::NodeId,
                                         value: &T)
                                         -> T
         where T : TypeFoldable<'tcx> + HasTypeFlags
     {
-        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+        let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
         assoc::normalize_associated_types_in(&self.infcx,
-                                             typer,
-                                             &mut *fulfillment_cx, span,
+                                             &mut fulfillment_cx,
+                                             span,
                                              body_id,
                                              value)
     }
@@ -431,8 +426,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id),
                                                     &fn_sig);
             let fn_sig =
-                inh.normalize_associated_types_in(&inh.infcx.parameter_environment,
-                                                  body.span,
+                inh.normalize_associated_types_in(body.span,
                                                   body.id,
                                                   &fn_sig);
 
@@ -1377,7 +1371,7 @@ fn instantiate_bounds(&self,
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
         where T : TypeFoldable<'tcx> + HasTypeFlags
     {
-        self.inh.normalize_associated_types_in(self.infcx(), span, self.body_id, value)
+        self.inh.normalize_associated_types_in(span, self.body_id, value)
     }
 
     fn normalize_associated_type(&self,
@@ -1389,10 +1383,11 @@ fn normalize_associated_type(&self,
         let cause = traits::ObligationCause::new(span,
                                                  self.body_id,
                                                  traits::ObligationCauseCode::MiscObligation);
-        self.inh.fulfillment_cx
+        self.inh
+            .infcx
+            .fulfillment_cx
             .borrow_mut()
             .normalize_projection_type(self.infcx(),
-                                       self.infcx(),
                                        ty::ProjectionTy {
                                            trait_ref: trait_ref,
                                            item_name: item_name,
@@ -1502,7 +1497,6 @@ pub fn type_is_known_to_be_sized(&self,
                                      -> bool
     {
         traits::type_known_to_meet_builtin_bound(self.infcx(),
-                                                 self.param_env(),
                                                  ty,
                                                  ty::BoundSized,
                                                  span)
@@ -1513,7 +1507,7 @@ pub fn register_builtin_bound(&self,
                                   builtin_bound: ty::BuiltinBound,
                                   cause: traits::ObligationCause<'tcx>)
     {
-        self.inh.fulfillment_cx.borrow_mut()
+        self.inh.infcx.fulfillment_cx.borrow_mut()
             .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
     }
 
@@ -1522,7 +1516,7 @@ pub fn register_predicate(&self,
     {
         debug!("register_predicate({:?})",
                obligation);
-        self.inh.fulfillment_cx
+        self.inh.infcx.fulfillment_cx
             .borrow_mut()
             .register_predicate_obligation(self.infcx(), obligation);
     }
@@ -1648,7 +1642,7 @@ pub fn register_region_obligation(&self,
                                       region: ty::Region,
                                       cause: traits::ObligationCause<'tcx>)
     {
-        let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
+        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
         fulfillment_cx.register_region_obligation(ty, region, cause);
     }
 
@@ -1747,8 +1741,8 @@ fn select_all_obligations_or_error(&self) {
         assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
 
         self.select_all_obligations_and_apply_defaults();
-        let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
-        match fulfillment_cx.select_all_or_error(self.infcx(), self.infcx()) {
+        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
+        match fulfillment_cx.select_all_or_error(self.infcx()) {
             Ok(()) => { }
             Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
         }
@@ -1757,9 +1751,9 @@ fn select_all_obligations_or_error(&self) {
     /// Select as many obligations as we can at present.
     fn select_obligations_where_possible(&self) {
         match
-            self.inh.fulfillment_cx
+            self.inh.infcx.fulfillment_cx
             .borrow_mut()
-            .select_where_possible(self.infcx(), self.infcx())
+            .select_where_possible(self.infcx())
         {
             Ok(()) => { }
             Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
@@ -1772,9 +1766,9 @@ fn select_obligations_where_possible(&self) {
     /// work.
     fn select_new_obligations(&self) {
         match
-            self.inh.fulfillment_cx
+            self.inh.infcx.fulfillment_cx
             .borrow_mut()
-            .select_new_obligations(self.infcx(), self.infcx())
+            .select_new_obligations(self.infcx())
         {
             Ok(()) => { }
             Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
@@ -4007,7 +4001,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let inh = static_inherited_fields(ccx, &tables);
     let rty = ccx.tcx.node_id_to_type(id);
     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
-    let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
+    let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
     check_const_with_ty(&fcx, sp, e, declty);
 }
 
index a86301907385a1246dc033758bddee9fe4fb9de4..bb3c9f9fb542508d4818f075648abbded17cf733 100644 (file)
 use check::dropck;
 use check::FnCtxt;
 use middle::free_region::FreeRegionMap;
-use middle::infer::InferCtxt;
 use middle::implicator;
 use middle::mem_categorization as mc;
 use middle::region::CodeExtent;
 use middle::subst::Substs;
 use middle::traits;
-use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall, HasTypeFlags};
+use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags};
 use middle::infer::{self, GenericKind};
 use middle::pat_util;
 
@@ -318,9 +317,13 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
         // Make a copy of the region obligations vec because we'll need
         // to be able to borrow the fulfillment-cx below when projecting.
         let region_obligations =
-            self.fcx.inh.fulfillment_cx.borrow()
-                                       .region_obligations(node_id)
-                                       .to_vec();
+            self.fcx
+                .inh
+                .infcx
+                .fulfillment_cx
+                .borrow()
+                .region_obligations(node_id)
+                .to_vec();
 
         for r_o in &region_obligations {
             debug!("visit_region_obligations: r_o={:?}",
@@ -332,7 +335,7 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
 
         // Processing the region obligations should not cause the list to grow further:
         assert_eq!(region_obligations.len(),
-                   self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len());
+                   self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
     }
 
     /// This method populates the region map's `free_region_map`. It walks over the transformed
@@ -356,7 +359,7 @@ fn relate_free_regions(&mut self,
             debug!("relate_free_regions(t={:?})", ty);
             let body_scope = CodeExtent::from_node_id(body_id);
             let body_scope = ty::ReScope(body_scope);
-            let implications = implicator::implications(self.fcx.infcx(), self.fcx.infcx(), body_id,
+            let implications = implicator::implications(self.fcx.infcx(), body_id,
                                                         ty, body_scope, span);
 
             // Record any relations between free regions that we observe into the free-region-map.
@@ -1097,8 +1100,8 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
 
 /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
 /// needed.
-fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
-                          mc: mc::MemCategorizationContext<InferCtxt<'a, 'tcx>>,
+fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
+                          mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
                           discr_cmt: mc::cmt<'tcx>,
                           root_pat: &ast::Pat) {
     debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
@@ -1405,7 +1408,7 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
            ty,
            region);
 
-    let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx.infcx(), rcx.body_id,
+    let implications = implicator::implications(rcx.fcx.infcx(), rcx.body_id,
                                                 ty, region, origin.span());
     for implication in implications {
         debug!("implication: {:?}", implication);
index df01b99fd9b808cf2748635409dcfc400c6fd70e..7cf7d73a5668c4e1a81a6b5fc5e84fbb5a7896ca 100644 (file)
@@ -268,7 +268,7 @@ fn check_impl(&mut self,
             let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
             let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
             let predicates = {
-                let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx.infcx());
+                let selcx = &mut traits::SelectionContext::new(fcx.infcx());
                 traits::normalize(selcx, cause.clone(), &predicates)
             };
             for predicate in predicates.value.predicates {
index fbabc287342e9e0ce9d5c59f1f6a18e17203580b..20407e927f7ff7f3bcc1164e027cfdcb8be91258 100644 (file)
@@ -214,7 +214,7 @@ fn instantiate_default_methods(
             };
             debug!("new_polytype={:?}", new_polytype);
 
-            tcx.tcache.borrow_mut().insert(new_did, new_polytype);
+            tcx.register_item_type(new_did, new_polytype);
             tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
             tcx.impl_or_trait_items
                .borrow_mut()
@@ -448,7 +448,7 @@ fn check_implementations_of_coerce_unsized(&self) {
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
                    source, target);
 
-            let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+            let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true);
 
             let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
                                mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
@@ -531,7 +531,7 @@ fn check_implementations_of_coerce_unsized(&self) {
                 }
             };
 
-            let mut fulfill_cx = traits::FulfillmentContext::new(true);
+            let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
 
             // Register an obligation for `A: Trait<B>`.
             let cause = traits::ObligationCause::misc(span, impl_did.node);
@@ -540,8 +540,7 @@ fn check_implementations_of_coerce_unsized(&self) {
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
 
             // Check that all transitive obligations are satisfied.
-            if let Err(errors) = fulfill_cx.select_all_or_error(&infcx,
-                                                                &infcx.parameter_environment) {
+            if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
                 traits::report_fulfillment_errors(&infcx, &errors);
             }
 
@@ -632,7 +631,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
 pub fn check_coherence(crate_context: &CrateCtxt) {
     CoherenceChecker {
         crate_context: crate_context,
-        inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None),
+        inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true),
         inherent_impls: RefCell::new(FnvHashMap()),
     }.check(crate_context.tcx.map.krate());
     unsafety::check(crate_context.tcx);
index 3495714fcc7367d08ecd42a5094a7e39977bdfd3..42c6bcbfbb999018705730889e4231c4bd908717 100644 (file)
@@ -133,7 +133,7 @@ fn check_if_impls_overlap(&self,
                    impl1_def_id,
                    impl2_def_id);
 
-            let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+            let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
             if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
                 self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
             }
index 7909908079fb38ca1938887dc0cffc643605870e..5161c84e4b1a6f318a89cfa92a83a77994c75687 100644 (file)
@@ -596,7 +596,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty: result_ty
         };
 
-        tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
+        tcx.register_item_type(variant_def_id, variant_scheme.clone());
         tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
         write_ty_to_tcx(tcx, variant.node.id, result_ty);
     }
@@ -635,7 +635,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
     debug!("method {} (id {}) has type {:?}",
             ident, id, fty);
-    ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
+    ccx.tcx.register_item_type(def_id, TypeScheme {
         generics: ty_method.generics.clone(),
         ty: fty
     });
@@ -661,11 +661,11 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
 
     /* add the field to the tcache */
-    ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
-                                       ty::TypeScheme {
-                                           generics: struct_generics.clone(),
-                                           ty: tt
-                                       });
+    ccx.tcx.register_item_type(local_def(v.node.id),
+                               ty::TypeScheme {
+                                   generics: struct_generics.clone(),
+                                   ty: tt
+                               });
     ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
                                            struct_predicates.clone());
 
@@ -841,9 +841,9 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id),
-                                           TypeScheme { generics: ty_generics.clone(),
-                                                        ty: selfty });
+            tcx.register_item_type(local_def(it.id),
+                                   TypeScheme { generics: ty_generics.clone(),
+                                                ty: selfty });
             tcx.predicates.borrow_mut().insert(local_def(it.id),
                                                ty_predicates.clone());
 
@@ -863,11 +863,11 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
                     let ty = ccx.icx(&ty_predicates)
                                 .to_ty(&ExplicitRscope, &*ty);
-                    tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
-                                                   TypeScheme {
-                                                       generics: ty_generics.clone(),
-                                                       ty: ty,
-                                                   });
+                    tcx.register_item_type(local_def(impl_item.id),
+                                           TypeScheme {
+                                               generics: ty_generics.clone(),
+                                               ty: ty,
+                                           });
                     convert_associated_const(ccx, ImplContainer(local_def(it.id)),
                                              impl_item.ident, impl_item.id,
                                              impl_item.vis.inherit_from(parent_visibility),
@@ -954,11 +954,11 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                     ast::ConstTraitItem(ref ty, ref default) => {
                         let ty = ccx.icx(&trait_predicates)
                                     .to_ty(&ExplicitRscope, ty);
-                        tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
-                                                       TypeScheme {
-                                                           generics: trait_def.generics.clone(),
-                                                           ty: ty,
-                                                       });
+                        tcx.register_item_type(local_def(trait_item.id),
+                                               TypeScheme {
+                                                   generics: trait_def.generics.clone(),
+                                                   ty: ty,
+                                               });
                         convert_associated_const(ccx, TraitContainer(local_def(it.id)),
                                                  trait_item.ident, trait_item.id,
                                                  ast::Public, ty, default.as_ref().map(|d| &**d));
@@ -1099,26 +1099,25 @@ fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 // Enum-like.
                 write_ty_to_tcx(tcx, ctor_id, selfty);
 
-                tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
+                tcx.register_item_type(local_def(ctor_id), scheme);
                 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
             } else if struct_def.fields[0].node.kind.is_unnamed() {
                 // Tuple-like.
                 let inputs: Vec<_> =
                     struct_def.fields
                               .iter()
-                              .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
-                                                              .unwrap()
-                                                              .ty)
+                              .map(|field| tcx.lookup_item_type(
+                                  local_def(field.node.id)).ty)
                               .collect();
                 let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
                                                 &inputs[..],
                                                 selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
-                tcx.tcache.borrow_mut().insert(local_def(ctor_id),
-                                               TypeScheme {
-                                                   generics: scheme.generics,
-                                                   ty: ctor_fn_ty
-                                               });
+                tcx.register_item_type(local_def(ctor_id),
+                                       TypeScheme {
+                                           generics: scheme.generics,
+                                           ty: ctor_fn_ty
+                                       });
                 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
             }
         }
@@ -2211,7 +2210,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                base_type,
                base_type_free);
 
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
         drop(::require_same_types(tcx,
                                   Some(&infcx),
                                   false,
index 05ddfe89bcf5c7786e44e9537ccdf856ba88afec..2c948a45f8c8034883e64dbbbd6ac79f2e475248 100644 (file)
@@ -1347,6 +1347,27 @@ fn foo() -> _ { 5 } // error, explicitly write out the return type instead
 ```
 "##,
 
+E0124: r##"
+You declared two fields of a struct with the same name. Erroneous code
+example:
+
+```
+struct Foo {
+    field1: i32,
+    field1: i32 // error: field is already declared
+}
+```
+
+Please verify that the field names have been correctly spelled. Example:
+
+```
+struct Foo {
+    field1: i32,
+    field2: i32 // ok!
+}
+```
+"##,
+
 E0131: r##"
 It is not possible to define `main` with type parameters, or even with function
 parameters. When `main` is present, it must take no arguments and return `()`.
@@ -1956,7 +1977,6 @@ impl Baz for Bar { } // Note: This is OK
     E0120,
     E0122,
     E0123,
-    E0124,
     E0127,
     E0128,
     E0129,
index 48a64675c708a3c38046e687f5ad490a16db221b..8c3ef4ae631c3ebb53551daa963915f246b0ed3e 100644 (file)
@@ -188,7 +188,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
 {
     let result = match maybe_infcx {
         None => {
-            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
             infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
         }
         Some(infcx) => {
index 760fa329fd9866808f68a7570a4bd2ba48b19c99..847e28d2bc510f7c8816174f05e67c4ba66505ff 100644 (file)
@@ -68,6 +68,7 @@ pub struct flock {
 
     #[cfg(any(target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     mod os {
         use libc;
index a17d121e60a2a834c4928480d6d2d9191ec6d962..3621d18daed818b27fe2ad08b5809804d7c09926 100644 (file)
@@ -160,6 +160,7 @@ fn test_loading_cosine() {
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     fn test_errors_do_not_crash() {
         // Open /dev/null as a library to get an error, and make sure
@@ -179,6 +180,7 @@ fn test_errors_do_not_crash() {
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod dl {
     use prelude::v1::*;
index 2e00e126e2378f8b7f9d385e4d184ad35b9d4411..7c2cd615303c0c19e2e30a6466d3e3e9ec9d44da 100644 (file)
@@ -633,6 +633,7 @@ pub mod consts {
     /// - freebsd
     /// - dragonfly
     /// - bitrig
+    /// - netbsd
     /// - openbsd
     /// - android
     /// - windows
@@ -759,6 +760,17 @@ mod os {
     pub const EXE_EXTENSION: &'static str = "";
 }
 
+#[cfg(target_os = "netbsd")]
+mod os {
+    pub const FAMILY: &'static str = "unix";
+    pub const OS: &'static str = "netbsd";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
+
 #[cfg(target_os = "openbsd")]
 mod os {
     pub const FAMILY: &'static str = "unix";
index 222059e4c0e6a164f6ebd0c26d021e6ee7a46429..085ba286dc3d94d626147e7ca993cabdd7d55c2f 100644 (file)
@@ -904,7 +904,7 @@ fn debug() {
 
     // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+    #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
index c3cf9895205e47290f49cd08d355ca8988fc84d9..0545175d9aee90cb788002205bae53f7d190a4a2 100644 (file)
@@ -360,9 +360,9 @@ fn debug() {
         assert_eq!(format!("{:?}", udpsock), compare);
     }
 
-    // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
+    // FIXME: re-enabled bitrig/openbsd/netbsd tests once their socket timeout code
     //        no longer has rounding errors.
-    #[cfg_attr(any(target_os = "bitrig", target_os = "openbsd"), ignore)]
+    #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
index cc4b1c944e7861124462ef7c53e4239fe1c2b302..859cb900460c54bc7f8fc1449c54b5ed58fd5775 100644 (file)
@@ -24,6 +24,7 @@
 #[cfg(target_os = "linux")]     pub mod linux;
 #[cfg(target_os = "macos")]     pub mod macos;
 #[cfg(target_os = "nacl")]      pub mod nacl;
+#[cfg(target_os = "netbsd")]   pub mod netbsd;
 #[cfg(target_os = "openbsd")]   pub mod openbsd;
 
 pub mod raw;
diff --git a/src/libstd/os/netbsd/mod.rs b/src/libstd/os/netbsd/mod.rs
new file mode 100644 (file)
index 0000000..bdb003b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! OpenBSD-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod raw;
+
+pub mod fs {
+    #![stable(feature = "raw_ext", since = "1.1.0")]
+    pub use sys::fs::MetadataExt;
+}
diff --git a/src/libstd/os/netbsd/raw.rs b/src/libstd/os/netbsd/raw.rs
new file mode 100644 (file)
index 0000000..f9898df
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! NetBSD/OpenBSD-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t};
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = i64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
+
+#[repr(C)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: mode_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: ino_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: nlink_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: uid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: gid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: off_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: blkcnt_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: blksize_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_flags: fflags_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gen: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime_nsec: c_long,
+}
index d23a124a6ecda21ddc572d19f8dc37aa7f9dd2e2..52697f00264beb4f3bd5232ead6109a8f8f7abfe 100644 (file)
@@ -44,6 +44,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod imp {
     use prelude::v1::*;
index 8f75ae5ef5cc8441cd5b3e687a8465687e7928f1..d99b31c9f2b4318ded1c96f695b7bae2d088d7b9 100644 (file)
@@ -106,7 +106,7 @@ pub enum _Unwind_Context {}
 #[link(name = "unwind", kind = "static")]
 extern {}
 
-#[cfg(any(target_os = "android", target_os = "openbsd"))]
+#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
 #[link(name = "gcc")]
 extern {}
 
index be674c83e221351903a0168741077c488cfbf946..a395dbf8995c648a02539fec1330804a8d806e5c 100644 (file)
@@ -39,6 +39,7 @@
 
 #[cfg(any(target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 #[link(name = "pthread")]
 extern {}
index 77aeeca7968099b4d80e1633a695e5556a4bdc35..1453c91fd4d1d019a92890faaaa5552b6a1f41a6 100644 (file)
@@ -768,6 +768,48 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
     /// If the corresponding `Sender` has disconnected, or it disconnects while
     /// this call is blocking, this call will wake up and return `Err` to
     /// indicate that no more messages can ever be received on this channel.
+    /// However, since channels are buffered, messages sent before the disconnect
+    /// will still be properly received.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::mpsc;
+    /// use std::thread;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    /// let handle = thread::spawn(move || {
+    ///     send.send(1u8).unwrap();
+    /// });
+    ///
+    /// handle.join().unwrap();
+    ///
+    /// assert_eq!(Ok(1), recv.recv());
+    /// ```
+    ///
+    /// Buffering behavior:
+    ///
+    /// ```
+    /// use std::sync::mpsc;
+    /// use std::thread;
+    /// use std::sync::mpsc::RecvError;
+    ///
+    /// let (send, recv) = mpsc::channel();
+    /// let handle = thread::spawn(move || {
+    ///     send.send(1u8).unwrap();
+    ///     send.send(2).unwrap();
+    ///     send.send(3).unwrap();
+    ///     drop(send);
+    /// });
+    ///
+    /// // wait for the thread to join so we ensure the sender is dropped
+    /// handle.join().unwrap();
+    ///
+    /// assert_eq!(Ok(1), recv.recv());
+    /// assert_eq!(Ok(2), recv.recv());
+    /// assert_eq!(Ok(3), recv.recv());
+    /// assert_eq!(Err(RecvError), recv.recv());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn recv(&self) -> Result<T, RecvError> {
         loop {
index 11982ebc572e5b3dc571d8a0726d7b5d5583ff8b..002e3b20c354222cff5c7f39eefa0b03ce906790 100644 (file)
@@ -202,6 +202,7 @@ unsafe fn target_record_sp_limit(limit: usize) {
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     unsafe fn target_record_sp_limit(_: usize) {
     }
@@ -299,6 +300,7 @@ unsafe fn target_get_sp_limit() -> usize {
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     #[inline(always)]
     unsafe fn target_get_sp_limit() -> usize {
index b23a3eee1a1738e03e69f9706901a3d5e82b21fa..a5d1595cfeb1f89da2d7e8c8cb0da2b84bc21e74 100644 (file)
@@ -363,6 +363,7 @@ unsafe fn init_state() -> *mut backtrace_state {
         let selfname = if cfg!(target_os = "freebsd") ||
                           cfg!(target_os = "dragonfly") ||
                           cfg!(target_os = "bitrig") ||
+                          cfg!(target_os = "netbsd") ||
                           cfg!(target_os = "openbsd") {
             env::current_exe().ok()
         } else {
index 99a6731c57d95317d597a8ddf4ac2c02f8ff03d8..eeecf7f50f79a52fa522e7a8a173a0a0dfda76fa 100644 (file)
@@ -34,6 +34,7 @@
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 pub const FIOCLEX: libc::c_ulong = 0x20006601;
 
@@ -60,6 +61,7 @@
           target_os = "dragonfly"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
 #[cfg(any(target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101;
 #[cfg(target_os = "android")]
@@ -82,6 +84,7 @@ pub struct passwd {
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 pub struct passwd {
     pub pw_name: *mut libc::c_char,
@@ -321,6 +324,7 @@ pub struct sigaltstack {
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod signal_os {
     use libc;
@@ -348,7 +352,7 @@ mod signal_os {
     pub struct sigset_t {
         bits: [u32; 4],
     }
-    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
     pub type sigset_t = libc::c_uint;
 
     // This structure has more fields, but we're not all that interested in
@@ -365,7 +369,7 @@ pub struct siginfo {
         pub _status: libc::c_int,
         pub si_addr: *mut libc::c_void
     }
-    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
     #[repr(C)]
     pub struct siginfo {
         pub si_signo: libc::c_int,
@@ -375,7 +379,7 @@ pub struct siginfo {
     }
 
     #[cfg(any(target_os = "macos", target_os = "ios",
-              target_os = "bitrig", target_os = "openbsd"))]
+              target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
     #[repr(C)]
     pub struct sigaction {
         pub sa_sigaction: sighandler_t,
index c1a4e8cee9ed4079fdbac145417ef76c7b520351..6fd20b940bb52f14c9c4b53cda1bf2ebf3f8e6f9 100644 (file)
@@ -26,6 +26,7 @@
 #[cfg(target_os = "linux")]     pub use os::linux as platform;
 #[cfg(target_os = "macos")]     pub use os::macos as platform;
 #[cfg(target_os = "nacl")]      pub use os::nacl as platform;
+#[cfg(target_os = "netbsd")]    pub use os::netbsd as platform;
 #[cfg(target_os = "openbsd")]   pub use os::openbsd as platform;
 
 pub mod backtrace;
index 5178d7b8fb1a0ac962ddb058a68fb0b31ff65a20..334dd6b5f18c1ef56b7c35967a3a6c9949c730e8 100644 (file)
@@ -51,23 +51,13 @@ unsafe fn errno_location() -> *const c_int {
         __error()
     }
 
-    #[cfg(target_os = "bitrig")]
-    fn errno_location() -> *const c_int {
-        extern {
-            fn __errno() -> *const c_int;
-        }
-        unsafe {
-            __errno()
-        }
-    }
-
     #[cfg(target_os = "dragonfly")]
     unsafe fn errno_location() -> *const c_int {
         extern { fn __dfly_error() -> *const c_int; }
         __dfly_error()
     }
 
-    #[cfg(target_os = "openbsd")]
+    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
     unsafe fn errno_location() -> *const c_int {
         extern { fn __errno() -> *const c_int; }
         __errno()
@@ -214,7 +204,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     ::fs::read_link("/proc/curproc/file")
 }
 
-#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+#[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use sync::StaticMutex;
     static LOCK: StaticMutex = StaticMutex::new();
@@ -356,6 +346,7 @@ pub fn args() -> Args {
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 pub fn args() -> Args {
     use rt;
index 695d0ddfaaf61f455cbb4faa23d3b276d91418c6..cc78dd4e5ef1233f4ac58a8d1a14e96c8b361f7a 100644 (file)
@@ -423,6 +423,7 @@ pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
index 52494a17b9d24f314a44b4504d15fc1e8aa5ce4b..62689c39255e37f8c5d4054fbdf3099e48c28b46 100644 (file)
@@ -35,6 +35,7 @@ fn drop(&mut self) {
 #[cfg(any(target_os = "linux",
           target_os = "macos",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod imp {
     use sys_common::stack;
@@ -149,6 +150,7 @@ pub unsafe fn drop_handler(handler: &mut Handler) {
 #[cfg(not(any(target_os = "linux",
               target_os = "macos",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd")))]
 mod imp {
     use libc;
index 41e1e206a423a7c43a0869c6ec642a5aedf9d1e9..9c8a1f4ca40ecc7e230da8aecb88f80365af639b 100644 (file)
@@ -55,6 +55,7 @@ pub fn gettimeofday(tp: *mut libc::timeval,
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod os {
     use libc;
index bb0e12e8df89944afeca8653820c5e4c661c9905..17804c8d81ffbbd2744e9a5edfac82a86258094e 100644 (file)
@@ -105,6 +105,7 @@ fn prctl(option: libc::c_int, arg2: libc::c_ulong,
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     pub fn set_name(name: &str) {
         extern {
@@ -162,6 +163,7 @@ fn drop(&mut self) {
 #[cfg(all(not(target_os = "linux"),
           not(target_os = "macos"),
           not(target_os = "bitrig"),
+          not(target_os = "netbsd"),
           not(target_os = "openbsd")))]
 pub mod guard {
     pub unsafe fn current() -> usize { 0 }
@@ -173,6 +175,7 @@ pub unsafe fn init() {}
 #[cfg(any(target_os = "linux",
           target_os = "macos",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 #[allow(unused_imports)]
 pub mod guard {
@@ -193,6 +196,7 @@ pub mod guard {
 
     #[cfg(any(target_os = "macos",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd"))]
     unsafe fn get_stack_start() -> *mut libc::c_void {
         current() as *mut libc::c_void
@@ -258,7 +262,7 @@ pub unsafe fn current() -> usize {
          pthread_get_stacksize_np(pthread_self())) as usize
     }
 
-    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
+    #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
     pub unsafe fn current() -> usize {
         #[repr(C)]
         struct stack_t {
index 3afe84b25804c3c5d11836da16d80052984b7ec0..7238adfcc566de983f2e9542f613367f2b449ef7 100644 (file)
@@ -46,6 +46,7 @@ pub unsafe fn destroy(key: Key) {
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 type pthread_key_t = ::libc::c_int;
 
@@ -54,6 +55,7 @@ pub unsafe fn destroy(key: Key) {
               target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
+              target_os = "netbsd",
               target_os = "openbsd")))]
 type pthread_key_t = ::libc::c_uint;
 
index 6b84baeca7dc9d6a2d0f298c253f53d196de2a62..db0d0f150613953e5100878c7930ae1468656e73 100644 (file)
@@ -80,6 +80,7 @@ pub struct SteadyTime {
     // OpenBSD provide it via libc
     #[cfg(not(any(target_os = "android",
                   target_os = "bitrig",
+                  target_os = "netbsd",
                   target_os = "openbsd",
                   target_env = "musl")))]
     #[link(name = "rt")]
index 7f89ea979391e251d3517090dd73ab8ff4e7c2f8..2ddf685729bcba2d013997c660013b46d66e1815 100644 (file)
@@ -64,6 +64,8 @@
 pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
 pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD;
 
+pub const HANDLE_FLAG_INHERIT: libc::DWORD = 0x00000001;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -408,6 +410,9 @@ pub fn WaitForSingleObject(hHandle: libc::HANDLE,
     pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
                                     lpProfileDir: libc::LPCWSTR,
                                     lpcchSize: *mut libc::DWORD) -> libc::BOOL;
+    pub fn SetHandleInformation(hObject: libc::HANDLE,
+                                dwMask: libc::DWORD,
+                                dwFlags: libc::DWORD) -> libc::BOOL;
 }
 
 // Functions that aren't available on Windows XP, but we still use them and just
index 0b9052672369d40da703be63f36969d1b39d45e9..b765bc6e50085c174da39fe8a8f085b4829e929d 100644 (file)
@@ -82,26 +82,31 @@ pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
             SocketAddr::V4(..) => libc::AF_INET,
             SocketAddr::V6(..) => libc::AF_INET6,
         };
-        let socket = unsafe {
-            c::WSASocketW(fam, ty, 0, 0 as *mut _, 0,
-                          c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT)
-        };
-        match socket {
-            INVALID_SOCKET => Err(last_error()),
-            n => Ok(Socket(n)),
-        }
+        let socket = try!(unsafe {
+            match c::WSASocketW(fam, ty, 0, 0 as *mut _, 0,
+                                c::WSA_FLAG_OVERLAPPED) {
+                INVALID_SOCKET => Err(last_error()),
+                n => Ok(Socket(n)),
+            }
+        });
+        try!(socket.set_no_inherit());
+        Ok(socket)
     }
 
     pub fn accept(&self, storage: *mut libc::sockaddr,
                   len: *mut libc::socklen_t) -> io::Result<Socket> {
-        match unsafe { libc::accept(self.0, storage, len) } {
-            INVALID_SOCKET => Err(last_error()),
-            n => Ok(Socket(n)),
-        }
+        let socket = try!(unsafe {
+            match libc::accept(self.0, storage, len) {
+                INVALID_SOCKET => Err(last_error()),
+                n => Ok(Socket(n)),
+            }
+        });
+        try!(socket.set_no_inherit());
+        Ok(socket)
     }
 
     pub fn duplicate(&self) -> io::Result<Socket> {
-        unsafe {
+        let socket = try!(unsafe {
             let mut info: c::WSAPROTOCOL_INFO = mem::zeroed();
             try!(cvt(c::WSADuplicateSocketW(self.0,
                                             c::GetCurrentProcessId(),
@@ -110,12 +115,13 @@ pub fn duplicate(&self) -> io::Result<Socket> {
                                 info.iSocketType,
                                 info.iProtocol,
                                 &mut info, 0,
-                                c::WSA_FLAG_OVERLAPPED |
-                                    c::WSA_FLAG_NO_HANDLE_INHERIT) {
+                                c::WSA_FLAG_OVERLAPPED) {
                 INVALID_SOCKET => Err(last_error()),
                 n => Ok(Socket(n)),
             }
-        }
+        });
+        try!(socket.set_no_inherit());
+        Ok(socket)
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -156,6 +162,13 @@ pub fn timeout(&self, kind: libc::c_int) -> io::Result<Option<Duration>> {
             Ok(Some(Duration::new(secs as u64, nsec as u32)))
         }
     }
+
+    fn set_no_inherit(&self) -> io::Result<()> {
+        sys::cvt(unsafe {
+            c::SetHandleInformation(self.0 as libc::HANDLE,
+                                    c::HANDLE_FLAG_INHERIT, 0)
+        }).map(|_| ())
+    }
 }
 
 impl Drop for Socket {
index 679902ec7abdb0fdaad47b0deb44b4de3e7c1a13..c2fad0aa89c9376aa8ef77012161169ac18c6caa 100644 (file)
@@ -104,6 +104,7 @@ macro_rules! __scoped_thread_local_inner {
         #[cfg_attr(not(any(windows,
                            target_os = "android",
                            target_os = "ios",
+                           target_os = "netbsd",
                            target_os = "openbsd",
                            target_arch = "aarch64")),
                    thread_local)]
@@ -215,6 +216,7 @@ pub fn is_set(&'static self) -> bool {
 #[cfg(not(any(windows,
               target_os = "android",
               target_os = "ios",
+              target_os = "netbsd",
               target_os = "openbsd",
               target_arch = "aarch64",
               no_elf_tls)))]
@@ -238,6 +240,7 @@ pub unsafe fn get(&self) -> *mut T { self.inner.get() }
 #[cfg(any(windows,
           target_os = "android",
           target_os = "ios",
+          target_os = "netbsd",
           target_os = "openbsd",
           target_arch = "aarch64",
           no_elf_tls))]
index 27e331893e5d7fcd642113988baf2123092ef15a..50c86a80b4ab5e27ae66031489a3b177766d3c6b 100644 (file)
@@ -25,6 +25,7 @@ pub enum Os {
     OsiOS,
     OsDragonfly,
     OsBitrig,
+    OsNetbsd,
     OsOpenbsd,
 }
 
@@ -138,6 +139,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             OsFreebsd => "freebsd".fmt(f),
             OsDragonfly => "dragonfly".fmt(f),
             OsBitrig => "bitrig".fmt(f),
+            OsNetbsd => "netbsd".fmt(f),
             OsOpenbsd => "openbsd".fmt(f),
         }
     }
diff --git a/src/test/compile-fail/issue-8640.rs b/src/test/compile-fail/issue-8640.rs
new file mode 100644 (file)
index 0000000..5c1592e
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(unused_imports)]
+
+mod foo {
+    use baz::bar;
+    //~^ ERROR import `bar` conflicts with existing submodule
+    mod bar {}
+}
+mod baz { pub mod bar {} }
+
+fn main() {}
index f54423139049e89534e4272a08548b5c284732f4..f6606a58ecaf190d58f809febd95ba10d6b77f85 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-windows
 // ignore-freebsd
 // ignore-openbsd
+// ignore-netbsd
 // ignore-bitrig
 
 // compile-flags: -Z parse-only
index 67dd4021cb5c8dd65ae347ec635c2858c4bbc6a6..f147a2dca63432dfe321f8cec58580211f3d392b 100644 (file)
 
 // Test a very simple custom DST coercion.
 
-#![feature(core)]
+#![feature(core, rc_weak)]
 
 use std::cell::RefCell;
-use std::rc::Rc;
+use std::rc::{Rc, Weak};
 
 trait Baz {
     fn get(&self) -> i32;
@@ -36,9 +36,13 @@ fn main() {
     let b: Rc<Baz> = a.clone();
     assert_eq!(b.get(), 42);
 
+    let c: Weak<i32> = a.downgrade();
+    let d: Weak<Baz> = c.clone();
+
     let _c = b.clone();
 
     let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
     let b: Rc<RefCell<Baz>> = a.clone();
     assert_eq!(b.borrow().get(), 42);
+    let c: Weak<RefCell<Baz>> = a.downgrade();
 }
index fa97ef8fcd39434983863aab8b715e1821bca4b1..ef69946d7aa2ad27c943bd0db86744bab4088819 100644 (file)
@@ -22,6 +22,7 @@ mod rusti {
           target_os = "macos",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod m {
     #[main]
index bae95bcb50f50d2beee9c0422df10a11fc1c1748..fc032aa3ff0cdfd45fa9642c7727d8e8e8b40b09 100644 (file)
@@ -40,6 +40,7 @@ struct Outer {
           target_os = "macos",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "netbsd",
           target_os = "openbsd"))]
 mod m {
     #[cfg(target_arch = "x86")]
index c47b95bec2b52daaad2ccb4ce63fd519f76f2302..dca65f03f690af16f126e1c746e80e64d39f26a9 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // ignore-android needs extra network permissions
-// ignore-openbsd system ulimit (Too many open files)
 // ignore-bitrig system ulimit (Too many open files)
+// ignore-netbsd system ulimit (Too many open files)
+// ignore-openbsd system ulimit (Too many open files)
 
 use std::io::prelude::*;
 use std::net::{TcpListener, TcpStream};
index b0bfb5c29c18c9b48ad736d0a2a07fc72bd746bc..62cbb76c3095099038983347f51e7c0b203281a9 100644 (file)
@@ -35,6 +35,7 @@ pub fn main() {
           target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
+          target_os = "netbsd",
           target_os = "openbsd",
           target_os = "android"))]
 pub fn main() { }