diff options
| author | bors <bors@rust-lang.org> | 2018-01-10 12:29:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-01-10 12:29:05 +0000 |
| commit | f62f774035735a06c880c48c0b9017fcc0577e33 (patch) | |
| tree | f9951a684aed69cbec2e1f5876f25bba59789945 | |
| parent | 27ede55414e01f13c6869a8763da207e544cc6ad (diff) | |
| parent | 6132806d361dce863a220e278c568f83b72a3c8a (diff) | |
| download | rust-f62f774035735a06c880c48c0b9017fcc0577e33.tar.gz rust-f62f774035735a06c880c48c0b9017fcc0577e33.zip | |
Auto merge of #47167 - ivanbakel:builtin_indexing, r=nikomatsakis
Fix built-in indexing not being used where index type wasn't "obviously" usize Fixes #33903 Fixes #46095 This PR was made possible thanks to the generous help of @eddyb Following the example of binary operators, builtin checking for indexing has been moved from the typecheck stage to a writeback stage, after type constraints have been resolved.
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 12 | ||||
| -rw-r--r-- | src/librustc_typeck/check/writeback.rs | 46 | ||||
| -rw-r--r-- | src/test/run-pass/issue-33903.rs | 19 | ||||
| -rw-r--r-- | src/test/run-pass/issue-46095.rs | 39 |
4 files changed, 104 insertions, 12 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 57598f99bd1..69236d77ed3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2217,18 +2217,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adjusted_ty, index_ty); - // First, try built-in indexing. - match (adjusted_ty.builtin_index(), &index_ty.sty) { - (Some(ty), &ty::TyUint(ast::UintTy::Usize)) | - (Some(ty), &ty::TyInfer(ty::IntVar(_))) => { - debug!("try_index_step: success, using built-in indexing"); - let adjustments = autoderef.adjust_steps(lvalue_pref); - self.apply_adjustments(base_expr, adjustments); - return Some((self.tcx.types.usize, ty)); - } - _ => {} - } - for &unsize in &[false, true] { let mut self_ty = adjusted_ty; if unsize { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 29dc983ab56..5e102c7a445 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -18,6 +18,7 @@ use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::InferCtxt; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::adjustment::{Adjust, Adjustment}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::util::nodemap::DefIdSet; use syntax::ast; @@ -159,8 +160,52 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { _ => {} } } + + // Similar to operators, indexing is always assumed to be overloaded + // Here, correct cases where an indexing expression can be simplified + // to use builtin indexing because the index type is known to be + // usize-ish + fn fix_index_builtin_expr(&mut self, e: &hir::Expr) { + if let hir::ExprIndex(ref base, ref index) = e.node { + let mut tables = self.fcx.tables.borrow_mut(); + + match tables.expr_ty_adjusted(&base).sty { + // All valid indexing looks like this + ty::TyRef(_, ty::TypeAndMut { ty: ref base_ty, .. }) => { + let index_ty = tables.expr_ty_adjusted(&index); + let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty); + + if base_ty.builtin_index().is_some() + && index_ty == self.fcx.tcx.types.usize { + // Remove the method call record + tables.type_dependent_defs_mut().remove(e.hir_id); + tables.node_substs_mut().remove(e.hir_id); + + tables.adjustments_mut().get_mut(base.hir_id).map(|a| { + // Discard the need for a mutable borrow + match a.pop() { + // Extra adjustment made when indexing causes a drop + // of size information - we need to get rid of it + // Since this is "after" the other adjustment to be + // discarded, we do an extra `pop()` + Some(Adjustment { kind: Adjust::Unsize, .. }) => { + // So the borrow discard actually happens here + a.pop(); + }, + _ => {} + } + }); + } + }, + // Might encounter non-valid indexes at this point, so there + // has to be a fall-through + _ => {}, + } + } + } } + /////////////////////////////////////////////////////////////////////////// // Impl of Visitor for Resolver // @@ -176,6 +221,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); + self.fix_index_builtin_expr(e); self.visit_node_id(e.span, e.hir_id); diff --git a/src/test/run-pass/issue-33903.rs b/src/test/run-pass/issue-33903.rs new file mode 100644 index 00000000000..ab368537e21 --- /dev/null +++ b/src/test/run-pass/issue-33903.rs @@ -0,0 +1,19 @@ +// 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. + +// Issue 33903: +// Built-in indexing should be used even when the index is not +// trivially an integer +// Only built-in indexing can be used in constant expresssions + +const FOO: i32 = [12, 34][0 + 1]; + +fn main() {} + diff --git a/src/test/run-pass/issue-46095.rs b/src/test/run-pass/issue-46095.rs new file mode 100644 index 00000000000..35e51ebe70b --- /dev/null +++ b/src/test/run-pass/issue-46095.rs @@ -0,0 +1,39 @@ +// 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. + +struct A; + +impl A { + fn take_mutably(&mut self) {} +} + +fn identity<T>(t: T) -> T { + t +} + +// Issue 46095 +// Built-in indexing should be used even when the index is not +// trivially an integer +// Overloaded indexing would cause wrapped to be borrowed mutably + +fn main() { + let mut a1 = A; + let mut a2 = A; + + let wrapped = [&mut a1, &mut a2]; + + { + wrapped[0 + 1 - 1].take_mutably(); + } + + { + wrapped[identity(0)].take_mutably(); + } +} |
