Parse and typecheck (not kindcheck) bounds on trait paths.
This commit is contained in:
parent
394f455b5e
commit
ce857e3d60
@ -954,7 +954,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
encode_name(ecx, ebml_w, item.ident);
|
||||
encode_attributes(ebml_w, item.attrs);
|
||||
match ty.node {
|
||||
ast::ty_path(path, _) if path.idents.len() == 1 => {
|
||||
ast::ty_path(path, bounds, _) if path.idents.len() == 1 => {
|
||||
assert!(bounds.is_empty());
|
||||
encode_impl_type_basename(ecx, ebml_w,
|
||||
ast_util::path_to_ident(path));
|
||||
}
|
||||
|
@ -311,8 +311,9 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
||||
let substs = parse_substs(st, conv);
|
||||
let store = parse_trait_store(st);
|
||||
let mt = parse_mutability(st);
|
||||
let bounds = parse_bounds(st, conv);
|
||||
assert_eq!(next(st), ']');
|
||||
return ty::mk_trait(st.tcx, def, substs, store, mt);
|
||||
return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
|
||||
}
|
||||
'p' => {
|
||||
let did = parse_def(st, TypeParameter, conv);
|
||||
|
@ -261,13 +261,16 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) {
|
||||
enc_substs(w, cx, substs);
|
||||
w.write_char(']');
|
||||
}
|
||||
ty::ty_trait(def, ref substs, store, mt) => {
|
||||
ty::ty_trait(def, ref substs, store, mt, bounds) => {
|
||||
w.write_str(&"x[");
|
||||
w.write_str((cx.ds)(def));
|
||||
w.write_char('|');
|
||||
enc_substs(w, cx, substs);
|
||||
enc_trait_store(w, cx, store);
|
||||
enc_mutability(w, mt);
|
||||
let bounds = ty::ParamBounds {builtin_bounds: bounds,
|
||||
trait_bounds: ~[]};
|
||||
enc_bounds(w, cx, &bounds);
|
||||
w.write_char(']');
|
||||
}
|
||||
ty::ty_tup(ts) => {
|
||||
|
@ -129,7 +129,8 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
|
||||
if cx.tcx.lang_items.drop_trait() == trait_def_id {
|
||||
// Yes, it's a destructor.
|
||||
match self_type.node {
|
||||
ty_path(_, path_node_id) => {
|
||||
ty_path(_, bounds, path_node_id) => {
|
||||
assert!(bounds.is_empty());
|
||||
let struct_def = cx.tcx.def_map.get_copy(
|
||||
&path_node_id);
|
||||
let struct_did =
|
||||
@ -307,7 +308,7 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
|
||||
|
||||
fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
|
||||
match aty.node {
|
||||
ty_path(_, id) => {
|
||||
ty_path(_, _, id) => {
|
||||
let r = cx.tcx.node_type_substs.find(&id);
|
||||
for r.iter().advance |ts| {
|
||||
let did = ast_util::def_id_of_def(cx.tcx.def_map.get_copy(&id));
|
||||
@ -533,7 +534,8 @@ pub fn check_cast_for_escaping_regions(
|
||||
pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) {
|
||||
let target_ty = ty::expr_ty(cx.tcx, target);
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
|
||||
// FIXME(#3569) kind check bounds here
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _, _bounds) => {
|
||||
let source_ty = ty::expr_ty(cx.tcx, source);
|
||||
if !ty::type_is_owned(cx.tcx, source_ty) {
|
||||
cx.tcx.sess.span_err(
|
||||
|
@ -714,7 +714,7 @@ fn check_item_ctypes(cx: &Context, it: @ast::item) {
|
||||
let tys = vec::map(decl.inputs, |a| a.ty );
|
||||
for vec::each(vec::append_one(tys, decl.output)) |ty| {
|
||||
match ty.node {
|
||||
ast::ty_path(_, id) => {
|
||||
ast::ty_path(_, _, id) => {
|
||||
match cx.tcx.def_map.get_copy(&id) {
|
||||
ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
|
||||
cx.span_lint(ctypes, ty.span,
|
||||
|
@ -804,7 +804,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
||||
// then check whether it is region-parameterized and consider
|
||||
// that as a direct dependency.
|
||||
match ty.node {
|
||||
ast::ty_path(path, id) => {
|
||||
ast::ty_path(path, _bounds, id) => {
|
||||
match cx.def_map.find(&id) {
|
||||
Some(&ast::def_ty(did)) |
|
||||
Some(&ast::def_trait(did)) |
|
||||
@ -840,7 +840,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
||||
visit_mt(mt, (cx, visitor));
|
||||
}
|
||||
|
||||
ast::ty_path(path, _) => {
|
||||
ast::ty_path(path, _bounds, _) => {
|
||||
// type parameters are---for now, anyway---always invariant
|
||||
do cx.with_ambient_variance(rv_invariant) {
|
||||
for path.types.iter().advance |tp| {
|
||||
|
@ -1250,7 +1250,7 @@ impl Resolver {
|
||||
// If there are static methods, then create the module
|
||||
// and add them.
|
||||
match (trait_ref_opt, ty) {
|
||||
(None, @Ty { node: ty_path(path, _), _ }) if
|
||||
(None, @Ty { node: ty_path(path, _, _), _ }) if
|
||||
has_static_methods && path.idents.len() == 1 => {
|
||||
let name = path_to_ident(path);
|
||||
|
||||
@ -4120,7 +4120,7 @@ impl Resolver {
|
||||
// Like path expressions, the interpretation of path types depends
|
||||
// on whether the path has multiple elements in it or not.
|
||||
|
||||
ty_path(path, path_id) => {
|
||||
ty_path(path, bounds, path_id) => {
|
||||
// This is a path in the type namespace. Walk through scopes
|
||||
// scopes looking for it.
|
||||
let mut result_def = None;
|
||||
@ -4179,6 +4179,10 @@ impl Resolver {
|
||||
self.idents_to_str(path.idents)));
|
||||
}
|
||||
}
|
||||
|
||||
for bounds.each |bound| {
|
||||
self.resolve_type_parameter_bound(bound, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
ty_closure(c) => {
|
||||
|
@ -561,7 +561,7 @@ fn create_ty(cx: @mut CrateContext, t: ty::t, span: span) -> DIType {
|
||||
cx.sess.span_note(span, "debuginfo for closure NYI");
|
||||
create_unimpl_ty(cx, t)
|
||||
},
|
||||
ty::ty_trait(_did, ref _substs, ref _vstore, _) => {
|
||||
ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => {
|
||||
cx.sess.span_note(span, "debuginfo for trait NYI");
|
||||
create_unimpl_ty(cx, t)
|
||||
},
|
||||
|
@ -683,7 +683,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
||||
}
|
||||
ast::expr_cast(val, _) => {
|
||||
match ty::get(node_id_type(bcx, expr.id)).sty {
|
||||
ty::ty_trait(_, _, store, _) => {
|
||||
ty::ty_trait(_, _, store, _, _) => {
|
||||
return meth::trans_trait_cast(bcx, val, expr.id, dest,
|
||||
store);
|
||||
}
|
||||
|
@ -486,13 +486,13 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v0, t, drop_ty)
|
||||
}
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _) => {
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
|
||||
let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]);
|
||||
let llbox = Load(bcx, llbox_ptr);
|
||||
decr_refcnt_maybe_free(bcx, llbox, Some(llbox_ptr),
|
||||
ty::mk_opaque_box(ccx.tcx))
|
||||
}
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
|
||||
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
|
||||
// Only drop the value when it is non-null
|
||||
do with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue))) |bcx| {
|
||||
@ -571,12 +571,12 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
ty::ty_closure(_) => {
|
||||
closure::make_closure_glue(bcx, v, t, take_ty)
|
||||
}
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _) => {
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
|
||||
let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
|
||||
incr_refcnt_of_boxed(bcx, llbox);
|
||||
bcx
|
||||
}
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
|
||||
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
|
||||
let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]);
|
||||
let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable]));
|
||||
|
||||
|
@ -293,7 +293,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
|
||||
ty::ty_closure(ref fty) => {
|
||||
Some(normalized_closure_ty(tcx, fty.sigil))
|
||||
}
|
||||
ty::ty_trait(_, _, ref store, _) => {
|
||||
ty::ty_trait(_, _, ref store, _, _) => {
|
||||
let sigil = match *store {
|
||||
ty::UniqTraitStore => ast::OwnedSigil,
|
||||
ty::BoxTraitStore => ast::ManagedSigil,
|
||||
|
@ -160,7 +160,7 @@ fn traverse_ty<'a>(ty: @Ty, (cx, v): (@mut ctx<'a>, visit::vt<@mut ctx<'a>>)) {
|
||||
}
|
||||
|
||||
match ty.node {
|
||||
ty_path(p, p_id) => {
|
||||
ty_path(p, _bounds, p_id) => {
|
||||
match cx.tcx.def_map.find(&p_id) {
|
||||
// Kind of a hack to check this here, but I'm not sure what else
|
||||
// to do
|
||||
|
@ -335,7 +335,7 @@ impl Reflector {
|
||||
}
|
||||
|
||||
// Miscallaneous extra types
|
||||
ty::ty_trait(_, _, _, _) => self.leaf(~"trait"),
|
||||
ty::ty_trait(_, _, _, _, _) => self.leaf(~"trait"),
|
||||
ty::ty_infer(_) => self.leaf(~"infer"),
|
||||
ty::ty_err => self.leaf(~"err"),
|
||||
ty::ty_param(ref p) => {
|
||||
|
@ -140,7 +140,7 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
|
||||
ty::ty_bare_fn(*) => Type::i8p(),
|
||||
ty::ty_closure(*) => Type::struct_([Type::i8p(), Type::i8p()], false),
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
|
||||
ty::ty_evec(mt, ty::vstore_fixed(size)) => {
|
||||
@ -271,7 +271,7 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
let ty = type_of_fn_from_ty(cx, t);
|
||||
Type::func_pair(cx, &ty)
|
||||
}
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
|
||||
ty::ty_type => cx.tydesc_type.ptr_to(),
|
||||
ty::ty_tup(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
|
@ -208,7 +208,7 @@ pub fn type_needs_inner(cx: Context,
|
||||
ty::ty_bare_fn(*) |
|
||||
ty::ty_ptr(_) |
|
||||
ty::ty_rptr(_, _) |
|
||||
ty::ty_trait(_, _, _, _) => false,
|
||||
ty::ty_trait(*) => false,
|
||||
|
||||
ty::ty_enum(did, ref substs) => {
|
||||
if list::find(enums_seen, |id| *id == did).is_none() {
|
||||
|
@ -419,7 +419,8 @@ impl to_bytes::IterBytes for ClosureTy {
|
||||
self.sigil.iter_bytes(lsb0, f) &&
|
||||
self.onceness.iter_bytes(lsb0, f) &&
|
||||
self.region.iter_bytes(lsb0, f) &&
|
||||
self.sig.iter_bytes(lsb0, f)
|
||||
self.sig.iter_bytes(lsb0, f) &&
|
||||
self.bounds.iter_bytes(lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,7 +601,7 @@ pub enum sty {
|
||||
ty_rptr(Region, mt),
|
||||
ty_bare_fn(BareFnTy),
|
||||
ty_closure(ClosureTy),
|
||||
ty_trait(def_id, substs, TraitStore, ast::mutability),
|
||||
ty_trait(def_id, substs, TraitStore, ast::mutability, BuiltinBounds),
|
||||
ty_struct(def_id, substs),
|
||||
ty_tup(~[t]),
|
||||
|
||||
@ -1046,7 +1047,7 @@ fn mk_t(cx: ctxt, st: sty) -> t {
|
||||
&ty_infer(_) => flags |= needs_infer as uint,
|
||||
&ty_self(_) => flags |= has_self as uint,
|
||||
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
|
||||
&ty_trait(_, ref substs, _, _) => {
|
||||
&ty_trait(_, ref substs, _, _, _) => {
|
||||
flags |= sflags(substs);
|
||||
}
|
||||
&ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
|
||||
@ -1268,10 +1269,11 @@ pub fn mk_trait(cx: ctxt,
|
||||
did: ast::def_id,
|
||||
substs: substs,
|
||||
store: TraitStore,
|
||||
mutability: ast::mutability)
|
||||
mutability: ast::mutability,
|
||||
bounds: BuiltinBounds)
|
||||
-> t {
|
||||
// take a copy of substs so that we own the vectors inside
|
||||
mk_t(cx, ty_trait(did, substs, store, mutability))
|
||||
mk_t(cx, ty_trait(did, substs, store, mutability, bounds))
|
||||
}
|
||||
|
||||
pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, substs: substs) -> t {
|
||||
@ -1319,7 +1321,7 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
|
||||
maybe_walk_ty(tm.ty, f);
|
||||
}
|
||||
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
|
||||
ty_trait(_, ref substs, _, _) => {
|
||||
ty_trait(_, ref substs, _, _, _) => {
|
||||
for (*substs).tps.iter().advance |subty| { maybe_walk_ty(*subty, f); }
|
||||
}
|
||||
ty_tup(ref ts) => { for ts.iter().advance |tt| { maybe_walk_ty(*tt, f); } }
|
||||
@ -1380,8 +1382,8 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
|
||||
ty_enum(tid, ref substs) => {
|
||||
ty_enum(tid, fold_substs(substs, fldop))
|
||||
}
|
||||
ty_trait(did, ref substs, st, mutbl) => {
|
||||
ty_trait(did, fold_substs(substs, fldop), st, mutbl)
|
||||
ty_trait(did, ref substs, st, mutbl, bounds) => {
|
||||
ty_trait(did, fold_substs(substs, fldop), st, mutbl, bounds)
|
||||
}
|
||||
ty_tup(ref ts) => {
|
||||
let new_ts = ts.map(|tt| fldop(*tt));
|
||||
@ -1470,8 +1472,12 @@ pub fn fold_regions_and_ty(
|
||||
ty_struct(def_id, ref substs) => {
|
||||
ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
|
||||
}
|
||||
ty_trait(def_id, ref substs, st, mutbl) => {
|
||||
ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl)
|
||||
ty_trait(def_id, ref substs, st, mutbl, bounds) => {
|
||||
let st = match st {
|
||||
RegionTraitStore(region) => RegionTraitStore(fldr(region)),
|
||||
st => st,
|
||||
};
|
||||
ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl, bounds)
|
||||
}
|
||||
ty_bare_fn(ref f) => {
|
||||
ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
|
||||
@ -2054,18 +2060,18 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
||||
TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
|
||||
}
|
||||
|
||||
ty_trait(_, _, UniqTraitStore, _) => {
|
||||
ty_trait(_, _, UniqTraitStore, _, _bounds) => {
|
||||
TC_OWNED_CLOSURE
|
||||
}
|
||||
|
||||
ty_trait(_, _, BoxTraitStore, mutbl) => {
|
||||
ty_trait(_, _, BoxTraitStore, mutbl, _bounds) => {
|
||||
match mutbl {
|
||||
ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
|
||||
_ => TC_MANAGED
|
||||
}
|
||||
}
|
||||
|
||||
ty_trait(_, _, RegionTraitStore(r), mutbl) => {
|
||||
ty_trait(_, _, RegionTraitStore(r), mutbl, _bounds) => {
|
||||
borrowed_contents(r, mutbl)
|
||||
}
|
||||
|
||||
@ -2347,7 +2353,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
||||
false // unsafe ptrs can always be NULL
|
||||
}
|
||||
|
||||
ty_trait(_, _, _, _) => {
|
||||
ty_trait(_, _, _, _, _) => {
|
||||
false
|
||||
}
|
||||
|
||||
@ -2500,7 +2506,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
|
||||
ty_box(_) | ty_uniq(_) | ty_closure(_) |
|
||||
ty_estr(vstore_uniq) | ty_estr(vstore_box) |
|
||||
ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
|
||||
ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
|
||||
ty_trait(_, _, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
|
||||
// Structural types
|
||||
ty_enum(did, ref substs) => {
|
||||
let variants = enum_variants(cx, did);
|
||||
@ -2791,12 +2797,13 @@ impl to_bytes::IterBytes for sty {
|
||||
|
||||
ty_uniq(ref mt) => 19u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
|
||||
|
||||
ty_trait(ref did, ref substs, ref v, ref mutbl) => {
|
||||
ty_trait(ref did, ref substs, ref v, ref mutbl, bounds) => {
|
||||
20u8.iter_bytes(lsb0, f) &&
|
||||
did.iter_bytes(lsb0, f) &&
|
||||
substs.iter_bytes(lsb0, f) &&
|
||||
v.iter_bytes(lsb0, f) &&
|
||||
mutbl.iter_bytes(lsb0, f)
|
||||
mutbl.iter_bytes(lsb0, f) &&
|
||||
bounds.iter_bytes(lsb0, f)
|
||||
}
|
||||
|
||||
ty_opaque_closure_ptr(ref ck) => 21u8.iter_bytes(lsb0, f) && ck.iter_bytes(lsb0, f),
|
||||
@ -3440,7 +3447,7 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
|
||||
ty_rptr(_, _) => ~"&-ptr",
|
||||
ty_bare_fn(_) => ~"extern fn",
|
||||
ty_closure(_) => ~"fn",
|
||||
ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
|
||||
ty_trait(id, _, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
|
||||
ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
|
||||
ty_tup(_) => ~"tuple",
|
||||
ty_infer(TyVar(_)) => ~"inferred type",
|
||||
@ -3774,7 +3781,7 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
|
||||
|
||||
pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
|
||||
match get(ty).sty {
|
||||
ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
|
||||
ty_trait(id, _, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@ -4454,5 +4461,6 @@ pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
|
||||
assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
|
||||
let trait_ref = tcx.intrinsic_traits.get_copy(&ty_visitor_name);
|
||||
(trait_ref,
|
||||
mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm))
|
||||
mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
|
||||
BoxTraitStore, ast::m_imm, EmptyBuiltinBounds()))
|
||||
}
|
||||
|
@ -277,7 +277,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||
}
|
||||
return ty::mk_evec(tcx, mt, vst);
|
||||
}
|
||||
ast::ty_path(path, id) => {
|
||||
ast::ty_path(path, bounds, id) => {
|
||||
// Note that the "bounds must be empty if path is not a trait"
|
||||
// restriction is enforced in the below case for ty_path, which
|
||||
// will run after this as long as the path isn't a trait.
|
||||
match tcx.def_map.find(&id) {
|
||||
Some(&ast::def_prim_ty(ast::ty_str)) if a_seq_ty.mutbl == ast::m_imm => {
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
@ -300,11 +303,13 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||
ty::BoxTraitStore
|
||||
}
|
||||
};
|
||||
let bounds = conv_builtin_bounds(this.tcx(), bounds);
|
||||
return ty::mk_trait(tcx,
|
||||
result.def_id,
|
||||
copy result.substs,
|
||||
trait_store,
|
||||
a_seq_ty.mutbl);
|
||||
a_seq_ty.mutbl,
|
||||
bounds);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -395,13 +400,22 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
|
||||
ast_ty.span);
|
||||
ty::mk_closure(tcx, fn_decl)
|
||||
}
|
||||
ast::ty_path(path, id) => {
|
||||
ast::ty_path(path, bounds, id) => {
|
||||
let a_def = match tcx.def_map.find(&id) {
|
||||
None => tcx.sess.span_fatal(
|
||||
ast_ty.span, fmt!("unbound path %s",
|
||||
path_to_str(path, tcx.sess.intr()))),
|
||||
Some(&d) => d
|
||||
};
|
||||
// Kind bounds on path types are only supported for traits.
|
||||
match a_def {
|
||||
// But don't emit the error if the user meant to do a trait anyway.
|
||||
ast::def_trait(*) => { },
|
||||
_ if !bounds.is_empty() =>
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
"kind bounds can only be used on trait types"),
|
||||
_ => { },
|
||||
}
|
||||
match a_def {
|
||||
ast::def_trait(_) => {
|
||||
let path_str = path_to_str(path, tcx.sess.intr());
|
||||
|
@ -292,7 +292,7 @@ impl<'self> LookupContext<'self> {
|
||||
ty_param(p) => {
|
||||
self.push_inherent_candidates_from_param(self_ty, p);
|
||||
}
|
||||
ty_trait(did, ref substs, store, _) => {
|
||||
ty_trait(did, ref substs, store, _, _) => {
|
||||
self.push_inherent_candidates_from_trait(
|
||||
self_ty, did, substs, store);
|
||||
self.push_inherent_impl_candidates_for_type(did);
|
||||
|
@ -360,7 +360,7 @@ fn visit_expr(expr: @ast::expr, (rcx, v): (@mut Rcx, rvt)) {
|
||||
// explaining how it goes about doing that.
|
||||
let target_ty = rcx.resolve_node_type(expr.id);
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(_, _, ty::RegionTraitStore(trait_region), _) => {
|
||||
ty::ty_trait(_, _, ty::RegionTraitStore(trait_region), _, _) => {
|
||||
let source_ty = rcx.fcx.expr_ty(source);
|
||||
constrain_regions_in_type(rcx, trait_region,
|
||||
expr.span, source_ty);
|
||||
|
@ -139,10 +139,11 @@ fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
|
||||
let t = ty::mk_trait(tcx,
|
||||
id, substs,
|
||||
ty::RegionTraitStore(ty::re_static),
|
||||
ast::m_imm);
|
||||
ast::m_imm,
|
||||
ty::EmptyBuiltinBounds());
|
||||
do fixup_ty(vcx, location_info, t, is_early).map |t_f| {
|
||||
match ty::get(*t_f).sty {
|
||||
ty::ty_trait(_, ref substs_f, _, _) => (/*bad*/copy *substs_f),
|
||||
ty::ty_trait(_, ref substs_f, _, _, _) => (/*bad*/copy *substs_f),
|
||||
_ => fail!("t_f should be a trait")
|
||||
}
|
||||
}
|
||||
@ -530,7 +531,9 @@ pub fn early_resolve_expr(ex: @ast::expr,
|
||||
debug!("vtable resolution on expr %s", ex.repr(fcx.tcx()));
|
||||
let target_ty = fcx.expr_ty(ex);
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(target_def_id, ref target_substs, store, target_mutbl) => {
|
||||
// Bounds of type's contents are not checked here, but in kind.rs.
|
||||
ty::ty_trait(target_def_id, ref target_substs, store,
|
||||
target_mutbl, _bounds) => {
|
||||
fn mutability_allowed(a_mutbl: ast::mutability,
|
||||
b_mutbl: ast::mutability) -> bool {
|
||||
a_mutbl == b_mutbl ||
|
||||
|
@ -114,7 +114,7 @@ pub fn type_is_defined_in_local_crate(original_type: t) -> bool {
|
||||
do ty::walk_ty(original_type) |t| {
|
||||
match get(t).sty {
|
||||
ty_enum(def_id, _) |
|
||||
ty_trait(def_id, _, _, _) |
|
||||
ty_trait(def_id, _, _, _, _) |
|
||||
ty_struct(def_id, _) => {
|
||||
if def_id.crate == ast::local_crate {
|
||||
found_nominal = true;
|
||||
@ -140,7 +140,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
|
||||
match get(base_type).sty {
|
||||
ty_enum(def_id, _) |
|
||||
ty_struct(def_id, _) |
|
||||
ty_trait(def_id, _, _, _) => {
|
||||
ty_trait(def_id, _, _, _, _) => {
|
||||
return Some(def_id);
|
||||
}
|
||||
_ => {
|
||||
@ -753,7 +753,7 @@ impl CoherenceChecker {
|
||||
pub fn ast_type_is_defined_in_local_crate(&self, original_type: @ast::Ty)
|
||||
-> bool {
|
||||
match original_type.node {
|
||||
ty_path(_, path_id) => {
|
||||
ty_path(_, _, path_id) => {
|
||||
match self.crate_context.tcx.def_map.get_copy(&path_id) {
|
||||
def_ty(def_id) | def_struct(def_id) => {
|
||||
if def_id.crate != local_crate {
|
||||
|
@ -508,13 +508,15 @@ pub fn super_tys<C:Combine>(
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::ty_trait(a_id, ref a_substs, a_store, a_mutbl),
|
||||
&ty::ty_trait(b_id, ref b_substs, b_store, b_mutbl))
|
||||
(&ty::ty_trait(a_id, ref a_substs, a_store, a_mutbl, a_bounds),
|
||||
&ty::ty_trait(b_id, ref b_substs, b_store, b_mutbl, b_bounds))
|
||||
if a_id == b_id && a_mutbl == b_mutbl => {
|
||||
let trait_def = ty::lookup_trait_def(tcx, a_id);
|
||||
do this.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
|
||||
do this.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
|
||||
Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s, a_mutbl))
|
||||
do this.bounds(a_bounds, b_bounds).chain |bounds| {
|
||||
Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s, a_mutbl, bounds))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -717,10 +717,11 @@ impl InferCtxt {
|
||||
trait_ref.def_id,
|
||||
copy trait_ref.substs,
|
||||
ty::UniqTraitStore,
|
||||
ast::m_imm);
|
||||
ast::m_imm,
|
||||
ty::EmptyBuiltinBounds());
|
||||
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
|
||||
match ty::get(dummy1).sty {
|
||||
ty::ty_trait(ref def_id, ref substs, _, _) => {
|
||||
ty::ty_trait(ref def_id, ref substs, _, _, _) => {
|
||||
ty::TraitRef {def_id: *def_id,
|
||||
substs: copy *substs}
|
||||
}
|
||||
|
@ -365,6 +365,8 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
|
||||
s.push_str("fn");
|
||||
|
||||
s.push_str(cty.bounds.repr(cx));
|
||||
|
||||
push_sig_to_str(cx, &mut s, &cty.sig);
|
||||
|
||||
return s;
|
||||
@ -451,11 +453,13 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
let base = ast_map::path_to_str(path, cx.sess.intr());
|
||||
parameterized(cx, base, substs.self_r, substs.tps)
|
||||
}
|
||||
ty_trait(did, ref substs, s, mutbl) => {
|
||||
ty_trait(did, ref substs, s, mutbl, ref bounds) => {
|
||||
let path = ty::item_path(cx, did);
|
||||
let base = ast_map::path_to_str(path, cx.sess.intr());
|
||||
let ty = parameterized(cx, base, substs.self_r, substs.tps);
|
||||
fmt!("%s%s%s", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty)
|
||||
let bound_str = bounds.repr(cx);
|
||||
fmt!("%s%s%s%s", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty,
|
||||
bound_str)
|
||||
}
|
||||
ty_evec(ref mt, vs) => {
|
||||
vstore_ty_to_str(cx, mt, vs)
|
||||
|
@ -797,7 +797,7 @@ pub enum ty_ {
|
||||
ty_closure(@TyClosure),
|
||||
ty_bare_fn(@TyBareFn),
|
||||
ty_tup(~[@Ty]),
|
||||
ty_path(@Path, node_id),
|
||||
ty_path(@Path, @OptVec<TyParamBound>, node_id),
|
||||
ty_mac(mac),
|
||||
// ty_infer means the type should be inferred instead of it having been
|
||||
// specified. This should only appear at the "top level" of a type and not
|
||||
|
@ -473,7 +473,7 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
|
||||
|
||||
visit_ty: |ty, (t, vt)| {
|
||||
match ty.node {
|
||||
ty_path(_, id) => vfn(id, copy t),
|
||||
ty_path(_, _, id) => vfn(id, copy t),
|
||||
_ => { /* fall through */ }
|
||||
}
|
||||
visit::visit_ty(ty, (t, vt));
|
||||
|
@ -48,7 +48,7 @@ pub trait AstBuilder {
|
||||
fn ty_mt(&self, ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt;
|
||||
|
||||
fn ty(&self, span: span, ty: ast::ty_) -> @ast::Ty;
|
||||
fn ty_path(&self, @ast::Path) -> @ast::Ty;
|
||||
fn ty_path(&self, @ast::Path, @OptVec<ast::TyParamBound>) -> @ast::Ty;
|
||||
fn ty_ident(&self, span: span, idents: ast::ident) -> @ast::Ty;
|
||||
|
||||
fn ty_rptr(&self, span: span,
|
||||
@ -267,14 +267,17 @@ impl AstBuilder for @ExtCtxt {
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_path(&self, path: @ast::Path) -> @ast::Ty {
|
||||
fn ty_path(&self, path: @ast::Path, bounds: @OptVec<ast::TyParamBound>)
|
||||
-> @ast::Ty {
|
||||
self.ty(path.span,
|
||||
ast::ty_path(path, self.next_id()))
|
||||
ast::ty_path(path, bounds, self.next_id()))
|
||||
}
|
||||
|
||||
// Might need to take bounds as an argument in the future, if you ever want
|
||||
// to generate a bounded existential trait type.
|
||||
fn ty_ident(&self, span: span, ident: ast::ident)
|
||||
-> @ast::Ty {
|
||||
self.ty_path(self.path_ident(span, ident))
|
||||
self.ty_path(self.path_ident(span, ident), @opt_vec::Empty)
|
||||
}
|
||||
|
||||
fn ty_rptr(&self,
|
||||
@ -304,7 +307,8 @@ impl AstBuilder for @ExtCtxt {
|
||||
self.ident_of("Option")
|
||||
],
|
||||
None,
|
||||
~[ ty ]))
|
||||
~[ ty ]),
|
||||
@opt_vec::Empty)
|
||||
}
|
||||
|
||||
fn ty_field_imm(&self, span: span, name: ident, ty: @ast::Ty) -> ast::ty_field {
|
||||
@ -342,7 +346,7 @@ impl AstBuilder for @ExtCtxt {
|
||||
fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
|
||||
opt_vec::take_vec(
|
||||
ty_params.map(|p| self.ty_path(
|
||||
self.path_global(dummy_sp(), ~[p.ident]))))
|
||||
self.path_global(dummy_sp(), ~[p.ident]), @opt_vec::Empty)))
|
||||
}
|
||||
|
||||
fn strip_bounds(&self, generics: &Generics) -> Generics {
|
||||
|
@ -358,7 +358,8 @@ impl<'self> TraitDef<'self> {
|
||||
|
||||
// Create the type of `self`.
|
||||
let self_type = cx.ty_path(cx.path_all(span, false, ~[ type_ident ], self_lifetime,
|
||||
opt_vec::take_vec(self_ty_params)));
|
||||
opt_vec::take_vec(self_ty_params)),
|
||||
@opt_vec::Empty);
|
||||
|
||||
let doc_attr = cx.attribute(
|
||||
span,
|
||||
|
@ -65,7 +65,7 @@ impl<'self> Path<'self> {
|
||||
self_generics: &Generics)
|
||||
-> @ast::Ty {
|
||||
cx.ty_path(self.to_path(cx, span,
|
||||
self_ty, self_generics))
|
||||
self_ty, self_generics), @opt_vec::Empty)
|
||||
}
|
||||
pub fn to_path(&self,
|
||||
cx: @ExtCtxt,
|
||||
@ -144,7 +144,8 @@ impl<'self> Ty<'self> {
|
||||
}
|
||||
Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
|
||||
Self => {
|
||||
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
|
||||
cx.ty_path(self.to_path(cx, span, self_ty, self_generics),
|
||||
@opt_vec::Empty)
|
||||
}
|
||||
Tuple(ref fields) => {
|
||||
let ty = if fields.is_empty() {
|
||||
|
@ -61,7 +61,7 @@ impl gen_send for message {
|
||||
|
||||
let pipe_ty = cx.ty_path(
|
||||
path(~[this.data_name()], span)
|
||||
.add_tys(cx.ty_vars(&this.generics.ty_params)));
|
||||
.add_tys(cx.ty_vars(&this.generics.ty_params)), @opt_vec::Empty);
|
||||
let args_ast = vec::append(
|
||||
~[cx.arg(span, cx.ident_of("pipe"), pipe_ty)],
|
||||
args_ast);
|
||||
@ -117,7 +117,7 @@ impl gen_send for message {
|
||||
|
||||
let mut rty = cx.ty_path(path(~[next.data_name()],
|
||||
span)
|
||||
.add_tys(copy next_state.tys));
|
||||
.add_tys(copy next_state.tys), @opt_vec::Empty);
|
||||
if try {
|
||||
rty = cx.ty_option(rty);
|
||||
}
|
||||
@ -146,7 +146,7 @@ impl gen_send for message {
|
||||
cx.ty_path(
|
||||
path(~[this.data_name()], span)
|
||||
.add_tys(cx.ty_vars(
|
||||
&this.generics.ty_params))))],
|
||||
&this.generics.ty_params)), @opt_vec::Empty))],
|
||||
args_ast);
|
||||
|
||||
let message_args = if arg_names.len() == 0 {
|
||||
@ -192,7 +192,7 @@ impl gen_send for message {
|
||||
|
||||
fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty {
|
||||
cx.ty_path(path(~[cx.ident_of(self.name())], self.span())
|
||||
.add_tys(cx.ty_vars(&self.get_generics().ty_params)))
|
||||
.add_tys(cx.ty_vars(&self.get_generics().ty_params)), @opt_vec::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ impl to_type_decls for state {
|
||||
cx.ty_path(
|
||||
path(~[cx.ident_of(dir),
|
||||
cx.ident_of(next_name)], span)
|
||||
.add_tys(copy next_state.tys)))
|
||||
.add_tys(copy next_state.tys), @opt_vec::Empty))
|
||||
}
|
||||
None => tys
|
||||
};
|
||||
@ -279,7 +279,8 @@ impl to_type_decls for state {
|
||||
self.data_name()],
|
||||
dummy_sp())
|
||||
.add_tys(cx.ty_vars(
|
||||
&self.generics.ty_params))))),
|
||||
&self.generics.ty_params)), @opt_vec::Empty)),
|
||||
@opt_vec::Empty),
|
||||
cx.strip_bounds(&self.generics)));
|
||||
}
|
||||
else {
|
||||
@ -298,8 +299,8 @@ impl to_type_decls for state {
|
||||
self.data_name()],
|
||||
dummy_sp())
|
||||
.add_tys(cx.ty_vars_global(
|
||||
&self.generics.ty_params))),
|
||||
self.proto.buffer_ty_path(cx)])),
|
||||
&self.generics.ty_params)), @opt_vec::Empty),
|
||||
self.proto.buffer_ty_path(cx)]), @opt_vec::Empty),
|
||||
cx.strip_bounds(&self.generics)));
|
||||
};
|
||||
items
|
||||
@ -384,7 +385,7 @@ impl gen_init for protocol {
|
||||
cx.ty_path(path(~[cx.ident_of("super"),
|
||||
cx.ident_of("__Buffer")],
|
||||
copy self.span)
|
||||
.add_tys(cx.ty_vars_global(¶ms)))
|
||||
.add_tys(cx.ty_vars_global(¶ms)), @opt_vec::Empty)
|
||||
}
|
||||
|
||||
fn gen_buffer_type(&self, cx: @ExtCtxt) -> @ast::item {
|
||||
|
@ -15,6 +15,7 @@ use codemap::span;
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::build::AstBuilder;
|
||||
use ext::pipes::ast_builder::{append_types, path};
|
||||
use opt_vec;
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum direction { send, recv }
|
||||
@ -101,7 +102,7 @@ impl state_ {
|
||||
pub fn to_ty(&self, cx: @ExtCtxt) -> @ast::Ty {
|
||||
cx.ty_path
|
||||
(path(~[cx.ident_of(self.name)],self.span).add_tys(
|
||||
cx.ty_vars(&self.generics.ty_params)))
|
||||
cx.ty_vars(&self.generics.ty_params)), @opt_vec::Empty)
|
||||
}
|
||||
|
||||
/// Iterate over the states that can be reached in one message
|
||||
|
@ -680,7 +680,9 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
|
||||
})
|
||||
}
|
||||
ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(*ty))),
|
||||
ty_path(path, id) => ty_path(fld.fold_path(path), fld.new_id(id)),
|
||||
ty_path(path, bounds, id) =>
|
||||
ty_path(fld.fold_path(path),
|
||||
@bounds.map(|x| fold_ty_param_bound(x, fld)), fld.new_id(id)),
|
||||
ty_fixed_length_vec(ref mt, e) => {
|
||||
ty_fixed_length_vec(
|
||||
fold_mt(mt, fld),
|
||||
|
@ -494,7 +494,7 @@ mod test {
|
||||
idents:~[str_to_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
2),
|
||||
@opt_vec::Empty, 2),
|
||||
span:sp(4,7)},
|
||||
pat: @ast::pat{id:1,
|
||||
node: ast::pat_ident(ast::bind_infer,
|
||||
@ -530,7 +530,7 @@ mod test {
|
||||
idents:~[str_to_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
2),
|
||||
@opt_vec::Empty, 2),
|
||||
span:sp(10,13)},
|
||||
pat: @ast::pat{id:1, // fixme
|
||||
node: ast::pat_ident(
|
||||
|
@ -46,7 +46,6 @@ pub enum ObsoleteSyntax {
|
||||
ObsoleteUnsafeBlock,
|
||||
ObsoleteUnenforcedBound,
|
||||
ObsoleteImplSyntax,
|
||||
ObsoleteTraitBoundSeparator,
|
||||
ObsoleteMutOwnedPointer,
|
||||
ObsoleteMutVector,
|
||||
ObsoleteImplVisibility,
|
||||
@ -143,10 +142,6 @@ impl Parser {
|
||||
"colon-separated impl syntax",
|
||||
"write `impl Trait for Type`"
|
||||
),
|
||||
ObsoleteTraitBoundSeparator => (
|
||||
"space-separated trait bounds",
|
||||
"write `+` between trait bounds"
|
||||
),
|
||||
ObsoleteMutOwnedPointer => (
|
||||
"const or mutable owned pointer",
|
||||
"mutability inherits through `~` pointers; place the `~` box
|
||||
|
@ -75,7 +75,7 @@ use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator};
|
||||
use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove, ObsoleteSwap};
|
||||
use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds};
|
||||
use parse::obsolete::{ObsoleteUnsafeBlock, ObsoleteImplSyntax};
|
||||
use parse::obsolete::{ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer};
|
||||
use parse::obsolete::{ObsoleteMutOwnedPointer};
|
||||
use parse::obsolete::{ObsoleteMutVector, ObsoleteImplVisibility};
|
||||
use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern};
|
||||
use parse::obsolete::{ObsoletePostFnTySigil};
|
||||
@ -710,8 +710,8 @@ impl Parser {
|
||||
} else if *self.token == token::MOD_SEP
|
||||
|| is_ident_or_path(self.token) {
|
||||
// NAMED TYPE
|
||||
let path = self.parse_path_with_tps(false);
|
||||
ty_path(path, self.get_id())
|
||||
let (path, bounds) = self.parse_type_path();
|
||||
ty_path(path, @bounds, self.get_id())
|
||||
} else {
|
||||
self.fatal(fmt!("expected type, found token %?",
|
||||
*self.token));
|
||||
@ -974,10 +974,8 @@ impl Parser {
|
||||
types: ~[] }
|
||||
}
|
||||
|
||||
// parse a path optionally with type parameters. If 'colons'
|
||||
// is true, then type parameters must be preceded by colons,
|
||||
// as in a::t::<t1,t2>
|
||||
pub fn parse_path_with_tps(&self, colons: bool) -> @ast::Path {
|
||||
pub fn parse_bounded_path_with_tps(&self, colons: bool,
|
||||
before_tps: Option<&fn()>) -> @ast::Path {
|
||||
debug!("parse_path_with_tps(colons=%b)", colons);
|
||||
|
||||
maybe_whole!(self, nt_path);
|
||||
@ -987,6 +985,10 @@ impl Parser {
|
||||
return path;
|
||||
}
|
||||
|
||||
// If the path might have bounds on it, they should be parsed before
|
||||
// the parameters, e.g. module::TraitName:B1+B2<T>
|
||||
before_tps.map_consume(|callback| callback());
|
||||
|
||||
// Parse the (obsolete) trailing region parameter, if any, which will
|
||||
// be written "foo/&x"
|
||||
let rp_slash = {
|
||||
@ -1038,6 +1040,25 @@ impl Parser {
|
||||
.. copy *path }
|
||||
}
|
||||
|
||||
// parse a path optionally with type parameters. If 'colons'
|
||||
// is true, then type parameters must be preceded by colons,
|
||||
// as in a::t::<t1,t2>
|
||||
pub fn parse_path_with_tps(&self, colons: bool) -> @ast::Path {
|
||||
self.parse_bounded_path_with_tps(colons, None)
|
||||
}
|
||||
|
||||
// Like the above, but can also parse kind bounds in the case of a
|
||||
// path to be used as a type that might be a trait.
|
||||
pub fn parse_type_path(&self) -> (@ast::Path, OptVec<TyParamBound>) {
|
||||
let mut bounds = opt_vec::Empty;
|
||||
let path = self.parse_bounded_path_with_tps(false, Some(|| {
|
||||
// Note: this closure might not even get called in the case of a
|
||||
// macro-generated path. But that's the macro parser's job.
|
||||
bounds = self.parse_optional_ty_param_bounds();
|
||||
}));
|
||||
(path, bounds)
|
||||
}
|
||||
|
||||
/// parses 0 or 1 lifetime
|
||||
pub fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> {
|
||||
match *self.token {
|
||||
@ -2847,16 +2868,6 @@ impl Parser {
|
||||
spanned(lo, hi, bloc)
|
||||
}
|
||||
|
||||
fn mk_ty_path(&self, i: ident) -> @Ty {
|
||||
@Ty {
|
||||
id: self.get_id(),
|
||||
node: ty_path(
|
||||
ident_to_path(*self.last_span, i),
|
||||
self.get_id()),
|
||||
span: *self.last_span,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_optional_purity(&self) -> ast::purity {
|
||||
if self.eat_keyword(keywords::Pure) {
|
||||
self.obsolete(*self.last_span, ObsoletePurity);
|
||||
@ -2921,13 +2932,8 @@ impl Parser {
|
||||
_ => break,
|
||||
}
|
||||
|
||||
if self.eat(&token::BINOP(token::PLUS)) {
|
||||
loop;
|
||||
}
|
||||
|
||||
if is_ident_or_path(self.token) {
|
||||
self.obsolete(*self.span,
|
||||
ObsoleteTraitBoundSeparator);
|
||||
if !self.eat(&token::BINOP(token::PLUS)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3284,14 +3290,19 @@ impl Parser {
|
||||
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
|
||||
// New-style trait. Reinterpret the type as a trait.
|
||||
let opt_trait_ref = match ty.node {
|
||||
ty_path(path, node_id) => {
|
||||
ty_path(path, @opt_vec::Empty, node_id) => {
|
||||
Some(@trait_ref {
|
||||
path: path,
|
||||
ref_id: node_id
|
||||
})
|
||||
}
|
||||
ty_path(*) => {
|
||||
self.span_err(ty.span,
|
||||
"bounded traits are only valid in type position");
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
self.span_err(*self.span, "not a trait");
|
||||
self.span_err(ty.span, "not a trait");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
@ -422,7 +422,7 @@ pub fn print_type(s: @ps, ty: @ast::Ty) {
|
||||
f.purity, f.onceness, &f.decl, None,
|
||||
Some(&generics), None);
|
||||
}
|
||||
ast::ty_path(path, _) => print_path(s, path, false),
|
||||
ast::ty_path(path, bounds, _) => print_bounded_path(s, path, bounds),
|
||||
ast::ty_fixed_length_vec(ref mt, v) => {
|
||||
word(s.s, "[");
|
||||
match mt.mutbl {
|
||||
@ -1483,7 +1483,8 @@ pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) {
|
||||
print_expr(s, coll);
|
||||
}
|
||||
|
||||
pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) {
|
||||
fn print_path_(s: @ps, path: @ast::Path, colons_before_params: bool,
|
||||
opt_bounds: Option<@OptVec<ast::TyParamBound>>) {
|
||||
maybe_print_comment(s, path.span.lo);
|
||||
if path.global { word(s.s, "::"); }
|
||||
let mut first = true;
|
||||
@ -1491,6 +1492,9 @@ pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) {
|
||||
if first { first = false; } else { word(s.s, "::"); }
|
||||
print_ident(s, *id);
|
||||
}
|
||||
do opt_bounds.map_consume |bounds| {
|
||||
print_bounds(s, bounds);
|
||||
};
|
||||
if path.rp.is_some() || !path.types.is_empty() {
|
||||
if colons_before_params { word(s.s, "::"); }
|
||||
|
||||
@ -1511,6 +1515,15 @@ pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) {
|
||||
print_path_(s, path, colons_before_params, None)
|
||||
}
|
||||
|
||||
pub fn print_bounded_path(s: @ps, path: @ast::Path,
|
||||
bounds: @OptVec<ast::TyParamBound>) {
|
||||
print_path_(s, path, false, Some(bounds))
|
||||
}
|
||||
|
||||
pub fn print_irrefutable_pat(s: @ps, pat: @ast::pat) {
|
||||
print_pat(s, pat, false)
|
||||
}
|
||||
|
@ -247,13 +247,17 @@ pub fn visit_ty<E: Copy>(t: @Ty, (e, v): (E, vt<E>)) {
|
||||
},
|
||||
ty_closure(ref f) => {
|
||||
for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); }
|
||||
(v.visit_ty)(f.decl.output, (e, v));
|
||||
(v.visit_ty)(f.decl.output, (copy e, v));
|
||||
visit_ty_param_bounds(&f.bounds, (e, v));
|
||||
},
|
||||
ty_bare_fn(ref f) => {
|
||||
for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); }
|
||||
(v.visit_ty)(f.decl.output, (e, v));
|
||||
},
|
||||
ty_path(p, _) => visit_path(p, (e, v)),
|
||||
ty_path(p, bounds, _) => {
|
||||
visit_path(p, (copy e, v));
|
||||
visit_ty_param_bounds(bounds, (e, v));
|
||||
},
|
||||
ty_fixed_length_vec(ref mt, ex) => {
|
||||
(v.visit_ty)(mt.ty, (copy e, v));
|
||||
(v.visit_expr)(ex, (copy e, v));
|
||||
@ -328,7 +332,7 @@ pub fn visit_foreign_item<E: Copy>(ni: @foreign_item, (e, v): (E, vt<E>)) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_ty_param_bounds<E: Copy>(bounds: @OptVec<TyParamBound>,
|
||||
pub fn visit_ty_param_bounds<E: Copy>(bounds: &OptVec<TyParamBound>,
|
||||
(e, v): (E, vt<E>)) {
|
||||
for bounds.each |bound| {
|
||||
match *bound {
|
||||
|
Loading…
x
Reference in New Issue
Block a user