提交 15688eaf 编写于 作者: P Patrick Walton

librustc: Require explicit lifetime binders

上级 3b2fcf9f
......@@ -58,13 +58,15 @@
use middle::ty::{arg, field, substs};
use middle::ty::{ty_param_substs_and_ty};
use middle::ty;
use middle::typeck::rscope::{in_binding_rscope};
use middle::typeck::rscope::{in_binding_rscope, in_binding_rscope_ext};
use middle::typeck::rscope::{region_scope, type_rscope, RegionError};
use middle::typeck::rscope::{RegionParamNames};
use core::result;
use core::vec;
use syntax::{ast, ast_util};
use syntax::codemap::span;
use syntax::opt_vec::OptVec;
use syntax::print::pprust::{lifetime_to_str, path_to_str};
use syntax::parse::token::special_idents;
use util::common::indenter;
......@@ -348,9 +350,15 @@ fn check_path_args(tcx: ty::ctxt,
bf.abi, &bf.decl))
}
ast::ty_closure(ref f) => {
let fn_decl = ty_of_closure(self, rscope, f.sigil,
f.purity, f.onceness,
f.region, &f.decl, None,
let fn_decl = ty_of_closure(self,
rscope,
f.sigil,
f.purity,
f.onceness,
f.region,
&f.decl,
None,
&f.lifetimes,
ast_ty.span);
ty::mk_closure(tcx, fn_decl)
}
......@@ -507,7 +515,7 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
abi: ast::Abi,
decl: &ast::fn_decl)
-> ty::BareFnTy {
debug!("ty_of_fn_decl");
debug!("ty_of_bare_fn");
// new region names that appear inside of the fn decl are bound to
// that function type
......@@ -526,6 +534,33 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
}
}
pub fn ty_of_bare_fn_ext<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
purity: ast::purity,
abi: ast::Abi,
decl: &ast::fn_decl,
+region_param_names: RegionParamNames)
-> ty::BareFnTy {
debug!("ty_of_bare_fn_ext");
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = in_binding_rscope_ext(rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None));
let output_ty = match decl.output.node {
ast::ty_infer => self.ty_infer(decl.output.span),
_ => ast_ty_to_ty(self, &rb, decl.output)
};
ty::BareFnTy {
purity: purity,
abi: abi,
sig: ty::FnSig {inputs: input_tys, output: output_ty}
}
}
pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
......@@ -535,6 +570,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
opt_lifetime: Option<@ast::Lifetime>,
decl: &ast::fn_decl,
expected_tys: Option<ty::FnSig>,
lifetimes: &OptVec<ast::Lifetime>,
span: span)
-> ty::ClosureTy {
debug!("ty_of_fn_decl");
......@@ -563,7 +599,8 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = in_binding_rscope(rscope);
let region_param_names = RegionParamNames::from_lifetimes(lifetimes);
let rb = in_binding_rscope_ext(rscope, region_param_names);
let input_tys = do decl.inputs.mapi |i, a| {
let expected_arg_ty = do expected_tys.chain_ref |e| {
......
......@@ -100,7 +100,7 @@
use middle::typeck::infer::{resolve_type, force_tvar, mk_eqty};
use middle::typeck::infer;
use middle::typeck::rscope::{binding_rscope, bound_self_region};
use middle::typeck::rscope::{RegionError};
use middle::typeck::rscope::{RegionError, RegionParameterization};
use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope};
use middle::typeck::rscope;
use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
......@@ -126,10 +126,11 @@
use syntax::ast_util;
use syntax::codemap::{span, spanned, respan};
use syntax::codemap;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax::parse::token::special_idents;
use syntax::print::pprust;
use syntax::visit;
use syntax::opt_vec::OptVec;
use syntax;
pub mod _match;
......@@ -570,10 +571,12 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
ast::item_fn(ref decl, _, _, ref body) => {
check_bare_fn(ccx, decl, body, it.id, None);
}
ast::item_impl(_, _, ty, ref ms) => {
ast::item_impl(ref generics, _, ty, ref ms) => {
let rp = ccx.tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
debug!("item_impl %s with id %d rp %?",
*ccx.tcx.sess.str_of(it.ident), it.id, rp);
let rp = RegionParameterization::from_variance_and_generics(
rp, generics);
let self_ty = ccx.to_ty(&rscope::type_rscope(rp), ty);
for ms.each |m| {
check_method(ccx, *m, self_ty);
......@@ -1069,9 +1072,13 @@ pub fn impl_self_ty(vcx: &VtableContext,
node: ast::item_impl(ref ts, _, st, _),
_
}, _)) => {
let region_parameterization =
RegionParameterization::from_variance_and_generics(
region_param,
ts);
(ts.ty_params.len(),
region_param,
vcx.ccx.to_ty(&rscope::type_rscope(region_param), st))
vcx.ccx.to_ty(&rscope::type_rscope(region_parameterization), st))
}
Some(&ast_map::node_item(@ast::item {
node: ast::item_struct(_, ref ts),
......@@ -1654,10 +1661,16 @@ fn check_expr_fn(fcx: @mut FnCtxt,
};
// construct the function type
let mut fn_ty = astconv::ty_of_closure(
fcx, fcx,
sigil, purity, expected_onceness,
None, decl, expected_tys, expr.span);
let mut fn_ty = astconv::ty_of_closure(fcx,
fcx,
sigil,
purity,
expected_onceness,
None,
decl,
expected_tys,
&opt_vec::Empty,
expr.span);
let mut fty_sig;
let fty = if error_happened {
......
......@@ -166,12 +166,15 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
// Create a set of parameter types shared among all the variants.
for variants.each |variant| {
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let result_ty;
match variant.node.kind {
ast::tuple_variant_kind(ref args) if args.len() > 0 => {
let rs = type_rscope(rp);
let rs = type_rscope(region_parameterization);
let input_tys = args.map(|va| ccx.to_ty(&rs, va.ty));
result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
}
......@@ -301,7 +304,8 @@ fn make_static_method_ty(ccx: &CrateCtxt,
ccx,
&ty_m,
region_paramd,
def_id
def_id,
generics
);
if ty_m.self_ty.node == ast::sty_static {
make_static_method_ty(ccx, &ty_m, region_paramd,
......@@ -319,13 +323,14 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
id: ast::node_id,
sp: codemap::span,
rp: Option<ty::region_variance>,
trait_refs: &[@ast::trait_ref]) {
trait_refs: &[@ast::trait_ref],
generics: &ast::Generics) {
let tcx = ccx.tcx;
if tcx.supertraits.contains_key(&local_def(id)) { return; }
let mut instantiated = ~[];
for trait_refs.each |trait_ref| {
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp);
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp, generics);
if instantiated.any(|other_trait: &InstantiatedTraitRef|
{ other_trait.def_id == did }) {
// This means a trait inherited from the same supertrait more
......@@ -506,7 +511,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
impl_ms: &[ConvertedMethod]) {
let tcx = ccx.tcx;
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp);
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
if did.crate == ast::local_crate {
// NB: This is subtle. We need to do this on the type of the trait
......@@ -553,8 +558,11 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
pub fn convert_field(ccx: &CrateCtxt,
rp: Option<ty::region_variance>,
bounds: @~[ty::param_bounds],
v: @ast::struct_field) {
let tt = ccx.to_ty(&type_rscope(rp), v.node.ty);
v: @ast::struct_field,
generics: &ast::Generics) {
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let tt = ccx.to_ty(&type_rscope(region_parameterization), v.node.ty);
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
/* add the field to the tcache */
ccx.tcx.tcache.insert(local_def(v.node.id),
......@@ -575,13 +583,14 @@ pub struct ConvertedMethod {
pub fn convert_methods(ccx: &CrateCtxt,
ms: &[@ast::method],
rp: Option<ty::region_variance>,
rcvr_bounds: @~[ty::param_bounds])
rcvr_bounds: @~[ty::param_bounds],
rcvr_generics: &ast::Generics)
-> ~[ConvertedMethod] {
let tcx = ccx.tcx;
do vec::map(ms) |m| {
let bounds = ty_param_bounds(ccx, &m.generics);
let mty = ty_of_method(ccx, *m, rp);
let mty = ty_of_method(ccx, *m, rp, rcvr_generics, &m.generics);
let fty = ty::mk_bare_fn(tcx, copy mty.fty);
tcx.tcache.insert(
local_def(m.id),
......@@ -633,7 +642,9 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
}
ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, generics);
let selfty = ccx.to_ty(&type_rscope(rp), selfty);
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id),
ty_param_bounds_and_ty {
......@@ -642,7 +653,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
ty: selfty});
// XXX: Bad copy of `ms` below.
let cms = convert_methods(ccx, *ms, rp, i_bounds);
let cms = convert_methods(ccx, *ms, rp, i_bounds, generics);
for trait_ref.each |t| {
check_methods_against_trait(ccx, generics, rp, selfty, *t, cms);
}
......@@ -653,12 +664,12 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
it.id, ppaux::ty_to_str(tcx, tpt.ty));
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id, tpt.ty);
ensure_supertraits(ccx, it.id, it.span, rp, *supertraits);
ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics);
let (_, provided_methods) =
split_trait_methods(*trait_methods);
let (bounds, _) = mk_substs(ccx, generics, rp);
let _ = convert_methods(ccx, provided_methods, rp, bounds);
let _ = convert_methods(ccx, provided_methods, rp, bounds, generics);
}
ast::item_struct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
......@@ -694,12 +705,17 @@ pub fn convert_struct(ccx: &CrateCtxt,
let tcx = ccx.tcx;
for struct_def.dtor.each |dtor| {
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
// Write the dtor type
let t_dtor = ty::mk_bare_fn(
tcx,
astconv::ty_of_bare_fn(
ccx, &type_rscope(rp),
ast::impure_fn, ast::RustAbi,
ccx,
&type_rscope(region_parameterization),
ast::impure_fn,
ast::RustAbi,
&ast_util::dtor_dec()));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
......@@ -711,7 +727,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
// Write the type of each of the members
for struct_def.fields.each |f| {
convert_field(ccx, rp, tpt.bounds, *f);
convert_field(ccx, rp, tpt.bounds, *f, generics);
}
let (_, substs) = mk_substs(ccx, generics, rp);
let selfty = ty::mk_struct(tcx, local_def(id), substs);
......@@ -754,17 +770,23 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
pub fn ty_of_method(ccx: &CrateCtxt,
m: @ast::method,
rp: Option<ty::region_variance>) -> ty::method {
let rscope = MethodRscope {
self_ty: m.self_ty.node,
region_parameterization: rp
};
rp: Option<ty::region_variance>,
rcvr_generics: &ast::Generics,
method_generics: &ast::Generics)
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node,
rp,
rcvr_generics,
method_generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(ccx, &m.generics),
fty: astconv::ty_of_bare_fn(ccx, &rscope, m.purity,
ast::RustAbi, &m.decl),
fty: astconv::ty_of_bare_fn_ext(ccx,
&rscope,
m.purity,
ast::RustAbi,
&m.decl,
rscope.region_param_names()),
self_ty: m.self_ty.node,
vis: m.vis,
def_id: local_def(m.id)
......@@ -774,17 +796,19 @@ pub fn ty_of_method(ccx: &CrateCtxt,
pub fn ty_of_ty_method(self: &CrateCtxt,
m: &ast::ty_method,
rp: Option<ty::region_variance>,
id: ast::def_id) -> ty::method {
let rscope = MethodRscope {
self_ty: m.self_ty.node,
region_parameterization: rp
};
id: ast::def_id,
generics: &ast::Generics)
-> ty::method {
let rscope = MethodRscope::new(m.self_ty.node, rp, generics, &m.generics);
ty::method {
ident: m.ident,
tps: ty_param_bounds(self, &m.generics),
fty: astconv::ty_of_bare_fn(self, &rscope, m.purity,
ast::RustAbi, &m.decl),
fty: astconv::ty_of_bare_fn_ext(self,
&rscope,
m.purity,
ast::RustAbi,
&m.decl,
rscope.region_param_names()),
// assume public, because this is only invoked on trait methods
self_ty: m.self_ty.node,
vis: ast::public,
......@@ -797,13 +821,17 @@ pub fn ty_of_ty_method(self: &CrateCtxt,
it's bound to a valid trait type. Returns the def_id for the defining
trait. Fails if the type is a type other than an trait type.
*/
pub fn instantiate_trait_ref(ccx: &CrateCtxt, t: @ast::trait_ref,
rp: Option<ty::region_variance>)
pub fn instantiate_trait_ref(ccx: &CrateCtxt,
t: @ast::trait_ref,
rp: Option<ty::region_variance>,
generics: &ast::Generics)
-> (ast::def_id, ty_param_substs_and_ty) {
let sp = t.path.span, err = ~"can only implement trait types",
sess = ccx.tcx.sess;
let rp = RegionParameterization::from_variance_and_generics(rp, generics);
let rscope = type_rscope(rp);
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
......@@ -841,8 +869,13 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
ast::item_fn(ref decl, purity, ref generics, _) => {
let bounds = ty_param_bounds(ccx, generics);
let tofd = astconv::ty_of_bare_fn(ccx, &empty_rscope, purity,
ast::RustAbi, decl);
let region_param_names = RegionParamNames::from_generics(generics);
let tofd = astconv::ty_of_bare_fn_ext(ccx,
&empty_rscope,
purity,
ast::RustAbi,
decl,
region_param_names);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: None,
......@@ -862,9 +895,11 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
}
let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let tpt = {
let ty = {
let t0 = ccx.to_ty(&type_rscope(rp), t);
let t0 = ccx.to_ty(&type_rscope(region_parameterization), t);
// Do not associate a def id with a named, parameterized type
// like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to
......@@ -1007,7 +1042,8 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
generics: &ast::Generics)
-> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(ccx, generics);
let rb = in_binding_rscope(&empty_rscope);
let region_param_names = RegionParamNames::from_generics(generics);
let rb = in_binding_rscope_ext(&empty_rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) );
let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
......
......@@ -16,6 +16,9 @@
use core::result;
use syntax::ast;
use syntax::codemap::span;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax::parse::token::special_idents;
pub struct RegionError {
msg: ~str,
......@@ -47,10 +50,130 @@ fn named_region(&self, _span: span, _id: ast::ident)
}
}
pub struct RegionParamNames(OptVec<ast::ident>);
impl RegionParamNames {
fn has_self(&self) -> bool {
self.has_ident(special_idents::self_)
}
fn has_ident(&self, ident: ast::ident) -> bool {
for self.each |region_param_name| {
if *region_param_name == ident {
return true;
}
}
false
}
pub fn add_generics(&mut self, generics: &ast::Generics) {
match generics.lifetimes {
opt_vec::Empty => {}
opt_vec::Vec(ref new_lifetimes) => {
match **self {
opt_vec::Empty => {
*self = RegionParamNames(
opt_vec::Vec(new_lifetimes.map(|lt| lt.ident)));
}
opt_vec::Vec(ref mut existing_lifetimes) => {
for new_lifetimes.each |new_lifetime| {
existing_lifetimes.push(new_lifetime.ident);
}
}
}
}
}
}
// Convenience function to produce the error for an unresolved name. The
// optional argument specifies a custom replacement.
pub fn undeclared_name(custom_replacement: Option<ty::Region>)
-> Result<ty::Region, RegionError> {
let replacement = match custom_replacement {
None => ty::re_bound(ty::br_self),
Some(custom_replacement) => custom_replacement
};
Err(RegionError {
msg: ~"this lifetime must be declared",
replacement: replacement
})
}
pub fn from_generics(generics: &ast::Generics) -> RegionParamNames {
match generics.lifetimes {
opt_vec::Empty => RegionParamNames(opt_vec::Empty),
opt_vec::Vec(ref lifetimes) => {
RegionParamNames(opt_vec::Vec(lifetimes.map(|lt| lt.ident)))
}
}
}
pub fn from_lifetimes(lifetimes: &opt_vec::OptVec<ast::Lifetime>)
-> RegionParamNames {
match *lifetimes {
opt_vec::Empty => RegionParamNames::new(),
opt_vec::Vec(ref v) => {
RegionParamNames(opt_vec::Vec(v.map(|lt| lt.ident)))
}
}
}
fn new() -> RegionParamNames {
RegionParamNames(opt_vec::Empty)
}
}
struct RegionParameterization {
variance: ty::region_variance,
region_param_names: RegionParamNames,
}
impl RegionParameterization {
pub fn from_variance_and_generics(variance: Option<ty::region_variance>,
generics: &ast::Generics)
-> Option<RegionParameterization> {
match variance {
None => None,
Some(variance) => {
Some(RegionParameterization {
variance: variance,
region_param_names:
RegionParamNames::from_generics(generics),
})
}
}
}
}
pub struct MethodRscope {
self_ty: ast::self_ty_,
region_parameterization: Option<ty::region_variance>
variance: Option<ty::region_variance>,
region_param_names: RegionParamNames,
}
impl MethodRscope {
// `generics` here refers to the generics of the outer item (impl or
// trait).
pub fn new(self_ty: ast::self_ty_,
variance: Option<ty::region_variance>,
rcvr_generics: &ast::Generics,
method_generics: &ast::Generics)
-> MethodRscope {
let mut region_param_names =
RegionParamNames::from_generics(rcvr_generics);
region_param_names.add_generics(method_generics);
MethodRscope {
self_ty: self_ty,
variance: variance,
region_param_names: region_param_names
}
}
pub fn region_param_names(&self) -> RegionParamNames {
copy self.region_param_names
}
}
impl region_scope for MethodRscope {
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
result::Err(RegionError {
......@@ -59,12 +182,26 @@ fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
})
}
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
fail_unless!(self.region_parameterization.is_some() ||
self.self_ty.is_borrowed());
fail_unless!(self.variance.is_some() || self.self_ty.is_borrowed());
match self.variance {
None => {} // must be borrowed self, so this is OK
Some(_) => {
if !self.self_ty.is_borrowed() &&
!self.region_param_names.has_self() {
return Err(RegionError {
msg: ~"the `self` lifetime must be declared",
replacement: ty::re_bound(ty::br_self)
})
}
}
}
result::Ok(ty::re_bound(ty::br_self))
}
fn named_region(&self, span: span, id: ast::ident)
-> Result<ty::Region, RegionError> {
if !self.region_param_names.has_ident(id) {
return RegionParamNames::undeclared_name(None);
}
do empty_rscope.named_region(span, id).chain_err |_e| {
result::Err(RegionError {
msg: ~"lifetime is not in scope",
......@@ -74,7 +211,7 @@ fn named_region(&self, span: span, id: ast::ident)
}
}
pub struct type_rscope(Option<ty::region_variance>);
pub struct type_rscope(Option<RegionParameterization>);
impl type_rscope {
priv fn replacement(&self) -> ty::Region {
......@@ -93,17 +230,29 @@ fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
})
}
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
// if the self region is used, region parameterization should
// have inferred that this type is RP
fail_unless!(self.is_some());
match **self {
None => {
// if the self region is used, region parameterization should
// have inferred that this type is RP
fail!(~"region parameterization should have inferred that \
this type is RP");
}
Some(ref region_parameterization) => {
if !region_parameterization.region_param_names.has_self() {
return Err(RegionError {
msg: ~"the `self` lifetime must be declared",
replacement: ty::re_bound(ty::br_self)
})
}
}
}
result::Ok(ty::re_bound(ty::br_self))
}
fn named_region(&self, span: span, id: ast::ident)
-> Result<ty::Region, RegionError> {
do empty_rscope.named_region(span, id).chain_err |_e| {
result::Err(RegionError {
msg: ~"only 'self is allowed allowed as \
part of a type declaration",
msg: ~"only 'self is allowed as part of a type declaration",
replacement: self.replacement()
})
}
......@@ -121,14 +270,33 @@ pub fn bound_self_region(rp: Option<ty::region_variance>)
pub struct binding_rscope {
base: @region_scope,
anon_bindings: @mut uint,
region_param_names: RegionParamNames,
}
pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(self: &RS)
-> binding_rscope {
let base = @copy *self;
let base = base as @region_scope;
binding_rscope { base: base, anon_bindings: @mut 0 }
binding_rscope {
base: base,
anon_bindings: @mut 0,
region_param_names: RegionParamNames::new()
}
}
pub fn in_binding_rscope_ext<RS:region_scope + Copy + Durable>(
self: &RS,
+region_param_names: RegionParamNames)
-> binding_rscope {
let base = @copy *self;
let base = base as @region_scope;
binding_rscope {
base: base,
anon_bindings: @mut 0,
region_param_names: region_param_names,
}
}
impl region_scope for binding_rscope {
fn anon_region(&self, _span: span) -> Result<ty::Region, RegionError> {
let idx = *self.anon_bindings;
......@@ -143,7 +311,12 @@ fn named_region(&self,
id: ast::ident) -> Result<ty::Region, RegionError>
{
do self.base.named_region(span, id).chain_err |_e| {
result::Ok(ty::re_bound(ty::br_named(id)))
let result = ty::re_bound(ty::br_named(id));
if self.region_param_names.has_ident(id) {
result::Ok(result)
} else {
RegionParamNames::undeclared_name(Some(result))
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册