about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2016-10-19 11:22:49 -0700
committerGitHub <noreply@github.com>2016-10-19 11:22:49 -0700
commitd4f39402a0c2c2b94ec0375cd7f7f6d7918113cd (patch)
tree0a3f7ab1668706d533e6692e8ce853c2aec4609a
parent3191fbae9da539442351f883bdabcad0d72efcb6 (diff)
parent2d493421cacc42d04e7626259cc08a51ef6c24cb (diff)
downloadrust-d4f39402a0c2c2b94ec0375cd7f7f6d7918113cd.tar.gz
rust-d4f39402a0c2c2b94ec0375cd7f7f6d7918113cd.zip
Merge pull request #37173 from brson/stable-next 1.12.1
[stable] Backports for 1.12.1
-rw-r--r--mk/main.mk2
-rw-r--r--src/librustc/ty/flags.rs5
-rw-r--r--src/librustc/ty/fold.rs2
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/mod.rs4
-rw-r--r--src/librustc_mir/build/expr/as_lvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs4
-rw-r--r--src/librustc_mir/build/expr/category.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs1
-rw-r--r--src/librustc_mir/hair/cx/expr.rs4
-rw-r--r--src/librustc_mir/hair/mod.rs3
-rw-r--r--src/librustc_trans/base.rs11
-rw-r--r--src/librustc_trans/builder.rs73
-rw-r--r--src/librustc_trans/collector.rs4
-rw-r--r--src/librustc_trans/mir/mod.rs35
-rw-r--r--src/librustc_typeck/check/_match.rs16
m---------src/llvm0
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
-rw-r--r--src/test/run-pass/issue-36381.rs34
-rw-r--r--src/test/run-pass/issue-36744-bitcast-args-if-needed.rs32
-rw-r--r--src/test/run-pass/issue-36744-without-calls.rs22
-rw-r--r--src/test/run-pass/issue-36856.rs24
-rw-r--r--src/test/run-pass/issue-36936.rs35
23 files changed, 268 insertions, 49 deletions
diff --git a/mk/main.mk b/mk/main.mk
index 90d3563240c..171ded42303 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -13,7 +13,7 @@
 ######################################################################
 
 # The version number
-CFG_RELEASE_NUM=1.12.0
+CFG_RELEASE_NUM=1.12.1
 
 # An optional number to put after the label, e.g. '.2' -> '-beta.2'
 # NB Make sure it starts with a dot to conform to semver pre-release
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 0997d6c1a75..a428c99119a 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -107,6 +107,11 @@ impl FlagComputation {
             }
 
             &ty::TyProjection(ref data) => {
+                // currently we can't normalize projections that
+                // include bound regions, so track those separately.
+                if !data.has_escaping_regions() {
+                    self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
+                }
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_projection_ty(data);
             }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 3eeff6ee579..a8826f0b23b 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -105,7 +105,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
                              TypeFlags::HAS_FREE_REGIONS |
                              TypeFlags::HAS_TY_INFER |
                              TypeFlags::HAS_PARAMS |
-                             TypeFlags::HAS_PROJECTION |
+                             TypeFlags::HAS_NORMALIZABLE_PROJECTION |
                              TypeFlags::HAS_TY_ERR |
                              TypeFlags::HAS_SELF)
     }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 8ddd8bef36a..5e4e7b342d6 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// Returns the def-id of `def_id`'s parent in the def tree. If
     /// this returns `None`, then `def_id` represents a crate root or
     /// inlined root.
