syntax: make OptVec immutable.

This is the first step to replacing OptVec with a new representation:
remove all mutability. Any mutations have to go via `Vec` and then make
to `OptVec`.

Many of the uses of OptVec are unnecessary now that Vec has no-alloc
emptiness (and have been converted to Vec): the only ones that really
need it are the AST and sty's (and so on) where there are a *lot* of
instances of them, and they're (mostly) immutable.
This commit is contained in:
Huon Wilson 2014-03-19 23:16:56 +11:00
parent 7334c11b4b
commit 7785fe1916
15 changed files with 79 additions and 126 deletions

View File

@ -192,13 +192,13 @@ fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
match next(st) {
'e' => ty::ErasedRegions,
'n' => {
let mut regions = opt_vec::Empty;
let mut regions = vec!();
while peek(st) != '.' {
let r = parse_region(st, |x,y| conv(x,y));
regions.push(r);
}
assert_eq!(next(st), '.');
ty::NonerasedRegions(regions)
ty::NonerasedRegions(opt_vec::from(regions))
}
_ => fail!("parse_bound_region: bad input")
}

View File

@ -26,8 +26,6 @@ use middle::typeck;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use util::ppaux::Repr;
pub struct MoveData {
@ -316,15 +314,15 @@ impl MoveData {
fn existing_base_paths(&self,
lp: @LoanPath)
-> OptVec<MovePathIndex> {
let mut result = opt_vec::Empty;
-> Vec<MovePathIndex> {
let mut result = vec!();
self.add_existing_base_paths(lp, &mut result);
result
}
fn add_existing_base_paths(&self,
lp: @LoanPath,
result: &mut OptVec<MovePathIndex>) {
result: &mut Vec<MovePathIndex>) {
/*!
* Adds any existing move path indices for `lp` and any base
* paths of `lp` to `result`, but does not add new move paths

View File

@ -14,7 +14,6 @@ use middle::typeck;
use middle::ty;
use syntax::ast;
use syntax::ast_util;
use syntax::opt_vec;
use util::nodemap::NodeMap;
struct CFGBuilder<'a> {
@ -470,7 +469,7 @@ impl<'a> CFGBuilder<'a> {
fn add_contained_edge(&mut self,
source: CFGIndex,
target: CFGIndex) {
let data = CFGEdgeData {exiting_scopes: opt_vec::Empty};
let data = CFGEdgeData {exiting_scopes: vec!() };
self.graph.add_edge(source, target, data);
}
@ -479,9 +478,10 @@ impl<'a> CFGBuilder<'a> {
from_index: CFGIndex,
to_loop: LoopScope,
to_index: CFGIndex) {
let mut data = CFGEdgeData {exiting_scopes: opt_vec::Empty};
let mut data = CFGEdgeData {exiting_scopes: vec!() };
let mut scope_id = from_expr.id;
while scope_id != to_loop.loop_id {
data.exiting_scopes.push(scope_id);
scope_id = self.tcx.region_maps.encl_scope(scope_id);
}

View File

@ -19,7 +19,6 @@ use middle::graph;
use middle::ty;
use middle::typeck;
use syntax::ast;
use syntax::opt_vec::OptVec;
use util::nodemap::NodeMap;
mod construct;
@ -36,7 +35,7 @@ pub struct CFGNodeData {
}
pub struct CFGEdgeData {
exiting_scopes: OptVec<ast::NodeId>
exiting_scopes: Vec<ast::NodeId>
}
pub type CFGIndex = graph::NodeIndex;

View File

@ -21,7 +21,6 @@ use driver::session::Session;
use util::nodemap::NodeMap;
use syntax::ast;
use syntax::codemap::Span;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
use syntax::parse::token::special_idents;
use syntax::parse::token;
@ -413,7 +412,7 @@ pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifeti
.collect()
}
pub fn free_lifetimes(ty_params: &OptVec<ast::TyParam>) -> OptVec<ast::Name> {
pub fn free_lifetimes(ty_params: &OptVec<ast::TyParam>) -> Vec<ast::Name> {
/*!
* Gathers up and returns the names of any lifetimes that appear
* free in `ty_params`. Of course, right now, all lifetimes appear
@ -421,14 +420,14 @@ pub fn free_lifetimes(ty_params: &OptVec<ast::TyParam>) -> OptVec<ast::Name> {
* declarations; just being forwards compatible with future extensions.
*/
let mut collector = FreeLifetimeCollector { names: opt_vec::Empty };
let mut collector = FreeLifetimeCollector { names: vec!() };
for ty_param in ty_params.iter() {
visit::walk_ty_param_bounds(&mut collector, &ty_param.bounds, ());
}
return collector.names;
struct FreeLifetimeCollector {
names: OptVec<ast::Name>,
names: Vec<ast::Name>,
}
impl Visitor<()> for FreeLifetimeCollector {

View File

@ -24,8 +24,6 @@ use middle::trans::glue;
use middle::trans::type_::Type;
use middle::ty;
use syntax::ast;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
use util::ppaux::Repr;
pub struct CleanupScope<'a> {
@ -37,9 +35,9 @@ pub struct CleanupScope<'a> {
kind: CleanupScopeKind<'a>,
// Cleanups to run upon scope exit.
cleanups: OptVec<~Cleanup>,
cleanups: Vec<~Cleanup>,
cached_early_exits: OptVec<CachedEarlyExit>,
cached_early_exits: Vec<CachedEarlyExit>,
cached_landing_pad: Option<BasicBlockRef>,
}
@ -379,7 +377,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
assert!(orig_scopes_len > 0);
// Remove any scopes that do not have cleanups on failure:
let mut popped_scopes = opt_vec::Empty;
let mut popped_scopes = vec!();
while !self.top_scope(|s| s.needs_invoke()) {
debug!("top scope does not need invoke");
popped_scopes.push(self.pop_scope());
@ -510,7 +508,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
let orig_scopes_len = self.scopes_len();
let mut prev_llbb;
let mut popped_scopes = opt_vec::Empty;
let mut popped_scopes = vec!();
// First we pop off all the cleanup stacks that are
// traversed until the exit is reached, pushing them
@ -708,14 +706,14 @@ impl<'a> CleanupScope<'a> {
fn new(kind: CleanupScopeKind<'a>) -> CleanupScope<'a> {
CleanupScope {
kind: kind,
cleanups: opt_vec::Empty,
cached_early_exits: opt_vec::Empty,
cleanups: vec!(),
cached_early_exits: vec!(),
cached_landing_pad: None,
}
}
fn clear_cached_exits(&mut self) {
self.cached_early_exits = opt_vec::Empty;
self.cached_early_exits = vec!();
self.cached_landing_pad = None;
}

View File

@ -5072,11 +5072,10 @@ pub fn construct_parameter_environment(
// map bound 'a => free 'a
let region_params = {
fn push_region_params(accum: OptVec<ty::Region>,
fn push_region_params(mut accum: Vec<ty::Region>,
free_id: ast::NodeId,
region_params: &[RegionParameterDef])
-> OptVec<ty::Region> {
let mut accum = accum;
-> Vec<ty::Region> {
for r in region_params.iter() {
accum.push(
ty::ReFree(ty::FreeRegion {
@ -5086,14 +5085,14 @@ pub fn construct_parameter_environment(
accum
}
let t = push_region_params(opt_vec::Empty, free_id, item_region_params);
let t = push_region_params(vec!(), free_id, item_region_params);
push_region_params(t, free_id, method_region_params)
};
let free_substs = substs {
self_ty: self_ty,
tps: type_params,
regions: ty::NonerasedRegions(region_params)
regions: ty::NonerasedRegions(opt_vec::from(region_params))
};
//

View File

@ -104,6 +104,7 @@ use syntax::ast::{MutMutable, MutImmutable};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::opt_vec;
#[deriving(Eq)]
pub enum CheckTraitsFlag {
@ -1102,8 +1103,8 @@ impl<'a> LookupContext<'a> {
// Determine values for the early-bound lifetime parameters.
// FIXME -- permit users to manually specify lifetimes
let mut all_regions = match candidate.rcvr_substs.regions {
NonerasedRegions(ref v) => v.clone(),
let mut all_regions: Vec<Region> = match candidate.rcvr_substs.regions {
NonerasedRegions(ref v) => v.iter().map(|r| r.clone()).collect(),
ErasedRegions => tcx.sess.span_bug(self.span, "ErasedRegions")
};
let m_regions =
@ -1119,7 +1120,7 @@ impl<'a> LookupContext<'a> {
let all_substs = substs {
tps: vec::append(candidate.rcvr_substs.tps.clone(),
m_substs.as_slice()),
regions: NonerasedRegions(all_regions),
regions: NonerasedRegions(opt_vec::from(all_regions)),
self_ty: candidate.rcvr_substs.self_ty,
};

View File

@ -160,7 +160,7 @@ pub trait Combine {
assert_eq!(num_region_params, a_rs.len());
assert_eq!(num_region_params, b_rs.len());
let mut rs = opt_vec::Empty;
let mut rs = vec!();
for i in range(0, num_region_params) {
let a_r = *a_rs.get(i);
let b_r = *b_rs.get(i);
@ -176,7 +176,7 @@ pub trait Combine {
};
rs.push(if_ok!(r));
}
Ok(ty::NonerasedRegions(rs))
Ok(ty::NonerasedRegions(opt_vec::from(rs)))
}
}
}

View File

@ -80,8 +80,6 @@ use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
use syntax::ast_util::name_to_dummy_lifetime;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
use syntax::parse::token;
use syntax::print::pprust;
use util::ppaux::UserString;
@ -90,10 +88,10 @@ use util::ppaux::note_and_explain_region;
pub trait ErrorReporting {
fn report_region_errors(&self,
errors: &OptVec<RegionResolutionError>);
errors: &Vec<RegionResolutionError>);
fn process_errors(&self, errors: &OptVec<RegionResolutionError>)
-> OptVec<RegionResolutionError>;
fn process_errors(&self, errors: &Vec<RegionResolutionError>)
-> Vec<RegionResolutionError>;
fn report_type_error(&self, trace: TypeTrace, terr: &ty::type_err);
@ -151,7 +149,7 @@ trait ErrorReportingHelpers {
impl<'a> ErrorReporting for InferCtxt<'a> {
fn report_region_errors(&self,
errors: &OptVec<RegionResolutionError>) {
errors: &Vec<RegionResolutionError>) {
let p_errors = self.process_errors(errors);
let errors = if p_errors.is_empty() { errors } else { &p_errors };
for error in errors.iter() {
@ -195,12 +193,12 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
// complete view of what lifetimes should be the same.
// If the return value is an empty vector, it means that processing
// failed (so the return value of this method should not be used)
fn process_errors(&self, errors: &OptVec<RegionResolutionError>)
-> OptVec<RegionResolutionError> {
fn process_errors(&self, errors: &Vec<RegionResolutionError>)
-> Vec<RegionResolutionError> {
let mut var_origins = Vec::new();
let mut trace_origins = Vec::new();
let mut same_regions = Vec::new();
let mut processed_errors = opt_vec::Empty;
let mut processed_errors = Vec::new();
for error in errors.iter() {
match *error {
ConcreteFailure(origin, sub, sup) => {
@ -239,7 +237,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
// declaration, we want to make sure that they are, in fact,
// from the same scope
if sr.scope_id != common_scope_id {
return opt_vec::Empty;
return vec!();
}
}
let pe = ProcessedErrors(var_origins, trace_origins, same_regions);

View File

@ -29,8 +29,6 @@ use std::uint;
use std::slice;
use collections::{HashMap, HashSet};
use syntax::ast;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
mod doc;
@ -561,9 +559,9 @@ impl<'a> RegionVarBindings<'a> {
constraints, assuming such values can be found; if they cannot,
errors are reported.
*/
pub fn resolve_regions(&self) -> OptVec<RegionResolutionError> {
pub fn resolve_regions(&self) -> Vec<RegionResolutionError> {
debug!("RegionVarBindings: resolve_regions()");
let mut errors = opt_vec::Empty;
let mut errors = vec!();
let v = self.infer_variable_values(&mut errors);
let mut values = self.values.borrow_mut();
*values.get() = Some(v);
@ -815,7 +813,7 @@ type RegionGraph = graph::Graph<(), Constraint>;
impl<'a> RegionVarBindings<'a> {
fn infer_variable_values(&self,
errors: &mut OptVec<RegionResolutionError>)
errors: &mut Vec<RegionResolutionError>)
-> Vec<VarValue> {
let mut var_data = self.construct_var_data();
self.expansion(var_data.as_mut_slice());
@ -1004,7 +1002,7 @@ impl<'a> RegionVarBindings<'a> {
fn collect_concrete_region_errors(
&self,
errors: &mut OptVec<RegionResolutionError>)
errors: &mut Vec<RegionResolutionError>)
{
let constraints = self.constraints.borrow();
for (constraint, _) in constraints.get().iter() {
@ -1033,7 +1031,7 @@ impl<'a> RegionVarBindings<'a> {
fn extract_values_and_collect_conflicts(
&self,
var_data: &[VarData],
errors: &mut OptVec<RegionResolutionError>)
errors: &mut Vec<RegionResolutionError>)
-> Vec<VarValue> {
debug!("extract_values_and_collect_conflicts()");
@ -1157,7 +1155,7 @@ impl<'a> RegionVarBindings<'a> {
var_data: &[VarData],
dup_vec: &mut [uint],
node_idx: RegionVid,
errors: &mut OptVec<RegionResolutionError>)
errors: &mut Vec<RegionResolutionError>)
{
// Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound.
@ -1206,7 +1204,7 @@ impl<'a> RegionVarBindings<'a> {
var_data: &[VarData],
dup_vec: &mut [uint],
node_idx: RegionVid,
errors: &mut OptVec<RegionResolutionError>)
errors: &mut Vec<RegionResolutionError>)
{
// Errors in contracting nodes result from two upper-bounds
// that have no intersection.

View File

@ -904,32 +904,33 @@ impl<'a> SolveContext<'a> {
let num_inferred = self.terms_cx.num_inferred();
while index < num_inferred {
let item_id = inferred_infos.get(index).item_id;
let mut item_variances = ty::ItemVariances {
self_param: None,
type_params: opt_vec::Empty,
region_params: opt_vec::Empty
};
let mut self_param = None;
let mut type_params = vec!();
let mut region_params = vec!();
while index < num_inferred &&
inferred_infos.get(index).item_id == item_id {
let info = inferred_infos.get(index);
match info.kind {
SelfParam => {
assert!(item_variances.self_param.is_none());
item_variances.self_param =
Some(*solutions.get(index));
assert!(self_param.is_none());
self_param = Some(*solutions.get(index));
}
TypeParam => {
item_variances.type_params
.push(*solutions.get(index));
type_params.push(*solutions.get(index));
}
RegionParam => {
item_variances.region_params
.push(*solutions.get(index));
region_params.push(*solutions.get(index));
}
}
index += 1;
}
let item_variances = ty::ItemVariances {
self_param: self_param,
type_params: opt_vec::from(type_params),
region_params: opt_vec::from(region_params)
};
debug!("item_id={} item_variances={}",
item_id,
item_variances.repr(tcx));

View File

@ -360,27 +360,32 @@ impl<'a> TraitDef<'a> {
methods: Vec<@ast::Method> ) -> @ast::Item {
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
let mut trait_generics = self.generics.to_generics(cx, self.span,
type_ident, generics);
let Generics { mut lifetimes, ty_params } =
self.generics.to_generics(cx, self.span, type_ident, generics);
let mut ty_params = opt_vec::take_vec(ty_params);
// Copy the lifetimes
for l in generics.lifetimes.iter() {
trait_generics.lifetimes.push(*l)
};
lifetimes.extend(&mut generics.lifetimes.iter().map(|l| *l));
// Create the type parameters.
for ty_param in generics.ty_params.iter() {
ty_params.extend(&mut generics.ty_params.iter().map(|ty_param| {
// I don't think this can be moved out of the loop, since
// a TyParamBound requires an ast id
let mut bounds = opt_vec::from(
let mut bounds =
// extra restrictions on the generics parameters to the type being derived upon
self.additional_bounds.map(|p| {
cx.typarambound(p.to_path(cx, self.span,
type_ident, generics))
}));
});
// require the current trait
bounds.push(cx.typarambound(trait_path.clone()));
trait_generics.ty_params.push(cx.typaram(ty_param.ident, bounds, None));
}
cx.typaram(ty_param.ident, opt_vec::from(bounds), None)
}));
let trait_generics = Generics {
lifetimes: lifetimes,
ty_params: opt_vec::from(ty_params)
};
// Create the reference to the trait.
let trait_ref = cx.trait_ref(trait_path);

View File

@ -37,25 +37,6 @@ pub fn from<T>(t: Vec<T> ) -> OptVec<T> {
}
impl<T> OptVec<T> {
pub fn push(&mut self, t: T) {
match *self {
Vec(ref mut v) => {
v.push(t);
return;
}
Empty => {
*self = Vec(vec!(t));
}
}
}
pub fn pop(&mut self) -> Option<T> {
match *self {
Vec(ref mut v) => v.pop(),
Empty => None
}
}
pub fn last<'a>(&'a self) -> Option<&'a T> {
match *self {
Vec(ref v) => v.last(),
@ -102,16 +83,6 @@ impl<T> OptVec<T> {
}
}
pub fn swap_remove(&mut self, index: uint) {
match *self {
Empty => { fail!("index out of bounds"); }
Vec(ref mut v) => {
assert!(index < v.len());
v.swap_remove(index);
}
}
}
#[inline]
pub fn iter<'r>(&'r self) -> Items<'r, T> {
match *self {
@ -142,17 +113,6 @@ pub fn take_vec<T>(v: OptVec<T>) -> Vec<T> {
}
}
impl<T:Clone> OptVec<T> {
pub fn prepend(&self, t: T) -> OptVec<T> {
let mut v0 = vec!(t);
match *self {
Empty => {}
Vec(ref v1) => { v0.push_all(v1.as_slice()); }
}
return Vec(v0);
}
}
impl<A:Eq> Eq for OptVec<A> {
fn eq(&self, other: &OptVec<A>) -> bool {
// Note: cannot use #[deriving(Eq)] here because
@ -208,10 +168,7 @@ impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
impl<A> FromIterator<A> for OptVec<A> {
fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> OptVec<A> {
let mut r = Empty;
for x in *iterator {
r.push(x);
}
r
let v: Vec<A> = iterator.collect();
from(v)
}
}

View File

@ -632,7 +632,7 @@ impl<'a> Parser<'a> {
f: |&mut Parser| -> T)
-> OptVec<T> {
let mut first = true;
let mut v = opt_vec::Empty;
let mut v = Vec::new();
while self.token != token::GT
&& self.token != token::BINOP(token::SHR) {
match sep {
@ -644,7 +644,7 @@ impl<'a> Parser<'a> {
}
v.push(f(self));
}
return v;
return opt_vec::from(v);
}
pub fn parse_seq_to_gt<T>(
@ -681,7 +681,7 @@ impl<'a> Parser<'a> {
f: |&mut Parser| -> T)
-> Vec<T> {
let mut first: bool = true;
let mut v: Vec<T> = Vec::new();
let mut v = vec!();
while self.token != *ket {
match sep.sep {
Some(ref t) => {
@ -3437,7 +3437,7 @@ impl<'a> Parser<'a> {
return None;
}
let mut result = opt_vec::Empty;
let mut result = vec!();
loop {
match self.token {
token::LIFETIME(lifetime) => {
@ -3462,7 +3462,7 @@ impl<'a> Parser<'a> {
}
}
return Some(result);
return Some(opt_vec::from(result));
}
// matches typaram = IDENT optbounds ( EQ ty )?