Skip to content

Commit ba70db9

Browse files
authored
Merge pull request #37239 from brson/beta-next
[beta] backports
2 parents 6d9b0bf + b477047 commit ba70db9

16 files changed

+172
-53
lines changed

src/librustc/infer/mod.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,8 @@ impl_trans_normalize!('gcx,
583583
ty::FnSig<'gcx>,
584584
&'gcx ty::BareFnTy<'gcx>,
585585
ty::ClosureSubsts<'gcx>,
586-
ty::PolyTraitRef<'gcx>
586+
ty::PolyTraitRef<'gcx>,
587+
ty::ExistentialTraitRef<'gcx>
587588
);
588589

589590
impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
@@ -603,6 +604,18 @@ impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
603604

604605
// NOTE: Callable from trans only!
605606
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
607+
/// Currently, higher-ranked type bounds inhibit normalization. Therefore,
608+
/// each time we erase them in translation, we need to normalize
609+
/// the contents.
610+
pub fn erase_late_bound_regions_and_normalize<T>(self, value: &ty::Binder<T>)
611+
-> T
612+
where T: TransNormalize<'tcx>
613+
{
614+
assert!(!value.needs_subst());
615+
let value = self.erase_late_bound_regions(value);
616+
self.normalize_associated_type(&value)
617+
}
618+
606619
pub fn normalize_associated_type<T>(self, value: &T) -> T
607620
where T: TransNormalize<'tcx>
608621
{

src/librustc_trans/base.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,7 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
11331133
let fn_ty = ccx.tcx().erase_regions(&fn_ty);
11341134
let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty);
11351135

1136-
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
1137-
let sig = ccx.tcx().normalize_associated_type(&sig);
1136+
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(fn_ty.fn_sig());
11381137
let abi = fn_ty.fn_abi();
11391138

11401139
let lldecl = match ccx.instances().borrow().get(&instance) {
@@ -1156,8 +1155,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
11561155
let ctor_ty = ccx.tcx().lookup_item_type(def_id).ty;
11571156
let ctor_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &ctor_ty);
11581157

1159-
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
1160-
let sig = ccx.tcx().normalize_associated_type(&sig);
1158+
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
11611159
let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
11621160

11631161
let (arena, fcx): (TypedArena<_>, FunctionContext);

src/librustc_trans/builder.rs

+56-17
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use value::Value;
2222
use util::nodemap::FnvHashMap;
2323
use libc::{c_uint, c_char};
2424

25+
use std::borrow::Cow;
2526
use std::ffi::CString;
2627
use std::ptr;
2728
use syntax_pos::Span;
@@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
175176
.collect::<Vec<String>>()
176177
.join(", "));
177178

178-
check_call("invoke", llfn, args);
179-
179+
let args = self.check_call("invoke", llfn, args);
180180
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
181181

182182
unsafe {
@@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
543543
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
544544
assert!(!self.llbuilder.is_null());
545545
self.count_insn("store");
546+
let ptr = self.check_store(val, ptr);
546547
unsafe {
547548
llvm::LLVMBuildStore(self.llbuilder, val, ptr)
548549
}
@@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
552553
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
553554
assert!(!self.llbuilder.is_null());
554555
self.count_insn("store.volatile");
556+
let ptr = self.check_store(val, ptr);
555557
unsafe {
556558
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
557559
llvm::LLVMSetVolatile(insn, llvm::True);
@@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
562564
pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
563565
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
564566
self.count_insn("store.atomic");
567+
let ptr = self.check_store(val, ptr);
565568
unsafe {
566569
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
567570
let align = llalign_of_pref(self.ccx, ty.element_type());
@@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
857860
.collect::<Vec<String>>()
858861
.join(", "));
859862

860-
check_call("call", llfn, args);
861-
863+
let args = self.check_call("call", llfn, args);
862864
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
863865

864866
unsafe {
@@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11001102
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
11011103
}
11021104
}
1103-
}
11041105

1105-
fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
1106-
if cfg!(debug_assertions) {
1106+
/// Returns the ptr value that should be used for storing `val`.
1107+
fn check_store<'b>(&self,
1108+
val: ValueRef,
1109+
ptr: ValueRef) -> ValueRef {
1110+
let dest_ptr_ty = val_ty(ptr);
1111+
let stored_ty = val_ty(val);
1112+
let stored_ptr_ty = stored_ty.ptr_to();
1113+
1114+
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
1115+
1116+
if dest_ptr_ty == stored_ptr_ty {
1117+
ptr
1118+
} else {
1119+
debug!("Type mismatch in store. \
1120+
Expected {:?}, got {:?}; inserting bitcast",
1121+
dest_ptr_ty, stored_ptr_ty);
1122+
self.bitcast(ptr, stored_ptr_ty)
1123+
}
1124+
}
1125+
1126+
/// Returns the args that should be used for a call to `llfn`.
1127+
fn check_call<'b>(&self,
1128+
typ: &str,
1129+
llfn: ValueRef,
1130+
args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
11071131
let mut fn_ty = val_ty(llfn);
11081132
// Strip off pointers
11091133
while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1115,16 +1139,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
11151139

