Skip to content

Make &self parse explicit lifetimes, but don't really use them #5426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,10 @@ fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
'v' => { return ast::sty_value; }
'@' => { return ast::sty_box(get_mutability(string[1])); }
'~' => { return ast::sty_uniq(get_mutability(string[1])); }
'&' => { return ast::sty_region(get_mutability(string[1])); }
'&' => {
// FIXME(#4846) expl. region
return ast::sty_region(None, get_mutability(string[1]));
}
_ => {
fail!(fmt!("unknown self type code: `%c`", self_ty_kind as char));
}
Expand Down
53 changes: 34 additions & 19 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,32 +406,47 @@ fn encode_self_type(ebml_w: writer::Encoder, self_type: ast::self_ty_) {
ebml_w.start_tag(tag_item_trait_method_self_ty);

// Encode the base self type.
let ch;
match self_type {
sty_static => { ch = 's' as u8; }
sty_by_ref => { ch = 'r' as u8; }
sty_value => { ch = 'v' as u8; }
sty_region(_) => { ch = '&' as u8; }
sty_box(_) => { ch = '@' as u8; }
sty_uniq(_) => { ch = '~' as u8; }
}
ebml_w.writer.write(&[ ch ]);

// Encode mutability.
match self_type {
sty_static | sty_by_ref | sty_value => { /* No-op. */ }
sty_region(m_imm) | sty_box(m_imm) | sty_uniq(m_imm) => {
ebml_w.writer.write(&[ 'i' as u8 ]);
sty_static => {
ebml_w.writer.write(&[ 's' as u8 ]);
}
sty_by_ref => {
ebml_w.writer.write(&[ 'r' as u8 ]);
}
sty_value => {
ebml_w.writer.write(&[ 'v' as u8 ]);
}
sty_region(_, m) => {
// FIXME(#4846) encode custom lifetime
ebml_w.writer.write(&[ '&' as u8 ]);
encode_mutability(ebml_w, m);
}
sty_region(m_mutbl) | sty_box(m_mutbl) | sty_uniq(m_mutbl) => {
ebml_w.writer.write(&[ 'm' as u8 ]);
sty_box(m) => {
ebml_w.writer.write(&[ '@' as u8 ]);
encode_mutability(ebml_w, m);
}
sty_region(m_const) | sty_box(m_const) | sty_uniq(m_const) => {
ebml_w.writer.write(&[ 'c' as u8 ]);
sty_uniq(m) => {
ebml_w.writer.write(&[ '~' as u8 ]);
encode_mutability(ebml_w, m);
}
}

ebml_w.end_tag();

fn encode_mutability(ebml_w: writer::Encoder,
m: ast::mutability) {
match m {
m_imm => {
ebml_w.writer.write(&[ 'i' as u8 ]);
}
m_mutbl => {
ebml_w.writer.write(&[ 'm' as u8 ]);
}
m_const => {
ebml_w.writer.write(&[ 'c' as u8 ]);
}
}
}
}

fn encode_method_sort(ebml_w: writer::Encoder, sort: char) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ fn visit_fn(fk: &visit::fn_kind,
special_idents::self_,
by_ref));
}
sty_value | sty_region(_) | sty_box(_) | sty_uniq(_) => {
sty_value | sty_region(*) | sty_box(_) | sty_uniq(_) => {
fn_maps.add_variable(Arg(method.self_id,
special_idents::self_,
by_copy));
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ pub fn trans_trait_callee(bcx: block,
let llpair = self_datum.to_ref_llval(bcx);

let llpair = match explicit_self {
ast::sty_region(_) => Load(bcx, llpair),
ast::sty_region(*) => Load(bcx, llpair),
ast::sty_static | ast::sty_by_ref | ast::sty_value |
ast::sty_box(_) | ast::sty_uniq(_) => llpair
};
Expand Down Expand Up @@ -658,7 +658,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
bcx.tcx().sess.bug(~"methods with by-value self should not be \
called on objects");
}
ast::sty_region(_) => {
ast::sty_region(*) => {
// As before, we need to pass a pointer to a pointer to the
// payload.
match store {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub impl Reflector {
v,
ty::BoxTraitStore,
ast::sty_region(
None,
ast::m_imm)),
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
let result = scratch.to_value_llval(bcx);
Expand Down
9 changes: 6 additions & 3 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,12 @@ pub impl LookupContext/&self {
sty_box(_) | sty_uniq(_) => {
self_substs
}
sty_region(_) if self_substs.self_r.is_some() => {
sty_region(*) if self_substs.self_r.is_some() => {
// FIXME(#4846) ignoring expl lifetime here
self_substs
}
sty_region(_) => {
sty_region(*) => {
// FIXME(#4846) ignoring expl lifetime here
substs {
self_r:
Some(self.infcx().next_region_var(
Expand Down Expand Up @@ -1326,7 +1328,8 @@ pub fn transform_self_type_for_method(tcx: ty::ctxt,
sty_by_ref | sty_value => {
impl_ty
}
sty_region(mutability) => {
sty_region(_, mutability) => {
// FIXME(#4846) ignoring expl lifetime here
mk_rptr(tcx,
self_region.expect(~"self region missing for &self param"),
ty::mt { ty: impl_ty, mutbl: mutability })
Expand Down
12 changes: 7 additions & 5 deletions src/librustc/middle/typeck/check/regionmanip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ pub fn replace_bound_regions_in_fn_sig(
isr: isr_alist,
self_info: Option<SelfInfo>,
fn_sig: &ty::FnSig,
mapf: &fn(ty::bound_region) -> ty::Region) ->
(isr_alist, Option<SelfInfo>, ty::FnSig) {
mapf: &fn(ty::bound_region) -> ty::Region)
-> (isr_alist, Option<SelfInfo>, ty::FnSig)
{
// Take self_info apart; the self_ty part is the only one we want
// to update here.
let self_ty = self_info.map(|s| s.self_ty);
Expand All @@ -41,8 +42,10 @@ pub fn replace_bound_regions_in_fn_sig(

match self_info {
Some(SelfInfo {
explicit_self: codemap::spanned { node: ast::sty_region(m),
_}, _}) => {
explicit_self: codemap::spanned {
node: ast::sty_region(_, m),
// FIXME(#4846) ------^ Use this lifetime instead of self
_}, _}) => {
let region = ty::re_bound(ty::br_self);
let ty = ty::mk_rptr(tcx, region,
ty::mt { ty: ty::mk_self(tcx), mutbl: m });
Expand All @@ -51,7 +54,6 @@ pub fn replace_bound_regions_in_fn_sig(
_ => {}
}


for self_ty.each |t| { all_tys.push(*t) }

debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \
Expand Down
14 changes: 7 additions & 7 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,18 +1002,18 @@ impl to_bytes::IterBytes for ret_style {
#[auto_decode]
#[deriving_eq]
pub enum self_ty_ {
sty_static, // no self: static method
sty_by_ref, // old by-reference self: ``
sty_value, // by-value self: `self`
sty_region(mutability), // by-region self: `&self`
sty_box(mutability), // by-managed-pointer self: `@self`
sty_uniq(mutability) // by-unique-pointer self: `~self`
sty_static, // no self
sty_by_ref, // ``
sty_value, // `self`
sty_region(Option<@Lifetime>, mutability), // `&'lt self`
sty_box(mutability), // `@self`
sty_uniq(mutability) // `~self`
}

impl self_ty_ {
fn is_borrowed(&self) -> bool {
match *self {
sty_region(_) => true,
sty_region(*) => true,
_ => false
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/libsyntax/ext/auto_encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,10 @@ fn mk_ser_method(
ident: cx.ident_of(~"encode"),
attrs: ~[],
generics: ast_util::empty_generics(),
self_ty: codemap::spanned { node: ast::sty_region(ast::m_imm),
span: span },
self_ty: codemap::spanned {
node: ast::sty_region(None, ast::m_imm),
span: span
},
purity: ast::impure_fn,
decl: ser_decl,
body: ser_body,
Expand Down
6 changes: 3 additions & 3 deletions src/libsyntax/ext/deriving.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ fn create_eq_method(cx: @ext_ctxt,
let body_block = build::mk_simple_block(cx, span, body);

// Create the method.
let self_ty = spanned { node: sty_region(m_imm), span: span };
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
@ast::method {
ident: method_ident,
attrs: ~[],
Expand Down Expand Up @@ -398,7 +398,7 @@ fn create_iter_bytes_method(cx: @ext_ctxt,
let body_block = build::mk_block_(cx, span, statements);

// Create the method.
let self_ty = spanned { node: sty_region(m_imm), span: span };
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
let method_ident = cx.ident_of(~"iter_bytes");
@ast::method {
ident: method_ident,
Expand Down Expand Up @@ -448,7 +448,7 @@ fn create_clone_method(cx: @ext_ctxt,
let body_block = build::mk_simple_block(cx, span, expr);

// Create the self type and method identifier.
let self_ty = spanned { node: sty_region(m_imm), span: span };
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
let method_ident = cx.ident_of(~"clone");

// Create the method.
Expand Down
63 changes: 62 additions & 1 deletion src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,13 @@ pub impl Parser {
}
}

fn token_is_lifetime(&self, tok: &token::Token) -> bool {
match *tok {
token::LIFETIME(_) => true,
_ => false
}
}

fn parse_lifetime(&self) -> ast::Lifetime {
/*!
*
Expand Down Expand Up @@ -1041,6 +1048,11 @@ pub impl Parser {
}
}

fn token_is_mutability(&self, tok: &token::Token) -> bool {
self.token_is_keyword(&~"mut", tok) ||
self.token_is_keyword(&~"const", tok)
}

fn parse_mutability(&self) -> mutability {
if self.eat_keyword(&~"mut") {
m_mutbl
Expand Down Expand Up @@ -2844,14 +2856,63 @@ pub impl Parser {
}
}

fn maybe_parse_borrowed_self_ty(
self: &Parser
) -> ast::self_ty_ {
// The following things are possible to see here:
//
// fn(&self)
// fn(&mut self)
// fn(&'lt self)
// fn(&'lt mut self)
//
// We already know that the current token is `&`.

if (
self.token_is_keyword(&~"self", &self.look_ahead(1)))
{
self.bump();
self.expect_self_ident();
sty_region(None, m_imm)
} else if (
self.token_is_mutability(&self.look_ahead(1)) &&
self.token_is_keyword(&~"self", &self.look_ahead(2)))
{
self.bump();
let mutability = self.parse_mutability();
self.expect_self_ident();
sty_region(None, mutability)
} else if (
self.token_is_lifetime(&self.look_ahead(1)) &&
self.token_is_keyword(&~"self", &self.look_ahead(2)))
{
self.bump();
let lifetime = @self.parse_lifetime();
self.expect_self_ident();
sty_region(Some(lifetime), m_imm)
} else if (
self.token_is_lifetime(&self.look_ahead(1)) &&
self.token_is_mutability(&self.look_ahead(2)) &&
self.token_is_keyword(&~"self", &self.look_ahead(3)))
{
self.bump();
let lifetime = @self.parse_lifetime();
let mutability = self.parse_mutability();
self.expect_self_ident();
sty_region(Some(lifetime), mutability)
} else {
sty_by_ref
}
}

self.expect(&token::LPAREN);

// A bit of complexity and lookahead is needed here in order to to be
// backwards compatible.
let lo = self.span.lo;
let self_ty = match *self.token {
token::BINOP(token::AND) => {
maybe_parse_self_ty(sty_region, self)
maybe_parse_borrowed_self_ty(self)
}
token::AT => {
maybe_parse_self_ty(sty_box, self)
Expand Down
25 changes: 14 additions & 11 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1646,17 +1646,20 @@ pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) {
// Returns whether it printed anything
pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool {
match self_ty {
ast::sty_static | ast::sty_by_ref => { return false; }
ast::sty_value => { word(s.s, ~"self"); }
ast::sty_region(m) => {
word(s.s, ~"&"); print_mutability(s, m); word(s.s, ~"self");
}
ast::sty_box(m) => {
word(s.s, ~"@"); print_mutability(s, m); word(s.s, ~"self");
}
ast::sty_uniq(m) => {
word(s.s, ~"~"); print_mutability(s, m); word(s.s, ~"self");
}
ast::sty_static | ast::sty_by_ref => { return false; }
ast::sty_value => { word(s.s, ~"self"); }
ast::sty_region(lt, m) => {
word(s.s, ~"&");
print_opt_lifetime(s, lt);
print_mutability(s, m);
word(s.s, ~"self");
}
ast::sty_box(m) => {
word(s.s, ~"@"); print_mutability(s, m); word(s.s, ~"self");
}
ast::sty_uniq(m) => {
word(s.s, ~"~"); print_mutability(s, m); word(s.s, ~"self");
}
}
return true;
}
Expand Down
21 changes: 21 additions & 0 deletions src/test/run-pass/regions-expl-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.

// Test that you can insert an explicit lifetime in explicit self.

struct Foo {
f: uint
}

pub impl Foo {
fn foo(&'a self) {}
}

fn main() {}