BinopAssignment => PreferMutLvalue,
SimpleBinop => NoPreference
};
- check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
+ check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
// Callee does bot / err checking
- let lhs_t = structurally_resolved_type(fcx, lhs.span,
- fcx.expr_ty(&*lhs));
+ let lhs_t =
+ structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || {
+ if ast_util::is_symmetric_binop(op.node) {
+ // Try RHS first
+ check_expr(fcx, &**rhs);
+ fcx.expr_ty(&**rhs)
+ } else {
+ fcx.tcx().types.err
+ }
+ });
if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
// Shift is a special case: rhs must be uint, no matter what lhs is
}
}
-// Resolves `typ` by a single level if `typ` is a type variable. If no
-// resolution is possible, then an error is reported.
-pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- sp: Span,
- ty: Ty<'tcx>)
- -> Ty<'tcx>
+fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ ty: Ty<'tcx>,
+ f: F) -> Ty<'tcx>
+ where F: Fn() -> Ty<'tcx>
{
let mut ty = fcx.resolve_type_vars_if_possible(ty);
- // If not, error.
if ty::type_is_ty_var(ty) {
- fcx.type_error_message(sp, |_actual| {
- "the type of this value must be known in this \
- context".to_string()
- }, ty, None);
- demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
- ty = fcx.tcx().types.err;
+ let alternative = f();
+
+ // If not, error.
+ if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
+ fcx.type_error_message(sp, |_actual| {
+ "the type of this value must be known in this context".to_string()
+ }, ty, None);
+ demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
+ ty = fcx.tcx().types.err;
+ } else {
+ demand::suptype(fcx, sp, alternative, ty);
+ ty = alternative;
+ }
}
ty
}
+// Resolves `typ` by a single level if `typ` is a type variable. If no
+// resolution is possible, then an error is reported.
+pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ ty: Ty<'tcx>)
+ -> Ty<'tcx>
+{
+ structurally_resolve_type_or_else(fcx, sp, ty, || {
+ fcx.tcx().types.err
+ })
+}
+
// Returns true if b contains a break that can exit from b
pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
// First: is there an unlabeled break immediately
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+fn main() {
+ if let Ok(x) = "3.1415".parse() {
+ assert_eq!(false, x <= 0.0);
+ }
+ if let Ok(x) = "3.1415".parse() {
+ assert_eq!(3.1415, x + 0.0);
+ }
+ if let Ok(mut x) = "3.1415".parse() {
+ assert_eq!(8.1415, { x += 5.0; x });
+ }
+}