@@ -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 ) {
@@ -129,7 +127,8 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
129127 if cx. tcx . lang_items . drop_trait ( ) == trait_def_id {
130128 // Yes, it's a destructor.
131129 match self_type. node {
132- ty_path( _, path_node_id) => {
130+ ty_path( _, bounds, path_node_id) => {
131+ assert ! ( bounds. is_empty( ) ) ;
133132 let struct_def = cx. tcx . def_map . get_copy (
134133 & path_node_id) ;
135134 let struct_did =
@@ -162,30 +161,43 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
162161// Yields the appropriate function to check the kind of closed over
163162// variables. `id` is the node_id for some expression that creates the
164163// closure.
165- fn with_appropriate_checker ( cx : Context , id : node_id , b : & fn ( check_fn ) ) {
166- 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 ) {
167167 // all captured data must be owned, regardless of whether it is
168168 // moved in or copied in.
169169 let id = ast_util:: def_id_of_def ( fv. def ) . node ;
170170 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.
171174 if !check_owned ( cx, var_t, fv. span ) { return ; }
172175
173176 // check that only immutable variables are implicitly copied in
174177 check_imm_free_var ( cx, fv. def , fv. span ) ;
178+
179+ check_freevar_bounds ( cx, fv. span , var_t, bounds) ;
175180 }
176181
177- fn check_for_box ( cx : Context , fv : @freevar_entry ) {
182+ fn check_for_box ( cx : Context , fv : @freevar_entry , bounds : ty :: BuiltinBounds ) {
178183 // all captured data must be owned
179184 let id = ast_util:: def_id_of_def ( fv. def ) . node ;
180185 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.
181189 if !check_durable ( cx. tcx , var_t, fv. span ) { return ; }
182190
183191 // check that only immutable variables are implicitly copied in
184192 check_imm_free_var ( cx, fv. def , fv. span ) ;
193+
194+ check_freevar_bounds ( cx, fv. span , var_t, bounds) ;
185195 }
186196
187- fn check_for_block ( _cx : Context , _fv : @freevar_entry ) {
188- // 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) ;
189201 }
190202
191203 fn check_for_bare ( cx : Context , fv : @freevar_entry ) {
@@ -196,14 +208,14 @@ fn with_appropriate_checker(cx: Context, id: node_id, b: &fn(check_fn)) {
196208
197209 let fty = ty:: node_id_to_type ( cx. tcx , id) ;
198210 match ty:: get ( fty) . sty {
199- ty:: ty_closure( ty:: ClosureTy { sigil : OwnedSigil , _} ) => {
200- b ( check_for_uniq)
211+ ty:: ty_closure( ty:: ClosureTy { sigil : OwnedSigil , bounds : bounds , _} ) => {
212+ b ( |cx , fv| check_for_uniq ( cx , fv , bounds ) )
201213 }
202- ty:: ty_closure( ty:: ClosureTy { sigil : ManagedSigil , _} ) => {
203- b ( check_for_box)
214+ ty:: ty_closure( ty:: ClosureTy { sigil : ManagedSigil , bounds : bounds , _} ) => {
215+ b ( |cx , fv| check_for_box ( cx , fv , bounds ) )
204216 }
205- ty:: ty_closure( ty:: ClosureTy { sigil : BorrowedSigil , _} ) => {
206- b ( check_for_block)
217+ ty:: ty_closure( ty:: ClosureTy { sigil : BorrowedSigil , bounds : bounds , _} ) => {
218+ b ( |cx , fv| check_for_block ( cx , fv , bounds ) )
207219 }
208220 ty:: ty_bare_fn( _) => {
209221 b ( check_for_bare)
@@ -271,15 +283,21 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
271283 type_param_defs. repr( cx. tcx) ) ;
272284 }
273285 for ts. iter( ) . zip( type_param_defs. iter( ) ) . advance |( & ty, type_param_def) | {
274- 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)
275287 }
276288 }
277289 }
278290
279291 match e. node {
280292 expr_cast( source, _) => {
281293 check_cast_for_escaping_regions( cx, source, e) ;
282- check_kind_bounds_of_cast( cx, source, e) ;
294+ match ty:: get( ty:: expr_ty( cx. tcx, e) ) . sty {
295+ ty : : ty_trait( _, _, store, _, bounds) => {
296+ let source_ty = ty:: expr_ty( cx. tcx, source) ;
297+ check_trait_cast_bounds( cx, e. span, source_ty, bounds, store)
298+ }
299+ _ => { }
300+ }
283301 }
284302 expr_copy( expr) => {
285303 // Note: This is the only place where we must check whether the
@@ -307,14 +325,14 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
307325
308326fn check_ty( aty: @Ty , ( cx, v) : ( Context , visit:: vt < Context > ) ) {
309327 match aty. node {
310- ty_path( _, id) => {
328+ ty_path( _, _ , id) => {
311329 let r = cx. tcx. node_type_substs. find( & id) ;
312330 for r. iter( ) . advance |ts| {
313331 let did = ast_util:: def_id_of_def( cx. tcx. def_map. get_copy( & id) ) ;
314332 let type_param_defs =
315333 ty:: lookup_item_type( cx. tcx, did) . generics. type_param_defs;
316334 for ts. iter( ) . zip( type_param_defs. iter( ) ) . advance |( & ty, type_param_def) | {
317- check_bounds ( cx, aty. id, aty. span, ty, type_param_def)
335+ check_typaram_bounds ( cx, aty. id, aty. span, ty, type_param_def)
318336 }
319337 }
320338 }
@@ -323,20 +341,29 @@ fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
323341 visit:: visit_ty( aty, ( cx, v) ) ;
324342}
325343
326- pub fn check_bounds ( cx : Context ,
327- _type_parameter_id : node_id ,
328- sp : span ,
329- ty : ty:: t ,
330- type_param_def : & ty:: TypeParameterDef )
344+ // Calls "any_missing" if any bounds were missing.
345+ pub fn check_builtin_bounds ( cx : Context , ty : ty:: t , bounds : ty:: BuiltinBounds ,
346+ any_missing : & fn ( ty:: BuiltinBounds ) )
331347{
332348 let kind = ty:: type_contents ( cx. tcx , ty) ;
333349 let mut missing = ty:: EmptyBuiltinBounds ( ) ;
334- for type_param_def . bounds. builtin_bounds . each |bound| {
350+ for bounds. each |bound| {
335351 if !kind. meets_bound ( cx. tcx , bound) {
336352 missing. add ( bound) ;
337353 }
338354 }
339355 if !missing. is_empty ( ) {
356+ any_missing ( missing) ;
357+ }
358+ }
359+
360+ pub fn check_typaram_bounds ( cx : Context ,
361+ _type_parameter_id : node_id ,
362+ sp : span ,
363+ ty : ty:: t ,
364+ type_param_def : & ty:: TypeParameterDef )
365+ {
366+ do check_builtin_bounds ( cx, ty, type_param_def. bounds . builtin_bounds ) |missing| {
340367 cx. tcx . sess . span_err (
341368 sp,
342369 fmt ! ( "instantiating a type parameter with an incompatible type \
@@ -346,6 +373,38 @@ pub fn check_bounds(cx: Context,
346373 }
347374}
348375
376+ pub fn check_freevar_bounds ( cx : Context , sp : span , ty : ty:: t ,
377+ bounds : ty:: BuiltinBounds )
378+ {
379+ do check_builtin_bounds ( cx, ty, bounds) |missing| {
380+ cx. tcx . sess . span_err (
381+ sp,
382+ fmt ! ( "cannot capture variable of type `%s`, which does not fulfill \
383+ `%s`, in a bounded closure",
384+ ty_to_str( cx. tcx, ty) , missing. user_string( cx. tcx) ) ) ;
385+ cx. tcx . sess . span_note (
386+ sp,
387+ fmt ! ( "this closure's environment must satisfy `%s`" ,
388+ bounds. user_string( cx. tcx) ) ) ;
389+ }
390+ }
391+
392+ pub fn check_trait_cast_bounds( cx : Context , sp : span , ty : ty:: t ,
393+ bounds : ty:: BuiltinBounds , store : ty:: TraitStore ) {
394+ do check_builtin_bounds ( cx, ty, bounds) |missing| {
395+ cx. tcx . sess . span_err ( sp,
396+ fmt ! ( "cannot pack type `%s`, which does not fulfill \
397+ `%s`, as a trait bounded by %s",
398+ ty_to_str( cx. tcx, ty) , missing. user_string( cx. tcx) ,
399+ bounds. user_string( cx. tcx) ) ) ;
400+ }
401+ // FIXME(#3569): Remove this check when the corresponding restriction
402+ // is made with type contents.
403+ if store == ty:: UniqTraitStore && !ty:: type_is_owned ( cx. tcx , ty) {
404+ cx. tcx . sess . span_err ( sp, "uniquely-owned trait objects must be sendable" ) ;
405+ }
406+ }
407+
349408fn is_nullary_variant ( cx : Context , ex: @expr) -> bool {
350409 match ex. node {
351410 expr_path( _) => {
@@ -528,19 +587,3 @@ pub fn check_cast_for_escaping_regions(
528587 cx. tcx . region_maps . is_subregion_of ( r_sub, r_sup)
529588 }
530589}
531-
532- /// Ensures that values placed into a ~Trait are copyable and sendable.
533- pub fn check_kind_bounds_of_cast ( cx : Context , source: @expr, target: @expr) {
534- let target_ty = ty:: expr_ty ( cx. tcx , target) ;
535- match ty:: get ( target_ty) . sty {
536- ty:: ty_trait( _, _, ty:: UniqTraitStore , _) => {
537- let source_ty = ty:: expr_ty ( cx. tcx , source) ;
538- if !ty:: type_is_owned ( cx. tcx , source_ty) {
539- cx. tcx . sess . span_err (
540- target. span ,
541- "uniquely-owned trait objects must be sendable" ) ;
542- }
543- }
544- _ => { } // Nothing to do.
545- }
546- }
0 commit comments