Skip to content

Commit

Permalink
Consistently normalize fn types after erasing lifetimes.
Browse files Browse the repository at this point in the history
Fixes #23406.
Fixes #23958.
Fixes #29832.
  • Loading branch information
eefriedman committed Nov 14, 2015
1 parent 4f5edf9 commit 82ab707
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/librustc_trans/trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
};

let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);

let mut attrs = llvm::AttrBuilder::new();
let ret_ty = fn_sig.output;
Expand Down
34 changes: 13 additions & 21 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use metadata::{csearch, encoder, loader};
use middle::astencode;
use middle::cfg;
use middle::def_id::DefId;
use middle::infer;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::weak_lang_items;
use middle::pat_util::simple_name;
Expand Down Expand Up @@ -1905,7 +1906,11 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
debug!("trans_fn(param_substs={:?})", param_substs);
let _icx = push_ctxt("trans_fn");
let fn_ty = ccx.tcx().node_id_to_type(id);
let output_type = ccx.tcx().erase_late_bound_regions(&fn_ty.fn_ret());
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty);
let sig = fn_ty.fn_sig();
let sig = ccx.tcx().erase_late_bound_regions(&sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let output_type = sig.output;
let abi = fn_ty.fn_abi();
trans_closure(ccx, decl, body, llfndecl, param_substs, id, attrs, output_type, abi,
closure::ClosureEnv::NotClosure);
Expand Down Expand Up @@ -1936,15 +1941,9 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,

let ccx = bcx.fcx.ccx;

let result_ty = match ctor_ty.sty {
ty::TyBareFn(_, ref bft) => {
bcx.tcx().erase_late_bound_regions(&bft.sig.output()).unwrap()
}
_ => ccx.sess().bug(
&format!("trans_enum_variant_constructor: \
unexpected ctor return type {}",
ctor_ty))
};
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let result_ty = sig.output.unwrap();

// Get location to store the result. If the user does not care about
// the result, just make a stack slot
Expand Down Expand Up @@ -2026,15 +2025,10 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);

let result_ty = match ctor_ty.sty {
ty::TyBareFn(_, ref bft) => {
ccx.tcx().erase_late_bound_regions(&bft.sig.output())
}
_ => ccx.sess().bug(
&format!("trans_enum_variant_or_tuple_like_struct: \
unexpected ctor return type {}",
ctor_ty))
};
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let arg_tys = sig.inputs;
let result_ty = sig.output;

let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
Expand All @@ -2044,8 +2038,6 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx

assert!(!fcx.needs_ret_allocas);

let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());

