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
This commit is contained in:
bors 2014-08-21 12:55:54 +00:00
commit 6f1b1a65ef
7 changed files with 133 additions and 43 deletions

View File

@ -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()
ty::lookup_item_type(typer.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()),
}
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(),
}
}

View File

@ -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 \

View File

@ -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)

View File

@ -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> {

View File

@ -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,

View File

@ -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
}

View File

@ -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,));
}