@@ -81,8 +81,6 @@ pub fn check_crate(tcx: ty::ctxt,
8181 tcx. sess . abort_if_errors ( ) ;
8282}
8383
84- type check_fn = @fn ( Context , @freevar_entry ) ;
85-
8684fn check_struct_safe_for_destructor ( cx : Context ,
8785 span : span ,
8886 struct_did : def_id ) {
@@ -163,30 +161,43 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
163161// Yields the appropriate function to check the kind of closed over
164162// variables. `id` is the node_id for some expression that creates the
165163// closure.
166- fn with_appropriate_checker ( cx : Context , id : node_id , b : & fn ( check_fn ) ) {
167- fn check_for_uniq ( cx : Context , fv : @freevar_entry ) {
164+ fn with_appropriate_checker ( cx : Context , id : node_id ,
165+ b : & fn ( checker : & fn ( Context , @freevar_entry ) ) ) {
166+ fn check_for_uniq ( cx : Context , fv : @freevar_entry , bounds : ty:: BuiltinBounds ) {
168167 // all captured data must be owned, regardless of whether it is
169168 // moved in or copied in.
170169 let id = ast_util:: def_id_of_def ( fv. def ) . node ;
171170 let var_t = ty:: node_id_to_type ( cx. tcx , id) ;
171+
172+ // FIXME(#3569): Once closure capabilities are restricted based on their
173+ // incoming bounds, make this check conditional based on the bounds.
172174 if !check_owned ( cx, var_t, fv. span ) { return ; }
173175
174176 // check that only immutable variables are implicitly copied in
175177 check_imm_free_var ( cx, fv. def , fv. span ) ;
178+
179+ check_freevar_bounds ( cx, fv. span , var_t, bounds) ;
176180 }
177181
178- fn check_for_box ( cx : Context , fv : @freevar_entry ) {
182+ fn check_for_box ( cx : Context , fv : @freevar_entry , bounds : ty :: BuiltinBounds ) {
179183 // all captured data must be owned
180184 let id = ast_util:: def_id_of_def ( fv. def ) . node ;
181185 let var_t = ty:: node_id_to_type ( cx. tcx , id) ;
186+
187+ // FIXME(#3569): Once closure capabilities are restricted based on their
188+ // incoming bounds, make this check conditional based on the bounds.
182189 if !check_durable ( cx. tcx , var_t, fv. span ) { return ; }
183190
184191 // check that only immutable variables are implicitly copied in
185192 check_imm_free_var ( cx, fv. def , fv. span ) ;
193+
194+ check_freevar_bounds ( cx, fv. span , var_t, bounds) ;
186195 }
187196
188- fn check_for_block ( _cx : Context , _fv : @freevar_entry ) {
189- // no restrictions
197+ fn check_for_block ( cx : Context , fv : @freevar_entry , bounds : ty:: BuiltinBounds ) {
198+ let id = ast_util:: def_id_of_def ( fv. def ) . node ;
199+ let var_t = ty:: node_id_to_type ( cx. tcx , id) ;
200+ check_freevar_bounds ( cx, fv. span , var_t, bounds) ;
190201 }
191202
192203 fn check_for_bare ( cx : Context , fv : @freevar_entry ) {
@@ -197,14 +208,14 @@ fn with_appropriate_checker(cx: Context, id: node_id, b: &fn(check_fn)) {
197208
198209 let fty = ty:: node_id_to_type ( cx. tcx , id) ;
199210 match ty:: get ( fty) . sty {
200- ty:: ty_closure( ty:: ClosureTy { sigil : OwnedSigil , _} ) => {
201- b ( check_for_uniq)
211+ ty:: ty_closure( ty:: ClosureTy { sigil : OwnedSigil , bounds : bounds , _} ) => {
212+ b ( |cx , fv| check_for_uniq ( cx , fv , bounds ) )
202213 }
203- ty:: ty_closure( ty:: ClosureTy { sigil : ManagedSigil , _} ) => {
204- b ( check_for_box)
214+ ty:: ty_closure( ty:: ClosureTy { sigil : ManagedSigil , bounds : bounds , _} ) => {
215+ b ( |cx , fv| check_for_box ( cx , fv , bounds ) )
205216 }
206- ty:: ty_closure( ty:: ClosureTy { sigil : BorrowedSigil , _} ) => {
207- b ( check_for_block)
217+ ty:: ty_closure( ty:: ClosureTy { sigil : BorrowedSigil , bounds : bounds , _} ) => {
218+ b ( |cx , fv| check_for_block ( cx , fv , bounds ) )
208219 }
209220 ty:: ty_bare_fn( _) => {
210221 b ( check_for_bare)
@@ -272,7 +283,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
272283 type_param_defs. repr( cx. tcx) ) ;
273284 }
274285 for ts. iter( ) . zip( type_param_defs. iter( ) ) . advance |( & ty, type_param_def) | {
275- check_bounds ( cx, type_parameter_id, e. span, ty, type_param_def)
286+ check_typaram_bounds ( cx, type_parameter_id, e. span, ty, type_param_def)
276287 }
277288 }
278289 }
@@ -315,7 +326,7 @@ fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
315326 let type_param_defs =
316327 ty:: lookup_item_type( cx. tcx, did) . generics. type_param_defs;
317328 for ts. iter( ) . zip( type_param_defs. iter( ) ) . advance |( & ty, type_param_def) | {
318- check_bounds ( cx, aty. id, aty. span, ty, type_param_def)
329+ check_typaram_bounds ( cx, aty. id, aty. span, ty, type_param_def)
319330 }
320331 }
321332 }
@@ -324,19 +335,26 @@ fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
324335 visit:: visit_ty( aty, ( cx, v) ) ;
325336}
326337
327- pub fn check_bounds ( cx : Context ,
328- _type_parameter_id : node_id ,
329- sp : span ,
330- ty : ty:: t ,
331- type_param_def : & ty:: TypeParameterDef )
338+ pub fn check_builtin_bounds( cx: Context , ty: ty:: t, bounds: ty:: BuiltinBounds )
339+ -> ty:: BuiltinBounds // returns the missing bounds
332340{
333341 let kind = ty:: type_contents( cx. tcx, ty) ;
334342 let mut missing = ty:: EmptyBuiltinBounds ( ) ;
335- for type_param_def . bounds. builtin_bounds . each |bound| {
343+ for bounds. each |bound| {
336344 if !kind. meets_bound( cx. tcx, bound) {
337345 missing. add( bound) ;
338346 }
339347 }
348+ missing
349+ }
350+
351+ pub fn check_typaram_bounds ( cx : Context ,
352+ _type_parameter_id : node_id ,
353+ sp : span ,
354+ ty : ty:: t ,
355+ type_param_def : & ty:: TypeParameterDef )
356+ {
357+ let missing = check_builtin_bounds ( cx, ty, type_param_def. bounds . builtin_bounds ) ;
340358 if !missing. is_empty ( ) {
341359 cx. tcx . sess . span_err (
342360 sp,
@@ -347,6 +365,23 @@ pub fn check_bounds(cx: Context,
347365 }
348366}
349367
368+ pub fn check_freevar_bounds ( cx : Context , sp : span , ty : ty:: t ,
369+ bounds : ty:: BuiltinBounds )
370+ {
371+ let missing = check_builtin_bounds ( cx, ty, bounds) ;
372+ if !missing. is_empty ( ) {
373+ cx. tcx . sess . span_err (
374+ sp,
375+ fmt ! ( "cannot capture variable of type `%s`, which does not fulfill \
376+ `%s`, in a bounded closure",
377+ ty_to_str( cx. tcx, ty) , missing. user_string( cx. tcx) ) ) ;
378+ cx. tcx . sess . span_note (
379+ sp,
380+ fmt ! ( "this closure's environment must satisfy `%s`" ,
381+ bounds. user_string( cx. tcx) ) ) ;
382+ }
383+ }
384+
350385fn is_nullary_variant ( cx : Context , ex: @expr) -> bool {
351386 match ex. node {
352387 expr_path( _) => {
0 commit comments