about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorCorey Farwell <coreyf@rwell.org>2017-04-27 19:59:18 -0400
committerGitHub <noreply@github.com>2017-04-27 19:59:18 -0400
commit1cd3d2f1c40ddf88351af96891f9ab7035130a9a (patch)
tree4c798951e22f95939947166532a8e03f35e93d0a /src
parent6fe2c24be0ec916abeb4875e424d82531706e812 (diff)
parenta260df27e0be9a2dd154376ee65c4c5d107927c0 (diff)
Rollup merge of #41578 - arielb1:missing-adjustment, r=eddyb
typeck: resolve type vars before calling `try_index_step`

`try_index_step` does not resolve type variables by itself and would
fail otherwise. Also harden the failure path in `confirm` to cause less
confusing errors.

r? @eddyb

Fixes #41498.

beta-nominating because regression (caused by #41279).
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/mem_categorization.rs11
-rw-r--r--src/librustc_errors/lib.rs3
-rw-r--r--src/librustc_typeck/check/method/confirm.rs11
-rw-r--r--src/test/run-pass/issue-41498.rs26
4 files changed, 49 insertions, 2 deletions
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 677eca10d7b..9db6dffb0e8 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -451,7 +451,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 // So peel off one-level, turning the &T into T.
                 match base_ty.builtin_deref(false, ty::NoPreference) {
                     Some(t) => t.ty,
-                    None => { return Err(()); }
+                    None => {
+                        debug!("By-ref binding of non-derefable type {:?}", base_ty);
+                        return Err(());
+                    }
                 }
             }
             _ => base_ty,
@@ -1039,6 +1042,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 match base_cmt.ty.builtin_index() {
                     Some(ty) => (ty, ElementKind::VecElement),
                     None => {
+                        debug!("Explicit index of non-indexable type {:?}", base_cmt);
                         return Err(());
                     }
                 }
@@ -1154,7 +1158,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
             PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
                 match path.def {
-                    Def::Err => return Err(()),
+                    Def::Err => {
+                        debug!("access to unresolvable pattern {:?}", pat);
+                        return Err(())
+                    }
                     Def::Variant(variant_did) |
                     Def::VariantCtor(variant_did, ..) => {
                         // univariant enums do not need downcasts
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index da29e354a70..cc8012d965a 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -375,6 +375,9 @@ impl Handler {
         panic!(ExplicitBug);
     }
     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+        if self.treat_err_as_bug {
+            self.span_bug(sp, msg);
+        }
         let mut delayed = self.delayed_span_bug.borrow_mut();
         *delayed = Some((sp.into(), msg.to_string()));
     }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index f0a74ea4be9..e81805b9660 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -516,6 +516,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                     };
 
                     let index_expr_ty = self.node_ty(index_expr.id);
+                    let adjusted_base_ty = self.resolve_type_vars_if_possible(&adjusted_base_ty);
+                    let index_expr_ty = self.resolve_type_vars_if_possible(&index_expr_ty);
 
                     let result = self.try_index_step(ty::MethodCall::expr(expr.id),
                                                      expr,
@@ -531,6 +533,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
                         let expr_ty = self.node_ty(expr.id);
                         self.demand_suptype(expr.span, expr_ty, return_ty);
+                    } else {
+                        // We could not perform a mutable index. Re-apply the
+                        // immutable index adjustments - borrowck will detect
+                        // this as an error.
+                        if let Some(adjustment) = adjustment {
+                            self.apply_adjustment(expr.id, adjustment);
+                        }
+                        self.tcx.sess.delay_span_bug(
+                            expr.span, "convert_lvalue_derefs_to_mutable failed");
                     }
                 }
                 hir::ExprUnary(hir::UnDeref, ref base_expr) => {
diff --git a/src/test/run-pass/issue-41498.rs b/src/test/run-pass/issue-41498.rs
new file mode 100644
index 00000000000..66fd30bdbbb
--- /dev/null
+++ b/src/test/run-pass/issue-41498.rs
@@ -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.
+
+// regression test for issue #41498.
+
+struct S;
+impl S {
+    fn mutate(&mut self) {}
+}
+
+fn call_and_ref<T, F: FnOnce() -> T>(x: &mut Option<T>, f: F) -> &mut T {
+    *x = Some(f());
+    x.as_mut().unwrap()
+}
+
+fn main() {
+    let mut n = None;
+    call_and_ref(&mut n, || [S])[0].mutate();
+}