Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't drag function signatures along function item types. #42417

Merged
merged 4 commits into from
Jun 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,10 +524,9 @@ for ty::TypeVariants<'tcx>
region.hash_stable(hcx, hasher);
pointee_ty.hash_stable(hcx, hasher);
}
TyFnDef(def_id, substs, ref sig) => {
TyFnDef(def_id, substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
sig.hash_stable(hcx, hasher);
}
TyFnPtr(ref sig) => {
sig.hash_stable(hcx, hasher);
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
Some(self.tcx.closure_kind(def_id))
}

pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
/// Obtain the signature of a function or closure.
/// For closures, unlike `tcx.fn_sig(def_id)`, this method will
/// work during the type-checking of the enclosing function and
/// return the closure signature in its partially inferred state.
pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
if let Some(tables) = self.in_progress_tables {
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
Expand All @@ -1378,7 +1382,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}

self.tcx.closure_type(def_id)
self.tcx.fn_sig(def_id)
}
}

Expand Down
28 changes: 13 additions & 15 deletions src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//! `unsafe`.
use self::RootUnsafeContext::*;

use ty::{self, Ty, TyCtxt};
use ty::{self, TyCtxt};
use lint;

use syntax::ast;
Expand Down Expand Up @@ -40,14 +40,6 @@ enum RootUnsafeContext {
UnsafeBlock(ast::NodeId),
}

fn type_is_unsafe_function(ty: Ty) -> bool {
match ty.sty {
ty::TyFnDef(.., f) |
ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe,
_ => false,
}
}

struct EffectCheckVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
Expand Down Expand Up @@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
match expr.node {
hir::ExprMethodCall(..) => {
let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
let base_type = self.tcx.type_of(def_id);
debug!("effect: method call case, base type is {:?}",
base_type);
if type_is_unsafe_function(base_type) {
let sig = self.tcx.fn_sig(def_id);
debug!("effect: method call case, signature is {:?}",
sig);

if sig.0.unsafety == hir::Unsafety::Unsafe {
self.require_unsafe(expr.span,
"invocation of unsafe method")
}
Expand All @@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
let base_type = self.tables.expr_ty_adjusted(base);
debug!("effect: call case, base type is {:?}",
base_type);
if type_is_unsafe_function(base_type) {
self.require_unsafe(expr.span, "call to unsafe function")
match base_type.sty {
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
self.require_unsafe(expr.span, "call to unsafe function")
}
}
_ => {}
}
}
hir::ExprUnary(hir::UnDeref, ref base) => {
Expand Down
27 changes: 8 additions & 19 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
let intrinsic = match self.tcx.type_of(def_id).sty {
ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic,
_ => return false
};
intrinsic && self.tcx.item_name(def_id) == "transmute"
self.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
self.tcx.item_name(def_id) == "transmute"
}

fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
Expand Down Expand Up @@ -153,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
} else {
Def::Err
};
match def {
Def::Fn(did) if self.def_id_is_transmute(did) => {
if let Def::Fn(did) = def {
if self.def_id_is_transmute(did) {
let typ = self.tables.node_id_to_type(expr.id);
let typ = self.tcx.lift_to_global(&typ).unwrap();
match typ.sty {
ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => {
let from = sig.inputs().skip_binder()[0];
let to = *sig.output().skip_binder();
self.check_transmute(expr.span, from, to);
}
_ => {
span_bug!(expr.span, "transmute wasn't a bare fn?!");
}
}
let sig = typ.fn_sig(self.tcx);
let from = sig.inputs().skip_binder()[0];
let to = *sig.output().skip_binder();
self.check_transmute(expr.span, from, to);
}
_ => {}
}

intravisit::walk_expr(self, expr);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

// The `Self` type is erased, so it should not appear in list of
// arguments or return type apart from the receiver.
let ref sig = self.type_of(method.def_id).fn_sig();
let ref sig = self.fn_sig(method.def_id);
for input_ty in &sig.skip_binder().inputs()[1..] {
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf);
Expand Down
14 changes: 12 additions & 2 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
-> Progress<'tcx>
{
let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
let sig = fn_type.fn_sig();
let sig = fn_type.fn_sig(selcx.tcx());
let Normalized {
value: sig,
obligations
} = normalize_with_depth(selcx,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth+1,
&sig);

confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
.with_addl_obligations(fn_pointer_vtable.nested)
.with_addl_obligations(obligations)
}

fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
Expand All @@ -1149,7 +1159,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
-> Progress<'tcx>
{
let closure_typer = selcx.closure_typer();
let closure_type = closure_typer.closure_type(vtable.closure_def_id)
let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
.subst(selcx.tcx(), vtable.substs.substs);
let Normalized {
value: closure_type,
Expand Down
35 changes: 19 additions & 16 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1404,19 +1404,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}

// provide an impl, but only for suitable `fn` pointers
ty::TyFnDef(.., ty::Binder(ty::FnSig {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
variadic: false,
..
})) |
ty::TyFnPtr(ty::Binder(ty::FnSig {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
variadic: false,
..
})) => {
candidates.vec.push(FnPointerCandidate);
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
if let ty::Binder(ty::FnSig {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
variadic: false,
..
}) = self_ty.fn_sig(self.tcx()) {
candidates.vec.push(FnPointerCandidate);
}
}

_ => { }
Expand Down Expand Up @@ -2348,19 +2344,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

// ok to skip binder; it is reintroduced below
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let sig = self_ty.fn_sig();
let sig = self_ty.fn_sig(self.tcx());
let trait_ref =
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
self_ty,
sig,
util::TupleArgumentsFlag::Yes)
.map_bound(|(trait_ref, _)| trait_ref);

let Normalized { value: trait_ref, obligations } =
project::normalize_with_depth(self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
&trait_ref);

self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref)?;
Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
}

