diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 7169f7e924f01..ccc28aeda5044 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -588,14 +588,43 @@ type gather_result = ty_var_counter: @mut uint}; // AST fragment checking -fn check_lit(ccx: @crate_ctxt, lit: @ast::lit) -> ty::t { +fn check_lit(fcx: @fn_ctxt, lit: @ast::lit, + expected: option) -> ty::t { alt lit.node { - ast::lit_str(_) { ty::mk_str(ccx.tcx) } - ast::lit_int(_, t) { ty::mk_mach_int(ccx.tcx, t) } - ast::lit_uint(_, t) { ty::mk_mach_uint(ccx.tcx, t) } - ast::lit_float(_, t) { ty::mk_mach_float(ccx.tcx, t) } - ast::lit_nil { ty::mk_nil(ccx.tcx) } - ast::lit_bool(_) { ty::mk_bool(ccx.tcx) } + ast::lit_str(_) { ty::mk_str(fcx.ccx.tcx) } + ast::lit_int(_, t) { + // This is a quick hack to allow some relaxation of when one + // needs a "u" suffix on integer literals. + + // Leaving off "u" suffixes means that something that's parsed + // as an int might in fact be a uint. Check to see what its + // expected type is; if it's expected to be a uint, then we + // can treat it like one. Otherwise, treat it like an int. + + alt t { + // First make sure we never treat chars like uints. + syntax::ast::ty_char { ty::mk_mach_int(fcx.ccx.tcx, t) } + // Then handle all the other int variants. + _ { + let expected = unpack_expected(fcx, expected) { |sty| + alt sty { + ty::ty_uint(t) { + some(ty::mk_mach_uint(fcx.ccx.tcx, t)) + } + _ { none } + } + }; + alt expected { + some(t) { t } + none { ty::mk_mach_int(fcx.ccx.tcx, t) } + } + } + } + } + ast::lit_uint(_, t) { ty::mk_mach_uint(fcx.ccx.tcx, t) } + ast::lit_float(_, t) { ty::mk_mach_float(fcx.ccx.tcx, t) } + ast::lit_nil { ty::mk_nil(fcx.ccx.tcx) } + ast::lit_bool(_) { ty::mk_bool(fcx.ccx.tcx) } } } @@ -987,24 +1016,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } } - // Resolves `expected` by a single level if it is a variable and passes it - // through the `unpack` function. It there is no expected type or - // resolution is not possible (e.g., no constraints yet present), just - // returns `none`. - fn unpack_expected(fcx: @fn_ctxt, expected: option, - unpack: fn(ty::sty) -> option) - -> option { - alt expected { - some(t) { - alt infer::resolve_shallow(fcx.infcx, t, false) { - result::ok(t) { unpack(ty::get(t).struct) } - _ { none } - } - } - _ { none } - } - } - fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, proto: ast::proto, @@ -1062,7 +1073,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } ast::expr_lit(lit) { - let typ = check_lit(fcx.ccx, lit); + #debug["checking expr_lit %s", + syntax::print::pprust::expr_to_str(expr)]; + + let typ = check_lit(fcx, lit, expected); fcx.write_ty(id, typ); } @@ -1671,6 +1685,24 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, ret bot; } +// Resolves `expected` by a single level if it is a variable and +// passes it through the `unpack` function. It there is no expected +// type or resolution is not possible (e.g., no constraints yet +// present), just returns `none`. +fn unpack_expected(fcx: @fn_ctxt, expected: option, + unpack: fn(ty::sty) -> option) + -> option { + alt expected { + some(t) { + alt infer::resolve_shallow(fcx.infcx, t, false) { + result::ok(t) { unpack(ty::get(t).struct) } + _ { none } + } + } + _ { none } + } +} + fn require_integral(fcx: @fn_ctxt, sp: span, t: ty::t) { if !type_is_integral(fcx, sp, t) { fcx.ccx.tcx.sess.span_err(sp, "mismatched types: expected \ diff --git a/src/test/compile-fail/inferred-integer-literal-type.rs b/src/test/compile-fail/inferred-integer-literal-type.rs new file mode 100644 index 0000000000000..fe3966bd7db65 --- /dev/null +++ b/src/test/compile-fail/inferred-integer-literal-type.rs @@ -0,0 +1,20 @@ +// Issue #1425. + +// Relax the need for the "u" suffix on unsigned integer literals +// under certain very limited conditions. + +// But, when inferring uint types for would-be ints, make sure we +// don't allow chars to be treated as uints. + +fn main() { + let x1: uint = 'c'; //! ERROR mismatched types + let x2 = 1u + 'c'; //! ERROR mismatched types + let x3: uint = 1u + 'c'; //! ERROR mismatched types + let x4 = vec::slice(["hello", "world"], 'c', 'd'); + //!^ ERROR mismatched types + //!^^ ERROR mismatched types + let x5 = vec::slice(["hello", "world"], 0u, 'c'); + //!^ ERROR mismatched types + let x6 = vec::slice(["hello", "world"], 'c', 1u); + //!^ ERROR mismatched types +} diff --git a/src/test/compile-fail/issue-1362.rs b/src/test/compile-fail/issue-1362.rs index 9cdf905f81bdc..a44f26e10f7a5 100644 --- a/src/test/compile-fail/issue-1362.rs +++ b/src/test/compile-fail/issue-1362.rs @@ -1,7 +1,7 @@ // Regression test for issue #1362 - without that fix the span will be bogus // no-reformat fn main() { - let x: uint = 20; //! ERROR mismatched types + let x: uint = "hello"; //! ERROR mismatched types } // NOTE: Do not add any extra lines as the line number the error is // on is significant; an error later in the source file might not diff --git a/src/test/compile-fail/issue-1448-2.rs b/src/test/compile-fail/issue-1448-2.rs index 548523ecb45e7..823547a34d248 100644 --- a/src/test/compile-fail/issue-1448-2.rs +++ b/src/test/compile-fail/issue-1448-2.rs @@ -1,5 +1,5 @@ // Regresion test for issue #1448 and #1386 fn main() { - #debug["%u", 10]; //! ERROR mismatched types + #debug["%u", "hello"]; //! ERROR mismatched types } diff --git a/src/test/run-pass/inferred-integer-literal-type.rs b/src/test/run-pass/inferred-integer-literal-type.rs new file mode 100644 index 0000000000000..52ddb57d97c80 --- /dev/null +++ b/src/test/run-pass/inferred-integer-literal-type.rs @@ -0,0 +1,22 @@ +// Issue #1425. + +// Relax the need for the "u" suffix on unsigned integer literals +// under certain very limited conditions. + +fn main() { + let x1: uint = 4; + let x2 = 1u + 5; + let x3: uint = 1u + 6; + let x4 = vec::slice(["hello", "world"], 0, 1); + let x5 = vec::slice(["hello", "world"], 0u, 1); + let x6 = vec::slice(["hello", "world"], 0, 1u); + + // Something we can't do yet. + // let x = 5; + // fn foo(a : uint) { } + // foo(x); + + // These fail, too, as predicted. + // let x7 = 1 + 5u; + // let x8: uint = 1 + 6u; +}