@@ -979,9 +979,9 @@ mod demand {
979
979
// Requires that the two types unify, and prints an error message if they
980
980
// don't. Returns the unified type and the type parameter substitutions.
981
981
fn full(fcx: &@fn_ctxt, sp: &span, expected: ty::t, actual: ty::t,
982
- ty_param_substs_0: &[ty::t], do_block_coerece : bool) ->
982
+ ty_param_substs_0: &[ty::t], do_block_coerce : bool) ->
983
983
ty_param_substs_and_ty {
984
- if do_block_coerece {
984
+ if do_block_coerce {
985
985
actual = do_fn_block_coerce(fcx, sp, actual, expected);
986
986
}
987
987
@@ -1715,54 +1715,6 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr, unify: &unifier,
1715
1715
ret bot;
1716
1716
}
1717
1717
1718
- // A generic function for checking the pred in a check
1719
- // or if-check
1720
- fn check_pred_expr( fcx: & @fn_ctxt, e: & @ast:: expr) -> bool {
1721
- let bot = check_expr_with( fcx, e, ty:: mk_bool( fcx. ccx. tcx) ) ;
1722
-
1723
- /* e must be a call expr where all arguments are either
1724
- literals or slots */
1725
- alt e. node {
1726
- ast:: expr_call( operator, operands) {
1727
- if !ty:: is_pred_ty( fcx. ccx. tcx, expr_ty( fcx. ccx. tcx, operator) ) {
1728
- fcx. ccx. tcx. sess. span_fatal( operator. span,
1729
- ~"Operator in constraint has non-boolean return type ") ;
1730
- }
1731
-
1732
- alt operator. node {
1733
- ast : : expr_path( oper_name) {
1734
- alt fcx. ccx. tcx. def_map. find( operator. id) {
1735
- some( ast:: def_fn( _, ast:: pure_fn. ) ) {
1736
- // do nothing
1737
- }
1738
- _ {
1739
- fcx. ccx. tcx. sess. span_fatal( operator. span,
1740
- ~"Impure function as operator \
1741
- in constraint") ;
1742
- }
1743
- }
1744
- for operand: @ast:: expr in operands {
1745
- if !ast_util : : is_constraint_arg( operand) {
1746
- let s =
1747
- ~"Constraint args must be \
1748
- slot variables or literals";
1749
- fcx. ccx. tcx. sess. span_fatal( e. span, s) ;
1750
- }
1751
- }
1752
- }
1753
- _ {
1754
- let s =
1755
- ~"In a constraint, expected the \
1756
- constraint name to be an explicit name";
1757
- fcx. ccx. tcx. sess. span_fatal( e. span, s) ;
1758
- }
1759
- }
1760
- }
1761
- _ { fcx. ccx. tcx. sess. span_fatal(
1762
- e. span, ~"check on non-predicate") ; }
1763
- }
1764
- ret bot;
1765
- }
1766
1718
1767
1719
// A generic function for checking the then and else in an if
1768
1720
// or if-check
@@ -2604,6 +2556,110 @@ fn check_const(ccx: &@crate_ctxt, _sp: &span, e: &@ast::expr,
2604
2556
check_expr ( fcx, e) ;
2605
2557
}
2606
2558
2559
+ // A generic function for checking the pred in a check
2560
+ // or if-check
2561
+ fn check_pred_expr ( fcx : & @fn_ctxt , e : & @ast:: expr ) -> bool {
2562
+ let bot = check_expr_with ( fcx, e, ty:: mk_bool ( fcx. ccx . tcx ) ) ;
2563
+
2564
+ /* e must be a call expr where all arguments are either
2565
+ literals or slots */
2566
+ alt e. node {
2567
+ ast:: expr_call ( operator, operands) {
2568
+ if !ty:: is_pred_ty ( fcx. ccx . tcx , expr_ty ( fcx. ccx . tcx , operator) ) {
2569
+ fcx. ccx . tcx . sess . span_fatal ( operator. span ,
2570
+ ~"Operator in constraint has non-boolean return type") ;
2571
+ }
2572
+
2573
+ alt operator. node {
2574
+ ast:: expr_path ( oper_name) {
2575
+ alt fcx. ccx . tcx . def_map . find ( operator. id ) {
2576
+ some ( ast:: def_fn ( _, ast:: pure_fn. ) ) {
2577
+ // do nothing
2578
+ }
2579
+ _ {
2580
+ fcx. ccx . tcx . sess . span_fatal ( operator. span ,
2581
+ ~"Impure function as operator \
2582
+ in constraint ") ;
2583
+ }
2584
+ }
2585
+ for operand: @ast:: expr in operands {
2586
+ if !ast_util:: is_constraint_arg ( operand) {
2587
+ let s =
2588
+ ~"Constraint args must be \
2589
+ slot variables or literals";
2590
+ fcx. ccx . tcx . sess . span_fatal ( e. span , s) ;
2591
+ }
2592
+ }
2593
+ }
2594
+ _ {
2595
+ let s =
2596
+ ~"In a constraint, expected the \
2597
+ constraint name to be an explicit name";
2598
+ fcx. ccx . tcx . sess . span_fatal ( e. span , s) ;
2599
+ }
2600
+ }
2601
+ }
2602
+ _ { fcx. ccx . tcx . sess . span_fatal (
2603
+ e. span , ~"check on non-predicate") ; }
2604
+ }
2605
+ ret bot;
2606
+ }
2607
+
2608
+ fn check_constraints( fcx : & @fn_ctxt , cs : [ @ast:: constr ] , args : [ ast:: arg ] ) {
2609
+ let c_args;
2610
+ let num_args = vec:: len ( args) ;
2611
+ for c: @ast:: constr in cs {
2612
+ c_args = [ ] ;
2613
+ for a: @spanned < ast:: fn_constr_arg > in c. node. args {
2614
+ c_args += [ @( alt a. node {
2615
+ ast : : carg_base . {
2616
+ // "base" should not occur in a fn type thing, as of
2617
+ // yet, b/c we don't allow constraints on the return type
2618
+
2619
+ fcx. ccx. tcx. sess. span_bug( a. span, ~"check_constraints : \
2620
+ unexpected carg_base") ;
2621
+ }
2622
+ ast:: carg_lit( l) {
2623
+ let tmp_node_id = fcx. ccx. tcx. sess. next_node_id( ) ;
2624
+ { id: tmp_node_id, node : ast:: expr_lit( l) , span : a. span} }
2625
+ ast:: carg_ident( i) {
2626
+ if i < num_args {
2627
+ let p : ast:: path_ =
2628
+ { global: false, idents: [ ( args[ i] ) . ident ] ,
2629
+ // Works b/c no higher-order polymorphism
2630
+ types: [ ] } ;
2631
+ /*
2632
+ This is kludgy, and we probably shouldn't be assigning
2633
+ node IDs here, but we're creating exprs that are
2634
+ ephemeral, just for the purposes of typechecking. So
2635
+ that's my justification.
2636
+ */
2637
+ let arg_occ_node_id = fcx. ccx . tcx . sess . next_node_id ( ) ;
2638
+ fcx. ccx . tcx . def_map . insert ( arg_occ_node_id,
2639
+ ast:: def_arg ( local_def ( args[ i] . id ) ) ) ;
2640
+ { id: arg_occ_node_id,
2641
+ node: ast:: expr_path ( respan ( a. span , p) ) ,
2642
+ span: a. span }
2643
+ }
2644
+ else {
2645
+ fcx. ccx . tcx . sess . span_bug ( a. span , ~"check_constraints: \
2646
+ carg_ident index out of bounds") ;
2647
+ }
2648
+ }
2649
+ } ) ]
2650
+ }
2651
+ let p_op : ast:: expr_ = ast:: expr_path ( c. node . path) ;
2652
+ let oper : @ast:: expr = @{ id: c. node . id ,
2653
+ node : p_op , span : c. span } ;
2654
+ // Another ephemeral expr
2655
+ let call_expr_id = fcx. ccx. tcx. sess. next_node_id( ) ;
2656
+ let call_expr = @{ id: call_expr_id ,
2657
+ node : ast:: expr_call ( oper , c_args ) ,
2658
+ span : c. span } ;
2659
+ check_pred_expr ( fcx , call_expr ) ;
2660
+ }
2661
+ }
2662
+
2607
2663
fn check_fn ( ccx : & @crate_ctxt , f : & ast:: _fn , id : & ast:: node_id ,
2608
2664
old_fcx : & option:: t < @fn_ctxt > ) {
2609
2665
let decl = f. decl ;
@@ -2620,6 +2676,7 @@ fn check_fn(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
2620
2676
next_var_id: gather_result. next_var_id ,
2621
2677
mutable fixups: fixups,
2622
2678
ccx: ccx} ;
2679
+ check_constraints ( fcx, decl. constraints , decl. inputs ) ;
2623
2680
check_block ( fcx, body) ;
2624
2681
2625
2682
// For non-iterator fns, we unify the tail expr's type with the
0 commit comments