Skip to content

Commit ad8e236

Browse files
committed
auto merge of #6336 : nikomatsakis/rust/issue-6308-closure-bounds, r=nikomatsakis
Use a bitset to represent built-in bounds. There are several places in the language where only builtin bounds (aka kinds) will be accepted, e.g. on closures, destructor type parameters perhaps, and on trait types. r? @brson
2 parents f547a67 + 7852086 commit ad8e236

File tree

14 files changed

+515
-213
lines changed

14 files changed

+515
-213
lines changed

src/librustc/metadata/tydecode.rs

+28-12
Original file line numberDiff line numberDiff line change
@@ -555,18 +555,34 @@ fn parse_type_param_def(st: @mut PState, conv: conv_did) -> ty::TypeParameterDef
555555
bounds: parse_bounds(st, conv)}
556556
}
557557
558-
fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] {
559-
let mut bounds = ~[];
558+
fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
559+
let mut param_bounds = ty::ParamBounds {
560+
builtin_bounds: ty::EmptyBuiltinBounds(),
561+
trait_bounds: ~[]
562+
};
560563
loop {
561-
bounds.push(match next(st) {
562-
'S' => ty::bound_owned,
563-
'C' => ty::bound_copy,
564-
'K' => ty::bound_const,
565-
'O' => ty::bound_durable,
566-
'I' => ty::bound_trait(@parse_trait_ref(st, conv)),
567-
'.' => break,
568-
_ => fail!(~"parse_bounds: bad bounds")
569-
});
564+
match next(st) {
565+
'S' => {
566+
param_bounds.builtin_bounds.add(ty::BoundOwned);
567+
}
568+
'C' => {
569+
param_bounds.builtin_bounds.add(ty::BoundCopy);
570+
}
571+
'K' => {
572+
param_bounds.builtin_bounds.add(ty::BoundConst);
573+
}
574+
'O' => {
575+
param_bounds.builtin_bounds.add(ty::BoundStatic);
576+
}
577+
'I' => {
578+
param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
579+
}
580+
'.' => {
581+
return @param_bounds;
582+
}
583+
_ => {
584+
fail!(~"parse_bounds: bad bounds")
585+
}
586+
}
570587
}
571-
@bounds
572588
}

src/librustc/metadata/tyencode.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -396,19 +396,21 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
396396
enc_ty(w, cx, fsig.output);
397397
}
398398

