From 73ec50a51875f14e25a6e845fc528df94788b6c4 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sat, 7 Jun 2014 19:05:47 -0400 Subject: [PATCH 1/2] librustc: Apply coercions to return expressions. --- src/librustc/middle/typeck/check/demand.rs | 8 +++- src/librustc/middle/typeck/check/mod.rs | 51 ++++++++++++---------- src/librustrt/util.rs | 2 +- src/test/run-pass/issue-12755.rs | 29 ++++++++++++ 4 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 src/test/run-pass/issue-12755.rs diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs index 10d44ecede6cc..acbe25bb8c66d 100644 --- a/src/librustc/middle/typeck/check/demand.rs +++ b/src/librustc/middle/typeck/check/demand.rs @@ -60,6 +60,12 @@ pub fn eqtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { // Checks that the type `actual` can be coerced to `expected`. pub fn coerce(fcx: &FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) { + coerce_with_fn(fcx, sp, expected, expr, + |sp, a, e, err| fcx.report_mismatched_types(sp, e, a, err)) +} + +pub fn coerce_with_fn(fcx: &FnCtxt, sp: Span, expected: ty::t, + expr: &ast::Expr, handle_err: |Span, ty::t, ty::t, &ty::type_err|) { let expr_ty = fcx.expr_ty(expr); debug!("demand::coerce(expected = {}, expr_ty = {})", expected.repr(fcx.ccx.tcx), @@ -71,7 +77,7 @@ pub fn coerce(fcx: &FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) { match fcx.mk_assignty(expr, expr_ty, expected) { result::Ok(()) => { /* ok */ } result::Err(ref err) => { - fcx.report_mismatched_types(sp, expected, expr_ty, err); + handle_err(sp, expr_ty, expected, err); } } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d25fc9cc5bcdb..34c921b9d43df 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -502,9 +502,9 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>, Some(tail_expr) => { // Special case: we print a special error if there appears // to be do-block/for-loop confusion - demand::suptype_with_fn(&fcx, tail_expr.span, false, - fcx.ret_ty, fcx.expr_ty(tail_expr), - |sp, e, a, s| { + demand::coerce_with_fn(&fcx, tail_expr.span, + fcx.ret_ty, tail_expr, + |sp, a, e, s| { fcx.report_mismatched_return_types(sp, e, a, s); }); } @@ -2958,7 +2958,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } }, Some(e) => { - check_expr_has_type(fcx, e, ret_ty); + check_expr_coercable_to_type(fcx, e, ret_ty); } } fcx.write_bot(id); @@ -3500,26 +3500,31 @@ pub fn check_block_with_expected(fcx: &FnCtxt, else { fcx.write_nil(blk.id); }, - Some(e) => { - if any_bot && !warned { - fcx.ccx - .tcx - .sess - .add_lint(UnreachableCode, - e.id, - e.span, - "unreachable expression".to_string()); + Some(e) => { + if any_bot && !warned { + fcx.ccx.tcx.sess + .add_lint(UnreachableCode, + e.id, + e.span, + "unreachable expression".to_string()); + } + let ety = match expected { + Some(ety) => { + check_expr_coercable_to_type(fcx, e, ety); + ety + }, + None => { + check_expr(fcx, e); + fcx.expr_ty(e) + } + }; + fcx.write_ty(blk.id, ety); + if any_err { + fcx.write_error(blk.id); + } else if any_bot { + fcx.write_bot(blk.id); + } } - check_expr_with_opt_hint(fcx, e, expected); - let ety = fcx.expr_ty(e); - fcx.write_ty(blk.id, ety); - if any_err { - fcx.write_error(blk.id); - } - else if any_bot { - fcx.write_bot(blk.id); - } - } }; }); diff --git a/src/librustrt/util.rs b/src/librustrt/util.rs index c08652cc08c79..3d1f8c6cc66fb 100644 --- a/src/librustrt/util.rs +++ b/src/librustrt/util.rs @@ -73,7 +73,7 @@ pub fn abort(args: &fmt::Arguments) -> ! { let mut w = BufWriter { buf: msg, pos: 0 }; let _ = write!(&mut w, "{}", args); let msg = str::from_utf8(w.buf.slice_to(w.pos)).unwrap_or("aborted"); - let msg = if msg.is_empty() {"aborted"} else {msg}; + let msg = if !msg.is_empty() {msg} else {"aborted"}; // Give some context to the message let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) ); diff --git a/src/test/run-pass/issue-12755.rs b/src/test/run-pass/issue-12755.rs new file mode 100644 index 0000000000000..84364762fe8e8 --- /dev/null +++ b/src/test/run-pass/issue-12755.rs @@ -0,0 +1,29 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure we apply the usual coercions to return expressions + +pub struct Foo<'a> { + a: &'a mut int, + b: int, + take_a: bool +} + +impl<'a> Foo<'a> { + fn take(&'a mut self) -> &'a mut int { + if self.take_a { + self.a + } else { + &mut self.b + } + } +} + +fn main() {} From 95a5184f916989411af16d810713ce6ff159b104 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Sun, 8 Jun 2014 02:57:13 -0400 Subject: [PATCH 2/2] librustc: Don't try to resolve in demand::coerce instead just do it for method calls. --- src/librustc/middle/typeck/check/demand.rs | 6 ------ src/librustc/middle/typeck/check/mod.rs | 6 +++++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs index acbe25bb8c66d..0bc15709871ab 100644 --- a/src/librustc/middle/typeck/check/demand.rs +++ b/src/librustc/middle/typeck/check/demand.rs @@ -12,8 +12,6 @@ use middle::ty; use middle::typeck::check::FnCtxt; use middle::typeck::infer; -use middle::typeck::infer::resolve_type; -use middle::typeck::infer::resolve::try_resolve_tvar_shallow; use std::result::{Err, Ok}; use std::result; @@ -70,10 +68,6 @@ pub fn coerce_with_fn(fcx: &FnCtxt, sp: Span, expected: ty::t, debug!("demand::coerce(expected = {}, expr_ty = {})", expected.repr(fcx.ccx.tcx), expr_ty.repr(fcx.ccx.tcx)); - let expected = if ty::type_needs_infer(expected) { - resolve_type(fcx.infcx(), expected, - try_resolve_tvar_shallow).unwrap_or(expected) - } else { expected }; match fcx.mk_assignty(expr, expr_ty, expected) { result::Ok(()) => { /* ok */ } result::Err(ref err) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 34c921b9d43df..7740e86106117 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1722,7 +1722,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt, match ty::get(method_fn_ty).sty { ty::ty_bare_fn(ref fty) => { // HACK(eddyb) ignore self in the definition (see above). - check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1), + let arg_tys = fty.sig.inputs.slice_from(1).iter() + .map(|t| { + fcx.infcx().resolve_type_vars_if_possible(*t) + }).collect::>(); + check_argument_types(fcx, sp, arg_tys.as_slice(), callee_expr, args, deref_args, fty.sig.variadic); fty.sig.output