diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9c49c1638bf..a3d2fe96b5d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -123,13 +123,11 @@ const crate_node_id: node_id = 0; #[auto_serialize] #[auto_deserialize] -enum ty_param_bound { - bound_copy, - bound_send, - bound_const, - bound_owned, - bound_trait(@Ty), -} +// The AST represents all type param bounds as types. +// typeck::collect::compute_bounds matches these against +// the "special" built-in traits (see middle::lang_items) and +// detects Copy, Send, Owned, and Const. +enum ty_param_bound = @Ty; #[auto_serialize] #[auto_deserialize] diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs index 7e5e68ffff9..47e61c26f38 100644 --- a/src/libsyntax/ext/auto_serialize.rs +++ b/src/libsyntax/ext/auto_serialize.rs @@ -227,7 +227,7 @@ priv impl ext_ctxt { path: @ast::path, bounds: @~[ast::ty_param_bound] ) -> ast::ty_param { - let bound = ast::bound_trait(@{ + let bound = ast::ty_param_bound(@{ id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: span, @@ -366,7 +366,7 @@ fn mk_impl( let mut trait_tps = vec::append( ~[ty_param], do tps.map |tp| { - let t_bound = ast::bound_trait(@{ + let t_bound = ast::ty_param_bound(@{ id: cx.next_id(), node: ast::ty_path(path, cx.next_id()), span: span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 564debefa25..311928dd4e0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -131,10 +131,7 @@ fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl { } fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound { - match tpb { - bound_copy | bound_send | bound_const | bound_owned => tpb, - bound_trait(ty) => bound_trait(fld.fold_ty(ty)) - } + ty_param_bound(fld.fold_ty(*tpb)) } fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1ee683bdd08..925da063ca6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -24,8 +24,7 @@ use obsolete::{ }; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move, - bitand, bitor, bitxor, blk, blk_check_mode, bound_const, - bound_copy, bound_send, bound_trait, bound_owned, box, by_copy, + bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy, by_move, by_ref, by_val, capture_clause, capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item, class_immutable, class_mutable, @@ -2295,19 +2294,20 @@ impl Parser { return spanned(lo, hi, bloc); } + fn mk_ty_path(i: ident) -> @Ty { + @{id: self.get_id(), node: ty_path( + ident_to_path(copy self.last_span, i), + self.get_id()), span: self.last_span} + } + fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { let mut bounds = ~[]; if self.eat(token::COLON) { while is_ident(self.token) { if is_ident(self.token) { - // XXX: temporary until kinds become traits let maybe_bound = match self.token { token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { - ~"Send" => Some(bound_send), - ~"Copy" => Some(bound_copy), - ~"Const" => Some(bound_const), - ~"Owned" => Some(bound_owned), ~"send" | ~"copy" @@ -2317,7 +2317,7 @@ impl Parser { ObsoleteLowerCaseKindBounds); // Bogus value, but doesn't matter, since // is an error - Some(bound_send) + Some(ty_param_bound(self.mk_ty_path(sid))) } _ => None @@ -2332,11 +2332,11 @@ impl Parser { bounds.push(bound); } None => { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } else { - bounds.push(bound_trait(self.parse_ty(false))); + bounds.push(ty_param_bound(self.parse_ty(false))); } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 807a78b3122..909f59552d4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1704,17 +1704,11 @@ fn print_arg_mode(s: ps, m: ast::mode) { } fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) { - if vec::len(*bounds) > 0u { + if bounds.is_not_empty() { word(s.s, ~":"); for vec::each(*bounds) |bound| { nbsp(s); - match *bound { - ast::bound_copy => word(s.s, ~"Copy"), - ast::bound_send => word(s.s, ~"Send"), - ast::bound_const => word(s.s, ~"Const"), - ast::bound_owned => word(s.s, ~"Owned"), - ast::bound_trait(t) => print_type(s, t) - } + print_type(s, **bound); } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 32fcbdfc758..b45af2d4ae8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -264,10 +264,7 @@ fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { fn visit_ty_param_bounds(bounds: @~[ty_param_bound], e: E, v: vt) { for vec::each(*bounds) |bound| { - match *bound { - bound_trait(t) => v.visit_ty(t, e, v), - bound_copy | bound_send | bound_const | bound_owned => () - } + v.visit_ty(**bound, e, v) } } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 33b56d7fabe..3d2cd6a621c 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -9,9 +9,9 @@ use middle::pat_util::{pat_bindings}; use syntax::ast::{_mod, add, arm}; use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value}; use syntax::ast::{bitand, bitor, bitxor}; -use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send}; -use syntax::ast::{bound_trait, binding_mode, capture_clause, class_ctor}; -use syntax::ast::{class_dtor, crate, crate_num, decl_item}; +use syntax::ast::{binding_mode, blk, + capture_clause, class_ctor, class_dtor}; +use syntax::ast::{crate, crate_num, decl_item}; use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn}; use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod}; use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param}; @@ -39,6 +39,7 @@ use syntax::ast::{trait_ref, tuple_variant_kind, Ty, ty_bool, ty_char}; use syntax::ast::{ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16, ty_i32}; use syntax::ast::{ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str, ty_u}; use syntax::ast::{ty_u16, ty_u32, ty_u64, ty_u8, ty_uint, type_value_ns}; +use syntax::ast::{ty_param_bound}; use syntax::ast::{variant, view_item, view_item_export, view_item_import}; use syntax::ast::{view_item_use, view_path_glob, view_path_list}; use syntax::ast::{view_path_simple, visibility, anonymous, named}; @@ -3764,14 +3765,7 @@ impl Resolver { visitor: ResolveVisitor) { for type_parameters.each |type_parameter| { for type_parameter.bounds.each |bound| { - match *bound { - bound_copy | bound_send | bound_const | bound_owned => { - // Nothing to do. - } - bound_trait(trait_type) => { - self.resolve_type(trait_type, visitor); - } - } + self.resolve_type(**bound, visitor); } } } @@ -4088,7 +4082,7 @@ impl Resolver { let mut result_def = None; // First, check to see whether the name is a primitive type. - if path.idents.len() == 1u { + if path.idents.len() == 1 { let name = path.idents.last(); match self.primitive_type_table diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index a5390d8f293..e12104a21da 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -707,28 +707,41 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item) } } +// Translate the AST's notion of ty param bounds (which are just newtyped Tys) +// to ty's notion of ty param bounds, which can either be user-defined traits, +// or one of the four built-in traits (formerly known as kinds): Const, Copy, +// Owned, and Send. fn compute_bounds(ccx: @crate_ctxt, ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds { @do vec::flat_map(*ast_bounds) |b| { - match *b { - ast::bound_send => ~[ty::bound_send], - ast::bound_copy => ~[ty::bound_copy], - ast::bound_const => ~[ty::bound_const], - ast::bound_owned => ~[ty::bound_owned], - ast::bound_trait(t) => { - let ity = ast_ty_to_ty(ccx, empty_rscope, t); - match ty::get(ity).sty { - ty::ty_trait(*) => { - ~[ty::bound_trait(ity)] - } - _ => { - ccx.tcx.sess.span_err( - t.span, ~"type parameter bounds must be \ - trait types"); - ~[] - } + let li = &ccx.tcx.lang_items; + let ity = ast_ty_to_ty(ccx, empty_rscope, **b); + match ty::get(ity).sty { + ty::ty_trait(did, _, _) => { + let d = Some(did); + if d == li.send_trait { + ~[ty::bound_send] + } + else if d == li.copy_trait { + ~[ty::bound_copy] + } + else if d == li.const_trait { + ~[ty::bound_const] + } + else if d == li.owned_trait { + ~[ty::bound_owned] + } + else { + // Must be a user-defined trait + ~[ty::bound_trait(ity)] + } + } + _ => { + ccx.tcx.sess.span_err( + (*b).span, ~"type parameter bounds must be \ + trait types"); + ~[] } - } } } } diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs index 80a36945097..f5bd208f00f 100644 --- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs +++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs @@ -5,7 +5,7 @@ extern mod core; -fn last(v: ~[const T]) -> core::Option { +fn last(v: ~[const &T]) -> core::Option { fail; } diff --git a/src/test/run-pass/issue-2284.rs b/src/test/run-pass/issue-2284.rs index 3689c42253b..c2c4c03fb8f 100644 --- a/src/test/run-pass/issue-2284.rs +++ b/src/test/run-pass/issue-2284.rs @@ -1,4 +1,3 @@ -// xfail-test trait Send { fn f(); }