Skip to content

Commit

Permalink
auto merge of rust-lang#6336 : nikomatsakis/rust/issue-6308-closure-b…
Browse files Browse the repository at this point in the history
…ounds, 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
  • Loading branch information
bors committed May 10, 2013
2 parents f547a67 + 7852086 commit ad8e236
Show file tree
Hide file tree
Showing 14 changed files with 515 additions and 213 deletions.
40 changes: 28 additions & 12 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,18 +555,34 @@ fn parse_type_param_def(st: @mut PState, conv: conv_did) -> ty::TypeParameterDef
bounds: parse_bounds(st, conv)}
}
fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] {
let mut bounds = ~[];
fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
let mut param_bounds = ty::ParamBounds {
builtin_bounds: ty::EmptyBuiltinBounds(),
trait_bounds: ~[]
};
loop {
bounds.push(match next(st) {
'S' => ty::bound_owned,
'C' => ty::bound_copy,
'K' => ty::bound_const,
'O' => ty::bound_durable,
'I' => ty::bound_trait(@parse_trait_ref(st, conv)),
'.' => break,
_ => fail!(~"parse_bounds: bad bounds")
});
match next(st) {
'S' => {
param_bounds.builtin_bounds.add(ty::BoundOwned);
}
'C' => {
param_bounds.builtin_bounds.add(ty::BoundCopy);
}
'K' => {
param_bounds.builtin_bounds.add(ty::BoundConst);
}
'O' => {
param_bounds.builtin_bounds.add(ty::BoundStatic);
}
'I' => {
param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
}
'.' => {
return @param_bounds;
}
_ => {
fail!(~"parse_bounds: bad bounds")
}
}
}
@bounds
}
24 changes: 13 additions & 11 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,21 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
enc_ty(w, cx, fsig.output);
}

fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
for (*bs).each |bound| {
match *bound {
ty::bound_owned => w.write_char('S'),
ty::bound_copy => w.write_char('C'),
ty::bound_const => w.write_char('K'),
ty::bound_durable => w.write_char('O'),
ty::bound_trait(tp) => {
w.write_char('I');
enc_trait_ref(w, cx, tp);
}
fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @ty::ParamBounds) {
for bs.builtin_bounds.each |bound| {
match bound {
ty::BoundOwned => w.write_char('S'),
ty::BoundCopy => w.write_char('C'),
ty::BoundConst => w.write_char('K'),
ty::BoundStatic => w.write_char('O'),
}
}

for bs.trait_bounds.each |&tp| {
w.write_char('I');
enc_trait_ref(w, cx, tp);
}

w.write_char('.');
}

Expand Down
40 changes: 7 additions & 33 deletions src/librustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use middle::pat_util;
use middle::ty;
use middle::typeck;
use util::ppaux::{Repr, ty_to_str};
use util::ppaux::UserString;

use syntax::ast::*;
use syntax::attr::attrs_contains_name;
Expand Down Expand Up @@ -338,46 +339,19 @@ pub fn check_bounds(cx: Context,
type_param_def: &ty::TypeParameterDef)
{
let kind = ty::type_contents(cx.tcx, ty);
let mut missing = ~[];
for type_param_def.bounds.each |bound| {
match *bound {
ty::bound_trait(_) => {
/* Not our job, checking in typeck */
}

ty::bound_copy => {
if !kind.is_copy(cx.tcx) {
missing.push("Copy");
}
}

ty::bound_durable => {
if !kind.is_durable(cx.tcx) {
missing.push("'static");
}
}

ty::bound_owned => {
if !kind.is_owned(cx.tcx) {
missing.push("Owned");
}
}

ty::bound_const => {
if !kind.is_const(cx.tcx) {
missing.push("Const");
}
}
let mut missing = ty::EmptyBuiltinBounds();
for type_param_def.bounds.builtin_bounds.each |bound| {
if !kind.meets_bound(cx.tcx, bound) {
missing.add(bound);
}
}

if !missing.is_empty() {
cx.tcx.sess.span_err(
sp,
fmt!("instantiating a type parameter with an incompatible type \
`%s`, which does not fulfill `%s`",
ty_to_str(cx.tcx, ty),
str::connect_slices(missing, " ")));
missing.user_string(cx.tcx)));
}
}

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

// note: also used from middle::typeck::regionck!
pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool {
if !ty::type_is_durable(tcx, ty) {
if !ty::type_is_static(tcx, ty) {
match ty::get(ty).sty {
ty::ty_param(*) => {
tcx.sess.span_err(sp, "value may contain borrowed \
Expand Down
26 changes: 10 additions & 16 deletions src/librustc/middle/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ impl<T:Subst> Subst for ~[T] {
}
}

impl<T:Subst> Subst for @~[T] {
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @~[T] {
@(**self).subst(tcx, substs)
impl<T:Subst> Subst for @T {
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @T {
match self {
&@ref t => @t.subst(tcx, substs)
}
}
}

Expand Down Expand Up @@ -115,19 +117,11 @@ impl Subst for ty::BareFnTy {
}
}

impl Subst for ty::param_bound {
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::param_bound {
match self {
&ty::bound_copy |
&ty::bound_durable |
&ty::bound_owned |
&ty::bound_const => {
*self
}

&ty::bound_trait(tref) => {
ty::bound_trait(@tref.subst(tcx, substs))
}
impl Subst for ty::ParamBounds {
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ParamBounds {
ty::ParamBounds {
builtin_bounds: self.builtin_bounds,
trait_bounds: self.trait_bounds.subst(tcx, substs)
}
}
}
Expand Down
11 changes: 3 additions & 8 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,14 +348,9 @@ pub fn make_mono_id(ccx: @CrateContext,
let mut i = 0;
vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
let mut v = ~[];
for type_param_def.bounds.each |bound| {
match *bound {
ty::bound_trait(_) => {
v.push(meth::vtable_id(ccx, /*bad*/copy vts[i]));
i += 1;
}
_ => ()
}
for type_param_def.bounds.trait_bounds.each |_bound| {
v.push(meth::vtable_id(ccx, /*bad*/copy vts[i]));
i += 1;
}
(*subst, if !v.is_empty() { Some(v) } else { None })
})
Expand Down
107 changes: 61 additions & 46 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use util::ppaux::{note_and_explain_region, bound_region_to_str};
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
use util::ppaux::Repr;
use util::common::{indenter};
use util::enum_set::{EnumSet, CLike};

use core;
use core::ptr::to_unsafe_ptr;
Expand Down Expand Up @@ -58,8 +59,6 @@ pub struct field {
mt: mt
}

pub type param_bounds = @~[param_bound];

pub struct method {
ident: ast::ident,
generics: ty::Generics,
Expand Down Expand Up @@ -655,12 +654,32 @@ pub enum type_err {
}

#[deriving(Eq, IterBytes)]
pub enum param_bound {
bound_copy,
bound_durable,
bound_owned,
bound_const,
bound_trait(@TraitRef),
pub struct ParamBounds {
builtin_bounds: BuiltinBounds,
trait_bounds: ~[@TraitRef]
}

pub type BuiltinBounds = EnumSet<BuiltinBound>;

#[deriving(Eq, IterBytes)]
pub enum BuiltinBound {
BoundCopy,
BoundStatic,
BoundOwned,
BoundConst,
}

pub fn EmptyBuiltinBounds() -> BuiltinBounds {
EnumSet::empty()
}

impl CLike for BuiltinBound {
pub fn to_uint(&self) -> uint {
*self as uint
}
pub fn from_uint(v: uint) -> BuiltinBound {
unsafe { cast::transmute(v) }
}
}

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

pub struct TypeParameterDef {
def_id: ast::def_id,
bounds: param_bounds
bounds: @ParamBounds
}

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

pub fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
pb.repr(cx)
}

pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
pbs.repr(cx)
}

pub fn subst(cx: ctxt,
substs: &substs,
typ: t)
Expand Down Expand Up @@ -1795,6 +1806,19 @@ pub struct TypeContents {
}
pub impl TypeContents {
fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
iter::all(|bb| self.meets_bound(cx, bb), |f| bbs.each(f))
}
fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
match bb {
BoundCopy => self.is_copy(cx),
BoundStatic => self.is_static(cx),
BoundConst => self.is_const(cx),
BoundOwned => self.is_owned(cx)
}
}
fn intersects(&self, tc: TypeContents) -> bool {
(self.bits & tc.bits) != 0
}
Expand All @@ -1808,11 +1832,11 @@ pub impl TypeContents {
TC_EMPTY_ENUM
}
fn is_durable(&self, cx: ctxt) -> bool {
!self.intersects(TypeContents::nondurable(cx))
fn is_static(&self, cx: ctxt) -> bool {
!self.intersects(TypeContents::nonstatic(cx))
}
fn nondurable(_cx: ctxt) -> TypeContents {
fn nonstatic(_cx: ctxt) -> TypeContents {
TC_BORROWED_POINTER
}
Expand Down Expand Up @@ -1917,8 +1941,8 @@ pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
type_contents(cx, t).is_copy(cx)
}
pub fn type_is_durable(cx: ctxt, t: ty::t) -> bool {
type_contents(cx, t).is_durable(cx)
pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
type_contents(cx, t).is_static(cx)
}
pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
Expand Down Expand Up @@ -2198,19 +2222,19 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
let _i = indenter();
let r = type_param_def.bounds.foldl(TC_ALL, |tc, bound| {
let mut tc = TC_ALL;
for type_param_def.bounds.builtin_bounds.each |bound| {
debug!("tc = %s, bound = %?", tc.to_str(), bound);
match *bound {
bound_copy => tc - TypeContents::nonimplicitly_copyable(cx),
bound_durable => tc - TypeContents::nondurable(cx),
bound_owned => tc - TypeContents::nonowned(cx),
bound_const => tc - TypeContents::nonconst(cx),
bound_trait(_) => *tc
}
});
tc = tc - match bound {
BoundCopy => TypeContents::nonimplicitly_copyable(cx),
BoundStatic => TypeContents::nonstatic(cx),
BoundOwned => TypeContents::nonowned(cx),
BoundConst => TypeContents::nonconst(cx),
};
}
debug!("result = %s", r.to_str());
return r;
debug!("result = %s", tc.to_str());
return tc;
}
}
Expand Down Expand Up @@ -3577,7 +3601,7 @@ pub fn trait_supertraits(cx: ctxt,
pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
supertrait_refs.map(
|supertrait_ref| @supertrait_ref.subst(cx, &trait_ref.substs))
|supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
}

fn lookup_locally_or_in_crate_store<V:Copy>(
Expand Down Expand Up @@ -4261,18 +4285,9 @@ pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
// relation on the supertraits from each bounded trait's constraint
// list.
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
bounds: param_bounds,
f: &fn(&TraitRef) -> bool) {
for bounds.each |bound| {
let bound_trait_ref = match *bound {
ty::bound_trait(bound_t) => bound_t,
ty::bound_copy | ty::bound_owned |
ty::bound_const | ty::bound_durable => {
loop; // skip non-trait bounds
}
};
bounds: &ParamBounds,
f: &fn(@TraitRef) -> bool) {
for bounds.trait_bounds.each |&bound_trait_ref| {
let mut supertrait_set = HashMap::new();
let mut trait_refs = ~[];
let mut i = 0;
Expand Down
Loading

0 comments on commit ad8e236

Please sign in to comment.