Skip to content

Commit 043c97b

Browse files
committed
move the signature into the closure type
1 parent 08d1d6c commit 043c97b

File tree

9 files changed

+66
-26
lines changed

9 files changed

+66
-26
lines changed

src/librustc/infer/error_reporting/need_type_info.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
125125
// ```
126126
labels.clear();
127127
labels.push((pattern.span, format!("consider giving this closure parameter a type")));
128-
}
129-
130-
if let Some(pattern) = local_visitor.found_local_pattern {
128+
} else if let Some(pattern) = local_visitor.found_local_pattern {
131129
if let Some(simple_name) = pattern.simple_name() {
132130
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
133131
} else {

src/librustc/ty/sty.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub enum TypeVariants<'tcx> {
173173

174174
/// A closure can be modeled as a struct that looks like:
175175
///
176-
/// struct Closure<'l0...'li, T0...Tj, CK, U0...Uk> {
176+
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> {
177177
/// upvar0: U0,
178178
/// ...
179179
/// upvark: Uk
@@ -186,6 +186,10 @@ pub enum TypeVariants<'tcx> {
186186
/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
187187
/// is rather hackily encoded via a scalar type. See
188188
/// `TyS::to_opt_closure_kind` for details.
189+
/// - CS represents the *closure signature*, representing as a `fn()`
190+
/// type. For example, `fn(u32, u32) -> u32` would mean that the closure
191+
/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
192+
/// specified above.
189193
/// - U0...Uk are type parameters representing the types of its upvars
190194
/// (borrowed, if appropriate; that is, if Ui represents a by-ref upvar,
191195
/// and the up-var has the type `Foo`, then `Ui = &Foo`).
@@ -265,6 +269,7 @@ pub struct ClosureSubsts<'tcx> {
265269
/// parent slice and not canonical substs themselves.
266270
struct SplitClosureSubsts<'tcx> {
267271
closure_kind_ty: Ty<'tcx>,
272+
closure_sig_ty: Ty<'tcx>,
268273
upvar_kinds: &'tcx [Kind<'tcx>],
269274
}
270275

@@ -276,8 +281,9 @@ impl<'tcx> ClosureSubsts<'tcx> {
276281
let generics = tcx.generics_of(def_id);
277282
let parent_len = generics.parent_count();
278283
SplitClosureSubsts {
279-
closure_kind_ty: self.substs[parent_len].as_type().expect("closure-kind should be type"),
280-
upvar_kinds: &self.substs[parent_len + 1..],
284+
closure_kind_ty: self.substs[parent_len].as_type().expect("CK should be a type"),
285+
closure_sig_ty: self.substs[parent_len + 1].as_type().expect("CS should be a type"),
286+
upvar_kinds: &self.substs[parent_len + 2..],
281287
}
282288
}
283289

@@ -294,6 +300,20 @@ impl<'tcx> ClosureSubsts<'tcx> {
294300
pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
295301
self.split(def_id, tcx).closure_kind_ty
296302
}
303+
304+
/// Returns the type representing the closure signature for this
305+
/// closure; may contain type variables during inference.
306+
pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
307+
self.split(def_id, tcx).closure_sig_ty
308+
}
309+
310+
/// Extracts the signature from the closure.
311+
pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> ty::PolyFnSig<'tcx> {
312+
match &self.split(def_id, tcx).closure_sig_ty.sty {
313+
ty::TyFnPtr(sig) => *sig,
314+
t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t),
315+
}
316+
}
297317
}
298318

299319
impl<'tcx> ClosureSubsts<'tcx> {

src/librustc/ty/wf.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
336336
}
337337
}
338338

