Change:
Hello, today we've found some weird behaviour of array indexing. Here is the Code snippet: The question is, why is the indexing operator behaves depending on whether we evaluate in place or not.
Highly related question :
Moreover, does not compile too.
points to this being a difference in how builtin indexing works vs overloaded indexing. My cleaned up version of the transcript: Highly related to , which will cause these types of situations to occur more frequently.
As a workaround, you can write an explicit type of which will then allow builtin indexing to happen:

Discussion:
adjusted_ty, index_ty); <del> // 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)); } _ => {} } </del> for &unsize in &[false, true] { let mut self_ty = adjusted_ty; if unsize {

use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::InferCtxt; use rustc::ty::{self, Ty, TyCtxt}; <ins> use rustc::ty::adjustment::{Adjust, Adjustment}; </ins> use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::util::nodemap::DefIdSet; use syntax::ast;

_ => {} } } <ins> // 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 _ => {}, } } } </ins> } /////////////////////////////////////////////////////////////////////////// // Impl of Visitor for Resolver //

fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); <ins> self.fix_index_builtin_expr(e); </ins> self.visit_node_id(e.span, e.hir_id);

<ins> // 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() {} </ins>

<ins> // 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(); } } </ins>