]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/demand.rs
librustc: Try to resolve before coercions.
[rust.git] / src / librustc / middle / typeck / check / demand.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use middle::ty;
13 use middle::typeck::check::FnCtxt;
14 use middle::typeck::infer;
15 use middle::typeck::infer::resolve_type;
16 use middle::typeck::infer::resolve::try_resolve_tvar_shallow;
17
18 use std::result::{Err, Ok};
19 use std::result;
20 use syntax::ast;
21 use syntax::codemap::Span;
22 use util::ppaux::Repr;
23
24 // Requires that the two types unify, and prints an error message if they
25 // don't.
26 pub fn suptype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
27     suptype_with_fn(fcx, sp, false, expected, actual,
28         |sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) })
29 }
30
31 pub fn subtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
32     suptype_with_fn(fcx, sp, true, actual, expected,
33         |sp, a, e, s| { fcx.report_mismatched_types(sp, e, a, s) })
34 }
35
36 pub fn suptype_with_fn(fcx: &FnCtxt,
37                        sp: Span,
38                        b_is_expected: bool,
39                        ty_a: ty::t,
40                        ty_b: ty::t,
41                        handle_err: |Span, ty::t, ty::t, &ty::type_err|) {
42     // n.b.: order of actual, expected is reversed
43     match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp),
44                           ty_b, ty_a) {
45       result::Ok(()) => { /* ok */ }
46       result::Err(ref err) => {
47           handle_err(sp, ty_a, ty_b, err);
48       }
49     }
50 }
51
52 pub fn eqtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
53     match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
54         Ok(()) => { /* ok */ }
55         Err(ref err) => {
56             fcx.report_mismatched_types(sp, expected, actual, err);
57         }
58     }
59 }
60
61 // Checks that the type `actual` can be coerced to `expected`.
62 pub fn coerce(fcx: &FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) {
63     let expr_ty = fcx.expr_ty(expr);
64     debug!("demand::coerce(expected = {}, expr_ty = {})",
65            expected.repr(fcx.ccx.tcx),
66            expr_ty.repr(fcx.ccx.tcx));
67     let expected = if ty::type_needs_infer(expected) {
68         resolve_type(fcx.infcx(), expected,
69                      try_resolve_tvar_shallow).unwrap_or(expected)
70     } else { expected };
71     match fcx.mk_assignty(expr, expr_ty, expected) {
72       result::Ok(()) => { /* ok */ }
73       result::Err(ref err) => {
74         fcx.report_mismatched_types(sp, expected, expr_ty, err);
75       }
76     }
77 }