From bc41cc0ec9fbe395598fde5ef22b3e95582a5236 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 26 Jan 2015 06:22:06 -0500 Subject: [PATCH] Make `unboxed_closure_kind` return `Option` to allow for the possibility that its value is not yet known. --- src/librustc/middle/mem_categorization.rs | 12 ++++++++++-- src/librustc/middle/traits/select.rs | 17 +++++++++++------ src/librustc/middle/ty.rs | 19 +++++++++++++++---- src/librustc_trans/trans/common.rs | 12 +++++++++--- src/librustc_typeck/check/mod.rs | 7 +++++-- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 0d86dbeadf4a..1330ad86bfc9 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -594,8 +594,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { let ty = try!(self.node_ty(fn_node_id)); match ty.sty { ty::ty_closure(closure_id, _, _) => { - let kind = self.typer.closure_kind(closure_id); - self.cat_upvar(id, span, var_id, fn_node_id, kind) + match self.typer.closure_kind(closure_id) { + Some(kind) => { + self.cat_upvar(id, span, var_id, fn_node_id, kind) + } + None => { + self.tcx().sess.span_bug( + span, + &*format!("No closure kind for {:?}", closure_id)); + } + } } _ => { self.tcx().sess.span_bug( diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 5780b5b70f4a..106c07baaa7a 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1024,12 +1024,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { kind, obligation.repr(self.tcx())); - let closure_kind = self.closure_typer.closure_kind(closure_def_id); - - debug!("closure_kind = {:?}", closure_kind); - - if closure_kind == kind { - candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone())); + match self.closure_typer.closure_kind(closure_def_id) { + Some(closure_kind) => { + debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); + if closure_kind == kind { + candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone())); + } + } + None => { + debug!("assemble_unboxed_candidates: closure_kind not yet known"); + candidates.ambiguous = true; + } } Ok(()) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e88e4338cd8..cd9684b840b7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2288,14 +2288,22 @@ impl ClosureKind { pub trait ClosureTyper<'tcx> { fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>; - fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind; + /// 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; + /// Returns the argument/return types of this closure. fn closure_type(&self, def_id: ast::DefId, substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx>; - // Returns `None` if the upvar types cannot yet be definitively determined. + /// 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>) @@ -6473,8 +6481,11 @@ impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> { self } - fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { - self.tcx.closure_kind(def_id) + fn closure_kind(&self, + def_id: ast::DefId) + -> Option + { + Some(self.tcx.closure_kind(def_id)) } fn closure_type(&self, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index a0dbc9c40a68..5782b3987cb4 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -693,7 +693,10 @@ impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> { &self.fcx.param_env } - fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { + fn closure_kind(&self, + def_id: ast::DefId) + -> Option + { let typer = NormalizingClosureTyper::new(self.tcx()); typer.closure_kind(def_id) } @@ -1065,8 +1068,11 @@ impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> { &self.param_env } - fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { - self.param_env.tcx.closure_kind(def_id) + fn closure_kind(&self, + def_id: ast::DefId) + -> Option + { + self.param_env.closure_kind(def_id) } fn closure_type(&self, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 565e96483b9a..285b4fdf2e87 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -348,8 +348,11 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { &self.inh.param_env } - fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { - self.inh.closures.borrow()[def_id].kind + fn closure_kind(&self, + def_id: ast::DefId) + -> Option + { + Some(self.inh.closures.borrow()[def_id].kind) } fn closure_type(&self,