Skip to content

Commit

Permalink
Temporary bootstrapping hack: introduce syntax for r egion bounds lik…
Browse files Browse the repository at this point in the history
…e `'b:'a`,

meaning `'b outlives 'a`. Syntax currently does nothing but is needed for full
fix to #5763. To use this syntax, the issue_5763_bootstrap feature guard is
required.
  • Loading branch information
nikomatsakis committed Aug 7, 2014
1 parent 1a53c00 commit fcab980
Show file tree
Hide file tree
Showing 19 changed files with 240 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ impl<'a> Visitor<()> for Context<'a> {
run_lints!(self, check_lifetime_ref, lt);
}

fn visit_lifetime_decl(&mut self, lt: &ast::Lifetime, _: ()) {
fn visit_lifetime_decl(&mut self, lt: &ast::LifetimeDef, _: ()) {
run_lints!(self, check_lifetime_decl, lt);
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub trait LintPass {
fn check_variant(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<ast::Lifetime>) { }
fn check_lifetime_ref(&mut self, _: &Context, _: &ast::Lifetime) { }
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::Lifetime) { }
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::LifetimeDef) { }
fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { }
fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { }
Expand Down
44 changes: 27 additions & 17 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ struct LifetimeContext<'a> {
enum ScopeChain<'a> {
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
EarlyScope(subst::ParamSpace, &'a Vec<ast::Lifetime>, Scope<'a>),
EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
/// lifetimes introduced by the declaration binder_id.
LateScope(ast::NodeId, &'a Vec<ast::Lifetime>, Scope<'a>),
LateScope(ast::NodeId, &'a Vec<ast::LifetimeDef>, Scope<'a>),
/// lifetimes introduced by items within a code block are scoped
/// to that block.
BlockScope(ast::NodeId, Scope<'a>),
Expand Down Expand Up @@ -136,7 +136,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
fn push_fn_scope(this: &mut LifetimeContext,
ty: &ast::Ty,
scope: Scope,
lifetimes: &Vec<ast::Lifetime>) {
lifetimes: &Vec<ast::LifetimeDef>) {
let scope1 = LateScope(ty.id, lifetimes, scope);
this.check_lifetime_names(lifetimes);
debug!("pushing fn scope id={} due to type", ty.id);
Expand Down Expand Up @@ -216,7 +216,7 @@ impl<'a> LifetimeContext<'a> {
walk(self, &scope1)
} else {
let (early, late) = generics.lifetimes.clone().partition(
|l| referenced_idents.iter().any(|&i| i == l.name));
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));

let scope1 = EarlyScope(subst::FnSpace, &early, scope);
let scope2 = LateScope(n, &late, &scope1);
Expand Down Expand Up @@ -334,29 +334,39 @@ impl<'a> LifetimeContext<'a> {
token::get_name(lifetime_ref.name)).as_slice());
}

fn check_lifetime_names(&self, lifetimes: &Vec<ast::Lifetime>) {
fn check_lifetime_names(&self, lifetimes: &Vec<ast::LifetimeDef>) {
for i in range(0, lifetimes.len()) {
let lifetime_i = lifetimes.get(i);

let special_idents = [special_idents::static_lifetime];
for lifetime in lifetimes.iter() {
if special_idents.iter().any(|&i| i.name == lifetime.name) {
if special_idents.iter().any(|&i| i.name == lifetime.lifetime.name) {
self.sess.span_err(
lifetime.span,
lifetime.lifetime.span,
format!("illegal lifetime parameter name: `{}`",
token::get_name(lifetime.name)).as_slice());
token::get_name(lifetime.lifetime.name))
.as_slice());
}
}

for j in range(i + 1, lifetimes.len()) {
let lifetime_j = lifetimes.get(j);

if lifetime_i.name == lifetime_j.name {
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
self.sess.span_err(
lifetime_j.span,
lifetime_j.lifetime.span,
format!("lifetime name `{}` declared twice in \
the same scope",
token::get_name(lifetime_j.name)).as_slice());
token::get_name(lifetime_j.lifetime.name))
.as_slice());
}
}

for bound in lifetime_i.bounds.iter() {
if !self.sess.features.issue_5723_bootstrap.get() {
self.sess.span_err(
bound.span,
"region bounds require `issue_5723_bootstrap`");
}
}
}
Expand All @@ -379,28 +389,28 @@ impl<'a> LifetimeContext<'a> {
}
}

