Update region inference for traits so that a method with
explicit self doesn't incorrectly cause the entire trait to be tagged as being region-parameterized. Fixes #5224.
This commit is contained in:
parent
65986ba0c0
commit
cbfd88a486
13 changed files with 264 additions and 190 deletions
|
|
@ -16,7 +16,6 @@ use middle::ty;
|
|||
use middle::typeck;
|
||||
use util::ppaux;
|
||||
|
||||
use core::option;
|
||||
use syntax::ast::*;
|
||||
use syntax::codemap;
|
||||
use syntax::{visit, ast_util, ast_map};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use middle::typeck::method_map;
|
|||
use middle::moves;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use core::option;
|
||||
use core::uint;
|
||||
use core::vec;
|
||||
use std::sort;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use middle::ty;
|
|||
use middle::typeck;
|
||||
use util::ppaux::{ty_to_str, tys_to_str};
|
||||
|
||||
use core::option;
|
||||
use core::str;
|
||||
use core::vec;
|
||||
use std::oldmap::HashMap;
|
||||
|
|
|
|||
|
|
@ -416,9 +416,13 @@ pub struct DetermineRpCtxt {
|
|||
item_id: ast::node_id,
|
||||
|
||||
// true when we are within an item but not within a method.
|
||||
// see long discussion on region_is_relevant()
|
||||
// see long discussion on region_is_relevant().
|
||||
anon_implies_rp: bool,
|
||||
|
||||
// true when we are not within an &self method.
|
||||
// see long discussion on region_is_relevant().
|
||||
self_implies_rp: bool,
|
||||
|
||||
// encodes the context of the current type; invariant if
|
||||
// mutable, covariant otherwise
|
||||
ambient_variance: region_variance,
|
||||
|
|
@ -458,14 +462,14 @@ pub fn add_variance(+ambient_variance: region_variance,
|
|||
}
|
||||
|
||||
pub impl DetermineRpCtxt {
|
||||
fn add_variance(@mut self, variance: region_variance) -> region_variance {
|
||||
fn add_variance(&self, variance: region_variance) -> region_variance {
|
||||
add_variance(self.ambient_variance, variance)
|
||||
}
|
||||
|
||||
/// Records that item `id` is region-parameterized with the
|
||||
/// variance `variance`. If `id` was already parameterized, then
|
||||
/// the new variance is joined with the old variance.
|
||||
fn add_rp(@mut self, id: ast::node_id, variance: region_variance) {
|
||||
fn add_rp(&mut self, id: ast::node_id, variance: region_variance) {
|
||||
assert id != 0;
|
||||
let old_variance = self.region_paramd_items.find(&id);
|
||||
let joined_variance = match old_variance {
|
||||
|
|
@ -490,7 +494,7 @@ pub impl DetermineRpCtxt {
|
|||
/// `from`. Put another way, it indicates that the current item
|
||||
/// contains a value of type `from`, so if `from` is
|
||||
/// region-parameterized, so is the current item.
|
||||
fn add_dep(@mut self, from: ast::node_id) {
|
||||
fn add_dep(&mut self, from: ast::node_id) {
|
||||
debug!("add dependency from %d -> %d (%s -> %s) with variance %?",
|
||||
from, self.item_id,
|
||||
ast_map::node_id_to_str(self.ast_map, from,
|
||||
|
|
@ -515,42 +519,46 @@ pub impl DetermineRpCtxt {
|
|||
}
|
||||
|
||||
// Determines whether a reference to a region that appears in the
|
||||
// AST implies that the enclosing type is region-parameterized.
|
||||
//
|
||||
// This point is subtle. Here are four examples to make it more
|
||||
// AST implies that the enclosing type is region-parameterized (RP).
|
||||
// This point is subtle. Here are some examples to make it more
|
||||
// concrete.
|
||||
//
|
||||
// 1. impl foo for &int { ... }
|
||||
// 2. impl foo for &self/int { ... }
|
||||
// 3. impl foo for bar { fn m() -> &self/int { ... } }
|
||||
// 4. impl foo for bar { fn m() -> &int { ... } }
|
||||
// 3. impl foo for bar { fn m(@self) -> &self/int { ... } }
|
||||
// 4. impl foo for bar { fn m(&self) -> &self/int { ... } }
|
||||
// 5. impl foo for bar { fn m(&self) -> &int { ... } }
|
||||
//
|
||||
// In case 1, the anonymous region is being referenced,
|
||||
// but it appears in a context where the anonymous region
|
||||
// resolves to self, so the impl foo is region-parameterized.
|
||||
// resolves to self, so the impl foo is RP.
|
||||
//
|
||||
// In case 2, the self parameter is written explicitly.
|
||||
//
|
||||
// In case 3, the method refers to self, so that implies that the
|
||||
// impl must be region parameterized. (If the type bar is not
|
||||
// region parameterized, that is an error, because the self region
|
||||
// is effectively unconstrained, but that is detected elsewhere).
|
||||
// In case 3, the method refers to the region `self`, so that
|
||||
// implies that the impl must be region parameterized. (If the
|
||||
// type bar is not region parameterized, that is an error, because
|
||||
// the self region is effectively unconstrained, but that is
|
||||
// detected elsewhere).
|
||||
//
|
||||
// In case 4, the anonymous region is referenced, but it
|
||||
// In case 4, the method refers to the region `self`, but the
|
||||
// `self` region is bound by the `&self` receiver, and so this
|
||||
// does not require that `bar` be RP.
|
||||
//
|
||||
// In case 5, the anonymous region is referenced, but it
|
||||
// bound by the method, so it does not refer to self. This impl
|
||||
// need not be region parameterized.
|
||||
//
|
||||
// So the rules basically are: the `self` region always implies
|
||||
// that the enclosing type is region parameterized. The anonymous
|
||||
// region also does, unless it appears within a method, in which
|
||||
// case it is bound. We handle this by setting a flag
|
||||
// (anon_implies_rp) to true when we enter an item and setting
|
||||
// that flag to false when we enter a method.
|
||||
fn region_is_relevant(@mut self, r: @ast::region) -> bool {
|
||||
// Normally, & or &self implies that the enclosing item is RP.
|
||||
// However, within a function, & is always bound. Within a method
|
||||
// with &self type, &self is also bound. We detect those last two
|
||||
// cases via flags (anon_implies_rp and self_implies_rp) that are
|
||||
// true when the anon or self region implies RP.
|
||||
fn region_is_relevant(&self, r: @ast::region) -> bool {
|
||||
match r.node {
|
||||
ast::re_static => false,
|
||||
ast::re_anon => self.anon_implies_rp,
|
||||
ast::re_self => true,
|
||||
ast::re_self => self.self_implies_rp,
|
||||
ast::re_named(_) => false
|
||||
}
|
||||
}
|
||||
|
|
@ -561,7 +569,7 @@ pub impl DetermineRpCtxt {
|
|||
//
|
||||
// If the region is explicitly specified, then we follows the
|
||||
// normal rules.
|
||||
fn opt_region_is_relevant(@mut self,
|
||||
fn opt_region_is_relevant(&self,
|
||||
opt_r: Option<@ast::region>)
|
||||
-> bool {
|
||||
debug!("opt_region_is_relevant: %? (anon_implies_rp=%b)",
|
||||
|
|
@ -575,16 +583,23 @@ pub impl DetermineRpCtxt {
|
|||
fn with(@mut self,
|
||||
item_id: ast::node_id,
|
||||
anon_implies_rp: bool,
|
||||
self_implies_rp: bool,
|
||||
f: &fn()) {
|
||||
let old_item_id = self.item_id;
|
||||
let old_anon_implies_rp = self.anon_implies_rp;
|
||||
let old_self_implies_rp = self.self_implies_rp;
|
||||
self.item_id = item_id;
|
||||
self.anon_implies_rp = anon_implies_rp;
|
||||
debug!("with_item_id(%d, %b)", item_id, anon_implies_rp);
|
||||
self.self_implies_rp = self_implies_rp;
|
||||
debug!("with_item_id(%d, %b, %b)",
|
||||
item_id,
|
||||
anon_implies_rp,
|
||||
self_implies_rp);
|
||||
let _i = ::util::common::indenter();
|
||||
f();
|
||||
self.item_id = old_item_id;
|
||||
self.anon_implies_rp = old_anon_implies_rp;
|
||||
self.self_implies_rp = old_self_implies_rp;
|
||||
}
|
||||
|
||||
fn with_ambient_variance(@mut self, variance: region_variance, f: &fn()) {
|
||||
|
|
@ -598,7 +613,7 @@ pub impl DetermineRpCtxt {
|
|||
pub fn determine_rp_in_item(item: @ast::item,
|
||||
&&cx: @mut DetermineRpCtxt,
|
||||
visitor: visit::vt<@mut DetermineRpCtxt>) {
|
||||
do cx.with(item.id, true) {
|
||||
do cx.with(item.id, true, true) {
|
||||
visit::visit_item(item, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
|
@ -610,7 +625,12 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
|
|||
_: ast::node_id,
|
||||
&&cx: @mut DetermineRpCtxt,
|
||||
visitor: visit::vt<@mut DetermineRpCtxt>) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
let self_implies_rp = match fk {
|
||||
&visit::fk_method(_, _, m) => !m.self_ty.node.is_borrowed(),
|
||||
_ => true
|
||||
};
|
||||
|
||||
do cx.with(cx.item_id, false, self_implies_rp) {
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for decl.inputs.each |a| {
|
||||
(visitor.visit_ty)(a.ty, cx, visitor);
|
||||
|
|
@ -626,7 +646,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
|
|||
pub fn determine_rp_in_ty_method(ty_m: &ast::ty_method,
|
||||
&&cx: @mut DetermineRpCtxt,
|
||||
visitor: visit::vt<@mut DetermineRpCtxt>) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
do cx.with(cx.item_id, false, !ty_m.self_ty.node.is_borrowed()) {
|
||||
visit::visit_ty_method(ty_m, cx, visitor);
|
||||
}
|
||||
}
|
||||
|
|
@ -735,7 +755,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
|
|||
ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
|
||||
// fn() binds the & region, so do not consider &T types that
|
||||
// appear *inside* a fn() type to affect the enclosing item:
|
||||
do cx.with(cx.item_id, false) {
|
||||
do cx.with(cx.item_id, false, true) {
|
||||
// parameters are contravariant
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for decl.inputs.each |a| {
|
||||
|
|
@ -796,6 +816,7 @@ pub fn determine_rp_in_crate(sess: Session,
|
|||
worklist: ~[],
|
||||
item_id: 0,
|
||||
anon_implies_rp: false,
|
||||
self_implies_rp: true,
|
||||
ambient_variance: rv_covariant
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ use core::hash;
|
|||
use core::int;
|
||||
use core::io;
|
||||
use core::libc::{c_uint, c_ulonglong};
|
||||
use core::option;
|
||||
use core::uint;
|
||||
use std::oldmap::HashMap;
|
||||
use std::{oldmap, time, list};
|
||||
|
|
|
|||
|
|
@ -69,12 +69,11 @@ use syntax::print::pprust::path_to_str;
|
|||
use util::common::indenter;
|
||||
|
||||
pub trait AstConv {
|
||||
fn tcx(@mut self) -> ty::ctxt;
|
||||
fn ccx(@mut self) -> @mut CrateCtxt;
|
||||
fn get_item_ty(@mut self, id: ast::def_id) -> ty::ty_param_bounds_and_ty;
|
||||
fn tcx(&self) -> ty::ctxt;
|
||||
fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty;
|
||||
|
||||
// what type should we use when a type is omitted?
|
||||
fn ty_infer(@mut self, span: span) -> ty::t;
|
||||
fn ty_infer(&self, span: span) -> ty::t;
|
||||
}
|
||||
|
||||
pub fn get_region_reporting_err(tcx: ty::ctxt,
|
||||
|
|
@ -92,8 +91,8 @@ pub fn get_region_reporting_err(tcx: ty::ctxt,
|
|||
}
|
||||
|
||||
pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
span: span,
|
||||
a_r: @ast::region)
|
||||
-> ty::Region {
|
||||
|
|
@ -108,8 +107,8 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
|
||||
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
did: ast::def_id,
|
||||
path: @ast::path)
|
||||
-> ty_param_substs_and_ty {
|
||||
|
|
@ -164,8 +163,8 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
|
||||
pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
did: ast::def_id,
|
||||
path: @ast::path,
|
||||
path_id: ast::node_id)
|
||||
|
|
@ -189,11 +188,11 @@ pub const NO_TPS: uint = 2;
|
|||
// Parses the programmer's textual representation of a type into our
|
||||
// internal notion of a type. `getter` is a function that returns the type
|
||||
// corresponding to a definition ID:
|
||||
pub fn ast_ty_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC, rscope: RS, &&ast_ty: @ast::Ty) -> ty::t {
|
||||
pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
|
||||
self: &AC, rscope: &RS, &&ast_ty: @ast::Ty) -> ty::t {
|
||||
|
||||
fn ast_mt_to_mt<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC, rscope: RS, mt: ast::mt) -> ty::mt {
|
||||
fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Copy + Durable>(
|
||||
self: &AC, rscope: &RS, mt: ast::mt) -> ty::mt {
|
||||
|
||||
ty::mt {ty: ast_ty_to_ty(self, rscope, mt.ty), mutbl: mt.mutbl}
|
||||
}
|
||||
|
|
@ -202,8 +201,8 @@ pub fn ast_ty_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
// If a_seq_ty is a str or a vec, make it an estr/evec.
|
||||
// Also handle function sigils and first-class trait types.
|
||||
fn mk_pointer<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
a_seq_ty: ast::mt,
|
||||
vst: ty::vstore,
|
||||
constr: fn(ty::mt) -> ty::t) -> ty::t
|
||||
|
|
@ -316,7 +315,8 @@ pub fn ast_ty_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
ast::ty_rptr(region, mt) => {
|
||||
let r = ast_region_to_region(self, rscope, ast_ty.span, region);
|
||||
mk_pointer(self, in_anon_rscope(rscope, r), mt, ty::vstore_slice(r),
|
||||
let anon_rscope = in_anon_rscope(rscope, r);
|
||||
mk_pointer(self, &anon_rscope, mt, ty::vstore_slice(r),
|
||||
|tmt| ty::mk_rptr(tcx, r, tmt))
|
||||
}
|
||||
ast::ty_tup(fields) => {
|
||||
|
|
@ -419,8 +419,8 @@ pub fn ast_ty_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
|
||||
pub fn ty_of_arg<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
a: ast::arg,
|
||||
expected_ty: Option<ty::arg>)
|
||||
-> ty::arg {
|
||||
|
|
@ -467,8 +467,8 @@ pub fn ty_of_arg<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
|
||||
pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
purity: ast::purity,
|
||||
abi: ast::Abi,
|
||||
decl: &ast::fn_decl)
|
||||
|
|
@ -479,10 +479,10 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
// that function type
|
||||
let rb = in_binding_rscope(rscope);
|
||||
|
||||
let input_tys = decl.inputs.map(|a| ty_of_arg(self, rb, *a, None));
|
||||
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)
|
||||
_ => ast_ty_to_ty(self, &rb, decl.output)
|
||||
};
|
||||
|
||||
ty::BareFnTy {
|
||||
|
|
@ -493,8 +493,8 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
}
|
||||
|
||||
pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: @mut AC,
|
||||
rscope: RS,
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
sigil: ast::Sigil,
|
||||
purity: ast::purity,
|
||||
onceness: ast::Onceness,
|
||||
|
|
@ -538,14 +538,14 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + Durable>(
|
|||
// were supplied
|
||||
if i < e.inputs.len() {Some(e.inputs[i])} else {None}
|
||||
};
|
||||
ty_of_arg(self, rb, *a, expected_arg_ty)
|
||||
ty_of_arg(self, &rb, *a, expected_arg_ty)
|
||||
};
|
||||
|
||||
let expected_ret_ty = expected_tys.map(|e| e.output);
|
||||
let output_ty = match decl.output.node {
|
||||
ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
|
||||
ast::ty_infer => self.ty_infer(decl.output.span),
|
||||
_ => ast_ty_to_ty(self, rb, decl.output)
|
||||
_ => ast_ty_to_ty(self, &rb, decl.output)
|
||||
};
|
||||
|
||||
ty::ClosureTy {
|
||||
|
|
|
|||
|
|
@ -581,7 +581,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
|
|||
let rp = ccx.tcx.region_paramd_items.find(&it.id);
|
||||
debug!("item_impl %s with id %d rp %?",
|
||||
*ccx.tcx.sess.str_of(it.ident), it.id, rp);
|
||||
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
|
||||
let self_ty = ccx.to_ty(&rscope::type_rscope(rp), ty);
|
||||
for ms.each |m| {
|
||||
check_method(ccx, *m, self_ty, local_def(it.id));
|
||||
}
|
||||
|
|
@ -636,21 +636,20 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
|
|||
}
|
||||
|
||||
impl AstConv for FnCtxt {
|
||||
fn tcx(@mut self) -> ty::ctxt { self.ccx.tcx }
|
||||
fn ccx(@mut self) -> @mut CrateCtxt { self.ccx }
|
||||
fn tcx(&self) -> ty::ctxt { self.ccx.tcx }
|
||||
|
||||
fn get_item_ty(@mut self, id: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
ty::lookup_item_type(self.tcx(), id)
|
||||
}
|
||||
|
||||
fn ty_infer(@mut self, _span: span) -> ty::t {
|
||||
fn ty_infer(&self, _span: span) -> ty::t {
|
||||
self.infcx().next_ty_var()
|
||||
}
|
||||
}
|
||||
|
||||
pub impl FnCtxt {
|
||||
fn infcx(@mut self) -> @mut infer::InferCtxt { self.inh.infcx }
|
||||
fn search_in_scope_regions(@mut self,
|
||||
fn infcx(&self) -> @mut infer::InferCtxt { self.inh.infcx }
|
||||
fn search_in_scope_regions(&self,
|
||||
br: ty::bound_region)
|
||||
-> Result<ty::Region, ~str> {
|
||||
let in_scope_regions = self.in_scope_regions;
|
||||
|
|
@ -669,25 +668,17 @@ pub impl FnCtxt {
|
|||
}
|
||||
}
|
||||
|
||||
impl region_scope for @mut FnCtxt {
|
||||
pure fn anon_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
// XXX: Unsafe to work around purity
|
||||
unsafe {
|
||||
result::Ok(self.infcx().next_region_var_nb(span))
|
||||
}
|
||||
impl region_scope for FnCtxt {
|
||||
fn anon_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
result::Ok(self.infcx().next_region_var_nb(span))
|
||||
}
|
||||
pure fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
// XXX: Unsafe to work around purity
|
||||
unsafe {
|
||||
self.search_in_scope_regions(ty::br_self)
|
||||
}
|
||||
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
self.search_in_scope_regions(ty::br_self)
|
||||
}
|
||||
pure fn named_region(&self, _span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
// XXX: Unsafe to work around purity
|
||||
unsafe {
|
||||
self.search_in_scope_regions(ty::br_named(id))
|
||||
}
|
||||
fn named_region(&self,
|
||||
_span: span,
|
||||
id: ast::ident) -> Result<ty::Region, ~str> {
|
||||
self.search_in_scope_regions(ty::br_named(id))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -710,7 +701,7 @@ pub impl FnCtxt {
|
|||
pprust::expr_to_str(expr, self.tcx().sess.intr()))
|
||||
}
|
||||
|
||||
fn block_region(@mut self) -> ty::Region {
|
||||
fn block_region(&self) -> ty::Region {
|
||||
ty::re_scope(self.region_lb)
|
||||
}
|
||||
|
||||
|
|
@ -1076,7 +1067,7 @@ pub fn impl_self_ty(vcx: &VtableContext,
|
|||
}, _)) => {
|
||||
(ts.ty_params.len(),
|
||||
region_param,
|
||||
vcx.ccx.to_ty(rscope::type_rscope(region_param), st))
|
||||
vcx.ccx.to_ty(&rscope::type_rscope(region_param), st))
|
||||
}
|
||||
Some(ast_map::node_item(@ast::item {
|
||||
node: ast::item_struct(_, ref ts),
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ use util::common::{indenter, pluralize};
|
|||
use util::ppaux;
|
||||
|
||||
use core::dvec;
|
||||
use core::option;
|
||||
use core::vec;
|
||||
use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
|
||||
use syntax::ast;
|
||||
|
|
@ -108,24 +107,24 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
|
|||
visit::visit_crate(
|
||||
*crate, (),
|
||||
visit::mk_simple_visitor(@visit::SimpleVisitor {
|
||||
visit_item: |a|convert(ccx, a),
|
||||
visit_item: |a| convert(ccx, a),
|
||||
visit_foreign_item: |a|convert_foreign(ccx, a),
|
||||
.. *visit::default_simple_visitor()
|
||||
}));
|
||||
}
|
||||
|
||||
pub impl @mut CrateCtxt {
|
||||
fn to_ty<RS:region_scope + Copy + Durable>(rs: RS, ast_ty: @ast::Ty)
|
||||
-> ty::t {
|
||||
impl CrateCtxt {
|
||||
fn to_ty<RS:region_scope + Copy + Durable>(
|
||||
&self, rs: &RS, ast_ty: @ast::Ty) -> ty::t
|
||||
{
|
||||
ast_ty_to_ty(self, rs, ast_ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl AstConv for CrateCtxt {
|
||||
fn tcx(@mut self) -> ty::ctxt { self.tcx }
|
||||
fn ccx(@mut self) -> @mut CrateCtxt { self }
|
||||
fn tcx(&self) -> ty::ctxt { self.tcx }
|
||||
|
||||
fn get_item_ty(@mut self, id: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty {
|
||||
if id.crate != ast::local_crate {
|
||||
csearch::get_type(self.tcx, id)
|
||||
} else {
|
||||
|
|
@ -144,13 +143,13 @@ impl AstConv for CrateCtxt {
|
|||
}
|
||||
}
|
||||
|
||||
fn ty_infer(@mut self, span: span) -> ty::t {
|
||||
fn ty_infer(&self, span: span) -> ty::t {
|
||||
self.tcx.sess.span_bug(span,
|
||||
~"found `ty_infer` in unexpected place");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
|
||||
pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||
enum_ty: ty::t,
|
||||
variants: &[ast::variant],
|
||||
generics: &ast::Generics,
|
||||
|
|
@ -165,7 +164,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
|
|||
match variant.node.kind {
|
||||
ast::tuple_variant_kind(ref args) if args.len() > 0 => {
|
||||
let rs = type_rscope(rp);
|
||||
let input_tys = args.map(|va| ccx.to_ty(rs, va.ty));
|
||||
let input_tys = args.map(|va| ccx.to_ty(&rs, va.ty));
|
||||
result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
|
||||
}
|
||||
|
||||
|
|
@ -217,17 +216,17 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
|
||||
pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
||||
id: ast::node_id,
|
||||
trait_ty: ty::t) {
|
||||
fn store_methods<T>(ccx: @mut CrateCtxt,
|
||||
fn store_methods<T>(ccx: &CrateCtxt,
|
||||
id: ast::node_id,
|
||||
stuff: ~[T],
|
||||
f: &fn(v: &T) -> ty::method) {
|
||||
ty::store_trait_methods(ccx.tcx, id, @vec::map(stuff, f));
|
||||
}
|
||||
|
||||
fn make_static_method_ty(ccx: @mut CrateCtxt,
|
||||
fn make_static_method_ty(ccx: &CrateCtxt,
|
||||
am: &ast::ty_method,
|
||||
rp: Option<ty::region_variance>,
|
||||
m: ty::method,
|
||||
|
|
@ -308,7 +307,7 @@ pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ensure_supertraits(ccx: @mut CrateCtxt,
|
||||
pub fn ensure_supertraits(ccx: &CrateCtxt,
|
||||
id: ast::node_id,
|
||||
sp: codemap::span,
|
||||
rp: Option<ty::region_variance>,
|
||||
|
|
@ -492,7 +491,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
|
||||
pub fn check_methods_against_trait(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics,
|
||||
rp: Option<ty::region_variance>,
|
||||
selfty: ty::t,
|
||||
|
|
@ -544,11 +543,11 @@ pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
|
|||
}
|
||||
} // fn
|
||||
|
||||
pub fn convert_field(ccx: @mut 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);
|
||||
let tt = ccx.to_ty(&type_rscope(rp), 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),
|
||||
|
|
@ -566,8 +565,8 @@ pub struct ConvertedMethod {
|
|||
body_id: ast::node_id
|
||||
}
|
||||
|
||||
pub fn convert_methods(ccx: @mut CrateCtxt,
|
||||
ms: ~[@ast::method],
|
||||
pub fn convert_methods(ccx: &CrateCtxt,
|
||||
ms: &[@ast::method],
|
||||
rp: Option<ty::region_variance>,
|
||||
rcvr_bounds: @~[ty::param_bounds])
|
||||
-> ~[ConvertedMethod] {
|
||||
|
|
@ -593,7 +592,7 @@ pub fn convert_methods(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ensure_no_ty_param_bounds(ccx: @mut CrateCtxt,
|
||||
pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
|
||||
span: span,
|
||||
generics: &ast::Generics,
|
||||
thing: &static/str) {
|
||||
|
|
@ -607,7 +606,7 @@ pub fn ensure_no_ty_param_bounds(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
|
||||
pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
|
||||
let tcx = ccx.tcx;
|
||||
let rp = tcx.region_paramd_items.find(&it.id);
|
||||
debug!("convert: item %s with id %d rp %?",
|
||||
|
|
@ -627,7 +626,7 @@ pub fn convert(ccx: @mut 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 selfty = ccx.to_ty(&type_rscope(rp), selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
tcx.tcache.insert(local_def(it.id),
|
||||
ty_param_bounds_and_ty {
|
||||
|
|
@ -636,7 +635,7 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
|
|||
ty: selfty});
|
||||
|
||||
// XXX: Bad copy of `ms` below.
|
||||
let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds);
|
||||
let cms = convert_methods(ccx, *ms, rp, i_bounds);
|
||||
for trait_ref.each |t| {
|
||||
check_methods_against_trait(ccx, generics, rp, selfty,
|
||||
*t, /*bad*/copy cms);
|
||||
|
|
@ -680,7 +679,7 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn convert_struct(ccx: @mut CrateCtxt,
|
||||
pub fn convert_struct(ccx: &CrateCtxt,
|
||||
rp: Option<ty::region_variance>,
|
||||
struct_def: @ast::struct_def,
|
||||
generics: &ast::Generics,
|
||||
|
|
@ -693,7 +692,7 @@ pub fn convert_struct(ccx: @mut CrateCtxt,
|
|||
let t_dtor = ty::mk_bare_fn(
|
||||
tcx,
|
||||
astconv::ty_of_bare_fn(
|
||||
ccx, type_rscope(rp),
|
||||
ccx, &type_rscope(rp),
|
||||
ast::impure_fn, ast::RustAbi,
|
||||
&ast_util::dtor_dec()));
|
||||
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
|
||||
|
|
@ -738,7 +737,7 @@ pub fn convert_struct(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn convert_foreign(ccx: @mut CrateCtxt, i: @ast::foreign_item) {
|
||||
pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
|
||||
// As above, this call populates the type table with the converted
|
||||
// type of the foreign item. We simply write it into the node type
|
||||
// table.
|
||||
|
|
@ -747,13 +746,18 @@ pub fn convert_foreign(ccx: @mut CrateCtxt, i: @ast::foreign_item) {
|
|||
ccx.tcx.tcache.insert(local_def(i.id), tpt);
|
||||
}
|
||||
|
||||
pub fn ty_of_method(ccx: @mut CrateCtxt,
|
||||
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
|
||||
};
|
||||
|
||||
ty::method {
|
||||
ident: m.ident,
|
||||
tps: ty_param_bounds(ccx, &m.generics),
|
||||
fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity,
|
||||
fty: astconv::ty_of_bare_fn(ccx, &rscope, m.purity,
|
||||
ast::RustAbi, &m.decl),
|
||||
self_ty: m.self_ty.node,
|
||||
vis: m.vis,
|
||||
|
|
@ -761,14 +765,19 @@ pub fn ty_of_method(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_ty_method(self: @mut 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
|
||||
};
|
||||
|
||||
ty::method {
|
||||
ident: m.ident,
|
||||
tps: ty_param_bounds(self, &m.generics),
|
||||
fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity,
|
||||
fty: astconv::ty_of_bare_fn(self, &rscope, m.purity,
|
||||
ast::RustAbi, &m.decl),
|
||||
// assume public, because this is only invoked on trait methods
|
||||
self_ty: m.self_ty.node,
|
||||
|
|
@ -782,7 +791,7 @@ pub fn ty_of_ty_method(self: @mut 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: @mut CrateCtxt, t: @ast::trait_ref,
|
||||
pub fn instantiate_trait_ref(ccx: &CrateCtxt, t: @ast::trait_ref,
|
||||
rp: Option<ty::region_variance>)
|
||||
-> (ast::def_id, ty_param_substs_and_ty) {
|
||||
|
||||
|
|
@ -793,7 +802,7 @@ pub fn instantiate_trait_ref(ccx: @mut CrateCtxt, t: @ast::trait_ref,
|
|||
|
||||
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
|
||||
ast::def_ty(t_id) => {
|
||||
let tpt = astconv::ast_path_to_ty(ccx, rscope, t_id, t.path,
|
||||
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path,
|
||||
t.ref_id);
|
||||
match ty::get(tpt.ty).sty {
|
||||
ty::ty_trait(*) => {
|
||||
|
|
@ -806,7 +815,7 @@ pub fn instantiate_trait_ref(ccx: @mut CrateCtxt, t: @ast::trait_ref,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
|
||||
pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
|
||||
-> ty::ty_param_bounds_and_ty {
|
||||
let def_id = local_def(it.id);
|
||||
let tcx = ccx.tcx;
|
||||
|
|
@ -817,14 +826,14 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
|
|||
let rp = tcx.region_paramd_items.find(&it.id);
|
||||
match it.node {
|
||||
ast::item_const(t, _) => {
|
||||
let typ = ccx.to_ty(empty_rscope, t);
|
||||
let typ = ccx.to_ty(&empty_rscope, t);
|
||||
let tpt = no_params(typ);
|
||||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
return tpt;
|
||||
}
|
||||
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,
|
||||
let tofd = astconv::ty_of_bare_fn(ccx, &empty_rscope, purity,
|
||||
ast::RustAbi, decl);
|
||||
let tpt = ty_param_bounds_and_ty {
|
||||
bounds: bounds,
|
||||
|
|
@ -847,7 +856,7 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
|
|||
let rp = tcx.region_paramd_items.find(&it.id);
|
||||
let tpt = {
|
||||
let ty = {
|
||||
let t0 = ccx.to_ty(type_rscope(rp), t);
|
||||
let t0 = ccx.to_ty(&type_rscope(rp), 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
|
||||
|
|
@ -906,23 +915,21 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item)
|
||||
pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item)
|
||||
-> ty::ty_param_bounds_and_ty {
|
||||
match /*bad*/copy it.node {
|
||||
match it.node {
|
||||
ast::foreign_item_fn(ref fn_decl, _, ref generics) => {
|
||||
ty_of_foreign_fn_decl(
|
||||
ccx,
|
||||
fn_decl,
|
||||
local_def(it.id),
|
||||
generics
|
||||
)
|
||||
ty_of_foreign_fn_decl(ccx,
|
||||
fn_decl,
|
||||
local_def(it.id),
|
||||
generics)
|
||||
}
|
||||
ast::foreign_item_const(t) => {
|
||||
let rb = in_binding_rscope(empty_rscope);
|
||||
let rb = in_binding_rscope(&empty_rscope);
|
||||
ty::ty_param_bounds_and_ty {
|
||||
bounds: @~[],
|
||||
region_param: None,
|
||||
ty: ast_ty_to_ty(ccx, rb, t)
|
||||
ty: ast_ty_to_ty(ccx, &rb, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -932,14 +939,14 @@ pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item)
|
|||
// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can
|
||||
// either be user-defined traits, or one of the four built-in traits (formerly
|
||||
// known as kinds): Const, Copy, Durable, and Send.
|
||||
pub fn compute_bounds(ccx: @mut CrateCtxt,
|
||||
pub fn compute_bounds(ccx: &CrateCtxt,
|
||||
ast_bounds: @OptVec<ast::TyParamBound>)
|
||||
-> ty::param_bounds {
|
||||
@ast_bounds.flat_map_to_vec(|b| {
|
||||
match b {
|
||||
&TraitTyParamBound(b) => {
|
||||
let li = &ccx.tcx.lang_items;
|
||||
let ity = ast_ty_to_ty(ccx, empty_rscope, b);
|
||||
let ity = ast_ty_to_ty(ccx, &empty_rscope, b);
|
||||
match ty::get(ity).sty {
|
||||
ty::ty_trait(did, _, _) => {
|
||||
if did == li.owned_trait() {
|
||||
|
|
@ -968,7 +975,7 @@ pub fn compute_bounds(ccx: @mut CrateCtxt,
|
|||
})
|
||||
}
|
||||
|
||||
pub fn ty_param_bounds(ccx: @mut CrateCtxt,
|
||||
pub fn ty_param_bounds(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics)
|
||||
-> @~[ty::param_bounds] {
|
||||
@do generics.ty_params.map_to_vec |param| {
|
||||
|
|
@ -983,15 +990,15 @@ pub fn ty_param_bounds(ccx: @mut CrateCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
|
||||
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||
decl: &ast::fn_decl,
|
||||
def_id: ast::def_id,
|
||||
generics: &ast::Generics)
|
||||
-> ty::ty_param_bounds_and_ty {
|
||||
let bounds = ty_param_bounds(ccx, generics);
|
||||
let rb = in_binding_rscope(empty_rscope);
|
||||
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);
|
||||
let rb = in_binding_rscope(&empty_rscope);
|
||||
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);
|
||||
|
||||
let t_fn = ty::mk_bare_fn(
|
||||
ccx.tcx,
|
||||
|
|
@ -1009,7 +1016,7 @@ pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
|
|||
return tpt;
|
||||
}
|
||||
|
||||
pub fn mk_generics(ccx: @mut CrateCtxt, generics: &ast::Generics)
|
||||
pub fn mk_generics(ccx: &CrateCtxt, generics: &ast::Generics)
|
||||
-> (@~[ty::param_bounds], ~[ty::t])
|
||||
{
|
||||
let mut i = 0u;
|
||||
|
|
@ -1022,7 +1029,7 @@ pub fn mk_generics(ccx: @mut CrateCtxt, generics: &ast::Generics)
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn mk_substs(ccx: @mut CrateCtxt,
|
||||
pub fn mk_substs(ccx: &CrateCtxt,
|
||||
generics: &ast::Generics,
|
||||
rp: Option<ty::region_variance>)
|
||||
-> (@~[ty::param_bounds], ty::substs)
|
||||
|
|
|
|||
|
|
@ -18,41 +18,59 @@ use syntax::ast;
|
|||
use syntax::codemap::span;
|
||||
|
||||
pub trait region_scope {
|
||||
pure fn anon_region(&self, span: span) -> Result<ty::Region, ~str>;
|
||||
pure fn self_region(&self, span: span) -> Result<ty::Region, ~str>;
|
||||
pure fn named_region(&self, span: span, id: ast::ident)
|
||||
fn anon_region(&self, span: span) -> Result<ty::Region, ~str>;
|
||||
fn self_region(&self, span: span) -> Result<ty::Region, ~str>;
|
||||
fn named_region(&self, span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str>;
|
||||
}
|
||||
|
||||
pub enum empty_rscope { empty_rscope }
|
||||
|
||||
impl region_scope for empty_rscope {
|
||||
pure fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
result::Ok(ty::re_static)
|
||||
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
Ok(ty::re_static)
|
||||
}
|
||||
pure fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
result::Err(~"only the static region is allowed here")
|
||||
}
|
||||
pure fn named_region(&self, _span: span, _id: ast::ident)
|
||||
fn named_region(&self, _span: span, _id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
result::Err(~"only the static region is allowed here")
|
||||
}
|
||||
}
|
||||
|
||||
pub enum type_rscope = Option<ty::region_variance>;
|
||||
|
||||
impl region_scope for type_rscope {
|
||||
pure fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
match **self {
|
||||
Some(_) => result::Ok(ty::re_bound(ty::br_self)),
|
||||
None => result::Err(~"to use region types here, the containing \
|
||||
type must be declared with a region bound")
|
||||
pub struct MethodRscope {
|
||||
self_ty: ast::self_ty_,
|
||||
region_parameterization: Option<ty::region_variance>
|
||||
}
|
||||
impl region_scope for MethodRscope {
|
||||
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
result::Err(~"anonymous region types are not permitted here")
|
||||
}
|
||||
fn self_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
assert self.region_parameterization.is_some() ||
|
||||
self.self_ty.is_borrowed();
|
||||
result::Ok(ty::re_bound(ty::br_self))
|
||||
}
|
||||
fn named_region(&self, span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
do empty_rscope.named_region(span, id).chain_err |_e| {
|
||||
result::Err(~"region is not in scope here")
|
||||
}
|
||||
}
|
||||
pure fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
}
|
||||
|
||||
pub enum type_rscope = Option<ty::region_variance>;
|
||||
impl region_scope for type_rscope {
|
||||
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
// if the anon or self region is used, region parameterization should
|
||||
// have inferred that this type is RP
|
||||
assert self.is_some();
|
||||
result::Ok(ty::re_bound(ty::br_self))
|
||||
}
|
||||
fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
self.anon_region(span)
|
||||
}
|
||||
pure fn named_region(&self, span: span, id: ast::ident)
|
||||
fn named_region(&self, span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
do empty_rscope.named_region(span, id).chain_err |_e| {
|
||||
result::Err(~"named regions other than `self` are not \
|
||||
|
|
@ -70,50 +88,55 @@ pub fn bound_self_region(rp: Option<ty::region_variance>)
|
|||
}
|
||||
|
||||
pub struct anon_rscope { anon: ty::Region, base: @region_scope }
|
||||
pub fn in_anon_rscope<RS:region_scope + Copy + Durable>(self: RS,
|
||||
r: ty::Region)
|
||||
-> @anon_rscope {
|
||||
@anon_rscope {anon: r, base: @self as @region_scope}
|
||||
pub fn in_anon_rscope<RS:region_scope + Copy + Durable>(
|
||||
self: &RS,
|
||||
r: ty::Region) -> anon_rscope
|
||||
{
|
||||
let base = @(copy *self) as @region_scope;
|
||||
anon_rscope {anon: r, base: base}
|
||||
}
|
||||
|
||||
impl region_scope for @anon_rscope {
|
||||
pure fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
impl region_scope for anon_rscope {
|
||||
fn anon_region(&self,
|
||||
_span: span) -> Result<ty::Region, ~str>
|
||||
{
|
||||
result::Ok(self.anon)
|
||||
}
|
||||
pure fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
fn self_region(&self,
|
||||
span: span) -> Result<ty::Region, ~str>
|
||||
{
|
||||
self.base.self_region(span)
|
||||
}
|
||||
pure fn named_region(&self, span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
fn named_region(&self,
|
||||
span: span,
|
||||
id: ast::ident) -> Result<ty::Region, ~str>
|
||||
{
|
||||
self.base.named_region(span, id)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct binding_rscope {
|
||||
base: region_scope,
|
||||
anon_bindings: uint,
|
||||
base: @region_scope,
|
||||
anon_bindings: @mut uint,
|
||||
}
|
||||
|
||||
pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(self: RS)
|
||||
-> @mut binding_rscope {
|
||||
let base = @self as @region_scope;
|
||||
@mut binding_rscope { base: base, anon_bindings: 0 }
|
||||
pub fn in_binding_rscope<RS:region_scope + Copy + Durable>(self: &RS)
|
||||
-> binding_rscope {
|
||||
let base = @(copy *self) as @region_scope;
|
||||
binding_rscope { base: base, anon_bindings: @mut 0 }
|
||||
}
|
||||
|
||||
impl region_scope for @mut binding_rscope {
|
||||
pure fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
// XXX: Unsafe to work around purity
|
||||
unsafe {
|
||||
let idx = self.anon_bindings;
|
||||
self.anon_bindings += 1;
|
||||
result::Ok(ty::re_bound(ty::br_anon(idx)))
|
||||
}
|
||||
impl region_scope for binding_rscope {
|
||||
fn anon_region(&self, _span: span) -> Result<ty::Region, ~str> {
|
||||
let idx = *self.anon_bindings;
|
||||
*self.anon_bindings += 1;
|
||||
result::Ok(ty::re_bound(ty::br_anon(idx)))
|
||||
}
|
||||
pure fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
fn self_region(&self, span: span) -> Result<ty::Region, ~str> {
|
||||
self.base.self_region(span)
|
||||
}
|
||||
pure fn named_region(&self, span: span, id: ast::ident)
|
||||
-> Result<ty::Region, ~str> {
|
||||
fn named_region(&self,
|
||||
span: span,
|
||||
id: ast::ident) -> Result<ty::Region, ~str>
|
||||
{
|
||||
do self.base.named_region(span, id).chain_err |_e| {
|
||||
result::Ok(ty::re_bound(ty::br_named(id)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1017,6 +1017,15 @@ pub enum self_ty_ {
|
|||
sty_uniq(mutability) // by-unique-pointer self: `~self`
|
||||
}
|
||||
|
||||
impl self_ty_ {
|
||||
fn is_borrowed(&self) -> bool {
|
||||
match *self {
|
||||
sty_region(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type self_ty = spanned<self_ty_>;
|
||||
|
||||
#[auto_encode]
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ use print::pprust;
|
|||
use core::char;
|
||||
use core::dvec::DVec;
|
||||
use core::io;
|
||||
use core::option;
|
||||
use core::str;
|
||||
use core::u64;
|
||||
use core::vec;
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ fn main() {
|
|||
let x: @Map<~str, ~str> = @LinearMap::new::<~str, ~str>() as
|
||||
Map::<~str, ~str>;
|
||||
let y: @Map<uint, ~str> = @x;
|
||||
//~^ ERROR mismatched types: expected `@core::container::Map/&<uint,~str>`
|
||||
//~^ ERROR mismatched types: expected `@core::container::Map<uint,~str>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// Test how region-parameterization inference
|
||||
// interacts with explicit self types.
|
||||
//
|
||||
// Issue #5224.
|
||||
|
||||
trait Getter {
|
||||
// This trait does not need to be
|
||||
// region-parameterized, because 'self
|
||||
// is bound in the self type:
|
||||
fn get(&self) -> &'self int;
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
field: int
|
||||
}
|
||||
|
||||
impl Getter for Foo {
|
||||
fn get(&self) -> &'self int { &self.field }
|
||||
}
|
||||
|
||||
fn get_int<G: Getter>(g: &G) -> int {
|
||||
*g.get()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo { field: 22 };
|
||||
assert get_int(&foo) == 22;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue