try to fix lvalue ops for real
Hopefully this is the last PR needed. Fixes #41726. Fixes #41742. Fixes #41774.
This commit is contained in:
parent
ced823e267
commit
052d071bb2
@ -433,22 +433,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
for (i, &expr) in exprs.iter().rev().enumerate() {
|
for (i, &expr) in exprs.iter().rev().enumerate() {
|
||||||
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
|
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
|
||||||
|
|
||||||
// Fix up the adjustment.
|
// Fix up the autoderefs. Autorefs can only occur immediately preceding
|
||||||
let autoderefs = match self.tables.borrow_mut().adjustments.get_mut(&expr.id) {
|
// overloaded lvalue ops, and will be fixed by them in order to get
|
||||||
Some(&mut Adjustment {
|
// the correct region.
|
||||||
kind: Adjust::DerefRef { autoderefs, ref mut autoref, .. }, ref mut target
|
let autoderefs = match self.tables.borrow().adjustments.get(&expr.id) {
|
||||||
}) => {
|
Some(&Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => autoderefs,
|
||||||
if let &mut Some(AutoBorrow::Ref(_, ref mut mutbl)) = autoref {
|
|
||||||
*mutbl = hir::Mutability::MutMutable;
|
|
||||||
*target = match target.sty {
|
|
||||||
ty::TyRef(r, ty::TypeAndMut { ty, .. }) =>
|
|
||||||
self.tcx.mk_ref(r, ty::TypeAndMut { ty, mutbl: *mutbl }),
|
|
||||||
_ => span_bug!(expr.span, "AutoBorrow::Ref resulted in non-ref {:?}",
|
|
||||||
target)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
autoderefs
|
|
||||||
}
|
|
||||||
Some(_) | None => 0
|
Some(_) | None => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -502,10 +491,35 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
let method = self.try_overloaded_lvalue_op(
|
let method = self.try_overloaded_lvalue_op(
|
||||||
expr.span, None, base_ty, arg_tys, PreferMutLvalue, op);
|
expr.span, None, base_ty, arg_tys, PreferMutLvalue, op);
|
||||||
let ok = method.expect("re-trying op failed");
|
let ok = match method {
|
||||||
|
Some(method) => method,
|
||||||
|
None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
|
||||||
|
};
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
debug!("convert_lvalue_op_to_mutable: method={:?}", method);
|
debug!("convert_lvalue_op_to_mutable: method={:?}", method);
|
||||||
self.tables.borrow_mut().method_map.insert(method_call, method);
|
self.tables.borrow_mut().method_map.insert(method_call, method);
|
||||||
|
|
||||||
|
// Convert the autoref in the base expr to mutable with the correct
|
||||||
|
// region and mutability.
|
||||||
|
if let Some(&mut Adjustment {
|
||||||
|
ref mut target, kind: Adjust::DerefRef {
|
||||||
|
autoref: Some(AutoBorrow::Ref(ref mut r, ref mut mutbl)), ..
|
||||||
|
}
|
||||||
|
}) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
|
||||||
|
debug!("convert_lvalue_op_to_mutable: converting autoref of {:?}", target);
|
||||||
|
|
||||||
|
// extract method return type, which will be &mut T;
|
||||||
|
// all LB regions should have been instantiated during method lookup
|
||||||
|
let method_sig = self.tcx.no_late_bound_regions(&method.ty.fn_sig()).unwrap();
|
||||||
|
|
||||||
|
*target = method_sig.inputs()[0];
|
||||||
|
if let ty::TyRef(r_, mt) = target.sty {
|
||||||
|
*r = r_;
|
||||||
|
*mutbl = mt.mutbl;
|
||||||
|
} else {
|
||||||
|
span_bug!(expr.span, "input to lvalue op is not a ref?");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
17
src/test/compile-fail/issue-41726.rs
Normal file
17
src/test/compile-fail/issue-41726.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
fn main() {
|
||||||
|
let things: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
|
for src in things.keys() {
|
||||||
|
things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
|
||||||
|
}
|
||||||
|
}
|
35
src/test/compile-fail/issue-41742.rs
Normal file
35
src/test/compile-fail/issue-41742.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
struct H;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn f(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<u32> for H {
|
||||||
|
type Output = S;
|
||||||
|
fn index(&self, index: u32) -> &S {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<u32> for H {
|
||||||
|
fn index_mut(&mut self, index: u32) -> &mut S {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
H["?"].f(); //~ ERROR mismatched types
|
||||||
|
}
|
26
src/test/compile-fail/regions-adjusted-lvalue-op.rs
Normal file
26
src/test/compile-fail/regions-adjusted-lvalue-op.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// check that we link regions in mutable lvalue ops correctly - issue #41774
|
||||||
|
|
||||||
|
struct Data(i32);
|
||||||
|
|
||||||
|
trait OhNo {
|
||||||
|
fn oh_no(&mut self, other: &Vec<Data>) { loop {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OhNo for Data {}
|
||||||
|
impl OhNo for [Data] {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut v = vec![Data(0)];
|
||||||
|
v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
|
||||||
|
(*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user