-    fn parent_def_id(&self, def_id: DefId) -> Option<DefId> {
+    pub fn parent_def_id(&self, def_id: DefId) -> Option<DefId> {
         let key = self.def_key(def_id);
         key.parent.map(|index| DefId { krate: def_id.krate, index: index })
     }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index cfc2e89f9d5..02be1573bf1 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -527,6 +527,10 @@ bitflags! {
         // Only set for TyInfer other than Fresh.
         const KEEP_IN_LOCAL_TCX  = 1 << 11,
 
+        // Is there a projection that does not involve a bound region?
+        // Currently we can't normalize projections w/ bound regions.
+        const HAS_NORMALIZABLE_PROJECTION = 1 << 12,
+
         const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
                                    TypeFlags::HAS_SELF.bits |
                                    TypeFlags::HAS_RE_EARLY_BOUND.bits,
diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs
index ae5ccbfd820..78330f0b975 100644
--- a/src/librustc_mir/build/expr/as_lvalue.rs
+++ b/src/librustc_mir/build/expr/as_lvalue.rs
@@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::LogicalOp { .. } |
             ExprKind::Box { .. } |
             ExprKind::Cast { .. } |
+            ExprKind::Use { .. } |
             ExprKind::NeverToAny { .. } |
             ExprKind::ReifyFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index dafc53d3c15..3cd79ee1c5a 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -115,6 +115,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let source = unpack!(block = this.as_operand(block, source));
                 block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
             }
+            ExprKind::Use { source } => {
+                let source = unpack!(block = this.as_operand(block, source));
+                block.and(Rvalue::Use(source))
+            }
             ExprKind::ReifyFnPointer { source } => {
                 let source = unpack!(block = this.as_operand(block, source));
                 block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index c19ea0f445a..9671f80f48b 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -68,6 +68,7 @@ impl Category {
             ExprKind::Binary { .. } |
             ExprKind::Box { .. } |
             ExprKind::Cast { .. } |
+            ExprKind::Use { .. } |
             ExprKind::ReifyFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
             ExprKind::Unsize { .. } |
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index e5930f5a62d..58265b5b0d3 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -249,6 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Binary { .. } |
             ExprKind::Box { .. } |
             ExprKind::Cast { .. } |
+            ExprKind::Use { .. } |
             ExprKind::ReifyFnPointer { .. } |
             ExprKind::UnsafeFnPointer { .. } |
             ExprKind::Unsize { .. } |
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index a61fdb79df8..605798ad44c 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -602,8 +602,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             // Check to see if this cast is a "coercion cast", where the cast is actually done
             // using a coercion (or is a no-op).
             if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) {
-                // Skip the actual cast itexpr, as it's now a no-op.
-                return source.make_mirror(cx);
+                // Convert the lexpr to a vexpr.
+                ExprKind::Use { source: source.to_ref() }
             } else {
                 ExprKind::Cast { source: source.to_ref() }
             }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 2a5b7d0fb29..cc59346487e 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
     Cast {
         source: ExprRef<'tcx>,
     },
+    Use {
+        source: ExprRef<'tcx>,
+    }, // Use a lexpr to get a vexpr.
     NeverToAny {
         source: ExprRef<'tcx>,
     },
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index c78cda75e82..479a6a2cac3 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -320,7 +320,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 _ => bug!("compare_scalar_types: must be a comparison operator"),
             }
         }
-        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
+        ty::TyBool => {
+            // FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`,
+            // which works around some LLVM bugs
+            ICmp(bcx,
+                 bin_op_to_icmp_predicate(op, false),
+                 from_immediate(bcx, lhs),
+                 from_immediate(bcx, rhs),
+                 debug_loc)
+        }
+        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => {
             ICmp(bcx,
                  bin_op_to_icmp_predicate(op, false),
                  lhs,
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 90f96af5496..8556e95903c 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -22,6 +22,7 @@ use value::Value;
 use util::nodemap::FnvHashMap;
 use libc::{c_uint, c_char};
 
+use std::borrow::Cow;
 use std::ffi::CString;
 use std::ptr;
 use syntax_pos::Span;
@@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                    .collect::<Vec<String>>()
                    .join(", "));
 
-        check_call("invoke", llfn, args);
-
+        let args = self.check_call("invoke", llfn, args);
         let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
 
         unsafe {
@@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         assert!(!self.llbuilder.is_null());
         self.count_insn("store");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             llvm::LLVMBuildStore(self.llbuilder, val, ptr)
         }
@@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         assert!(!self.llbuilder.is_null());
         self.count_insn("store.volatile");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
             llvm::LLVMSetVolatile(insn, llvm::True);
@@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         self.count_insn("store.atomic");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
             let align = llalign_of_pref(self.ccx, ty.element_type());
@@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                    .collect::<Vec<String>>()
                    .join(", "));
 
-        check_call("call", llfn, args);
-
+        let args = self.check_call("call", llfn, args);
         let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
 
         unsafe {
@@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
         }
     }
-}
 
-fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
-    if cfg!(debug_assertions) {
+    /// Returns the ptr value that should be used for storing `val`.
+    fn check_store<'b>(&self,
+                       val: ValueRef,
+                       ptr: ValueRef) -> ValueRef {
+        let dest_ptr_ty = val_ty(ptr);
+        let stored_ty = val_ty(val);
+        let stored_ptr_ty = stored_ty.ptr_to();
+
+        assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
+
+        if dest_ptr_ty == stored_ptr_ty {
+            ptr
+        } else {
+            debug!("Type mismatch in store. \
+                    Expected {:?}, got {:?}; inserting bitcast",
+                   dest_ptr_ty, stored_ptr_ty);
+            self.bitcast(ptr, stored_ptr_ty)
+        }
+    }
+
+    /// Returns the args that should be used for a call to `llfn`.
+    fn check_call<'b>(&self,
+                      typ: &str,
+                      llfn: ValueRef,
+                      args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
         let mut fn_ty = val_ty(llfn);
         // Strip off pointers
         while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1115,16 +1139,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
 
         let param_tys = fn_ty.func_params();
 
