about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-23 08:01:41 -0600
committerGitHub <noreply@github.com>2016-11-23 08:01:41 -0600
commit127a83df6615d09cda6ed9b53f7daba2d78c925d (patch)
treeeb600c4fd14fbd8ce216d84874396ee7b15440d5 /src
parent9fba8df2115141173ad60837f129f18e74424531 (diff)
parentd2c600a2c9bc0e180e6cef0920fd75e00ae03bfd (diff)
Auto merge of #37937 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 7 pull requests

- Successful merges: #37442, #37760, #37836, #37851, #37859, #37913, #37925
- Failed merges:
Diffstat (limited to 'src')
-rw-r--r--src/doc/index.md2
-rw-r--r--src/librustc/ty/mod.rs3
-rw-r--r--src/librustc/ty/walk.rs21
-rw-r--r--src/librustc_data_structures/small_vec.rs12
-rw-r--r--src/librustc_typeck/check/cast.rs44
-rw-r--r--src/libstd/env.rs18
-rw-r--r--src/libstd/net/addr.rs46
-rw-r--r--src/test/compile-fail/cast-rfc0401.rs5
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs254
-rw-r--r--src/test/run-pass-fulldeps/myriad-closures.rs (renamed from src/test/run-pass/myriad-closures.rs)8
-rw-r--r--src/test/run-pass/issue-23699.rs23
11 files changed, 415 insertions, 21 deletions
diff --git a/src/doc/index.md b/src/doc/index.md
index f8a1ec134d9..71dfcf0b067 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -17,7 +17,7 @@ the language.
 
 [**The Rust Reference**][ref]. While Rust does not have a
 specification, the reference tries to describe its working in
-detail. It tends to be out of date.
+detail. It is accurate, but not necessarily complete.
 
 [**Standard Library API Reference**][api]. Documentation for the
 standard library.
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e94e93158c4..ebf8c96def7 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -48,6 +48,7 @@ use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 use rustc_const_math::ConstInt;
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
 
 use hir;
 use hir::itemlikevisit::ItemLikeVisitor;
@@ -1887,7 +1888,7 @@ impl<'tcx> TyS<'tcx> {
     /// Iterator that walks the immediate children of `self`.  Hence
     /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
     /// (but not `i32`, like `walk`).
-    pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+    pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
         walk::walk_shallow(self)
     }
 
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index a6ecfd2fb70..2f9468dbe58 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -12,17 +12,22 @@
 //! WARNING: this does not keep track of the region depth.
 
 use ty::{self, Ty};
-use std::iter::Iterator;
-use std::vec::IntoIter;
+use rustc_data_structures::small_vec::SmallVec;
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+
+// The TypeWalker's stack is hot enough that it's worth going to some effort to
+// avoid heap allocations.
+pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8];
+pub type TypeWalkerStack<'tcx> = SmallVec<TypeWalkerArray<'tcx>>;
 
 pub struct TypeWalker<'tcx> {
-    stack: Vec<Ty<'tcx>>,
+    stack: TypeWalkerStack<'tcx>,
     last_subtree: usize,
 }
 
 impl<'tcx> TypeWalker<'tcx> {
     pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
-        TypeWalker { stack: vec![ty], last_subtree: 1, }
+        TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, }
     }
 
     /// Skips the subtree of types corresponding to the last type
@@ -61,8 +66,8 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
     }
 }
 
-pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
-    let mut stack = vec![];
+pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
+    let mut stack = SmallVec::new();
     push_subtypes(&mut stack, ty);
     stack.into_iter()
 }
@@ -73,7 +78,7 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
 // known to be significant to any code, but it seems like the
 // natural order one would expect (basically, the order of the
 // types as they are written).
-fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
+fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
         ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
         ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
@@ -112,7 +117,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
     }
 }
 
-fn push_sig_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, sig: &ty::PolyFnSig<'tcx>) {
+fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: &ty::PolyFnSig<'tcx>) {
     stack.push(sig.0.output);
     stack.extend(sig.0.inputs.iter().cloned().rev());
 }
diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs
index 565a3c443a3..4e2b3786021 100644
--- a/src/librustc_data_structures/small_vec.rs
+++ b/src/librustc_data_structures/small_vec.rs
@@ -130,6 +130,18 @@ impl<A: Array> SmallVec<A> {
             self.set_len(len + 1);
         }
     }
+
+    pub fn truncate(&mut self, len: usize) {
+        unsafe {
+            while len < self.len() {
+                // Decrement len before the drop_in_place(), so a panic on Drop
+                // doesn't re-drop the just-failed value.
+                let newlen = self.len() - 1;
+                self.set_len(newlen);
+                ::std::ptr::drop_in_place(self.get_unchecked_mut(newlen));
+            }
+        }
+    }
 }
 
 impl<A: Array> Deref for SmallVec<A> {
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 4edf0011cb3..5839c606566 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -102,6 +102,7 @@ enum CastError {
     /// Cast of thin to fat raw ptr (eg. `*const () as *const [u8]`)
     SizedUnsizedCast,
     IllegalCast,
+    NeedDeref,
     NeedViaPtr,
     NeedViaThinPtr,
     NeedViaInt,
@@ -138,6 +139,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
 
     fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
+            CastError::NeedDeref => {
+                let cast_ty = fcx.ty_to_string(self.cast_ty);
+                let mut err = fcx.type_error_struct(self.cast_span,
+                                       |actual| {
+                                           format!("casting `{}` as `{}` is invalid",
+                                                   actual,
+                                                   cast_ty)
+                                       },
+                                       self.expr_ty);
+                err.span_label(self.expr.span,
+                               &format!("cannot cast `{}` as `{}`",
+                                        fcx.ty_to_string(self.expr_ty),
+                                        cast_ty));
+                if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
+                    err.span_label(self.expr.span,
+                                   &format!("did you mean `*{}`?", snippet));
+                }
+                err.emit();
+            }
             CastError::NeedViaThinPtr |
             CastError::NeedViaPtr => {
                 let mut err = fcx.type_error_struct(self.span,
@@ -390,8 +410,28 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
             (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
             (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
-            (RPtr(_), Int(_)) |
-            (RPtr(_), Float) => Err(CastError::NeedViaPtr),
+            (RPtr(p), Int(_)) |
+            (RPtr(p), Float) => {
+                match p.ty.sty {
+                    ty::TypeVariants::TyInt(_) |
+                    ty::TypeVariants::TyUint(_) |
+                    ty::TypeVariants::TyFloat(_) => {
+                        Err(CastError::NeedDeref)
+                    }
+                    ty::TypeVariants::TyInfer(t) => {
+                        match t {
+                            ty::InferTy::IntVar(_) |
+                            ty::InferTy::FloatVar(_) |
+                            ty::InferTy::FreshIntTy(_) |
+                            ty::InferTy::FreshFloatTy(_) => {
+                                Err(CastError::NeedDeref)
+                            }
+                            _ => Err(CastError::NeedViaPtr),
+                        }
+                    }
+                    _ => Err(CastError::NeedViaPtr),
+                }
+            }
             // * -> ptr
             (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
             (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index e29dbe35c5a..baa2b5d2846 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -546,17 +546,23 @@ pub fn current_exe() -> io::Result<PathBuf> {
     os_imp::current_exe()
 }
 
-/// An iterator over the arguments of a process, yielding a `String` value
+/// An iterator over the arguments of a process, yielding a [`String`] value
 /// for each argument.
 ///
-/// This structure is created through the `std::env::args` method.
+/// This structure is created through the [`std::env::args`] method.
+///
+/// [`String`]: ../string/struct.String.html
+/// [`std::env::args`]: ./fn.args.html
 #[stable(feature = "env", since = "1.0.0")]
 pub struct Args { inner: ArgsOs }
 
-/// An iterator over the arguments of a process, yielding an `OsString` value
+/// An iterator over the arguments of a process, yielding an [`OsString`] value
 /// for each argument.
 ///
-/// This structure is created through the `std::env::args_os` method.
+/// This structure is created through the [`std::env::args_os`] method.
+///
+/// [`OsString`]: ../ffi/struct.OsString.html
+/// [`std::env::args_os`]: ./fn.args_os.html
 #[stable(feature = "env", since = "1.0.0")]
 pub struct ArgsOs { inner: sys::args::Args }
 
@@ -571,7 +577,7 @@ pub struct ArgsOs { inner: sys::args::Args }
 ///
 /// The returned iterator will panic during iteration if any argument to the
 /// process is not valid unicode. If this is not desired,
-/// use the `args_os` function instead.
+/// use the [`args_os`] function instead.
 ///
 /// # Examples
 ///
@@ -583,6 +589,8 @@ pub struct ArgsOs { inner: sys::args::Args }
 ///     println!("{}", argument);
 /// }
 /// ```
+///
+/// [`args_os`]: ./fn.args_os.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn args() -> Args {
     Args { inner: args_os() }
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 1c016015b79..0328012ee57 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -194,6 +194,14 @@ impl SocketAddr {
 
 impl SocketAddrV4 {
     /// Creates a new socket address from the (ip, port) pair.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
         SocketAddrV4 {
@@ -207,6 +215,15 @@ impl SocketAddrV4 {
     }
 
     /// Returns the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ip(&self) -> &Ipv4Addr {
         unsafe {
@@ -215,18 +232,47 @@ impl SocketAddrV4 {
     }
 
     /// Change the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
+    /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
+    /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
         self.inner.sin_addr = *new_ip.as_inner()
     }
 
     /// Returns the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
         ntoh(self.inner.sin_port)
     }
 
     /// Change the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// socket.set_port(4242);
+    /// assert_eq!(socket.port(), 4242);
+    /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
         self.inner.sin_port = hton(new_port);
diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs
index 1dbad9e30e3..b98f464c902 100644
--- a/src/test/compile-fail/cast-rfc0401.rs
+++ b/src/test/compile-fail/cast-rfc0401.rs
@@ -115,4 +115,9 @@ fn main()
     let _ = cf as *const Bar;
     //~^ ERROR casting
     //~^^ NOTE vtable kinds
+
+    vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+    //~^ ERROR casting `&{float}` as `f32` is invalid
+    //~| NOTE cannot cast `&{float}` as `f32`
+    //~| NOTE did you mean `*s`?
 }
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
new file mode 100644
index 00000000000..c4366ea11e3
--- /dev/null
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -0,0 +1,254 @@
+// 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.
+
+
+// This test case tests the incremental compilation hash (ICH) implementation
+// for struct constructor expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// must-compile-successfully
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+struct RegularStruct {
+    x: i32,
+    y: i64,
+    z: i16,
+}
+
+// Change field value (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_value_regular_struct() -> RegularStruct {
+    RegularStruct {
+        x: 0,
+        y: 1,
+        z: 2,
+    }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_field_value_regular_struct() -> RegularStruct {
+    RegularStruct {
+        x: 0,
+        y: 2,
+        z: 2,
+    }
+}
+
+
+
+// Change field order (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_order_regular_struct() -> RegularStruct {
+    RegularStruct {
+        x: 3,
+        y: 4,
+        z: 5,
+    }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_field_order_regular_struct() -> RegularStruct {
+    RegularStruct {
+        y: 4,
+        x: 3,
+        z: 5,
+    }
+}
+
+
+
+// Add field (regular struct) --------------------------------------------------
+#[cfg(cfail1)]
+fn add_field_regular_struct() -> RegularStruct {
+    let struct1 = RegularStruct {
+        x: 3,
+        y: 4,
+        z: 5,
+    };
+
+    RegularStruct {
+        x: 7,
+        .. struct1
+    }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn add_field_regular_struct() -> RegularStruct {
+    let struct1 = RegularStruct {
+        x: 3,
+        y: 4,
+        z: 5,
+    };
+
+    RegularStruct {
+        x: 7,
+        y: 8,
+        .. struct1
+    }
+}
+
+
+
+// Change field label (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_label_regular_struct() -> RegularStruct {
+    let struct1 = RegularStruct {
+        x: 3,
+        y: 4,
+        z: 5,
+    };
+
+    RegularStruct {
+        x: 7,
+        y: 9,
+        .. struct1
+    }
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_field_label_regular_struct() -> RegularStruct {
+    let struct1 = RegularStruct {
+        x: 3,
+        y: 4,
+        z: 5,
+    };
+
+    RegularStruct {
+        x: 7,
+        z: 9,
+        .. struct1
+    }
+}
+
+
+
+struct RegularStruct2 {
+    x: i8,
+    y: i8,
+    z: i8,
+}
+
+// Change constructor path (regular struct) ------------------------------------
+#[cfg(cfail1)]
+fn change_constructor_path_regular_struct() {
+    let _ = RegularStruct {
+        x: 0,
+        y: 1,
+        z: 2,
+    };
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_constructor_path_regular_struct() {
+    let _ = RegularStruct2 {
+        x: 0,
+        y: 1,
+        z: 2,
+    };
+}
+
+
+
+// Change constructor path indirectly (regular struct) -------------------------
+mod change_constructor_path_indirectly_regular_struct {
+    #[cfg(cfail1)]
+    use super::RegularStruct as Struct;
+    #[cfg(not(cfail1))]
+    use super::RegularStruct2 as Struct;
+
+    fn function() -> Struct {
+        Struct {
+            x: 0,
+            y: 1,
+            z: 2,
+        }
+    }
+}
+
+
+
+struct TupleStruct(i32, i64, i16);
+
+// Change field value (tuple struct) -------------------------------------------
+#[cfg(cfail1)]
+fn change_field_value_tuple_struct() -> TupleStruct {
+    TupleStruct(0, 1, 2)
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_field_value_tuple_struct() -> TupleStruct {
+    TupleStruct(0, 1, 3)
+}
+
+
+
+struct TupleStruct2(u16, u16, u16);
+
+// Change constructor path (tuple struct) --------------------------------------
+#[cfg(cfail1)]
+fn change_constructor_path_tuple_struct() {
+    let _ = TupleStruct(0, 1, 2);
+}
+
+#[cfg(not(cfail1))]
+#[rustc_dirty(label="Hir", cfg="cfail2")]
+#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_metadata_dirty(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+fn change_constructor_path_tuple_struct() {
+    let _ = TupleStruct2(0, 1, 2);
+}
+
+
+
+// Change constructor path indirectly (tuple struct) ---------------------------
+mod change_constructor_path_indirectly_tuple_struct {
+    #[cfg(cfail1)]
+    use super::TupleStruct as Struct;
+    #[cfg(not(cfail1))]
+    use super::TupleStruct2 as Struct;
+
+    fn function() -> Struct {
+        Struct(0, 1, 2)
+    }
+}
diff --git a/src/test/run-pass/myriad-closures.rs b/src/test/run-pass-fulldeps/myriad-closures.rs
index d2c9a5d562b..a946ec635b2 100644
--- a/src/test/run-pass/myriad-closures.rs
+++ b/src/test/run-pass-fulldeps/myriad-closures.rs
@@ -13,6 +13,9 @@
 // toolchain.
 // See https://github.com/rust-lang/rust/issues/34793 for more information.
 
+// Make sure we don't optimize anything away:
+// compile-flags: -C no-prepopulate-passes
+
 // Expand something exponentially
 macro_rules! go_bacterial {
     ($mac:ident) => ($mac!());
@@ -23,10 +26,7 @@ macro_rules! go_bacterial {
 }
 
 macro_rules! mk_closure {
-    () => ({
-        let c = |a: u32| a + 4;
-        let _ = c(2);
-    })
+    () => ((move || {})())
 }
 
 macro_rules! mk_fn {
diff --git a/src/test/run-pass/issue-23699.rs b/src/test/run-pass/issue-23699.rs
new file mode 100644
index 00000000000..1909be4df7b
--- /dev/null
+++ b/src/test/run-pass/issue-23699.rs
@@ -0,0 +1,23 @@
+// 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.
+
+fn gimme_a_raw_pointer<T>(_: *const T) { }
+
+fn test<T>(t: T) { }
+
+fn main() {
+    // Clearly `pointer` must be of type `*const ()`.
+    let pointer = &() as *const _;
+    gimme_a_raw_pointer(pointer);
+
+    let t = test as fn (i32);
+    t(0i32);
+}
+