From edc7f9abec051b3c388f3199c052a0f617a99423 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 27 Mar 2017 21:52:51 +0300 Subject: [PATCH] Avoid type-checking addition and indexing twice. --- src/librustc_typeck/check/mod.rs | 1 - src/librustc_typeck/check/op.rs | 21 +++++++++++---------- src/test/compile-fail/issue-40610.rs | 16 ++++++++++++++++ src/test/compile-fail/issue-40861.rs | 16 ++++++++++++++++ 4 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 src/test/compile-fail/issue-40610.rs create mode 100644 src/test/compile-fail/issue-40861.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index aaa3cf0f29e74..c995b7e92843d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3884,7 +3884,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { element_ty } None => { - self.check_expr_has_type(&idx, self.tcx.types.err); let mut err = self.type_error_struct( expr.span, |actual| { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index f492ab12e3f99..cc33bd8754d9e 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -184,9 +184,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // particularly for things like `String + &String`. let rhs_ty_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(rhs_expr.span)); - let return_ty = match self.lookup_op_method(expr, lhs_ty, vec![rhs_ty_var], - Symbol::intern(name), trait_def_id, - lhs_expr) { + let return_ty = self.lookup_op_method(expr, lhs_ty, vec![rhs_ty_var], + Symbol::intern(name), trait_def_id, + lhs_expr); + + // see `NB` above + let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var); + + let return_ty = match return_ty { Ok(return_ty) => return_ty, Err(()) => { // error types are considered "builtin" @@ -209,7 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty { if !self.infcx.type_moves_by_default(ty_mut.ty, lhs_expr.span) && - self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty_var], + self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty], Symbol::intern(name), trait_def_id, lhs_expr).is_ok() { err.note( @@ -240,7 +245,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(missing_trait) = missing_trait { if missing_trait == "std::ops::Add" && self.check_str_addition(expr, lhs_expr, lhs_ty, - rhs_expr, rhs_ty_var, &mut err) { + rhs_expr, rhs_ty, &mut err) { // This has nothing here because it means we did string // concatenation (e.g. "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted @@ -257,9 +262,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - // see `NB` above - self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var); - (rhs_ty_var, return_ty) } @@ -268,12 +270,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { lhs_expr: &'gcx hir::Expr, lhs_ty: Ty<'tcx>, rhs_expr: &'gcx hir::Expr, - rhs_ty_var: Ty<'tcx>, + rhs_ty: Ty<'tcx>, mut err: &mut errors::DiagnosticBuilder) -> bool { // If this function returns true it means a note was printed, so we don't need // to print the normal "implementation of `std::ops::Add` might be missing" note let mut is_string_addition = false; - let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var); if let TyRef(_, l_ty) = lhs_ty.sty { if let TyRef(_, r_ty) = rhs_ty.sty { if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr { diff --git a/src/test/compile-fail/issue-40610.rs b/src/test/compile-fail/issue-40610.rs new file mode 100644 index 0000000000000..aec20b4ad87b7 --- /dev/null +++ b/src/test/compile-fail/issue-40610.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +fn f(_: &[f32]) {} + +fn main() { + () + f(&[1.0]); + //~^ ERROR binary operation `+` cannot be applied to type `()` +} diff --git a/src/test/compile-fail/issue-40861.rs b/src/test/compile-fail/issue-40861.rs new file mode 100644 index 0000000000000..e525b3954f5ed --- /dev/null +++ b/src/test/compile-fail/issue-40861.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +fn f(_: &[f32]) {} + +fn main() { + ()[f(&[1.0])]; + //~^ ERROR cannot index a value of type `()` +}