339-
ty::TyGenerator(..) | ty::TyClosure(..) => {
339+
ty::TyGenerator(..) => {
340340
// the types in a closure or generator are always the types of
341341
// local variables (or possibly references to local
342342
// variables), we'll walk those.
@@ -346,6 +346,21 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
346346
// WFedness.)
347347
}
348348

349+
ty::TyClosure(def_id, substs) => {
350+
// Just check the upvar types for WF. This is
351+
// needed because we capture the signature and it
352+
// may not be WF without the implied
353+
// bounds. Consider a closure like `|x: &'a T|` --
354+
// it may be that `T: 'a` is not known to hold in
355+
// the creator's context (and indeed the closure
356+
// may not be invoked by its creator, but rather
357+
// turned to someone who *can* verify that).
358+
subtys.skip_current_subtree(); // subtree handled by compute_projection
359+
for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
360+
self.compute(upvar_ty);
361+
}
362+
}
363+
349364
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
350365
// let the loop iterate into the argument/return
351366
// types appearing in the fn signature

src/librustc_typeck/check/closure.rs

+8
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
110110
self.demand_eqtype(expr.span,
111111
ty::ClosureKind::FnOnce.to_ty(self.tcx),
112112
substs.closure_kind_ty(expr_def_id, self.tcx));
113+
self.demand_eqtype(expr.span,
114+
self.tcx.types.char, // for generator, use some bogus type
115+
substs.closure_sig_ty(expr_def_id, self.tcx));
113116
return self.tcx.mk_generator(expr_def_id, substs, interior);
114117
}
115118

@@ -138,6 +141,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
138141
opt_kind
139142
);
140143

144+
let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
145+
self.demand_eqtype(expr.span,
146+
sig_fn_ptr_ty,
147+
substs.closure_sig_ty(expr_def_id, self.tcx));
148+
141149
self.tables.borrow_mut().closure_tys_mut().insert(expr.hir_id, sig);
142150
if let Some(kind) = opt_kind {
143151
self.demand_eqtype(expr.span,

src/librustc_typeck/collect.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
989989
if let NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) = node {
990990
// add a dummy parameter for the closure kind
991991
types.push(ty::TypeParameterDef {
992-
index: type_start as u32,
992+
index: type_start,
993993
name: Symbol::intern("<closure_kind>"),
994994
def_id,
995995
has_default: false,
@@ -998,9 +998,20 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
998998
synthetic: None,
999999
});
10001000

1001+
// add a dummy parameter for the closure signature
1002+
types.push(ty::TypeParameterDef {
1003+
index: type_start + 1,
1004+
name: Symbol::intern("<closure_signature>"),
1005+
def_id,
1006+
has_default: false,
1007+
object_lifetime_default: rl::Set1::Empty,
1008+
pure_wrt_drop: false,
1009+
synthetic: None,
1010+
});
1011+
10011012
tcx.with_freevars(node_id, |fv| {
1002-
types.extend(fv.iter().zip(1..).map(|(_, i)| ty::TypeParameterDef {
1003-
index: type_start + i as u32,
1013+
types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
1014+
index: type_start + i,
10041015
name: Symbol::intern("<upvar>"),
10051016
def_id,
10061017
has_default: false,

src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ fn bar<F>(blk: F) where F: FnOnce() + 'static {
1313

1414
fn foo(x: &()) {
1515
bar(|| {
16-
//~^ ERROR cannot infer
17-
//~| ERROR does not fulfill
16+
//~^ ERROR does not fulfill
1817
let _ = x;
1918
})
2019
}

src/test/run-pass/issue-21410.rs renamed to src/test/compile-fail/issue-21410.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
fn g<F>(_: F) where F: FnOnce(Option<F>) {}
1212

1313
fn main() {
14-
g(|_| { });
14+
g(|_| { }); //~ ERROR mismatched types
1515
}

src/test/run-pass/issue-25439.rs renamed to src/test/compile-fail/issue-25439.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
1515
}
1616

1717
fn main() {
18-
fix(|_, x| x);
18+
fix(|_, x| x); //~ ERROR mismatched types
1919
}

src/test/ui/block-result/issue-3563.stderr

+1-12
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,5 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
66
|
77
= help: did you mean `a`?
88

9-
error[E0308]: mismatched types
10-
--> $DIR/issue-3563.rs:13:9
11-
|
12-
12 | fn a(&self) {
13-
| - possibly return type missing here?
14-
13 | || self.b()
15-
| ^^^^^^^^^^^ expected (), found closure
16-
|
17-
= note: expected type `()`
18-
found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]`
19-
20-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
2110

0 commit comments

Comments
 (0)