Skip to content

Commit 0431134

Browse files
committed
Remove the explicit closure kind syntax from the parser and AST;
upgrade the inference based on expected type so that it is able to infer the fn kind in isolation even if the full signature is not available (and we could perhaps do better still in some cases, such as extracting just the types of the arguments but not the return value).
1 parent 47f1865 commit 0431134

File tree

23 files changed

+155
-136
lines changed

23 files changed

+155
-136
lines changed

src/librustc/middle/check_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
4545
ast::ExprLoop(ref b, _) => {
4646
self.with_context(Loop, |v| v.visit_block(&**b));
4747
}
48-
ast::ExprClosure(_, _, _, ref b) => {
48+
ast::ExprClosure(_, _, ref b) => {
4949
self.with_context(Closure, |v| v.visit_block(&**b));
5050
}
5151
ast::ExprBreak(_) => self.require_loop("break", e.span),

src/librustc/middle/liveness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
959959
self.propagate_through_expr(&**e, succ)
960960
}
961961

962-
ast::ExprClosure(_, _, _, ref blk) => {
962+
ast::ExprClosure(_, _, ref blk) => {
963963
debug!("{} is an ExprClosure",
964964
expr_to_string(expr));
965965

src/librustc/middle/mem_categorization.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
739739
};
740740

741741
match fn_expr.node {
742-
ast::ExprClosure(_, _, _, ref body) => body.id,
742+
ast::ExprClosure(_, _, ref body) => body.id,
743743
_ => unreachable!()
744744
}
745745
};

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
324324
tcx: &ty::ctxt) -> ast::NodeId {
325325
match tcx.map.get(closure_id) {
326326
ast_map::NodeExpr(expr) => match expr.node {
327-
ast::ExprClosure(_, _, _, ref block) => {
327+
ast::ExprClosure(_, _, ref block) => {
328328
block.id
329329
}
330330
_ => {

src/librustc_resolve/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4521,7 +4521,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
45214521
visit::walk_expr(self, expr);
45224522
}
45234523

4524-
ExprClosure(_, _, ref fn_decl, ref block) => {
4524+
ExprClosure(_, ref fn_decl, ref block) => {
45254525
self.resolve_function(ClosureRibKind(expr.id),
45264526
Some(&**fn_decl), NoTypeParameters,
45274527
&**block);

src/librustc_trans/save/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
13941394
type, found {:?}", ty)[]),
13951395
}
13961396
},
1397-
ast::ExprClosure(_, _, ref decl, ref body) => {
1397+
ast::ExprClosure(_, ref decl, ref body) => {
13981398
if generated_code(body.span) {
13991399
return
14001400
}

src/librustc_trans/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
13401340
}
13411341
Some(ast_map::NodeExpr(e)) => {
13421342
match e.node {
1343-
ast::ExprClosure(_, _, _, ref blk) => {
1343+
ast::ExprClosure(_, _, ref blk) => {
13441344
blk
13451345
}
13461346
_ => tcx.sess.bug("unexpected expr variant in has_nested_returns")

src/librustc_trans/trans/debuginfo.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,7 +1283,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
12831283
}
12841284
ast_map::NodeExpr(ref expr) => {
12851285
match expr.node {
1286-
ast::ExprClosure(_, _, ref fn_decl, ref top_level_block) => {
1286+
ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
12871287
let name = format!("fn{}", token::gensym("fn"));
12881288
let name = token::str_to_ident(&name[]);
12891289
(name, &**fn_decl,
@@ -3595,7 +3595,7 @@ fn create_scope_map(cx: &CrateContext,
35953595
})
35963596
}
35973597

3598-
ast::ExprClosure(_, _, ref decl, ref block) => {
3598+
ast::ExprClosure(_, ref decl, ref block) => {
35993599
with_new_scope(cx,
36003600
block.span,
36013601
scope_stack,

src/librustc_trans/trans/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
10941094
ast::ExprVec(..) | ast::ExprRepeat(..) => {
10951095
tvec::trans_fixed_vstore(bcx, expr, dest)
10961096
}
1097-
ast::ExprClosure(_, _, ref decl, ref body) => {
1097+
ast::ExprClosure(_, ref decl, ref body) => {
10981098
closure::trans_closure_expr(bcx, &**decl, &**body, expr.id, dest)
10991099
}
11001100
ast::ExprCall(ref f, ref args) => {

src/librustc_typeck/check/closure.rs

Lines changed: 90 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,46 +25,21 @@ use util::ppaux::Repr;
2525
pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2626
expr: &ast::Expr,
2727
_capture: ast::CaptureClause,
28-
opt_kind: Option<ast::ClosureKind>,
2928
decl: &'tcx ast::FnDecl,
3029
body: &'tcx ast::Block,
3130
expected: Expectation<'tcx>) {
3231
debug!("check_expr_closure(expr={},expected={})",
3332
expr.repr(fcx.tcx()),
3433
expected.repr(fcx.tcx()));
3534

36-
let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| {
37-
deduce_expectations_from_expected_type(fcx, ty)
38-
});
39-
40-
match opt_kind {
41-
None => {
42-
// If users didn't specify what sort of closure they want,
43-
// examine the expected type. For now, if we see explicit
44-
// evidence than an unboxed closure is desired, we'll use
45-
// that. Otherwise, we leave it unspecified, to be filled
46-
// in by upvar inference.
47-
match expected_sig_and_kind {
48-
None => { // don't have information about the kind, request explicit annotation
49-
check_closure(fcx, expr, None, decl, body, None);
50-
},
51-
Some((sig, kind)) => {
52-
check_closure(fcx, expr, Some(kind), decl, body, Some(sig));
53-
}
54-
}
55-
}
56-
57-
Some(kind) => {
58-
let kind = match kind {
59-
ast::FnClosureKind => ty::FnClosureKind,
60-
ast::FnMutClosureKind => ty::FnMutClosureKind,
61-
ast::FnOnceClosureKind => ty::FnOnceClosureKind,
62-
};
63-
64-
let expected_sig = expected_sig_and_kind.map(|t| t.0);
65-
check_closure(fcx, expr, Some(kind), decl, body, expected_sig);
66-
}
67-
}
35+
// It's always helpful for inference if we know the kind of
36+
// closure sooner rather than later, so first examine the expected
37+
// type, and see if can glean a closure kind from there.
38+
let (expected_sig,expected_kind) = match expected.to_option(fcx) {
39+
Some(ty) => deduce_expectations_from_expected_type(fcx, ty),
40+
None => (None, None)
41+
};
42+
check_closure(fcx, expr, expected_kind, decl, body, expected_sig)
6843
}
6944

7045
fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
@@ -133,55 +108,92 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
133108
fn deduce_expectations_from_expected_type<'a,'tcx>(
134109
fcx: &FnCtxt<'a,'tcx>,
135110
expected_ty: Ty<'tcx>)
136-
-> Option<(ty::FnSig<'tcx>,ty::ClosureKind)>
111+
-> (Option<ty::FnSig<'tcx>>,Option<ty::ClosureKind>)
137112
{
113+
debug!("deduce_expectations_from_expected_type(expected_ty={})",
114+
expected_ty.repr(fcx.tcx()));
115+
138116
match expected_ty.sty {
139117
ty::ty_trait(ref object_type) => {
140118
let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
141119
fcx.tcx().types.err);
142-
proj_bounds.iter()
143-
.filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
144-
.next()
120+
let expectations =
121+
proj_bounds.iter()
122+
.filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
123+
.next();
124+
125+
match expectations {
126+
Some((sig, kind)) => (Some(sig), Some(kind)),
127+
None => (None, None)
128+
}
145129
}
146130
ty::ty_infer(ty::TyVar(vid)) => {
147131
deduce_expectations_from_obligations(fcx, vid)
148132
}
149133
_ => {
150-
None
134+
(None, None)
151135
}
152136
}
153137
}
154138

155139
fn deduce_expectations_from_obligations<'a,'tcx>(
156140
fcx: &FnCtxt<'a,'tcx>,
157141
expected_vid: ty::TyVid)
158-
-> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
142+
-> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
159143
{
160144
let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
161145
// Here `expected_ty` is known to be a type inference variable.
162146

163-
fulfillment_cx.pending_obligations()
164-
.iter()
165-
.filter_map(|obligation| {
166-
match obligation.predicate {
167-
ty::Predicate::Projection(ref proj_predicate) => {
168-
let trait_ref = proj_predicate.to_poly_trait_ref();
169-
let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
170-
match self_ty.sty {
171-
ty::ty_infer(ty::TyVar(v)) if expected_vid == v => {
172-
deduce_expectations_from_projection(fcx, proj_predicate)
173-
}
174-
_ => {
175-
None
176-
}
177-
}
178-
}
179-
_ => {
180-
None
181-
}
182-
}
183-
})
184-
.next()
147+
let expected_sig_and_kind =
148+
fulfillment_cx
149+
.pending_obligations()
150+
.iter()
151+
.filter_map(|obligation| {
152+
debug!("deduce_expectations_from_obligations: obligation.predicate={}",
153+
obligation.predicate.repr(fcx.tcx()));
154+
155+
match obligation.predicate {
156+
// Given a Projection predicate, we can potentially infer
157+
// the complete signature.
158+
ty::Predicate::Projection(ref proj_predicate) => {
159+
let trait_ref = proj_predicate.to_poly_trait_ref();
160+
self_type_matches_expected_vid(fcx, trait_ref, expected_vid)
161+
.and_then(|_| deduce_expectations_from_projection(fcx, proj_predicate))
162+
}
163+
_ => {
164+
None
165+
}
166+
}
167+
})
168+
.next();
169+
170+
match expected_sig_and_kind {
171+
Some((sig, kind)) => { return (Some(sig), Some(kind)); }
172+
None => { }
173+
}
174+
175+
// Even if we can't infer the full signature, we may be able to
176+
// infer the kind. This can occur if there is a trait-reference
177+
// like `F : Fn<A>`.
178+
let expected_kind =
179+
fulfillment_cx
180+
.pending_obligations()
181+
.iter()
182+
.filter_map(|obligation| {
183+
let opt_trait_ref = match obligation.predicate {
184+
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()),
185+
ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
186+
ty::Predicate::Equate(..) => None,
187+
ty::Predicate::RegionOutlives(..) => None,
188+
ty::Predicate::TypeOutlives(..) => None,
189+
};
190+
opt_trait_ref
191+
.and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))
192+
.and_then(|trait_ref| fcx.tcx().lang_items.fn_trait_kind(trait_ref.def_id()))
193+
})
194+
.next();
195+
196+
(None, expected_kind)
185197
}
186198

187199
/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
@@ -229,3 +241,20 @@ fn deduce_expectations_from_projection<'a,'tcx>(
229241
return Some((fn_sig, kind));
230242
}
231243

244+
fn self_type_matches_expected_vid<'a,'tcx>(
245+
fcx: &FnCtxt<'a,'tcx>,
246+
trait_ref: ty::PolyTraitRef<'tcx>,
247+
expected_vid: ty::TyVid)
248+
-> Option<ty::PolyTraitRef<'tcx>>
249+
{
250+
let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
251+
debug!("self_type_matches_expected_vid(trait_ref={}, self_ty={})",
252+
trait_ref.repr(fcx.tcx()),
253+
self_ty.repr(fcx.tcx()));
254+
match self_ty.sty {
255+
ty::ty_infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
256+
_ => None,
257+
}
258+
}
259+
260+

src/librustc_typeck/check/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,8 +3736,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
37363736
ast::ExprMatch(ref discrim, ref arms, match_src) => {
37373737
_match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
37383738
}
3739-
ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3740-
closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3739+
ast::ExprClosure(capture, ref decl, ref body) => {
3740+
closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
37413741
}
37423742
ast::ExprBlock(ref b) => {
37433743
check_block_with_expected(fcx, &**b, expected);

src/librustc_typeck/check/regionck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
638638
visit::walk_expr(rcx, expr);
639639
}
640640

641-
ast::ExprClosure(_, _, _, ref body) => {
641+
ast::ExprClosure(_, _, ref body) => {
642642
check_expr_fn_block(rcx, expr, &**body);
643643
}
644644

src/librustc_typeck/check/upvar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ struct SeedBorrowKind<'a,'tcx:'a> {
8383
impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
8484
fn visit_expr(&mut self, expr: &ast::Expr) {
8585
match expr.node {
86-
ast::ExprClosure(cc, _, _, ref body) => {
86+
ast::ExprClosure(cc, _, ref body) => {
8787
self.check_closure(expr, cc, &**body);
8888
}
8989

src/librustc_typeck/check/writeback.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
118118
MethodCall::expr(e.id));
119119

120120
match e.node {
121-
ast::ExprClosure(_, _, ref decl, _) => {
121+
ast::ExprClosure(_, ref decl, _) => {
122122
for input in &decl.inputs {
123123
let _ = self.visit_node_id(ResolvingExpr(e.span),
124124
input.id);

src/libsyntax/ast.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ pub use self::TraitItem::*;
4848
pub use self::Ty_::*;
4949
pub use self::TyParamBound::*;
5050
pub use self::UintTy::*;
51-
pub use self::ClosureKind::*;
5251
pub use self::UnOp::*;
5352
pub use self::UnsafeSource::*;
5453
pub use self::VariantKind::*;
@@ -736,7 +735,7 @@ pub enum Expr_ {
736735
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
737736
ExprLoop(P<Block>, Option<Ident>),
738737
ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
739-
ExprClosure(CaptureClause, Option<ClosureKind>, P<FnDecl>, P<Block>),
738+
ExprClosure(CaptureClause, P<FnDecl>, P<Block>),
740739
ExprBlock(P<Block>),
741740

742741
ExprAssign(P<Expr>, P<Expr>),
@@ -1687,13 +1686,6 @@ impl ForeignItem_ {
16871686
}
16881687
}
16891688

1690-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
1691-
pub enum ClosureKind {
1692-
FnClosureKind,
1693-
FnMutClosureKind,
1694-
FnOnceClosureKind,
1695-
}
1696-
16971689
/// The data we save and restore about an inlined item or method. This is not
16981690
/// part of the AST that we parse from a file, but it becomes part of the tree
16991691
/// that we trans.

src/libsyntax/ast_map/blocks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'a> FnLikeNode<'a> {
218218
}
219219
}
220220
ast_map::NodeExpr(e) => match e.node {
221-
ast::ExprClosure(_, _, ref decl, ref block) =>
221+
ast::ExprClosure(_, ref decl, ref block) =>
222222
closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
223223
_ => panic!("expr FnLikeNode that is not fn-like"),
224224
},

src/libsyntax/ext/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,14 +876,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
876876

877877
fn lambda_fn_decl(&self, span: Span,
878878
fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr> {
879-
self.expr(span, ast::ExprClosure(ast::CaptureByRef, None, fn_decl, blk))
879+
self.expr(span, ast::ExprClosure(ast::CaptureByRef, fn_decl, blk))
880880
}
881881
fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr> {
882882
let fn_decl = self.fn_decl(
883883
ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
884884
self.ty_infer(span));
885885

886-
self.expr(span, ast::ExprClosure(ast::CaptureByRef, None, fn_decl, blk))
886+
self.expr(span, ast::ExprClosure(ast::CaptureByRef, fn_decl, blk))
887887
}
888888
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
889889
self.lambda(span, Vec::new(), blk)

src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,11 +322,10 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
322322
fld.cx.expr_match(span, into_iter_expr, vec![iter_arm])
323323
}
324324

325-
ast::ExprClosure(capture_clause, opt_kind, fn_decl, block) => {
325+
ast::ExprClosure(capture_clause, fn_decl, block) => {
326326
let (rewritten_fn_decl, rewritten_block)
327327
= expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
328328
let new_node = ast::ExprClosure(capture_clause,
329-
opt_kind,
330329
rewritten_fn_decl,
331330
rewritten_block);
332331
P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)})

0 commit comments

Comments
 (0)