about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-21 12:55:54 +0000
committerbors <bors@rust-lang.org>2014-08-21 12:55:54 +0000
commit6f1b1a65ef9720e302a2fb5a0601d06c7d0dfa1e (patch)
treedcae18b49343e9df32be966c9ecae3e50b8f942b
parent6de570f8173fb35ad52c4e5b90bae74d282d28ad (diff)
parentb0931a0a0f8ff10befa1e3037b670badca52a65f (diff)
downloadrust-6f1b1a65ef9720e302a2fb5a0601d06c7d0dfa1e.tar.gz
rust-6f1b1a65ef9720e302a2fb5a0601d06c7d0dfa1e.zip
auto merge of #16631 : pcwalton/rust/unboxed-closures-wrong-trait, r=huonw
the right trait and take the method name into account.

Closes #16599.

r? @huonw
-rw-r--r--src/librustc/middle/ty.rs49
-rw-r--r--src/librustc/middle/typeck/check/method.rs53
-rw-r--r--src/librustc/middle/typeck/check/mod.rs37
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs3
-rw-r--r--src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs17
-rw-r--r--src/test/run-pass/unboxed-closures-static-call-fn-once.rs17
7 files changed, 134 insertions, 44 deletions
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index ae96937757f..f9043ca337f 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -19,7 +19,8 @@ use middle::def;
 use middle::dependency_format;
 use middle::freevars::CaptureModeMap;
 use middle::freevars;
-use middle::lang_items::{FnMutTraitLangItem, OpaqueStructLangItem};
+use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
+use middle::lang_items::{FnOnceTraitLangItem, OpaqueStructLangItem};
 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
 use middle::mem_categorization as mc;
 use middle::resolve;
@@ -1205,6 +1206,24 @@ pub enum UnboxedClosureKind {
     FnOnceUnboxedClosureKind,
 }
 
+impl UnboxedClosureKind {
+    pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
+        let result = match *self {
+            FnUnboxedClosureKind => cx.lang_items.require(FnTraitLangItem),
+            FnMutUnboxedClosureKind => {
+                cx.lang_items.require(FnMutTraitLangItem)
+            }
+            FnOnceUnboxedClosureKind => {
+                cx.lang_items.require(FnOnceTraitLangItem)
+            }
+        };
+        match result {
+            Ok(trait_did) => trait_did,
+            Err(err) => cx.sess.fatal(err.as_slice()),
+        }
+    }
+}
+
 pub fn mk_ctxt(s: Session,
                dm: resolve::DefMap,
                named_region_map: resolve_lifetime::NamedRegionMap,
@@ -3195,19 +3214,23 @@ impl AutoRef {
     }
 }
 
-pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
-                                   -> VecPerParamSpace<TypeParameterDef> {
+pub fn method_call_type_param_defs<T>(typer: &T,
+                                      origin: typeck::MethodOrigin)
+                                      -> VecPerParamSpace<TypeParameterDef>
+                                      where T: mc::Typer {
     match origin {
         typeck::MethodStatic(did) => {
-            ty::lookup_item_type(tcx, did).generics.types.clone()
-        }
-        typeck::MethodStaticUnboxedClosure(_) => {
-            match tcx.lang_items.require(FnMutTraitLangItem) {
-                Ok(def_id) => {
-                    lookup_trait_def(tcx, def_id).generics.types.clone()
-                }
-                Err(s) => tcx.sess.fatal(s.as_slice()),
-            }
+            ty::lookup_item_type(typer.tcx(), did).generics.types.clone()
+        }
+        typeck::MethodStaticUnboxedClosure(did) => {
+            let def_id = typer.unboxed_closures()
+                              .borrow()
+                              .find(&did)
+                              .expect("method_call_type_param_defs: didn't \
+                                       find unboxed closure")
+                              .kind
+                              .trait_did(typer.tcx());
+            lookup_trait_def(typer.tcx(), def_id).generics.types.clone()
         }
         typeck::MethodParam(typeck::MethodParam{
             trait_id: trt_id,
@@ -3219,7 +3242,7 @@ pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
                 method_num: n_mth,
                 ..
         }) => {
-            match ty::trait_item(tcx, trt_id, n_mth) {
+            match ty::trait_item(typer.tcx(), trt_id, n_mth) {
                 ty::MethodTraitItem(method) => method.generics.types.clone(),
             }
         }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 1e3ea095704..245bbe396fd 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -534,6 +534,11 @@ impl<'a> LookupContext<'a> {
             ty::MethodTraitItem(method) => method,
         };
 
+        // Make sure it has the right name!
+        if method.ident.name != self.m_name {
+            return
+        }
+
         let vcx = self.fcx.vtable_context();
         let region_params =
             vec!(vcx.infcx.next_region_var(MiscVariable(self.span)));
@@ -562,38 +567,28 @@ impl<'a> LookupContext<'a> {
     fn push_unboxed_closure_call_candidates_if_applicable(
             &mut self,
             closure_did: DefId) {
-        let trait_dids = [
-            self.tcx().lang_items.fn_trait(),
-            self.tcx().lang_items.fn_mut_trait(),
-            self.tcx().lang_items.fn_once_trait()
-        ];
-        for optional_trait_did in trait_dids.iter() {
-            let trait_did = match *optional_trait_did {
-                Some(trait_did) => trait_did,
-                None => continue,
-            };
-
-            match self.tcx().unboxed_closures.borrow().find(&closure_did) {
-                None => {}  // Fall through to try inherited.
-                Some(closure) => {
-                    self.push_unboxed_closure_call_candidate_if_applicable(
-                        trait_did,
-                        closure_did,
-                        &closure.closure_type);
-                    return
-                }
+        match self.tcx().unboxed_closures.borrow().find(&closure_did) {
+            None => {}  // Fall through to try inherited.
+            Some(closure) => {
+                let tcx = self.tcx();
+                self.push_unboxed_closure_call_candidate_if_applicable(
+                    closure.kind.trait_did(tcx),
+                    closure_did,
+                    &closure.closure_type);
+                return
             }
+        }
 
-            match self.fcx.inh.unboxed_closures.borrow().find(&closure_did) {
-                Some(closure) => {
-                    self.push_unboxed_closure_call_candidate_if_applicable(
-                        trait_did,
-                        closure_did,
-                        &closure.closure_type);
-                    return
-                }
-                None => {}
+        match self.fcx.inh.unboxed_closures.borrow().find(&closure_did) {
+            Some(closure) => {
+                let tcx = self.tcx();
+                self.push_unboxed_closure_call_candidate_if_applicable(
+                    closure.kind.trait_did(tcx),
+                    closure_did,
+                    &closure.closure_type);
+                return
             }
+            None => {}
         }
 
         self.tcx().sess.bug("didn't find unboxed closure type in tcx map or \
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 1cec680ff2c..f33406be595 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -79,7 +79,10 @@ type parameter).
 
 use middle::const_eval;
 use middle::def;
+use middle::freevars;
 use middle::lang_items::IteratorItem;
+use middle::mem_categorization::McResult;
+use middle::mem_categorization;
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
 use middle::subst;
@@ -110,6 +113,7 @@ use middle::typeck::no_params;
 use middle::typeck::{require_same_types, vtable_map};
 use middle::typeck::{MethodCall, MethodMap};
 use middle::typeck::{TypeAndSubsts};
+use middle::typeck;
 use middle::lang_items::TypeIdLangItem;
 use lint;
 use util::common::{block_query, indenter, loop_query};
@@ -261,6 +265,39 @@ pub struct FnCtxt<'a> {
     ccx: &'a CrateCtxt<'a>,
 }
 
+impl<'a> mem_categorization::Typer for FnCtxt<'a> {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt {
+        self.ccx.tcx
+    }
+    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
+        self.ccx.tcx.node_ty(id)
+    }
+    fn node_method_ty(&self, method_call: typeck::MethodCall)
+                      -> Option<ty::t> {
+        self.ccx.tcx.node_method_ty(method_call)
+    }
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+        self.ccx.tcx.adjustments()
+    }
+    fn is_method_call(&self, id: ast::NodeId) -> bool {
+        self.ccx.tcx.is_method_call(id)
+    }
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+        self.ccx.tcx.temporary_scope(rvalue_id)
+    }
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
+        self.ccx.tcx.upvar_borrow(upvar_id)
+    }
+    fn capture_mode(&self, closure_expr_id: ast::NodeId)
+                    -> freevars::CaptureMode {
+        self.ccx.tcx.capture_mode(closure_expr_id)
+    }
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+        &self.inh.unboxed_closures
+    }
+}
+
 impl<'a> Inherited<'a> {
     fn new(tcx: &'a ty::ctxt,
            param_env: ty::ParameterEnvironment)
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 8e41c9463f6..3813dd79642 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -263,7 +263,7 @@ impl<'a> Rcx<'a> {
 
 impl<'fcx> mc::Typer for Rcx<'fcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
-        self.fcx.tcx()
+        self.fcx.ccx.tcx
     }
 
     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 1aa469b15ba..0708846af2a 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -774,7 +774,8 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
           Some(method) => {
               debug!("vtable resolution on parameter bounds for method call {}",
                      ex.repr(fcx.tcx()));
-              let type_param_defs = ty::method_call_type_param_defs(cx.tcx, method.origin);
+              let type_param_defs =
+                  ty::method_call_type_param_defs(fcx, method.origin);
               let substs = fcx.method_ty_substs(ex.id);
               let vcx = fcx.vtable_context();
               let vtbls = lookup_vtables(&vcx, ex.span,
diff --git a/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs
new file mode 100644
index 00000000000..871889f26df
--- /dev/null
+++ b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+#![feature(unboxed_closures)]
+
+fn main() {
+    let mut_ = |&mut: x| x;
+    mut_.call_once((0i, )); //~ ERROR type `closure` does not implement
+}
+
diff --git a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
new file mode 100644
index 00000000000..beab82e804b
--- /dev/null
+++ b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+#![feature(unboxed_closures)]
+
+fn main() {
+    let onetime = |: x| x;
+    onetime.call_once((0i,));
+}
+