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:
commit
6f1b1a65ef
@ -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(),
|
||||
}
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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)
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
17
src/test/run-pass/unboxed-closures-static-call-fn-once.rs
Normal file
17
src/test/run-pass/unboxed-closures-static-call-fn-once.rs
Normal 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,));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user