if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
let repr = adt::represent_type(ccx, result_ty.unwrap());
Expand Down
25 changes: 17 additions & 8 deletions src/librustc_trans/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use llvm::{self, ValueRef, get_params};
use metadata::cstore::LOCAL_CRATE;
use middle::def;
use middle::def_id::DefId;
use middle::infer::normalize_associated_type;
use middle::infer;
use middle::subst;
use middle::subst::{Substs};
use rustc::front::map as hir_map;
Expand Down Expand Up @@ -304,6 +304,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
}
};
let sig = tcx.erase_late_bound_regions(sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
let tuple_fn_ty = tcx.mk_fn(opt_def_id,
tcx.mk_bare_fn(ty::BareFnTy {
Expand Down Expand Up @@ -466,7 +467,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(

// Type scheme of the function item (may have type params)
let fn_type_scheme = tcx.lookup_item_type(def_id);
let fn_type = normalize_associated_type(tcx, &fn_type_scheme.ty);
let fn_type = infer::normalize_associated_type(tcx, &fn_type_scheme.ty);

// Find the actual function pointer.
let mut val = {
Expand Down Expand Up @@ -605,8 +606,9 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,

let (abi, ret_ty) = match callee.ty.sty {
ty::TyBareFn(_, ref f) => {
let output = bcx.tcx().erase_late_bound_regions(&f.sig.output());
(f.abi, output)
let sig = bcx.tcx().erase_late_bound_regions(&f.sig);
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
(f.abi, sig.output)
}
_ => panic!("expected bare rust fn or closure in trans_call_inner")
};
Expand Down Expand Up @@ -826,7 +828,9 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
ignore_self: bool)
-> Block<'blk, 'tcx>
{
let args = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
let args = sig.inputs;

// Translate the `self` argument first.
if !ignore_self {
Expand Down Expand Up @@ -887,7 +891,10 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
ignore_self: bool)
-> Block<'blk, 'tcx> {
// Translate the `self` argument first.
let arg_tys = bcx.tcx().erase_late_bound_regions( &fn_ty.fn_args());
let sig = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
let arg_tys = sig.inputs;

if !ignore_self {
let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
bcx = trans_arg_datum(bcx,
Expand Down Expand Up @@ -933,8 +940,10 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
debug!("trans_args(abi={})", abi);

let _icx = push_ctxt("trans_args");
let arg_tys = cx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
let variadic = fn_ty.fn_sig().0.variadic;
let sig = cx.tcx().erase_late_bound_regions(&fn_ty.fn_sig());
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
let arg_tys = sig.inputs;
let variadic = sig.variadic;

let mut bcx = cx;

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_trans/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
tcx.with_freevars(id, |fv| fv.iter().cloned().collect());

let sig = tcx.erase_late_bound_regions(&function_type.sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);

trans_closure(ccx,
decl,
Expand Down Expand Up @@ -371,6 +372,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
let lloncefn = declare::define_internal_rust_fn(ccx, &function_name,
llonce_fn_ty);
let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);

let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = new_fn_ctxt(ccx,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_trans/trans/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use llvm::{self, ValueRef};
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};

use middle::def_id::DefId;
use middle::infer;
use middle::pat_util;
use middle::subst::{self, Substs};
use rustc::front::map as hir_map;
Expand Down Expand Up @@ -262,6 +263,7 @@ impl<'tcx> TypeMap<'tcx> {
unique_type_id.push_str(" fn(");

let sig = cx.tcx().erase_late_bound_regions(sig);
let sig = infer::normalize_associated_type(cx.tcx(), &sig);

for &parameter_type in &sig.inputs {
let parameter_type_id =
Expand Down
11 changes: 8 additions & 3 deletions src/librustc_trans/trans/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use rustc_front::hir;
use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
use trans;
use trans::{monomorphize, type_of};
use middle::infer;
use middle::ty::{self, Ty};
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
Expand Down Expand Up @@ -418,19 +419,23 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// Return type -- llvm::DIBuilder wants this at index 0
assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
let fn_type = cx.tcx().node_id_to_type(fn_ast_id);
let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type);

let (sig, abi) = match fn_type.sty {
ty::TyBareFn(_, ref barefnty) => {
(cx.tcx().erase_late_bound_regions(&barefnty.sig), barefnty.abi)
let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig);
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
(sig, barefnty.abi)
}
ty::TyClosure(def_id, ref substs) => {
let closure_type = cx.tcx().closure_type(def_id, substs);
(cx.tcx().erase_late_bound_regions(&closure_type.sig), closure_type.abi)
let sig = cx.tcx().erase_late_bound_regions(&closure_type.sig);
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
(sig, closure_type.abi)
}

_ => cx.sess().bug("get_function_metdata: Expected a function type!")
};
let sig = monomorphize::apply_param_substs(cx.tcx(), param_substs, &sig);

let mut signature = Vec::with_capacity(sig.inputs.len() + 1);

Expand Down
2 changes: 2 additions & 0 deletions src/librustc_trans/trans/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use super::namespace::crate_root_namespace;

use trans::common::CrateContext;
use middle::def_id::DefId;
use middle::infer;
use middle::subst::{self, Substs};
use middle::ty::{self, Ty};

Expand Down Expand Up @@ -124,6 +125,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
output.push_str("fn(");

let sig = cx.tcx().erase_late_bound_regions(sig);
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
if !sig.inputs.is_empty() {
for &parameter_type in &sig.inputs {
push_debuginfo_type_name(cx, parameter_type, true, output);
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_trans/trans/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name,
fn_type);
let fn_type = infer::normalize_associated_type(ccx.tcx(), &fn_type);
debug!("declare_rust_fn (after normalised associated types) fn_type={:?}",
fn_type);

let function_type; // placeholder so that the memory ownership works out ok
let (sig, abi, env) = match fn_type.sty {
Expand All @@ -124,14 +121,15 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
_ => ccx.sess().bug("expected closure or fn")
};

let sig = ty::Binder(ccx.tcx().erase_late_bound_regions(sig));
let sig = ccx.tcx().erase_late_bound_regions(sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi);
debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty));

// it is ok to directly access sig.0.output because we erased all
// late-bound-regions above
let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output);
let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.output);
attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn);
llfn
}
Expand Down
21 changes: 8 additions & 13 deletions src/librustc_trans/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use intrinsics::{self, Intrinsic};
use libc;
use llvm;
use llvm::{SequentiallyConsistent, Acquire, Release, AtomicXchg, ValueRef, TypeKind};
use middle::infer;
use middle::subst;
use middle::subst::FnSpace;
use trans::adt;
Expand Down Expand Up @@ -170,13 +171,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,

let _icx = push_ctxt("trans_intrinsic_call");

let (arg_tys, ret_ty) = match callee_ty.sty {
ty::TyBareFn(_, ref f) => {
(bcx.tcx().erase_late_bound_regions(&f.sig.inputs()),
bcx.tcx().erase_late_bound_regions(&f.sig.output()))
}
_ => panic!("expected bare_fn in trans_intrinsic_call")
};
let sig = ccx.tcx().erase_late_bound_regions(callee_ty.fn_sig());
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
let arg_tys = sig.inputs;
let ret_ty = sig.output;
let foreign_item = tcx.map.expect_foreign_item(node);
let name = foreign_item.name.as_str();

Expand Down Expand Up @@ -1330,12 +1328,9 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>


let tcx = bcx.tcx();
let arg_tys = match callee_ty.sty {
ty::TyBareFn(_, ref f) => {
bcx.tcx().erase_late_bound_regions(&f.sig.inputs())
}
_ => unreachable!()
};
let sig = tcx.erase_late_bound_regions(callee_ty.fn_sig());
let sig = infer::normalize_associated_type(tcx, &sig);
let arg_tys = sig.inputs;

// every intrinsic takes a SIMD vector as its first argument
require_simd!(arg_tys[0], "input");
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_trans/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use arena::TypedArena;
use back::link;
use llvm::{ValueRef, get_params};
use middle::def_id::DefId;
use middle::infer;
use middle::subst::{Subst, Substs};
use middle::subst::VecPerParamSpace;
use middle::subst;
Expand Down Expand Up @@ -522,6 +523,7 @@ fn trans_object_shim<'a, 'tcx>(
let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty);

let sig = ccx.tcx().erase_late_bound_regions(&fty.sig);
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);

let empty_substs = tcx.mk_substs(Substs::trans_empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
Expand Down
16 changes: 10 additions & 6 deletions src/librustc_trans/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![allow(non_camel_case_types)]

use middle::def_id::DefId;
use middle::infer;
use middle::subst;
use trans::adt;
use trans::common::*;
Expand Down Expand Up @@ -89,24 +90,25 @@ pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
llenvironment_type: Option<Type>,
sig: &ty::Binder<ty::FnSig<'tcx>>,
sig: &ty::FnSig<'tcx>,
abi: abi::Abi)
-> Type
{
debug!("type_of_rust_fn(sig={:?},abi={:?})",
sig,
abi);

let sig = cx.tcx().erase_late_bound_regions(sig);
assert!(!sig.variadic); // rust fns are never variadic

let mut atys: Vec<Type> = Vec::new();

// First, munge the inputs, if this has the `rust-call` ABI.
let inputs = &if abi == abi::RustCall {
untuple_arguments(cx, &sig.inputs)
let inputs_temp;
let inputs = if abi == abi::RustCall {
inputs_temp = untuple_arguments(cx, &sig.inputs);
&inputs_temp
} else {
sig.inputs
&sig.inputs
};

// Arg 0: Output pointer.
Expand Down Expand Up @@ -155,7 +157,9 @@ pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>)
// FIXME(#19925) once fn item types are
// zero-sized, we'll need to do something here
if f.abi == abi::Rust || f.abi == abi::RustCall {
type_of_rust_fn(cx, None, &f.sig, f.abi)
let sig = cx.tcx().erase_late_bound_regions(&f.sig);
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
type_of_rust_fn(cx, None, &sig, f.abi)
} else {
foreign::lltype_for_foreign_fn(cx, fty)
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/run-pass/issue-23406.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2015 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.

trait Inner {
type T;
}

impl<'a> Inner for &'a i32 {
type T = i32;
}

fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T {
*x
}

fn main() {}
Loading

0 comments on commit 82ab707

Please sign in to comment.