fn search_lifetimes(lifetimes: &Vec<ast::Lifetime>,
fn search_lifetimes(lifetimes: &Vec<ast::LifetimeDef>,
lifetime_ref: &ast::Lifetime)
-> Option<(uint, ast::NodeId)> {
for (i, lifetime_decl) in lifetimes.iter().enumerate() {
if lifetime_decl.name == lifetime_ref.name {
return Some((i, lifetime_decl.id));
if lifetime_decl.lifetime.name == lifetime_ref.name {
return Some((i, lifetime_decl.lifetime.id));
}
}
return None;
}

///////////////////////////////////////////////////////////////////////////

pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifetime> {
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::LifetimeDef> {
let referenced_idents = free_lifetimes(&generics.ty_params);
if referenced_idents.is_empty() {
return Vec::new();
}

generics.lifetimes.iter()
.filter(|l| referenced_idents.iter().any(|&i| i == l.name))
.map(|l| *l)
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
.map(|l| (*l).clone())
.collect()
}

Expand Down
11 changes: 6 additions & 5 deletions src/librustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,9 +804,10 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
generics.lifetimes
.iter()
.enumerate()
.map(|(i, def)| ty::ReEarlyBound(def.id,
.map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
subst::TypeSpace,
i, def.name))
i,
def.lifetime.name))
.collect();

let types =
Expand Down Expand Up @@ -1073,18 +1074,18 @@ fn add_unsized_bound(ccx: &CrateCtxt,

fn ty_generics(ccx: &CrateCtxt,
space: subst::ParamSpace,
lifetimes: &Vec<ast::Lifetime>,
lifetimes: &Vec<ast::LifetimeDef>,
types: &OwnedSlice<ast::TyParam>,
base_generics: ty::Generics)
-> ty::Generics
{
let mut result = base_generics;

for (i, l) in lifetimes.iter().enumerate() {
let def = ty::RegionParameterDef { name: l.name,
let def = ty::RegionParameterDef { name: l.lifetime.name,
space: space,
index: i,
def_id: local_def(l.id) };
def_id: local_def(l.lifetime.id) };
debug!("ty_generics: def for region param: {}", def);
result.regions.push(space, def);
}
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/typeck/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,10 +976,13 @@ impl<'a> Rebuilder<'a> {
-> ast::Generics {
let mut lifetimes = Vec::new();
for lt in add.iter() {
lifetimes.push(*lt);
lifetimes.push(ast::LifetimeDef { lifetime: *lt,
bounds: Vec::new() });
}
for lt in generics.lifetimes.iter() {
if keep.contains(&lt.name) || !remove.contains(&lt.name) {
if keep.contains(&lt.lifetime.name) ||
!remove.contains(&lt.lifetime.name)
{
lifetimes.push((*lt).clone());
}
}
Expand Down Expand Up @@ -1439,7 +1442,7 @@ impl Resolvable for Rc<ty::TraitRef> {

fn lifetimes_in_scope(tcx: &ty::ctxt,
scope_id: ast::NodeId)
-> Vec<ast::Lifetime> {
-> Vec<ast::LifetimeDef> {
let mut taken = Vec::new();
let parent = tcx.map.get_parent(scope_id);
let method_id_opt = match tcx.map.find(parent) {
Expand Down Expand Up @@ -1486,10 +1489,10 @@ struct LifeGiver {
}

impl LifeGiver {
fn with_taken(taken: &[ast::Lifetime]) -> LifeGiver {
fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
let mut taken_ = HashSet::new();
for lt in taken.iter() {
let lt_name = token::get_name(lt.name).get().to_string();
let lt_name = token::get_name(lt.lifetime.name).get().to_string();
taken_.insert(lt_name);
}
LifeGiver {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/typeck/variance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ impl<'a> Visitor<()> for TermsContext<'a> {
ast::ItemStruct(_, ref generics) |
ast::ItemTrait(ref generics, _, _, _) => {
for (i, p) in generics.lifetimes.iter().enumerate() {
self.add_inferred(item.id, RegionParam, TypeSpace, i, p.id);
let id = p.lifetime.id;
self.add_inferred(item.id, RegionParam, TypeSpace, i, id);
}
for (i, p) in generics.ty_params.iter().enumerate() {
self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_back/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ mod svh_visitor {
SawLifetimeRef(content(l.name)).hash(self.st);
}

fn visit_lifetime_decl(&mut self, l: &Lifetime, _: E) {
SawLifetimeDecl(content(l.name)).hash(self.st);
fn visit_lifetime_decl(&mut self, l: &LifetimeDef, _: E) {
SawLifetimeDecl(content(l.lifetime.name)).hash(self.st);
}

// We do recursively walk the bodies of functions/methods
Expand Down
6 changes: 6 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,12 @@ impl Clean<Lifetime> for ast::Lifetime {
}
}

impl Clean<Lifetime> for ast::LifetimeDef {
fn clean(&self) -> Lifetime {
Lifetime(token::get_name(self.lifetime.name).get().to_string())
}
}

impl Clean<Lifetime> for ty::RegionParameterDef {
fn clean(&self) -> Lifetime {
Lifetime(token::get_name(self.name).get().to_string())
Expand Down
12 changes: 9 additions & 3 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ pub struct Lifetime {
pub name: Name
}

#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct LifetimeDef {
pub lifetime: Lifetime,
pub bounds: Vec<Lifetime>
}

/// A "Path" is essentially Rust's notion of a name; for instance:
/// std::cmp::PartialEq . It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
Expand Down Expand Up @@ -231,7 +237,7 @@ pub struct TyParam {
/// of a function, enum, trait, etc.
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,
pub lifetimes: Vec<LifetimeDef>,
pub ty_params: OwnedSlice<TyParam>,
}

Expand Down Expand Up @@ -861,7 +867,7 @@ impl fmt::Show for Onceness {
/// Represents the type of a closure
#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct ClosureTy {
pub lifetimes: Vec<Lifetime>,
pub lifetimes: Vec<LifetimeDef>,
pub fn_style: FnStyle,
pub onceness: Onceness,
pub decl: P<FnDecl>,
Expand All @@ -876,7 +882,7 @@ pub struct ClosureTy {
pub struct BareFnTy {
pub fn_style: FnStyle,
pub abi: Abi,
pub lifetimes: Vec<Lifetime>,
pub lifetimes: Vec<LifetimeDef>,
pub decl: P<FnDecl>
}

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
self.operation.visit_id(type_parameter.id)
}
for lifetime in generics.lifetimes.iter() {
self.operation.visit_id(lifetime.id)
self.operation.visit_id(lifetime.lifetime.id)
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ pub trait AstBuilder {
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
fn lifetime_def(&self,
span: Span,
name: ast::Name,
bounds: Vec<ast::Lifetime>)
-> ast::LifetimeDef;

// statements
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt>;
Expand Down Expand Up @@ -456,6 +461,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
}

fn lifetime_def(&self,
span: Span,
name: ast::Name,
bounds: Vec<ast::Lifetime>)
-> ast::LifetimeDef {
ast::LifetimeDef {
lifetime: self.lifetime(span, name),
bounds: bounds
}
}

fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt> {
box(GC) respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
}
Expand Down
8 changes: 6 additions & 2 deletions src/libsyntax/ext/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ impl<'a> TraitDef<'a> {
let mut ty_params = ty_params.into_vec();

// Copy the lifetimes
lifetimes.extend(generics.lifetimes.iter().map(|l| *l));
lifetimes.extend(generics.lifetimes.iter().map(|l| (*l).clone()));

// Create the type parameters.
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
Expand Down Expand Up @@ -429,7 +429,11 @@ impl<'a> TraitDef<'a> {
cx.ty_ident(self.span, ty_param.ident)
});

let self_lifetimes = generics.lifetimes.clone();
let self_lifetimes: Vec<ast::Lifetime> =
generics.lifetimes
.iter()
.map(|ld| ld.lifetime)
.collect();

// Create the type of `self`.
let self_type = cx.ty_path(
Expand Down
15 changes: 10 additions & 5 deletions src/libsyntax/ext/deriving/generic/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ impl<'a> Ty<'a> {
let self_params = self_generics.ty_params.map(|ty_param| {
cx.ty_ident(span, ty_param.ident)
});
let lifetimes = self_generics.lifetimes.clone();
let lifetimes = self_generics.lifetimes.iter()
.map(|d| d.lifetime)
.collect();

cx.path_all(span, false, vec!(self_ty), lifetimes,
self_params.into_vec())
Expand All @@ -200,7 +202,7 @@ fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}

fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam> ) -> Generics {
Generics {
lifetimes: lifetimes,
ty_params: OwnedSlice::from_vec(ty_params)
Expand All @@ -210,7 +212,7 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) ->
/// Lifetimes and bounds on type parameters
#[deriving(Clone)]
pub struct LifetimeBounds<'a> {
pub lifetimes: Vec<&'a str>,
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
}

Expand All @@ -226,8 +228,11 @@ impl<'a> LifetimeBounds<'a> {
self_ty: Ident,
self_generics: &Generics)
-> Generics {
let lifetimes = self.lifetimes.iter().map(|lt| {
cx.lifetime(span, cx.ident_of(*lt).name)
let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
let bounds =
bounds.iter().map(
|b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
}).collect();
let ty_params = self.bounds.iter().map(|t| {
match t {
Expand Down
Loading

5 comments on commit fcab980

@bors
Copy link
Contributor

@bors bors commented on fcab980 Aug 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from pnkfelix
at nikomatsakis@fcab980

@bors
Copy link
Contributor

@bors bors commented on fcab980 Aug 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging nikomatsakis/rust/issue-5723-bootstrap-2 = fcab980 into auto

@bors
Copy link
Contributor

@bors bors commented on fcab980 Aug 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nikomatsakis/rust/issue-5723-bootstrap-2 = fcab980 merged ok, testing candidate = 8a02304

@bors
Copy link
Contributor

@bors bors commented on fcab980 Aug 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 8a02304

Please sign in to comment.