Skip to content

Commit 0afe53e

Browse files
arielb1nikomatsakis
authored andcommitted
try to fix lvalue ops for real
Hopefully this is the last PR needed. Fixes #41726. Fixes #41742. Fixes #41774.
1 parent 4809658 commit 0afe53e

File tree

4 files changed

+109
-17
lines changed

4 files changed

+109
-17
lines changed

src/librustc_typeck/check/method/confirm.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -433,22 +433,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
433433
for (i, &expr) in exprs.iter().rev().enumerate() {
434434
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
435435

436-
// Fix up the adjustment.
437-
let autoderefs = match self.tables.borrow_mut().adjustments.get_mut(&expr.id) {
438-
Some(&mut Adjustment {
439-
kind: Adjust::DerefRef { autoderefs, ref mut autoref, .. }, ref mut target
440-
}) => {
441-
if let &mut Some(AutoBorrow::Ref(_, ref mut mutbl)) = autoref {
442-
*mutbl = hir::Mutability::MutMutable;
443-
*target = match target.sty {
444-
ty::TyRef(r, ty::TypeAndMut { ty, .. }) =>
445-
self.tcx.mk_ref(r, ty::TypeAndMut { ty, mutbl: *mutbl }),
446-
_ => span_bug!(expr.span, "AutoBorrow::Ref resulted in non-ref {:?}",
447-
target)
448-
};
449-
}
450-
autoderefs
451-
}
436+
// Fix up the autoderefs. Autorefs can only occur immediately preceding
437+
// overloaded lvalue ops, and will be fixed by them in order to get
438+
// the correct region.
439+
let autoderefs = match self.tables.borrow().adjustments.get(&expr.id) {
440+
Some(&Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => autoderefs,
452441
Some(_) | None => 0
453442
};
454443

@@ -502,10 +491,35 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
502491

503492
let method = self.try_overloaded_lvalue_op(
504493
expr.span, None, base_ty, arg_tys, PreferMutLvalue, op);
505-
let ok = method.expect("re-trying op failed");
494+
let ok = match method {
495+
Some(method) => method,
496+
None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
497+
};
506498
let method = self.register_infer_ok_obligations(ok);
507499
debug!("convert_lvalue_op_to_mutable: method={:?}", method);
508500
self.tables.borrow_mut().method_map.insert(method_call, method);
501+
502+
// Convert the autoref in the base expr to mutable with the correct
503+
// region and mutability.
504+
if let Some(&mut Adjustment {
505+
ref mut target, kind: Adjust::DerefRef {
506+
autoref: Some(AutoBorrow::Ref(ref mut r, ref mut mutbl)), ..
507+
}
508+
}) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
509+
debug!("convert_lvalue_op_to_mutable: converting autoref of {:?}", target);
510+
511+
// extract method return type, which will be &mut T;
512+
// all LB regions should have been instantiated during method lookup
513+
let method_sig = self.tcx.no_late_bound_regions(&method.ty.fn_sig()).unwrap();
514+
515+
*target = method_sig.inputs()[0];
516+
if let ty::TyRef(r_, mt) = target.sty {
517+
*r = r_;
518+
*mutbl = mt.mutbl;
519+
} else {
520+
span_bug!(expr.span, "input to lvalue op is not a ref?");
521+
}
522+
}
509523
}
510524

511525
///////////////////////////////////////////////////////////////////////////

src/test/compile-fail/issue-41726.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::collections::HashMap;
12+
fn main() {
13+
let things: HashMap<String, Vec<String>> = HashMap::new();
14+
for src in things.keys() {
15+
things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
16+
}
17+
}

src/test/compile-fail/issue-41742.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::ops::{Index, IndexMut};
12+
13+
struct S;
14+
struct H;
15+
16+
impl S {
17+
fn f(&mut self) {}
18+
}
19+
20+
impl Index<u32> for H {
21+
type Output = S;
22+
fn index(&self, index: u32) -> &S {
23+
unimplemented!()
24+
}
25+
}
26+
27+
impl IndexMut<u32> for H {
28+
fn index_mut(&mut self, index: u32) -> &mut S {
29+
unimplemented!()
30+
}
31+
}
32+
33+
fn main() {
34+
H["?"].f(); //~ ERROR mismatched types
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// check that we link regions in mutable lvalue ops correctly - issue #41774
12+
13+
struct Data(i32);
14+
15+
trait OhNo {
16+
fn oh_no(&mut self, other: &Vec<Data>) { loop {} }
17+
}
18+
19+
impl OhNo for Data {}
20+
impl OhNo for [Data] {}
21+
22+
fn main() {
23+
let mut v = vec![Data(0)];
24+
v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
25+
(*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
26+
}

0 commit comments

Comments
 (0)