]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #26682 - posix4e:netbsd, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 2 Jul 2015 18:50:46 +0000 (18:50 +0000)
committerbors <bors@rust-lang.org>
Thu, 2 Jul 2015 18:50:46 +0000 (18:50 +0000)
This is dependent on https://github.com/rust-lang/rust-installer/pull/38. Once it is merged we most likely need to update the commit.

67 files changed:
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcore/any.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_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_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/libstd/sync/mpsc/mod.rs
src/test/compile-fail/issue-8640.rs [new file with mode: 0644]
src/test/run-pass/dst-coerce-rc.rs

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 f0c77ae866d599dcf374caf103c793893baa3c89..8d86e6fb194dbe10b1aaa0076b65bbaa6e0441f6 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 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 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..a9617bd17c097e8cbf890c18e39489aebbbd8108 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::*;
@@ -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(),
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..156d591b909f440a463838a24ca28a3b27f2698f 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::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::Session;
@@ -434,8 +435,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);
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..39bb9b25be76ea135437a401eeafc1c90f85a01b 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};
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 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 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 {
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 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();
 }