Change DST syntax: type -> Sized?
closes #13367 [breaking-change] Use `Sized?` to indicate a dynamically sized type parameter or trait (used to be `type`). E.g., ``` trait Tr for Sized? {} fn foo<Sized? X: Share>(x: X) {} ```
This commit is contained in:
parent
6959931498
commit
a0cfda53c4
@ -109,12 +109,12 @@ fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
|
||||
.map(|x| *x).collect();
|
||||
ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
|
||||
}
|
||||
ast::ItemTrait(ref a, b, ref c, ref methods) => {
|
||||
ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
|
||||
let methods = methods.iter()
|
||||
.filter(|m| trait_method_in_cfg(cx, *m) )
|
||||
.map(|x| (*x).clone())
|
||||
.collect();
|
||||
ast::ItemTrait((*a).clone(), b, (*c).clone(), methods)
|
||||
ast::ItemTrait((*a).clone(), (*b).clone(), (*c).clone(), methods)
|
||||
}
|
||||
ast::ItemStruct(ref def, ref generics) => {
|
||||
ast::ItemStruct(fold_struct(cx, &**def), generics.clone())
|
||||
|
@ -164,19 +164,6 @@ fn item_visibility(item: ebml::Doc) -> ast::Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
fn item_sized(item: ebml::Doc) -> ast::Sized {
|
||||
match reader::maybe_get_doc(item, tag_items_data_item_sized) {
|
||||
None => ast::StaticSize,
|
||||
Some(sized_doc) => {
|
||||
match reader::doc_as_u8(sized_doc) as char {
|
||||
'd' => ast::DynSize,
|
||||
's' => ast::StaticSize,
|
||||
_ => fail!("unknown sized-ness character")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn item_method_sort(item: ebml::Doc) -> char {
|
||||
let mut ret = 'r';
|
||||
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
|
||||
@ -393,7 +380,6 @@ pub fn get_trait_def(cdata: Cmd,
|
||||
let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
|
||||
tag_items_data_item_ty_param_bounds);
|
||||
let rp_defs = item_region_param_defs(item_doc, cdata);
|
||||
let sized = item_sized(item_doc);
|
||||
let mut bounds = ty::empty_builtin_bounds();
|
||||
// Collect the builtin bounds from the encoded supertraits.
|
||||
// FIXME(#8559): They should be encoded directly.
|
||||
@ -405,12 +391,6 @@ pub fn get_trait_def(cdata: Cmd,
|
||||
});
|
||||
true
|
||||
});
|
||||
// Turn sized into a bound, FIXME(#8559).
|
||||
if sized == ast::StaticSize {
|
||||
tcx.lang_items.to_builtin_kind(tcx.lang_items.sized_trait().unwrap()).map(|bound| {
|
||||
bounds.add(bound);
|
||||
});
|
||||
}
|
||||
|
||||
ty::TraitDef {
|
||||
generics: ty::Generics {types: tp_defs,
|
||||
|
@ -881,16 +881,6 @@ fn encode_extension_implementations(ecx: &EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
|
||||
ebml_w.start_tag(tag_items_data_item_sized);
|
||||
let ch = match sized {
|
||||
DynSize => 'd',
|
||||
StaticSize => 's',
|
||||
};
|
||||
ebml_w.wr_str(str::from_char(ch).as_slice());
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
|
||||
stab_opt.map(|stab| {
|
||||
ebml_w.start_tag(tag_items_data_item_stability);
|
||||
@ -1149,7 +1139,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
ast_method)
|
||||
}
|
||||
}
|
||||
ItemTrait(_, sized, ref super_traits, ref ms) => {
|
||||
ItemTrait(_, _, ref super_traits, ref ms) => {
|
||||
add_to_index(item, ebml_w, index);
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id(ebml_w, def_id);
|
||||
@ -1163,9 +1153,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
|
||||
encode_name(ebml_w, item.ident.name);
|
||||
encode_attributes(ebml_w, item.attrs.as_slice());
|
||||
// When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
|
||||
// should no longer need this ugly little hack either.
|
||||
encode_sized(ebml_w, sized);
|
||||
encode_visibility(ebml_w, vis);
|
||||
encode_stability(ebml_w, stab);
|
||||
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
|
||||
|
@ -3598,6 +3598,7 @@ impl<'a> Resolver<'a> {
|
||||
item.id,
|
||||
ItemRibKind),
|
||||
|this| {
|
||||
this.resolve_type_parameters(&generics.ty_params);
|
||||
visit::walk_item(this, item, ());
|
||||
});
|
||||
}
|
||||
@ -3623,7 +3624,7 @@ impl<'a> Resolver<'a> {
|
||||
methods.as_slice());
|
||||
}
|
||||
|
||||
ItemTrait(ref generics, _, ref traits, ref methods) => {
|
||||
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
|
||||
// Create a new rib for the self type.
|
||||
let self_type_rib = Rib::new(ItemRibKind);
|
||||
|
||||
@ -3645,6 +3646,12 @@ impl<'a> Resolver<'a> {
|
||||
for trt in traits.iter() {
|
||||
this.resolve_trait_reference(item.id, trt, TraitDerivation);
|
||||
}
|
||||
match unbound {
|
||||
&Some(ast::TraitTyParamBound(ref tpb)) => {
|
||||
this.resolve_trait_reference(item.id, tpb, TraitDerivation);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
for method in (*methods).iter() {
|
||||
// Create a new rib for the method-specific type
|
||||
@ -3856,11 +3863,15 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn resolve_type_parameters(&mut self,
|
||||
type_parameters: &OwnedSlice<TyParam>) {
|
||||
type_parameters: &OwnedSlice<TyParam>) {
|
||||
for type_parameter in type_parameters.iter() {
|
||||
for bound in type_parameter.bounds.iter() {
|
||||
self.resolve_type_parameter_bound(type_parameter.id, bound);
|
||||
}
|
||||
match &type_parameter.unbound {
|
||||
&Some(ref unbound) => self.resolve_type_parameter_bound(type_parameter.id, unbound),
|
||||
&None => {}
|
||||
}
|
||||
match type_parameter.default {
|
||||
Some(ref ty) => self.resolve_type(&**ty),
|
||||
None => {}
|
||||
@ -3887,9 +3898,9 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn resolve_trait_reference(&mut self,
|
||||
id: NodeId,
|
||||
trait_reference: &TraitRef,
|
||||
reference_type: TraitReferenceType) {
|
||||
id: NodeId,
|
||||
trait_reference: &TraitRef,
|
||||
reference_type: TraitReferenceType) {
|
||||
match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
|
||||
None => {
|
||||
let path_str = self.path_idents_to_str(&trait_reference.path);
|
||||
|
@ -692,9 +692,9 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let (generics, sized, supertraits) = match it.node {
|
||||
ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
|
||||
(generics, sized, supertraits)
|
||||
let (generics, unbound, supertraits) = match it.node {
|
||||
ast::ItemTrait(ref generics, ref unbound, ref supertraits, _) => {
|
||||
(generics, unbound, supertraits)
|
||||
}
|
||||
ref s => {
|
||||
tcx.sess.span_bug(
|
||||
@ -711,7 +711,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
generics);
|
||||
|
||||
let builtin_bounds =
|
||||
ensure_supertraits(ccx, it.id, it.span, supertraits, sized);
|
||||
ensure_supertraits(ccx, it.id, it.span, supertraits, unbound);
|
||||
|
||||
let substs = mk_item_substs(ccx, &ty_generics);
|
||||
let trait_def = Rc::new(ty::TraitDef {
|
||||
@ -759,7 +759,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
id: ast::NodeId,
|
||||
sp: codemap::Span,
|
||||
ast_trait_refs: &Vec<ast::TraitRef>,
|
||||
sized: ast::Sized)
|
||||
unbound: &Option<ast::TyParamBound>)
|
||||
-> ty::BuiltinBounds
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
@ -798,15 +798,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
}
|
||||
}
|
||||
|
||||
if sized == ast::StaticSize {
|
||||
match tcx.lang_items.require(SizedTraitLangItem) {
|
||||
Ok(def_id) => {
|
||||
ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
|
||||
}
|
||||
Err(s) => tcx.sess.err(s.as_slice()),
|
||||
};
|
||||
}
|
||||
|
||||
add_unsized_bound(ccx, unbound, &mut bounds, "trait", sp);
|
||||
tcx.supertraits.borrow_mut().insert(local_def(id),
|
||||
Rc::new(ty_trait_refs));
|
||||
bounds
|
||||
@ -974,6 +966,43 @@ fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
|
||||
&generics.ty_params, base_generics)
|
||||
}
|
||||
|
||||
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
|
||||
fn add_unsized_bound(ccx: &CrateCtxt,
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
bounds: &mut ty::BuiltinBounds,
|
||||
desc: &str,
|
||||
span: Span) {
|
||||
let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
|
||||
match unbound {
|
||||
&Some(TraitTyParamBound(ref tpb)) => {
|
||||
// #FIXME(8559) currently requires the unbound to be built-in.
|
||||
let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
|
||||
match kind_id {
|
||||
Ok(kind_id) if trait_def_id != kind_id => {
|
||||
ccx.tcx.sess.span_warn(span,
|
||||
format!("default bound relaxed \
|
||||
for a {}, but this does \
|
||||
nothing because the given \
|
||||
bound is not a default. \
|
||||
Only `Sized?` is supported.",
|
||||
desc).as_slice());
|
||||
ty::try_add_builtin_trait(ccx.tcx,
|
||||
kind_id,
|
||||
bounds);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ if kind_id.is_ok() => {
|
||||
ty::try_add_builtin_trait(ccx.tcx,
|
||||
kind_id.unwrap(),
|
||||
bounds);
|
||||
}
|
||||
// No lang item for Sized, so we can't add it as a bound.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_generics(ccx: &CrateCtxt,
|
||||
space: subst::ParamSpace,
|
||||
lifetimes: &Vec<ast::Lifetime>,
|
||||
@ -1016,7 +1045,7 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||
let bounds = Rc::new(compute_bounds(ccx,
|
||||
param_ty,
|
||||
¶m.bounds,
|
||||
param.sized,
|
||||
¶m.unbound,
|
||||
param.ident,
|
||||
param.span));
|
||||
let default = param.default.map(|path| {
|
||||
@ -1056,7 +1085,7 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||
ccx: &CrateCtxt,
|
||||
param_ty: ty::ParamTy,
|
||||
ast_bounds: &OwnedSlice<ast::TyParamBound>,
|
||||
sized: ast::Sized,
|
||||
unbound: &Option<ast::TyParamBound>,
|
||||
ident: ast::Ident,
|
||||
span: Span) -> ty::ParamBounds
|
||||
{
|
||||
@ -1113,15 +1142,11 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
if sized == ast::StaticSize {
|
||||
match ccx.tcx.lang_items.require(SizedTraitLangItem) {
|
||||
Ok(def_id) => { ty::try_add_builtin_trait(ccx.tcx,
|
||||
def_id,
|
||||
&mut param_bounds.builtin_bounds); },
|
||||
// Fixme(13367) after `type` makes it into the snapshot, we can check this properly
|
||||
Err(_s) => {}, //ccx.tcx.sess.err(s),
|
||||
}
|
||||
}
|
||||
add_unsized_bound(ccx,
|
||||
unbound,
|
||||
&mut param_bounds.builtin_bounds,
|
||||
"type parameter",
|
||||
span);
|
||||
|
||||
check_bounds_compatible(ccx.tcx, ¶m_bounds, ident, span);
|
||||
|
||||
|
@ -895,9 +895,9 @@ impl<'a> Rebuilder<'a> {
|
||||
ident: ty_param.ident,
|
||||
id: ty_param.id,
|
||||
bounds: bounds,
|
||||
unbound: ty_param.unbound.clone(),
|
||||
default: ty_param.default,
|
||||
span: ty_param.span,
|
||||
sized: ty_param.sized,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
|
||||
// miscellaneous, no highlighting
|
||||
t::DOT | t::DOTDOT | t::DOTDOTDOT | t::COMMA | t::SEMI |
|
||||
t::COLON | t::MOD_SEP | t::LARROW | t::LPAREN |
|
||||
t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE => "",
|
||||
t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE | t::QUESTION => "",
|
||||
t::DOLLAR => {
|
||||
if t::is_ident(&lexer.peek().tok) {
|
||||
is_macro_nonterminal = true;
|
||||
|
@ -184,8 +184,8 @@ pub enum TyParamBound {
|
||||
pub struct TyParam {
|
||||
pub ident: Ident,
|
||||
pub id: NodeId,
|
||||
pub sized: Sized,
|
||||
pub bounds: OwnedSlice<TyParamBound>,
|
||||
pub unbound: Option<TyParamBound>,
|
||||
pub default: Option<P<Ty>>,
|
||||
pub span: Span
|
||||
}
|
||||
@ -1041,12 +1041,6 @@ impl Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
||||
pub enum Sized {
|
||||
DynSize,
|
||||
StaticSize,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
||||
pub struct StructField_ {
|
||||
pub kind: StructFieldKind,
|
||||
@ -1115,7 +1109,11 @@ pub enum Item_ {
|
||||
ItemEnum(EnumDef, Generics),
|
||||
ItemStruct(Gc<StructDef>, Generics),
|
||||
/// Represents a Trait Declaration
|
||||
ItemTrait(Generics, Sized, Vec<TraitRef> , Vec<TraitMethod> ),
|
||||
ItemTrait(Generics,
|
||||
Option<TyParamBound>, // (optional) default bound not required for Self.
|
||||
// Currently, only Sized makes sense here.
|
||||
Vec<TraitRef> ,
|
||||
Vec<TraitMethod>),
|
||||
ItemImpl(Generics,
|
||||
Option<TraitRef>, // (optional) trait this impl implements
|
||||
P<Ty>, // self
|
||||
|
@ -66,8 +66,8 @@ pub trait AstBuilder {
|
||||
fn typaram(&self,
|
||||
span: Span,
|
||||
id: ast::Ident,
|
||||
sized: ast::Sized,
|
||||
bounds: OwnedSlice<ast::TyParamBound>,
|
||||
unbound: Option<ast::TyParamBound>,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam;
|
||||
|
||||
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
|
||||
@ -396,14 +396,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
fn typaram(&self,
|
||||
span: Span,
|
||||
id: ast::Ident,
|
||||
sized: ast::Sized,
|
||||
bounds: OwnedSlice<ast::TyParamBound>,
|
||||
unbound: Option<ast::TyParamBound>,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam {
|
||||
ast::TyParam {
|
||||
ident: id,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
sized: sized,
|
||||
bounds: bounds,
|
||||
unbound: unbound,
|
||||
default: default,
|
||||
span: span
|
||||
}
|
||||
@ -423,7 +423,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
|
||||
fn strip_bounds(&self, generics: &Generics) -> Generics {
|
||||
let new_params = generics.ty_params.map(|ty_param| {
|
||||
ast::TyParam { bounds: OwnedSlice::empty(), ..*ty_param }
|
||||
ast::TyParam { bounds: OwnedSlice::empty(), unbound: None, ..*ty_param }
|
||||
});
|
||||
Generics {
|
||||
ty_params: new_params,
|
||||
|
@ -13,7 +13,6 @@ The compiler code necessary for `#[deriving(Decodable)]`. See
|
||||
encodable.rs for more.
|
||||
*/
|
||||
|
||||
use ast;
|
||||
use ast::{MetaItem, Item, Expr, MutMutable, Ident};
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
@ -39,10 +38,10 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("__D", ast::StaticSize, vec!(Path::new_(
|
||||
bounds: vec!(("__D", None, vec!(Path::new_(
|
||||
vec!("serialize", "Decoder"), None,
|
||||
vec!(box Literal(Path::new_local("__E"))), true))),
|
||||
("__E", ast::StaticSize, vec!()))
|
||||
("__E", None, vec!()))
|
||||
},
|
||||
methods: vec!(
|
||||
MethodDef {
|
||||
|
@ -82,7 +82,6 @@ would yield functions like:
|
||||
```
|
||||
*/
|
||||
|
||||
use ast;
|
||||
use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
@ -107,10 +106,10 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("__S", ast::StaticSize, vec!(Path::new_(
|
||||
bounds: vec!(("__S", None, vec!(Path::new_(
|
||||
vec!("serialize", "Encoder"), None,
|
||||
vec!(box Literal(Path::new_local("__E"))), true))),
|
||||
("__E", ast::StaticSize, vec!()))
|
||||
("__E", None, vec!()))
|
||||
},
|
||||
methods: vec!(
|
||||
MethodDef {
|
||||
|
@ -406,8 +406,8 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
cx.typaram(self.span,
|
||||
ty_param.ident,
|
||||
ty_param.sized,
|
||||
OwnedSlice::from_vec(bounds),
|
||||
ty_param.unbound.clone(),
|
||||
None)
|
||||
}));
|
||||
let trait_generics = Generics {
|
||||
|
@ -188,17 +188,18 @@ impl<'a> Ty<'a> {
|
||||
}
|
||||
|
||||
|
||||
fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, sized: ast::Sized, bounds: &[Path],
|
||||
fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
|
||||
bounds: &[Path], unbound: Option<ast::TyParamBound>,
|
||||
self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
|
||||
let bounds =
|
||||
bounds.iter().map(|b| {
|
||||
let path = b.to_path(cx, span, self_ident, self_generics);
|
||||
cx.typarambound(path)
|
||||
}).collect();
|
||||
cx.typaram(span, cx.ident_of(name), sized, bounds, None)
|
||||
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
|
||||
}
|
||||
|
||||
fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) -> Generics {
|
||||
fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
|
||||
Generics {
|
||||
lifetimes: lifetimes,
|
||||
ty_params: OwnedSlice::from_vec(ty_params)
|
||||
@ -208,7 +209,7 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) -
|
||||
/// Lifetimes and bounds on type parameters
|
||||
pub struct LifetimeBounds<'a> {
|
||||
pub lifetimes: Vec<&'a str>,
|
||||
pub bounds: Vec<(&'a str, ast::Sized, Vec<Path<'a>>)>,
|
||||
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
|
||||
}
|
||||
|
||||
impl<'a> LifetimeBounds<'a> {
|
||||
@ -228,12 +229,12 @@ impl<'a> LifetimeBounds<'a> {
|
||||
}).collect();
|
||||
let ty_params = self.bounds.iter().map(|t| {
|
||||
match t {
|
||||
&(ref name, sized, ref bounds) => {
|
||||
&(ref name, ref unbound, ref bounds) => {
|
||||
mk_ty_param(cx,
|
||||
span,
|
||||
*name,
|
||||
sized,
|
||||
bounds.as_slice(),
|
||||
unbound.clone(),
|
||||
self_ty,
|
||||
self_generics)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast;
|
||||
use ast::{MetaItem, Item, Expr, MutMutable};
|
||||
use codemap::Span;
|
||||
use ext::base::ExtCtxt;
|
||||
@ -30,7 +29,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
||||
vec!(box Literal(Path::new_local("__S"))), true),
|
||||
LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("__S", ast::StaticSize,
|
||||
bounds: vec!(("__S", None,
|
||||
vec!(Path::new(vec!("std", "hash", "Writer"))))),
|
||||
},
|
||||
Path::new_local("__S"))
|
||||
|
@ -35,7 +35,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("R",
|
||||
ast::StaticSize,
|
||||
None,
|
||||
vec!( Path::new(vec!("std", "rand", "Rng")) )))
|
||||
},
|
||||
explicit_self: None,
|
||||
|
@ -491,8 +491,8 @@ pub fn fold_ty_param<T: Folder>(tp: &TyParam, fld: &mut T) -> TyParam {
|
||||
TyParam {
|
||||
ident: tp.ident,
|
||||
id: id,
|
||||
sized: tp.sized,
|
||||
bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)),
|
||||
unbound: tp.unbound.as_ref().map(|x| fold_ty_param_bound(x, fld)),
|
||||
default: tp.default.map(|x| fld.fold_ty(x)),
|
||||
span: tp.span
|
||||
}
|
||||
@ -666,7 +666,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
|
||||
methods.iter().map(|x| folder.fold_method(*x)).collect()
|
||||
)
|
||||
}
|
||||
ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
|
||||
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
|
||||
let methods = methods.iter().map(|method| {
|
||||
match *method {
|
||||
Required(ref m) => Required(folder.fold_type_method(m)),
|
||||
@ -674,7 +674,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
|
||||
}
|
||||
}).collect();
|
||||
ItemTrait(fold_generics(generics, folder),
|
||||
*sized,
|
||||
unbound.clone(),
|
||||
traits.iter().map(|p| fold_trait_ref(p, folder)).collect(),
|
||||
methods)
|
||||
}
|
||||
|
@ -849,6 +849,7 @@ impl<'a> StringReader<'a> {
|
||||
'@' => { self.bump(); return token::AT; }
|
||||
'#' => { self.bump(); return token::POUND; }
|
||||
'~' => { self.bump(); return token::TILDE; }
|
||||
'?' => { self.bump(); return token::QUESTION; }
|
||||
':' => {
|
||||
self.bump();
|
||||
if self.curr_is(':') {
|
||||
|
@ -42,7 +42,6 @@ use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
|
||||
use ast::{PatTup, PatBox, PatWild, PatWildMulti};
|
||||
use ast::{BiRem, Required};
|
||||
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
|
||||
use ast::{Sized, DynSize, StaticSize};
|
||||
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
|
||||
use ast::{StructVariantKind, BiSub};
|
||||
use ast::StrStyle;
|
||||
@ -3564,11 +3563,40 @@ impl<'a> Parser<'a> {
|
||||
return (ret_lifetime, OwnedSlice::from_vec(result));
|
||||
}
|
||||
|
||||
// matches typaram = type? IDENT optbounds ( EQ ty )?
|
||||
fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
};
|
||||
let path = ast::Path {
|
||||
span: span,
|
||||
global: false,
|
||||
segments: vec![segment],
|
||||
};
|
||||
ast::TraitRef {
|
||||
path: path,
|
||||
ref_id: ast::DUMMY_NODE_ID,
|
||||
}
|
||||
}
|
||||
|
||||
// matches typaram = (unbound`?`)? IDENT optbounds ( EQ ty )?
|
||||
fn parse_ty_param(&mut self) -> TyParam {
|
||||
let sized = self.parse_sized();
|
||||
let span = self.span;
|
||||
let ident = self.parse_ident();
|
||||
// This is a bit hacky. Currently we are only interested in a single
|
||||
// unbound, and it may only be `Sized`. To avoid backtracking and other
|
||||
// complications, we parse an ident, then check for `?`. If we find it,
|
||||
// we use the ident as the unbound, otherwise, we use it as the name of
|
||||
// type param.
|
||||
let mut span = self.span;
|
||||
let mut ident = self.parse_ident();
|
||||
let mut unbound = None;
|
||||
if self.eat(&token::QUESTION) {
|
||||
let tref = Parser::trait_ref_from_ident(ident, span);
|
||||
unbound = Some(TraitTyParamBound(tref));
|
||||
span = self.span;
|
||||
ident = self.parse_ident();
|
||||
}
|
||||
|
||||
let opt_bounds = {
|
||||
if self.eat(&token::COLON) {
|
||||
let (_, bounds) = self.parse_ty_param_bounds(false);
|
||||
@ -3589,8 +3617,8 @@ impl<'a> Parser<'a> {
|
||||
TyParam {
|
||||
ident: ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
sized: sized,
|
||||
bounds: bounds,
|
||||
unbound: unbound,
|
||||
default: default,
|
||||
span: span,
|
||||
}
|
||||
@ -4209,21 +4237,19 @@ impl<'a> Parser<'a> {
|
||||
else { Inherited }
|
||||
}
|
||||
|
||||
fn parse_sized(&mut self) -> Sized {
|
||||
if self.eat_keyword(keywords::Type) { DynSize }
|
||||
else { StaticSize }
|
||||
}
|
||||
|
||||
fn parse_for_sized(&mut self) -> Sized {
|
||||
fn parse_for_sized(&mut self) -> Option<ast::TyParamBound> {
|
||||
if self.eat_keyword(keywords::For) {
|
||||
if !self.eat_keyword(keywords::Type) {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
"expected 'type' after for in trait item");
|
||||
let span = self.span;
|
||||
let ident = self.parse_ident();
|
||||
if !self.eat(&token::QUESTION) {
|
||||
self.span_err(span,
|
||||
"expected 'Sized?' after `for` in trait item");
|
||||
return None;
|
||||
}
|
||||
DynSize
|
||||
let tref = Parser::trait_ref_from_ident(ident, span);
|
||||
Some(TraitTyParamBound(tref))
|
||||
} else {
|
||||
StaticSize
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ pub enum Token {
|
||||
RBRACE,
|
||||
POUND,
|
||||
DOLLAR,
|
||||
QUESTION,
|
||||
|
||||
/* Literals */
|
||||
LIT_BYTE(u8),
|
||||
@ -195,6 +196,7 @@ pub fn to_str(t: &Token) -> String {
|
||||
RBRACE => "}".to_string(),
|
||||
POUND => "#".to_string(),
|
||||
DOLLAR => "$".to_string(),
|
||||
QUESTION => "?".to_string(),
|
||||
|
||||
/* Literals */
|
||||
LIT_BYTE(b) => {
|
||||
|
@ -740,14 +740,19 @@ impl<'a> State<'a> {
|
||||
}
|
||||
try!(self.bclose(item.span));
|
||||
}
|
||||
ast::ItemTrait(ref generics, ref sized, ref traits, ref methods) => {
|
||||
ast::ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
|
||||
try!(self.head(visibility_qualified(item.vis,
|
||||
"trait").as_slice()));
|
||||
try!(self.print_ident(item.ident));
|
||||
try!(self.print_generics(generics));
|
||||
if *sized == ast::DynSize {
|
||||
try!(space(&mut self.s));
|
||||
try!(word(&mut self.s, "for type"));
|
||||
match unbound {
|
||||
&Some(TraitTyParamBound(ref tref)) => {
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("for"));
|
||||
try!(self.print_trait_ref(tref));
|
||||
try!(word(&mut self.s, "?"));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if traits.len() != 0u {
|
||||
try!(word(&mut self.s, ":"));
|
||||
@ -2029,8 +2034,12 @@ impl<'a> State<'a> {
|
||||
} else {
|
||||
let idx = idx - generics.lifetimes.len();
|
||||
let param = generics.ty_params.get(idx);
|
||||
if param.sized == ast::DynSize {
|
||||
try!(s.word_space("type"));
|
||||
match param.unbound {
|
||||
Some(TraitTyParamBound(ref tref)) => {
|
||||
try!(s.print_trait_ref(tref));
|
||||
try!(s.word_space("?"));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
try!(s.print_ident(param.ident));
|
||||
try!(s.print_bounds(&None,
|
||||
|
@ -10,5 +10,5 @@
|
||||
|
||||
// error-pattern: instantiating a type parameter with an incompatible type
|
||||
fn bar<T: Sized>() { }
|
||||
fn foo<type T>() { bar::<T>() }
|
||||
fn foo<Sized? T>() { bar::<T>() }
|
||||
fn main() { }
|
||||
|
@ -10,5 +10,5 @@
|
||||
|
||||
// error-pattern: instantiating a type parameter with an incompatible type
|
||||
fn bar<T: Sized>() { }
|
||||
fn foo<type T>() { bar::<Option<T>>() }
|
||||
fn foo<Sized? T>() { bar::<Option<T>>() }
|
||||
fn main() { }
|
||||
|
@ -13,5 +13,5 @@
|
||||
struct Foo<T> { data: T }
|
||||
|
||||
fn bar<T: Sized>() { }
|
||||
fn foo<type T>() { bar::<Foo<T>>() }
|
||||
fn foo<Sized? T>() { bar::<Foo<T>>() }
|
||||
fn main() { }
|
||||
|
@ -12,45 +12,45 @@
|
||||
|
||||
|
||||
// Unbounded.
|
||||
fn f1<type X>(x: &X) {
|
||||
fn f1<Sized? X>(x: &X) {
|
||||
f2::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
|
||||
}
|
||||
fn f2<X>(x: &X) {
|
||||
}
|
||||
|
||||
// Bounded.
|
||||
trait T for type {}
|
||||
fn f3<type X: T>(x: &X) {
|
||||
trait T for Sized? {}
|
||||
fn f3<Sized? X: T>(x: &X) {
|
||||
f4::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
|
||||
}
|
||||
fn f4<X: T>(x: &X) {
|
||||
}
|
||||
|
||||
// Test with unsized enum.
|
||||
enum E<type X> {
|
||||
enum E<Sized? X> {
|
||||
V(X),
|
||||
}
|
||||
|
||||
fn f5<Y>(x: &Y) {}
|
||||
fn f6<type X>(x: &X) {}
|
||||
fn f7<type X>(x1: &E<X>, x2: &E<X>) {
|
||||
fn f6<Sized? X>(x: &X) {}
|
||||
fn f7<Sized? X>(x1: &E<X>, x2: &E<X>) {
|
||||
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `E<X>`, which does not
|
||||
f6(x2); // ok
|
||||
}
|
||||
|
||||
|
||||
// Test with unsized struct.
|
||||
struct S<type X> {
|
||||
struct S<Sized? X> {
|
||||
x: X,
|
||||
}
|
||||
|
||||
fn f8<type X>(x1: &S<X>, x2: &S<X>) {
|
||||
fn f8<Sized? X>(x1: &S<X>, x2: &S<X>) {
|
||||
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `S<X>`, which does not
|
||||
f6(x2); // ok
|
||||
}
|
||||
|
||||
// Test some tuples.
|
||||
fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
||||
fn f9<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
||||
f5(&(*x1, 34i)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
|
||||
f5(&(32i, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
|
||||
}
|
||||
@ -60,20 +60,20 @@ fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
|
||||
// impl - bounded
|
||||
trait T1<Z: T> {
|
||||
}
|
||||
struct S3<type Y>;
|
||||
impl<type X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
|
||||
struct S3<Sized? Y>;
|
||||
impl<Sized? X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
|
||||
}
|
||||
|
||||
// impl - unbounded
|
||||
trait T2<Z> {
|
||||
}
|
||||
impl<type X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X`
|
||||
impl<Sized? X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X
|
||||
|
||||
// impl - struct
|
||||
trait T3<type Z> {
|
||||
trait T3<Sized? Z> {
|
||||
}
|
||||
struct S4<Y>;
|
||||
impl<type X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X`
|
||||
impl<Sized? X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
// Test that bounds are sized-compatible.
|
||||
|
||||
trait T {}
|
||||
fn f<type Y: T>() {
|
||||
fn f<Sized? Y: T>() {
|
||||
//~^ERROR incompatible bounds on type parameter Y, bound T does not allow unsized type
|
||||
}
|
||||
|
||||
|
@ -9,19 +9,19 @@
|
||||
// except according to those terms.
|
||||
#![feature(struct_variant)]
|
||||
|
||||
// Test `type` types not allowed in fields.
|
||||
// Test `Sized?` types not allowed in fields.
|
||||
|
||||
struct S1<type X> {
|
||||
struct S1<Sized? X> {
|
||||
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
|
||||
f2: int,
|
||||
}
|
||||
struct S2<type X> {
|
||||
struct S2<Sized? X> {
|
||||
f: int,
|
||||
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
|
||||
h: int,
|
||||
}
|
||||
|
||||
enum E<type X> {
|
||||
enum E<Sized? X> {
|
||||
V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
|
||||
V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app
|
||||
}
|
||||
|
@ -8,37 +8,37 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test `type` local variables.
|
||||
// Test `Sized?` local variables.
|
||||
|
||||
|
||||
trait T for type {}
|
||||
trait T for Sized? {}
|
||||
|
||||
fn f1<type X>(x: &X) {
|
||||
fn f1<Sized? X>(x: &X) {
|
||||
let _: X; //~ERROR variable `_` has dynamically sized type `X`
|
||||
let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
|
||||
let y: X; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
|
||||
}
|
||||
fn f2<type X: T>(x: &X) {
|
||||
fn f2<Sized? X: T>(x: &X) {
|
||||
let _: X; //~ERROR variable `_` has dynamically sized type `X`
|
||||
let _: (int, (X, int)); //~ERROR variable `_` has dynamically sized type `(int,(X,int))`
|
||||
let y: X; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
|
||||
}
|
||||
|
||||
fn f3<type X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
fn f3<Sized? X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
|
||||
}
|
||||
fn f4<type X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
fn f4<Sized? X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
|
||||
let (y, z) = (*x3, 4i); //~ERROR variable `y` has dynamically sized type `X`
|
||||
}
|
||||
|
||||
fn g1<type X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
|
||||
fn g2<type X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
|
||||
fn g1<Sized? X>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
|
||||
fn g2<Sized? X: T>(x: X) {} //~ERROR variable `x` has dynamically sized type `X`
|
||||
|
||||
pub fn main() {
|
||||
}
|
||||
|
@ -8,20 +8,20 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test syntax checks for `type` keyword.
|
||||
// Test syntax checks for `Sized?` syntax.
|
||||
|
||||
trait T1 for type {}
|
||||
pub trait T2 for type {}
|
||||
trait T3<X: T1> for type: T2 {}
|
||||
trait T4<type X> {}
|
||||
trait T5<type X, Y> {}
|
||||
trait T6<Y, type X> {}
|
||||
trait T7<type X, type Y> {}
|
||||
trait T8<type X: T2> {}
|
||||
struct S1<type X>;
|
||||
enum E<type X> {}
|
||||
impl <type X> T1 for S1<X> {}
|
||||
fn f<type X>() {}
|
||||
trait T1 for Sized? {}
|
||||
pub trait T2 for Sized? {}
|
||||
trait T3<X: T1> for Sized?: T2 {}
|
||||
trait T4<Sized? X> {}
|
||||
trait T5<Sized? X, Y> {}
|
||||
trait T6<Y, Sized? X> {}
|
||||
trait T7<Sized? X, Sized? Y> {}
|
||||
trait T8<Sized? X: T2> {}
|
||||
struct S1<Sized? X>;
|
||||
enum E<Sized? X> {}
|
||||
impl <Sized? X> T1 for S1<X> {}
|
||||
fn f<Sized? X>() {}
|
||||
|
||||
pub fn main() {
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// Test sized-ness checking in substitution.
|
||||
|
||||
// Unbounded.
|
||||
fn f1<type X>(x: &X) {
|
||||
fn f1<Sized? X>(x: &X) {
|
||||
f1::<X>(x);
|
||||
}
|
||||
fn f2<X>(x: &X) {
|
||||
@ -22,8 +22,8 @@ fn f2<X>(x: &X) {
|
||||
}
|
||||
|
||||
// Bounded.
|
||||
trait T for type {}
|
||||
fn f3<type X: T>(x: &X) {
|
||||
trait T for Sized? {}
|
||||
fn f3<Sized? X: T>(x: &X) {
|
||||
f3::<X>(x);
|
||||
}
|
||||
fn f4<X: T>(x: &X) {
|
||||
@ -32,7 +32,7 @@ fn f4<X: T>(x: &X) {
|
||||
}
|
||||
|
||||
// Self type.
|
||||
trait T2 for type {
|
||||
trait T2 for Sized? {
|
||||
fn f() -> Box<Self>;
|
||||
}
|
||||
struct S;
|
||||
@ -41,14 +41,14 @@ impl T2 for S {
|
||||
box S
|
||||
}
|
||||
}
|
||||
fn f5<type X: T2>(x: &X) {
|
||||
fn f5<Sized? X: T2>(x: &X) {
|
||||
let _: Box<X> = T2::f();
|
||||
}
|
||||
fn f6<X: T2>(x: &X) {
|
||||
let _: Box<X> = T2::f();
|
||||
}
|
||||
|
||||
trait T3 for type {
|
||||
trait T3 for Sized? {
|
||||
fn f() -> Box<Self>;
|
||||
}
|
||||
impl T3 for S {
|
||||
@ -56,7 +56,7 @@ impl T3 for S {
|
||||
box S
|
||||
}
|
||||
}
|
||||
fn f7<type X: T3>(x: &X) {
|
||||
fn f7<Sized? X: T3>(x: &X) {
|
||||
// This is valid, but the unsized bound on X is irrelevant because any type
|
||||
// which implements T3 must have statically known size.
|
||||
let _: Box<X> = T3::f();
|
||||
@ -66,7 +66,7 @@ trait T4<X> {
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
trait T5<type X> {
|
||||
trait T5<Sized? X> {
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
@ -76,21 +76,21 @@ trait T6<X: T> {
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
trait T7<type X: T> {
|
||||
trait T7<Sized? X: T> {
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
|
||||
// The last field in a struct or variant may be unsized
|
||||
struct S2<type X> {
|
||||
struct S2<Sized? X> {
|
||||
f: X,
|
||||
}
|
||||
struct S3<type X> {
|
||||
struct S3<Sized? X> {
|
||||
f1: int,
|
||||
f2: X,
|
||||
}
|
||||
enum E<type X> {
|
||||
enum E<Sized? X> {
|
||||
V1(X),
|
||||
V2{x: X},
|
||||
V3(int, X),
|
||||
|
Loading…
x
Reference in New Issue
Block a user