From 24b089721f2c0e2b25228d3d5d31b5ca70d68070 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 20 Aug 2014 09:12:16 -0700 Subject: [PATCH] librustc: Fix bogus logic for static calls to unboxed closures in the expression use visitor. Closes #16166. --- src/librustc/middle/expr_use_visitor.rs | 30 ++++++++++++------- src/librustc/middle/ty.rs | 21 ++++++++++++- .../unboxed-closures-direct-sugary-call.rs | 17 +++++++++++ 3 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 src/test/run-pass/unboxed-closures-direct-sugary-call.rs diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6caf54790d1b4..20ea2b1fba543 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -130,16 +130,11 @@ impl OverloadedCallType { fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId) -> OverloadedCallType { - let method_descriptor = - match tcx.impl_or_trait_items.borrow_mut().find(&method_id) { - Some(&ty::MethodTraitItem(ref method_descriptor)) => { - (*method_descriptor).clone() - } - None => { - tcx.sess.bug("overloaded call method wasn't in method \ - map") - } - }; + let method_descriptor = match ty::impl_or_trait_item(tcx, method_id) { + ty::MethodTraitItem(ref method_descriptor) => { + (*method_descriptor).clone() + } + }; let impl_id = match method_descriptor.container { ty::TraitContainer(_) => { tcx.sess.bug("statically resolved overloaded call method \ @@ -157,6 +152,19 @@ impl OverloadedCallType { OverloadedCallType::from_trait_id(tcx, trait_ref.def_id) } + fn from_unboxed_closure(tcx: &ty::ctxt, closure_did: ast::DefId) + -> OverloadedCallType { + let trait_did = + tcx.unboxed_closures + .borrow() + .find(&closure_did) + .expect("OverloadedCallType::from_unboxed_closure: didn't \ + find closure id") + .kind + .trait_did(tcx); + OverloadedCallType::from_trait_id(tcx, trait_did) + } + fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin) -> OverloadedCallType { match *origin { @@ -164,7 +172,7 @@ impl OverloadedCallType { OverloadedCallType::from_method_id(tcx, def_id) } MethodStaticUnboxedClosure(def_id) => { - OverloadedCallType::from_method_id(tcx, def_id) + OverloadedCallType::from_unboxed_closure(tcx, def_id) } MethodParam(ref method_param) => { OverloadedCallType::from_trait_id(tcx, method_param.trait_id) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ae96937757f0e..4772f6a4ddb39 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, diff --git a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs new file mode 100644 index 0000000000000..c77ee9914ef2e --- /dev/null +++ b/src/test/run-pass/unboxed-closures-direct-sugary-call.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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures, overloaded_calls)] + +fn main() { + let mut unboxed = |&mut:| {}; + unboxed(); +} +