Simplify the AST representation of ty param bounds
Change ast::ty_param_bound so that all ty param bounds are represented as traits, with no special cases for Copy/Send/Owned/Const. typeck::collect generates the special cases. A consequence of this is that code using the #[no_core] attribute can't use the Copy kind/trait. Probably not a big deal? As a side effect, any user-defined traits that happen to be called Copy, etc. in the same module override the built-in Copy trait. r=nmatsakis Closes #2284
This commit is contained in:
parent
42c05fe642
commit
46d4bbbae4
10 changed files with 59 additions and 67 deletions
|
@ -123,13 +123,11 @@ const crate_node_id: node_id = 0;
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
#[auto_deserialize]
|
#[auto_deserialize]
|
||||||
enum ty_param_bound {
|
// The AST represents all type param bounds as types.
|
||||||
bound_copy,
|
// typeck::collect::compute_bounds matches these against
|
||||||
bound_send,
|
// the "special" built-in traits (see middle::lang_items) and
|
||||||
bound_const,
|
// detects Copy, Send, Owned, and Const.
|
||||||
bound_owned,
|
enum ty_param_bound = @Ty;
|
||||||
bound_trait(@Ty),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[auto_serialize]
|
#[auto_serialize]
|
||||||
#[auto_deserialize]
|
#[auto_deserialize]
|
||||||
|
|
|
@ -227,7 +227,7 @@ priv impl ext_ctxt {
|
||||||
path: @ast::path,
|
path: @ast::path,
|
||||||
bounds: @~[ast::ty_param_bound]
|
bounds: @~[ast::ty_param_bound]
|
||||||
) -> ast::ty_param {
|
) -> ast::ty_param {
|
||||||
let bound = ast::bound_trait(@{
|
let bound = ast::ty_param_bound(@{
|
||||||
id: self.next_id(),
|
id: self.next_id(),
|
||||||
node: ast::ty_path(path, self.next_id()),
|
node: ast::ty_path(path, self.next_id()),
|
||||||
span: span,
|
span: span,
|
||||||
|
@ -366,7 +366,7 @@ fn mk_impl(
|
||||||
let mut trait_tps = vec::append(
|
let mut trait_tps = vec::append(
|
||||||
~[ty_param],
|
~[ty_param],
|
||||||
do tps.map |tp| {
|
do tps.map |tp| {
|
||||||
let t_bound = ast::bound_trait(@{
|
let t_bound = ast::ty_param_bound(@{
|
||||||
id: cx.next_id(),
|
id: cx.next_id(),
|
||||||
node: ast::ty_path(path, cx.next_id()),
|
node: ast::ty_path(path, cx.next_id()),
|
||||||
span: span,
|
span: span,
|
||||||
|
|
|
@ -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 {
|
fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound {
|
||||||
match tpb {
|
ty_param_bound(fld.fold_ty(*tpb))
|
||||||
bound_copy | bound_send | bound_const | bound_owned => tpb,
|
|
||||||
bound_trait(ty) => bound_trait(fld.fold_ty(ty))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param {
|
fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param {
|
||||||
|
|
|
@ -24,8 +24,7 @@ use obsolete::{
|
||||||
};
|
};
|
||||||
use ast::{_mod, add, arg, arm, attribute,
|
use ast::{_mod, add, arg, arm, attribute,
|
||||||
bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
|
bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
|
||||||
bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
|
bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy,
|
||||||
bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
|
|
||||||
by_move, by_ref, by_val, capture_clause,
|
by_move, by_ref, by_val, capture_clause,
|
||||||
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
|
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
|
||||||
class_immutable, class_mutable,
|
class_immutable, class_mutable,
|
||||||
|
@ -2295,19 +2294,20 @@ impl Parser {
|
||||||
return spanned(lo, hi, bloc);
|
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] {
|
fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
|
||||||
let mut bounds = ~[];
|
let mut bounds = ~[];
|
||||||
if self.eat(token::COLON) {
|
if self.eat(token::COLON) {
|
||||||
while is_ident(self.token) {
|
while is_ident(self.token) {
|
||||||
if is_ident(self.token) {
|
if is_ident(self.token) {
|
||||||
// XXX: temporary until kinds become traits
|
|
||||||
let maybe_bound = match self.token {
|
let maybe_bound = match self.token {
|
||||||
token::IDENT(copy sid, _) => {
|
token::IDENT(copy sid, _) => {
|
||||||
match *self.id_to_str(sid) {
|
match *self.id_to_str(sid) {
|
||||||
~"Send" => Some(bound_send),
|
|
||||||
~"Copy" => Some(bound_copy),
|
|
||||||
~"Const" => Some(bound_const),
|
|
||||||
~"Owned" => Some(bound_owned),
|
|
||||||
|
|
||||||
~"send"
|
~"send"
|
||||||
| ~"copy"
|
| ~"copy"
|
||||||
|
@ -2317,7 +2317,7 @@ impl Parser {
|
||||||
ObsoleteLowerCaseKindBounds);
|
ObsoleteLowerCaseKindBounds);
|
||||||
// Bogus value, but doesn't matter, since
|
// Bogus value, but doesn't matter, since
|
||||||
// is an error
|
// is an error
|
||||||
Some(bound_send)
|
Some(ty_param_bound(self.mk_ty_path(sid)))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => None
|
_ => None
|
||||||
|
@ -2332,11 +2332,11 @@ impl Parser {
|
||||||
bounds.push(bound);
|
bounds.push(bound);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
bounds.push(bound_trait(self.parse_ty(false)));
|
bounds.push(ty_param_bound(self.parse_ty(false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bounds.push(bound_trait(self.parse_ty(false)));
|
bounds.push(ty_param_bound(self.parse_ty(false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1704,17 +1704,11 @@ fn print_arg_mode(s: ps, m: ast::mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
|
fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
|
||||||
if vec::len(*bounds) > 0u {
|
if bounds.is_not_empty() {
|
||||||
word(s.s, ~":");
|
word(s.s, ~":");
|
||||||
for vec::each(*bounds) |bound| {
|
for vec::each(*bounds) |bound| {
|
||||||
nbsp(s);
|
nbsp(s);
|
||||||
match *bound {
|
print_type(s, **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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,10 +264,7 @@ fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
|
||||||
|
|
||||||
fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
|
fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
|
||||||
for vec::each(*bounds) |bound| {
|
for vec::each(*bounds) |bound| {
|
||||||
match *bound {
|
v.visit_ty(**bound, e, v)
|
||||||
bound_trait(t) => v.visit_ty(t, e, v),
|
|
||||||
bound_copy | bound_send | bound_const | bound_owned => ()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ use middle::pat_util::{pat_bindings};
|
||||||
use syntax::ast::{_mod, add, arm};
|
use syntax::ast::{_mod, add, arm};
|
||||||
use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value};
|
use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value};
|
||||||
use syntax::ast::{bitand, bitor, bitxor};
|
use syntax::ast::{bitand, bitor, bitxor};
|
||||||
use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
|
use syntax::ast::{binding_mode, blk,
|
||||||
use syntax::ast::{bound_trait, binding_mode, capture_clause, class_ctor};
|
capture_clause, class_ctor, class_dtor};
|
||||||
use syntax::ast::{class_dtor, crate, crate_num, decl_item};
|
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, 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_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};
|
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_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_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_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::{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_item_use, view_path_glob, view_path_list};
|
||||||
use syntax::ast::{view_path_simple, visibility, anonymous, named};
|
use syntax::ast::{view_path_simple, visibility, anonymous, named};
|
||||||
|
@ -3764,14 +3765,7 @@ impl Resolver {
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
for type_parameters.each |type_parameter| {
|
for type_parameters.each |type_parameter| {
|
||||||
for type_parameter.bounds.each |bound| {
|
for type_parameter.bounds.each |bound| {
|
||||||
match *bound {
|
self.resolve_type(**bound, visitor);
|
||||||
bound_copy | bound_send | bound_const | bound_owned => {
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
|
||||||
bound_trait(trait_type) => {
|
|
||||||
self.resolve_type(trait_type, visitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4088,7 +4082,7 @@ impl Resolver {
|
||||||
let mut result_def = None;
|
let mut result_def = None;
|
||||||
|
|
||||||
// First, check to see whether the name is a primitive type.
|
// 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();
|
let name = path.idents.last();
|
||||||
|
|
||||||
match self.primitive_type_table
|
match self.primitive_type_table
|
||||||
|
|
|
@ -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,
|
fn compute_bounds(ccx: @crate_ctxt,
|
||||||
ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds {
|
ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds {
|
||||||
@do vec::flat_map(*ast_bounds) |b| {
|
@do vec::flat_map(*ast_bounds) |b| {
|
||||||
match *b {
|
let li = &ccx.tcx.lang_items;
|
||||||
ast::bound_send => ~[ty::bound_send],
|
let ity = ast_ty_to_ty(ccx, empty_rscope, **b);
|
||||||
ast::bound_copy => ~[ty::bound_copy],
|
match ty::get(ity).sty {
|
||||||
ast::bound_const => ~[ty::bound_const],
|
ty::ty_trait(did, _, _) => {
|
||||||
ast::bound_owned => ~[ty::bound_owned],
|
let d = Some(did);
|
||||||
ast::bound_trait(t) => {
|
if d == li.send_trait {
|
||||||
let ity = ast_ty_to_ty(ccx, empty_rscope, t);
|
~[ty::bound_send]
|
||||||
match ty::get(ity).sty {
|
}
|
||||||
ty::ty_trait(*) => {
|
else if d == li.copy_trait {
|
||||||
~[ty::bound_trait(ity)]
|
~[ty::bound_copy]
|
||||||
}
|
}
|
||||||
_ => {
|
else if d == li.const_trait {
|
||||||
ccx.tcx.sess.span_err(
|
~[ty::bound_const]
|
||||||
t.span, ~"type parameter bounds must be \
|
}
|
||||||
trait types");
|
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");
|
||||||
|
~[]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
extern mod core;
|
extern mod core;
|
||||||
|
|
||||||
fn last<T: Copy>(v: ~[const T]) -> core::Option<T> {
|
fn last<T>(v: ~[const &T]) -> core::Option<T> {
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// xfail-test
|
|
||||||
trait Send {
|
trait Send {
|
||||||
fn f();
|
fn f();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue