auto merge of #12807 : pnkfelix/rust/fsk-issue5121-fns-with-early-lifetime-params, r=pnkfelix
Fix issue #5121: Add proper support for early/late distinction for lifetime bindings. There are some little refactoring cleanups as separate commits; the real meat that has the actual fix is in the final commit. The original author of the work was @nikomatsakis; I have reviewed it, revised it slightly, refactored it into these separate commits, and done some rebasing work.
This commit is contained in:
commit
c2e5135358
@ -164,12 +164,12 @@ fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: token::str_to_ident("std"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: token::str_to_ident("prelude"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}),
|
||||
};
|
||||
|
@ -369,7 +369,7 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
|
||||
global: false,
|
||||
segments: ids.move_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}).collect()
|
||||
}
|
||||
@ -381,7 +381,7 @@ fn path_node_global(ids: Vec<ast::Ident> ) -> ast::Path {
|
||||
global: true,
|
||||
segments: ids.move_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}).collect()
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ fn item_region_param_defs(item_doc: ebml::Doc, cdata: Cmd)
|
||||
tag_region_param_def_def_id);
|
||||
let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
|
||||
let def_id = translate_def_id(cdata, def_id);
|
||||
v.push(ty::RegionParameterDef { ident: ident.name,
|
||||
v.push(ty::RegionParameterDef { name: ident.name,
|
||||
def_id: def_id });
|
||||
true
|
||||
});
|
||||
|
@ -184,7 +184,7 @@ fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
|
||||
ebml_w.start_tag(tag_region_param_def);
|
||||
|
||||
ebml_w.start_tag(tag_region_param_def_ident);
|
||||
encode_name(ebml_w, param.ident);
|
||||
encode_name(ebml_w, param.name);
|
||||
ebml_w.end_tag();
|
||||
|
||||
ebml_w.wr_tagged_str(tag_region_param_def_def_id,
|
||||
|
@ -176,11 +176,11 @@ fn enc_region(w: &mut MemWriter, cx: @ctxt, r: ty::Region) {
|
||||
enc_bound_region(w, cx, br);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
ty::ReEarlyBound(node_id, index, ident) => {
|
||||
ty::ReEarlyBound(node_id, index, name) => {
|
||||
mywrite!(w, "B[{}|{}|{}]",
|
||||
node_id,
|
||||
index,
|
||||
token::get_name(ident));
|
||||
token::get_name(name));
|
||||
}
|
||||
ty::ReFree(ref fr) => {
|
||||
mywrite!(w, "f[{}|", fr.scope_id);
|
||||
@ -208,10 +208,10 @@ fn enc_bound_region(w: &mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
|
||||
ty::BrAnon(idx) => {
|
||||
mywrite!(w, "a{}|", idx);
|
||||
}
|
||||
ty::BrNamed(d, s) => {
|
||||
ty::BrNamed(d, name) => {
|
||||
mywrite!(w, "[{}|{}]",
|
||||
(cx.ds)(d),
|
||||
token::get_name(s));
|
||||
token::get_name(name));
|
||||
}
|
||||
ty::BrFresh(id) => {
|
||||
mywrite!(w, "f{}|", id);
|
||||
|
@ -13,6 +13,7 @@
|
||||
//! which are available for use externally when compiled as a library.
|
||||
|
||||
use std::mem::replace;
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::lint;
|
||||
@ -855,7 +856,7 @@ fn visit_view_item(&mut self, a: &ast::ViewItem, _: ()) {
|
||||
debug!("privacy - list {}", pid.node.id);
|
||||
let seg = ast::PathSegment {
|
||||
identifier: pid.node.name,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
};
|
||||
let segs = vec!(seg);
|
||||
|
@ -19,9 +19,11 @@
|
||||
|
||||
use driver::session;
|
||||
use std::cell::RefCell;
|
||||
use std::vec_ng::Vec;
|
||||
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;
|
||||
@ -33,18 +35,31 @@
|
||||
// that it corresponds to
|
||||
pub type NamedRegionMap = NodeMap<ast::DefRegion>;
|
||||
|
||||
// Returns an instance of some type that implements std::fmt::Show
|
||||
fn lifetime_show(lt_name: &ast::Name) -> token::InternedString {
|
||||
token::get_name(*lt_name)
|
||||
}
|
||||
|
||||
struct LifetimeContext {
|
||||
sess: session::Session,
|
||||
named_region_map: @RefCell<NamedRegionMap>,
|
||||
}
|
||||
|
||||
enum ScopeChain<'a> {
|
||||
ItemScope(&'a OptVec<ast::Lifetime>),
|
||||
FnScope(ast::NodeId, &'a OptVec<ast::Lifetime>, &'a ScopeChain<'a>),
|
||||
BlockScope(ast::NodeId, &'a ScopeChain<'a>),
|
||||
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
|
||||
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
|
||||
EarlyScope(uint, &'a Vec<ast::Lifetime>, 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>),
|
||||
/// lifetimes introduced by items within a code block are scoped
|
||||
/// to that block.
|
||||
BlockScope(ast::NodeId, Scope<'a>),
|
||||
RootScope
|
||||
}
|
||||
|
||||
type Scope<'a> = &'a ScopeChain<'a>;
|
||||
|
||||
pub fn krate(sess: session::Session, krate: &ast::Crate)
|
||||
-> @RefCell<NamedRegionMap> {
|
||||
let mut ctxt = LifetimeContext {
|
||||
@ -56,10 +71,11 @@ pub fn krate(sess: session::Session, krate: &ast::Crate)
|
||||
ctxt.named_region_map
|
||||
}
|
||||
|
||||
impl<'a> Visitor<&'a ScopeChain<'a>> for LifetimeContext {
|
||||
impl<'a> Visitor<Scope<'a>> for LifetimeContext {
|
||||
fn visit_item(&mut self,
|
||||
item: &ast::Item,
|
||||
_: &'a ScopeChain<'a>) {
|
||||
_: Scope<'a>) {
|
||||
let root = RootScope;
|
||||
let scope = match item.node {
|
||||
ast::ItemFn(..) | // fn lifetimes get added in visit_fn below
|
||||
ast::ItemMod(..) |
|
||||
@ -74,7 +90,7 @@ fn visit_item(&mut self,
|
||||
ast::ItemImpl(ref generics, _, _, _) |
|
||||
ast::ItemTrait(ref generics, _, _) => {
|
||||
self.check_lifetime_names(&generics.lifetimes);
|
||||
ItemScope(&generics.lifetimes)
|
||||
EarlyScope(0, &generics.lifetimes, &root)
|
||||
}
|
||||
};
|
||||
debug!("entering scope {:?}", scope);
|
||||
@ -84,58 +100,50 @@ fn visit_item(&mut self,
|
||||
|
||||
fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
|
||||
b: &ast::Block, s: Span, n: ast::NodeId,
|
||||
scope: &'a ScopeChain<'a>) {
|
||||
scope: Scope<'a>) {
|
||||
match *fk {
|
||||
visit::FkItemFn(_, generics, _, _) |
|
||||
visit::FkMethod(_, generics, _) => {
|
||||
let scope1 = FnScope(n, &generics.lifetimes, scope);
|
||||
self.check_lifetime_names(&generics.lifetimes);
|
||||
debug!("pushing fn scope id={} due to item/method", n);
|
||||
visit::walk_fn(self, fk, fd, b, s, n, &scope1);
|
||||
debug!("popping fn scope id={} due to item/method", n);
|
||||
self.visit_fn_decl(
|
||||
n, generics, scope,
|
||||
|this, scope1| visit::walk_fn(this, fk, fd, b, s, n, scope1))
|
||||
}
|
||||
visit::FkFnBlock(..) => {
|
||||
visit::walk_fn(self, fk, fd, b, s, n, scope);
|
||||
visit::walk_fn(self, fk, fd, b, s, n, scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &ast::Ty,
|
||||
scope: &'a ScopeChain<'a>) {
|
||||
fn visit_ty(&mut self, ty: &ast::Ty, scope: Scope<'a>) {
|
||||
match ty.node {
|
||||
ast::TyClosure(closure) => {
|
||||
let scope1 = FnScope(ty.id, &closure.lifetimes, scope);
|
||||
self.check_lifetime_names(&closure.lifetimes);
|
||||
debug!("pushing fn scope id={} due to type", ty.id);
|
||||
visit::walk_ty(self, ty, &scope1);
|
||||
debug!("popping fn scope id={} due to type", ty.id);
|
||||
}
|
||||
ast::TyBareFn(bare_fn) => {
|
||||
let scope1 = FnScope(ty.id, &bare_fn.lifetimes, scope);
|
||||
self.check_lifetime_names(&bare_fn.lifetimes);
|
||||
debug!("pushing fn scope id={} due to type", ty.id);
|
||||
visit::walk_ty(self, ty, &scope1);
|
||||
debug!("popping fn scope id={} due to type", ty.id);
|
||||
}
|
||||
_ => {
|
||||
visit::walk_ty(self, ty, scope);
|
||||
}
|
||||
ast::TyClosure(c) => push_fn_scope(self, ty, scope, &c.lifetimes),
|
||||
ast::TyBareFn(c) => push_fn_scope(self, ty, scope, &c.lifetimes),
|
||||
_ => visit::walk_ty(self, ty, scope),
|
||||
}
|
||||
|
||||
fn push_fn_scope(this: &mut LifetimeContext,
|
||||
ty: &ast::Ty,
|
||||
scope: Scope,
|
||||
lifetimes: &Vec<ast::Lifetime>) {
|
||||
let scope1 = LateScope(ty.id, lifetimes, scope);
|
||||
this.check_lifetime_names(lifetimes);
|
||||
debug!("pushing fn scope id={} due to type", ty.id);
|
||||
visit::walk_ty(this, ty, &scope1);
|
||||
debug!("popping fn scope id={} due to type", ty.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty_method(&mut self,
|
||||
m: &ast::TypeMethod,
|
||||
scope: &'a ScopeChain<'a>) {
|
||||
let scope1 = FnScope(m.id, &m.generics.lifetimes, scope);
|
||||
self.check_lifetime_names(&m.generics.lifetimes);
|
||||
debug!("pushing fn scope id={} due to ty_method", m.id);
|
||||
visit::walk_ty_method(self, m, &scope1);
|
||||
debug!("popping fn scope id={} due to ty_method", m.id);
|
||||
scope: Scope<'a>) {
|
||||
self.visit_fn_decl(
|
||||
m.id, &m.generics, scope,
|
||||
|this, scope1| visit::walk_ty_method(this, m, scope1))
|
||||
}
|
||||
|
||||
fn visit_block(&mut self,
|
||||
b: &ast::Block,
|
||||
scope: &'a ScopeChain<'a>) {
|
||||
scope: Scope<'a>) {
|
||||
let scope1 = BlockScope(b.id, scope);
|
||||
debug!("pushing block scope {}", b.id);
|
||||
visit::walk_block(self, b, &scope1);
|
||||
@ -144,8 +152,8 @@ fn visit_block(&mut self,
|
||||
|
||||
fn visit_lifetime_ref(&mut self,
|
||||
lifetime_ref: &ast::Lifetime,
|
||||
scope: &'a ScopeChain<'a>) {
|
||||
if lifetime_ref.ident == special_idents::statik.name {
|
||||
scope: Scope<'a>) {
|
||||
if lifetime_ref.name == special_idents::statik.name {
|
||||
self.insert_lifetime(lifetime_ref, ast::DefStaticRegion);
|
||||
return;
|
||||
}
|
||||
@ -153,10 +161,85 @@ fn visit_lifetime_ref(&mut self,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ScopeChain<'a> {
|
||||
fn count_early_params(&self) -> uint {
|
||||
/*!
|
||||
* Counts the number of early-bound parameters that are in
|
||||
* scope. Used when checking methods: the early-bound
|
||||
* lifetime parameters declared on the method are assigned
|
||||
* indices that come after the indices from the type. Given
|
||||
* something like `impl<'a> Foo { ... fn bar<'b>(...) }`
|
||||
* then `'a` gets index 0 and `'b` gets index 1.
|
||||
*/
|
||||
|
||||
match *self {
|
||||
RootScope => 0,
|
||||
EarlyScope(base, lifetimes, _) => base + lifetimes.len(),
|
||||
LateScope(_, _, s) => s.count_early_params(),
|
||||
BlockScope(_, _) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LifetimeContext {
|
||||
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
|
||||
fn visit_fn_decl(&mut self,
|
||||
n: ast::NodeId,
|
||||
generics: &ast::Generics,
|
||||
scope: Scope,
|
||||
walk: |&mut LifetimeContext, Scope|) {
|
||||
/*!
|
||||
* Handles visiting fns and methods. These are a bit
|
||||
* complicated because we must distinguish early- vs late-bound
|
||||
* lifetime parameters. We do this by checking which lifetimes
|
||||
* appear within type bounds; those are early bound lifetimes,
|
||||
* and the rest are late bound.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* fn foo<'a,'b,'c,T:Trait<'b>>(...)
|
||||
*
|
||||
* Here `'a` and `'c` are late bound but `'b` is early
|
||||
* bound. Note that early- and late-bound lifetimes may be
|
||||
* interspersed together.
|
||||
*
|
||||
* If early bound lifetimes are present, we separate them into
|
||||
* their own list (and likewise for late bound). They will be
|
||||
* numbered sequentially, starting from the lowest index that
|
||||
* is already in scope (for a fn item, that will be 0, but for
|
||||
* a method it might not be). Late bound lifetimes are
|
||||
* resolved by name and associated with a binder id (`n`), so
|
||||
* the ordering is not important there.
|
||||
*/
|
||||
|
||||
self.check_lifetime_names(&generics.lifetimes);
|
||||
|
||||
let early_count = scope.count_early_params();
|
||||
let referenced_idents = free_lifetimes(&generics.ty_params);
|
||||
debug!("pushing fn scope id={} due to fn item/method\
|
||||
referenced_idents={:?} \
|
||||
early_count={}",
|
||||
n,
|
||||
referenced_idents.map(lifetime_show),
|
||||
early_count);
|
||||
if referenced_idents.is_empty() {
|
||||
let scope1 = LateScope(n, &generics.lifetimes, scope);
|
||||
walk(self, &scope1)
|
||||
} else {
|
||||
let (early, late) = generics.lifetimes.clone().partition(
|
||||
|l| referenced_idents.iter().any(|&i| i == l.name));
|
||||
|
||||
let scope1 = EarlyScope(early_count, &early, scope);
|
||||
let scope2 = LateScope(n, &late, &scope1);
|
||||
|
||||
walk(self, &scope2);
|
||||
}
|
||||
debug!("popping fn scope id={} due to fn item/method", n);
|
||||
}
|
||||
|
||||
fn resolve_lifetime_ref(&self,
|
||||
lifetime_ref: &ast::Lifetime,
|
||||
scope: &ScopeChain) {
|
||||
scope: Scope) {
|
||||
// Walk up the scope chain, tracking the number of fn scopes
|
||||
// that we pass through, until we find a lifetime with the
|
||||
// given name or we run out of scopes. If we encounter a code
|
||||
@ -175,23 +258,25 @@ fn resolve_lifetime_ref(&self,
|
||||
break;
|
||||
}
|
||||
|
||||
ItemScope(lifetimes) => {
|
||||
EarlyScope(base, lifetimes, s) => {
|
||||
match search_lifetimes(lifetimes, lifetime_ref) {
|
||||
Some((index, decl_id)) => {
|
||||
Some((offset, decl_id)) => {
|
||||
let index = base + offset;
|
||||
let def = ast::DefEarlyBoundRegion(index, decl_id);
|
||||
self.insert_lifetime(lifetime_ref, def);
|
||||
return;
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
depth += 1;
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FnScope(id, lifetimes, s) => {
|
||||
LateScope(binder_id, lifetimes, s) => {
|
||||
match search_lifetimes(lifetimes, lifetime_ref) {
|
||||
Some((_index, decl_id)) => {
|
||||
let def = ast::DefLateBoundRegion(id, depth, decl_id);
|
||||
let def = ast::DefLateBoundRegion(binder_id, depth, decl_id);
|
||||
self.insert_lifetime(lifetime_ref, def);
|
||||
return;
|
||||
}
|
||||
@ -211,7 +296,7 @@ fn resolve_lifetime_ref(&self,
|
||||
fn resolve_free_lifetime_ref(&self,
|
||||
scope_id: ast::NodeId,
|
||||
lifetime_ref: &ast::Lifetime,
|
||||
scope: &ScopeChain) {
|
||||
scope: Scope) {
|
||||
// Walk up the scope chain, tracking the outermost free scope,
|
||||
// until we encounter a scope that contains the named lifetime
|
||||
// or we run out of scopes.
|
||||
@ -229,12 +314,8 @@ fn resolve_free_lifetime_ref(&self,
|
||||
break;
|
||||
}
|
||||
|
||||
ItemScope(lifetimes) => {
|
||||
search_result = search_lifetimes(lifetimes, lifetime_ref);
|
||||
break;
|
||||
}
|
||||
|
||||
FnScope(_, lifetimes, s) => {
|
||||
EarlyScope(_, lifetimes, s) |
|
||||
LateScope(_, lifetimes, s) => {
|
||||
search_result = search_lifetimes(lifetimes, lifetime_ref);
|
||||
if search_result.is_some() {
|
||||
break;
|
||||
@ -262,32 +343,32 @@ fn unresolved_lifetime_ref(&self,
|
||||
self.sess.span_err(
|
||||
lifetime_ref.span,
|
||||
format!("use of undeclared lifetime name `'{}`",
|
||||
token::get_name(lifetime_ref.ident)));
|
||||
token::get_name(lifetime_ref.name)));
|
||||
}
|
||||
|
||||
fn check_lifetime_names(&self, lifetimes: &OptVec<ast::Lifetime>) {
|
||||
fn check_lifetime_names(&self, lifetimes: &Vec<ast::Lifetime>) {
|
||||
for i in range(0, lifetimes.len()) {
|
||||
let lifetime_i = lifetimes.get(i);
|
||||
|
||||
let special_idents = [special_idents::statik];
|
||||
for lifetime in lifetimes.iter() {
|
||||
if special_idents.iter().any(|&i| i.name == lifetime.ident) {
|
||||
if special_idents.iter().any(|&i| i.name == lifetime.name) {
|
||||
self.sess.span_err(
|
||||
lifetime.span,
|
||||
format!("illegal lifetime parameter name: `{}`",
|
||||
token::get_name(lifetime.ident)));
|
||||
token::get_name(lifetime.name)));
|
||||
}
|
||||
}
|
||||
|
||||
for j in range(i + 1, lifetimes.len()) {
|
||||
let lifetime_j = lifetimes.get(j);
|
||||
|
||||
if lifetime_i.ident == lifetime_j.ident {
|
||||
if lifetime_i.name == lifetime_j.name {
|
||||
self.sess.span_err(
|
||||
lifetime_j.span,
|
||||
format!("lifetime name `'{}` declared twice in \
|
||||
the same scope",
|
||||
token::get_name(lifetime_j.ident)));
|
||||
token::get_name(lifetime_j.name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,13 +392,54 @@ fn insert_lifetime(&self,
|
||||
}
|
||||
}
|
||||
|
||||
fn search_lifetimes(lifetimes: &OptVec<ast::Lifetime>,
|
||||
fn search_lifetimes(lifetimes: &Vec<ast::Lifetime>,
|
||||
lifetime_ref: &ast::Lifetime)
|
||||
-> Option<(uint, ast::NodeId)> {
|
||||
for (i, lifetime_decl) in lifetimes.iter().enumerate() {
|
||||
if lifetime_decl.ident == lifetime_ref.ident {
|
||||
if lifetime_decl.name == lifetime_ref.name {
|
||||
return Some((i, lifetime_decl.id));
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifetime> {
|
||||
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)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn free_lifetimes(ty_params: &OptVec<ast::TyParam>) -> OptVec<ast::Name> {
|
||||
/*!
|
||||
* Gathers up and returns the names of any lifetimes that appear
|
||||
* free in `ty_params`. Of course, right now, all lifetimes appear
|
||||
* free, since we don't currently have any binders in type parameter
|
||||
* declarations; just being forwards compatible with future extensions.
|
||||
*/
|
||||
|
||||
let mut collector = FreeLifetimeCollector { names: opt_vec::Empty };
|
||||
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>,
|
||||
}
|
||||
|
||||
impl Visitor<()> for FreeLifetimeCollector {
|
||||
fn visit_lifetime_ref(&mut self,
|
||||
lifetime_ref: &ast::Lifetime,
|
||||
_: ()) {
|
||||
self.names.push(lifetime_ref.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ fn subst_spanned(&self, _tcx: ty::ctxt,
|
||||
// bound in *fn types*. Region substitution of the bound
|
||||
// regions that appear in a function signature is done using
|
||||
// the specialized routine
|
||||
// `middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig()`.
|
||||
// `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
|
||||
match self {
|
||||
&ty::ReEarlyBound(_, i, _) => {
|
||||
match substs.regions {
|
||||
|
@ -540,7 +540,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
return FunctionWithoutDebugInfo;
|
||||
}
|
||||
|
||||
let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
|
||||
let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: opt_vec::Empty };
|
||||
|
||||
let fnitem = cx.tcx.map.get(fn_ast_id);
|
||||
|
||||
|
@ -996,7 +996,7 @@ pub struct TypeParameterDef {
|
||||
|
||||
#[deriving(Encodable, Decodable, Clone)]
|
||||
pub struct RegionParameterDef {
|
||||
ident: ast::Name,
|
||||
name: ast::Name,
|
||||
def_id: ast::DefId,
|
||||
}
|
||||
|
||||
@ -1008,6 +1008,7 @@ pub struct Generics {
|
||||
type_param_defs: Rc<Vec<TypeParameterDef> >,
|
||||
|
||||
/// List of region parameters declared on the item.
|
||||
/// For a fn or method, only includes *early-bound* lifetimes.
|
||||
region_param_defs: Rc<Vec<RegionParameterDef> >,
|
||||
}
|
||||
|
||||
@ -5077,6 +5078,7 @@ pub fn construct_parameter_environment(
|
||||
item_type_params: &[TypeParameterDef],
|
||||
method_type_params: &[TypeParameterDef],
|
||||
item_region_params: &[RegionParameterDef],
|
||||
method_region_params: &[RegionParameterDef],
|
||||
free_id: ast::NodeId)
|
||||
-> ParameterEnvironment
|
||||
{
|
||||
@ -5104,11 +5106,24 @@ pub fn construct_parameter_environment(
|
||||
});
|
||||
|
||||
// map bound 'a => free 'a
|
||||
let region_params = item_region_params.iter().
|
||||
map(|r| ty::ReFree(ty::FreeRegion {
|
||||
scope_id: free_id,
|
||||
bound_region: ty::BrNamed(r.def_id, r.ident)})).
|
||||
collect();
|
||||
let region_params = {
|
||||
fn push_region_params(accum: OptVec<ty::Region>,
|
||||
free_id: ast::NodeId,
|
||||
region_params: &[RegionParameterDef])
|
||||
-> OptVec<ty::Region> {
|
||||
let mut accum = accum;
|
||||
for r in region_params.iter() {
|
||||
accum.push(
|
||||
ty::ReFree(ty::FreeRegion {
|
||||
scope_id: free_id,
|
||||
bound_region: ty::BrNamed(r.def_id, r.name)}));
|
||||
}
|
||||
accum
|
||||
}
|
||||
|
||||
let t = push_region_params(opt_vec::Empty, free_id, item_region_params);
|
||||
push_region_params(t, free_id, method_region_params)
|
||||
};
|
||||
|
||||
let free_substs = substs {
|
||||
self_ty: self_ty,
|
||||
@ -5130,6 +5145,15 @@ pub fn construct_parameter_environment(
|
||||
}
|
||||
});
|
||||
|
||||
debug!("construct_parameter_environment: free_id={} \
|
||||
free_subst={} \
|
||||
self_param_bound={} \
|
||||
type_param_bound={}",
|
||||
free_id,
|
||||
free_substs.repr(tcx),
|
||||
self_bound_substd.repr(tcx),
|
||||
type_param_bounds_substd.repr(tcx));
|
||||
|
||||
ty::ParameterEnvironment {
|
||||
free_substs: free_substs,
|
||||
self_param_bound: self_bound_substd,
|
||||
|
@ -92,18 +92,18 @@ pub fn ast_region_to_region(tcx: ty::ctxt, lifetime: &ast::Lifetime)
|
||||
|
||||
Some(&ast::DefLateBoundRegion(binder_id, _, id)) => {
|
||||
ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id),
|
||||
lifetime.ident))
|
||||
lifetime.name))
|
||||
}
|
||||
|
||||
Some(&ast::DefEarlyBoundRegion(index, id)) => {
|
||||
ty::ReEarlyBound(id, index, lifetime.ident)
|
||||
ty::ReEarlyBound(id, index, lifetime.name)
|
||||
}
|
||||
|
||||
Some(&ast::DefFreeRegion(scope_id, id)) => {
|
||||
ty::ReFree(ty::FreeRegion {
|
||||
scope_id: scope_id,
|
||||
bound_region: ty::BrNamed(ast_util::local_def(id),
|
||||
lifetime.ident)
|
||||
lifetime.name)
|
||||
})
|
||||
}
|
||||
};
|
||||
@ -186,9 +186,9 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
|
||||
}
|
||||
|
||||
match anon_regions {
|
||||
Ok(v) => opt_vec::from(v.move_iter().collect()),
|
||||
Err(()) => opt_vec::from(Vec::from_fn(expected_num_region_params,
|
||||
|_| ty::ReStatic)) // hokey
|
||||
Ok(v) => v.move_iter().collect(),
|
||||
Err(()) => Vec::from_fn(expected_num_region_params,
|
||||
|_| ty::ReStatic) // hokey
|
||||
}
|
||||
};
|
||||
|
||||
@ -231,7 +231,7 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
|
||||
.collect();
|
||||
|
||||
let mut substs = substs {
|
||||
regions: ty::NonerasedRegions(regions),
|
||||
regions: ty::NonerasedRegions(opt_vec::from(regions)),
|
||||
self_ty: self_ty,
|
||||
tps: tps
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
|
||||
use middle::typeck::{MethodOrigin, MethodParam};
|
||||
use middle::typeck::{MethodStatic, MethodObject};
|
||||
use middle::typeck::{param_numbered, param_self, param_index};
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
@ -428,7 +428,7 @@ fn push_inherent_candidates_from_object(&self,
|
||||
substs: &ty::substs) {
|
||||
debug!("push_inherent_candidates_from_object(did={}, substs={})",
|
||||
self.did_to_str(did),
|
||||
substs_to_str(self.tcx(), substs));
|
||||
substs.repr(self.tcx()));
|
||||
let _indenter = indenter();
|
||||
|
||||
// It is illegal to invoke a method on a trait instance that
|
||||
@ -554,7 +554,8 @@ fn push_inherent_candidates_from_bounds_inner(&self,
|
||||
|
||||
match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
|
||||
Some(cand) => {
|
||||
debug!("pushing inherent candidate for param: {:?}", cand);
|
||||
debug!("pushing inherent candidate for param: {}",
|
||||
cand.repr(self.tcx()));
|
||||
self.inherent_candidates.borrow_mut().get().push(cand);
|
||||
}
|
||||
None => {}
|
||||
@ -938,8 +939,9 @@ fn merge_candidates(&self, candidates: &[Candidate]) -> Vec<Candidate> {
|
||||
let mut j = i + 1;
|
||||
while j < candidates.len() {
|
||||
let candidate_b = &candidates[j];
|
||||
debug!("attempting to merge {:?} and {:?}",
|
||||
candidate_a, candidate_b);
|
||||
debug!("attempting to merge {} and {}",
|
||||
candidate_a.repr(self.tcx()),
|
||||
candidate_b.repr(self.tcx()));
|
||||
let candidates_same = match (&candidate_a.origin,
|
||||
&candidate_b.origin) {
|
||||
(&MethodParam(ref p1), &MethodParam(ref p2)) => {
|
||||
@ -984,9 +986,10 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!("confirm_candidate(expr={}, candidate={})",
|
||||
debug!("confirm_candidate(expr={}, rcvr_ty={}, candidate={})",
|
||||
self.expr.repr(tcx),
|
||||
self.cand_to_str(candidate));
|
||||
self.ty_to_str(rcvr_ty),
|
||||
candidate.repr(self.tcx()));
|
||||
|
||||
self.enforce_object_limitations(candidate);
|
||||
self.enforce_drop_trait_limitations(candidate);
|
||||
@ -994,9 +997,9 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||
// static methods should never have gotten this far:
|
||||
assert!(candidate.method_ty.explicit_self != SelfStatic);
|
||||
|
||||
// Determine the values for the type parameters of the method.
|
||||
// Determine the values for the generic parameters of the method.
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
// type variables.
|
||||
// variables.
|
||||
let num_supplied_tps = self.supplied_tps.len();
|
||||
let num_method_tps = candidate.method_ty.generics.type_param_defs().len();
|
||||
let m_substs = {
|
||||
@ -1018,12 +1021,26 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||
}
|
||||
};
|
||||
|
||||
// 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(),
|
||||
ErasedRegions => tcx.sess.span_bug(self.expr.span, "ErasedRegions")
|
||||
};
|
||||
let m_regions =
|
||||
self.fcx.infcx().region_vars_for_defs(
|
||||
self.expr.span,
|
||||
candidate.method_ty.generics.region_param_defs.borrow().as_slice());
|
||||
for &r in m_regions.iter() {
|
||||
all_regions.push(r);
|
||||
}
|
||||
|
||||
// Construct the full set of type parameters for the method,
|
||||
// which is equal to the class tps + the method tps.
|
||||
let all_substs = substs {
|
||||
tps: vec_ng::append(candidate.rcvr_substs.tps.clone(),
|
||||
m_substs.as_slice()),
|
||||
regions: candidate.rcvr_substs.regions.clone(),
|
||||
regions: NonerasedRegions(all_regions),
|
||||
self_ty: candidate.rcvr_substs.self_ty,
|
||||
};
|
||||
|
||||
@ -1057,10 +1074,10 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||
|
||||
// Replace any bound regions that appear in the function
|
||||
// signature with region variables
|
||||
let (_, fn_sig) = replace_bound_regions_in_fn_sig( tcx, &fn_sig, |br| {
|
||||
self.fcx.infcx().next_region_var(
|
||||
infer::BoundRegionInFnCall(self.expr.span, br))
|
||||
});
|
||||
let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(
|
||||
tcx, &fn_sig,
|
||||
|br| self.fcx.infcx().next_region_var(
|
||||
infer::LateBoundRegion(self.expr.span, br)));
|
||||
let transformed_self_ty = *fn_sig.inputs.get(0);
|
||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||
sig: fn_sig,
|
||||
@ -1245,7 +1262,7 @@ fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
|
||||
// candidate method's `self_ty`.
|
||||
fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
|
||||
debug!("is_relevant(rcvr_ty={}, candidate={})",
|
||||
self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
|
||||
self.ty_to_str(rcvr_ty), candidate.repr(self.tcx()));
|
||||
|
||||
return match candidate.method_ty.explicit_self {
|
||||
SelfStatic => {
|
||||
@ -1385,13 +1402,6 @@ fn ty_to_str(&self, t: ty::t) -> ~str {
|
||||
self.fcx.infcx().ty_to_str(t)
|
||||
}
|
||||
|
||||
fn cand_to_str(&self, cand: &Candidate) -> ~str {
|
||||
format!("Candidate(rcvr_ty={}, rcvr_substs={}, origin={:?})",
|
||||
cand.rcvr_match_condition.repr(self.tcx()),
|
||||
ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
|
||||
cand.origin)
|
||||
}
|
||||
|
||||
fn did_to_str(&self, did: DefId) -> ~str {
|
||||
ty::item_path_str(self.tcx(), did)
|
||||
}
|
||||
@ -1401,6 +1411,15 @@ fn bug(&self, s: ~str) -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Candidate {
|
||||
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
format!("Candidate(rcvr_ty={}, rcvr_substs={}, origin={:?})",
|
||||
self.rcvr_match_condition.repr(tcx),
|
||||
self.rcvr_substs.repr(tcx),
|
||||
self.origin)
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for RcvrMatchCondition {
|
||||
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
match *self {
|
||||
|
@ -97,7 +97,7 @@
|
||||
use middle::typeck::check::method::{AutoderefReceiverFlag};
|
||||
use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
|
||||
use middle::typeck::check::method::{DontAutoderefReceiver};
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::relate_free_regions;
|
||||
use middle::typeck::check::vtable::{LocationInfo, VtableContext};
|
||||
use middle::typeck::CrateCtxt;
|
||||
@ -439,7 +439,7 @@ fn check_fn(ccx: @CrateCtxt,
|
||||
|
||||
// First, we have to replace any bound regions in the fn type with free ones.
|
||||
// The free region references will be bound the node_id of the body block.
|
||||
let (_, fn_sig) = replace_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
|
||||
let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
|
||||
ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
|
||||
});
|
||||
|
||||
@ -563,13 +563,13 @@ pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) {
|
||||
ast::ItemFn(decl, _, _, _, body) => {
|
||||
let fn_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
|
||||
|
||||
// FIXME(#5121) -- won't work for lifetimes that appear in type bounds
|
||||
let param_env = ty::construct_parameter_environment(
|
||||
ccx.tcx,
|
||||
None,
|
||||
fn_tpt.generics.type_param_defs(),
|
||||
[],
|
||||
[],
|
||||
fn_tpt.generics.region_param_defs.borrow().as_slice(),
|
||||
body.id);
|
||||
|
||||
check_bare_fn(ccx, decl, body, it.id, fn_tpt.ty, param_env);
|
||||
@ -679,6 +679,7 @@ fn check_method_body(ccx: @CrateCtxt,
|
||||
item_generics.type_param_defs(),
|
||||
method_generics.type_param_defs(),
|
||||
item_generics.region_param_defs(),
|
||||
method_generics.region_param_defs(),
|
||||
method.body.id);
|
||||
|
||||
// Compute the fty from point of view of inside fn
|
||||
@ -901,7 +902,7 @@ trait = ty::item_path_str(tcx, trait_m.def_id),
|
||||
impl_generics.region_param_defs().iter().
|
||||
map(|l| ty::ReFree(ty::FreeRegion {
|
||||
scope_id: impl_m_body_id,
|
||||
bound_region: ty::BrNamed(l.def_id, l.ident)})).
|
||||
bound_region: ty::BrNamed(l.def_id, l.name)})).
|
||||
collect();
|
||||
let dummy_substs = ty::substs {
|
||||
tps: vec_ng::append(dummy_impl_tps, dummy_method_tps.as_slice()),
|
||||
@ -1439,22 +1440,17 @@ pub fn impl_self_ty(vcx: &VtableContext,
|
||||
-> ty_param_substs_and_ty {
|
||||
let tcx = vcx.tcx();
|
||||
|
||||
let (n_tps, n_rps, raw_ty) = {
|
||||
let ity = ty::lookup_item_type(tcx, did);
|
||||
let ity = ty::lookup_item_type(tcx, did);
|
||||
let (n_tps, rps, raw_ty) =
|
||||
(ity.generics.type_param_defs().len(),
|
||||
ity.generics.region_param_defs().len(),
|
||||
ity.ty)
|
||||
};
|
||||
ity.generics.region_param_defs(),
|
||||
ity.ty);
|
||||
|
||||
let rps =
|
||||
vcx.infcx.next_region_vars(
|
||||
infer::BoundRegionInTypeOrImpl(location_info.span),
|
||||
n_rps);
|
||||
let rps = vcx.infcx.region_vars_for_defs(location_info.span, rps);
|
||||
let tps = vcx.infcx.next_ty_vars(n_tps);
|
||||
|
||||
let substs = substs {
|
||||
regions: ty::NonerasedRegions(opt_vec::from(rps.move_iter()
|
||||
.collect())),
|
||||
regions: ty::NonerasedRegions(rps),
|
||||
self_ty: None,
|
||||
tps: tps,
|
||||
};
|
||||
@ -1888,9 +1884,8 @@ fn check_call(fcx: @FnCtxt,
|
||||
|
||||
// Replace any bound regions that appear in the function
|
||||
// signature with region variables
|
||||
let (_, fn_sig) = replace_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
|
||||
fcx.infcx()
|
||||
.next_region_var(infer::BoundRegionInFnCall(call_expr.span, br))
|
||||
let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
|
||||
fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
|
||||
});
|
||||
|
||||
// Call the generic checker.
|
||||
@ -2214,7 +2209,7 @@ fn check_expr_fn(fcx: @FnCtxt,
|
||||
match expected_sty {
|
||||
Some(ty::ty_closure(ref cenv)) => {
|
||||
let (_, sig) =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
replace_late_bound_regions_in_fn_sig(
|
||||
tcx, &cenv.sig,
|
||||
|_| fcx.inh.infcx.fresh_bound_region(expr.id));
|
||||
(Some(sig), cenv.purity, cenv.sigil,
|
||||
@ -2462,16 +2457,14 @@ fn check_struct_constructor(fcx: @FnCtxt,
|
||||
// determine whether the class is region-parameterized.
|
||||
let item_type = ty::lookup_item_type(tcx, class_id);
|
||||
let type_parameter_count = item_type.generics.type_param_defs().len();
|
||||
let region_parameter_count = item_type.generics.region_param_defs().len();
|
||||
let region_param_defs = item_type.generics.region_param_defs();
|
||||
let raw_type = item_type.ty;
|
||||
|
||||
// Generate the struct type.
|
||||
let regions = fcx.infcx().next_region_vars(
|
||||
infer::BoundRegionInTypeOrImpl(span),
|
||||
region_parameter_count).move_iter().collect();
|
||||
let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
|
||||
let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
|
||||
let substitutions = substs {
|
||||
regions: ty::NonerasedRegions(opt_vec::from(regions)),
|
||||
regions: ty::NonerasedRegions(regions),
|
||||
self_ty: None,
|
||||
tps: type_parameters
|
||||
};
|
||||
@ -2520,16 +2513,14 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
|
||||
// determine whether the enum is region-parameterized.
|
||||
let item_type = ty::lookup_item_type(tcx, enum_id);
|
||||
let type_parameter_count = item_type.generics.type_param_defs().len();
|
||||
let region_parameter_count = item_type.generics.region_param_defs().len();
|
||||
let region_param_defs = item_type.generics.region_param_defs();
|
||||
let raw_type = item_type.ty;
|
||||
|
||||
// Generate the enum type.
|
||||
let regions = fcx.infcx().next_region_vars(
|
||||
infer::BoundRegionInTypeOrImpl(span),
|
||||
region_parameter_count).move_iter().collect();
|
||||
let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
|
||||
let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
|
||||
let substitutions = substs {
|
||||
regions: ty::NonerasedRegions(opt_vec::from(regions)),
|
||||
regions: ty::NonerasedRegions(regions),
|
||||
self_ty: None,
|
||||
tps: type_parameters
|
||||
};
|
||||
@ -3727,8 +3718,8 @@ pub fn instantiate_path(fcx: @FnCtxt,
|
||||
let num_expected_regions = tpt.generics.region_param_defs().len();
|
||||
let num_supplied_regions = pth.segments.last().unwrap().lifetimes.len();
|
||||
let regions = if num_expected_regions == num_supplied_regions {
|
||||
pth.segments.last().unwrap().lifetimes.map(
|
||||
|l| ast_region_to_region(fcx.tcx(), l))
|
||||
opt_vec::from(pth.segments.last().unwrap().lifetimes.map(
|
||||
|l| ast_region_to_region(fcx.tcx(), l)))
|
||||
} else {
|
||||
if num_supplied_regions != 0 {
|
||||
fcx.ccx.tcx.sess.span_err(
|
||||
@ -3741,9 +3732,7 @@ pub fn instantiate_path(fcx: @FnCtxt,
|
||||
nsupplied = num_supplied_regions));
|
||||
}
|
||||
|
||||
opt_vec::from(fcx.infcx().next_region_vars(
|
||||
infer::BoundRegionInTypeOrImpl(span),
|
||||
num_expected_regions).move_iter().collect())
|
||||
fcx.infcx().region_vars_for_defs(span, tpt.generics.region_param_defs.borrow().as_slice())
|
||||
};
|
||||
let regions = ty::NonerasedRegions(regions);
|
||||
|
||||
|
@ -21,12 +21,12 @@
|
||||
|
||||
// Helper functions related to manipulating region types.
|
||||
|
||||
pub fn replace_bound_regions_in_fn_sig(
|
||||
pub fn replace_late_bound_regions_in_fn_sig(
|
||||
tcx: ty::ctxt,
|
||||
fn_sig: &ty::FnSig,
|
||||
mapf: |ty::BoundRegion| -> ty::Region)
|
||||
-> (HashMap<ty::BoundRegion,ty::Region>, ty::FnSig) {
|
||||
debug!("replace_bound_regions_in_fn_sig({})", fn_sig.repr(tcx));
|
||||
debug!("replace_late_bound_regions_in_fn_sig({})", fn_sig.repr(tcx));
|
||||
|
||||
let mut map = HashMap::new();
|
||||
let fn_sig = {
|
||||
|
@ -777,6 +777,7 @@ pub fn resolve_impl(tcx: ty::ctxt,
|
||||
impl_generics.type_param_defs(),
|
||||
[],
|
||||
impl_generics.region_param_defs(),
|
||||
[],
|
||||
impl_item.id);
|
||||
|
||||
let impl_trait_ref = @impl_trait_ref.subst(tcx, ¶m_env.free_substs);
|
||||
@ -832,7 +833,7 @@ pub fn trans_resolve_method(tcx: ty::ctxt, id: ast::NodeId,
|
||||
if has_trait_bounds(type_param_defs.as_slice()) {
|
||||
let vcx = VtableContext {
|
||||
infcx: &infer::new_infer_ctxt(tcx),
|
||||
param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], id)
|
||||
param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], [], id)
|
||||
};
|
||||
let loc_info = LocationInfo {
|
||||
id: id,
|
||||
|
@ -42,7 +42,6 @@
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util::{def_id_of_def, local_def};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::opt_vec;
|
||||
use syntax::parse::token;
|
||||
use syntax::visit;
|
||||
|
||||
@ -516,18 +515,17 @@ fn polytypes_unify(&self,
|
||||
// type variables. Returns the monotype and the type variables created.
|
||||
fn universally_quantify_polytype(&self, polytype: ty_param_bounds_and_ty)
|
||||
-> UniversalQuantificationResult {
|
||||
let region_parameter_count = polytype.generics.region_param_defs().len();
|
||||
let region_parameters =
|
||||
self.inference_context.next_region_vars(
|
||||
infer::BoundRegionInCoherence,
|
||||
region_parameter_count);
|
||||
polytype.generics.region_param_defs().iter()
|
||||
.map(|d| self.inference_context.next_region_var(
|
||||
infer::BoundRegionInCoherence(d.name)))
|
||||
.collect();
|
||||
|
||||
let bounds_count = polytype.generics.type_param_defs().len();
|
||||
let type_parameters = self.inference_context.next_ty_vars(bounds_count);
|
||||
|
||||
let substitutions = substs {
|
||||
regions: ty::NonerasedRegions(opt_vec::from(
|
||||
region_parameters.move_iter().collect())),
|
||||
regions: ty::NonerasedRegions(region_parameters),
|
||||
self_ty: None,
|
||||
tps: type_parameters
|
||||
};
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
|
||||
use middle::ty::{ty_param_bounds_and_ty};
|
||||
use middle::ty;
|
||||
@ -45,7 +46,6 @@
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::vec;
|
||||
use std::vec_ng::Vec;
|
||||
use std::vec_ng;
|
||||
use syntax::abi::AbiSet;
|
||||
@ -160,7 +160,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
|
||||
ast::StructVariantKind(struct_def) => {
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
generics: ty_generics(ccx, generics, 0),
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
ty: enum_ty
|
||||
};
|
||||
|
||||
@ -173,7 +173,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
};
|
||||
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
generics: ty_generics(ccx, generics, 0),
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
ty: result_ty
|
||||
};
|
||||
|
||||
@ -192,7 +192,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
|
||||
ast_map::NodeItem(item) => {
|
||||
match item.node {
|
||||
ast::ItemTrait(ref generics, _, ref ms) => {
|
||||
let trait_ty_generics = ty_generics(ccx, generics, 0);
|
||||
let trait_ty_generics = ty_generics_for_type(ccx, generics);
|
||||
|
||||
// For each method, construct a suitable ty::Method and
|
||||
// store it into the `tcx.methods` table:
|
||||
@ -293,7 +293,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
||||
|
||||
// Represents [A',B',C']
|
||||
let num_trait_bounds = trait_ty_generics.type_param_defs().len();
|
||||
let non_shifted_trait_tps = vec::from_fn(num_trait_bounds, |i| {
|
||||
let non_shifted_trait_tps = Vec::from_fn(num_trait_bounds, |i| {
|
||||
ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
|
||||
});
|
||||
|
||||
@ -303,7 +303,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
||||
|
||||
// Represents [E',F',G']
|
||||
let num_method_bounds = m.generics.type_param_defs().len();
|
||||
let shifted_method_tps = vec::from_fn(num_method_bounds, |i| {
|
||||
let shifted_method_tps = Vec::from_fn(num_method_bounds, |i| {
|
||||
ty::mk_param(tcx, i + num_trait_bounds + 1,
|
||||
m.generics.type_param_defs()[i].def_id)
|
||||
});
|
||||
@ -315,7 +315,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
||||
let rps_from_trait =
|
||||
trait_ty_generics.region_param_defs().iter().
|
||||
enumerate().
|
||||
map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.ident)).
|
||||
map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.name)).
|
||||
collect();
|
||||
|
||||
// build up the substitution from
|
||||
@ -326,8 +326,8 @@ fn make_static_method_ty(ccx: &CrateCtxt,
|
||||
let substs = substs {
|
||||
regions: ty::NonerasedRegions(rps_from_trait),
|
||||
self_ty: Some(self_param),
|
||||
tps: vec_ng::append(Vec::from_slice(non_shifted_trait_tps),
|
||||
shifted_method_tps)
|
||||
tps: vec_ng::append(non_shifted_trait_tps,
|
||||
shifted_method_tps.as_slice())
|
||||
};
|
||||
|
||||
// create the type of `foo`, applying the substitution above
|
||||
@ -394,10 +394,11 @@ fn ty_method_of_trait_method(this: &CrateCtxt,
|
||||
let fty = astconv::ty_of_method(this, *m_id, *m_purity, trait_self_ty,
|
||||
*m_explicit_self, m_decl);
|
||||
let num_trait_type_params = trait_generics.type_param_defs().len();
|
||||
let ty_generics = ty_generics_for_fn_or_method(this, m_generics,
|
||||
num_trait_type_params);
|
||||
ty::Method::new(
|
||||
*m_ident,
|
||||
// FIXME(#5121) -- distinguish early vs late lifetime params
|
||||
ty_generics(this, m_generics, num_trait_type_params),
|
||||
ty_generics,
|
||||
fty,
|
||||
m_explicit_self.node,
|
||||
// assume public, because this is only invoked on trait methods
|
||||
@ -477,7 +478,8 @@ fn convert_methods(ccx: &CrateCtxt,
|
||||
let tcx = ccx.tcx;
|
||||
for m in ms.iter() {
|
||||
let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
|
||||
let m_ty_generics = ty_generics(ccx, &m.generics, num_rcvr_ty_params);
|
||||
let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
|
||||
num_rcvr_ty_params);
|
||||
let mty = @ty_of_method(ccx,
|
||||
container,
|
||||
*m,
|
||||
@ -503,7 +505,9 @@ fn convert_methods(ccx: &CrateCtxt,
|
||||
Vec::from_slice(
|
||||
rcvr_ty_generics.type_param_defs()),
|
||||
m_ty_generics.type_param_defs())),
|
||||
region_param_defs: rcvr_ty_generics.region_param_defs.clone(),
|
||||
region_param_defs: Rc::new(vec_ng::append(
|
||||
Vec::from_slice(rcvr_ty_generics.region_param_defs()),
|
||||
m_ty_generics.region_param_defs())),
|
||||
},
|
||||
ty: fty
|
||||
});
|
||||
@ -533,10 +537,11 @@ fn ty_of_method(ccx: &CrateCtxt,
|
||||
let method_vis = m.vis.inherit_from(rcvr_visibility);
|
||||
|
||||
let num_rcvr_type_params = rcvr_generics.ty_params.len();
|
||||
let m_ty_generics =
|
||||
ty_generics_for_fn_or_method(ccx, &m.generics, num_rcvr_type_params);
|
||||
ty::Method::new(
|
||||
m.ident,
|
||||
// FIXME(#5121) -- distinguish early vs late lifetime params
|
||||
ty_generics(ccx, &m.generics, num_rcvr_type_params),
|
||||
m_ty_generics,
|
||||
fty,
|
||||
m.explicit_self.node,
|
||||
method_vis,
|
||||
@ -588,7 +593,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
generics);
|
||||
},
|
||||
ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
|
||||
let i_ty_generics = ty_generics(ccx, generics, 0);
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let selfty = ccx.to_ty(&ExplicitRscope, selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
|
||||
@ -596,7 +601,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
let mut tcache = tcx.tcache.borrow_mut();
|
||||
tcache.get().insert(local_def(it.id),
|
||||
ty_param_bounds_and_ty {
|
||||
generics: i_ty_generics.clone(),
|
||||
generics: ty_generics.clone(),
|
||||
ty: selfty});
|
||||
}
|
||||
|
||||
@ -615,7 +620,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
ImplContainer(local_def(it.id)),
|
||||
ms.as_slice(),
|
||||
selfty,
|
||||
&i_ty_generics,
|
||||
&ty_generics,
|
||||
generics,
|
||||
parent_visibility);
|
||||
|
||||
@ -813,7 +818,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
|
||||
match it.node {
|
||||
ast::ItemTrait(ref generics, ref supertraits, _) => {
|
||||
let self_ty = ty::mk_self(tcx, def_id);
|
||||
let ty_generics = ty_generics(ccx, generics, 0);
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
|
||||
let bounds = ensure_supertraits(ccx,
|
||||
it.id,
|
||||
@ -857,17 +862,14 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
return tpt;
|
||||
}
|
||||
ast::ItemFn(decl, purity, abi, ref generics, _) => {
|
||||
let ty_generics = ty_generics(ccx, generics, 0);
|
||||
let ty_generics = ty_generics_for_fn_or_method(ccx, generics, 0);
|
||||
let tofd = astconv::ty_of_bare_fn(ccx,
|
||||
it.id,
|
||||
purity,
|
||||
abi,
|
||||
decl);
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
generics: ty::Generics {
|
||||
type_param_defs: ty_generics.type_param_defs.clone(),
|
||||
region_param_defs: Rc::new(Vec::new()),
|
||||
},
|
||||
generics: ty_generics,
|
||||
ty: ty::mk_bare_fn(ccx.tcx, tofd)
|
||||
};
|
||||
debug!("type of {} (id {}) is {}",
|
||||
@ -891,7 +893,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
let tpt = {
|
||||
let ty = ccx.to_ty(&ExplicitRscope, t);
|
||||
ty_param_bounds_and_ty {
|
||||
generics: ty_generics(ccx, generics, 0),
|
||||
generics: ty_generics_for_type(ccx, generics),
|
||||
ty: ty
|
||||
}
|
||||
};
|
||||
@ -902,7 +904,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
}
|
||||
ast::ItemEnum(_, ref generics) => {
|
||||
// Create a new generic polytype.
|
||||
let ty_generics = ty_generics(ccx, generics, 0);
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let substs = mk_item_substs(ccx, &ty_generics, None);
|
||||
let t = ty::mk_enum(tcx, local_def(it.id), substs);
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
@ -920,7 +922,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
|
||||
format!("invoked ty_of_item on trait"));
|
||||
}
|
||||
ast::ItemStruct(_, ref generics) => {
|
||||
let ty_generics = ty_generics(ccx, generics, 0);
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let substs = mk_item_substs(ccx, &ty_generics, None);
|
||||
let t = ty::mk_struct(tcx, local_def(it.id), substs);
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
@ -961,42 +963,51 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_generics_for_type(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics)
|
||||
-> ty::Generics {
|
||||
ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
|
||||
}
|
||||
|
||||
pub fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics,
|
||||
base_index: uint)
|
||||
-> ty::Generics {
|
||||
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
|
||||
ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
|
||||
}
|
||||
|
||||
pub fn ty_generics(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics,
|
||||
lifetimes: &Vec<ast::Lifetime>,
|
||||
ty_params: &OptVec<ast::TyParam>,
|
||||
base_index: uint) -> ty::Generics {
|
||||
return ty::Generics {
|
||||
region_param_defs: Rc::new(generics.lifetimes.iter().map(|l| {
|
||||
ty::RegionParameterDef { ident: l.ident,
|
||||
region_param_defs: Rc::new(lifetimes.iter().map(|l| {
|
||||
ty::RegionParameterDef { name: l.name,
|
||||
def_id: local_def(l.id) }
|
||||
}).collect()),
|
||||
type_param_defs: Rc::new(generics.ty_params.mapi_to_vec(|offset, param| {
|
||||
type_param_defs: Rc::new(ty_params.mapi_to_vec(|offset, param| {
|
||||
let existing_def_opt = {
|
||||
let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
|
||||
ty_param_defs.get().find(¶m.id).map(|def| *def)
|
||||
ty_param_defs.get().find(¶m.id).map(|&def| def)
|
||||
};
|
||||
match existing_def_opt {
|
||||
Some(def) => def,
|
||||
None => {
|
||||
let param_ty = ty::param_ty {idx: base_index + offset,
|
||||
def_id: local_def(param.id)};
|
||||
let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
|
||||
let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
|
||||
let def = ty::TypeParameterDef {
|
||||
ident: param.ident,
|
||||
def_id: local_def(param.id),
|
||||
bounds: bounds,
|
||||
default: default
|
||||
};
|
||||
debug!("def for param: {}", def.repr(ccx.tcx));
|
||||
|
||||
let mut ty_param_defs = ccx.tcx
|
||||
.ty_param_defs
|
||||
.borrow_mut();
|
||||
ty_param_defs.get().insert(param.id, def);
|
||||
def
|
||||
}
|
||||
}
|
||||
}).move_iter().collect())
|
||||
existing_def_opt.unwrap_or_else(|| {
|
||||
let param_ty = ty::param_ty {idx: base_index + offset,
|
||||
def_id: local_def(param.id)};
|
||||
let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
|
||||
let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
|
||||
let def = ty::TypeParameterDef {
|
||||
ident: param.ident,
|
||||
def_id: local_def(param.id),
|
||||
bounds: bounds,
|
||||
default: default
|
||||
};
|
||||
debug!("def for param: {}", def.repr(ccx.tcx));
|
||||
let mut ty_param_defs = ccx.tcx.ty_param_defs.borrow_mut();
|
||||
ty_param_defs.get().insert(param.id, def);
|
||||
def
|
||||
})
|
||||
}).move_iter().collect()),
|
||||
};
|
||||
|
||||
fn compute_bounds(
|
||||
@ -1056,7 +1067,8 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
let ty_generics = ty_generics(ccx, ast_generics, 0);
|
||||
let ty_generics_for_fn_or_method =
|
||||
ty_generics_for_fn_or_method(ccx, ast_generics, 0);
|
||||
let rb = BindingRscope::new(def_id.node);
|
||||
let input_tys = decl.inputs
|
||||
.iter()
|
||||
@ -1076,7 +1088,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||
variadic: decl.variadic}
|
||||
});
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
generics: ty_generics,
|
||||
generics: ty_generics_for_fn_or_method,
|
||||
ty: t_fn
|
||||
};
|
||||
|
||||
@ -1095,7 +1107,7 @@ pub fn mk_item_substs(ccx: &CrateCtxt,
|
||||
|
||||
let regions: OptVec<ty::Region> =
|
||||
ty_generics.region_param_defs().iter().enumerate().map(
|
||||
|(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.ident)).collect();
|
||||
|(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.name)).collect();
|
||||
|
||||
substs {regions: ty::NonerasedRegions(regions),
|
||||
self_ty: self_ty,
|
||||
|
@ -72,6 +72,7 @@
|
||||
use middle::typeck::infer::region_inference::SubSupConflict;
|
||||
use middle::typeck::infer::region_inference::SupSupConflict;
|
||||
use syntax::opt_vec::OptVec;
|
||||
use syntax::parse::token;
|
||||
use util::ppaux::UserString;
|
||||
use util::ppaux::bound_region_to_str;
|
||||
use util::ppaux::note_and_explain_region;
|
||||
@ -479,19 +480,21 @@ fn report_inference_failure(&self,
|
||||
infer::AddrOfSlice(_) => ~" for slice expression",
|
||||
infer::Autoref(_) => ~" for autoref",
|
||||
infer::Coercion(_) => ~" for automatic coercion",
|
||||
infer::BoundRegionInFnCall(_, br) => {
|
||||
infer::LateBoundRegion(_, br) => {
|
||||
format!(" for {}in function call",
|
||||
bound_region_to_str(self.tcx, "region ", true, br))
|
||||
bound_region_to_str(self.tcx, "lifetime parameter ", true, br))
|
||||
}
|
||||
infer::BoundRegionInFnType(_, br) => {
|
||||
format!(" for {}in function type",
|
||||
bound_region_to_str(self.tcx, "region ", true, br))
|
||||
bound_region_to_str(self.tcx, "lifetime parameter ", true, br))
|
||||
}
|
||||
infer::BoundRegionInTypeOrImpl(_) => {
|
||||
format!(" for region in type/impl")
|
||||
infer::EarlyBoundRegion(_, name) => {
|
||||
format!(" for lifetime parameter `{}",
|
||||
token::get_name(name).get())
|
||||
}
|
||||
infer::BoundRegionInCoherence(..) => {
|
||||
format!(" for coherence check")
|
||||
infer::BoundRegionInCoherence(name) => {
|
||||
format!(" for lifetime parameter `{} in coherence check",
|
||||
token::get_name(name).get())
|
||||
}
|
||||
infer::UpvarRegion(ref upvar_id, _) => {
|
||||
format!(" for capture of `{}` by closure",
|
||||
|
@ -136,11 +136,11 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
|
||||
|
||||
// Instantiate each bound region with a fresh region variable.
|
||||
let (a_with_fresh, a_map) =
|
||||
self.get_ref().infcx.replace_bound_regions_with_fresh_regions(
|
||||
self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
|
||||
self.get_ref().trace, a);
|
||||
let a_vars = var_ids(self, &a_map);
|
||||
let (b_with_fresh, b_map) =
|
||||
self.get_ref().infcx.replace_bound_regions_with_fresh_regions(
|
||||
self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
|
||||
self.get_ref().trace, b);
|
||||
let b_vars = var_ids(self, &b_map);
|
||||
|
||||
|
@ -126,10 +126,10 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
|
||||
|
||||
// Instantiate each bound region with a fresh region variable.
|
||||
let (a_with_fresh, a_map) =
|
||||
self.get_ref().infcx.replace_bound_regions_with_fresh_regions(
|
||||
self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
|
||||
self.get_ref().trace, a);
|
||||
let (b_with_fresh, _) =
|
||||
self.get_ref().infcx.replace_bound_regions_with_fresh_regions(
|
||||
self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
|
||||
self.get_ref().trace, b);
|
||||
|
||||
// Collect constraints.
|
||||
|
@ -27,7 +27,7 @@
|
||||
use middle::ty;
|
||||
use middle::ty_fold;
|
||||
use middle::ty_fold::TypeFolder;
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
|
||||
use middle::typeck::infer::coercion::Coerce;
|
||||
use middle::typeck::infer::combine::{Combine, CombineFields, eq_tys};
|
||||
use middle::typeck::infer::region_inference::{RegionVarBindings};
|
||||
@ -44,6 +44,7 @@
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::opt_vec::OptVec;
|
||||
use util::common::indent;
|
||||
use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr};
|
||||
|
||||
@ -221,9 +222,12 @@ pub enum RegionVariableOrigin {
|
||||
// Regions created as part of an automatic coercion
|
||||
Coercion(TypeTrace),
|
||||
|
||||
// Region variables created as the values for early-bound regions
|
||||
EarlyBoundRegion(Span, ast::Name),
|
||||
|
||||
// Region variables created for bound regions
|
||||
// in a function or method that is called
|
||||
BoundRegionInFnCall(Span, ty::BoundRegion),
|
||||
LateBoundRegion(Span, ty::BoundRegion),
|
||||
|
||||
// Region variables created for bound regions
|
||||
// when doing subtyping/lub/glb computations
|
||||
@ -231,9 +235,7 @@ pub enum RegionVariableOrigin {
|
||||
|
||||
UpvarRegion(ty::UpvarId, Span),
|
||||
|
||||
BoundRegionInTypeOrImpl(Span),
|
||||
|
||||
BoundRegionInCoherence,
|
||||
BoundRegionInCoherence(ast::Name),
|
||||
}
|
||||
|
||||
pub enum fixup_err {
|
||||
@ -663,6 +665,15 @@ pub fn next_region_vars(&self,
|
||||
Vec::from_fn(count, |_| self.next_region_var(origin))
|
||||
}
|
||||
|
||||
pub fn region_vars_for_defs(&self,
|
||||
span: Span,
|
||||
defs: &[ty::RegionParameterDef])
|
||||
-> OptVec<ty::Region> {
|
||||
defs.iter()
|
||||
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
|
||||
self.region_vars.new_bound(binder_id)
|
||||
}
|
||||
@ -809,14 +820,14 @@ pub fn report_mismatched_types(&self,
|
||||
self.type_error_message(sp, mk_msg, a, Some(err));
|
||||
}
|
||||
|
||||
pub fn replace_bound_regions_with_fresh_regions(&self,
|
||||
trace: TypeTrace,
|
||||
fsig: &ty::FnSig)
|
||||
pub fn replace_late_bound_regions_with_fresh_regions(&self,
|
||||
trace: TypeTrace,
|
||||
fsig: &ty::FnSig)
|
||||
-> (ty::FnSig,
|
||||
HashMap<ty::BoundRegion,
|
||||
ty::Region>) {
|
||||
let (map, fn_sig) =
|
||||
replace_bound_regions_in_fn_sig(self.tcx, fsig, |br| {
|
||||
replace_late_bound_regions_in_fn_sig(self.tcx, fsig, |br| {
|
||||
let rvar = self.next_region_var(
|
||||
BoundRegionInFnType(trace.origin.span(), br));
|
||||
debug!("Bound region {} maps to {:?}",
|
||||
@ -932,10 +943,10 @@ pub fn span(&self) -> Span {
|
||||
AddrOfSlice(a) => a,
|
||||
Autoref(a) => a,
|
||||
Coercion(a) => a.span(),
|
||||
BoundRegionInFnCall(a, _) => a,
|
||||
EarlyBoundRegion(a, _) => a,
|
||||
LateBoundRegion(a, _) => a,
|
||||
BoundRegionInFnType(a, _) => a,
|
||||
BoundRegionInTypeOrImpl(a) => a,
|
||||
BoundRegionInCoherence => codemap::DUMMY_SP,
|
||||
BoundRegionInCoherence(_) => codemap::DUMMY_SP,
|
||||
UpvarRegion(_, a) => a
|
||||
}
|
||||
}
|
||||
@ -950,13 +961,14 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
|
||||
AddrOfSlice(a) => format!("AddrOfSlice({})", a.repr(tcx)),
|
||||
Autoref(a) => format!("Autoref({})", a.repr(tcx)),
|
||||
Coercion(a) => format!("Coercion({})", a.repr(tcx)),
|
||||
BoundRegionInFnCall(a, b) => format!("bound_regionInFnCall({},{})",
|
||||
EarlyBoundRegion(a, b) => format!("EarlyBoundRegion({},{})",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
LateBoundRegion(a, b) => format!("LateBoundRegion({},{})",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
BoundRegionInFnType(a, b) => format!("bound_regionInFnType({},{})",
|
||||
a.repr(tcx), b.repr(tcx)),
|
||||
BoundRegionInTypeOrImpl(a) => format!("bound_regionInTypeOrImpl({})",
|
||||
a.repr(tcx)),
|
||||
BoundRegionInCoherence => format!("bound_regionInCoherence"),
|
||||
BoundRegionInCoherence(a) => format!("bound_regionInCoherence({})",
|
||||
a.repr(tcx)),
|
||||
UpvarRegion(a, b) => format!("UpvarRegion({}, {})",
|
||||
a.repr(tcx),
|
||||
b.repr(tcx)),
|
||||
|
@ -12,7 +12,7 @@
|
||||
use middle::ty::{BuiltinBounds};
|
||||
use middle::ty;
|
||||
use middle::ty::TyVar;
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
|
||||
use middle::typeck::infer::combine::*;
|
||||
use middle::typeck::infer::{cres, CresCompare};
|
||||
use middle::typeck::infer::glb::Glb;
|
||||
@ -166,13 +166,13 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
|
||||
// First, we instantiate each bound region in the subtype with a fresh
|
||||
// region variable.
|
||||
let (a_sig, _) =
|
||||
self.get_ref().infcx.replace_bound_regions_with_fresh_regions(
|
||||
self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
|
||||
self.get_ref().trace, a);
|
||||
|
||||
// Second, we instantiate each bound region in the supertype with a
|
||||
// fresh concrete region.
|
||||
let (skol_map, b_sig) = {
|
||||
replace_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
|
||||
replace_late_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
|
||||
let skol = self.get_ref().infcx.region_vars.new_skolemized(br);
|
||||
debug!("Bound region {} skolemized to {:?}",
|
||||
bound_region_to_str(self.get_ref().infcx.tcx, "", false, br),
|
||||
|
@ -78,5 +78,5 @@ pub fn bound_type_regions(defs: &[ty::RegionParameterDef])
|
||||
-> OptVec<ty::Region> {
|
||||
assert!(defs.iter().all(|def| def.def_id.krate == ast::LOCAL_CRATE));
|
||||
defs.iter().enumerate().map(
|
||||
|(i, def)| ty::ReEarlyBound(def.def_id.node, i, def.ident)).collect()
|
||||
|(i, def)| ty::ReEarlyBound(def.def_id.node, i, def.name)).collect()
|
||||
}
|
||||
|
@ -161,8 +161,8 @@ pub fn bound_region_to_str(cx: ctxt,
|
||||
}
|
||||
|
||||
match br {
|
||||
BrNamed(_, ident) => format!("{}'{}{}", prefix,
|
||||
token::get_name(ident), space_str),
|
||||
BrNamed(_, name) => format!("{}'{}{}", prefix,
|
||||
token::get_name(name), space_str),
|
||||
BrAnon(_) => prefix.to_str(),
|
||||
BrFresh(_) => prefix.to_str(),
|
||||
}
|
||||
@ -224,7 +224,7 @@ pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~st
|
||||
// `explain_region()` or `note_and_explain_region()`.
|
||||
match region {
|
||||
ty::ReScope(_) => prefix.to_str(),
|
||||
ty::ReEarlyBound(_, _, ident) => token::get_name(ident).get().to_str(),
|
||||
ty::ReEarlyBound(_, _, name) => token::get_name(name).get().to_str(),
|
||||
ty::ReLateBound(_, br) => bound_region_to_str(cx, prefix, space, br),
|
||||
ty::ReFree(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
|
||||
ty::ReInfer(ReSkolemized(_, br)) => {
|
||||
@ -634,7 +634,7 @@ fn repr(&self, tcx: ctxt) -> ~str {
|
||||
impl Repr for ty::RegionParameterDef {
|
||||
fn repr(&self, _tcx: ctxt) -> ~str {
|
||||
format!("RegionParameterDef({}, {:?})",
|
||||
token::get_name(self.ident),
|
||||
token::get_name(self.name),
|
||||
self.def_id)
|
||||
}
|
||||
}
|
||||
@ -720,9 +720,9 @@ impl Repr for ty::BoundRegion {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
match *self {
|
||||
ty::BrAnon(id) => format!("BrAnon({})", id),
|
||||
ty::BrNamed(id, ident) => format!("BrNamed({}, {})",
|
||||
id.repr(tcx),
|
||||
token::get_name(ident)),
|
||||
ty::BrNamed(id, name) => format!("BrNamed({}, {})",
|
||||
id.repr(tcx),
|
||||
token::get_name(name)),
|
||||
ty::BrFresh(id) => format!("BrFresh({})", id),
|
||||
}
|
||||
}
|
||||
@ -731,9 +731,9 @@ fn repr(&self, tcx: ctxt) -> ~str {
|
||||
impl Repr for ty::Region {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
match *self {
|
||||
ty::ReEarlyBound(id, index, ident) => {
|
||||
ty::ReEarlyBound(id, index, name) => {
|
||||
format!("ReEarlyBound({}, {}, {})",
|
||||
id, index, token::get_name(ident))
|
||||
id, index, token::get_name(name))
|
||||
}
|
||||
|
||||
ty::ReLateBound(binder_id, ref bound_region) => {
|
||||
@ -841,6 +841,12 @@ fn repr(&self, tcx: ctxt) -> ~str {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::Name {
|
||||
fn repr(&self, _tcx: ctxt) -> ~str {
|
||||
token::get_name(*self).get().to_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::Ident {
|
||||
fn repr(&self, _tcx: ctxt) -> ~str {
|
||||
token::get_ident(*self).get().to_str()
|
||||
@ -1010,6 +1016,12 @@ fn user_string(&self, tcx: ctxt) -> ~str {
|
||||
}
|
||||
}
|
||||
|
||||
impl UserString for ast::Ident {
|
||||
fn user_string(&self, _tcx: ctxt) -> ~str {
|
||||
token::get_name(self.name).get().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for AbiSet {
|
||||
fn repr(&self, _tcx: ctxt) -> ~str {
|
||||
self.to_str()
|
||||
|
@ -333,7 +333,7 @@ pub fn get_ref<'a>(&'a self) -> &'a str {
|
||||
|
||||
impl Clean<Lifetime> for ast::Lifetime {
|
||||
fn clean(&self) -> Lifetime {
|
||||
Lifetime(token::get_name(self.ident).get().to_owned())
|
||||
Lifetime(token::get_name(self.name).get().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,26 @@ pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
|
||||
xs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Partitions the vector into two vectors `(A,B)`, where all
|
||||
* elements of `A` satisfy `f` and all elements of `B` do not.
|
||||
*/
|
||||
#[inline]
|
||||
pub fn partition(self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
|
||||
let mut lefts = Vec::new();
|
||||
let mut rights = Vec::new();
|
||||
|
||||
for elt in self.move_iter() {
|
||||
if f(&elt) {
|
||||
lefts.push(elt);
|
||||
} else {
|
||||
rights.push(elt);
|
||||
}
|
||||
}
|
||||
|
||||
(lefts, rights)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Vec<T> {
|
||||
|
@ -118,7 +118,7 @@ fn decode(d: &mut D) -> Ident {
|
||||
pub struct Lifetime {
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
ident: Name
|
||||
name: Name
|
||||
}
|
||||
|
||||
// a "Path" is essentially Rust's notion of a name;
|
||||
@ -142,7 +142,7 @@ pub struct PathSegment {
|
||||
/// The identifier portion of this path segment.
|
||||
identifier: Ident,
|
||||
/// The lifetime parameters for this path segment.
|
||||
lifetimes: OptVec<Lifetime>,
|
||||
lifetimes: Vec<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
types: OptVec<P<Ty>>,
|
||||
}
|
||||
@ -187,7 +187,7 @@ pub struct TyParam {
|
||||
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
|
||||
pub struct Generics {
|
||||
lifetimes: OptVec<Lifetime>,
|
||||
lifetimes: Vec<Lifetime>,
|
||||
ty_params: OptVec<TyParam>,
|
||||
}
|
||||
|
||||
@ -795,7 +795,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
pub struct ClosureTy {
|
||||
sigil: Sigil,
|
||||
region: Option<Lifetime>,
|
||||
lifetimes: OptVec<Lifetime>,
|
||||
lifetimes: Vec<Lifetime>,
|
||||
purity: Purity,
|
||||
onceness: Onceness,
|
||||
decl: P<FnDecl>,
|
||||
@ -810,7 +810,7 @@ pub struct ClosureTy {
|
||||
pub struct BareFnTy {
|
||||
purity: Purity,
|
||||
abis: AbiSet,
|
||||
lifetimes: OptVec<Lifetime>,
|
||||
lifetimes: Vec<Lifetime>,
|
||||
decl: P<FnDecl>
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -311,7 +311,7 @@ pub fn operator_prec(op: ast::BinOp) -> uint {
|
||||
pub static as_prec: uint = 12u;
|
||||
|
||||
pub fn empty_generics() -> Generics {
|
||||
Generics {lifetimes: opt_vec::Empty,
|
||||
Generics {lifetimes: Vec::new(),
|
||||
ty_params: opt_vec::Empty}
|
||||
}
|
||||
|
||||
@ -690,10 +690,11 @@ mod test {
|
||||
use ast::*;
|
||||
use super::*;
|
||||
use opt_vec;
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
fn ident_to_segment(id : &Ident) -> PathSegment {
|
||||
PathSegment {identifier:id.clone(),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ pub trait AstBuilder {
|
||||
fn path_all(&self, sp: Span,
|
||||
global: bool,
|
||||
idents: Vec<ast::Ident> ,
|
||||
lifetimes: OptVec<ast::Lifetime>,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>> )
|
||||
-> ast::Path;
|
||||
|
||||
@ -255,19 +255,19 @@ fn view_use_glob(&self, sp: Span,
|
||||
|
||||
impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, false, strs, opt_vec::Empty, Vec::new())
|
||||
self.path_all(span, false, strs, Vec::new(), Vec::new())
|
||||
}
|
||||
fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
|
||||
self.path(span, vec!(id))
|
||||
}
|
||||
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, true, strs, opt_vec::Empty, Vec::new())
|
||||
self.path_all(span, true, strs, Vec::new(), Vec::new())
|
||||
}
|
||||
fn path_all(&self,
|
||||
sp: Span,
|
||||
global: bool,
|
||||
mut idents: Vec<ast::Ident> ,
|
||||
lifetimes: OptVec<ast::Lifetime>,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>> )
|
||||
-> ast::Path {
|
||||
let last_identifier = idents.pop().unwrap();
|
||||
@ -275,7 +275,7 @@ fn path_all(&self,
|
||||
.map(|ident| {
|
||||
ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect();
|
||||
@ -342,7 +342,7 @@ fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
|
||||
self.ident_of("option"),
|
||||
self.ident_of("Option")
|
||||
),
|
||||
opt_vec::Empty,
|
||||
Vec::new(),
|
||||
vec!( ty )), None)
|
||||
}
|
||||
|
||||
@ -413,8 +413,8 @@ fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
|
||||
ast::TraitTyParamBound(self.trait_ref(path))
|
||||
}
|
||||
|
||||
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime {
|
||||
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, ident: ident }
|
||||
fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
|
||||
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
|
||||
}
|
||||
|
||||
fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt {
|
||||
|
@ -15,6 +15,7 @@
|
||||
use opt_vec;
|
||||
use parse::token;
|
||||
use parse::token::{str_to_ident};
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
@ -51,7 +52,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: res,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
)
|
||||
|
@ -14,7 +14,6 @@
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::build::{AstBuilder};
|
||||
use ext::deriving::generic::*;
|
||||
use opt_vec;
|
||||
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
@ -84,7 +83,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
|
||||
let rand_name = cx.path_all(trait_span,
|
||||
true,
|
||||
rand_ident.clone(),
|
||||
opt_vec::Empty,
|
||||
Vec::new(),
|
||||
Vec::new());
|
||||
let rand_name = cx.expr_path(rand_name);
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
use ext::build::AstBuilder;
|
||||
use codemap::{Span,respan};
|
||||
use opt_vec;
|
||||
use opt_vec::OptVec;
|
||||
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
@ -118,11 +117,12 @@ fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifet
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> OptVec<ast::Lifetime> {
|
||||
match *lt {
|
||||
fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
|
||||
let lifetimes = match *lt {
|
||||
Some(ref s) => opt_vec::with(cx.lifetime(span, cx.ident_of(*s).name)),
|
||||
None => opt_vec::Empty
|
||||
}
|
||||
};
|
||||
opt_vec::take_vec(lifetimes)
|
||||
}
|
||||
|
||||
impl<'a> Ty<'a> {
|
||||
@ -199,7 +199,7 @@ fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, bounds: &[Path],
|
||||
|
||||
fn mk_generics(lifetimes: Vec<ast::Lifetime> , ty_params: Vec<ast::TyParam> ) -> Generics {
|
||||
Generics {
|
||||
lifetimes: opt_vec::from(lifetimes),
|
||||
lifetimes: lifetimes,
|
||||
ty_params: opt_vec::from(ty_params)
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
use ext::base::*;
|
||||
use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
use opt_vec;
|
||||
use parse::token;
|
||||
|
||||
use std::os;
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
@ -38,7 +38,7 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("option"),
|
||||
cx.ident_of("None")),
|
||||
opt_vec::Empty,
|
||||
Vec::new(),
|
||||
vec!(cx.ty_rptr(sp,
|
||||
cx.ty_ident(sp,
|
||||
cx.ident_of("str")),
|
||||
|
@ -14,7 +14,6 @@
|
||||
use ext::base::*;
|
||||
use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
use opt_vec;
|
||||
use parse::token::InternedString;
|
||||
use parse::token;
|
||||
use rsparse = parse;
|
||||
@ -509,7 +508,7 @@ fn trans_method(&mut self, method: &parse::Method) -> @ast::Expr {
|
||||
sp,
|
||||
true,
|
||||
self.rtpath("Method"),
|
||||
opt_vec::with(life),
|
||||
vec!(life),
|
||||
Vec::new()
|
||||
), None);
|
||||
let st = ast::ItemStatic(ty, ast::MutImmutable, method);
|
||||
@ -632,8 +631,8 @@ fn to_expr(&self, extra: @ast::Expr) -> @ast::Expr {
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of("rt"),
|
||||
self.ecx.ident_of("Piece")),
|
||||
opt_vec::with(
|
||||
self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("static").name)),
|
||||
vec!(self.ecx.lifetime(self.fmtsp,
|
||||
self.ecx.ident_of("static").name)),
|
||||
Vec::new()
|
||||
), None);
|
||||
let ty = ast::TyFixedLengthVec(
|
||||
|
@ -435,12 +435,12 @@ pub fn fold_lifetime<T: Folder>(l: &Lifetime, fld: &mut T) -> Lifetime {
|
||||
Lifetime {
|
||||
id: fld.new_id(l.id),
|
||||
span: fld.new_span(l.span),
|
||||
ident: l.ident
|
||||
name: l.name
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fold_lifetimes<T: Folder>(lts: &OptVec<Lifetime>, fld: &mut T)
|
||||
-> OptVec<Lifetime> {
|
||||
pub fn fold_lifetimes<T: Folder>(lts: &Vec<Lifetime>, fld: &mut T)
|
||||
-> Vec<Lifetime> {
|
||||
lts.map(|l| fold_lifetime(l, fld))
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,7 @@ fn sp(a: u32, b: u32) -> Span {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -342,12 +342,12 @@ fn sp(a: u32, b: u32) -> Span {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
)
|
||||
@ -556,7 +556,7 @@ fn sp(a: u32, b: u32) -> Span {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("d"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -578,7 +578,7 @@ fn sp(a: u32, b: u32) -> Span {
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -605,7 +605,7 @@ fn parser_done(p: Parser){
|
||||
segments: vec!(
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -633,7 +633,7 @@ fn parser_done(p: Parser){
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident("int"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -651,7 +651,7 @@ fn parser_done(p: Parser){
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident("b"),
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
),
|
||||
@ -671,7 +671,7 @@ fn parser_done(p: Parser){
|
||||
ast::ImpureFn,
|
||||
abi::AbiSet::Rust(),
|
||||
ast::Generics{ // no idea on either of these:
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
ty_params: opt_vec::Empty,
|
||||
},
|
||||
ast::P(ast::Block {
|
||||
@ -689,7 +689,7 @@ fn parser_done(p: Parser){
|
||||
str_to_ident(
|
||||
"b"),
|
||||
lifetimes:
|
||||
opt_vec::Empty,
|
||||
Vec::new(),
|
||||
types:
|
||||
opt_vec::Empty
|
||||
}
|
||||
|
@ -958,7 +958,7 @@ pub fn parse_ty_closure(&mut self,
|
||||
|
||||
lifetimes
|
||||
} else {
|
||||
opt_vec::Empty
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let inputs = if self.eat(&token::OROR) {
|
||||
@ -1015,7 +1015,7 @@ pub fn parse_unsafety(&mut self) -> Purity {
|
||||
|
||||
// parse a function type (following the 'fn')
|
||||
pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
||||
-> (P<FnDecl>, OptVec<ast::Lifetime>) {
|
||||
-> (P<FnDecl>, Vec<ast::Lifetime>) {
|
||||
/*
|
||||
|
||||
(fn) <'lt> (S) -> T
|
||||
@ -1031,7 +1031,7 @@ pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
||||
self.expect_gt();
|
||||
lifetimes
|
||||
} else {
|
||||
opt_vec::Empty
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let (inputs, variadic) = self.parse_fn_args(false, allow_variadic);
|
||||
@ -1510,7 +1510,7 @@ pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
|
||||
segments.push(PathSegmentAndBoundSet {
|
||||
segment: ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
bound_set: bound_set
|
||||
@ -1525,7 +1525,7 @@ pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
|
||||
self.parse_generic_values_after_lt();
|
||||
(true, lifetimes, opt_vec::from(types))
|
||||
} else {
|
||||
(false, opt_vec::Empty, opt_vec::Empty)
|
||||
(false, Vec::new(), opt_vec::Empty)
|
||||
}
|
||||
};
|
||||
|
||||
@ -1609,7 +1609,7 @@ pub fn parse_lifetime(&mut self) -> ast::Lifetime {
|
||||
return ast::Lifetime {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: span,
|
||||
ident: i.name
|
||||
name: i.name
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
@ -1621,7 +1621,7 @@ pub fn parse_lifetime(&mut self) -> ast::Lifetime {
|
||||
// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes )
|
||||
// actually, it matches the empty one too, but putting that in there
|
||||
// messes up the grammar....
|
||||
pub fn parse_lifetimes(&mut self) -> OptVec<ast::Lifetime> {
|
||||
pub fn parse_lifetimes(&mut self) -> Vec<ast::Lifetime> {
|
||||
/*!
|
||||
*
|
||||
* Parses zero or more comma separated lifetimes.
|
||||
@ -1630,7 +1630,7 @@ pub fn parse_lifetimes(&mut self) -> OptVec<ast::Lifetime> {
|
||||
* lists, where we expect something like `<'a, 'b, T>`.
|
||||
*/
|
||||
|
||||
let mut res = opt_vec::Empty;
|
||||
let mut res = Vec::new();
|
||||
loop {
|
||||
match self.token {
|
||||
token::LIFETIME(_) => {
|
||||
@ -1995,7 +1995,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
|
||||
self.expect(&token::LT);
|
||||
self.parse_generic_values_after_lt()
|
||||
} else {
|
||||
(opt_vec::Empty, Vec::new())
|
||||
(Vec::new(), Vec::new())
|
||||
};
|
||||
|
||||
// expr.f() method call
|
||||
@ -3515,7 +3515,7 @@ pub fn parse_generics(&mut self) -> ast::Generics {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_generic_values_after_lt(&mut self) -> (OptVec<ast::Lifetime>, Vec<P<Ty>> ) {
|
||||
fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) {
|
||||
let lifetimes = self.parse_lifetimes();
|
||||
let result = self.parse_seq_to_gt(
|
||||
Some(token::COMMA),
|
||||
@ -4886,7 +4886,7 @@ fn parse_view_path(&mut self) -> @ViewPath {
|
||||
segments: path.move_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect()
|
||||
@ -4921,7 +4921,7 @@ fn parse_view_path(&mut self) -> @ViewPath {
|
||||
segments: path.move_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect()
|
||||
@ -4939,7 +4939,7 @@ fn parse_view_path(&mut self) -> @ViewPath {
|
||||
segments: path.move_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect()
|
||||
@ -4961,7 +4961,7 @@ fn parse_view_path(&mut self) -> @ViewPath {
|
||||
segments: path.move_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect()
|
||||
|
@ -1956,7 +1956,7 @@ pub fn print_bounds(s: &mut State, bounds: &OptVec<ast::TyParamBound>,
|
||||
pub fn print_lifetime(s: &mut State,
|
||||
lifetime: &ast::Lifetime) -> io::IoResult<()> {
|
||||
try!(word(&mut s.s, "'"));
|
||||
print_name(s, lifetime.ident)
|
||||
print_name(s, lifetime.name)
|
||||
}
|
||||
|
||||
pub fn print_generics(s: &mut State,
|
||||
|
@ -15,6 +15,7 @@
|
||||
use parse;
|
||||
use opt_vec;
|
||||
use opt_vec::OptVec;
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
// Context-passing AST walker. Each overridden visit method has full control
|
||||
// over what happens with its node, it can do its own traversal of the node's
|
||||
@ -55,7 +56,7 @@ pub fn generics_of_fn(fk: &FnKind) -> Generics {
|
||||
}
|
||||
FkFnBlock(..) => {
|
||||
Generics {
|
||||
lifetimes: opt_vec::Empty,
|
||||
lifetimes: Vec::new(),
|
||||
ty_params: opt_vec::Empty,
|
||||
}
|
||||
}
|
||||
@ -370,7 +371,7 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
|
||||
}
|
||||
|
||||
fn walk_lifetime_decls<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||
lifetimes: &OptVec<Lifetime>,
|
||||
lifetimes: &Vec<Lifetime>,
|
||||
env: E) {
|
||||
for l in lifetimes.iter() {
|
||||
visitor.visit_lifetime_decl(l, env.clone());
|
||||
|
35
src/test/compile-fail/regions-early-bound-error-method.rs
Normal file
35
src/test/compile-fail/regions-early-bound-error-method.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that you can use a fn lifetime parameter as part of
|
||||
// the value for a type parameter in a bound.
|
||||
|
||||
trait GetRef<'a> {
|
||||
fn get(&self) -> &'a int;
|
||||
}
|
||||
|
||||
struct Box<'a> {
|
||||
t: &'a int
|
||||
}
|
||||
|
||||
impl<'a> GetRef<'a> for Box<'a> {
|
||||
fn get(&self) -> &'a int {
|
||||
self.t
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Box<'a> {
|
||||
fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a int {
|
||||
g2.get() //~ ERROR lifetime mismatch
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
33
src/test/compile-fail/regions-early-bound-error.rs
Normal file
33
src/test/compile-fail/regions-early-bound-error.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that you can use a fn lifetime parameter as part of
|
||||
// the value for a type parameter in a bound.
|
||||
|
||||
trait GetRef<'a, T> {
|
||||
fn get(&self) -> &'a T;
|
||||
}
|
||||
|
||||
struct Box<'a, T> {
|
||||
t: &'a T
|
||||
}
|
||||
|
||||
impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
|
||||
fn get(&self) -> &'a T {
|
||||
self.t
|
||||
}
|
||||
}
|
||||
|
||||
fn get<'a,'b,G:GetRef<'a, int>>(g1: G, b: &'b int) -> &'b int {
|
||||
g1.get() //~ ERROR lifetime mismatch
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that you can use a fn lifetime parameter as part of
|
||||
// the value for a type parameter in a bound.
|
||||
|
||||
trait GetRef<'a> {
|
||||
fn get(&self) -> &'a int;
|
||||
}
|
||||
|
||||
struct Box<'a> {
|
||||
t: &'a int
|
||||
}
|
||||
|
||||
impl<'a> GetRef<'a> for Box<'a> {
|
||||
fn get(&self) -> &'a int {
|
||||
self.t
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Box<'a> {
|
||||
fn add<'b,G:GetRef<'b>>(&self, g2: G) -> int {
|
||||
*self.t + *g2.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let b1 = Box { t: &3 };
|
||||
assert_eq!(b1.add(b1), 6);
|
||||
}
|
35
src/test/run-pass/regions-early-bound-used-in-bound.rs
Normal file
35
src/test/run-pass/regions-early-bound-used-in-bound.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that you can use a fn lifetime parameter as part of
|
||||
// the value for a type parameter in a bound.
|
||||
|
||||
trait GetRef<'a, T> {
|
||||
fn get(&self) -> &'a T;
|
||||
}
|
||||
|
||||
struct Box<'a, T> {
|
||||
t: &'a T
|
||||
}
|
||||
|
||||
impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
|
||||
fn get(&self) -> &'a T {
|
||||
self.t
|
||||
}
|
||||
}
|
||||
|
||||
fn add<'a,G:GetRef<'a, int>>(g1: G, g2: G) -> int {
|
||||
*g1.get() + *g2.get()
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let b1 = Box { t: &3 };
|
||||
assert_eq!(add(b1, b1), 6);
|
||||
}
|
35
src/test/run-pass/regions-early-bound-used-in-type-param.rs
Normal file
35
src/test/run-pass/regions-early-bound-used-in-type-param.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that you can use a fn lifetime parameter as part of
|
||||
// the value for a type parameter in a bound.
|
||||
|
||||
trait Get<T> {
|
||||
fn get(&self) -> T;
|
||||
}
|
||||
|
||||
struct Box<T> {
|
||||
t: T
|
||||
}
|
||||
|
||||
impl<T:Clone> Get<T> for Box<T> {
|
||||
fn get(&self) -> T {
|
||||
self.t.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn add<'a,G:Get<&'a int>>(g1: G, g2: G) -> int {
|
||||
*g1.get() + *g2.get()
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let b1 = Box { t: &3 };
|
||||
assert_eq!(add(b1, b1), 6);
|
||||
}
|
Loading…
Reference in New Issue
Block a user