diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 4f8f600485e..dad660e8c70 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -58,13 +58,15 @@ use middle::const_eval; 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 @@ pub fn ast_ty_to_ty( 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( 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( } } +pub fn ty_of_bare_fn_ext( + 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( self: &AC, rscope: &RS, @@ -535,6 +570,7 @@ pub fn ty_of_closure( opt_lifetime: Option<@ast::Lifetime>, decl: &ast::fn_decl, expected_tys: Option, + lifetimes: &OptVec, span: span) -> ty::ClosureTy { debug!("ty_of_fn_decl"); @@ -563,7 +599,8 @@ pub fn ty_of_closure( // 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| { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 17a67838bbe..75c6bfd5d64 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -100,7 +100,7 @@ use middle::typeck::CrateCtxt; 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::{Private, Public, is_local, local_def}; 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 @@ pub fn check_expr_with_unifier(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 { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a1fcf102988..6d304247c5d 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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 @@ pub fn ensure_trait_methods(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, - 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, 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, - 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::method { - let rscope = MethodRscope { - self_ty: m.self_ty.node, - region_parameterization: rp - }; - + rp: Option, + 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, - 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) +pub fn instantiate_trait_ref(ccx: &CrateCtxt, + t: @ast::trait_ref, + rp: Option, + 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". 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); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index e29e63c41ec..135993e18a2 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -16,6 +16,9 @@ use core::result::Result; 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 @@ impl region_scope for empty_rscope { } } +pub struct RegionParamNames(OptVec); + +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) + -> Result { + 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) + -> 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, + generics: &ast::Generics) + -> Option { + 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 + variance: Option, + 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, + 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 { result::Err(RegionError { @@ -59,12 +182,26 @@ impl region_scope for MethodRscope { }) } fn self_region(&self, _span: span) -> Result { - 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 { + 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 @@ impl region_scope for MethodRscope { } } -pub struct type_rscope(Option); +pub struct type_rscope(Option); impl type_rscope { priv fn replacement(&self) -> ty::Region { @@ -93,17 +230,29 @@ impl region_scope for type_rscope { }) } fn self_region(&self, _span: span) -> Result { - // 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 { 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) pub struct binding_rscope { base: @region_scope, anon_bindings: @mut uint, + region_param_names: RegionParamNames, } pub fn in_binding_rscope(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( + 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 { let idx = *self.anon_bindings; @@ -143,7 +311,12 @@ impl region_scope for binding_rscope { id: ast::ident) -> Result { 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)) + } } } }