399-
fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
400-
for (*bs).each |bound| {
401-
match *bound {
402-
ty::bound_owned => w.write_char('S'),
403-
ty::bound_copy => w.write_char('C'),
404-
ty::bound_const => w.write_char('K'),
405-
ty::bound_durable => w.write_char('O'),
406-
ty::bound_trait(tp) => {
407-
w.write_char('I');
408-
enc_trait_ref(w, cx, tp);
409-
}
399+
fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @ty::ParamBounds) {
400+
for bs.builtin_bounds.each |bound| {
401+
match bound {
402+
ty::BoundOwned => w.write_char('S'),
403+
ty::BoundCopy => w.write_char('C'),
404+
ty::BoundConst => w.write_char('K'),
405+
ty::BoundStatic => w.write_char('O'),
410406
}
411407
}
408+
409+
for bs.trait_bounds.each |&tp| {
410+
w.write_char('I');
411+
enc_trait_ref(w, cx, tp);
412+
}
413+
412414
w.write_char('.');
413415
}
414416

src/librustc/middle/kind.rs

+7-33
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use middle::pat_util;
1414
use middle::ty;
1515
use middle::typeck;
1616
use util::ppaux::{Repr, ty_to_str};
17+
use util::ppaux::UserString;
1718

1819
use syntax::ast::*;
1920
use syntax::attr::attrs_contains_name;
@@ -338,46 +339,19 @@ pub fn check_bounds(cx: Context,
338339
type_param_def: &ty::TypeParameterDef)
339340
{
340341
let kind = ty::type_contents(cx.tcx, ty);
341-
let mut missing = ~[];
342-
for type_param_def.bounds.each |bound| {
343-
match *bound {
344-
ty::bound_trait(_) => {
345-
/* Not our job, checking in typeck */
346-
}
347-
348-
ty::bound_copy => {
349-
if !kind.is_copy(cx.tcx) {
350-
missing.push("Copy");
351-
}
352-
}
353-
354-
ty::bound_durable => {
355-
if !kind.is_durable(cx.tcx) {
356-
missing.push("'static");
357-
}
358-
}
359-
360-
ty::bound_owned => {
361-
if !kind.is_owned(cx.tcx) {
362-
missing.push("Owned");
363-
}
364-
}
365-
366-
ty::bound_const => {
367-
if !kind.is_const(cx.tcx) {
368-
missing.push("Const");
369-
}
370-
}
342+
let mut missing = ty::EmptyBuiltinBounds();
343+
for type_param_def.bounds.builtin_bounds.each |bound| {
344+
if !kind.meets_bound(cx.tcx, bound) {
345+
missing.add(bound);
371346
}
372347
}
373-
374348
if !missing.is_empty() {
375349
cx.tcx.sess.span_err(
376350
sp,
377351
fmt!("instantiating a type parameter with an incompatible type \
378352
`%s`, which does not fulfill `%s`",
379353
ty_to_str(cx.tcx, ty),
380-
str::connect_slices(missing, " ")));
354+
missing.user_string(cx.tcx)));
381355
}
382356
}
383357

@@ -440,7 +414,7 @@ pub fn check_owned(cx: Context, ty: ty::t, sp: span) -> bool {
440414

441415
// note: also used from middle::typeck::regionck!
442416
pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool {
443-
if !ty::type_is_durable(tcx, ty) {
417+
if !ty::type_is_static(tcx, ty) {
444418
match ty::get(ty).sty {
445419
ty::ty_param(*) => {
446420
tcx.sess.span_err(sp, "value may contain borrowed \

src/librustc/middle/subst.rs

+10-16
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,11 @@ impl<T:Subst> Subst for ~[T] {
7878
}
7979
}
8080

81-
impl<T:Subst> Subst for @~[T] {
82-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @~[T] {
83-
@(**self).subst(tcx, substs)
81+
impl<T:Subst> Subst for @T {
82+
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @T {
83+
match self {
84+
&@ref t => @t.subst(tcx, substs)
85+
}
8486
}
8587
}
8688

@@ -115,19 +117,11 @@ impl Subst for ty::BareFnTy {
115117
}
116118
}
117119

118-
impl Subst for ty::param_bound {
119-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::param_bound {
120-
match self {
121-
&ty::bound_copy |
122-
&ty::bound_durable |
123-
&ty::bound_owned |
124-
&ty::bound_const => {
125-
*self
126-
}
127-
128-
&ty::bound_trait(tref) => {
129-
ty::bound_trait(@tref.subst(tcx, substs))
130-
}
120+
impl Subst for ty::ParamBounds {
121+
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ParamBounds {
122+
ty::ParamBounds {
123+
builtin_bounds: self.builtin_bounds,
124+
trait_bounds: self.trait_bounds.subst(tcx, substs)
131125
}
132126
}
133127
}

src/librustc/middle/trans/monomorphize.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -348,14 +348,9 @@ pub fn make_mono_id(ccx: @CrateContext,
348348
let mut i = 0;
349349
vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
350350
let mut v = ~[];
351-
for type_param_def.bounds.each |bound| {
352-
match *bound {
353-
ty::bound_trait(_) => {
354-
v.push(meth::vtable_id(ccx, /*bad*/copy vts[i]));
355-
i += 1;
356-
}
357-
_ => ()
358-
}
351+
for type_param_def.bounds.trait_bounds.each |_bound| {
352+
v.push(meth::vtable_id(ccx, /*bad*/copy vts[i]));
353+
i += 1;
359354
}
360355
(*subst, if !v.is_empty() { Some(v) } else { None })
361356
})

src/librustc/middle/ty.rs

+61-46
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use util::ppaux::{note_and_explain_region, bound_region_to_str};
2626
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
2727
use util::ppaux::Repr;
2828
use util::common::{indenter};
29+
use util::enum_set::{EnumSet, CLike};
2930

3031
use core;
3132
use core::ptr::to_unsafe_ptr;
@@ -58,8 +59,6 @@ pub struct field {
5859
mt: mt
5960
}
6061

61-
pub type param_bounds = @~[param_bound];
62-
6362
pub struct method {
6463
ident: ast::ident,
6564
generics: ty::Generics,
@@ -655,12 +654,32 @@ pub enum type_err {
655654
}
656655

657656
#[deriving(Eq, IterBytes)]
658-
pub enum param_bound {
659-
bound_copy,
660-
bound_durable,
661-
bound_owned,
662-
bound_const,
663-
bound_trait(@TraitRef),
657+
pub struct ParamBounds {
658+
builtin_bounds: BuiltinBounds,
659+
trait_bounds: ~[@TraitRef]
660+
}
661+
662+
pub type BuiltinBounds = EnumSet<BuiltinBound>;
663+
664+
#[deriving(Eq, IterBytes)]
665+
pub enum BuiltinBound {
666+
BoundCopy,
667+
BoundStatic,
668+
BoundOwned,
669+
BoundConst,
670+
}
671+
672+
pub fn EmptyBuiltinBounds() -> BuiltinBounds {
673+
EnumSet::empty()
674+
}
675+
676+
impl CLike for BuiltinBound {
677+
pub fn to_uint(&self) -> uint {
678+
*self as uint
679+
}
680+
pub fn from_uint(v: uint) -> BuiltinBound {
681+
unsafe { cast::transmute(v) }
682+
}
664683
}
665684

666685
#[deriving(Eq)]
@@ -817,7 +836,7 @@ impl to_bytes::IterBytes for RegionVid {
817836

818837
pub struct TypeParameterDef {
819838
def_id: ast::def_id,
820-
bounds: param_bounds
839+
bounds: @ParamBounds
821840
}
822841

823842
/// Information about the type/lifetime parametesr associated with an item.
@@ -1497,14 +1516,6 @@ pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
14971516
substs.repr(cx)
14981517
}
14991518

1500-
pub fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
1501-
pb.repr(cx)
1502-
}
1503-
1504-
pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
1505-
pbs.repr(cx)
1506-
}
1507-
15081519
pub fn subst(cx: ctxt,
15091520
substs: &substs,
15101521
typ: t)
@@ -1795,6 +1806,19 @@ pub struct TypeContents {
17951806
}
17961807
17971808
pub impl TypeContents {
1809+
fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
1810+
iter::all(|bb| self.meets_bound(cx, bb), |f| bbs.each(f))
1811+
}
1812+
1813+
fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
1814+
match bb {
1815+
BoundCopy => self.is_copy(cx),
1816+
BoundStatic => self.is_static(cx),
1817+
BoundConst => self.is_const(cx),
1818+
BoundOwned => self.is_owned(cx)
1819+
}
1820+
}
1821+
17981822
fn intersects(&self, tc: TypeContents) -> bool {
17991823
(self.bits & tc.bits) != 0
18001824
}
@@ -1808,11 +1832,11 @@ pub impl TypeContents {
18081832
TC_EMPTY_ENUM
18091833
}
18101834
1811-
fn is_durable(&self, cx: ctxt) -> bool {
1812-
!self.intersects(TypeContents::nondurable(cx))
1835+
fn is_static(&self, cx: ctxt) -> bool {
1836+
!self.intersects(TypeContents::nonstatic(cx))
18131837
}
18141838
1815-
fn nondurable(_cx: ctxt) -> TypeContents {
1839+
fn nonstatic(_cx: ctxt) -> TypeContents {
18161840
TC_BORROWED_POINTER
18171841
}
18181842
@@ -1917,8 +1941,8 @@ pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
19171941
type_contents(cx, t).is_copy(cx)
19181942
}
19191943
1920-
pub fn type_is_durable(cx: ctxt, t: ty::t) -> bool {
1921-
type_contents(cx, t).is_durable(cx)
1944+
pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
1945+
type_contents(cx, t).is_static(cx)
19221946
}
19231947
19241948
pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
@@ -2198,19 +2222,19 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
21982222
debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
21992223
let _i = indenter();
22002224
2201-
let r = type_param_def.bounds.foldl(TC_ALL, |tc, bound| {
2225+
let mut tc = TC_ALL;
2226+
for type_param_def.bounds.builtin_bounds.each |bound| {
22022227
debug!("tc = %s, bound = %?", tc.to_str(), bound);
2203-
match *bound {
2204-
bound_copy => tc - TypeContents::nonimplicitly_copyable(cx),
2205-
bound_durable => tc - TypeContents::nondurable(cx),
2206-
bound_owned => tc - TypeContents::nonowned(cx),
2207-
bound_const => tc - TypeContents::nonconst(cx),
2208-
bound_trait(_) => *tc
2209-
}
2210-
});
2228+
tc = tc - match bound {
2229+
BoundCopy => TypeContents::nonimplicitly_copyable(cx),
2230+
BoundStatic => TypeContents::nonstatic(cx),
2231+
BoundOwned => TypeContents::nonowned(cx),
2232+
BoundConst => TypeContents::nonconst(cx),
2233+
};
2234+
}
22112235
2212-
debug!("result = %s", r.to_str());
2213-
return r;
2236+
debug!("result = %s", tc.to_str());
2237+
return tc;
22142238
}
22152239
}
22162240
@@ -3577,7 +3601,7 @@ pub fn trait_supertraits(cx: ctxt,
35773601
pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
35783602
let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
35793603
supertrait_refs.map(
3580-
|supertrait_ref| @supertrait_ref.subst(cx, &trait_ref.substs))
3604+
|supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
35813605
}
35823606

35833607
fn lookup_locally_or_in_crate_store<V:Copy>(
@@ -4261,18 +4285,9 @@ pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
42614285
// relation on the supertraits from each bounded trait's constraint
42624286
// list.
42634287
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
4264-
bounds: param_bounds,
4265-
f: &fn(&TraitRef) -> bool) {
4266-
for bounds.each |bound| {
4267-
let bound_trait_ref = match *bound {
4268-
ty::bound_trait(bound_t) => bound_t,
4269-
4270-
ty::bound_copy | ty::bound_owned |
4271-
ty::bound_const | ty::bound_durable => {
4272-
loop; // skip non-trait bounds
4273-
}
4274-
};
4275-
4288+
bounds: &ParamBounds,
4289+
f: &fn(@TraitRef) -> bool) {
4290+
for bounds.trait_bounds.each |&bound_trait_ref| {
42764291
let mut supertrait_set = HashMap::new();
42774292
let mut trait_refs = ~[];
42784293
let mut i = 0;

0 commit comments

Comments
 (0)