11161140
let param_tys = fn_ty.func_params();
11171141

1118-
let iter = param_tys.into_iter()
1119-
.zip(args.iter().map(|&v| val_ty(v)));
1120-
for (i, (expected_ty, actual_ty)) in iter.enumerate() {
1121-
if expected_ty != actual_ty {
1122-
bug!("Type mismatch in function call of {:?}. \
1123-
Expected {:?} for param {}, got {:?}",
1124-
Value(llfn),
1125-
expected_ty, i, actual_ty);
1142+
let all_args_match = param_tys.iter()
1143+
.zip(args.iter().map(|&v| val_ty(v)))
1144+
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
1145+
1146+
if all_args_match {
1147+
return Cow::Borrowed(args);
1148+
}
1149+
1150+
let casted_args: Vec<_> = param_tys.into_iter()
1151+
.zip(args.iter())
1152+
.enumerate()
1153+
.map(|(i, (expected_ty, &actual_val))| {
1154+
let actual_ty = val_ty(actual_val);
1155+
if expected_ty != actual_ty {
1156+
debug!("Type mismatch in function call of {:?}. \
1157+
Expected {:?} for param {}, got {:?}; injecting bitcast",
1158+
Value(llfn),
1159+
expected_ty, i, actual_ty);
1160+
self.bitcast(actual_val, expected_ty)
1161+
} else {
1162+
actual_val
1163+
}
1164+
})
1165+
.collect();
11261166

1127-
}
1128-
}
1167+
return Cow::Owned(casted_args);
11291168
}
11301169
}

