From f2235379bf5f205cef71baa4ba84b27035c3624b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 30 Sep 2016 18:15:11 -0400 Subject: [PATCH 01/10] loosen assertion against proj in collector The collector was asserting a total absence of projections, but some projections are expected, even in trans: in particular, projections containing higher-ranked regions, which we don't currently normalize. --- src/librustc/ty/flags.rs | 5 +++++ src/librustc/ty/fold.rs | 2 +- src/librustc/ty/mod.rs | 4 ++++ src/librustc_trans/collector.rs | 4 +++- src/test/run-pass/issue-36381.rs | 34 ++++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-36381.rs diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0997d6c1a7562..a428c99119a38 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 3eeff6ee5792f..a8826f0b23ba6 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/mod.rs b/src/librustc/ty/mod.rs index cfc2e89f9d5a1..02be1573bf176 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_trans/collector.rs b/src/librustc_trans/collector.rs index acc302430aee6..fdd1ee1fba1d9 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/test/run-pass/issue-36381.rs b/src/test/run-pass/issue-36381.rs new file mode 100644 index 0000000000000..6cd991bd942df --- /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 or the MIT license +// , 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) { +} + +fn follow(_: &str) -> <&str as StreamOnce>::Position { + panic!() +} + +fn main() { + parser(follow); +} From ca1b124cb8d6d30b2dbe516dc7e97e4818acee34 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 4 Oct 2016 05:55:45 -0400 Subject: [PATCH 02/10] force `i1` booleans to `i8` when comparing Work around LLVM bug. cc #36856 --- src/librustc_trans/base.rs | 11 ++++++++++- src/test/run-pass/issue-36856.rs | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-36856.rs diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c78cda75e820e..479a6a2cac3ed 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/test/run-pass/issue-36856.rs b/src/test/run-pass/issue-36856.rs new file mode 100644 index 0000000000000..91a0dadd65328 --- /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 or the MIT license +// , 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!(); + } +} From 566df6ca4b3dd9ff2bb0ae556941bd9085abb912 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 10 Oct 2016 11:12:29 -0400 Subject: [PATCH 03/10] LLVM: Backport "[SimplifyCFG] Correctly test for unconditional branches in GetCaseResults" --- src/llvm | 2 +- src/rustllvm/llvm-auto-clean-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index 7801978ec1f36..ac1c94226e9fa 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 7801978ec1f3637fcda1b564048ebc732bf586af +Subproject commit ac1c94226e9fa17005ce7e2dd52dd6d1875f3137 diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index ea8d59290df2e..b12e25bba694f 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 From 580cbd889f4a9e2baae3efda8589c6721da3f0f2 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 01:13:36 +0300 Subject: [PATCH 04/10] stop having identity casts be lexprs that made no sense (see test), and was incompatible with borrowck. Fixes #36936. --- src/librustc_mir/build/expr/as_lvalue.rs | 1 + src/librustc_mir/build/expr/as_rvalue.rs | 4 +++ src/librustc_mir/build/expr/category.rs | 1 + src/librustc_mir/build/expr/into.rs | 1 + src/librustc_mir/hair/cx/expr.rs | 4 +-- src/librustc_mir/hair/mod.rs | 3 ++ src/test/run-pass/issue-36936.rs | 35 ++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-36936.rs diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index ae5ccbfd82099..78330f0b9753b 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 dafc53d3c1542..3cd79ee1c5aa1 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 c19ea0f445ac0..9671f80f48ba7 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 e5930f5a62df6..58265b5b0d36b 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 a61fdb79df822..605798ad44ce1 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 2a5b7d0fb2902..cc59346487e39 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/test/run-pass/issue-36936.rs b/src/test/run-pass/issue-36936.rs new file mode 100644 index 0000000000000..4216e2bb4fe6c --- /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 or the MIT license +// , 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 +} From d0374d0475150281359debe1355c10e1d0e51cfa Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Sep 2016 00:51:46 +0300 Subject: [PATCH 05/10] Temporary fix for metadata decoding for struct constructors --- src/librustc/ty/item_path.rs | 2 +- src/librustc_typeck/check/_match.rs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8ddd8bef36a6f..5e4e7b342d631 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 { + pub fn parent_def_id(&self, def_id: DefId) -> Option { let key = self.def_key(def_id); key.parent.map(|index| DefId { krate: def_id.krate, index: index }) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 04f22b195110f..c2fba80385784 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() { From 70107c8a7a75f26b59ac73b735492ef213c0b436 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 14 Oct 2016 12:04:54 -0700 Subject: [PATCH 06/10] Bump version to 1.12.1 --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index 90d3563240cd3..171ded4230370 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 From 3361f1335024816cf4418cbf93eb47a5c38d970d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 17:36:04 +0200 Subject: [PATCH 07/10] Fix ICE by injecting bitcasts if types mismatch when building invokes or calls. --- src/librustc_trans/builder.rs | 49 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 90f96af549691..7e72b977de458 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::>() .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 { @@ -857,8 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .collect::>() .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 +1099,11 @@ 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) { + 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 +1115,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); } } From 45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 19:26:06 +0200 Subject: [PATCH 08/10] Inject bitcast if types mismatch when building a store instruction. --- src/librustc_trans/builder.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 7e72b977de458..8556e95903c18 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -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()); @@ -1100,6 +1103,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + /// 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, From f6859b07967e51de2620566340cfa8c4b1a7c4ab Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 12 Oct 2016 19:29:50 +0200 Subject: [PATCH 09/10] Some tests to check that lifetime parametric fn's do not trip up LLVM. --- .../issue-36744-bitcast-args-if-needed.rs | 32 +++++++++++++++++++ .../run-pass/issue-36744-without-calls.rs | 22 +++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/test/run-pass/issue-36744-bitcast-args-if-needed.rs create mode 100644 src/test/run-pass/issue-36744-without-calls.rs 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 0000000000000..1859cc9ca00b5 --- /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 or the MIT license +// , 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(s: T, functions: &Vec 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 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 0000000000000..1766edb06b481 --- /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 or the MIT license +// , 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); + +pub fn bad<'s>(v: &mut S)>, y: S fn(A<'b>)>) { + *v = y; +} + +fn main() {} From 2d493421cacc42d04e7626259cc08a51ef6c24cb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 13 Oct 2016 14:55:31 -0400 Subject: [PATCH 10/10] debuginfo: Create debuginfo for re-aggregated spread_arg instead of for the individual pieces. --- src/librustc_trans/mir/mod.rs | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 727b680541dd7..3b2059cd7ed18 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))); }