@@ -16,6 +16,7 @@ use self::EvalHint::*;
16
16
17
17
use front:: map as ast_map;
18
18
use front:: map:: blocks:: FnLikeNode ;
19
+ use lint;
19
20
use middle:: cstore:: { self , CrateStore , InlinedItem } ;
20
21
use middle:: { infer, subst, traits} ;
21
22
use middle:: def:: Def ;
@@ -323,10 +324,41 @@ impl ConstVal {
323
324
}
324
325
}
325
326
326
- pub fn const_expr_to_pat ( tcx : & TyCtxt , expr : & Expr , span : Span ) -> P < hir:: Pat > {
327
+ pub fn const_expr_to_pat ( tcx : & ty:: TyCtxt , expr : & Expr , pat_id : ast:: NodeId , span : Span )
328
+ -> Result < P < hir:: Pat > , DefId > {
329
+ let pat_ty = tcx. expr_ty ( expr) ;
330
+ debug ! ( "expr={:?} pat_ty={:?} pat_id={}" , expr, pat_ty, pat_id) ;
331
+ match pat_ty. sty {
332
+ ty:: TyFloat ( _) => {
333
+ tcx. sess . add_lint (
334
+ lint:: builtin:: ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN ,
335
+ pat_id,
336
+ span,
337
+ format ! ( "floating point constants cannot be used in patterns" ) ) ;
338
+ }
339
+ ty:: TyEnum ( adt_def, _) |
340
+ ty:: TyStruct ( adt_def, _) => {
341
+ if !tcx. has_attr ( adt_def. did , "structural_match" ) {
342
+ tcx. sess . add_lint (
343
+ lint:: builtin:: ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN ,
344
+ pat_id,
345
+ span,
346
+ format ! ( "to use a constant of type `{}` \
347
+ in a pattern, \
348
+ `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
349
+ tcx. item_path_str( adt_def. did) ,
350
+ tcx. item_path_str( adt_def. did) ) ) ;
351
+ }
352
+ }
353
+ _ => { }
354
+ }
355
+
327
356
let pat = match expr. node {
328
357
hir:: ExprTup ( ref exprs) =>
329
- PatKind :: Tup ( exprs. iter ( ) . map ( |expr| const_expr_to_pat ( tcx, & expr, span) ) . collect ( ) ) ,
358
+ PatKind :: Tup ( try!( exprs. iter ( )
359
+ . map ( |expr| const_expr_to_pat ( tcx, & expr,
360
+ pat_id, span) )
361
+ . collect ( ) ) ) ,
330
362
331
363
hir:: ExprCall ( ref callee, ref args) => {
332
364
let def = * tcx. def_map . borrow ( ) . get ( & callee. id ) . unwrap ( ) ;
@@ -336,31 +368,41 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
336
368
let path = match def. full_def ( ) {
337
369
Def :: Struct ( def_id) => def_to_path ( tcx, def_id) ,
338
370
Def :: Variant ( _, variant_did) => def_to_path ( tcx, variant_did) ,
339
- Def :: Fn ( ..) => return P ( hir:: Pat {
371
+ Def :: Fn ( ..) => return Ok ( P ( hir:: Pat {
340
372
id : expr. id ,
341
373
node : PatKind :: Lit ( P ( expr. clone ( ) ) ) ,
342
374
span : span,
343
- } ) ,
375
+ } ) ) ,
344
376
_ => unreachable ! ( )
345
377
} ;
346
- let pats = args. iter ( ) . map ( |expr| const_expr_to_pat ( tcx, & expr, span) ) . collect ( ) ;
378
+ let pats = try!( args. iter ( )
379
+ . map ( |expr| const_expr_to_pat ( tcx, & * * expr,
380
+ pat_id, span) )
381
+ . collect ( ) ) ;
347
382
PatKind :: TupleStruct ( path, Some ( pats) )
348
383
}
349
384
350
385
hir:: ExprStruct ( ref path, ref fields, None ) => {
351
- let field_pats = fields. iter ( ) . map ( |field| codemap:: Spanned {
352
- span : codemap:: DUMMY_SP ,
353
- node : hir:: FieldPat {
354
- name : field. name . node ,
355
- pat : const_expr_to_pat ( tcx, & field. expr , span) ,
356
- is_shorthand : false ,
357
- } ,
358
- } ) . collect ( ) ;
386
+ let field_pats =
387
+ try!( fields. iter ( )
388
+ . map ( |field| Ok ( codemap:: Spanned {
389
+ span : codemap:: DUMMY_SP ,
390
+ node : hir:: FieldPat {
391
+ name : field. name . node ,
392
+ pat : try!( const_expr_to_pat ( tcx, & field. expr ,
393
+ pat_id, span) ) ,
394
+ is_shorthand : false ,
395
+ } ,
396
+ } ) )
397
+ . collect ( ) ) ;
359
398
PatKind :: Struct ( path. clone ( ) , field_pats, false )
360
399
}
361
400
362
401
hir:: ExprVec ( ref exprs) => {
363
- let pats = exprs. iter ( ) . map ( |expr| const_expr_to_pat ( tcx, & expr, span) ) . collect ( ) ;
402
+ let pats = try!( exprs. iter ( )
403
+ . map ( |expr| const_expr_to_pat ( tcx, & expr,
404
+ pat_id, span) )
405
+ . collect ( ) ) ;
364
406
PatKind :: Vec ( pats, None , hir:: HirVec :: new ( ) )
365
407
}
366
408
@@ -373,15 +415,15 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
373
415
Some ( Def :: AssociatedConst ( def_id) ) => {
374
416
let substs = Some ( tcx. node_id_item_substs ( expr. id ) . substs ) ;
375
417
let ( expr, _ty) = lookup_const_by_id ( tcx, def_id, substs) . unwrap ( ) ;
376
- return const_expr_to_pat ( tcx, expr, span) ;
418
+ return const_expr_to_pat ( tcx, expr, pat_id , span) ;
377
419
} ,
378
420
_ => unreachable ! ( ) ,
379
421
}
380
422
}
381
423
382
424
_ => PatKind :: Lit ( P ( expr. clone ( ) ) )
383
425
} ;
384
- P ( hir:: Pat { id : expr. id , node : pat, span : span } )
426
+ Ok ( P ( hir:: Pat { id : expr. id , node : pat, span : span } ) )
385
427
}
386
428
387
429
pub fn eval_const_expr ( tcx : & TyCtxt , e : & Expr ) -> ConstVal {
0 commit comments