@@ -16,6 +16,7 @@ use self::EvalHint::*;
1616
1717use front:: map as ast_map;
1818use front:: map:: blocks:: FnLikeNode ;
19+ use lint;
1920use middle:: cstore:: { self , CrateStore , InlinedItem } ;
2021use middle:: { infer, subst, traits} ;
2122use middle:: def:: Def ;
@@ -323,10 +324,41 @@ impl ConstVal {
323324 }
324325}
325326
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+
327356 let pat = match expr. node {
328357 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 ( ) ) ) ,
330362
331363 hir:: ExprCall ( ref callee, ref args) => {
332364 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> {
336368 let path = match def. full_def ( ) {
337369 Def :: Struct ( def_id) => def_to_path ( tcx, def_id) ,
338370 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 {
340372 id : expr. id ,
341373 node : PatKind :: Lit ( P ( expr. clone ( ) ) ) ,
342374 span : span,
343- } ) ,
375+ } ) ) ,
344376 _ => unreachable ! ( )
345377 } ;
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 ( ) ) ;
347382 PatKind :: TupleStruct ( path, Some ( pats) )
348383 }
349384
350385 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 ( ) ) ;
359398 PatKind :: Struct ( path. clone ( ) , field_pats, false )
360399 }
361400
362401 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 ( ) ) ;
364406 PatKind :: Vec ( pats, None , hir:: HirVec :: new ( ) )
365407 }
366408
@@ -373,15 +415,15 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
373415 Some ( Def :: AssociatedConst ( def_id) ) => {
374416 let substs = Some ( tcx. node_id_item_substs ( expr. id ) . substs ) ;
375417 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) ;
377419 } ,
378420 _ => unreachable ! ( ) ,
379421 }
380422 }
381423
382424 _ => PatKind :: Lit ( P ( expr. clone ( ) ) )
383425 } ;
384- P ( hir:: Pat { id : expr. id , node : pat, span : span } )
426+ Ok ( P ( hir:: Pat { id : expr. id , node : pat, span : span } ) )
385427}
386428
387429pub fn eval_const_expr ( tcx : & TyCtxt , e : & Expr ) -> ConstVal {
0 commit comments