fn confirm_closure_candidate(&mut self,
Expand Down Expand Up @@ -2799,7 +2802,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
substs: ty::ClosureSubsts<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
let closure_type = self.infcx.closure_type(closure_def_id)
let closure_type = self.infcx.fn_sig(closure_def_id)
.subst(self.tcx(), substs.substs);
let ty::Binder((trait_ref, _)) =
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

pub fn mk_fn_def(self, def_id: DefId,
substs: &'tcx Substs<'tcx>,
fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyFnDef(def_id, substs, fty))
substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyFnDef(def_id, substs))
}

pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/ty/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// view of possibly unifying
simplify_type(tcx, mt.ty, can_simplify_params)
}
ty::TyFnDef(def_id, _) |
ty::TyClosure(def_id, _) => {
Some(ClosureSimplifiedType(def_id))
}
ty::TyNever => Some(NeverSimplifiedType),
ty::TyTuple(ref tys, _) => {
Some(TupleSimplifiedType(tys.len()))
}
ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
ty::TyFnPtr(ref f) => {
Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
}
ty::TyProjection(_) | ty::TyParam(_) => {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,8 @@ impl FlagComputation {
self.add_tys(&ts[..]);
}

&ty::TyFnDef(_, substs, f) => {
&ty::TyFnDef(_, substs) => {
self.add_substs(substs);
self.add_fn_sig(f);
}

&ty::TyFnPtr(f) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
.filter_map(|ty| characteristic_def_id_of_type(ty))
.next(),

ty::TyFnDef(def_id, ..) |
ty::TyFnDef(def_id, _) |
ty::TyClosure(def_id, _) => Some(def_id),

ty::TyBool |
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,13 +875,12 @@ define_maps! { <'tcx>
/// for trans. This is also the only query that can fetch non-local MIR, at present.
[] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,

/// Records the type of each closure. The def ID is the ID of the
/// Type of each closure. The def ID is the ID of the
/// expression defining the closure.
[] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,

/// Records the type of each closure. The def ID is the ID of the
/// expression defining the closure.
[] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
/// The signature of functions and closures.
[] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,

/// Caches CoerceUnsized kinds for impls on custom types.
[] coerce_unsized_info: ItemSignature(DefId)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl AssociatedItem {
// late-bound regions, and we don't want method signatures to show up
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
// regions just fine, showing `fn(&MyType)`.
format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder())
format!("{}", tcx.fn_sig(self.def_id).skip_binder())
}
ty::AssociatedKind::Type => format!("type {};", self.name.to_string()),
ty::AssociatedKind::Const => {
Expand Down
12 changes: 5 additions & 7 deletions src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
}
}
Expand All @@ -308,7 +308,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
}
}
Expand Down Expand Up @@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
}
}

(&ty::TyFnDef(a_def_id, a_substs, a_fty),
&ty::TyFnDef(b_def_id, b_substs, b_fty))
(&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
let substs = relate_substs(relation, None, a_substs, b_substs)?;
let fty = relation.relate(&a_fty, &b_fty)?;
Ok(tcx.mk_fn_def(a_def_id, substs, fty))
let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
Ok(tcx.mk_fn_def(a_def_id, substs))
}

(&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
Expand Down
10 changes: 3 additions & 7 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,10 +531,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyDynamic(ref trait_ty, ref region) =>
ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
ty::TyFnDef(def_id, substs, f) => {
ty::TyFnDef(def_id,
substs.fold_with(folder),
f.fold_with(folder))
ty::TyFnDef(def_id, substs) => {
ty::TyFnDef(def_id, substs.fold_with(folder))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay that signatures are not folded anymore? (Is it possible to fold something kept in the tables at all?)
It would be really nice if they were at least still visited by default.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole point (which I'll try to describe once I'm sure there's no fatal flaw with the approach) is to reduce the amount of work done for these types. Anything that relied on seeing the signature has to visit it manually. It's not a property of the type and it was never meant to be, it's just one way to use values of that type (i.e. calling them).

}
ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)),
ty::TyRef(ref r, tm) => {
Expand Down Expand Up @@ -568,9 +566,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyDynamic(ref trait_ty, ref reg) =>
trait_ty.visit_with(visitor) || reg.visit_with(visitor),
ty::TyTuple(ts, _) => ts.visit_with(visitor),
ty::TyFnDef(_, substs, ref f) => {
substs.visit_with(visitor) || f.visit_with(visitor)
}
ty::TyFnDef(_, substs) => substs.visit_with(visitor),
ty::TyFnPtr(ref f) => f.visit_with(visitor),
ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
Expand Down
Loading