]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #41828 - arielb1:lvalue-ops, r=eddyb
authorCorey Farwell <coreyf@rwell.org>
Tue, 9 May 2017 02:34:50 +0000 (22:34 -0400)
committerGitHub <noreply@github.com>
Tue, 9 May 2017 02:34:50 +0000 (22:34 -0400)
try to fix lvalue ops for real

Hopefully this is the last PR needed.

Fixes #41726.
Fixes #41742.
Fixes #41774.

src/librustc_typeck/check/method/confirm.rs
src/test/compile-fail/issue-41726.rs [new file with mode: 0644]
src/test/compile-fail/issue-41742.rs [new file with mode: 0644]
src/test/compile-fail/regions-adjusted-lvalue-op.rs [new file with mode: 0644]

index fdde4e9fef497cedbfa82d1a71fbe4ce9c844080..a9e82a0601feeafe8784bba5458cb49e51271399 100644 (file)
@@ -433,22 +433,11 @@ fn convert_lvalue_derefs_to_mutable(&self) {
         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 @@ fn convert_lvalue_op_to_mutable(&self,
 
         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?");
+            }
+        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/src/test/compile-fail/issue-41726.rs b/src/test/compile-fail/issue-41726.rs
new file mode 100644 (file)
index 0000000..c8cd920
--- /dev/null
@@ -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
+    }
+}
diff --git a/src/test/compile-fail/issue-41742.rs b/src/test/compile-fail/issue-41742.rs
new file mode 100644 (file)
index 0000000..067531e
--- /dev/null
@@ -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
+}
diff --git a/src/test/compile-fail/regions-adjusted-lvalue-op.rs b/src/test/compile-fail/regions-adjusted-lvalue-op.rs
new file mode 100644 (file)
index 0000000..167c863
--- /dev/null
@@ -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
+}