diff --git a/src/libextra/flate.rs b/src/libextra/flate.rs index 8024b9aa1596c..d5228b0a72536 100644 --- a/src/libextra/flate.rs +++ b/src/libextra/flate.rs @@ -25,13 +25,13 @@ pub mod rustrt { #[link_name = "rustrt"] extern { - pub fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, + pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, src_buf_len: size_t, pout_len: *mut size_t, flags: c_int) -> *c_void; - pub fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void, + pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, src_buf_len: size_t, pout_len: *mut size_t, flags: c_int) diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index 3a1129b1dd94e..349f1909df0a3 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -17,6 +17,7 @@ use syntax::attr; use syntax::codemap::dummy_sp; use syntax::codemap; use syntax::fold; +use syntax::opt_vec; static STD_VERSION: &'static str = "0.8-pre"; @@ -90,12 +91,18 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate { let prelude_path = ast::Path { span: dummy_sp(), global: false, - idents: ~[ - sess.ident_of("std"), - sess.ident_of("prelude") + segments: ~[ + ast::PathSegment { + identifier: sess.ident_of("std"), + lifetime: None, + types: opt_vec::Empty, + }, + ast::PathSegment { + identifier: sess.ident_of("prelude"), + lifetime: None, + types: opt_vec::Empty, + }, ], - rp: None, - types: ~[] }; let vp = @spanned(ast::view_path_glob(prelude_path, n2)); diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index d2d2a8b4be99d..f93170e90bdd4 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -16,14 +16,15 @@ use front::config; use std::vec; use syntax::ast_util::*; +use syntax::attr::AttrMetaMethods; use syntax::attr; use syntax::codemap::{dummy_sp, span, ExpnInfo, NameAndSpan}; use syntax::codemap; use syntax::ext::base::ExtCtxt; use syntax::fold; +use syntax::opt_vec; use syntax::print::pprust; use syntax::{ast, ast_util}; -use syntax::attr::AttrMetaMethods; type node_id_gen = @fn() -> ast::NodeId; @@ -340,19 +341,27 @@ fn nospan(t: T) -> codemap::spanned { } fn path_node(ids: ~[ast::ident]) -> ast::Path { - ast::Path { span: dummy_sp(), - global: false, - idents: ids, - rp: None, - types: ~[] } + ast::Path { + span: dummy_sp(), + global: false, + segments: ids.consume_iter().transform(|identifier| ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }).collect() + } } fn path_node_global(ids: ~[ast::ident]) -> ast::Path { - ast::Path { span: dummy_sp(), - global: true, - idents: ids, - rp: None, - types: ~[] } + ast::Path { + span: dummy_sp(), + global: true, + segments: ids.consume_iter().transform(|identifier| ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }).collect() + } } fn mk_tests(cx: &TestCtxt) -> @ast::item { diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c3097d1aa6657..4a5ba06557652 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -792,12 +792,9 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId, fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ { fn get_mutability(ch: u8) -> ast::mutability { match ch as char { - 'i' => { ast::m_imm } - 'm' => { ast::m_mutbl } - 'c' => { ast::m_const } - _ => { - fail!("unknown mutability character: `%c`", ch as char) - } + 'i' => ast::m_imm, + 'm' => ast::m_mutbl, + _ => fail!("unknown mutability character: `%c`", ch as char), } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d847d85112653..24d912034d851 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -643,15 +643,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic 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 ]); - } + m_imm => ebml_w.writer.write(&[ 'i' as u8 ]), + m_mutbl => ebml_w.writer.write(&[ 'm' as u8 ]), } } } @@ -1003,7 +996,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); match ty.node { - ast::ty_path(ref path, ref bounds, _) if path.idents.len() == 1 => { + ast::ty_path(ref path, ref bounds, _) if path.segments + .len() == 1 => { assert!(bounds.is_none()); encode_impl_type_basename(ecx, ebml_w, ast_util::path_to_ident(path)); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 89b30e46ac06d..3606ecd8d24c1 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -138,12 +138,20 @@ fn parse_path(st: &mut PState) -> @ast::Path { ':' => { next(st); next(st); } c => { if c == '(' { - return @ast::Path { span: dummy_sp(), - global: false, - idents: idents, - rp: None, - types: ~[] }; - } else { idents.push(parse_ident_(st, is_last)); } + return @ast::Path { + span: dummy_sp(), + global: false, + segments: idents.consume_iter().transform(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; + } else { + idents.push(parse_ident_(st, is_last)); + } } } }; @@ -417,7 +425,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { fn parse_mutability(st: &mut PState) -> ast::mutability { match peek(st) { 'm' => { next(st); ast::m_mutbl } - '?' => { next(st); ast::m_const } _ => { ast::m_imm } } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index ffd79433b7693..ea01b1a7a8b7f 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -100,7 +100,6 @@ fn enc_mutability(w: @io::Writer, mt: ast::mutability) { match mt { m_imm => (), m_mutbl => w.write_char('m'), - m_const => w.write_char('?') } } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index c3bb2000447f7..9e5d79fc48778 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -23,7 +23,7 @@ use mc = middle::mem_categorization; use middle::borrowck::*; use middle::moves; use middle::ty; -use syntax::ast::{m_mutbl, m_imm, m_const}; +use syntax::ast::m_mutbl; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; @@ -205,9 +205,9 @@ impl<'self> CheckLoanCtxt<'self> { // Restrictions that would cause the new loan to be illegal: let illegal_if = match loan2.mutbl { - m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, - m_imm => RESTR_ALIAS | RESTR_FREEZE, - m_const => RESTR_ALIAS, + MutableMutability => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, + ImmutableMutability => RESTR_ALIAS | RESTR_FREEZE, + ConstMutability => RESTR_ALIAS, }; debug!("illegal_if=%?", illegal_if); @@ -216,7 +216,7 @@ impl<'self> CheckLoanCtxt<'self> { if restr.loan_path != loan2.loan_path { loop; } match (new_loan.mutbl, old_loan.mutbl) { - (m_mutbl, m_mutbl) => { + (MutableMutability, MutableMutability) => { self.bccx.span_err( new_loan.span, fmt!("cannot borrow `%s` as mutable \ @@ -522,7 +522,6 @@ impl<'self> CheckLoanCtxt<'self> { // Otherwise stop iterating LpExtend(_, mc::McDeclared, _) | LpExtend(_, mc::McImmutable, _) | - LpExtend(_, mc::McReadOnly, _) | LpVar(_) => { return true; } @@ -530,8 +529,11 @@ impl<'self> CheckLoanCtxt<'self> { // Check for a non-const loan of `loan_path` let cont = do this.each_in_scope_loan(expr.id) |loan| { - if loan.loan_path == loan_path && loan.mutbl != m_const { - this.report_illegal_mutation(expr, full_loan_path, loan); + if loan.loan_path == loan_path && + loan.mutbl != ConstMutability { + this.report_illegal_mutation(expr, + full_loan_path, + loan); false } else { true diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index ddcc5fe56d043..9206d261e3943 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -15,7 +15,7 @@ use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; -use syntax::ast::{m_const, m_imm, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::ast; use syntax::codemap::span; use util::ppaux::{note_and_explain_region}; @@ -26,7 +26,7 @@ pub fn guarantee_lifetime(bccx: @BorrowckCtxt, span: span, cmt: mc::cmt, loan_region: ty::Region, - loan_mutbl: ast::mutability) { + loan_mutbl: LoanMutability) { debug!("guarantee_lifetime(cmt=%s, loan_region=%s)", cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx)); let ctxt = GuaranteeLifetimeContext {bccx: bccx, @@ -54,7 +54,7 @@ struct GuaranteeLifetimeContext { span: span, loan_region: ty::Region, - loan_mutbl: ast::mutability, + loan_mutbl: LoanMutability, cmt_original: mc::cmt } @@ -236,11 +236,11 @@ impl GuaranteeLifetimeContext { // we need to dynamically mark it to prevent incompatible // borrows from happening later. let opt_dyna = match ptr_mutbl { - m_imm | m_const => None, + m_imm => None, m_mutbl => { match self.loan_mutbl { - m_mutbl => Some(DynaMut), - m_imm | m_const => Some(DynaImm) + MutableMutability => Some(DynaMut), + ImmutableMutability | ConstMutability => Some(DynaImm) } } }; diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index b970a6585f6cd..c032d5fed3392 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -26,7 +26,6 @@ use middle::ty; use util::common::indenter; use util::ppaux::{Repr}; -use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast; use syntax::ast_util::id_range; use syntax::codemap::span; @@ -217,7 +216,11 @@ fn gather_loans_in_expr(ex: @ast::expr, // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: let scope_r = ty_region(tcx, ex.span, ty::expr_ty(tcx, ex)); - this.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r); + this.guarantee_valid(ex.id, + ex.span, + base_cmt, + LoanMutability::from_ast_mutability(mutbl), + scope_r); oldvisit::visit_expr(ex, (this, vt)); } @@ -258,7 +261,11 @@ fn gather_loans_in_expr(ex: @ast::expr, // adjustments). let scope_r = ty::re_scope(ex.id); let arg_cmt = this.bccx.cat_expr(arg); - this.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r); + this.guarantee_valid(arg.id, + arg.span, + arg_cmt, + ImmutableMutability, + scope_r); oldvisit::visit_expr(ex, (this, vt)); } @@ -337,18 +344,22 @@ impl GatherLoanCtxt { match *autoref { ty::AutoPtr(r, m) => { + let loan_mutability = + LoanMutability::from_ast_mutability(m); self.guarantee_valid(expr.id, expr.span, cmt, - m, + loan_mutability, r) } ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => { let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1); + let loan_mutability = + LoanMutability::from_ast_mutability(m); self.guarantee_valid(expr.id, expr.span, cmt_index, - m, + loan_mutability, r) } ty::AutoBorrowFn(r) => { @@ -356,7 +367,7 @@ impl GatherLoanCtxt { self.guarantee_valid(expr.id, expr.span, cmt_deref, - m_imm, + ImmutableMutability, r) } ty::AutoUnsafe(_) => {} @@ -374,7 +385,7 @@ impl GatherLoanCtxt { borrow_id: ast::NodeId, borrow_span: span, cmt: mc::cmt, - req_mutbl: ast::mutability, + req_mutbl: LoanMutability, loan_region: ty::Region) { debug!("guarantee_valid(borrow_id=%?, cmt=%s, \ req_mutbl=%?, loan_region=%?)", @@ -445,7 +456,7 @@ impl GatherLoanCtxt { let kill_scope = self.compute_kill_scope(loan_scope, loan_path); debug!("kill_scope = %?", kill_scope); - if req_mutbl == m_mutbl { + if req_mutbl == MutableMutability { self.mark_loan_path_as_mutated(loan_path); } @@ -488,7 +499,7 @@ impl GatherLoanCtxt { // index: all_loans.len(), // loan_path: loan_path, // cmt: cmt, - // mutbl: m_const, + // mutbl: ConstMutability, // gen_scope: borrow_id, // kill_scope: kill_scope, // span: borrow_span, @@ -499,29 +510,20 @@ impl GatherLoanCtxt { fn check_mutability(bccx: @BorrowckCtxt, borrow_span: span, cmt: mc::cmt, - req_mutbl: ast::mutability) { + req_mutbl: LoanMutability) { //! Implements the M-* rules in doc.rs. match req_mutbl { - m_const => { + ConstMutability => { // Data of any mutability can be lent as const. } - m_imm => { - match cmt.mutbl { - mc::McImmutable | mc::McDeclared | mc::McInherited => { - // both imm and mut data can be lent as imm; - // for mutable data, this is a freeze - } - mc::McReadOnly => { - bccx.report(BckError {span: borrow_span, - cmt: cmt, - code: err_mutbl(req_mutbl)}); - } - } + ImmutableMutability => { + // both imm and mut data can be lent as imm; + // for mutable data, this is a freeze } - m_mutbl => { + MutableMutability => { // Only mutable data can be lent as mutable. if !cmt.mutbl.is_mutable() { bccx.report(BckError {span: borrow_span, @@ -533,12 +535,14 @@ impl GatherLoanCtxt { } } - pub fn restriction_set(&self, req_mutbl: ast::mutability) + pub fn restriction_set(&self, req_mutbl: LoanMutability) -> RestrictionSet { match req_mutbl { - m_const => RESTR_EMPTY, - m_imm => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, - m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE + ConstMutability => RESTR_EMPTY, + ImmutableMutability => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, + MutableMutability => { + RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE + } } } @@ -554,8 +558,8 @@ impl GatherLoanCtxt { self.mark_loan_path_as_mutated(base); } LpExtend(_, mc::McDeclared, _) | - LpExtend(_, mc::McImmutable, _) | - LpExtend(_, mc::McReadOnly, _) => { + LpExtend(_, mc::McImmutable, _) => { + // Nothing to do. } } } @@ -673,8 +677,13 @@ impl GatherLoanCtxt { } } }; - self.guarantee_valid(pat.id, pat.span, - cmt_discr, mutbl, scope_r); + let loan_mutability = + LoanMutability::from_ast_mutability(mutbl); + self.guarantee_valid(pat.id, + pat.span, + cmt_discr, + loan_mutability, + scope_r); } ast::bind_infer => { // No borrows here, but there may be moves @@ -697,6 +706,8 @@ impl GatherLoanCtxt { self.vec_slice_info(slice_pat, slice_ty); let mcx = self.bccx.mc_ctxt(); let cmt_index = mcx.cat_index(slice_pat, cmt, 0); + let slice_loan_mutability = + LoanMutability::from_ast_mutability(slice_mutbl); // Note: We declare here that the borrow occurs upon // entering the `[...]` pattern. This implies that @@ -715,8 +726,11 @@ impl GatherLoanCtxt { // trans do the right thing, and it would only work // for `~` vectors. It seems simpler to just require // that people call `vec.pop()` or `vec.unshift()`. - self.guarantee_valid(pat.id, pat.span, - cmt_index, slice_mutbl, slice_r); + self.guarantee_valid(pat.id, + pat.span, + cmt_index, + slice_loan_mutability, + slice_r); } _ => {} diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index ad32eb0c805e4..424067a0fc64f 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -15,7 +15,7 @@ use std::vec; use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; -use syntax::ast::{m_const, m_imm, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::codemap::span; pub enum RestrictionResult { @@ -122,13 +122,6 @@ impl RestrictionsContext { Safe } - mc::cat_deref(_, _, mc::region_ptr(m_const, _)) | - mc::cat_deref(_, _, mc::gc_ptr(m_const)) => { - // R-Deref-Freeze-Borrowed - self.check_no_mutability_control(cmt, restrictions); - Safe - } - mc::cat_deref(cmt_base, _, mc::gc_ptr(m_mutbl)) => { // R-Deref-Managed-Borrowed // diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 3db90ed5d7494..6e15376ec495a 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -231,12 +231,39 @@ pub enum PartialTotal { /////////////////////////////////////////////////////////////////////////// // Loans and loan paths +#[deriving(Clone, Eq)] +pub enum LoanMutability { + ImmutableMutability, + ConstMutability, + MutableMutability, +} + +impl LoanMutability { + pub fn from_ast_mutability(ast_mutability: ast::mutability) + -> LoanMutability { + match ast_mutability { + ast::m_imm => ImmutableMutability, + ast::m_mutbl => MutableMutability, + } + } +} + +impl ToStr for LoanMutability { + fn to_str(&self) -> ~str { + match *self { + ImmutableMutability => ~"immutable", + ConstMutability => ~"read-only", + MutableMutability => ~"mutable", + } + } +} + /// Record of a loan that was issued. pub struct Loan { index: uint, loan_path: @LoanPath, cmt: mc::cmt, - mutbl: ast::mutability, + mutbl: LoanMutability, restrictions: ~[Restriction], gen_scope: ast::NodeId, kill_scope: ast::NodeId, @@ -406,7 +433,7 @@ impl ToStr for DynaFreezeKind { // Errors that can occur #[deriving(Eq)] pub enum bckerr_code { - err_mutbl(ast::mutability), + err_mutbl(LoanMutability), err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope err_out_of_scope(ty::Region, ty::Region), // superscope, subscope err_freeze_aliasable_const @@ -783,17 +810,14 @@ impl BorrowckCtxt { mc.cmt_to_str(cmt) } - pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { - let mc = &mc::mem_categorization_ctxt {tcx: self.tcx, - method_map: self.method_map}; - mc.mut_to_str(mutbl) + pub fn mut_to_str(&self, mutbl: LoanMutability) -> ~str { + mutbl.to_str() } pub fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str { match mutbl { ast::m_imm => "", - ast::m_const => "const", - ast::m_mutbl => "mut" + ast::m_mutbl => "mut", } } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index f9ef6dabcd64c..b30d544fdbe0a 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -117,7 +117,7 @@ pub fn check_expr(sess: Session, // to handle on-demand instantiation of functions via // foo:: in a const. Currently that is only done on // a path in trans::callee that only works in block contexts. - if pth.types.len() != 0 { + if !pth.segments.iter().all(|segment| segment.types.is_empty()) { sess.span_err( e.span, "paths in constants may only refer to \ items without type parameters"); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 6c5209cf504a6..2c1053d0157e6 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -52,7 +52,7 @@ use middle::typeck; use util::ppaux::{ty_to_str, region_ptr_to_str, Repr}; use util::common::indenter; -use syntax::ast::{m_imm, m_const, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::ast; use syntax::codemap::span; use syntax::print::pprust; @@ -114,7 +114,6 @@ pub enum ElementKind { #[deriving(Eq, IterBytes)] pub enum MutabilityCategory { McImmutable, // Immutable. - McReadOnly, // Read-only (`const`) McDeclared, // Directly declared as mutable. McInherited // Inherited from the fact that owner is mutable. } @@ -292,7 +291,6 @@ impl MutabilityCategory { pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory { match m { m_imm => McImmutable, - m_const => McReadOnly, m_mutbl => McDeclared } } @@ -300,7 +298,6 @@ impl MutabilityCategory { pub fn inherit(&self) -> MutabilityCategory { match *self { McImmutable => McImmutable, - McReadOnly => McReadOnly, McDeclared => McInherited, McInherited => McInherited } @@ -308,7 +305,7 @@ impl MutabilityCategory { pub fn is_mutable(&self) -> bool { match *self { - McImmutable | McReadOnly => false, + McImmutable => false, McDeclared | McInherited => true } } @@ -316,7 +313,7 @@ impl MutabilityCategory { pub fn is_immutable(&self) -> bool { match *self { McImmutable => true, - McReadOnly | McDeclared | McInherited => false + McDeclared | McInherited => false } } @@ -324,7 +321,6 @@ impl MutabilityCategory { match *self { McDeclared | McInherited => "mutable", McImmutable => "immutable", - McReadOnly => "const" } } } @@ -611,7 +607,6 @@ impl mem_categorization_ctxt { -> MutabilityCategory { match interior_m { m_imm => base_m.inherit(), - m_const => McReadOnly, m_mutbl => McDeclared } } @@ -1001,7 +996,6 @@ impl mem_categorization_ctxt { pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { match mutbl { m_mutbl => ~"mutable", - m_const => ~"const", m_imm => ~"immutable" } } @@ -1170,7 +1164,6 @@ impl cmt_ { Some(AliasableManaged(m)) } - cat_deref(_, _, region_ptr(m @ m_const, _)) | cat_deref(_, _, region_ptr(m @ m_imm, _)) => { Some(AliasableBorrowed(m)) } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 9ffeb99ac3559..5a43e27ea7689 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -33,8 +33,8 @@ use syntax::ast_util::{Private, Public, is_local}; use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy}; use syntax::attr; use syntax::codemap::span; -use syntax::parse::token; use syntax::oldvisit; +use syntax::parse::token; pub fn check_crate<'mm>(tcx: ty::ctxt, method_map: &'mm method_map, @@ -255,7 +255,9 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, match def { def_static_method(method_id, _, _) => { debug!("found static method def, checking it"); - check_method_common(span, method_id, path.idents.last()) + check_method_common(span, + method_id, + &path.segments.last().identifier) } def_fn(def_id, _) => { if def_id.crate == LOCAL_CRATE { @@ -263,13 +265,19 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, !privileged_items.iter().any(|x| x == &def_id.node) { tcx.sess.span_err(span, fmt!("function `%s` is private", - token::ident_to_str(path.idents.last()))); + token::ident_to_str( + &path.segments + .last() + .identifier))); } } else if csearch::get_item_visibility(tcx.sess.cstore, def_id) != public { tcx.sess.span_err(span, fmt!("function `%s` is private", - token::ident_to_str(path.idents.last()))); + token::ident_to_str( + &path.segments + .last() + .identifier))); } } _ => {} diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2d121209118f8..70d3766af42ce 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -797,7 +797,7 @@ fn determine_rp_in_ty(ty: &ast::Ty, Some(&ast::def_trait(did)) | Some(&ast::def_struct(did)) => { if did.crate == ast::LOCAL_CRATE { - if cx.region_is_relevant(&path.rp) { + if cx.region_is_relevant(&path.segments.last().lifetime) { cx.add_dep(did.node); } } else { @@ -807,7 +807,7 @@ 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.region_is_relevant(&path.rp) { + if cx.region_is_relevant(&path.segments.last().lifetime) { let rv = cx.add_variance(variance); cx.add_rp(cx.item_id, rv) } @@ -830,7 +830,7 @@ fn determine_rp_in_ty(ty: &ast::Ty, ast::ty_path(ref path, _, _) => { // type parameters are---for now, anyway---always invariant do cx.with_ambient_variance(rv_invariant) { - for tp in path.types.iter() { + for tp in path.segments.iter().flat_map_(|s| s.types.iter()) { (visitor.visit_ty)(tp, (cx, visitor)); } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 625dcd5d9cc49..727d607b4eb7b 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1230,7 +1230,7 @@ impl Resolver { &Ty { node: ty_path(ref path, _, _), _ - } if path.idents.len() == 1 => { + } if path.segments.len() == 1 => { let name = path_to_ident(path); let new_parent = match parent.children.find(&name) { @@ -1430,20 +1430,22 @@ impl Resolver { let mut module_path = ~[]; match view_path.node { view_path_simple(_, ref full_path, _) => { - let path_len = full_path.idents.len(); + let path_len = full_path.segments.len(); assert!(path_len != 0); - for (i, ident) in full_path.idents.iter().enumerate() { + for (i, segment) in full_path.segments + .iter() + .enumerate() { if i != path_len - 1 { - module_path.push(*ident); + module_path.push(segment.identifier) } } } view_path_glob(ref module_ident_path, _) | view_path_list(ref module_ident_path, _, _) => { - for ident in module_ident_path.idents.iter() { - module_path.push(*ident); + for segment in module_ident_path.segments.iter() { + module_path.push(segment.identifier) } } } @@ -1452,7 +1454,8 @@ impl Resolver { let module_ = self.get_module_from_parent(parent); match view_path.node { view_path_simple(binding, ref full_path, id) => { - let source_ident = *full_path.idents.last(); + let source_ident = + full_path.segments.last().identifier; let subclass = @SingleImport(binding, source_ident); self.build_import_directive(privacy, @@ -2059,6 +2062,14 @@ impl Resolver { return result; } + fn path_idents_to_str(@mut self, path: &Path) -> ~str { + let identifiers: ~[ast::ident] = path.segments + .iter() + .transform(|seg| seg.identifier) + .collect(); + self.idents_to_str(identifiers) + } + pub fn import_directive_subclass_to_str(@mut self, subclass: ImportDirectiveSubclass) -> @str { @@ -3807,8 +3818,7 @@ impl Resolver { reference_type: TraitReferenceType) { match self.resolve_path(id, &trait_reference.path, TypeNS, true, visitor) { None => { - let path_str = self.idents_to_str(trait_reference.path.idents); - + let path_str = self.path_idents_to_str(&trait_reference.path); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -4107,8 +4117,8 @@ impl Resolver { let mut result_def = None; // First, check to see whether the name is a primitive type. - if path.idents.len() == 1 { - let name = *path.idents.last(); + if path.segments.len() == 1 { + let name = path.segments.last().identifier; match self.primitive_type_table .primitive_types @@ -4131,7 +4141,7 @@ impl Resolver { debug!("(resolving type) resolved `%s` to \ type %?", self.session.str_of( - *path.idents.last()), + path.segments.last().identifier), def); result_def = Some(def); } @@ -4150,14 +4160,15 @@ impl Resolver { // Write the result into the def map. debug!("(resolving type) writing resolution for `%s` \ (id %d)", - self.idents_to_str(path.idents), + self.path_idents_to_str(path), path_id); self.record_def(path_id, def); } None => { self.session.span_err - (ty.span, fmt!("use of undeclared type name `%s`", - self.idents_to_str(path.idents))); + (ty.span, + fmt!("use of undeclared type name `%s`", + self.path_idents_to_str(path))) } } @@ -4196,7 +4207,7 @@ impl Resolver { do walk_pat(pattern) |pattern| { match pattern.node { pat_ident(binding_mode, ref path, _) - if !path.global && path.idents.len() == 1 => { + if !path.global && path.segments.len() == 1 => { // The meaning of pat_ident with no type parameters // depends on whether an enum variant or unit-like struct @@ -4207,7 +4218,7 @@ impl Resolver { // such a value is simply disallowed (since it's rarely // what you want). - let ident = path.idents[0]; + let ident = path.segments[0].identifier; match self.resolve_bare_identifier_pattern(ident) { FoundStructOrEnumVariant(def) @@ -4317,7 +4328,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map_(|seg| seg.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4341,7 +4354,7 @@ impl Resolver { path.span, fmt!("`%s` is not an enum variant or constant", self.session.str_of( - *path.idents.last()))); + path.segments.last().identifier))) } None => { self.session.span_err(path.span, @@ -4350,7 +4363,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map_(|s| s.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4368,8 +4383,10 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` is not an enum variant, struct or const", - self.session.str_of( - *path.idents.last()))); + self.session + .str_of(path.segments + .last() + .identifier))); } None => { self.session.span_err(path.span, @@ -4379,7 +4396,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map_(|s| s.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4414,7 +4433,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); + self.path_idents_to_str(path))); } } } @@ -4476,7 +4495,7 @@ impl Resolver { visitor: ResolveVisitor) -> Option { // First, resolve the types. - for ty in path.types.iter() { + for ty in path.segments.iter().flat_map_(|s| s.types.iter()) { self.resolve_type(ty, visitor); } @@ -4486,12 +4505,17 @@ impl Resolver { namespace); } - let unqualified_def = self.resolve_identifier( - *path.idents.last(), namespace, check_ribs, path.span); + let unqualified_def = self.resolve_identifier(path.segments + .last() + .identifier, + namespace, + check_ribs, + path.span); - if path.idents.len() > 1 { - let def = self.resolve_module_relative_path( - path, self.xray_context, namespace); + if path.segments.len() > 1 { + let def = self.resolve_module_relative_path(path, + self.xray_context, + namespace); match (def, unqualified_def) { (Some(d), Some(ud)) if d == ud => { self.session.add_lint(unnecessary_qualification, @@ -4606,12 +4630,12 @@ impl Resolver { pub fn intern_module_part_of_path(@mut self, path: &Path) -> ~[ident] { let mut module_path_idents = ~[]; - for (index, ident) in path.idents.iter().enumerate() { - if index == path.idents.len() - 1 { + for (index, segment) in path.segments.iter().enumerate() { + if index == path.segments.len() - 1 { break; } - module_path_idents.push(*ident); + module_path_idents.push(segment.identifier); } return module_path_idents; @@ -4647,7 +4671,7 @@ impl Resolver { } } - let name = *path.idents.last(); + let name = path.segments.last().identifier; let def = match self.resolve_definition_of_name_in_module(containing_module, name, namespace, @@ -4715,7 +4739,7 @@ impl Resolver { } } - let name = *path.idents.last(); + let name = path.segments.last().identifier; match self.resolve_definition_of_name_in_module(containing_module, name, namespace, @@ -4918,7 +4942,7 @@ impl Resolver { Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `%s`", - self.idents_to_str(path.idents)); + self.path_idents_to_str(path)); // First-class methods are not supported yet; error // out here. @@ -4938,8 +4962,7 @@ impl Resolver { self.record_def(expr.id, def); } None => { - let wrong_name = self.idents_to_str( - path.idents); + let wrong_name = self.path_idents_to_str(path); if self.name_exists_in_scope_struct(wrong_name) { self.session.span_err(expr.span, fmt!("unresolved name `%s`. \ @@ -4995,7 +5018,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); + self.path_idents_to_str(path))); } } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 40d0d77c16ecb..d829c2c40721a 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -540,7 +540,9 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef { } } ast::expr_path(ref pth) => { - assert_eq!(pth.types.len(), 0); + // Assert that there are no type parameters in this path. + assert!(pth.segments.iter().all(|seg| seg.types.is_empty())); + let tcx = cx.tcx; match tcx.def_map.find(&e.id) { Some(&ast::def_fn(def_id, _purity)) => { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 53853e4fe1a78..08688dc99d1ce 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -63,7 +63,6 @@ use middle::typeck::rscope::RegionParamNames; use middle::typeck::lookup_def_tcx; use std::result; -use std::vec; use syntax::abi::AbiSet; use syntax::{ast, ast_util}; use syntax::codemap::span; @@ -150,7 +149,8 @@ fn ast_path_substs( // If the type is parameterized by the this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - let regions = match (&decl_generics.region_param, &path.rp) { + let regions = match (&decl_generics.region_param, + &path.segments.last().lifetime) { (&None, &None) => { opt_vec::Empty } @@ -169,20 +169,34 @@ fn ast_path_substs( } (&Some(_), &Some(_)) => { opt_vec::with( - ast_region_to_region(this, rscope, path.span, &path.rp)) + ast_region_to_region(this, + rscope, + path.span, + &path.segments.last().lifetime)) } }; // Convert the type parameters supplied by the user. - if !vec::same_length(*decl_generics.type_param_defs, path.types) { + let supplied_type_parameter_count = + path.segments.iter().flat_map_(|s| s.types.iter()).len_(); + if decl_generics.type_param_defs.len() != supplied_type_parameter_count { this.tcx().sess.span_fatal( path.span, fmt!("wrong number of type arguments: expected %u but found %u", - decl_generics.type_param_defs.len(), path.types.len())); + decl_generics.type_param_defs.len(), + supplied_type_parameter_count)); + } + let tps = path.segments + .iter() + .flat_map_(|s| s.types.iter()) + .transform(|a_t| ast_ty_to_ty(this, rscope, a_t)) + .collect(); + + substs { + regions: ty::NonerasedRegions(regions), + self_ty: self_ty, + tps: tps } - let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, a_t)); - - substs {regions:ty::NonerasedRegions(regions), self_ty:self_ty, tps:tps} } pub fn ast_path_to_substs_and_ty( match a_seq_ty.ty.node { ast::ty_vec(ref mt) => { let mut mt = ast_mt_to_mt(this, rscope, mt); - if a_seq_ty.mutbl == ast::m_mutbl || - a_seq_ty.mutbl == ast::m_const { + if a_seq_ty.mutbl == ast::m_mutbl { mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl }; } return ty::mk_evec(tcx, mt, vst); @@ -326,7 +339,7 @@ pub fn ast_ty_to_ty( path: &ast::Path, flags: uint) { if (flags & NO_TPS) != 0u { - if path.types.len() > 0u { + if !path.segments.iter().all(|s| s.types.is_empty()) { tcx.sess.span_err( path.span, "type parameters are not allowed on this type"); @@ -334,7 +347,7 @@ pub fn ast_ty_to_ty( } if (flags & NO_REGIONS) != 0u { - if path.rp.is_some() { + if path.segments.last().lifetime.is_some() { tcx.sess.span_err( path.span, "region parameters are not allowed on this type"); diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index e1e7d10db0abd..e98fd41c51738 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -101,7 +101,7 @@ use std::vec; use extra::list::Nil; use syntax::ast::{def_id, sty_value, sty_region, sty_box}; use syntax::ast::{sty_uniq, sty_static, NodeId}; -use syntax::ast::{m_const, m_mutbl, m_imm}; +use syntax::ast::{m_mutbl, m_imm}; use syntax::ast; use syntax::ast_map; @@ -615,7 +615,7 @@ impl<'self> LookupContext<'self> { ty_evec(mt, vstore_fixed(_)) => { // First try to borrow to a slice let entry = self.search_for_some_kind_of_autorefd_method( - AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVec, autoderefs, [m_imm, m_mutbl], |m,r| ty::mk_evec(tcx, ty::mt {ty:mt.ty, mutbl:m}, vstore_slice(r))); @@ -624,7 +624,7 @@ impl<'self> LookupContext<'self> { // Then try to borrow to a slice *and* borrow a pointer. self.search_for_some_kind_of_autorefd_method( - AutoBorrowVecRef, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVecRef, autoderefs, [m_imm, m_mutbl], |m,r| { let slice_ty = ty::mk_evec(tcx, ty::mt {ty:mt.ty, mutbl:m}, @@ -682,7 +682,7 @@ impl<'self> LookupContext<'self> { ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => { self.search_for_some_kind_of_autorefd_method( - AutoPtr, autoderefs, [m_const, m_imm, m_mutbl], + AutoPtr, autoderefs, [m_imm, m_mutbl], |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m})) } @@ -1093,18 +1093,10 @@ impl<'self> LookupContext<'self> { return result; fn mutability_matches(self_mutbl: ast::mutability, - candidate_mutbl: ast::mutability) -> bool { + candidate_mutbl: ast::mutability) + -> bool { //! True if `self_mutbl <: candidate_mutbl` - - match (self_mutbl, candidate_mutbl) { - (_, m_const) => true, - (m_mutbl, m_mutbl) => true, - (m_imm, m_imm) => true, - (m_mutbl, m_imm) => false, - (m_imm, m_mutbl) => false, - (m_const, m_imm) => false, - (m_const, m_mutbl) => false, - } + self_mutbl == candidate_mutbl } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index ea8a11fc7b382..c5f1edd10bd88 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -490,7 +490,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, if pat_util::pat_is_binding(fcx.ccx.tcx.def_map, p) => { assign(p.id, None); debug!("Pattern binding %s is assigned to %s", - tcx.sess.str_of(path.idents[0]), + tcx.sess.str_of(path.segments[0].identifier), fcx.infcx().ty_to_str( fcx.inh.locals.get_copy(&p.id))); } @@ -3167,7 +3167,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt, debug!(">>> instantiate_path"); let ty_param_count = tpt.generics.type_param_defs.len(); - let ty_substs_len = pth.types.len(); + let mut ty_substs_len = 0; + for segment in pth.segments.iter() { + ty_substs_len += segment.types.len() + } debug!("ty_param_count=%? ty_substs_len=%?", ty_param_count, @@ -3175,7 +3178,7 @@ 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 regions = match pth.rp { + let regions = match pth.segments.last().lifetime { Some(_) => { // user supplied a lifetime parameter... match tpt.generics.region_param { None => { // ...but the type is not lifetime parameterized! @@ -3185,7 +3188,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt, } Some(_) => { // ...and the type is lifetime parameterized, ok. opt_vec::with( - ast_region_to_region(fcx, fcx, span, &pth.rp)) + ast_region_to_region(fcx, + fcx, + span, + &pth.segments.last().lifetime)) } } } @@ -3215,12 +3221,18 @@ pub fn instantiate_path(fcx: @mut FnCtxt, ty_param_count, ty_substs_len)); fcx.infcx().next_ty_vars(ty_param_count) } else { - pth.types.map(|aty| fcx.to_ty(aty)) + pth.segments + .iter() + .flat_map_(|s| s.types.iter()) + .transform(|aty| fcx.to_ty(aty)) + .collect() }; - let substs = substs {regions: ty::NonerasedRegions(regions), - self_ty: None, - tps: tps }; + let substs = substs { + regions: ty::NonerasedRegions(regions), + self_ty: None, + tps: tps + }; fcx.write_ty_substs(node_id, tpt.ty, substs); debug!("<<<"); diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index f05388344bc71..4b951d00677d6 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -22,7 +22,7 @@ use middle::typeck::infer::{TypeTrace, Subtype}; use middle::typeck::infer::fold_regions_in_sig; use middle::typeck::isr_alist; use syntax::ast; -use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl}; +use syntax::ast::{Many, Once, extern_fn, impure_fn, m_imm, m_mutbl}; use syntax::ast::{unsafe_fn}; use syntax::ast::{Onceness, purity}; use syntax::abi::AbiSet; @@ -54,16 +54,6 @@ impl Combine for Glb { match (a.mutbl, b.mutbl) { // If one side or both is mut, then the GLB must use // the precise type from the mut side. - (m_mutbl, m_const) => { - Sub(**self).tys(a.ty, b.ty).chain(|_t| { - Ok(ty::mt {ty: a.ty, mutbl: m_mutbl}) - }) - } - (m_const, m_mutbl) => { - Sub(**self).tys(b.ty, a.ty).chain(|_t| { - Ok(ty::mt {ty: b.ty, mutbl: m_mutbl}) - }) - } (m_mutbl, m_mutbl) => { eq_tys(self, a.ty, b.ty).then(|| { Ok(ty::mt {ty: a.ty, mutbl: m_mutbl}) @@ -72,22 +62,12 @@ impl Combine for Glb { // If one side or both is immutable, we can use the GLB of // both sides but mutbl must be `m_imm`. - (m_imm, m_const) | - (m_const, m_imm) | (m_imm, m_imm) => { self.tys(a.ty, b.ty).chain(|t| { Ok(ty::mt {ty: t, mutbl: m_imm}) }) } - // If both sides are const, then we can use GLB of both - // sides and mutbl of only `m_const`. - (m_const, m_const) => { - self.tys(a.ty, b.ty).chain(|t| { - Ok(ty::mt {ty: t, mutbl: m_const}) - }) - } - // There is no mutual subtype of these combinations. (m_mutbl, m_imm) | (m_imm, m_mutbl) => { diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 8afb5a18d4f6f..c97b99aaf0c08 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -26,7 +26,7 @@ use util::ppaux::mt_to_str; use extra::list; use syntax::abi::AbiSet; use syntax::ast; -use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn}; +use syntax::ast::{Many, Once, extern_fn, impure_fn}; use syntax::ast::{unsafe_fn}; use syntax::ast::{Onceness, purity}; @@ -57,14 +57,13 @@ impl Combine for Lub { mt_to_str(tcx, a), mt_to_str(tcx, b)); - let m = if a.mutbl == b.mutbl { - a.mutbl - } else { - m_const - }; + if a.mutbl != b.mutbl { + return Err(ty::terr_mutability) + } + let m = a.mutbl; match m { - m_imm | m_const => { + m_imm => { self.tys(a.ty, b.ty).chain(|t| Ok(ty::mt {ty: t, mutbl: m}) ) } @@ -73,11 +72,7 @@ impl Combine for Lub { eq_tys(self, a.ty, b.ty).then(|| { Ok(ty::mt {ty: a.ty, mutbl: m}) }) - }).chain_err(|_e| { - self.tys(a.ty, b.ty).chain(|t| { - Ok(ty::mt {ty: t, mutbl: m_const}) - }) - }) + }).chain_err(|e| Err(e)) } } } diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 441e71d4722b8..3a4d7df6a5b93 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -28,7 +28,7 @@ use extra::list::Nil; use extra::list; use syntax::abi::AbiSet; use syntax::ast; -use syntax::ast::{Onceness, m_const, purity}; +use syntax::ast::{Onceness, purity}; pub struct Sub(CombineFields); // "subtype", "subregion" etc @@ -69,7 +69,7 @@ impl Combine for Sub { fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres { debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); - if a.mutbl != b.mutbl && b.mutbl != m_const { + if a.mutbl != b.mutbl { return Err(ty::terr_mutability); } @@ -79,7 +79,7 @@ impl Combine for Sub { // (i.e., invariant if mut): eq_tys(self, a.ty, b.ty).then(|| Ok(*a)) } - m_imm | m_const => { + m_imm => { // Otherwise we can be covariant: self.tys(a.ty, b.ty).chain(|_t| Ok(*a) ) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1bea3003c63d2..b1f1871890eb2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -239,7 +239,6 @@ fn mutability_to_str(m: ast::mutability) -> ~str { match m { ast::m_mutbl => ~"mut ", ast::m_imm => ~"", - ast::m_const => ~"const " } } diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index ee91d12790953..4e48dc6877726 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -10,6 +10,7 @@ //! Unsafe casting functions +use ptr::RawPtr; use sys; use unstable::intrinsics; @@ -91,13 +92,13 @@ pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T { /// Coerce an immutable reference to be mutable. #[inline] -pub unsafe fn transmute_mut_unsafe(ptr: *const T) -> *mut T { +pub unsafe fn transmute_mut_unsafe>(ptr: P) -> *mut T { transmute(ptr) } /// Coerce an immutable reference to be mutable. #[inline] -pub unsafe fn transmute_immut_unsafe(ptr: *const T) -> *T { +pub unsafe fn transmute_immut_unsafe>(ptr: P) -> *T { transmute(ptr) } diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index b9535091ed810..f2d55d6e23191 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -11,7 +11,7 @@ #[doc(hidden)]; use libc::c_void; -use ptr::{mut_null}; +use ptr::null; use unstable::intrinsics::TyDesc; use unstable::raw; @@ -37,7 +37,7 @@ unsafe fn each_live_alloc(read_next_before: bool, use rt::local_heap; let mut box = local_heap::live_allocs(); - while box != mut_null() { + while box != null() { let next_before = (*box).next; let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index b0e1f35b4a018..4471f8b4207b1 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1446,7 +1446,7 @@ impl MemoryMap { let r = unsafe { libc::mmap(addr, len, prot, flags, fd, offset) }; - if r == libc::MAP_FAILED { + if r.equiv(&libc::MAP_FAILED) { Err(match errno() as c_int { libc::EACCES => ErrFdNotAvail, libc::EBADF => ErrInvalidFd, diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 78f937e058a41..0a0ba355f5c2e 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -86,6 +86,8 @@ bounded and unbounded protocols allows for less code duplication. use container::Container; use cast::{forget, transmute, transmute_copy, transmute_mut}; +use cast; +use cmp::Equiv; use either::{Either, Left, Right}; use iterator::{Iterator, IteratorUtil}; use kinds::Send; @@ -353,7 +355,10 @@ pub fn send(mut p: SendPacketBuffered, let header = p.header(); let p_ = p.unwrap(); let p = unsafe { &mut *p_ }; - assert_eq!(ptr::to_unsafe_ptr(&(p.header)), header); + unsafe { + assert_eq!(ptr::to_unsafe_ptr(&(p.header)), + cast::transmute_immut_unsafe(header)); + } assert!(p.payload.is_none()); p.payload = Some(payload); let old_state = swap_state_rel(&mut p.header.state, Full); @@ -621,7 +626,7 @@ pub fn wait_many(pkts: &mut [T]) -> uint { let mut pos = None; for (i, p) in pkts.mut_iter().enumerate() { - if p.header() == event { + if p.header().equiv(&event) { pos = Some(i); break; } diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index dfd11f9227d41..3cb52e33691a7 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -12,8 +12,11 @@ use cast; use clone::Clone; +use cmp::Equiv; use iterator::{range, Iterator}; use option::{Option, Some, None}; +#[cfg(stage0)] +use sys; use unstable::intrinsics; use util::swap; @@ -24,18 +27,28 @@ use util::swap; /// Calculate the offset from a pointer #[inline] +#[cfg(stage0)] pub fn offset(ptr: *T, count: int) -> *T { - unsafe { intrinsics::offset(ptr, count) } + (ptr as uint + (count as uint) * sys::size_of::()) as *T } -/// Calculate the offset from a const pointer +/// Calculate the offset from a mut pointer #[inline] -pub fn const_offset(ptr: *const T, count: int) -> *const T { - unsafe { intrinsics::offset(ptr as *T, count) } +#[cfg(stage0)] +pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { + (ptr as uint + (count as uint) * sys::size_of::()) as *mut T +} + +/// Calculate the offset from a pointer +#[inline] +#[cfg(not(stage0))] +pub fn offset(ptr: *T, count: int) -> *T { + unsafe { intrinsics::offset(ptr, count) } } /// Calculate the offset from a mut pointer #[inline] +#[cfg(not(stage0))] pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { unsafe { intrinsics::offset(ptr as *T, count) as *mut T } } @@ -72,11 +85,11 @@ pub fn mut_null() -> *mut T { 0 as *mut T } /// Returns true if the pointer is equal to the null pointer. #[inline] -pub fn is_null(ptr: *const T) -> bool { ptr == null() } +pub fn is_null>(ptr: P) -> bool { ptr.is_null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] -pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } +pub fn is_not_null>(ptr: P) -> bool { ptr.is_not_null() } /** * Copies data from one location to another. @@ -86,8 +99,10 @@ pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } */ #[inline] #[cfg(target_word_size = "32")] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memmove32(dst, src as *T, count as u32); +pub unsafe fn copy_memory>(dst: *mut T, src: P, count: uint) { + intrinsics::memmove32(dst, + cast::transmute_immut_unsafe(src), + count as u32); } /** @@ -98,8 +113,10 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { */ #[inline] #[cfg(target_word_size = "64")] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memmove64(dst, src as *T, count as u64); +pub unsafe fn copy_memory>(dst: *mut T, src: P, count: uint) { + intrinsics::memmove64(dst, + cast::transmute_immut_unsafe(src), + count as u64); } /** @@ -110,8 +127,12 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { */ #[inline] #[cfg(target_word_size = "32")] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memcpy32(dst, src as *T, count as u32); +pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, + src: P, + count: uint) { + intrinsics::memcpy32(dst, + cast::transmute_immut_unsafe(src), + count as u32); } /** @@ -122,8 +143,12 @@ pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: u */ #[inline] #[cfg(target_word_size = "64")] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memcpy64(dst, src as *T, count as u64); +pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, + src: P, + count: uint) { + intrinsics::memcpy64(dst, + cast::transmute_immut_unsafe(src), + count as u64); } /** @@ -215,12 +240,6 @@ pub fn to_unsafe_ptr(thing: &T) -> *T { thing as *T } -/// Transform a const region pointer - &const T - to a const unsafe pointer - *const T. -#[inline] -pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { - thing as *const T -} - /// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T. #[inline] pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { @@ -268,21 +287,31 @@ pub unsafe fn array_each(arr: **T, cb: &fn(*T)) { #[allow(missing_doc)] pub trait RawPtr { + fn null() -> Self; fn is_null(&self) -> bool; fn is_not_null(&self) -> bool; + fn to_uint(&self) -> uint; unsafe fn to_option(&self) -> Option<&T>; fn offset(&self, count: int) -> Self; } /// Extension methods for immutable pointers impl RawPtr for *T { + /// Returns the null pointer. + #[inline] + fn null() -> *T { null() } + /// Returns true if the pointer is equal to the null pointer. #[inline] - fn is_null(&self) -> bool { is_null(*self) } + fn is_null(&self) -> bool { *self == RawPtr::null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] - fn is_not_null(&self) -> bool { is_not_null(*self) } + fn is_not_null(&self) -> bool { *self != RawPtr::null() } + + /// Returns the address of this pointer. + #[inline] + fn to_uint(&self) -> uint { *self as uint } /// /// Returns `None` if the pointer is null, or else returns the value wrapped @@ -308,13 +337,21 @@ impl RawPtr for *T { /// Extension methods for mutable pointers impl RawPtr for *mut T { + /// Returns the null pointer. + #[inline] + fn null() -> *mut T { mut_null() } + /// Returns true if the pointer is equal to the null pointer. #[inline] - fn is_null(&self) -> bool { is_null(*self) } + fn is_null(&self) -> bool { *self == RawPtr::null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] - fn is_not_null(&self) -> bool { is_not_null(*self) } + fn is_not_null(&self) -> bool { *self != RawPtr::null() } + + /// Returns the address of this pointer. + #[inline] + fn to_uint(&self) -> uint { *self as uint } /// /// Returns `None` if the pointer is null, or else returns the value wrapped @@ -340,32 +377,77 @@ impl RawPtr for *mut T { // Equality for pointers #[cfg(not(test))] -impl Eq for *const T { +impl Eq for *T { + #[inline] + fn eq(&self, other: &*T) -> bool { + (*self as uint) == (*other as uint) + } + #[inline] + fn ne(&self, other: &*T) -> bool { !self.eq(other) } +} + +#[cfg(not(test))] +impl Eq for *mut T { #[inline] - fn eq(&self, other: &*const T) -> bool { + fn eq(&self, other: &*mut T) -> bool { (*self as uint) == (*other as uint) } #[inline] - fn ne(&self, other: &*const T) -> bool { !self.eq(other) } + fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } +} + +// Equivalence for pointers +#[cfg(not(test))] +impl Equiv<*mut T> for *T { + fn equiv(&self, other: &*mut T) -> bool { + self.to_uint() == other.to_uint() + } +} + +#[cfg(not(test))] +impl Equiv<*T> for *mut T { + fn equiv(&self, other: &*T) -> bool { + self.to_uint() == other.to_uint() + } } // Comparison for pointers #[cfg(not(test))] -impl Ord for *const T { +impl Ord for *T { + #[inline] + fn lt(&self, other: &*T) -> bool { + (*self as uint) < (*other as uint) + } + #[inline] + fn le(&self, other: &*T) -> bool { + (*self as uint) <= (*other as uint) + } + #[inline] + fn ge(&self, other: &*T) -> bool { + (*self as uint) >= (*other as uint) + } + #[inline] + fn gt(&self, other: &*T) -> bool { + (*self as uint) > (*other as uint) + } +} + +#[cfg(not(test))] +impl Ord for *mut T { #[inline] - fn lt(&self, other: &*const T) -> bool { + fn lt(&self, other: &*mut T) -> bool { (*self as uint) < (*other as uint) } #[inline] - fn le(&self, other: &*const T) -> bool { + fn le(&self, other: &*mut T) -> bool { (*self as uint) <= (*other as uint) } #[inline] - fn ge(&self, other: &*const T) -> bool { + fn ge(&self, other: &*mut T) -> bool { (*self as uint) >= (*other as uint) } #[inline] - fn gt(&self, other: &*const T) -> bool { + fn gt(&self, other: &*mut T) -> bool { (*self as uint) > (*other as uint) } } diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs index dcfcc3a9fc67a..9f58e440d7e81 100644 --- a/src/libstd/rt/borrowck.rs +++ b/src/libstd/rt/borrowck.rs @@ -9,14 +9,15 @@ // except according to those terms. use cast::transmute; -use libc::{c_char, c_void, size_t, STDERR_FILENO}; -use io; use io::{Writer, WriterUtil}; +use io; +use libc::{c_char, c_void, size_t, STDERR_FILENO}; use option::{Option, None, Some}; -use uint; -use str; +use ptr::RawPtr; use str::{OwnedStr, StrSlice}; +use str; use sys; +use uint; use unstable::raw; use vec::ImmutableVector; @@ -104,12 +105,12 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { static ENABLE_DEBUG: bool = false; #[inline] -unsafe fn debug_borrow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { +unsafe fn debug_borrow>(tag: &'static str, + p: P, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { //! A useful debugging function that prints a pointer + tag + newline //! without allocating memory. @@ -117,15 +118,15 @@ unsafe fn debug_borrow(tag: &'static str, debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); } - unsafe fn debug_borrow_slow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { + unsafe fn debug_borrow_slow>(tag: &'static str, + p: P, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { let dbg = STDERR_FILENO as io::fd_t; dbg.write_str(tag); - dbg.write_hex(p as uint); + dbg.write_hex(p.to_uint()); dbg.write_str(" "); dbg.write_hex(old_bits); dbg.write_str(" "); diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 1a75f2569b59e..6333e0bb4d500 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -582,7 +582,8 @@ impl Scheduler { let current_task: &mut Task = match sched.cleanup_job { Some(GiveTask(ref task, _)) => { - transmute_mut_region(*transmute_mut_unsafe(task)) + let task_ptr: *~Task = task; + transmute_mut_region(*transmute_mut_unsafe(task_ptr)) } Some(DoNothing) => { rtabort!("no next task"); diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index 5ad7969c8d21f..1bea9b8282e45 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -335,7 +335,14 @@ impl IterBytes for ~A { // NB: raw-pointer IterBytes does _not_ dereference // to the target; it just gives you the pointer-bytes. -impl IterBytes for *const A { +impl IterBytes for *A { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +impl IterBytes for *mut A { #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) diff --git a/src/libstd/util.rs b/src/libstd/util.rs index b46876ad3fe44..5085f337d4bba 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -54,8 +54,10 @@ pub fn swap(x: &mut T, y: &mut T) { let t: *mut T = &mut tmp; // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping_memory(t, x, 1); - ptr::copy_nonoverlapping_memory(x, y, 1); + let x_raw: *mut T = x; + let y_raw: *mut T = y; + ptr::copy_nonoverlapping_memory(t, x_raw, 1); + ptr::copy_nonoverlapping_memory(x, y_raw, 1); ptr::copy_nonoverlapping_memory(y, t, 1); // y and t now point to the same thing, but we need to completely forget `tmp` diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 0259b547ab3f0..4aa0c358dca28 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1076,14 +1076,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { * foreign interop. */ #[inline] - fn as_imm_buf(&self, - /* NB---this CANNOT be const, see below */ - f: &fn(*T, uint) -> U) -> U { - // NB---Do not change the type of s to `&const [T]`. This is - // unsound. The reason is that we are going to create immutable pointers - // into `s` and pass them to `f()`, but in fact they are potentially - // pointing at *mutable memory*. Use `as_mut_buf` instead! - + fn as_imm_buf(&self, f: &fn(*T, uint) -> U) -> U { let s = self.repr(); f(s.data, s.len / sys::nonzero_size_of::()) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 435be3c71af6f..16baaf6c24688 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -109,12 +109,21 @@ pub struct Path { /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). global: bool, - /// The segments in the path (the things separated by ::) - idents: ~[ident], - /// "Region parameter", currently only one lifetime is allowed in a path. - rp: Option, - /// These are the type parameters, ie, the `a, b` in `foo::bar::` - types: ~[Ty], + /// The segments in the path: the things separated by `::`. + segments: ~[PathSegment], +} + +/// A segment of a path: an identifier, an optional lifetime, and a set of +/// types. +#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] +pub struct PathSegment { + /// The identifier portion of this path segment. + identifier: ident, + /// The lifetime parameter for this path segment. Currently only one + /// lifetime parameter is allowed. + lifetime: Option, + /// The type parameters for this path segment, if present. + types: OptVec, } pub type CrateNum = int; @@ -298,7 +307,10 @@ pub enum pat_ { } #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] -pub enum mutability { m_mutbl, m_imm, m_const, } +pub enum mutability { + m_mutbl, + m_imm, +} #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum Sigil { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 84e6544f78092..572989a44c234 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -28,8 +28,8 @@ pub fn path_name_i(idents: &[ident]) -> ~str { idents.map(|i| token::interner_get(i.name)).connect("::") } -pub fn path_to_ident(p: &Path) -> ident { - *p.idents.last() +pub fn path_to_ident(path: &Path) -> ident { + path.segments.last().identifier } pub fn local_def(id: NodeId) -> def_id { @@ -217,12 +217,18 @@ pub fn default_block( } } -pub fn ident_to_path(s: span, i: ident) -> Path { - ast::Path { span: s, - global: false, - idents: ~[i], - rp: None, - types: ~[] } +pub fn ident_to_path(s: span, identifier: ident) -> Path { + ast::Path { + span: s, + global: false, + segments: ~[ + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + ], + } } pub fn ident_to_pat(id: NodeId, s: span, i: ident) -> @pat { @@ -410,7 +416,7 @@ impl IdVisitor { impl Visitor<()> for IdVisitor { fn visit_mod(@mut self, module: &_mod, - _span: span, + _: span, node_id: NodeId, env: ()) { (self.visit_callback)(node_id); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 6ed5ca3e402a8..2275d0093b65a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -321,20 +321,6 @@ pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: ~str) -> @str { } } -pub fn expr_to_ident(cx: @ExtCtxt, - expr: @ast::expr, - err_msg: &str) -> ast::ident { - match expr.node { - ast::expr_path(ref p) => { - if p.types.len() > 0u || p.idents.len() != 1u { - cx.span_fatal(expr.span, err_msg); - } - return p.idents[0]; - } - _ => cx.span_fatal(expr.span, err_msg) - } -} - pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], name: &str) { if tts.len() != 0 { @@ -345,15 +331,15 @@ pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], pub fn get_single_str_from_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], - name: &str) -> @str { + name: &str) + -> @str { if tts.len() != 1 { cx.span_fatal(sp, fmt!("%s takes 1 argument.", name)); } match tts[0] { ast::tt_tok(_, token::LIT_STR(ident)) => cx.str_of(ident), - _ => - cx.span_fatal(sp, fmt!("%s requires a string.", name)) + _ => cx.span_fatal(sp, fmt!("%s requires a string.", name)), } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index c373a3894884e..9ad602649169d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -233,18 +233,31 @@ impl AstBuilder for @ExtCtxt { fn path_global(&self, span: span, strs: ~[ast::ident]) -> ast::Path { self.path_all(span, true, strs, None, ~[]) } - fn path_all(&self, sp: span, + fn path_all(&self, + sp: span, global: bool, - idents: ~[ast::ident], + mut idents: ~[ast::ident], rp: Option, types: ~[ast::Ty]) - -> ast::Path { + -> ast::Path { + let last_identifier = idents.pop(); + let mut segments: ~[ast::PathSegment] = idents.consume_iter() + .transform(|ident| { + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + }).collect(); + segments.push(ast::PathSegment { + identifier: last_identifier, + lifetime: rp, + types: opt_vec::from(types), + }); ast::Path { span: sp, global: global, - idents: idents, - rp: rp, - types: types + segments: segments, } } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index edb5c634d5698..477f3fde99c73 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -12,6 +12,7 @@ use ast; use codemap::span; use ext::base::*; use ext::base; +use opt_vec; use parse::token; use parse::token::{str_to_ident}; @@ -39,9 +40,13 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) ast::Path { span: sp, global: false, - idents: ~[res], - rp: None, - types: ~[], + segments: ~[ + ast::PathSegment { + identifier: res, + lifetime: None, + types: opt_vec::Empty, + } + ] } ), span: sp, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c7020b990bf00..af0c438ef256c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -19,6 +19,7 @@ use codemap; use codemap::{span, spanned, ExpnInfo, NameAndSpan}; use ext::base::*; use fold::*; +use opt_vec; use parse; use parse::{parse_item_from_source_str}; use parse::token; @@ -42,13 +43,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, match (*mac).node { // Token-tree macros: mac_invoc_tt(ref pth, ref tts) => { - if (pth.idents.len() > 1u) { + if (pth.segments.len() > 1u) { cx.span_fatal( pth.span, fmt!("expected macro name without module \ separators")); } - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); // leaving explicit deref here to highlight unbox op: match (*extsbox).find(&extname.name) { @@ -143,9 +144,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ast::Path { span: span, global: false, - idents: ~[ident], - rp: None, - types: ~[] + segments: ~[ + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + ], } } @@ -368,7 +373,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, _ => cx.span_bug(it.span, "invalid item macro invocation") }; - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); let expanded = match (*extsbox).find(&extname.name) { None => cx.span_fatal(pth.span, @@ -459,13 +464,13 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } _ => return orig(s, sp, fld) }; - if (pth.idents.len() > 1u) { + if (pth.segments.len() > 1u) { cx.span_fatal( pth.span, fmt!("expected macro name without module \ separators")); } - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); let (fully_expanded, sp) = match (*extsbox).find(&extname.name) { None => @@ -534,10 +539,14 @@ impl Visitor<()> for NewNameFinderContext { // a path of length one: &ast::Path { global: false, - idents: [id], span: _, - rp: _, - types: _ + segments: [ + ast::PathSegment { + identifier: id, + lifetime: _, + types: _ + } + ] } => self.ident_accumulator.push(id), // I believe these must be enums... _ => () diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 5a1317034b221..ae41a0d684b16 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -16,7 +16,7 @@ use codemap::{BytePos, mk_sp}; use codemap; use parse::lexer::*; //resolve bug? use parse::ParseSess; -use parse::parser::Parser; +use parse::parser::{LifetimeAndTypesWithoutColons, Parser}; use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str}; use parse::token; @@ -429,7 +429,9 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal { _ => p.fatal(~"expected ident, found " + token::to_str(get_ident_interner(), p.token)) }, - "path" => token::nt_path(p.parse_path_with_tps(false)), + "path" => { + token::nt_path(p.parse_path(LifetimeAndTypesWithoutColons).path) + } "tt" => { *p.quote_depth += 1u; //but in theory, non-quoted tts might be useful let res = token::nt_tt(@p.parse_token_tree()); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7ffed13940e8a..af7f5a9823b21 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -765,9 +765,11 @@ fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path { ast::Path { span: fld.new_span(p.span), global: p.global, - idents: p.idents.map(|x| fld.fold_ident(*x)), - rp: p.rp, - types: p.types.map(|x| fld.fold_ty(x)), + segments: p.segments.map(|segment| ast::PathSegment { + identifier: fld.fold_ident(segment.identifier), + lifetime: segment.lifetime, + types: segment.types.map(|typ| fld.fold_ty(typ)), + }) } } diff --git a/src/libsyntax/oldvisit.rs b/src/libsyntax/oldvisit.rs index 295003c6ef538..56576ee359960 100644 --- a/src/libsyntax/oldvisit.rs +++ b/src/libsyntax/oldvisit.rs @@ -284,7 +284,11 @@ pub fn visit_ty(t: &Ty, (e, v): (E, vt)) { } pub fn visit_path(p: &Path, (e, v): (E, vt)) { - for tp in p.types.iter() { (v.visit_ty)(tp, (e.clone(), v)); } + for segment in p.segments.iter() { + for typ in segment.types.iter() { + (v.visit_ty)(typ, (e.clone(), v)) + } + } } pub fn visit_pat(p: &pat, (e, v): (E, vt)) { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1731a587a8efa..6291d2671a801 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -361,27 +361,47 @@ mod test { span{lo:BytePos(a),hi:BytePos(b),expn_info:None} } - #[test] fn path_exprs_1 () { + #[test] fn path_exprs_1() { assert_eq!(string_to_expr(@"a"), - @ast::expr{id:1, - node:ast::expr_path(ast::Path {span:sp(0,1), - global:false, - idents:~[str_to_ident("a")], - rp:None, - types:~[]}), - span:sp(0,1)}) + @ast::expr{ + id: 1, + node: ast::expr_path(ast::Path { + span: sp(0, 1), + global: false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("a"), + lifetime: None, + types: ~[], + } + ], + }), + span: sp(0, 1) + }) } #[test] fn path_exprs_2 () { assert_eq!(string_to_expr(@"::a::b"), - @ast::expr{id:1, - node:ast::expr_path( - ast::Path {span:sp(0,6), - global:true, - idents:strs_to_idents(~["a","b"]), - rp:None, - types:~[]}), - span:sp(0,6)}) + @ast::expr { + id:1, + node: ast::expr_path(ast::Path { + span: sp(0, 6), + global: true, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("a"), + lifetime: None, + types: ~[], + }, + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: ~[], + } + ] + }, + span: sp(0, 6)) + }) } #[should_fail] @@ -420,32 +440,43 @@ mod test { #[test] fn ret_expr() { assert_eq!(string_to_expr(@"return d"), - @ast::expr{id:2, - node:ast::expr_ret( - Some(@ast::expr{id:1, - node:ast::expr_path( - ast::Path{span:sp(7,8), - global:false, - idents:~[str_to_ident("d")], - rp:None, - types:~[] - }), - span:sp(7,8)})), - span:sp(0,8)}) + @ast::expr{ + id:2, + node:ast::expr_ret(Some(@ast::expr{ + id:1, + node:ast::expr_path(ast::Path{ + span: sp(7, 8), + global: false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("d"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }), + span:sp(7,8) + })), + span:sp(0,8) + }) } #[test] fn parse_stmt_1 () { assert_eq!(string_to_stmt(@"b;"), @spanned{ - node: ast::stmt_expr(@ast::expr{ + node: ast::stmt_expr(@ast::expr { id: 1, - node: ast::expr_path( - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp:None, - types: ~[]}), + node: ast::expr_path(ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }), span: sp(0,1)}, 2), // fixme span: sp(0,1)}) @@ -460,15 +491,20 @@ mod test { let parser = string_to_parser(@"b"); assert_eq!(parser.parse_pat(), @ast::pat{id:1, // fixme - node: ast::pat_ident(ast::bind_infer, - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None /* no idea */), span: sp(0,1)}); parser_done(parser); } @@ -483,21 +519,33 @@ mod test { span:sp(4,4), // this is bizarre... // check this in the original parser? global:false, - idents:~[str_to_ident("int")], - rp: None, - types: ~[]}, - None, 2), + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("int"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, None, 2), span:sp(4,7)}, pat: @ast::pat{id:1, - node: ast::pat_ident(ast::bind_infer, - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None // no idea + ), span: sp(0,1)}, id: 4 // fixme }) @@ -519,23 +567,37 @@ mod test { node: ast::ty_path(ast::Path{ span:sp(10,13), global:false, - idents:~[str_to_ident("int")], - rp: None, - types: ~[]}, - None, 2), - span:sp(10,13)}, - pat: @ast::pat{id:1, // fixme - node: ast::pat_ident( - ast::bind_infer, - ast::Path{ - span:sp(6,7), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), - span: sp(6,7)}, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("int"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, None, 2), + span:sp(10,13) + }, + pat: @ast::pat { + id:1, // fixme + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(6,7), + global:false, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None // no idea + ), + span: sp(6,7) + }, id: 4 // fixme }], output: ast::Ty{id:5, // fixme @@ -558,9 +620,18 @@ mod test { ast::Path{ span:sp(17,18), global:false, - idents:~[str_to_ident("b")], - rp:None, - types: ~[]}), + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident( + "b"), + lifetime: + None, + types: + opt_vec::Empty + } + ], + }), span: sp(17,18)}, 7), // fixme span: sp(17,18)}], diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index ec956f6186376..09498fbba6263 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -54,7 +54,6 @@ pub enum ObsoleteSyntax { ObsoleteMode, ObsoleteImplicitSelf, ObsoleteLifetimeNotation, - ObsoleteConstManagedPointer, ObsoletePurity, ObsoleteStaticMethod, ObsoleteConstItem, @@ -64,6 +63,7 @@ pub enum ObsoleteSyntax { ObsoleteMutWithMultipleBindings, ObsoleteExternVisibility, ObsoleteUnsafeExternFn, + ObsoleteConstPointer, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -207,10 +207,6 @@ impl ParserObsoleteMethods for Parser { "instead of `&foo/bar`, write `&'foo bar`; instead of \ `bar/&foo`, write `&bar<'foo>" ), - ObsoleteConstManagedPointer => ( - "const `@` pointer", - "instead of `@const Foo`, write `@Foo`" - ), ObsoletePurity => ( "pure function", "remove `pure`" @@ -253,6 +249,11 @@ impl ParserObsoleteMethods for Parser { "external functions are always unsafe; remove the `unsafe` \ keyword" ), + ObsoleteConstPointer => ( + "const pointer", + "instead of `&const Foo` or `@const Foo`, write `&Foo` or \ + `@Foo`" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a0932729930e3..b63ae038cab03 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -36,7 +36,7 @@ use ast::{ident, impure_fn, inherited, item, item_, item_static}; use ast::{item_enum, item_fn, item_foreign_mod, item_impl}; use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; -use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local, m_const}; +use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local}; use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal}; use ast::{match_seq, match_tok, method, mt, mul, mutability}; use ast::{named_field, neg, NodeId, noreturn, not, pat, pat_box, pat_enum}; @@ -79,12 +79,13 @@ use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern}; use parse::obsolete::{ObsoletePostFnTySigil}; use parse::obsolete::{ObsoleteBareFnType, ObsoleteNewtypeEnum}; use parse::obsolete::ObsoleteMode; -use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer}; +use parse::obsolete::{ObsoleteLifetimeNotation}; use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; use parse::obsolete::{ObsoleteMutWithMultipleBindings}; use parse::obsolete::{ObsoleteExternVisibility, ObsoleteUnsafeExternFn}; +use parse::obsolete::{ObsoleteConstPointer}; use parse::obsolete::{ParserObsoleteMethods}; use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident}; use parse::token::{is_ident_or_path}; @@ -112,6 +113,37 @@ enum restriction { type arg_or_capture_item = Either; type item_info = (ident, item_, Option<~[Attribute]>); +/// How to parse a path. There are four different kinds of paths, all of which +/// are parsed somewhat differently. +#[deriving(Eq)] +pub enum PathParsingMode { + /// A path with no type parameters; e.g. `foo::bar::Baz` + NoTypesAllowed, + /// A path with a lifetime and type parameters, with no double colons + /// before the type parameters; e.g. `foo::bar<'self>::Baz` + LifetimeAndTypesWithoutColons, + /// A path with a lifetime and type parameters with double colons before + /// the type parameters; e.g. `foo::bar::<'self>::Baz::` + LifetimeAndTypesWithColons, + /// A path with a lifetime and type parameters with bounds before the last + /// set of type parameters only; e.g. `foo::bar<'self>::Baz:X+Y` This + /// form does not use extra double colons. + LifetimeAndTypesAndBounds, +} + +/// A pair of a path segment and group of type parameter bounds. (See `ast.rs` +/// for the definition of a path segment.) +struct PathSegmentAndBoundSet { + segment: ast::PathSegment, + bound_set: Option>, +} + +/// A path paired with optional type bounds. +struct PathAndBounds { + path: ast::Path, + bounds: Option>, +} + pub enum item_or_view_item { // Indicates a failure to parse any kind of item. The attributes are // returned. @@ -1027,7 +1059,10 @@ impl Parser { } else if *self.token == token::MOD_SEP || is_ident_or_path(self.token) { // NAMED TYPE - let (path, bounds) = self.parse_type_path(); + let PathAndBounds { + path, + bounds + } = self.parse_path(LifetimeAndTypesAndBounds); ty_path(path, bounds, self.get_id()) } else { self.fatal(fmt!("expected type, found token %?", @@ -1073,9 +1108,6 @@ impl Parser { if mt.mutbl != m_imm && sigil == OwnedSigil { self.obsolete(*self.last_span, ObsoleteMutOwnedPointer); } - if mt.mutbl == m_const && sigil == ManagedSigil { - self.obsolete(*self.last_span, ObsoleteConstManagedPointer); - } ctor(mt) } @@ -1252,139 +1284,155 @@ impl Parser { } } - // parse a path into a vector of idents, whether the path starts - // with ::, and a span. - pub fn parse_path(&self) -> (~[ast::ident],bool,span) { + /// Parses a path and optional type parameter bounds, depending on the + /// mode. The `mode` parameter determines whether lifetimes, types, and/or + /// bounds are permitted and whether `::` must precede type parameter + /// groups. + pub fn parse_path(&self, mode: PathParsingMode) -> PathAndBounds { + // Check for a whole path... + let found = match *self.token { + INTERPOLATED(token::nt_path(_)) => Some(self.bump_and_get()), + _ => None, + }; + match found { + Some(INTERPOLATED(token::nt_path(path))) => { + return PathAndBounds { + path: path, + bounds: None, + } + } + _ => {} + } + let lo = self.span.lo; let is_global = self.eat(&token::MOD_SEP); - let (ids,span{lo:_,hi,expn_info}) = self.parse_path_non_global(); - (ids,is_global,span{lo:lo,hi:hi,expn_info:expn_info}) - } - // parse a path beginning with an identifier into a vector of idents and a span - pub fn parse_path_non_global(&self) -> (~[ast::ident],span) { - let lo = self.span.lo; - let mut ids = ~[]; - // must be at least one to begin: - ids.push(self.parse_ident()); + // Parse any number of segments and bound sets. A segment is an + // identifier followed by an optional lifetime and a set of types. + // A bound set is a set of type parameter bounds. + let mut segments = ~[]; loop { + // First, parse an identifier. match *self.token { - token::MOD_SEP => { - let is_ident = do self.look_ahead(1) |t| { - match *t { - token::IDENT(*) => true, - _ => false, - } - }; - if is_ident { - self.bump(); - ids.push(self.parse_ident()); - } else { - break - } - } - _ => break + token::IDENT(*) => {} + _ => break, } - } - (ids, mk_sp(lo, self.last_span.hi)) - } + let identifier = self.parse_ident(); - // parse a path that doesn't have type parameters attached - pub fn parse_path_without_tps(&self) -> ast::Path { - maybe_whole!(self, nt_path); - let (ids,is_global,sp) = self.parse_path(); - ast::Path { span: sp, - global: is_global, - idents: ids, - rp: None, - types: ~[] } - } + // Next, parse a colon and bounded type parameters, if applicable. + let bound_set = if mode == LifetimeAndTypesAndBounds { + self.parse_optional_ty_param_bounds() + } else { + None + }; - pub fn parse_bounded_path_with_tps(&self, colons: bool, - before_tps: Option<&fn()>) -> ast::Path { - debug!("parse_path_with_tps(colons=%b)", colons); + // Parse the '::' before type parameters if it's required. If + // it is required and wasn't present, then we're done. + if mode == LifetimeAndTypesWithColons && + !self.eat(&token::MOD_SEP) { + segments.push(PathSegmentAndBoundSet { + segment: ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }, + bound_set: bound_set + }); + break + } - maybe_whole!(self, nt_path); - let lo = self.span.lo; - let path = self.parse_path_without_tps(); - if colons && !self.eat(&token::MOD_SEP) { - return path; - } - - // If the path might have bounds on it, they should be parsed before - // the parameters, e.g. module::TraitName:B1+B2 - before_tps.map_consume(|callback| callback()); - - // Parse the (obsolete) trailing region parameter, if any, which will - // be written "foo/&x" - let rp_slash = { - if *self.token == token::BINOP(token::SLASH) - && self.look_ahead(1, |t| *t == token::BINOP(token::AND)) - { - self.bump(); self.bump(); - self.obsolete(*self.last_span, ObsoleteLifetimeNotation); - match *self.token { - token::IDENT(sid, _) => { - let span = self.span; - self.bump(); - Some(ast::Lifetime { - id: self.get_id(), - span: *span, - ident: sid - }) + // Parse the `<` before the lifetime and types, if applicable. + let (any_lifetime_or_types, optional_lifetime, types) = + if mode != NoTypesAllowed && self.eat(&token::LT) { + // Parse an optional lifetime. + let optional_lifetime = match *self.token { + token::LIFETIME(*) => Some(self.parse_lifetime()), + _ => None, + }; + + // Parse type parameters. + let mut types = opt_vec::Empty; + let mut need_comma = optional_lifetime.is_some(); + loop { + // We're done if we see a `>`. + match *self.token { + token::GT | token::BINOP(token::SHR) => { + self.expect_gt(); + break + } + _ => {} // Go on. } - _ => { - self.fatal(fmt!("Expected a lifetime name")); + + if need_comma { + self.expect(&token::COMMA) + } else { + need_comma = true } + + types.push(self.parse_ty(false)) } + + (true, optional_lifetime, types) } else { - None - } - }; + (false, None, opt_vec::Empty) + }; - // Parse any lifetime or type parameters which may appear: - let (lifetimes, tps) = self.parse_generic_values(); - let hi = self.span.lo; + // Assemble and push the result. + segments.push(PathSegmentAndBoundSet { + segment: ast::PathSegment { + identifier: identifier, + lifetime: optional_lifetime, + types: types, + }, + bound_set: bound_set + }); - let rp = match (&rp_slash, &lifetimes) { - (&Some(_), _) => rp_slash, - (&None, v) => { - if v.len() == 0 { - None - } else if v.len() == 1 { - Some(*v.get(0)) - } else { - self.fatal(fmt!("Expected at most one \ - lifetime name (for now)")); + // We're done if we don't see a '::', unless the mode required + // a double colon to get here in the first place. + if !(mode == LifetimeAndTypesWithColons && + !any_lifetime_or_types) { + if !self.eat(&token::MOD_SEP) { + break } } - }; - - ast::Path { - span: mk_sp(lo, hi), - rp: rp, - types: tps, - .. path.clone() } - } - // parse a path optionally with type parameters. If 'colons' - // is true, then type parameters must be preceded by colons, - // as in a::t:: - pub fn parse_path_with_tps(&self, colons: bool) -> ast::Path { - self.parse_bounded_path_with_tps(colons, None) - } + // Assemble the span. + let span = mk_sp(lo, self.last_span.hi); - // Like the above, but can also parse kind bounds in the case of a - // path to be used as a type that might be a trait. - pub fn parse_type_path(&self) -> (ast::Path, Option>) { + // Assemble the path segments. + let mut path_segments = ~[]; let mut bounds = None; - let path = self.parse_bounded_path_with_tps(false, Some(|| { - // Note: this closure might not even get called in the case of a - // macro-generated path. But that's the macro parser's job. - bounds = self.parse_optional_ty_param_bounds(); - })); - (path, bounds) + let last_segment_index = segments.len() - 1; + for (i, segment_and_bounds) in segments.consume_iter().enumerate() { + let PathSegmentAndBoundSet { + segment: segment, + bound_set: bound_set + } = segment_and_bounds; + path_segments.push(segment); + + if bound_set.is_some() { + if i != last_segment_index { + self.span_err(span, + "type parameter bounds are allowed only \ + before the last segment in a path") + } + + bounds = bound_set + } + } + + // Assemble the result. + let path_and_bounds = PathAndBounds { + path: ast::Path { + span: span, + global: is_global, + segments: path_segments, + }, + bounds: bounds, + }; + + path_and_bounds } /// parses 0 or 1 lifetime @@ -1488,7 +1536,8 @@ impl Parser { if self.eat_keyword(keywords::Mut) { m_mutbl } else if self.eat_keyword(keywords::Const) { - m_const + self.obsolete(*self.last_span, ObsoleteConstPointer); + m_imm } else { m_imm } @@ -1645,7 +1694,7 @@ impl Parser { } else if *self.token == token::LBRACKET { self.bump(); let mutbl = self.parse_mutability(); - if mutbl == m_mutbl || mutbl == m_const { + if mutbl == m_mutbl { self.obsolete(*self.last_span, ObsoleteMutVector); } @@ -1709,7 +1758,7 @@ impl Parser { } else if *self.token == token::MOD_SEP || is_ident(&*self.token) && !self.is_keyword(keywords::True) && !self.is_keyword(keywords::False) { - let pth = self.parse_path_with_tps(true); + let pth = self.parse_path(LifetimeAndTypesWithColons).path; // `!`, as an operator, is prefix, so we know this isn't that if *self.token == token::NOT { @@ -2100,10 +2149,6 @@ impl Parser { token::AT => { self.bump(); let m = self.parse_mutability(); - if m == m_const { - self.obsolete(*self.last_span, ObsoleteConstManagedPointer); - } - let e = self.parse_prefix_expr(); hi = e.span.hi; // HACK: turn @[...] into a @-evec @@ -2804,7 +2849,8 @@ impl Parser { let val = self.parse_literal_maybe_minus(); if self.eat(&token::DOTDOT) { let end = if is_ident_or_path(tok) { - let path = self.parse_path_with_tps(true); + let path = self.parse_path(LifetimeAndTypesWithColons) + .path; let hi = self.span.hi; self.mk_expr(lo, hi, expr_path(path)) } else { @@ -2833,7 +2879,7 @@ impl Parser { let end = self.parse_expr_res(RESTRICT_NO_BAR_OP); pat = pat_range(start, end); } else if is_plain_ident(&*self.token) && !can_be_enum_or_struct { - let name = self.parse_path_without_tps(); + let name = self.parse_path(NoTypesAllowed).path; let sub; if self.eat(&token::AT) { // parse foo @ pat @@ -2845,7 +2891,8 @@ impl Parser { pat = pat_ident(bind_infer, name, sub); } else { // parse an enum pat - let enum_path = self.parse_path_with_tps(true); + let enum_path = self.parse_path(LifetimeAndTypesWithColons) + .path; match *self.token { token::LBRACE => { self.bump(); @@ -2881,7 +2928,7 @@ impl Parser { } }, _ => { - if enum_path.idents.len()==1u { + if enum_path.segments.len() == 1 { // it could still be either an enum // or an identifier pattern, resolve // will sort it out: @@ -2916,7 +2963,7 @@ impl Parser { "expected identifier, found path"); } // why a path here, and not just an identifier? - let name = self.parse_path_without_tps(); + let name = self.parse_path(NoTypesAllowed).path; let sub = if self.eat(&token::AT) { Some(self.parse_pat()) } else { @@ -3033,7 +3080,7 @@ impl Parser { // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... - let pth = self.parse_path_without_tps(); + let pth = self.parse_path(NoTypesAllowed).path; self.bump(); let id = if *self.token == token::LPAREN { @@ -3720,7 +3767,7 @@ impl Parser { // parse a::B<~str,int> fn parse_trait_ref(&self) -> trait_ref { ast::trait_ref { - path: self.parse_path_with_tps(false), + path: self.parse_path(LifetimeAndTypesWithoutColons).path, ref_id: self.get_id(), } } @@ -4610,7 +4657,7 @@ impl Parser { } // item macro. - let pth = self.parse_path_without_tps(); + let pth = self.parse_path(NoTypesAllowed).path; self.expect(&token::NOT); // a 'special' identifier (like what `macro_rules!` uses) @@ -4694,11 +4741,17 @@ impl Parser { let id = self.parse_ident(); path.push(id); } - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.consume_iter().transform(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_simple(first_ident, path, @@ -4724,11 +4777,17 @@ impl Parser { seq_sep_trailing_allowed(token::COMMA), |p| p.parse_path_list_ident() ); - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.consume_iter().transform(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_list(path, idents, self.get_id())); } @@ -4736,11 +4795,17 @@ impl Parser { // foo::bar::* token::BINOP(token::STAR) => { self.bump(); - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.consume_iter().transform(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_glob(path, self.get_id())); } @@ -4752,11 +4817,17 @@ impl Parser { _ => () } let last = path[path.len() - 1u]; - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.consume_iter().transform(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.last_span.hi, view_path_simple(last, path, self.get_id())); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f517179f60366..d8735e48c81c4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -387,7 +387,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) { word(s.s, "["); match mt.mutbl { ast::m_mutbl => word_space(s, "mut"), - ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); @@ -430,7 +429,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) { word(s.s, "["); match mt.mutbl { ast::m_mutbl => word_space(s, "mut"), - ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); @@ -1504,34 +1502,52 @@ pub fn print_for_decl(s: @ps, loc: &ast::Local, coll: &ast::expr) { print_expr(s, coll); } -fn print_path_(s: @ps, path: &ast::Path, colons_before_params: bool, +fn print_path_(s: @ps, + path: &ast::Path, + colons_before_params: bool, opt_bounds: &Option>) { maybe_print_comment(s, path.span.lo); - if path.global { word(s.s, "::"); } - let mut first = true; - for id in path.idents.iter() { - if first { first = false; } else { word(s.s, "::"); } - print_ident(s, *id); + if path.global { + word(s.s, "::"); } - do opt_bounds.map |bounds| { - print_bounds(s, bounds, true); - }; - if path.rp.is_some() || !path.types.is_empty() { - if colons_before_params { word(s.s, "::"); } - if path.rp.is_some() || !path.types.is_empty() { + let mut first = true; + for (i, segment) in path.segments.iter().enumerate() { + if first { + first = false + } else { + word(s.s, "::") + } + + print_ident(s, segment.identifier); + + if segment.lifetime.is_some() || !segment.types.is_empty() { + // If this is the last segment, print the bounds. + if i == path.segments.len() - 1 { + match *opt_bounds { + None => {} + Some(ref bounds) => print_bounds(s, bounds, true), + } + } + + if colons_before_params { + word(s.s, "::") + } word(s.s, "<"); - for r in path.rp.iter() { - print_lifetime(s, r); - if !path.types.is_empty() { - word_space(s, ","); + for lifetime in segment.lifetime.iter() { + print_lifetime(s, lifetime); + if !segment.types.is_empty() { + word_space(s, ",") } } - commasep(s, inconsistent, path.types, print_type); + commasep(s, + inconsistent, + segment.types.map_to_vec(|t| (*t).clone()), + print_type); - word(s.s, ">"); + word(s.s, ">") } } } @@ -1822,7 +1838,7 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) { pub fn print_view_path(s: @ps, vp: &ast::view_path) { match vp.node { ast::view_path_simple(ident, ref path, _) => { - if path.idents[path.idents.len()-1u] != ident { + if path.segments.last().identifier != ident { print_ident(s, ident); space(s.s); word_space(s, "="); @@ -1879,7 +1895,6 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) { pub fn print_mutability(s: @ps, mutbl: ast::mutability) { match mutbl { ast::m_mutbl => word_nbsp(s, "mut"), - ast::m_const => word_nbsp(s, "const"), ast::m_imm => {/* nothing */ } } } @@ -1899,8 +1914,9 @@ pub fn print_arg(s: @ps, input: &ast::arg) { _ => { match input.pat.node { ast::pat_ident(_, ref path, _) if - path.idents.len() == 1 && - path.idents[0] == parse::token::special_idents::invalid => { + path.segments.len() == 1 && + path.segments[0].identifier == + parse::token::special_idents::invalid => { // Do nothing. } _ => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7aa52bc13e341..ff549d5fffd6f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -255,8 +255,10 @@ pub fn visit_ty(visitor: @Visitor, typ: &Ty, env: E) { } pub fn visit_path(visitor: @Visitor, path: &Path, env: E) { - for typ in path.types.iter() { - visitor.visit_ty(typ, env.clone()) + for segment in path.segments.iter() { + for typ in segment.types.iter() { + visitor.visit_ty(typ, env.clone()) + } } } diff --git a/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs b/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs deleted file mode 100644 index c51cf5b9538d9..0000000000000 --- a/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Test that attempt to alias `&mut` pointer while pointee is borrowed -// yields an error. -// -// Example from src/middle/borrowck/doc.rs - -use std::util::swap; - -fn foo(t0: &mut int) { - let p: &int = &*t0; // Freezes `*t0` - let q: &const &mut int = &const t0; //~ ERROR cannot borrow `t0` - **q = 22; //~ ERROR cannot assign to an `&mut` in a `&const` pointer -} - -fn main() { -} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs index 7e9c298ba4732..843b5436d842c 100644 --- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -11,16 +11,6 @@ fn foo(t0: & &mut int) { **t1 = 22; //~ ERROR cannot assign } -fn foo2(t0: &const &mut int) { - // Note: reborrowing from an &const actually yields two errors, since it - // is unsafe in two ways: we can't control the aliasing, and we can't - // control the mutation. - let t1 = t0; - let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&const` pointer - //~^ ERROR unsafe borrow of aliasable, const value - **t1 = 22; //~ ERROR cannot assign -} - fn foo3(t0: &mut &mut int) { let t1 = &mut *t0; let p: &int = &**t0; //~ ERROR cannot borrow @@ -28,4 +18,4 @@ fn foo3(t0: &mut &mut int) { } fn main() { -} \ No newline at end of file +} diff --git a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs index 0aa7cbf50b7a3..537e52120d9f1 100644 --- a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs +++ b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs @@ -14,29 +14,18 @@ struct Foo { impl Foo { pub fn f(&self) {} - pub fn g(&const self) {} pub fn h(&mut self) {} } fn a(x: &mut Foo) { x.f(); - x.g(); x.h(); } fn b(x: &Foo) { x.f(); - x.g(); x.h(); //~ ERROR cannot borrow } -fn c(x: &const Foo) { - x.f(); //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - x.g(); - x.h(); //~ ERROR cannot borrow - //~^ ERROR unsafe borrow -} - fn main() { } diff --git a/src/test/compile-fail/borrowck-lend-flow.rs b/src/test/compile-fail/borrowck-lend-flow.rs index 59cac0c5d953a..ea840a28b4e6a 100644 --- a/src/test/compile-fail/borrowck-lend-flow.rs +++ b/src/test/compile-fail/borrowck-lend-flow.rs @@ -32,14 +32,6 @@ fn pre_freeze() { borrow_mut(v); //~ ERROR cannot borrow } -fn pre_const() { - // In this instance, the freeze starts before the mut borrow. - - let mut v = ~3; - let _w = &const v; - borrow_mut(v); -} - fn post_freeze() { // In this instance, the const alias starts after the borrow. diff --git a/src/test/compile-fail/borrowck-loan-vec-content.rs b/src/test/compile-fail/borrowck-loan-vec-content.rs index 6a8e64377aab2..8a4a2cdedb230 100644 --- a/src/test/compile-fail/borrowck-loan-vec-content.rs +++ b/src/test/compile-fail/borrowck-loan-vec-content.rs @@ -29,16 +29,5 @@ fn has_mut_vec_but_tries_to_change_it() { } } -fn takes_const_elt(_v: &const int, f: &fn()) { - f(); -} - -fn has_mut_vec_and_tries_to_change_it() { - let mut v = ~[1, 2, 3]; - do takes_const_elt(&const v[0]) { - v[1] = 4; - } -} - fn main() { } diff --git a/src/test/compile-fail/borrowck-pat-by-value-binding.rs b/src/test/compile-fail/borrowck-pat-by-value-binding.rs deleted file mode 100644 index e77f5245d7d8b..0000000000000 --- a/src/test/compile-fail/borrowck-pat-by-value-binding.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -fn process(_t: T) {} - -fn match_const_opt_by_mut_ref(v: &const Option) { - match *v { - Some(ref mut i) => process(i), //~ ERROR cannot borrow - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_const_ref(v: &const Option) { - match *v { - Some(ref const i) => process(i), - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_imm_ref(v: &const Option) { - match *v { - Some(ref i) => process(i), //~ ERROR cannot borrow - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_value(v: &const Option) { - match *v { - Some(i) => process(i), - None => () - } -} - -fn main() { -} diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck-uniq-via-lend.rs index 43459acaaf185..c87428cd300a7 100644 --- a/src/test/compile-fail/borrowck-uniq-via-lend.rs +++ b/src/test/compile-fail/borrowck-uniq-via-lend.rs @@ -35,12 +35,6 @@ fn aliased_imm() { borrow(v); } -fn aliased_const() { - let mut v = ~3; - let _w = &const v; - borrow(v); -} - fn aliased_mut() { let mut v = ~3; let _w = &mut v; diff --git a/src/test/compile-fail/fn-variance-3.rs b/src/test/compile-fail/fn-variance-3.rs index 630eb4b538d58..e42c6b658e4f7 100644 --- a/src/test/compile-fail/fn-variance-3.rs +++ b/src/test/compile-fail/fn-variance-3.rs @@ -23,13 +23,10 @@ fn main() { // @int <: X // - // This constraint forces X to be - // @const int. - r(@3); + // Here the type check fails because @const is gone and there is no + // supertype. + r(@3); //~ ERROR mismatched types - // Here the type check succeeds but the - // mutability check will fail, because the - // type of r has been inferred to be - // fn(@const int) -> @const int - *r(@mut 3) = 4; //~ ERROR cannot assign to const dereference of @ pointer + // Here the type check succeeds. + *r(@mut 3) = 4; } diff --git a/src/test/compile-fail/issue-3969.rs b/src/test/compile-fail/issue-3969.rs deleted file mode 100644 index b60a54a44bbfd..0000000000000 --- a/src/test/compile-fail/issue-3969.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -struct Bike { - name: ~str, -} - -trait BikeMethods { - fn woops(&const self) -> ~str; -} - -impl BikeMethods for Bike { - fn woops() -> ~str { ~"foo" } - //~^ ERROR has a `&const self` declaration in the trait, but not in the impl -} - -pub fn main() { -} diff --git a/src/test/compile-fail/mutable-huh-ptr-assign.rs b/src/test/compile-fail/mutable-huh-ptr-assign.rs deleted file mode 100644 index 4460da72e2059..0000000000000 --- a/src/test/compile-fail/mutable-huh-ptr-assign.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -extern mod extra; - -fn main() { - unsafe fn f(v: *const int) { - *v = 1 //~ ERROR cannot assign - } - - unsafe { - let mut a = 0; - let v = &mut a; - f(v); - } -} diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs index 65fbbfc6e1985..351daf461d2fe 100644 --- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs +++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs @@ -26,13 +26,6 @@ fn matcher2(x: opts) { } } -fn matcher3(x: opts) { - match x { - a(ref mut i) | b(ref const i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 - c(_) => {} - } -} - fn matcher4(x: opts) { match x { a(ref mut i) | b(ref i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 diff --git a/src/test/run-pass/auto-ref-slice-plus-ref.rs b/src/test/run-pass/auto-ref-slice-plus-ref.rs index 58a477900c324..d35341516f2a7 100644 --- a/src/test/run-pass/auto-ref-slice-plus-ref.rs +++ b/src/test/run-pass/auto-ref-slice-plus-ref.rs @@ -13,17 +13,14 @@ trait MyIter { fn test_imm(&self); - fn test_const(&const self); } impl<'self> MyIter for &'self [int] { fn test_imm(&self) { assert_eq!(self[0], 1) } - fn test_const(&const self) { assert_eq!(self[0], 1) } } impl<'self> MyIter for &'self str { fn test_imm(&self) { assert_eq!(*self, "test") } - fn test_const(&const self) { assert_eq!(self[0], 't' as u8) } } pub fn main() { @@ -40,15 +37,6 @@ pub fn main() { // XXX: Other types of mutable vecs don't currently exist - ([1]).test_const(); - (~[1]).test_const(); - (@[1]).test_const(); - (&[1]).test_const(); - ("test").test_const(); - (~"test").test_const(); - (@"test").test_const(); - (&"test").test_const(); - // NB: We don't do this double autoreffing for &mut self because that would // allow creating a mutable pointer to a temporary, which would be a source // of confusion diff --git a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs index b00d8980c69fe..fc643ec594089 100644 --- a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs +++ b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs @@ -13,7 +13,7 @@ struct Foo { } impl Foo { - pub fn f(&const self) {} + pub fn f(&self) {} } fn g(x: &mut Foo) { diff --git a/src/test/compile-fail/borrowck-pat-enum.rs b/src/test/run-pass/borrowck-pat-enum.rs similarity index 65% rename from src/test/compile-fail/borrowck-pat-enum.rs rename to src/test/run-pass/borrowck-pat-enum.rs index f1cca89b227d6..6c00bea28b6e3 100644 --- a/src/test/compile-fail/borrowck-pat-enum.rs +++ b/src/test/run-pass/borrowck-pat-enum.rs @@ -24,32 +24,9 @@ fn match_ref_unused(v: Option) { } } -fn match_const_reg(v: &const Option) -> int { - match *v { - Some(ref i) => {*i} //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - None => {0} - } -} - fn impure(_i: int) { } -fn match_const_reg_unused(v: &const Option) { - match *v { - Some(_) => {impure(0)} // OK because nothing is captured - None => {} - } -} - -fn match_const_reg_impure(v: &const Option) { - match *v { - Some(ref i) => {impure(*i)} //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - None => {} - } -} - fn match_imm_reg(v: &Option) { match *v { Some(ref i) => {impure(*i)} // OK because immutable diff --git a/src/test/compile-fail/borrowck-uniq-via-ref.rs b/src/test/run-pass/borrowck-uniq-via-ref.rs similarity index 77% rename from src/test/compile-fail/borrowck-uniq-via-ref.rs rename to src/test/run-pass/borrowck-uniq-via-ref.rs index 8bf627d991911..44f3a8f518a15 100644 --- a/src/test/compile-fail/borrowck-uniq-via-ref.rs +++ b/src/test/run-pass/borrowck-uniq-via-ref.rs @@ -25,7 +25,6 @@ struct Innermost { } fn borrow(_v: &int) {} -fn borrow_const(_v: &const int) {} fn box_mut(v: &mut ~int) { borrow(*v); // OK: &mut -> &imm @@ -51,17 +50,5 @@ fn box_imm_recs(v: &Outer) { borrow(v.f.g.h); // OK } -fn box_const(v: &const ~int) { - borrow_const(*v); //~ ERROR unsafe borrow -} - -fn box_const_rec(v: &const Rec) { - borrow_const(v.f); //~ ERROR unsafe borrow -} - -fn box_const_recs(v: &const Outer) { - borrow_const(v.f.g.h); //~ ERROR unsafe borrow -} - fn main() { } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index d42c57c3b81a0..725019fd9f516 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -51,8 +51,8 @@ impl cat { } impl Container for cat { - fn len(&const self) -> uint { self.meows as uint } - fn is_empty(&const self) -> bool { self.meows == 0 } + fn len(&self) -> uint { self.meows as uint } + fn is_empty(&self) -> bool { self.meows == 0 } } impl Mutable for cat { diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs index 438c70c6583f4..69e5d692d0d3d 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs @@ -3,14 +3,14 @@ struct SpeechMaker { } impl SpeechMaker { - pub fn how_many(&const self) -> uint { self.speeches } + pub fn how_many(&self) -> uint { self.speeches } } -fn foo(speaker: &const SpeechMaker) -> uint { +fn foo(speaker: &SpeechMaker) -> uint { speaker.how_many() + 33 } pub fn main() { let mut lincoln = SpeechMaker {speeches: 22}; - assert_eq!(foo(&const lincoln), 55); + assert_eq!(foo(&lincoln), 55); } diff --git a/src/test/run-pass/const-vec-syntax.rs b/src/test/run-pass/const-vec-syntax.rs index 625f6ec30cc13..84ee54cfdde6d 100644 --- a/src/test/run-pass/const-vec-syntax.rs +++ b/src/test/run-pass/const-vec-syntax.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(_: &const [int]) {} +fn f(_: &[int]) {} pub fn main() { let v = [ 1, 2, 3 ]; diff --git a/src/test/run-pass/mid-path-type-params.rs b/src/test/run-pass/mid-path-type-params.rs new file mode 100644 index 0000000000000..8f01bd5e5eacf --- /dev/null +++ b/src/test/run-pass/mid-path-type-params.rs @@ -0,0 +1,16 @@ +struct S { + contents: T, +} + +impl S { + fn new(x: T, _: U) -> S { + S { + contents: x, + } + } +} + +fn main() { + let _ = S::::new::(1, 1.0); +} +