-        let iter = param_tys.into_iter()
-            .zip(args.iter().map(|&v| val_ty(v)));
-        for (i, (expected_ty, actual_ty)) in iter.enumerate() {
-            if expected_ty != actual_ty {
-                bug!("Type mismatch in function call of {:?}. \
-                      Expected {:?} for param {}, got {:?}",
-                     Value(llfn),
-                     expected_ty, i, actual_ty);
+        let all_args_match = param_tys.iter()
+            .zip(args.iter().map(|&v| val_ty(v)))
+            .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
+
+        if all_args_match {
+            return Cow::Borrowed(args);
+        }
+
+        let casted_args: Vec<_> = param_tys.into_iter()
+            .zip(args.iter())
+            .enumerate()
+            .map(|(i, (expected_ty, &actual_val))| {
+                let actual_ty = val_ty(actual_val);
+                if expected_ty != actual_ty {
+                    debug!("Type mismatch in function call of {:?}. \
+                            Expected {:?} for param {}, got {:?}; injecting bitcast",
+                           Value(llfn),
+                           expected_ty, i, actual_ty);
+                    self.bitcast(actual_val, expected_ty)
+                } else {
+                    actual_val
+                }
+            })
+            .collect();
 
-            }
-        }
+        return Cow::Owned(casted_args);
     }
 }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index acc302430ae..fdd1ee1fba1 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -1042,7 +1042,9 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let concrete_substs = monomorphize::apply_param_substs(tcx,
                                                            param_substs,
                                                            &fn_substs);
-    assert!(concrete_substs.is_normalized_for_trans());
+    assert!(concrete_substs.is_normalized_for_trans(),
+            "concrete_substs not normalized for trans: {:?}",
+            concrete_substs);
     TransItem::Fn(Instance::new(def_id, concrete_substs))
 }
 
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 727b680541d..3b2059cd7ed 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -22,7 +22,6 @@ use machine;
 use type_of;
 
 use syntax_pos::DUMMY_SP;
-use syntax::parse::token::keywords;
 
 use std::ops::Deref;
 use std::rc::Rc;
@@ -301,7 +300,6 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
-            let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
             let lltemp = bcx.with_block(|bcx| {
                 base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
             });
@@ -319,27 +317,20 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
                 } else {
                     arg.store_fn_arg(bcx, &mut llarg_idx, dst);
                 }
-
-                bcx.with_block(|bcx| arg_scope.map(|scope| {
-                    let byte_offset_of_var_in_tuple =
-                        machine::llelement_offset(bcx.ccx(), lltuplety, i);
-
-                    let ops = unsafe {
-                        [llvm::LLVMRustDIBuilderCreateOpDeref(),
-                         llvm::LLVMRustDIBuilderCreateOpPlus(),
-                         byte_offset_of_var_in_tuple as i64]
-                    };
-
-                    let variable_access = VariableAccess::IndirectVariable {
-                        alloca: lltemp,
-                        address_operations: &ops
-                    };
-                    declare_local(bcx, keywords::Invalid.name(),
-                                  tupled_arg_ty, scope, variable_access,
-                                  VariableKind::ArgumentVariable(arg_index + i + 1),
-                                  bcx.fcx().span.unwrap_or(DUMMY_SP));
-                }));
             }
+
+            // Now that we have one alloca that contains the aggregate value,
+            // we can create one debuginfo entry for the argument.
+            bcx.with_block(|bcx| arg_scope.map(|scope| {
+                let variable_access = VariableAccess::DirectVariable {
+                    alloca: lltemp
+                };
+                declare_local(bcx, arg_decl.debug_name,
+                              arg_ty, scope, variable_access,
+                              VariableKind::ArgumentVariable(arg_index + 1),
+                              bcx.fcx().span.unwrap_or(DUMMY_SP));
+            }));
+
             return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
         }
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 04f22b19511..c2fba803857 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -535,13 +535,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 report_unexpected_def();
                 return;
             }
-            Def::Variant(..) | Def::Struct(..) => {
+            Def::Variant(..) => {
                 let variant = tcx.expect_variant_def(def);
                 if variant.kind != VariantKind::Unit {
                     report_unexpected_def();
                     return;
                 }
             }
+            Def::Struct(ctor_did) => {
+                let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent");
+                let variant = tcx.lookup_adt_def(did).struct_variant();
+                if variant.kind != VariantKind::Unit {
+                    report_unexpected_def();
+                    return;
+                }
+            }
             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
             _ => bug!("unexpected pattern definition {:?}", def)
         }
