mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-24 05:33:41 +00:00
libsyntax: Allow +
to separate trait bounds from objects.
RFC #27. After a snapshot, the old syntax will be removed. This can break some code that looked like `foo as &Trait:Send`. Now you will need to write `foo as (&Trait+Send)`. Closes #12778. [breaking-change]
This commit is contained in:
parent
03ec8e5cc9
commit
9b9ef44233
@ -724,6 +724,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
|
||||
.collect();
|
||||
ty::mk_tup(tcx, flds)
|
||||
}
|
||||
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
|
||||
ast::TyBareFn(ref bf) => {
|
||||
if bf.decl.variadic && bf.abi != abi::C {
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
|
@ -1140,6 +1140,7 @@ impl<'a> Rebuilder<'a> {
|
||||
}
|
||||
ast::TyTup(new_tys)
|
||||
}
|
||||
ast::TyParen(ref typ) => ast::TyParen(build_to(*typ, to)),
|
||||
ref other => other.clone()
|
||||
};
|
||||
box(GC) ast::Ty { id: from.id, node: new_node, span: from.span }
|
||||
|
@ -60,7 +60,7 @@ impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clean<U>, U> Clean<U> for Gc<T> {
|
||||
impl<T: 'static + Clean<U>, U> Clean<U> for Gc<T> {
|
||||
fn clean(&self) -> U {
|
||||
(**self).clean()
|
||||
}
|
||||
@ -1198,6 +1198,7 @@ impl Clean<Type> for ast::Ty {
|
||||
TyClosure(ref c, region) => Closure(box c.clean(), region.clean()),
|
||||
TyProc(ref c) => Proc(box c.clean()),
|
||||
TyBareFn(ref barefn) => BareFunction(box barefn.clean()),
|
||||
TyParen(ref ty) => ty.clean(),
|
||||
TyBot => Bottom,
|
||||
ref x => fail!("Unimplemented type {:?}", x),
|
||||
}
|
||||
|
@ -784,6 +784,8 @@ pub enum Ty_ {
|
||||
TyUnboxedFn(Gc<UnboxedFnTy>),
|
||||
TyTup(Vec<P<Ty>> ),
|
||||
TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
|
||||
// No-op; kept solely so that we can pretty-print faithfully
|
||||
TyParen(P<Ty>),
|
||||
TyTypeof(Gc<Expr>),
|
||||
// TyInfer means the type should be inferred instead of it having been
|
||||
// specified. This can appear anywhere in a type.
|
||||
|
@ -737,6 +737,7 @@ pub fn get_inner_tys(ty: P<Ty>) -> Vec<P<Ty>> {
|
||||
| ast::TyUniq(ty)
|
||||
| ast::TyFixedLengthVec(ty, _) => vec!(ty),
|
||||
ast::TyTup(ref tys) => tys.clone(),
|
||||
ast::TyParen(ty) => get_inner_tys(ty),
|
||||
_ => Vec::new()
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,7 @@ pub trait Folder {
|
||||
})
|
||||
}
|
||||
TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()),
|
||||
TyParen(ref ty) => TyParen(self.fold_ty(*ty)),
|
||||
TyPath(ref path, ref bounds, id) => {
|
||||
let id = self.new_id(id);
|
||||
TyPath(self.fold_path(path),
|
||||
|
@ -51,7 +51,7 @@ use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
|
||||
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyPath, TyPtr, TyRptr};
|
||||
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyRptr};
|
||||
use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
|
||||
use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
|
||||
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
|
||||
@ -105,7 +105,7 @@ pub enum PathParsingMode {
|
||||
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
|
||||
LifetimeAndTypesWithColons,
|
||||
/// A path with a lifetime and type parameters with bounds before the last
|
||||
/// set of type parameters only; e.g. `foo::bar<'a>::Baz:X+Y<T>` This
|
||||
/// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
|
||||
/// form does not use extra double colons.
|
||||
LifetimeAndTypesAndBounds,
|
||||
}
|
||||
@ -1015,7 +1015,14 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
let (inputs, variadic) = self.parse_fn_args(false, false);
|
||||
let (_, bounds) = self.parse_optional_ty_param_bounds(false);
|
||||
let bounds = {
|
||||
if self.eat(&token::COLON) {
|
||||
let (_, bounds) = self.parse_ty_param_bounds(false);
|
||||
Some(bounds)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
let (ret_style, ret_ty) = self.parse_ret_ty();
|
||||
let decl = P(FnDecl {
|
||||
inputs: inputs,
|
||||
@ -1083,7 +1090,14 @@ impl<'a> Parser<'a> {
|
||||
(is_unboxed, inputs)
|
||||
};
|
||||
|
||||
let (region, bounds) = self.parse_optional_ty_param_bounds(true);
|
||||
let (region, bounds) = {
|
||||
if self.eat(&token::COLON) {
|
||||
let (region, bounds) = self.parse_ty_param_bounds(true);
|
||||
(region, Some(bounds))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
};
|
||||
|
||||
let (return_style, output) = self.parse_ret_ty();
|
||||
let decl = P(FnDecl {
|
||||
@ -1227,7 +1241,7 @@ impl<'a> Parser<'a> {
|
||||
// parse a possibly mutable type
|
||||
pub fn parse_mt(&mut self) -> MutTy {
|
||||
let mutbl = self.parse_mutability();
|
||||
let t = self.parse_ty(false);
|
||||
let t = self.parse_ty(true);
|
||||
MutTy { ty: t, mutbl: mutbl }
|
||||
}
|
||||
|
||||
@ -1238,7 +1252,7 @@ impl<'a> Parser<'a> {
|
||||
let mutbl = self.parse_mutability();
|
||||
let id = self.parse_ident();
|
||||
self.expect(&token::COLON);
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
let hi = ty.span.hi;
|
||||
ast::TypeField {
|
||||
ident: id,
|
||||
@ -1261,7 +1275,7 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
)
|
||||
} else {
|
||||
(Return, self.parse_ty(false))
|
||||
(Return, self.parse_ty(true))
|
||||
}
|
||||
} else {
|
||||
let pos = self.span.lo;
|
||||
@ -1276,10 +1290,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// parse a type.
|
||||
// Useless second parameter for compatibility with quasiquote macros.
|
||||
// Bleh!
|
||||
pub fn parse_ty(&mut self, _: bool) -> P<Ty> {
|
||||
/// Parse a type.
|
||||
///
|
||||
/// The second parameter specifies whether the `+` binary operator is
|
||||
/// allowed in the type grammar.
|
||||
pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
|
||||
maybe_whole!(no_clone self, NtTy);
|
||||
|
||||
let lo = self.span.lo;
|
||||
@ -1293,12 +1308,12 @@ impl<'a> Parser<'a> {
|
||||
// (t) is a parenthesized ty
|
||||
// (t,) is the type of a tuple with only one field,
|
||||
// of type t
|
||||
let mut ts = vec!(self.parse_ty(false));
|
||||
let mut ts = vec!(self.parse_ty(true));
|
||||
let mut one_tuple = false;
|
||||
while self.token == token::COMMA {
|
||||
self.bump();
|
||||
if self.token != token::RPAREN {
|
||||
ts.push(self.parse_ty(false));
|
||||
ts.push(self.parse_ty(true));
|
||||
}
|
||||
else {
|
||||
one_tuple = true;
|
||||
@ -1307,17 +1322,17 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if ts.len() == 1 && !one_tuple {
|
||||
self.expect(&token::RPAREN);
|
||||
return *ts.get(0)
|
||||
TyParen(*ts.get(0))
|
||||
} else {
|
||||
let t = TyTup(ts);
|
||||
self.expect(&token::RPAREN);
|
||||
t
|
||||
}
|
||||
|
||||
let t = TyTup(ts);
|
||||
self.expect(&token::RPAREN);
|
||||
t
|
||||
}
|
||||
} else if self.token == token::AT {
|
||||
// MANAGED POINTER
|
||||
self.bump();
|
||||
TyBox(self.parse_ty(false))
|
||||
TyBox(self.parse_ty(plus_allowed))
|
||||
} else if self.token == token::TILDE {
|
||||
// OWNED POINTER
|
||||
self.bump();
|
||||
@ -1326,7 +1341,7 @@ impl<'a> Parser<'a> {
|
||||
self.obsolete(self.last_span, ObsoleteOwnedVector),
|
||||
_ => self.obsolete(self.last_span, ObsoleteOwnedType),
|
||||
};
|
||||
TyUniq(self.parse_ty(false))
|
||||
TyUniq(self.parse_ty(true))
|
||||
} else if self.token == token::BINOP(token::STAR) {
|
||||
// STAR POINTER (bare pointer?)
|
||||
self.bump();
|
||||
@ -1334,7 +1349,7 @@ impl<'a> Parser<'a> {
|
||||
} else if self.token == token::LBRACKET {
|
||||
// VECTOR
|
||||
self.expect(&token::LBRACKET);
|
||||
let t = self.parse_ty(false);
|
||||
let t = self.parse_ty(true);
|
||||
|
||||
// Parse the `, ..e` in `[ int, ..e ]`
|
||||
// where `e` is a const expression
|
||||
@ -1377,10 +1392,15 @@ impl<'a> Parser<'a> {
|
||||
} else if self.token == token::MOD_SEP
|
||||
|| is_ident_or_path(&self.token) {
|
||||
// NAMED TYPE
|
||||
let mode = if plus_allowed {
|
||||
LifetimeAndTypesAndBounds
|
||||
} else {
|
||||
LifetimeAndTypesWithoutColons
|
||||
};
|
||||
let PathAndBounds {
|
||||
path,
|
||||
bounds
|
||||
} = self.parse_path(LifetimeAndTypesAndBounds);
|
||||
} = self.parse_path(mode);
|
||||
TyPath(path, bounds, ast::DUMMY_NODE_ID)
|
||||
} else if self.eat(&token::UNDERSCORE) {
|
||||
// TYPE TO BE INFERRED
|
||||
@ -1438,7 +1458,7 @@ impl<'a> Parser<'a> {
|
||||
special_idents::invalid)
|
||||
};
|
||||
|
||||
let t = self.parse_ty(false);
|
||||
let t = self.parse_ty(true);
|
||||
|
||||
Arg {
|
||||
ty: t,
|
||||
@ -1456,7 +1476,7 @@ impl<'a> Parser<'a> {
|
||||
pub fn parse_fn_block_arg(&mut self) -> Arg {
|
||||
let pat = self.parse_pat();
|
||||
let t = if self.eat(&token::COLON) {
|
||||
self.parse_ty(false)
|
||||
self.parse_ty(true)
|
||||
} else {
|
||||
P(Ty {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -1611,9 +1631,19 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Next, parse a colon and bounded type parameters, if applicable.
|
||||
// Next, parse a plus and bounded type parameters, if applicable.
|
||||
//
|
||||
// NOTE(stage0, pcwalton): Remove `token::COLON` after a snapshot.
|
||||
let bounds = if mode == LifetimeAndTypesAndBounds {
|
||||
let (_, bounds) = self.parse_optional_ty_param_bounds(false);
|
||||
let bounds = {
|
||||
if self.eat(&token::BINOP(token::PLUS)) ||
|
||||
self.eat(&token::COLON) {
|
||||
let (_, bounds) = self.parse_ty_param_bounds(false);
|
||||
Some(bounds)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
bounds
|
||||
} else {
|
||||
None
|
||||
@ -2438,7 +2468,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
None => {
|
||||
if as_prec > min_prec && self.eat_keyword(keywords::As) {
|
||||
let rhs = self.parse_ty(true);
|
||||
let rhs = self.parse_ty(false);
|
||||
let _as = self.mk_expr(lhs.span.lo,
|
||||
rhs.span.hi,
|
||||
ExprCast(lhs, rhs));
|
||||
@ -3067,7 +3097,9 @@ impl<'a> Parser<'a> {
|
||||
node: TyInfer,
|
||||
span: mk_sp(lo, lo),
|
||||
});
|
||||
if self.eat(&token::COLON) { ty = self.parse_ty(false); }
|
||||
if self.eat(&token::COLON) {
|
||||
ty = self.parse_ty(true);
|
||||
}
|
||||
let init = self.parse_initializer();
|
||||
box(GC) ast::Local {
|
||||
ty: ty,
|
||||
@ -3095,7 +3127,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
let name = self.parse_ident();
|
||||
self.expect(&token::COLON);
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
spanned(lo, self.last_span.hi, ast::StructField_ {
|
||||
kind: NamedField(name, pr),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -3427,7 +3459,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// matches optbounds = ( ( : ( boundseq )? )? )
|
||||
// matches bounds = ( boundseq )?
|
||||
// where boundseq = ( bound + boundseq ) | bound
|
||||
// and bound = 'static | ty
|
||||
// Returns "None" if there's no colon (e.g. "T");
|
||||
@ -3439,13 +3471,9 @@ impl<'a> Parser<'a> {
|
||||
// AST doesn't support arbitrary lifetimes in bounds on type parameters. In
|
||||
// the future, this flag should be removed, and the return value of this
|
||||
// function should be Option<~[TyParamBound]>
|
||||
fn parse_optional_ty_param_bounds(&mut self, allow_any_lifetime: bool)
|
||||
-> (Option<ast::Lifetime>, Option<OwnedSlice<TyParamBound>>)
|
||||
{
|
||||
if !self.eat(&token::COLON) {
|
||||
return (None, None);
|
||||
}
|
||||
|
||||
fn parse_ty_param_bounds(&mut self, allow_any_lifetime: bool)
|
||||
-> (Option<ast::Lifetime>,
|
||||
OwnedSlice<TyParamBound>) {
|
||||
let mut ret_lifetime = None;
|
||||
let mut result = vec!();
|
||||
loop {
|
||||
@ -3489,7 +3517,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
return (ret_lifetime, Some(OwnedSlice::from_vec(result)));
|
||||
return (ret_lifetime, OwnedSlice::from_vec(result));
|
||||
}
|
||||
|
||||
// matches typaram = type? IDENT optbounds ( EQ ty )?
|
||||
@ -3497,13 +3525,20 @@ impl<'a> Parser<'a> {
|
||||
let sized = self.parse_sized();
|
||||
let span = self.span;
|
||||
let ident = self.parse_ident();
|
||||
let (_, opt_bounds) = self.parse_optional_ty_param_bounds(false);
|
||||
let opt_bounds = {
|
||||
if self.eat(&token::COLON) {
|
||||
let (_, bounds) = self.parse_ty_param_bounds(false);
|
||||
Some(bounds)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
// For typarams we don't care about the difference b/w "<T>" and "<T:>".
|
||||
let bounds = opt_bounds.unwrap_or_default();
|
||||
|
||||
let default = if self.token == token::EQ {
|
||||
self.bump();
|
||||
Some(self.parse_ty(false))
|
||||
Some(self.parse_ty(true))
|
||||
}
|
||||
else { None };
|
||||
|
||||
@ -3548,7 +3583,7 @@ impl<'a> Parser<'a> {
|
||||
Some(token::COMMA),
|
||||
|p| {
|
||||
p.forbid_lifetime();
|
||||
p.parse_ty(false)
|
||||
p.parse_ty(true)
|
||||
}
|
||||
);
|
||||
(lifetimes, result.into_vec())
|
||||
@ -3804,7 +3839,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
let output = if self.eat(&token::RARROW) {
|
||||
self.parse_ty(false)
|
||||
self.parse_ty(true)
|
||||
} else {
|
||||
P(Ty {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -3830,7 +3865,7 @@ impl<'a> Parser<'a> {
|
||||
|p| p.parse_fn_block_arg());
|
||||
|
||||
let output = if self.eat(&token::RARROW) {
|
||||
self.parse_ty(false)
|
||||
self.parse_ty(true)
|
||||
} else {
|
||||
P(Ty {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -3942,7 +3977,7 @@ impl<'a> Parser<'a> {
|
||||
let could_be_trait = self.token != token::LPAREN;
|
||||
|
||||
// Parse the trait.
|
||||
let mut ty = self.parse_ty(false);
|
||||
let mut ty = self.parse_ty(true);
|
||||
|
||||
// Parse traits, if necessary.
|
||||
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
|
||||
@ -3965,7 +4000,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
ty = self.parse_ty(false);
|
||||
ty = self.parse_ty(true);
|
||||
opt_trait_ref
|
||||
} else {
|
||||
None
|
||||
@ -4008,7 +4043,7 @@ impl<'a> Parser<'a> {
|
||||
let generics = self.parse_generics();
|
||||
|
||||
let super_struct = if self.eat(&token::COLON) {
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
match ty.node {
|
||||
TyPath(_, None, _) => {
|
||||
Some(ty)
|
||||
@ -4051,7 +4086,7 @@ impl<'a> Parser<'a> {
|
||||
let struct_field_ = ast::StructField_ {
|
||||
kind: UnnamedField(p.parse_visibility()),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
ty: p.parse_ty(false),
|
||||
ty: p.parse_ty(true),
|
||||
attrs: attrs,
|
||||
};
|
||||
spanned(lo, p.span.hi, struct_field_)
|
||||
@ -4205,7 +4240,7 @@ impl<'a> Parser<'a> {
|
||||
let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
|
||||
let id = self.parse_ident();
|
||||
self.expect(&token::COLON);
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
self.expect(&token::EQ);
|
||||
let e = self.parse_expr();
|
||||
self.commit_expr_expecting(e, token::SEMI);
|
||||
@ -4386,7 +4421,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let ident = self.parse_ident();
|
||||
self.expect(&token::COLON);
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
let hi = self.span.hi;
|
||||
self.expect(&token::SEMI);
|
||||
box(GC) ast::ForeignItem {
|
||||
@ -4514,7 +4549,7 @@ impl<'a> Parser<'a> {
|
||||
let ident = self.parse_ident();
|
||||
let tps = self.parse_generics();
|
||||
self.expect(&token::EQ);
|
||||
let ty = self.parse_ty(false);
|
||||
let ty = self.parse_ty(true);
|
||||
self.expect(&token::SEMI);
|
||||
(ident, ItemTy(ty, tps), None)
|
||||
}
|
||||
@ -4562,7 +4597,7 @@ impl<'a> Parser<'a> {
|
||||
&token::LPAREN,
|
||||
&token::RPAREN,
|
||||
seq_sep_trailing_disallowed(token::COMMA),
|
||||
|p| p.parse_ty(false)
|
||||
|p| p.parse_ty(true)
|
||||
);
|
||||
for ty in arg_tys.move_iter() {
|
||||
args.push(ast::VariantArg {
|
||||
|
@ -495,6 +495,11 @@ impl<'a> State<'a> {
|
||||
}
|
||||
try!(self.pclose());
|
||||
}
|
||||
ast::TyParen(ref typ) => {
|
||||
try!(self.popen());
|
||||
try!(self.print_type(&**typ));
|
||||
try!(self.pclose());
|
||||
}
|
||||
ast::TyBareFn(f) => {
|
||||
let generics = ast::Generics {
|
||||
lifetimes: f.lifetimes.clone(),
|
||||
@ -1673,7 +1678,7 @@ impl<'a> State<'a> {
|
||||
|
||||
match *opt_bounds {
|
||||
None => Ok(()),
|
||||
Some(ref bounds) => self.print_bounds(&None, bounds, true),
|
||||
Some(ref bounds) => self.print_bounds(&None, bounds, true, true),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1932,9 +1937,16 @@ impl<'a> State<'a> {
|
||||
pub fn print_bounds(&mut self,
|
||||
region: &Option<ast::Lifetime>,
|
||||
bounds: &OwnedSlice<ast::TyParamBound>,
|
||||
print_colon_anyway: bool) -> IoResult<()> {
|
||||
print_colon_anyway: bool,
|
||||
print_plus_before_bounds: bool)
|
||||
-> IoResult<()> {
|
||||
let separator = if print_plus_before_bounds {
|
||||
"+"
|
||||
} else {
|
||||
":"
|
||||
};
|
||||
if !bounds.is_empty() || region.is_some() {
|
||||
try!(word(&mut self.s, ":"));
|
||||
try!(word(&mut self.s, separator));
|
||||
let mut first = true;
|
||||
match *region {
|
||||
Some(ref lt) => {
|
||||
@ -1976,7 +1988,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
Ok(())
|
||||
} else if print_colon_anyway {
|
||||
word(&mut self.s, ":")
|
||||
word(&mut self.s, separator)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -2011,7 +2023,10 @@ impl<'a> State<'a> {
|
||||
try!(s.word_space("type"));
|
||||
}
|
||||
try!(s.print_ident(param.ident));
|
||||
try!(s.print_bounds(&None, ¶m.bounds, false));
|
||||
try!(s.print_bounds(&None,
|
||||
¶m.bounds,
|
||||
false,
|
||||
false));
|
||||
match param.default {
|
||||
Some(ref default) => {
|
||||
try!(space(&mut s.s));
|
||||
@ -2214,7 +2229,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
opt_bounds.as_ref().map(|bounds| {
|
||||
self.print_bounds(opt_region, bounds, true)
|
||||
self.print_bounds(opt_region, bounds, true, false)
|
||||
});
|
||||
|
||||
try!(self.maybe_print_comment(decl.output.span.lo));
|
||||
|
@ -336,7 +336,7 @@ pub fn skip_ty<E, V: Visitor<E>>(_: &mut V, _: &Ty, _: E) {
|
||||
|
||||
pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
|
||||
match typ.node {
|
||||
TyUniq(ty) | TyVec(ty) | TyBox(ty) => {
|
||||
TyUniq(ty) | TyVec(ty) | TyBox(ty) | TyParen(ty) => {
|
||||
visitor.visit_ty(&*ty, env)
|
||||
}
|
||||
TyPtr(ref mutable_type) => {
|
||||
|
@ -27,7 +27,7 @@ impl Drop for Foo {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn registrar(_: &mut Registry) {
|
||||
local_data_key!(foo: Box<Any:Send>);
|
||||
foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
|
||||
local_data_key!(foo: Box<Any+Send>);
|
||||
foo.replace(Some(box Foo { foo: 10 } as Box<Any+Send>));
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ struct A {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A {v: box B{v: None} as Box<Foo:Send>};
|
||||
let a = A {v: box B{v: None} as Box<Foo+Send>};
|
||||
//~^ ERROR cannot pack type `~B`, which does not fulfill `Send`
|
||||
let v = Rc::new(RefCell::new(a));
|
||||
let w = v.clone();
|
||||
|
@ -45,15 +45,15 @@ fn test<'a,T,U:Copy>(_: &'a int) {
|
||||
|
||||
// borrowed object types are generally ok
|
||||
assert_copy::<&'a Dummy>();
|
||||
assert_copy::<&'a Dummy:Copy>();
|
||||
assert_copy::<&'static Dummy:Copy>();
|
||||
assert_copy::<&'a Dummy+Copy>();
|
||||
assert_copy::<&'static Dummy+Copy>();
|
||||
|
||||
// owned object types are not ok
|
||||
assert_copy::<Box<Dummy>>(); //~ ERROR does not fulfill
|
||||
assert_copy::<Box<Dummy:Copy>>(); //~ ERROR does not fulfill
|
||||
assert_copy::<Box<Dummy+Copy>>(); //~ ERROR does not fulfill
|
||||
|
||||
// mutable object types are not ok
|
||||
assert_copy::<&'a mut Dummy:Copy>(); //~ ERROR does not fulfill
|
||||
assert_copy::<&'a mut Dummy+Copy>(); //~ ERROR does not fulfill
|
||||
|
||||
// closures are like an `&mut` object
|
||||
assert_copy::<||>(); //~ ERROR does not fulfill
|
||||
|
@ -39,17 +39,17 @@ fn test<'a,T,U:Send>(_: &'a int) {
|
||||
// careful with object types, who knows what they close over...
|
||||
assert_send::<&'static Dummy>(); //~ ERROR does not fulfill `Send`
|
||||
assert_send::<&'a Dummy>(); //~ ERROR does not fulfill `Send`
|
||||
assert_send::<&'a Dummy:Send>(); //~ ERROR does not fulfill `Send`
|
||||
assert_send::<Box<Dummy:>>(); //~ ERROR does not fulfill `Send`
|
||||
assert_send::<&'a Dummy+Send>(); //~ ERROR does not fulfill `Send`
|
||||
assert_send::<Box<Dummy+>>(); //~ ERROR does not fulfill `Send`
|
||||
|
||||
// ...unless they are properly bounded
|
||||
assert_send::<&'static Dummy:Send>();
|
||||
assert_send::<Box<Dummy:Send>>();
|
||||
assert_send::<&'static Dummy+Send>();
|
||||
assert_send::<Box<Dummy+Send>>();
|
||||
|
||||
// but closure and object types can have lifetime bounds which make
|
||||
// them not ok (FIXME #5121)
|
||||
// assert_send::<proc:'a()>(); // ERROR does not fulfill `Send`
|
||||
// assert_send::<Box<Dummy:'a>>(); // ERROR does not fulfill `Send`
|
||||
// assert_send::<Box<Dummy+'a>>(); // ERROR does not fulfill `Send`
|
||||
|
||||
// unsafe ptrs are ok unless they point at unsendable things
|
||||
assert_send::<*int>();
|
||||
|
@ -12,14 +12,14 @@
|
||||
trait Foo {
|
||||
}
|
||||
|
||||
fn a(_x: Box<Foo:Send>) {
|
||||
fn a(_x: Box<Foo+Send>) {
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo:Share+Send>) {
|
||||
fn c(x: Box<Foo+Share+Send>) {
|
||||
a(x);
|
||||
}
|
||||
|
||||
fn d(x: Box<Foo:>) {
|
||||
fn d(x: Box<Foo+>) {
|
||||
a(x); //~ ERROR found no bounds
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,17 @@
|
||||
|
||||
trait Foo {}
|
||||
|
||||
fn a(_x: Box<Foo:Send>) {
|
||||
fn a(_x: Box<Foo+Send>) {
|
||||
}
|
||||
|
||||
fn b(_x: &'static Foo) { // should be same as &'static Foo:'static
|
||||
fn b(_x: &'static Foo) { // should be same as &'static Foo+'static
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo:Share>) {
|
||||
fn c(x: Box<Foo+Share>) {
|
||||
a(x); //~ ERROR expected bounds `Send`
|
||||
}
|
||||
|
||||
fn d(x: &'static Foo:Share) {
|
||||
fn d(x: &'static Foo+Share) {
|
||||
b(x); //~ ERROR expected bounds `'static`
|
||||
}
|
||||
|
||||
|
@ -12,5 +12,5 @@
|
||||
|
||||
|
||||
fn main() {
|
||||
fail!(box 413 as Box<::std::any::Any:Send>);
|
||||
fail!(box 413 as Box<::std::any::Any+Send>);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
|
||||
box Invoker {
|
||||
a: a,
|
||||
b: b,
|
||||
} as Box<Invokable<A>>:
|
||||
} as (Box<Invokable<A>>+)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
18
src/test/run-pass/as-precedence.rs
Normal file
18
src/test/run-pass/as-precedence.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
assert_eq!(3 as uint * 3, 9);
|
||||
assert_eq!(3 as (uint) * 3, 9);
|
||||
assert_eq!(3 as (uint) / 3, 1);
|
||||
assert_eq!(3 as uint + 3, 6);
|
||||
assert_eq!(3 as (uint) + 3, 6);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fn main() {
|
||||
let (tx, rx) = channel();
|
||||
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
|
||||
spawn(proc() {
|
||||
set_logger(box MyWriter(w) as Box<Logger:Send>);
|
||||
set_logger(box MyWriter(w) as Box<Logger+Send>);
|
||||
debug!("debug");
|
||||
info!("info");
|
||||
});
|
||||
|
@ -33,11 +33,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
|
||||
}
|
||||
}
|
||||
|
||||
fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
|
||||
fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>+> {
|
||||
box Invoker {
|
||||
a: a,
|
||||
b: b,
|
||||
} as Box<Invokable<A>>:
|
||||
} as (Box<Invokable<A>>+)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -12,21 +12,21 @@
|
||||
trait Foo {
|
||||
}
|
||||
|
||||
fn a(_x: Box<Foo:>) {
|
||||
fn a(_x: Box<Foo+>) {
|
||||
}
|
||||
|
||||
fn b(_x: Box<Foo:Send>) {
|
||||
fn b(_x: Box<Foo+Send>) {
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo:Share+Send>) {
|
||||
fn c(x: Box<Foo+Share+Send>) {
|
||||
a(x);
|
||||
}
|
||||
|
||||
fn d(x: Box<Foo:Send>) {
|
||||
fn d(x: Box<Foo+Send>) {
|
||||
b(x);
|
||||
}
|
||||
|
||||
fn e(x: Box<Foo>) { // sugar for Box<Foo:Owned>
|
||||
fn e(x: Box<Foo>) { // sugar for Box<Foo+Owned>
|
||||
a(x);
|
||||
}
|
||||
|
||||
|
@ -71,10 +71,10 @@ pub fn main() {
|
||||
swim_speed: 998,
|
||||
name: "alec_guinness".to_string(),
|
||||
};
|
||||
let arc = Arc::new(vec!(box catte as Box<Pet:Share+Send>,
|
||||
box dogge1 as Box<Pet:Share+Send>,
|
||||
box fishe as Box<Pet:Share+Send>,
|
||||
box dogge2 as Box<Pet:Share+Send>));
|
||||
let arc = Arc::new(vec!(box catte as Box<Pet+Share+Send>,
|
||||
box dogge1 as Box<Pet+Share+Send>,
|
||||
box fishe as Box<Pet+Share+Send>,
|
||||
box dogge2 as Box<Pet+Share+Send>));
|
||||
let (tx1, rx1) = channel();
|
||||
let arc1 = arc.clone();
|
||||
task::spawn(proc() { check_legs(arc1); tx1.send(()); });
|
||||
@ -89,21 +89,21 @@ pub fn main() {
|
||||
rx3.recv();
|
||||
}
|
||||
|
||||
fn check_legs(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
|
||||
fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
let mut legs = 0;
|
||||
for pet in arc.iter() {
|
||||
legs += pet.num_legs();
|
||||
}
|
||||
assert!(legs == 12);
|
||||
}
|
||||
fn check_names(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
|
||||
fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
for pet in arc.iter() {
|
||||
pet.name(|name| {
|
||||
assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
|
||||
})
|
||||
}
|
||||
}
|
||||
fn check_pedigree(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
|
||||
fn check_pedigree(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
for pet in arc.iter() {
|
||||
assert!(pet.of_good_pedigree());
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ struct Tree(@RefCell<TreeR>);
|
||||
struct TreeR {
|
||||
left: Option<Tree>,
|
||||
right: Option<Tree>,
|
||||
val: Box<to_str:Send>
|
||||
val: Box<to_str+Send>
|
||||
}
|
||||
|
||||
trait to_str {
|
||||
@ -57,10 +57,10 @@ fn foo<T:to_str>(x: T) -> String { x.to_str_() }
|
||||
pub fn main() {
|
||||
let t1 = Tree(@RefCell::new(TreeR{left: None,
|
||||
right: None,
|
||||
val: box 1 as Box<to_str:Send>}));
|
||||
val: box 1 as Box<to_str+Send>}));
|
||||
let t2 = Tree(@RefCell::new(TreeR{left: Some(t1),
|
||||
right: Some(t1),
|
||||
val: box 2 as Box<to_str:Send>}));
|
||||
val: box 2 as Box<to_str+Send>}));
|
||||
let expected =
|
||||
"[2, some([1, none, none]), some([1, none, none])]".to_string();
|
||||
assert!(t2.to_str_() == expected);
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
// This is an interesting test case. We have a trait (Bar) that is
|
||||
// implemented for a `Box<Foo>` object (note: no bounds). And then we
|
||||
// have a `Box<Foo:Send>` object. The impl for `Box<Foo>` is applicable
|
||||
// to `Box<Foo:Send>` because:
|
||||
// have a `Box<Foo+Send>` object. The impl for `Box<Foo>` is applicable
|
||||
// to `Box<Foo+Send>` because:
|
||||
//
|
||||
// 1. The trait Bar is contravariant w/r/t Self because `Self` appears
|
||||
// only in argument position.
|
||||
@ -30,7 +30,7 @@ impl Bar for Box<Foo> { fn dummy(&self) { } }
|
||||
fn wants_bar<B:Bar>(b: &B) { }
|
||||
|
||||
fn main() {
|
||||
let x: Box<Foo:Send> = (box SFoo);
|
||||
let x: Box<Foo+Send> = (box SFoo);
|
||||
wants_bar(&x);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user