src/librustc_trans/callee.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ impl<'tcx> Callee<'tcx> {
184184
pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
185185
extra_args: &[Ty<'tcx>]) -> FnType {
186186
let abi = self.ty.fn_abi();
187-
let sig = ccx.tcx().erase_late_bound_regions(self.ty.fn_sig());
188-
let sig = ccx.tcx().normalize_associated_type(&sig);
187+
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(self.ty.fn_sig());
189188
let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args);
190189
if let Virtual(_) = self.data {
191190
// Don't pass the vtable, it's not an argument of the virtual fn.
@@ -327,8 +326,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
327326
bare_fn_ty);
328327
}
329328
};
330-
let sig = tcx.erase_late_bound_regions(sig);
331-
let sig = ccx.tcx().normalize_associated_type(&sig);
329+
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
332330
let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
333331
let sig = ty::FnSig {
334332
inputs: vec![bare_fn_ty_maybe_ref,

src/librustc_trans/closure.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
6161

6262
// Compute the rust-call form of the closure call method.
6363
let sig = &tcx.closure_type(closure_id, substs).sig;
64-
let sig = tcx.erase_late_bound_regions(sig);
65-
let sig = tcx.normalize_associated_type(&sig);
64+
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
6665
let closure_type = tcx.mk_closure_from_closure_substs(closure_id, substs);
6766
let function_type = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
6867
unsafety: hir::Unsafety::Normal,
@@ -126,8 +125,7 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
126125
// of the closure expression.
127126

128127
let sig = &tcx.closure_type(closure_def_id, closure_substs).sig;
129-
let sig = tcx.erase_late_bound_regions(sig);
130-
let sig = tcx.normalize_associated_type(&sig);
128+
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
131129

132130
let closure_type = tcx.mk_closure_from_closure_substs(closure_def_id,
133131
closure_substs);
@@ -249,8 +247,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
249247
assert_eq!(abi, Abi::RustCall);
250248
sig.0.inputs[0] = closure_ty;
251249

252-
let sig = tcx.erase_late_bound_regions(&sig);
253-
let sig = tcx.normalize_associated_type(&sig);
250+
let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
254251
let fn_ty = FnType::new(ccx, abi, &sig, &[]);
255252

256253
let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {

src/librustc_trans/debuginfo/metadata.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ impl<'tcx> TypeMap<'tcx> {
235235
ty::TyTrait(ref trait_data) => {
236236
unique_type_id.push_str("trait ");
237237

238-
let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
238+
let principal = cx.tcx().erase_late_bound_regions_and_normalize(
239+
&trait_data.principal);
239240

240241
from_def_id_and_substs(self,
241242
cx,
@@ -253,8 +254,7 @@ impl<'tcx> TypeMap<'tcx> {
253254

254255
unique_type_id.push_str(" fn(");
255256

256-
let sig = cx.tcx().erase_late_bound_regions(sig);
257-
let sig = cx.tcx().normalize_associated_type(&sig);
257+
let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig);
258258

259259
for &parameter_type in &sig.inputs {
260260
let parameter_type_id =

src/librustc_trans/debuginfo/type_names.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
9494
output.push(']');
9595
},
9696
ty::TyTrait(ref trait_data) => {
97-
let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
97+
let principal = cx.tcx().erase_late_bound_regions_and_normalize(
98+
&trait_data.principal);
9899
push_item_name(cx, principal.def_id, false, output);
99100
push_type_params(cx, principal.substs, output);
100101
},
@@ -112,8 +113,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
112113

113114
output.push_str("fn(");
114115

115-
let sig = cx.tcx().erase_late_bound_regions(sig);
116-
let sig = cx.tcx().normalize_associated_type(&sig);
116+
let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig);
117117
if !sig.inputs.is_empty() {
118118
for &parameter_type in &sig.inputs {
119119
push_debuginfo_type_name(cx, parameter_type, true, output);

src/librustc_trans/declare.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
104104
fn_type: ty::Ty<'tcx>) -> ValueRef {
105105
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
106106
let abi = fn_type.fn_abi();
107-
let sig = ccx.tcx().erase_late_bound_regions(fn_type.fn_sig());
108-
let sig = ccx.tcx().normalize_associated_type(&sig);
107+
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(fn_type.fn_sig());
109108
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
110109

111110
let fty = FnType::new(ccx, abi, &sig, &[]);

src/librustc_trans/intrinsic.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
9999

100100
let _icx = push_ctxt("trans_intrinsic_call");
101101

102-
let (def_id, substs, sig) = match callee_ty.sty {
103-
ty::TyFnDef(def_id, substs, fty) => {
104-
let sig = tcx.erase_late_bound_regions(&fty.sig);
105-
(def_id, substs, tcx.normalize_associated_type(&sig))
106-
}
102+
let (def_id, substs, fty) = match callee_ty.sty {
103+
ty::TyFnDef(def_id, substs, ref fty) => (def_id, substs, fty),
107104
_ => bug!("expected fn item type, found {}", callee_ty)
108105
};
106+
107+
let sig = tcx.erase_late_bound_regions_and_normalize(&fty.sig);
109108
let arg_tys = sig.inputs;
110109
let ret_ty = sig.output;
111110
let name = tcx.item_name(def_id).as_str();
@@ -1108,8 +1107,7 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
11081107

11091108

11101109
let tcx = bcx.tcx();
1111-
let sig = tcx.erase_late_bound_regions(callee_ty.fn_sig());
1112-
let sig = tcx.normalize_associated_type(&sig);
1110+
let sig = tcx.erase_late_bound_regions_and_normalize(callee_ty.fn_sig());
11131111
let arg_tys = sig.inputs;
11141112

11151113
// every intrinsic takes a SIMD vector as its first argument

src/librustc_trans/meth.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
8080
_ => bug!()
8181
};
8282

83-
let sig = tcx.erase_late_bound_regions(sig);
84-
let sig = tcx.normalize_associated_type(&sig);
83+
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
8584
let fn_ty = FnType::new(ccx, abi, &sig, &[]);
8685

8786
let llfn = declare::define_internal_fn(ccx, &function_name, callee.ty);

src/librustc_trans/mir/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
419419
_ => bug!("{} is not callable", callee.ty)
420420
};
421421

422-
let sig = bcx.tcx().erase_late_bound_regions(sig);
422+
let sig = bcx.tcx().erase_late_bound_regions_and_normalize(sig);
423423

424424
// Handle intrinsics old trans wants Expr's for, ourselves.
425425
let intrinsic = match (&callee.ty.sty, &callee.data) {

src/librustc_trans/trans_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
473473

474474
output.push_str("fn(");
475475

476-
let sig = tcx.erase_late_bound_regions(sig);
476+
let sig = tcx.erase_late_bound_regions_and_normalize(sig);
477477
if !sig.inputs.is_empty() {
478478
for &parameter_type in &sig.inputs {
479479
push_unique_type_name(tcx, parameter_type, output);

src/librustc_trans/type_of.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
264264

265265
ty::TyFnDef(..) => Type::nil(cx),
266266
ty::TyFnPtr(f) => {
267-
let sig = cx.tcx().erase_late_bound_regions(&f.sig);
268-
let sig = cx.tcx().normalize_associated_type(&sig);
267+
let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig);
269268
FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to()
270269
}
271270
ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This tests for an ICE (and, if ignored, subsequent LLVM abort) when
12+
// a lifetime-parametric fn is passed into a context whose expected
13+
// type has a differing lifetime parameterization.
14+
15+
struct A<'a> {
16+
_a: &'a i32,
17+
}
18+
19+
fn call<T>(s: T, functions: &Vec<for <'n> fn(&'n T)>) {
20+
for function in functions {
21+
function(&s);
22+
}
23+
}
24+
25+
fn f(a: &A) { println!("a holds {}", a._a); }
26+
27+
fn main() {
28+
let a = A { _a: &10 };
29+
30+
let vec: Vec<for <'u,'v> fn(&'u A<'v>)> = vec![f];
31+
call(a, &vec);
32+
}

0 commit comments

Comments
 (0)