librustc: Require explicit lifetime binders
This commit is contained in:
parent
3b2fcf9f59
commit
15688eaf28
@ -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<AC:AstConv, RS:region_scope + Copy + Durable>(
|
||||
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::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 {
|
||||
|
@ -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<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::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<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 @@ impl region_scope for MethodRscope {
|
||||
})
|
||||
}
|
||||
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 @@ impl region_scope for MethodRscope {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl region_scope for type_rscope {
|
||||
})
|
||||
}
|
||||
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 @@ impl region_scope for binding_rscope {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user