Skip to content

Commit

Permalink
Avoid type-checking addition and indexing twice.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 6, 2017
1 parent 44855a4 commit edc7f9a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 11 deletions.
1 change: 0 additions & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
21 changes: 11 additions & 10 deletions src/librustc_typeck/check/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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)
}

Expand All @@ -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 {
Expand Down
16 changes: 16 additions & 0 deletions src/test/compile-fail/issue-40610.rs
Original file line number Diff line number Diff line change
@@ -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 <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 f(_: &[f32]) {}

fn main() {
() + f(&[1.0]);
//~^ ERROR binary operation `+` cannot be applied to type `()`
}
16 changes: 16 additions & 0 deletions src/test/compile-fail/issue-40861.rs
Original file line number Diff line number Diff line change
@@ -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 <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 f(_: &[f32]) {}

fn main() {
()[f(&[1.0])];
//~^ ERROR cannot index a value of type `()`
}

0 comments on commit edc7f9a

Please sign in to comment.