提交 7cbd4b20 编写于 作者: N Niko Matsakis

Remove @ast::Region and replace with @ast::Lifetime.

Modify pretty-printer to emit lifetimes and fix a few minor
parser bugs that this uncovered.
上级 98ce99d5
......@@ -31,6 +31,7 @@
use syntax::ast_map;
use syntax::codemap::span;
use syntax::print::pprust;
use syntax::parse::token::special_idents;
use syntax::{ast, visit};
pub type parent = Option<ast::node_id>;
......@@ -546,29 +547,20 @@ fn add_dep(&mut self, from: ast::node_id) {
// with &self type, &self is also bound. We detect those last two
// cases via flags (anon_implies_rp and self_implies_rp) that are
// true when the anon or self region implies RP.
fn region_is_relevant(&self, r: @ast::region) -> bool {
match r.node {
ast::re_static => false,
ast::re_anon => self.anon_implies_rp,
ast::re_self => self.self_implies_rp,
ast::re_named(_) => false
}
}
// For named types like Foo, if there is no explicit region
// parameter, then we will add the anonymous region, so there is
// a dependency if the anonymous region implies rp.
//
// If the region is explicitly specified, then we follows the
// normal rules.
fn opt_region_is_relevant(&self,
opt_r: Option<@ast::region>)
-> bool {
debug!("opt_region_is_relevant: %? (anon_implies_rp=%b)",
opt_r, self.anon_implies_rp);
match opt_r {
None => self.anon_implies_rp,
Some(r) => self.region_is_relevant(r)
fn region_is_relevant(&self, r: Option<@ast::Lifetime>) -> bool {
match r {
None => {
self.anon_implies_rp
}
Some(ref l) if l.ident == special_idents::static => {
false
}
Some(ref l) if l.ident == special_idents::self_ => {
self.self_implies_rp
}
Some(_) => {
false
}
}
}
......@@ -672,8 +664,8 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
debug!("referenced fn type: %s",
pprust::ty_to_str(ty, sess.intr()));
match f.region {
Some(r) => {
if cx.region_is_relevant(r) {
Some(_) => {
if cx.region_is_relevant(f.region) {
cx.add_rp(cx.item_id,
cx.add_variance(rv_contravariant))
}
......@@ -699,7 +691,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
match cx.def_map.find(&id) {
Some(ast::def_ty(did)) | Some(ast::def_struct(did)) => {
if did.crate == ast::local_crate {
if cx.opt_region_is_relevant(path.rp) {
if cx.region_is_relevant(path.rp) {
cx.add_dep(did.node);
}
} else {
......@@ -709,7 +701,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
Some(variance) => {
debug!("reference to external, rp'd type %s",
pprust::ty_to_str(ty, sess.intr()));
if cx.opt_region_is_relevant(path.rp) {
if cx.region_is_relevant(path.rp) {
cx.add_rp(cx.item_id, cx.add_variance(variance))
}
}
......
......@@ -65,7 +65,8 @@
use core::vec;
use syntax::ast;
use syntax::codemap::span;
use syntax::print::pprust::{region_to_str, path_to_str};
use syntax::print::pprust::{lifetime_to_str, path_to_str};
use syntax::parse::token::special_idents;
use util::common::indenter;
pub trait AstConv {
......@@ -79,7 +80,7 @@ pub trait AstConv {
pub fn get_region_reporting_err(
tcx: ty::ctxt,
span: span,
a_r: Option<@ast::region>,
a_r: Option<@ast::Lifetime>,
res: Result<ty::Region, RegionError>) -> ty::Region
{
match res {
......@@ -87,13 +88,8 @@ pub fn get_region_reporting_err(
result::Err(ref e) => {
let descr = match a_r {
None => ~"anonymous lifetime",
Some(a) if a.node == ast::re_anon => {
~"anonymous lifetime"
}
Some(a) => {
fmt!("lifetime %s",
region_to_str(a, tcx.sess.intr()))
}
Some(a) => fmt!("lifetime %s",
lifetime_to_str(a, tcx.sess.intr()))
};
tcx.sess.span_err(
span,
......@@ -105,19 +101,28 @@ pub fn get_region_reporting_err(
}
pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
span: span,
a_r: @ast::region)
-> ty::Region {
let res = match a_r.node {
ast::re_static => Ok(ty::re_static),
ast::re_anon => rscope.anon_region(span),
ast::re_self => rscope.self_region(span),
ast::re_named(id) => rscope.named_region(span, id)
self: &AC,
rscope: &RS,
default_span: span,
opt_lifetime: Option<@ast::Lifetime>) -> ty::Region
{
let (span, res) = match opt_lifetime {
None => {
(default_span, rscope.anon_region(default_span))
}
Some(ref lifetime) if lifetime.ident == special_idents::static => {
(lifetime.span, Ok(ty::re_static))
}
Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
(lifetime.span, rscope.self_region(lifetime.span))
}
Some(ref lifetime) => {
(lifetime.span, rscope.named_region(lifetime.span,
lifetime.ident))
}
};
get_region_reporting_err(self.tcx(), span, Some(a_r), res)
get_region_reporting_err(self.tcx(), span, opt_lifetime, res)
}
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
......@@ -156,8 +161,8 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
let r = get_region_reporting_err(self.tcx(), path.span, None, res);
Some(r)
}
(Some(_), Some(r)) => {
Some(ast_region_to_region(self, rscope, path.span, r))
(Some(_), Some(_)) => {
Some(ast_region_to_region(self, rscope, path.span, path.rp))
}
};
......@@ -504,7 +509,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
sigil: ast::Sigil,
purity: ast::purity,
onceness: ast::Onceness,
opt_region: Option<@ast::region>,
opt_lifetime: Option<@ast::Lifetime>,
decl: &ast::fn_decl,
expected_tys: Option<ty::FnSig>,
span: span)
......@@ -514,9 +519,9 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
// resolve the function bound region in the original region
// scope `rscope`, not the scope of the function parameters
let bound_region = match opt_region {
Some(region) => {
ast_region_to_region(self, rscope, span, region)
let bound_region = match opt_lifetime {
Some(_) => {
ast_region_to_region(self, rscope, span, opt_lifetime)
}
None => {
match sigil {
......@@ -526,9 +531,8 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
ty::re_static
}
ast::BorrowedSigil => {
// &fn() defaults to an anonymous region:
let r_result = rscope.anon_region(span);
get_region_reporting_err(self.tcx(), span, None, r_result)
// &fn() defaults as normal for an omitted lifetime:
ast_region_to_region(self, rscope, span, opt_lifetime)
}
}
}
......
......@@ -2950,19 +2950,19 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
// determine the region bound, using the value given by the user
// (if any) and otherwise using a fresh region variable
let self_r = match pth.rp {
Some(r) => {
Some(_) => { // user supplied a lifetime parameter...
match tpt.region_param {
None => {
None => { // ...but the type is not lifetime parameterized!
fcx.ccx.tcx.sess.span_err
(span, ~"this item is not region-parameterized");
None
}
Some(_) => {
Some(ast_region_to_region(fcx, fcx, span, r))
Some(_) => { // ...and the type is lifetime parameterized, ok.
Some(ast_region_to_region(fcx, fcx, span, pth.rp))
}
}
}
None => {
None => { // no lifetime parameter supplied, insert default
fcx.region_var_if_parameterized(
tpt.region_param, span, region_lb)
}
......
......@@ -116,7 +116,7 @@ pub struct path {
span: span,
global: bool,
idents: ~[ident],
rp: Option<@region>,
rp: Option<@Lifetime>,
types: ~[@Ty],
}
......@@ -374,10 +374,10 @@ impl ToStr for Sigil {
#[deriving_eq]
pub enum vstore {
// FIXME (#3469): Change uint to @expr (actually only constant exprs)
vstore_fixed(Option<uint>), // [1,2,3,4]
vstore_uniq, // ~[1,2,3,4]
vstore_box, // @[1,2,3,4]
vstore_slice(@region) // &[1,2,3,4](foo)?
vstore_fixed(Option<uint>), // [1,2,3,4]
vstore_uniq, // ~[1,2,3,4]
vstore_box, // @[1,2,3,4]
vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4]
}
#[auto_encode]
......@@ -857,24 +857,6 @@ pub enum prim_ty {
ty_bool,
}
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub struct region {
id: node_id,
node: region_,
}
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub enum region_ {
re_anon,
re_static,
re_self,
re_named(ident)
}
#[auto_encode]
#[auto_decode]
#[deriving_eq]
......@@ -903,7 +885,7 @@ impl to_bytes::IterBytes for Onceness {
#[deriving_eq]
pub struct TyClosure {
sigil: Sigil,
region: Option<@region>,
region: Option<@Lifetime>,
purity: purity,
onceness: Onceness,
decl: fn_decl
......@@ -929,7 +911,7 @@ pub enum ty_ {
ty_vec(mt),
ty_fixed_length_vec(mt, uint),
ty_ptr(mt),
ty_rptr(@region, mt),
ty_rptr(Option<@Lifetime>, mt),
ty_closure(@TyClosure),
ty_bare_fn(@TyBareFn),
ty_tup(~[@Ty]),
......
......@@ -594,10 +594,7 @@ fn mk_ser_method(
let ty_s = @ast::Ty {
id: cx.next_id(),
node: ast::ty_rptr(
@ast::region {
id: cx.next_id(),
node: ast::re_anon,
},
None,
ast::mt {
ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
mutbl: ast::m_imm
......@@ -658,10 +655,7 @@ fn mk_deser_method(
let ty_d = @ast::Ty {
id: cx.next_id(),
node: ast::ty_rptr(
@ast::region {
id: cx.next_id(),
node: ast::re_anon,
},
None,
ast::mt {
ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
mutbl: ast::m_imm
......
......@@ -19,7 +19,7 @@
use ast::{item_enum, item_impl, item_struct, Generics};
use ast::{m_imm, meta_item, method};
use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
use ast::{re_anon, stmt, struct_def, struct_variant_kind};
use ast::{stmt, struct_def, struct_variant_kind};
use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
use ext::base::ext_ctxt;
......@@ -147,9 +147,8 @@ fn create_eq_method(cx: ext_ctxt,
span,
type_ident,
generics);
let arg_region = @ast::region { id: cx.next_id(), node: re_anon };
let arg_type = ty_rptr(
arg_region,
None,
ast::mt { ty: arg_path_type, mutbl: m_imm }
);
let arg_type = @ast::Ty {
......
......@@ -52,6 +52,7 @@ pub enum ObsoleteSyntax {
ObsoleteRecordType,
ObsoleteRecordPattern,
ObsoleteAssertion,
ObsoletePostFnTySigil,
}
impl to_bytes::IterBytes for ObsoleteSyntax {
......@@ -160,6 +161,11 @@ fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
"assertion",
"use `fail_unless!()` instead"
),
ObsoletePostFnTySigil => (
"fn sigil in postfix position",
"Rather than `fn@`, `fn~`, or `fn&`, \
write `@fn`, `~fn`, and `&fn` respectively"
),
};
self.report(sp, kind, kind_str, desc);
......
......@@ -14,7 +14,7 @@
use ast::{CallSugar, NoSugar, DoSugar, ForSugar};
use ast::{TyBareFn, TyClosure};
use ast::{RegionTyParamBound, TraitTyParamBound};
use ast::{provided, public, pure_fn, purity, re_static};
use ast::{provided, public, pure_fn, purity};
use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
use ast::{blk_check_mode, box, by_copy, by_ref, by_val};
......@@ -40,9 +40,9 @@
use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability};
use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct, pat_tup};
use ast::{pat_uniq, pat_wild, path, private};
use ast::{re_self, re_anon, re_named, region, rem, required};
use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct};
use ast::{pat_tup, pat_uniq, pat_wild, path, private};
use ast::{rem, required};
use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
use ast::{struct_immutable, struct_mutable, struct_variant_kind, subtract};
......@@ -76,7 +76,7 @@
use parse::obsolete::{ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer};
use parse::obsolete::{ObsoleteMutVector, ObsoleteTraitImplVisibility};
use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern};
use parse::obsolete::{ObsoleteAssertion};
use parse::obsolete::{ObsoleteAssertion, ObsoletePostFnTySigil};
use parse::prec::{as_prec, token_to_binop};
use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
......@@ -363,12 +363,13 @@ fn parse_ty_bare_fn(&self) -> ty_
});
}
fn parse_ty_closure(&self, pre_sigil: Option<ast::Sigil>,
pre_region_name: Option<ident>) -> ty_
fn parse_ty_closure(&self,
sigil: ast::Sigil,
region: Option<@ast::Lifetime>) -> ty_
{
/*
(&|~|@) [r/] [pure|unsafe] [once] fn <'lt> (S) -> T
(&|~|@) ['r] [pure|unsafe] [once] fn <'lt> (S) -> T
^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^ ^~~~^ ^~^ ^
| | | | | | |
| | | | | | Return type
......@@ -388,13 +389,10 @@ fn parse_ty_closure(&self, pre_sigil: Option<ast::Sigil>,
let onceness = parse_onceness(self);
self.expect_keyword(&~"fn");
let sigil = match pre_sigil { None => BorrowedSigil, Some(p) => p };
let region = if pre_region_name.is_some() {
Some(self.region_from_name(pre_region_name))
} else {
None
};
if self.parse_fn_ty_sigil().is_some() {
self.obsolete(*self.span,
ObsoletePostFnTySigil);
}
return ty_closure(@TyClosure {
sigil: sigil,
......@@ -432,7 +430,7 @@ fn parse_ty_fn_decl(&self) -> fn_decl {
*/
if self.eat(&token::LT) {
let _lifetimes = self.parse_lifetimes();
self.expect(&token::GT);
self.expect_gt();
}
let inputs = self.parse_unspanned_seq(
&token::LPAREN,
......@@ -575,38 +573,6 @@ fn parse_ret_ty(&self) -> (ret_style, @Ty) {
}
}
fn region_from_name(&self, s: Option<ident>) -> @region {
let r = match s {
Some(id) if id == special_idents::static => ast::re_static,
Some(id) if id == special_idents::self_ => re_self,
Some(id) => re_named(id),
None => re_anon
};
@ast::region { id: self.get_id(), node: r }
}
// Parses something like "&x"
fn parse_region(&self) -> @region {
self.expect(&token::BINOP(token::AND));
match *self.token {
token::IDENT(sid, _) => {
self.bump();
self.region_from_name(Some(sid))
}
_ => {
self.region_from_name(None)
}
}
}
fn region_from_lifetime(&self, l: &ast::Lifetime) -> @region {
// eventually `ast::region` should go away in favor of
// `ast::Lifetime`. For now we convert between them.
self.region_from_name(Some(l.ident))
}
fn parse_ty(&self, colons_before_params: bool) -> @Ty {
maybe_whole!(self, nt_ty);
......@@ -681,7 +647,8 @@ fn parse_ty(&self, colons_before_params: bool) -> @Ty {
} else if self.eat_keyword(&~"extern") {
self.parse_ty_bare_fn()
} else if self.token_is_closure_keyword(&copy *self.token) {
self.parse_ty_closure(None, None)
// self.warn(fmt!("Old-school closure keyword"));
self.parse_ty_closure(ast::BorrowedSigil, None)
} else if *self.token == token::MOD_SEP
|| is_ident_or_path(&*self.token) {
let path = self.parse_path_with_tps(colons_before_params);
......@@ -701,20 +668,20 @@ fn parse_box_or_uniq_pointee(
{
// @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types:
match *self.token {
token::LIFETIME(rname) => {
token::LIFETIME(*) => {
let lifetime = @self.parse_lifetime();
self.bump();
return self.parse_ty_closure(Some(sigil), Some(rname));
return self.parse_ty_closure(sigil, Some(lifetime));
}
token::IDENT(rname, _) => {
token::IDENT(*) => {
if self.look_ahead(1u) == token::BINOP(token::SLASH) &&
self.token_is_closure_keyword(&self.look_ahead(2u))
{
self.bump();
self.bump();
return self.parse_ty_closure(Some(sigil), Some(rname));
let lifetime = @self.parse_lifetime();
return self.parse_ty_closure(sigil, Some(lifetime));
} else if self.token_is_closure_keyword(&copy *self.token) {
return self.parse_ty_closure(Some(sigil), None);
return self.parse_ty_closure(sigil, None);
}
}
_ => {}
......@@ -735,31 +702,14 @@ fn parse_box_or_uniq_pointee(
fn parse_borrowed_pointee(&self) -> ty_ {
// look for `&'lt` or `&foo/` and interpret `foo` as the region name:
let rname = match *self.token {
token::LIFETIME(sid) => {
self.bump();
Some(sid)
}
token::IDENT(sid, _) => {
if self.look_ahead(1u) == token::BINOP(token::SLASH) {
self.bump(); self.bump();
Some(sid)
} else {
None
}
}
_ => { None }
};
let opt_lifetime = self.parse_opt_lifetime();
if self.token_is_closure_keyword(&copy *self.token) {
return self.parse_ty_closure(Some(BorrowedSigil), rname);
return self.parse_ty_closure(BorrowedSigil, opt_lifetime);
}
let r = self.region_from_name(rname);
let mt = self.parse_mt();
return ty_rptr(r, mt);
return ty_rptr(opt_lifetime, mt);
}
fn parse_arg_mode(&self) -> mode {
......@@ -939,19 +889,27 @@ fn parse_path_with_tps(&self, colons: bool) -> @ast::path {
return path;
}
// Parse the region parameter, if any, which will
// Parse the (obsolete) trailing region parameter, if any, which will
// be written "foo/&x"
let rp_slash = {
// Hack: avoid parsing vstores like /@ and /~. This is painful
// because the notation for region bounds and the notation for
// vstores is... um... the same. I guess that's my fault. This
// is still not ideal as for &str we end up parsing more than we
// ought to and have to sort it out later.
if *self.token == token::BINOP(token::SLASH)
&& self.look_ahead(1u) == token::BINOP(token::AND) {
self.expect(&token::BINOP(token::SLASH));
Some(self.parse_region())
&& self.look_ahead(1u) == token::BINOP(token::AND)
{
self.bump(); self.bump();
match *self.token {
token::IDENT(sid, _) => {
let span = copy self.span;
self.bump();
Some(@ast::Lifetime {
id: self.get_id(),
span: *span,
ident: sid
})
}
_ => {
self.fatal(fmt!("Expected a lifetime name"));
}
}
} else {
None
}
......@@ -967,7 +925,7 @@ fn parse_path_with_tps(&self, colons: bool) -> @ast::path {
if v.len() == 0 {
None
} else if v.len() == 1 {
Some(self.region_from_lifetime(v.get(0)))
Some(@*v.get(0))
} else {
self.fatal(fmt!("Expected at most one \
lifetime name (for now)"));
......@@ -981,16 +939,26 @@ fn parse_path_with_tps(&self, colons: bool) -> @ast::path {
.. copy *path }
}
fn parse_opt_lifetime(&self) -> Option<ast::Lifetime> {
fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> {
/*!
*
* Parses 0 or 1 lifetime.
*/
match *self.token {
token::LIFETIME(_) => {
Some(self.parse_lifetime())
token::LIFETIME(*) => {
Some(@self.parse_lifetime())
}
// Also accept the (obsolete) syntax `foo/`
token::IDENT(*) => {
if self.look_ahead(1u) == token::BINOP(token::SLASH) {
Some(@self.parse_lifetime())
} else {
None
}
}
_ => {
None
}
......@@ -1005,13 +973,27 @@ fn parse_lifetime(&self) -> ast::Lifetime {
match *self.token {
token::LIFETIME(i) => {
let span = copy self.span;
self.bump();
return ast::Lifetime {
id: self.get_id(),
span: *span,
ident: i
};
}
// Also accept the (obsolete) syntax `foo/`
token::IDENT(i, _) => {
let span = copy self.span;
self.bump();
self.expect(&token::BINOP(token::SLASH));
return ast::Lifetime {
id: self.get_id(),
span: *self.span,
span: *span,
ident: i
};
}
_ => {
self.fatal(fmt!("Expected a lifetime name"));
}
......@@ -1041,6 +1023,7 @@ fn parse_lifetimes(&self) -> OptVec<ast::Lifetime> {
match *self.token {
token::COMMA => { self.bump();}
token::GT => { return res; }
token::BINOP(token::SHR) => { return res; }
_ => {
self.fatal(~"expected `,` or `>` after lifetime name");
}
......
......@@ -146,8 +146,8 @@ pub fn expr_to_str(e: @ast::expr, intr: @ident_interner) -> ~str {
to_str(e, print_expr, intr)
}
pub fn region_to_str(e: @ast::region, intr: @ident_interner) -> ~str {
to_str(e, |s, e| print_region(s, ~"&", e, ~""), intr)
pub fn lifetime_to_str(e: &ast::Lifetime, intr: @ident_interner) -> ~str {
to_str(e, print_lifetime, intr)
}
pub fn tt_to_str(tt: ast::token_tree, intr: @ident_interner) -> ~str {
......@@ -355,23 +355,11 @@ pub fn print_foreign_mod(s: @ps, nmod: ast::foreign_mod,
for nmod.items.each |item| { print_foreign_item(s, *item); }
}
pub fn print_region(s: @ps, prefix: ~str, region: @ast::region, sep: ~str) {
word(s.s, prefix);
match region.node {
ast::re_anon => {
return;
}
ast::re_static => {
word_space(s, ~"static")
}
ast::re_self => {
word_space(s, ~"self")
}
ast::re_named(name) => {
print_ident(s, name);
}
pub fn print_opt_lifetime(s: @ps, lifetime: Option<@ast::Lifetime>) {
for lifetime.each |l| {
print_lifetime(s, *l);
nbsp(s);
}
word(s.s, sep);
}
pub fn print_type(s: @ps, &&ty: @ast::Ty) {
......@@ -397,8 +385,9 @@ pub fn print_type_ex(s: @ps, &&ty: @ast::Ty, print_colons: bool) {
word(s.s, ~"]");
}
ast::ty_ptr(mt) => { word(s.s, ~"*"); print_mt(s, mt); }
ast::ty_rptr(region, mt) => {
print_region(s, ~"&", region, ~"/");
ast::ty_rptr(lifetime, mt) => {
word(s.s, ~"&");
print_opt_lifetime(s, lifetime);
print_mt(s, mt);
}
ast::ty_tup(elts) => {
......@@ -1048,7 +1037,10 @@ pub fn print_vstore(s: @ps, t: ast::vstore) {
ast::vstore_fixed(None) => word(s.s, ~"_"),
ast::vstore_uniq => word(s.s, ~"~"),
ast::vstore_box => word(s.s, ~"@"),
ast::vstore_slice(r) => print_region(s, ~"&", r, ~"/")
ast::vstore_slice(r) => {
word(s.s, ~"&");
print_opt_lifetime(s, r);
}
}
}
......@@ -1501,17 +1493,18 @@ pub fn print_path(s: @ps, &&path: @ast::path, colons_before_params: bool) {
if path.rp.is_some() || !path.types.is_empty() {
if colons_before_params { word(s.s, ~"::"); }
match path.rp {
None => { /* ok */ }
Some(r) => {
word(s.s, ~"/");
print_region(s, ~"&", r, ~"");
}
}
if !path.types.is_empty() {
if path.rp.is_some() || !path.types.is_empty() {
word(s.s, ~"<");
for path.rp.each |r| {
print_lifetime(s, *r);
if !path.types.is_empty() {
word_space(s, ~",");
}
}
commasep(s, inconsistent, path.types, print_type);
word(s.s, ~">");
}
}
......@@ -1749,7 +1742,7 @@ pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
}
}
pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) {
pub fn print_lifetime(s: @ps, &&lifetime: &ast::Lifetime) {
word(s.s, ~"'");
print_ident(s, lifetime.ident);
}
......@@ -1908,7 +1901,7 @@ pub fn print_arg(s: @ps, input: ast::arg) {
pub fn print_ty_fn(s: @ps,
opt_abi: Option<ast::Abi>,
opt_sigil: Option<ast::Sigil>,
opt_region: Option<@ast::region>,
opt_region: Option<@ast::Lifetime>,
purity: ast::purity,
onceness: ast::Onceness,
decl: &ast::fn_decl, id: Option<ast::ident>,
......@@ -1921,7 +1914,7 @@ pub fn print_ty_fn(s: @ps,
print_self_ty_if_static(s, opt_self_ty);
print_opt_abi(s, opt_abi);
print_opt_sigil(s, opt_sigil);
for opt_region.each |r| { print_region(s, ~"", *r, ~"/"); }
print_opt_lifetime(s, opt_region);
print_purity(s, purity);
print_onceness(s, onceness);
word(s.s, ~"fn");
......
......@@ -23,17 +23,17 @@ fn main() {
let x: float<int>; //~ ERROR type parameters are not allowed on this type
let x: char<int>; //~ ERROR type parameters are not allowed on this type
let x: int/&; //~ ERROR region parameters are not allowed on this type
let x: i8/&; //~ ERROR region parameters are not allowed on this type
let x: i16/&; //~ ERROR region parameters are not allowed on this type
let x: i32/&; //~ ERROR region parameters are not allowed on this type
let x: i64/&; //~ ERROR region parameters are not allowed on this type
let x: uint/&; //~ ERROR region parameters are not allowed on this type
let x: u8/&; //~ ERROR region parameters are not allowed on this type
let x: u16/&; //~ ERROR region parameters are not allowed on this type
let x: u32/&; //~ ERROR region parameters are not allowed on this type
let x: u64/&; //~ ERROR region parameters are not allowed on this type
let x: float/&; //~ ERROR region parameters are not allowed on this type
let x: char/&; //~ ERROR region parameters are not allowed on this type
let x: int<'static>; //~ ERROR region parameters are not allowed on this type
let x: i8<'static>; //~ ERROR region parameters are not allowed on this type
let x: i16<'static>; //~ ERROR region parameters are not allowed on this type
let x: i32<'static>; //~ ERROR region parameters are not allowed on this type
let x: i64<'static>; //~ ERROR region parameters are not allowed on this type
let x: uint<'static>; //~ ERROR region parameters are not allowed on this type
let x: u8<'static>; //~ ERROR region parameters are not allowed on this type
let x: u16<'static>; //~ ERROR region parameters are not allowed on this type
let x: u32<'static>; //~ ERROR region parameters are not allowed on this type
let x: u64<'static>; //~ ERROR region parameters are not allowed on this type
let x: float<'static>; //~ ERROR region parameters are not allowed on this type
let x: char<'static>; //~ ERROR region parameters are not allowed on this type
}
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
const c_x: &'blk int = &22; //~ ERROR Illegal lifetime &blk: only 'static is allowed here
const c_x: &'blk int = &22; //~ ERROR Illegal lifetime 'blk: only 'static is allowed here
const c_y: &int = &22; //~ ERROR Illegal anonymous lifetime: only 'static is allowed here
const c_z: &'static int = &22;
......
......@@ -10,7 +10,7 @@
enum yes0<'lt> {
// This will eventually be legal (and in fact the only way):
X3(&'lt uint) //~ ERROR Illegal lifetime &lt: only 'self is allowed allowed as part of a type declaration
X3(&'lt uint) //~ ERROR Illegal lifetime 'lt: only 'self is allowed allowed as part of a type declaration
}
enum yes1 {
......@@ -18,7 +18,7 @@ enum yes1 {
}
enum yes2 {
X5(&'foo uint) //~ ERROR Illegal lifetime &foo: only 'self is allowed allowed as part of a type declaration
X5(&'foo uint) //~ ERROR Illegal lifetime 'foo: only 'self is allowed allowed as part of a type declaration
}
fn main() {}
......@@ -17,7 +17,7 @@ struct yes1<'self> {
}
struct yes2<'self> {
x: &'foo uint, //~ ERROR Illegal lifetime &foo: only 'self is allowed allowed as part of a type declaration
x: &'foo uint, //~ ERROR Illegal lifetime 'foo: only 'self is allowed allowed as part of a type declaration
}
fn main() {}
......@@ -13,19 +13,16 @@ struct direct<'self> {
}
struct indirect1 {
// Here the lifetime parameter of direct is bound by the fn()
g: @fn(direct)
}
struct indirect2 {
g: @fn(direct/&)
}
struct indirect3 {
struct indirect2<'self> {
// But here it is set to 'self
g: @fn(direct<'self>)
}
fn take_direct(p: direct) -> direct { p } //~ ERROR mismatched types
fn take_indirect1(p: indirect1) -> indirect1 { p }
fn take_indirect2(p: indirect2) -> indirect2 { p }
fn take_indirect3(p: indirect3) -> indirect3 { p } //~ ERROR mismatched types
fn take_indirect2(p: indirect2) -> indirect2 { p } //~ ERROR mismatched types
fn main() {}
......@@ -13,7 +13,7 @@
// contains region pointers
enum foo = ~fn(x: &int);
fn take_foo(x: foo/&) {} //~ ERROR no region bound is allowed on `foo`
fn take_foo(x: foo<'static>) {} //~ ERROR no region bound is allowed on `foo`
fn main() {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册