mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-20 19:52:48 +00:00
auto merge of #5296 : nikomatsakis/rust/region-syntax-expl-lifetimes-2, r=nikomatsakis
Modify pretty-printer to emit lifetimes and fix a few minor parser bugs that this uncovered. r? whomever.
This commit is contained in:
commit
a347e9d635
@ -31,6 +31,7 @@ use std::oldmap::HashMap;
|
||||
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 @@ pub impl DetermineRpCtxt {
|
||||
// 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::result;
|
||||
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::{enum_variant_kind, expr, expr_match, ident, impure_fn, item, item_};
|
||||
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 @@ pub impl Parser {
|
||||
"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::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil, RustAbi};
|
||||
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::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const};
|
||||
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::{ObsoleteUnsafeBlock, ObsoleteImplSyntax};
|
||||
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 @@ pub impl Parser {
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ pub impl Parser {
|
||||
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 @@ pub impl Parser {
|
||||
*/
|
||||
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 @@ pub impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ pub impl Parser {
|
||||
} else if self.eat_keyword(&~"extern") {
|
||||
self.parse_ty_bare_fn()
|
||||
} else if self.token_is_closure_keyword(© *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 @@ pub impl Parser {
|
||||
{
|
||||
// @'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(© *self.token) {
|
||||
return self.parse_ty_closure(Some(sigil), None);
|
||||
return self.parse_ty_closure(sigil, None);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -735,31 +702,14 @@ pub impl Parser {
|
||||
|
||||
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(© *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 @@ pub impl Parser {
|
||||
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 @@ pub impl Parser {
|
||||
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 @@ pub impl Parser {
|
||||
.. 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 @@ pub impl Parser {
|
||||
|
||||
match *self.token {
|
||||
token::LIFETIME(i) => {
|
||||
let span = copy self.span;
|
||||
self.bump();
|
||||
return ast::Lifetime {
|
||||
id: self.get_id(),
|
||||
span: *self.span,
|
||||
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: *span,
|
||||
ident: i
|
||||
};
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.fatal(fmt!("Expected a lifetime name"));
|
||||
}
|
||||
@ -1041,6 +1023,7 @@ pub impl Parser {
|
||||
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 @@ let x: u64<int>; //~ ERROR type parameters are not allowed on this type
|
||||
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 <: 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() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user