New upstream version 1.12.1+dfsg1

This commit is contained in:
Sylvestre Ledru 2016-10-24 14:30:40 +02:00
parent 5bcae85e42
commit 1bb2cb6e3a
27 changed files with 267 additions and 61 deletions

View File

@ -13,7 +13,7 @@
###################################################################### ######################################################################
# The version number # 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' # 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 # NB Make sure it starts with a dot to conform to semver pre-release

View File

@ -1 +0,0 @@
* text=auto eol=lf

View File

@ -107,6 +107,11 @@ impl FlagComputation {
} }
&ty::TyProjection(ref data) => { &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_flags(TypeFlags::HAS_PROJECTION);
self.add_projection_ty(data); self.add_projection_ty(data);
} }

View File

@ -105,7 +105,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_FREE_REGIONS |
TypeFlags::HAS_TY_INFER | TypeFlags::HAS_TY_INFER |
TypeFlags::HAS_PARAMS | TypeFlags::HAS_PARAMS |
TypeFlags::HAS_PROJECTION | TypeFlags::HAS_NORMALIZABLE_PROJECTION |
TypeFlags::HAS_TY_ERR | TypeFlags::HAS_TY_ERR |
TypeFlags::HAS_SELF) TypeFlags::HAS_SELF)
} }

View File

@ -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 /// 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 /// this returns `None`, then `def_id` represents a crate root or
/// inlined root. /// 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); let key = self.def_key(def_id);
key.parent.map(|index| DefId { krate: def_id.krate, index: index }) key.parent.map(|index| DefId { krate: def_id.krate, index: index })
} }

View File

@ -527,6 +527,10 @@ bitflags! {
// Only set for TyInfer other than Fresh. // Only set for TyInfer other than Fresh.
const KEEP_IN_LOCAL_TCX = 1 << 11, 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 | const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits | TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits, TypeFlags::HAS_RE_EARLY_BOUND.bits,

View File

@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::LogicalOp { .. } | ExprKind::LogicalOp { .. } |
ExprKind::Box { .. } | ExprKind::Box { .. } |
ExprKind::Cast { .. } | ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::NeverToAny { .. } | ExprKind::NeverToAny { .. } |
ExprKind::ReifyFnPointer { .. } | ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } |

View File

@ -115,6 +115,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source = unpack!(block = this.as_operand(block, source)); let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) 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 } => { ExprKind::ReifyFnPointer { source } => {
let source = unpack!(block = this.as_operand(block, source)); let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty)) block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))

View File

@ -68,6 +68,7 @@ impl Category {
ExprKind::Binary { .. } | ExprKind::Binary { .. } |
ExprKind::Box { .. } | ExprKind::Box { .. } |
ExprKind::Cast { .. } | ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } | ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } | ExprKind::Unsize { .. } |

View File

@ -249,6 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Binary { .. } | ExprKind::Binary { .. } |
ExprKind::Box { .. } | ExprKind::Box { .. } |
ExprKind::Cast { .. } | ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } | ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } | ExprKind::Unsize { .. } |

View File

@ -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 // Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op). // using a coercion (or is a no-op).
if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) { 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. // Convert the lexpr to a vexpr.
return source.make_mirror(cx); ExprKind::Use { source: source.to_ref() }
} else { } else {
ExprKind::Cast { source: source.to_ref() } ExprKind::Cast { source: source.to_ref() }
} }

View File

@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
Cast { Cast {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
}, },
Use {
source: ExprRef<'tcx>,
}, // Use a lexpr to get a vexpr.
NeverToAny { NeverToAny {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
}, },

View File