@@ -592,9 +600,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 report_unexpected_def(false);
                 return;
             }
-            Def::Variant(..) | Def::Struct(..) => {
+            Def::Variant(..) => {
                 tcx.expect_variant_def(def)
             }
+            Def::Struct(ctor_did) => {
+                let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent");
+                tcx.lookup_adt_def(did).struct_variant()
+            }
             _ => bug!("unexpected pattern definition {:?}", def)
         };
         if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
diff --git a/src/llvm b/src/llvm
-Subproject 7801978ec1f3637fcda1b564048ebc732bf586a
+Subproject ac1c94226e9fa17005ce7e2dd52dd6d1875f313
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index ea8d59290df..b12e25bba69 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2016-09-17
+2016-10-10
diff --git a/src/test/run-pass/issue-36381.rs b/src/test/run-pass/issue-36381.rs
new file mode 100644
index 00000000000..6cd991bd942
--- /dev/null
+++ b/src/test/run-pass/issue-36381.rs
@@ -0,0 +1,34 @@
+// Copyright 2014 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 #36381. The trans collector was asserting that
+// there are no projection types, but the `<&str as
+// StreamOnce>::Position` projection contained a late-bound region,
+// and we don't currently normalize in that case until the function is
+// actually invoked.
+
+pub trait StreamOnce {
+    type Position;
+}
+
+impl<'a> StreamOnce for &'a str {
+    type Position = usize;
+}
+
+pub fn parser<F>(_: F) {
+}
+
+fn follow(_: &str) -> <&str as StreamOnce>::Position {
+    panic!()
+}
+
+fn main() {
+    parser(follow);
+}
diff --git a/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs b/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs
new file mode 100644
index 00000000000..1859cc9ca00
--- /dev/null
+++ b/src/test/run-pass/issue-36744-bitcast-args-if-needed.rs
@@ -0,0 +1,32 @@
+// 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 tests for an ICE (and, if ignored, subsequent LLVM abort) when
+// a lifetime-parametric fn is passed into a context whose expected
+// type has a differing lifetime parameterization.
+
+struct A<'a> {
+    _a: &'a i32,
+}
+
+fn call<T>(s: T, functions: &Vec<for <'n> fn(&'n T)>) {
+    for function in functions {
+        function(&s);
+    }
+}
+
+fn f(a: &A) { println!("a holds {}", a._a); }
+
+fn main() {
+    let a = A { _a: &10 };
+
+    let vec: Vec<for <'u,'v> fn(&'u A<'v>)> = vec![f];
+    call(a, &vec);
+}
diff --git a/src/test/run-pass/issue-36744-without-calls.rs b/src/test/run-pass/issue-36744-without-calls.rs
new file mode 100644
index 00000000000..1766edb06b4
--- /dev/null
+++ b/src/test/run-pass/issue-36744-without-calls.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// Tests for an LLVM abort when storing a lifetime-parametric fn into
+// context that is expecting one that is not lifetime-parametric
+// (i.e. has no `for <'_>`).
+
+pub struct A<'a>(&'a ());
+pub struct S<T>(T);
+
+pub fn bad<'s>(v: &mut S<fn(A<'s>)>, y: S<for<'b> fn(A<'b>)>) {
+    *v = y;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-36856.rs b/src/test/run-pass/issue-36856.rs
new file mode 100644
index 00000000000..91a0dadd653
--- /dev/null
+++ b/src/test/run-pass/issue-36856.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 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 #36856.
+
+// compile-flags:-g
+
+fn g() -> bool {
+    false
+}
+
+pub fn main() {
+    let a = !g();
+    if a != !g() {
+        panic!();
+    }
+}
diff --git a/src/test/run-pass/issue-36936.rs b/src/test/run-pass/issue-36936.rs
new file mode 100644
index 00000000000..4216e2bb4fe
--- /dev/null
+++ b/src/test/run-pass/issue-36936.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.
+
+// check that casts are not being treated as lexprs.
+
+fn main() {
+    let mut a = 0i32;
+    let b = &(a as i32);
+    a = 1;
+    assert!((&a as *const i32) != (b as *const i32));
+    assert_eq!(*b, 0);
+
+    assert_eq!(issue_36936(), 1);
+}
+
+
+struct A(u32);
+
+impl Drop for A {
+    fn drop(&mut self) {
+        self.0 = 0;
+    }
+}
+
+fn issue_36936() -> u32 {
+    let a = &(A(1) as A);
+    a.0
+}