Skip to content

Commit 8f3f666

Browse files
committed
Forbid use of generics with foreign functions. Closes #10353.
1 parent c848906 commit 8f3f666

File tree

2 files changed

+125
-94
lines changed

2 files changed

+125
-94
lines changed

src/librustc/middle/typeck/collect.rs

+110-94
Original file line numberDiff line numberDiff line change
@@ -552,110 +552,126 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
552552
}
553553
}
554554

555+
fn ensure_generics_abi(ccx: &CrateCtxt,
556+
span: Span,
557+
abis: AbiSet,
558+
generics: &ast::Generics) {
559+
if generics.ty_params.len() > 0 &&
560+
!(abis.is_rust() || abis.is_intrinsic()) {
561+
ccx.tcx.sess.span_err(span,
562+
"foreign functions may not use type parameters");
563+
}
564+
}
565+
555566
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
556567
let tcx = ccx.tcx;
557568
debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
558569
match it.node {
559-
// These don't define types.
560-
ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
561-
ast::ItemEnum(ref enum_definition, ref generics) => {
562-
ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
563-
let tpt = ty_of_item(ccx, it);
564-
write_ty_to_tcx(tcx, it.id, tpt.ty);
565-
get_enum_variant_types(ccx,
566-
tpt.ty,
567-
enum_definition.variants,
568-
generics);
569-
}
570-
ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
571-
let i_ty_generics = ty_generics(ccx, generics, 0);
572-
let selfty = ccx.to_ty(&ExplicitRscope, selfty);
573-
write_ty_to_tcx(tcx, it.id, selfty);
570+
// These don't define types.
571+
ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
572+
ast::ItemEnum(ref enum_definition, ref generics) => {
573+
ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
574+
let tpt = ty_of_item(ccx, it);
575+
write_ty_to_tcx(tcx, it.id, tpt.ty);
576+
get_enum_variant_types(ccx,
577+
tpt.ty,
578+
enum_definition.variants,
579+
generics);
580+
},
581+
ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
582+
let i_ty_generics = ty_generics(ccx, generics, 0);
583+
let selfty = ccx.to_ty(&ExplicitRscope, selfty);
584+
write_ty_to_tcx(tcx, it.id, selfty);
574585

575-
{
576-
let mut tcache = tcx.tcache.borrow_mut();
577-
tcache.get().insert(local_def(it.id),
578-
ty_param_bounds_and_ty {
579-
generics: i_ty_generics.clone(),
580-
ty: selfty});
581-
}
586+
{
587+
let mut tcache = tcx.tcache.borrow_mut();
588+
tcache.get().insert(local_def(it.id),
589+
ty_param_bounds_and_ty {
590+
generics: i_ty_generics.clone(),
591+
ty: selfty});
592+
}
582593

583-
// If there is a trait reference, treat the methods as always public.
584-
// This is to work around some incorrect behavior in privacy checking:
585-
// when the method belongs to a trait, it should acquire the privacy
586-
// from the trait, not the impl. Forcing the visibility to be public
587-
// makes things sorta work.
588-
let parent_visibility = if opt_trait_ref.is_some() {
589-
ast::Public
590-
} else {
591-
it.vis
592-
};
594+
// If there is a trait reference, treat the methods as always public.
595+
// This is to work around some incorrect behavior in privacy checking:
596+
// when the method belongs to a trait, it should acquire the privacy
597+
// from the trait, not the impl. Forcing the visibility to be public
598+
// makes things sorta work.
599+
let parent_visibility = if opt_trait_ref.is_some() {
600+
ast::Public
601+
} else {
602+
it.vis
603+
};
593604

594-
convert_methods(ccx,
595-
ImplContainer(local_def(it.id)),
596-
*ms,
597-
selfty,
598-
&i_ty_generics,
599-
generics,
600-
parent_visibility);
601-
602-
for trait_ref in opt_trait_ref.iter() {
603-
let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
604-
605-
// Prevent the builtin kind traits from being manually implemented.
606-
if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
607-
tcx.sess.span_err(it.span,
608-
"cannot provide an explicit implementation \
609-
for a builtin kind");
605+
convert_methods(ccx,
606+
ImplContainer(local_def(it.id)),
607+
*ms,
608+
selfty,
609+
&i_ty_generics,
610+
generics,
611+
parent_visibility);
612+
613+
for trait_ref in opt_trait_ref.iter() {
614+
let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
615+
616+
// Prevent the builtin kind traits from being manually implemented.
617+
if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
618+
tcx.sess.span_err(it.span,
619+
"cannot provide an explicit implementation \
620+
for a builtin kind");
621+
}
610622
}
611-
}
612-
}
613-
ast::ItemTrait(ref generics, _, ref trait_methods) => {
614-
let trait_def = trait_def_of_item(ccx, it);
615-
616-
// Run convert_methods on the provided methods.
617-
let (_, provided_methods) =
618-
split_trait_methods(*trait_methods);
619-
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
620-
convert_methods(ccx,
621-
TraitContainer(local_def(it.id)),
622-
provided_methods,
623-
untransformed_rcvr_ty,
624-
&trait_def.generics,
625-
generics,
626-
it.vis);
627-
628-
// We need to do this *after* converting methods, since
629-
// convert_methods produces a tcache entry that is wrong for
630-
// static trait methods. This is somewhat unfortunate.
631-
ensure_trait_methods(ccx, it.id);
632-
}
633-
ast::ItemStruct(struct_def, ref generics) => {
634-
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
635-
636-
// Write the class type
637-
let tpt = ty_of_item(ccx, it);
638-
write_ty_to_tcx(tcx, it.id, tpt.ty);
623+
},
624+
ast::ItemTrait(ref generics, _, ref trait_methods) => {
625+
let trait_def = trait_def_of_item(ccx, it);
626+
627+
// Run convert_methods on the provided methods.
628+
let (_, provided_methods) =
629+
split_trait_methods(*trait_methods);
630+
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
631+
convert_methods(ccx,
632+
TraitContainer(local_def(it.id)),
633+
provided_methods,
634+
untransformed_rcvr_ty,
635+
&trait_def.generics,
636+
generics,
637+
it.vis);
638+
639+
// We need to do this *after* converting methods, since
640+
// convert_methods produces a tcache entry that is wrong for
641+
// static trait methods. This is somewhat unfortunate.
642+
ensure_trait_methods(ccx, it.id);
643+
},
644+
ast::ItemStruct(struct_def, ref generics) => {
645+
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
646+
647+
// Write the class type
648+
let tpt = ty_of_item(ccx, it);
649+
write_ty_to_tcx(tcx, it.id, tpt.ty);
639650

640-
{
641-
let mut tcache = tcx.tcache.borrow_mut();
642-
tcache.get().insert(local_def(it.id), tpt.clone());
643-
}
651+
{
652+
let mut tcache = tcx.tcache.borrow_mut();
653+
tcache.get().insert(local_def(it.id), tpt.clone());
654+
}
644655

645-
convert_struct(ccx, struct_def, tpt, it.id);
646-
}
647-
ast::ItemTy(_, ref generics) => {
648-
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
649-
let tpt = ty_of_item(ccx, it);
650-
write_ty_to_tcx(tcx, it.id, tpt.ty);
651-
}
652-
_ => {
653-
// This call populates the type cache with the converted type
654-
// of the item in passing. All we have to do here is to write
655-
// it into the node type table.
656-
let tpt = ty_of_item(ccx, it);
657-
write_ty_to_tcx(tcx, it.id, tpt.ty);
658-
}
656+
convert_struct(ccx, struct_def, tpt, it.id);
657+
},
658+
ast::ItemTy(_, ref generics) => {
659+
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
660+
let tpt = ty_of_item(ccx, it);
661+
write_ty_to_tcx(tcx, it.id, tpt.ty);
662+
},
663+
ast::ItemFn(_, _, abi, ref generics, _) => {
664+
ensure_generics_abi(ccx, it.span, abi, generics);
665+
let tpt = ty_of_item(ccx, it);
666+
write_ty_to_tcx(tcx, it.id, tpt.ty);
667+
},
668+
_ => {
669+
// This call populates the type cache with the converted type
670+
// of the item in passing. All we have to do here is to write
671+
// it into the node type table.
672+
let tpt = ty_of_item(ccx, it);
673+
write_ty_to_tcx(tcx, it.id, tpt.ty);
674+
},
659675
}
660676
}
661677

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2014 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+
extern "C" fn foo<T>() {} //~ERROR foreign functions may not use type parameters
12+
13+
fn main() {
14+
let _ = foo::<int>;
15+
}

0 commit comments

Comments
 (0)