Skip to content

Commit

Permalink
Add BuiltinBounds to closure type: parse and handle subtyping,
Browse files Browse the repository at this point in the history
but do not integrate with kindck etc (requires a snapshot first)
  • Loading branch information
nikomatsakis committed May 16, 2013
1 parent 53196bb commit 035c01a
Show file tree
Hide file tree
Showing 19 changed files with 261 additions and 61 deletions.
8 changes: 5 additions & 3 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,12 +470,14 @@ fn parse_closure_ty(st: @mut PState, conv: conv_did) -> ty::ClosureTy {
let purity = parse_purity(next(st));
let onceness = parse_onceness(next(st));
let region = parse_region(st);
let bounds = parse_bounds(st, conv);
let sig = parse_sig(st, conv);
ty::ClosureTy {
purity: purity,
sigil: sigil,
onceness: onceness,
region: region,
bounds: bounds.builtin_bounds,
sig: sig
}
}
Expand Down Expand Up @@ -540,10 +542,10 @@ pub fn parse_type_param_def_data(data: @~[u8], start: uint,

fn parse_type_param_def(st: @mut PState, conv: conv_did) -> ty::TypeParameterDef {
ty::TypeParameterDef {def_id: parse_def(st, NominalType, conv),
bounds: parse_bounds(st, conv)}
bounds: @parse_bounds(st, conv)}
}

fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
fn parse_bounds(st: @mut PState, conv: conv_did) -> ty::ParamBounds {
let mut param_bounds = ty::ParamBounds {
builtin_bounds: ty::EmptyBuiltinBounds(),
trait_bounds: ~[]
Expand All @@ -566,7 +568,7 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
}
'.' => {
return @param_bounds;
return param_bounds;
}
_ => {
fail!("parse_bounds: bad bounds")
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ fn enc_closure_ty(w: @io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
enc_purity(w, ft.purity);
enc_onceness(w, ft.onceness);
enc_region(w, cx, ft.region);
let bounds = ty::ParamBounds {builtin_bounds: ft.bounds,
trait_bounds: ~[]};
enc_bounds(w, cx, &bounds);
enc_fn_sig(w, cx, &ft.sig);
}

Expand All @@ -392,7 +395,7 @@ 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::ParamBounds) {
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'),
Expand Down
28 changes: 21 additions & 7 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use middle::lint::{allow, level, unused_imports};
use middle::lint::{get_lint_level, get_lint_settings_level};
use middle::pat_util::pat_bindings;

use syntax::ast::{TyParamBound, ty_closure};
use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk};
use syntax::ast::{bind_infer, bind_by_ref, bind_by_copy};
Expand Down Expand Up @@ -3732,14 +3733,20 @@ pub impl Resolver {
type_parameters: &OptVec<TyParam>,
visitor: ResolveVisitor) {
for type_parameters.each |type_parameter| {
for type_parameter.bounds.each |&bound| {
match bound {
TraitTyParamBound(tref) => {
self.resolve_trait_reference(tref, visitor)
}
RegionTyParamBound => {}
}
for type_parameter.bounds.each |bound| {
self.resolve_type_parameter_bound(bound, visitor);
}
}
}

fn resolve_type_parameter_bound(@mut self,
type_parameter_bound: &TyParamBound,
visitor: ResolveVisitor) {
match *type_parameter_bound {
TraitTyParamBound(tref) => {
self.resolve_trait_reference(tref, visitor)
}
RegionTyParamBound => {}
}
}

Expand Down Expand Up @@ -4070,6 +4077,13 @@ pub impl Resolver {
}
}

ty_closure(c) => {
for c.bounds.each |bound| {
self.resolve_type_parameter_bound(bound, visitor);
}
visit_ty(ty, (), visitor);
}

_ => {
// Just resolve embedded types.
visit_ty(ty, (), visitor);
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
sigil: ast::BorrowedSigil,
onceness: ast::Many,
region: ty::re_bound(ty::br_anon(0)),
bounds: ty::EmptyBuiltinBounds(),
sig: FnSig {
bound_lifetime_names: opt_vec::Empty,
inputs: ~[ star_u8 ],
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
sigil: sigil,
onceness: ast::Many,
region: ty::re_static,
bounds: ty::EmptyBuiltinBounds(),
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
inputs: ~[],
output: ty::mk_nil()}})
Expand Down
29 changes: 27 additions & 2 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use middle::typeck;
use middle;
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::ppaux::{Repr, UserString};
use util::common::{indenter};
use util::enum_set::{EnumSet, CLike};

