From a6187c62e93ba96dce8f19849fb7016f4f941f8c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 9 Mar 2013 19:43:53 -0500 Subject: [PATCH] Make &self permit explicit lifetimes, but don't really use them (this will be needed for snapshotting at some point). --- src/librustc/metadata/decoder.rs | 5 +- src/librustc/metadata/encoder.rs | 53 ++++++++++------ src/librustc/middle/liveness.rs | 2 +- src/librustc/middle/trans/meth.rs | 4 +- src/librustc/middle/trans/reflect.rs | 1 + src/librustc/middle/typeck/check/method.rs | 9 ++- .../middle/typeck/check/regionmanip.rs | 12 ++-- src/libsyntax/ast.rs | 14 ++--- src/libsyntax/ext/auto_encode.rs | 6 +- src/libsyntax/ext/deriving.rs | 6 +- src/libsyntax/parse/parser.rs | 63 ++++++++++++++++++- src/libsyntax/print/pprust.rs | 25 ++++---- src/test/run-pass/regions-expl-self.rs | 21 +++++++ 13 files changed, 166 insertions(+), 55 deletions(-) create mode 100644 src/test/run-pass/regions-expl-self.rs diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 658b32edf2163..2e8b536e44dae 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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)); } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 4b1260e76d0d4..83550289a4fa1 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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) { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 2afe9564b207d..34fe7af8f1c67 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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)); diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 5a46c24b93940..51e26d3cfef1f 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -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 }; @@ -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 { diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index a4a7d958e692b..955bc56310704 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -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); diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index d673cf6a39ad6..39c0948ec6712 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -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( @@ -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 }) diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 98f49e48c0849..ffdd40c6cd8ca 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -30,8 +30,9 @@ pub fn replace_bound_regions_in_fn_sig( isr: isr_alist, self_info: Option, fn_sig: &ty::FnSig, - mapf: &fn(ty::bound_region) -> ty::Region) -> - (isr_alist, Option, ty::FnSig) { + mapf: &fn(ty::bound_region) -> ty::Region) + -> (isr_alist, Option, 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); @@ -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 }); @@ -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, \ diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e5fb2ad153cf1..f603b86b58a70 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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 } } diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 8c02b4323715d..294174dc8f9b3 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -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, diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index 26b5b4566b7f7..324c5289eb399 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -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: ~[], @@ -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, @@ -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. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a30b910b347eb..1881a2115d76d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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 { /*! * @@ -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 @@ -2844,6 +2856,55 @@ 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 @@ -2851,7 +2912,7 @@ pub impl Parser { 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) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5aae5570dbfee..dcd57e1232932 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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; } diff --git a/src/test/run-pass/regions-expl-self.rs b/src/test/run-pass/regions-expl-self.rs new file mode 100644 index 0000000000000..736ed24097c89 --- /dev/null +++ b/src/test/run-pass/regions-expl-self.rs @@ -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 or the MIT license +// , 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() {} \ No newline at end of file