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() {
|
||||
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
|
||||
|
||||
// Fix up the adjustment.
|
||||
let autoderefs = match self.tables.borrow_mut().adjustments.get_mut(&expr.id) {
|
||||
Some(&mut Adjustment {
|
||||
kind: Adjust::DerefRef { autoderefs, ref mut autoref, .. }, ref mut target
|
||||
}) => {
|
||||
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
|
||||
}
|
||||
// Fix up the autoderefs. Autorefs can only occur immediately preceding
|
||||
// overloaded lvalue ops, and will be fixed by them in order to get
|
||||
// the correct region.
|
||||
let autoderefs = match self.tables.borrow().adjustments.get(&expr.id) {
|
||||
Some(&Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => autoderefs,
|
||||
Some(_) | None => 0
|
||||
};
|
||||
|
||||
@ -502,10 +491,35 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
let method = self.try_overloaded_lvalue_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);
|
||||
debug!("convert_lvalue_op_to_mutable: method={:?}", 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