Expand Down Expand Up @@ -390,7 +390,8 @@ pub struct ClosureTy {
sigil: ast::Sigil,
onceness: ast::Onceness,
region: Region,
sig: FnSig
bounds: BuiltinBounds,
sig: FnSig,
}

/**
Expand Down Expand Up @@ -685,6 +686,7 @@ pub enum type_err {
terr_int_mismatch(expected_found<IntVarValue>),
terr_float_mismatch(expected_found<ast::float_ty>),
terr_traits(expected_found<ast::def_id>),
terr_builtin_bounds(expected_found<BuiltinBounds>),
}

#[deriving(Eq, IterBytes)]
Expand All @@ -707,6 +709,15 @@ pub fn EmptyBuiltinBounds() -> BuiltinBounds {
EnumSet::empty()
}

pub fn AllBuiltinBounds() -> BuiltinBounds {
let mut set = EnumSet::empty();
set.add(BoundCopy);
set.add(BoundStatic);
set.add(BoundOwned);
set.add(BoundConst);
set
}

impl CLike for BuiltinBound {
pub fn to_uint(&self) -> uint {
*self as uint
Expand Down Expand Up @@ -3169,6 +3180,7 @@ pub fn adjust_ty(cx: ctxt,
sigil: s,
onceness: ast::Many,
region: r,
bounds: ty::AllBuiltinBounds(),
sig: copy b.sig})
}
ref b => {
Expand Down Expand Up @@ -3697,6 +3709,19 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
item_path_str(cx, values.expected),
item_path_str(cx, values.found))
}
terr_builtin_bounds(values) => {
if values.expected.is_empty() {
fmt!("expected no bounds but found `%s`",
values.found.user_string(cx))
} else if values.found.is_empty() {
fmt!("expected bounds `%s` but found no bounds",
values.expected.user_string(cx))
} else {
fmt!("expected bounds `%s` but found bounds `%s`",
values.expected.user_string(cx),
values.found.user_string(cx))
}
}
terr_self_substs => {
~"inconsistent self substitution" // XXX this is more of a bug
}
Expand Down
88 changes: 76 additions & 12 deletions src/librustc/middle/typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ use middle::ty;
use middle::typeck::rscope::in_binding_rscope;
use middle::typeck::rscope::{region_scope, RegionError};
use middle::typeck::rscope::RegionParamNames;
use middle::typeck::lookup_def_tcx;

use syntax::abi::AbiSet;
use syntax::{ast, ast_util};
Expand Down Expand Up @@ -220,7 +221,6 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
return trait_ref;
}


pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
this: &AC,
rscope: &RS,
Expand Down Expand Up @@ -377,11 +377,13 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
bf.abis, &bf.lifetimes, &bf.decl))
}
ast::ty_closure(ref f) => {
let bounds = conv_builtin_bounds(this.tcx(), &f.bounds);
let fn_decl = ty_of_closure(this,
rscope,
f.sigil,
f.purity,
f.onceness,
bounds,
f.region,
&f.decl,
None,
Expand Down Expand Up @@ -646,17 +648,18 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
}

pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
this: &AC,
rscope: &RS,
sigil: ast::Sigil,
purity: ast::purity,
onceness: ast::Onceness,
opt_lifetime: Option<@ast::Lifetime>,
decl: &ast::fn_decl,
expected_sig: Option<ty::FnSig>,
lifetimes: &OptVec<ast::Lifetime>,
span: span)
-> ty::ClosureTy
this: &AC,
rscope: &RS,
sigil: ast::Sigil,
purity: ast::purity,
onceness: ast::Onceness,
bounds: ty::BuiltinBounds,
opt_lifetime: Option<@ast::Lifetime>,
decl: &ast::fn_decl,
expected_sig: Option<ty::FnSig>,
lifetimes: &OptVec<ast::Lifetime>,
span: span)
-> ty::ClosureTy
{
// The caller should not both provide explicit bound lifetime
// names and expected types. Either we infer the bound lifetime
Expand Down Expand Up @@ -713,8 +716,69 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
sigil: sigil,
onceness: onceness,
region: bound_region,
bounds: bounds,
sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
inputs: input_tys,
output: output_ty}
}
}

fn conv_builtin_bounds(tcx: ty::ctxt,
ast_bounds: &OptVec<ast::TyParamBound>)
-> ty::BuiltinBounds {
//! Converts a list of bounds from the AST into a `BuiltinBounds`
//! struct. Reports an error if any of the bounds that appear
//! in the AST refer to general traits and not the built-in traits
//! like `Copy` or `Owned`. Used to translate the bounds that
//! appear in closure and trait types, where only builtin bounds are
//! legal.
let mut builtin_bounds = ty::EmptyBuiltinBounds();
for ast_bounds.each |ast_bound| {
match *ast_bound {
ast::TraitTyParamBound(b) => {
match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
ast::def_trait(trait_did) => {
if try_add_builtin_trait(tcx,
trait_did,
&mut builtin_bounds) {
loop; // success
}
}
_ => { }
}
tcx.sess.span_fatal(
b.path.span,
fmt!("only the builtin traits can be used \
as closure or object bounds"));
}
ast::RegionTyParamBound => {
builtin_bounds.add(ty::BoundStatic);
}
}
}
builtin_bounds
}

pub fn try_add_builtin_trait(tcx: ty::ctxt,
trait_def_id: ast::def_id,
builtin_bounds: &mut ty::BuiltinBounds) -> bool {
//! Checks whether `trait_ref` refers to one of the builtin
//! traits, like `Copy` or `Owned`, and adds the corresponding
//! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
//! is a builtin trait.
let li = &tcx.lang_items;
if trait_def_id == li.owned_trait() {
builtin_bounds.add(ty::BoundOwned);
true
} else if trait_def_id == li.copy_trait() {
builtin_bounds.add(ty::BoundCopy);
true
} else if trait_def_id == li.const_trait() {
builtin_bounds.add(ty::BoundConst);
true
} else {
false
}
}
29 changes: 17 additions & 12 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1661,19 +1661,22 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
let (expected_sig,
expected_purity,
expected_sigil,
expected_onceness) = {
expected_onceness,
expected_bounds) = {
match expected_sty {
Some(ty::ty_closure(ref cenv)) => {
let id = expr.id;
let (_, _, sig) =
replace_bound_regions_in_fn_sig(
tcx, @Nil, None, &cenv.sig,
|br| ty::re_bound(ty::br_cap_avoid(id, @br)));
(Some(sig), cenv.purity, cenv.sigil, cenv.onceness)
(Some(sig), cenv.purity, cenv.sigil,
cenv.onceness, cenv.bounds)
}
_ => {
// Not an error! Means we're inferring the closure type
(None, ast::impure_fn, ast::BorrowedSigil, ast::Many)
(None, ast::impure_fn, ast::BorrowedSigil,
ast::Many, ty::EmptyBuiltinBounds())
}
}
};
Expand All @@ -1687,15 +1690,16 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,

// construct the function type
let fn_ty = astconv::ty_of_closure(fcx,
fcx,
sigil,
purity,
expected_onceness,
None,
decl,
expected_sig,
&opt_vec::Empty,
expr.span);
fcx,
sigil,
purity,
expected_onceness,
expected_bounds,
None,
decl,
expected_sig,
&opt_vec::Empty,
expr.span);

let fty_sig;
let fty = if error_happened {
Expand Down Expand Up @@ -3526,6 +3530,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
sigil: ast::BorrowedSigil,
onceness: ast::Once,
region: ty::re_bound(ty::br_anon(0)),
bounds: ty::EmptyBuiltinBounds(),
sig: ty::FnSig {
bound_lifetime_names: opt_vec::Empty,
inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))],
Expand Down
Loading

0 comments on commit 035c01a

Please sign in to comment.