@ -320,7 +320,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
_ => bug!("compare_scalar_types: must be a comparison operator"), _ => 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, ICmp(bcx,
bin_op_to_icmp_predicate(op, false), bin_op_to_icmp_predicate(op, false),
lhs, lhs,

View File

@ -22,6 +22,7 @@ use value::Value;
use util::nodemap::FnvHashMap; use util::nodemap::FnvHashMap;
use libc::{c_uint, c_char}; use libc::{c_uint, c_char};
use std::borrow::Cow;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use syntax_pos::Span; use syntax_pos::Span;
@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", ")); .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()); let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
unsafe { unsafe {
@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
assert!(!self.llbuilder.is_null()); assert!(!self.llbuilder.is_null());
self.count_insn("store"); self.count_insn("store");
let ptr = self.check_store(val, ptr);
unsafe { unsafe {
llvm::LLVMBuildStore(self.llbuilder, val, ptr) llvm::LLVMBuildStore(self.llbuilder, val, ptr)
} }
@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
assert!(!self.llbuilder.is_null()); assert!(!self.llbuilder.is_null());
self.count_insn("store.volatile"); self.count_insn("store.volatile");
let ptr = self.check_store(val, ptr);
unsafe { unsafe {
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr); let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
llvm::LLVMSetVolatile(insn, llvm::True); 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) { pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
self.count_insn("store.atomic"); self.count_insn("store.atomic");
let ptr = self.check_store(val, ptr);
unsafe { unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr)); let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
let align = llalign_of_pref(self.ccx, ty.element_type()); let align = llalign_of_pref(self.ccx, ty.element_type());
@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", ")); .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()); let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
unsafe { unsafe {
@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope); llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
} }
} }
}
fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) { /// Returns the ptr value that should be used for storing `val`.
if cfg!(debug_assertions) { 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); let mut fn_ty = val_ty(llfn);
// Strip off pointers // Strip off pointers
while fn_ty.kind() == llvm::TypeKind::Pointer { 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 param_tys = fn_ty.func_params();
let iter = param_tys.into_iter() let all_args_match = param_tys.iter()
.zip(args.iter().map(|&v| val_ty(v))); .zip(args.iter().map(|&v| val_ty(v)))
for (i, (expected_ty, actual_ty)) in iter.enumerate() { .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
if expected_ty != actual_ty {
bug!("Type mismatch in function call of {:?}. \
Expected {:?} for param {}, got {:?}",
Value(llfn),
expected_ty, i, 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);
} }
} }

View File

@ -1042,7 +1042,9 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let concrete_substs = monomorphize::apply_param_substs(tcx, let concrete_substs = monomorphize::apply_param_substs(tcx,
param_substs, param_substs,
&fn_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)) TransItem::Fn(Instance::new(def_id, concrete_substs))
} }

View File

@ -22,7 +22,6 @@ use machine;
use type_of; use type_of;
use syntax_pos::DUMMY_SP; use syntax_pos::DUMMY_SP;
use syntax::parse::token::keywords;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; 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?!") _ => bug!("spread argument isn't a tuple?!")
}; };
let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
let lltemp = bcx.with_block(|bcx| { let lltemp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) 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 { } else {
arg.store_fn_arg(bcx, &mut llarg_idx, dst); 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))); return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
} }

View File

@ -535,13 +535,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
report_unexpected_def(); report_unexpected_def();
return; return;
} }
Def::Variant(..) | Def::Struct(..) => { Def::Variant(..) => {
let variant = tcx.expect_variant_def(def); let variant = tcx.expect_variant_def(def);
if variant.kind != VariantKind::Unit { if variant.kind != VariantKind::Unit {
report_unexpected_def(); report_unexpected_def();
return; 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 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
_ => bug!("unexpected pattern definition {:?}", def) _ => bug!("unexpected pattern definition {:?}", def)
} }
@ -592,9 +600,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
report_unexpected_def(false); report_unexpected_def(false);
return; return;
} }
Def::Variant(..) | Def::Struct(..) => { Def::Variant(..) => {
tcx.expect_variant_def(def) 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) _ => bug!("unexpected pattern definition {:?}", def)
}; };
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() { if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {

View File

@ -1,6 +0,0 @@
[submodule "test/rust-installer-v1"]
path = test/rust-installer-v1
url = https://github.com/rust-lang/rust-installer
[submodule "test/rust-installer-v2"]
path = test/rust-installer-v2
url = https://github.com/rust-lang/rust-installer

View File

@ -1,3 +0,0 @@
[submodule "test/rust-installer-v1"]
path = test/rust-installer-v1
url = https://github.com/rust-lang/rust-installer

View File

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # 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 # 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. # build bots then the contents should be changed so git updates the mtime.
2016-09-17 2016-10-10

View File

@ -1 +0,0 @@
trailing-carriage-return-in-string.rs -text

View File

@ -1,2 +0,0 @@
lexer-crlf-line-endings-string-literal-doc-comment.rs -text
issue-16278.rs -text

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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() {}

View File

@ -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!();
}
}

View File

@ -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
}