about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-15 06:54:18 +0000
committerbors <bors@rust-lang.org>2018-08-15 06:54:18 +0000
commit81cfaad030435aae447d73c66123b3df856c09cb (patch)
treea1808fdca400c8292d201cc8c05c13d1149ced7e
parentafd0a2f2499ff66e74236c5b06d3ab9ab87dd3d3 (diff)
parent644765197abd9a219d88b98323084b2ac29388b7 (diff)
Auto merge of #53212 - sunjay:nll-raw-cast, r=nikomatsakis
NLL - Prevent where clauses from extending the lifetime of bindings

Fixes https://github.com/rust-lang/rust/issues/53123

r? @nikomatsakis
-rw-r--r--src/librustc/traits/select.rs15
-rw-r--r--src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs35
2 files changed, 49 insertions, 1 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index fbd12c9fe8e..ea96c305026 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -226,6 +226,7 @@ pub struct SelectionCache<'tcx> {
 /// parameter environment.
 #[derive(PartialEq,Eq,Debug,Clone)]
 enum SelectionCandidate<'tcx> {
+    /// If has_nested is false, there are no *further* obligations
     BuiltinCandidate { has_nested: bool },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(DefId),
@@ -2039,12 +2040,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         }
 
         match other.candidate {
+            // Prefer BuiltinCandidate { has_nested: false } to anything else.
+            // This is a fix for #53123 and prevents winnowing from accidentally extending the
+            // lifetime of a variable.
+            BuiltinCandidate { has_nested: false } => true,
             ParamCandidate(ref cand) => match victim.candidate {
                 AutoImplCandidate(..) => {
                     bug!(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
                 }
+                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
                 ImplCandidate(..) |
                 ClosureCandidate |
                 GeneratorCandidate |
@@ -2072,6 +2081,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
                 }
+                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
                 ImplCandidate(..) |
                 ClosureCandidate |
                 GeneratorCandidate |
@@ -2115,7 +2128,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             FnPointerCandidate |
             BuiltinObjectCandidate |
             BuiltinUnsizeCandidate |
-            BuiltinCandidate { .. } => {
+            BuiltinCandidate { has_nested: true } => {
                 match victim.candidate {
                     ParamCandidate(ref cand) => {
                         // Prefer these to a global where-clause bound
diff --git a/src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs b/src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs
new file mode 100644
index 00000000000..7959f1737b9
--- /dev/null
+++ b/src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+#![feature(nll)]
+#![allow(unused_variables)]
+
+pub trait TryTransform {
+    fn try_transform<F>(self, f: F)
+    where
+        Self: Sized,
+        F: FnOnce(Self);
+}
+
+impl<'a, T> TryTransform for &'a mut T {
+    fn try_transform<F>(self, f: F)
+    where
+        // The bug was that `Self: Sized` caused the lifetime of `this` to "extend" for all
+        // of 'a instead of only lasting as long as the binding is used (for just that line).
+        Self: Sized,
+        F: FnOnce(Self),
+    {
+        let this: *mut T = self as *mut T;
+        f(self);
+    }
+}
+
+fn main() {
+}