Issue #5656: Make &self not mean "&'self self"
Fixes #5656. Fixes #5541.
This commit is contained in:
parent
3322595e89
commit
49de82cdca
@ -16,7 +16,7 @@ use middle::liveness;
|
||||
use middle::pat_util;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use util::ppaux::{Repr, ty_to_str, tys_to_str};
|
||||
use util::ppaux::{Repr, ty_to_str};
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::attr::attrs_contains_name;
|
||||
|
@ -544,10 +544,6 @@ pub struct DetermineRpCtxt {
|
||||
// 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,
|
||||
@ -689,7 +685,7 @@ pub impl DetermineRpCtxt {
|
||||
false
|
||||
}
|
||||
Some(ref l) if l.ident == special_idents::self_ => {
|
||||
self.self_implies_rp
|
||||
true
|
||||
}
|
||||
Some(_) => {
|
||||
false
|
||||
@ -700,23 +696,18 @@ 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;
|
||||
self.self_implies_rp = self_implies_rp;
|
||||
debug!("with_item_id(%d, %b, %b)",
|
||||
debug!("with_item_id(%d, %b)",
|
||||
item_id,
|
||||
anon_implies_rp,
|
||||
self_implies_rp);
|
||||
anon_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()) {
|
||||
@ -730,7 +721,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, true) {
|
||||
do cx.with(item.id, true) {
|
||||
visit::visit_item(item, cx, visitor);
|
||||
}
|
||||
}
|
||||
@ -742,12 +733,7 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
|
||||
_: ast::node_id,
|
||||
&&cx: @mut DetermineRpCtxt,
|
||||
visitor: visit::vt<@mut DetermineRpCtxt>) {
|
||||
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(cx.item_id, false) {
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for decl.inputs.each |a| {
|
||||
(visitor.visit_ty)(a.ty, cx, visitor);
|
||||
@ -763,7 +749,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, !ty_m.self_ty.node.is_borrowed()) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
visit::visit_ty_method(ty_m, cx, visitor);
|
||||
}
|
||||
}
|
||||
@ -868,7 +854,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, true) {
|
||||
do cx.with(cx.item_id, false) {
|
||||
// parameters are contravariant
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for decl.inputs.each |a| {
|
||||
@ -929,7 +915,6 @@ pub fn determine_rp_in_crate(sess: Session,
|
||||
worklist: ~[],
|
||||
item_id: 0,
|
||||
anon_implies_rp: false,
|
||||
self_implies_rp: true,
|
||||
ambient_variance: rv_covariant
|
||||
};
|
||||
|
||||
|
@ -62,22 +62,7 @@ impl EffectfulSubst for ty::t {
|
||||
_ => {
|
||||
ty::fold_regions_and_ty(
|
||||
tcx, *self,
|
||||
|r| match r {
|
||||
ty::re_bound(ty::br_self) => {
|
||||
match substs.self_r {
|
||||
None => {
|
||||
tcx.sess.bug(
|
||||
fmt!("ty::subst: \
|
||||
Reference to self region when \
|
||||
given substs with no self region, \
|
||||
ty = %s",
|
||||
self.repr(tcx)));
|
||||
}
|
||||
Some(self_r) => self_r
|
||||
}
|
||||
}
|
||||
_ => r
|
||||
},
|
||||
|r| r.subst(tcx, substs),
|
||||
|t| t.effectfulSubst(tcx, substs),
|
||||
|t| t.effectfulSubst(tcx, substs))
|
||||
}
|
||||
@ -118,7 +103,7 @@ impl Subst for ty::TraitRef {
|
||||
impl Subst for ty::substs {
|
||||
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::substs {
|
||||
ty::substs {
|
||||
self_r: self.self_r,
|
||||
self_r: self.self_r.subst(tcx, substs),
|
||||
self_ty: self.self_ty.map(|typ| typ.subst(tcx, substs)),
|
||||
tps: self.tps.map(|typ| typ.subst(tcx, substs))
|
||||
}
|
||||
@ -166,6 +151,34 @@ impl Subst for ty::Generics {
|
||||
}
|
||||
}
|
||||
|
||||
impl Subst for ty::Region {
|
||||
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Region {
|
||||
// Note: This routine only handles the self region, because it
|
||||
// is only concerned with substitutions of regions that appear
|
||||
// in types. Region substitution of the bound regions that
|
||||
// appear in a function signature is done using the
|
||||
// specialized routine
|
||||
// `middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig()`.
|
||||
// As we transition to the new region syntax this distinction
|
||||
// will most likely disappear.
|
||||
match self {
|
||||
&ty::re_bound(ty::br_self) => {
|
||||
match substs.self_r {
|
||||
None => {
|
||||
tcx.sess.bug(
|
||||
fmt!("ty::Region#subst(): \
|
||||
Reference to self region when \
|
||||
given substs with no self region: %s",
|
||||
substs.repr(tcx)));
|
||||
}
|
||||
Some(self_r) => self_r
|
||||
}
|
||||
}
|
||||
_ => *self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Subst for ty::ty_param_bounds_and_ty {
|
||||
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ty_param_bounds_and_ty {
|
||||
ty::ty_param_bounds_and_ty {
|
||||
|
@ -24,8 +24,7 @@ use middle::subst::Subst;
|
||||
use middle::typeck;
|
||||
use middle;
|
||||
use util::ppaux::{note_and_explain_region, bound_region_to_str};
|
||||
use util::ppaux::{region_to_str, vstore_to_str};
|
||||
use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str};
|
||||
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
|
||||
use util::ppaux::Repr;
|
||||
use util::common::{indenter};
|
||||
|
||||
|
@ -178,15 +178,6 @@ pub struct Candidate {
|
||||
origin: method_origin,
|
||||
}
|
||||
|
||||
/**
|
||||
* How the self type should be transformed according to the form of explicit
|
||||
* self provided by the method.
|
||||
*/
|
||||
pub enum TransformTypeFlag {
|
||||
TransformTypeNormally,
|
||||
TransformTypeForObject,
|
||||
}
|
||||
|
||||
pub impl<'self> LookupContext<'self> {
|
||||
fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
|
||||
let mut self_ty = structurally_resolved_type(self.fcx,
|
||||
@ -285,13 +276,13 @@ pub impl<'self> LookupContext<'self> {
|
||||
|
||||
fn push_inherent_candidates(&self, self_ty: ty::t) {
|
||||
/*!
|
||||
*
|
||||
* Collect all inherent candidates into
|
||||
* `self.inherent_candidates`. See comment at the start of
|
||||
* the file. To find the inherent candidates, we repeatedly
|
||||
* deref the self-ty to find the "base-type". So, for
|
||||
* example, if the receiver is @@C where `C` is a struct type,
|
||||
* we'll want to find the inherent impls for `C`. */
|
||||
* we'll want to find the inherent impls for `C`.
|
||||
*/
|
||||
|
||||
let mut enum_dids = ~[];
|
||||
let mut self_ty = self_ty;
|
||||
@ -407,16 +398,9 @@ pub impl<'self> LookupContext<'self> {
|
||||
};
|
||||
let method = trait_methods[pos];
|
||||
|
||||
let (rcvr_ty, rcvr_substs) =
|
||||
self.create_rcvr_ty_and_substs_for_method(
|
||||
method.self_ty,
|
||||
rcvr_ty,
|
||||
copy bound_trait_ref.substs,
|
||||
TransformTypeNormally);
|
||||
|
||||
let cand = Candidate {
|
||||
rcvr_ty: rcvr_ty,
|
||||
rcvr_substs: rcvr_substs,
|
||||
rcvr_substs: copy bound_trait_ref.substs,
|
||||
method_ty: method,
|
||||
origin: method_param(
|
||||
method_param {
|
||||
@ -476,14 +460,8 @@ pub impl<'self> LookupContext<'self> {
|
||||
../*bad*/copy *substs
|
||||
};
|
||||
|
||||
let (rcvr_ty, rcvr_substs) =
|
||||
self.create_rcvr_ty_and_substs_for_method(method.self_ty,
|
||||
self_ty,
|
||||
rcvr_substs,
|
||||
TransformTypeForObject);
|
||||
|
||||
self.inherent_candidates.push(Candidate {
|
||||
rcvr_ty: rcvr_ty,
|
||||
rcvr_ty: self_ty,
|
||||
rcvr_substs: rcvr_substs,
|
||||
method_ty: method,
|
||||
origin: method_trait(did, index, store)
|
||||
@ -538,19 +516,13 @@ pub impl<'self> LookupContext<'self> {
|
||||
// We've found a method -- return it
|
||||
let rcvr_substs = substs {self_ty: Some(self_ty),
|
||||
..copy *substs };
|
||||
let (rcvr_ty, rcvr_substs) =
|
||||
self.create_rcvr_ty_and_substs_for_method(
|
||||
info.method_ty.self_ty,
|
||||
self_ty,
|
||||
rcvr_substs,
|
||||
TransformTypeNormally);
|
||||
let origin = if did == info.trait_def_id {
|
||||
method_self(info.trait_def_id, info.index)
|
||||
} else {
|
||||
method_super(info.trait_def_id, info.index)
|
||||
};
|
||||
self.inherent_candidates.push(Candidate {
|
||||
rcvr_ty: rcvr_ty,
|
||||
rcvr_ty: self_ty,
|
||||
rcvr_substs: rcvr_substs,
|
||||
method_ty: info.method_ty,
|
||||
origin: origin
|
||||
@ -598,13 +570,6 @@ pub impl<'self> LookupContext<'self> {
|
||||
ty: impl_ty
|
||||
} = impl_self_ty(&vcx, location_info, impl_info.did);
|
||||
|
||||
let (impl_ty, impl_substs) =
|
||||
self.create_rcvr_ty_and_substs_for_method(
|
||||
method.self_ty,
|
||||
impl_ty,
|
||||
impl_substs,
|
||||
TransformTypeNormally);
|
||||
|
||||
candidates.push(Candidate {
|
||||
rcvr_ty: impl_ty,
|
||||
rcvr_substs: impl_substs,
|
||||
@ -639,69 +604,16 @@ pub impl<'self> LookupContext<'self> {
|
||||
self_ty: None,
|
||||
tps: ~[]
|
||||
};
|
||||
let (impl_ty, impl_substs) =
|
||||
self.create_rcvr_ty_and_substs_for_method(
|
||||
method.self_ty,
|
||||
self_ty,
|
||||
dummy_substs,
|
||||
TransformTypeNormally);
|
||||
|
||||
candidates.push(Candidate {
|
||||
rcvr_ty: impl_ty,
|
||||
rcvr_substs: impl_substs,
|
||||
rcvr_ty: self_ty,
|
||||
rcvr_substs: dummy_substs,
|
||||
method_ty: method,
|
||||
origin: method_static(provided_method_info.method_info.did)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn create_rcvr_ty_and_substs_for_method(&self,
|
||||
self_decl: ast::self_ty_,
|
||||
self_ty: ty::t,
|
||||
+self_substs: ty::substs,
|
||||
transform_type: TransformTypeFlag)
|
||||
-> (ty::t, ty::substs) {
|
||||
// If the self type includes a region (like &self), we need to
|
||||
// ensure that the receiver substitutions have a self region.
|
||||
// If the receiver type does not itself contain borrowed
|
||||
// pointers, there may not be one yet.
|
||||
//
|
||||
// FIXME(#3446)--this awkward situation comes about because
|
||||
// the regions in the receiver are substituted before (and
|
||||
// differently from) those in the argument types. This
|
||||
// shouldn't really have to be.
|
||||
let rcvr_substs = {
|
||||
match self_decl {
|
||||
sty_static | sty_value |
|
||||
sty_box(_) | sty_uniq(_) => {
|
||||
self_substs
|
||||
}
|
||||
sty_region(*) if self_substs.self_r.is_some() => {
|
||||
// FIXME(#4846) ignoring expl lifetime here
|
||||
self_substs
|
||||
}
|
||||
sty_region(*) => {
|
||||
// FIXME(#4846) ignoring expl lifetime here
|
||||
substs {
|
||||
self_r:
|
||||
Some(self.infcx().next_region_var(
|
||||
self.expr.span,
|
||||
self.expr.id)),
|
||||
..self_substs
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let rcvr_ty = transform_self_type_for_method(self.tcx(),
|
||||
rcvr_substs.self_r,
|
||||
self_ty,
|
||||
self_decl,
|
||||
transform_type);
|
||||
|
||||
(rcvr_ty, rcvr_substs)
|
||||
}
|
||||
|
||||
// ______________________________________________________________________
|
||||
// Candidate selection (see comment at start of file)
|
||||
|
||||
@ -1036,20 +948,34 @@ pub impl<'self> LookupContext<'self> {
|
||||
self.enforce_trait_instance_limitations(fty, candidate);
|
||||
self.enforce_drop_trait_limitations(candidate);
|
||||
|
||||
// before we only checked whether self_ty could be a subtype
|
||||
// of rcvr_ty; now we actually make it so (this may cause
|
||||
// variables to unify etc). Since we checked beforehand, and
|
||||
// nothing has changed in the meantime, this unification
|
||||
// should never fail.
|
||||
match self.fcx.mk_subty(false, self.self_expr.span,
|
||||
self_ty, candidate.rcvr_ty) {
|
||||
result::Ok(_) => (),
|
||||
result::Err(_) => {
|
||||
self.bug(fmt!("%s was assignable to %s but now is not?",
|
||||
self.ty_to_str(self_ty),
|
||||
self.ty_to_str(candidate.rcvr_ty)));
|
||||
// static methods should never have gotten this far:
|
||||
assert!(candidate.method_ty.self_ty != sty_static);
|
||||
|
||||
let transformed_self_ty = match candidate.origin {
|
||||
method_trait(*) => {
|
||||
match candidate.method_ty.self_ty {
|
||||
sty_region(*) => {
|
||||
// FIXME(#5762) again, preserving existing
|
||||
// behavior here which (for &self) desires
|
||||
// &@Trait where @Trait is the type of the
|
||||
// receiver. Here we fetch the method's
|
||||
// transformed_self_ty which will be something
|
||||
// like &'a Self. We then perform a
|
||||
// substitution which will replace Self with
|
||||
// @Trait.
|
||||
let t = candidate.method_ty.transformed_self_ty.get();
|
||||
ty::subst(tcx, &candidate.rcvr_substs, t)
|
||||
}
|
||||
_ => {
|
||||
candidate.rcvr_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let t = candidate.method_ty.transformed_self_ty.get();
|
||||
ty::subst(tcx, &candidate.rcvr_substs, t)
|
||||
}
|
||||
};
|
||||
|
||||
// Determine the values for the type parameters of the method.
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
@ -1100,16 +1026,32 @@ pub impl<'self> LookupContext<'self> {
|
||||
fmt!("Invoking method with non-bare-fn ty: %?", s));
|
||||
}
|
||||
};
|
||||
let (_, _, fn_sig) =
|
||||
let (_, opt_transformed_self_ty, fn_sig) =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, @Nil, None, &bare_fn_ty.sig,
|
||||
tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig,
|
||||
|_br| self.fcx.infcx().next_region_var(
|
||||
self.expr.span, self.expr.id));
|
||||
let transformed_self_ty = opt_transformed_self_ty.get();
|
||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
|
||||
debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
|
||||
|
||||
let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty);
|
||||
|
||||
// before we only checked whether self_ty could be a subtype
|
||||
// of rcvr_ty; now we actually make it so (this may cause
|
||||
// variables to unify etc). Since we checked beforehand, and
|
||||
// nothing has changed in the meantime, this unification
|
||||
// should never fail.
|
||||
match self.fcx.mk_subty(false, self.self_expr.span,
|
||||
self_ty, transformed_self_ty) {
|
||||
result::Ok(_) => (),
|
||||
result::Err(_) => {
|
||||
self.bug(fmt!("%s was a subtype of %s but now is not?",
|
||||
self.ty_to_str(self_ty),
|
||||
self.ty_to_str(transformed_self_ty)));
|
||||
}
|
||||
}
|
||||
|
||||
self.fcx.write_ty(self.callee_id, fty);
|
||||
self.fcx.write_substs(self.callee_id, all_substs);
|
||||
method_map_entry {
|
||||
@ -1180,7 +1122,87 @@ pub impl<'self> LookupContext<'self> {
|
||||
debug!("is_relevant(self_ty=%s, candidate=%s)",
|
||||
self.ty_to_str(self_ty), self.cand_to_str(candidate));
|
||||
|
||||
self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok()
|
||||
// Check for calls to object methods. We resolve these differently.
|
||||
//
|
||||
// FIXME(#5762)---we don't check that an @self method is only called
|
||||
// on an @Trait object here and so forth
|
||||
match candidate.origin {
|
||||
method_trait(*) => {
|
||||
match candidate.method_ty.self_ty {
|
||||
sty_static | sty_value => {
|
||||
return false;
|
||||
}
|
||||
sty_region(*) => {
|
||||
// just echoing current behavior here, which treats
|
||||
// an &self method on an @Trait object as requiring
|
||||
// an &@Trait receiver (wacky)
|
||||
}
|
||||
sty_box(*) | sty_uniq(*) => {
|
||||
return self.fcx.can_mk_subty(self_ty,
|
||||
candidate.rcvr_ty).is_ok();
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
return match candidate.method_ty.self_ty {
|
||||
sty_static => {
|
||||
false
|
||||
}
|
||||
|
||||
sty_value => {
|
||||
self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok()
|
||||
}
|
||||
|
||||
sty_region(_, m) => {
|
||||
match ty::get(self_ty).sty {
|
||||
ty::ty_rptr(_, mt) => {
|
||||
mutability_matches(mt.mutbl, m) &&
|
||||
self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
|
||||
}
|
||||
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
sty_box(m) => {
|
||||
match ty::get(self_ty).sty {
|
||||
ty::ty_box(mt) => {
|
||||
mutability_matches(mt.mutbl, m) &&
|
||||
self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
|
||||
}
|
||||
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
sty_uniq(m) => {
|
||||
match ty::get(self_ty).sty {
|
||||
ty::ty_uniq(mt) => {
|
||||
mutability_matches(mt.mutbl, m) &&
|
||||
self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
|
||||
}
|
||||
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn mutability_matches(self_mutbl: ast::mutability,
|
||||
candidate_mutbl: ast::mutability) -> bool {
|
||||
//! True if `self_mutbl <: candidate_mutbl`
|
||||
|
||||
match (self_mutbl, candidate_mutbl) {
|
||||
(_, m_const) => true,
|
||||
(m_mutbl, m_mutbl) => true,
|
||||
(m_imm, m_imm) => true,
|
||||
(m_mutbl, m_imm) => false,
|
||||
(m_imm, m_mutbl) => false,
|
||||
(m_const, m_imm) => false,
|
||||
(m_const, m_mutbl) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
|
||||
@ -1281,45 +1303,6 @@ pub impl<'self> LookupContext<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_self_type_for_method(tcx: ty::ctxt,
|
||||
self_region: Option<ty::Region>,
|
||||
impl_ty: ty::t,
|
||||
self_type: ast::self_ty_,
|
||||
flag: TransformTypeFlag)
|
||||
-> ty::t {
|
||||
match self_type {
|
||||
sty_static => {
|
||||
tcx.sess.bug(~"calling transform_self_type_for_method on \
|
||||
static method");
|
||||
}
|
||||
sty_value => {
|
||||
impl_ty
|
||||
}
|
||||
sty_region(_, mutability) => {
|
||||
// FIXME(#4846) ignoring expl lifetime here
|
||||
mk_rptr(tcx,
|
||||
self_region.expect(~"self region missing for &self param"),
|
||||
ty::mt { ty: impl_ty, mutbl: mutability })
|
||||
}
|
||||
sty_box(mutability) => {
|
||||
match flag {
|
||||
TransformTypeNormally => {
|
||||
mk_box(tcx, ty::mt { ty: impl_ty, mutbl: mutability })
|
||||
}
|
||||
TransformTypeForObject => impl_ty
|
||||
}
|
||||
}
|
||||
sty_uniq(mutability) => {
|
||||
match flag {
|
||||
TransformTypeNormally => {
|
||||
mk_uniq(tcx, ty::mt { ty: impl_ty, mutbl: mutability })
|
||||
}
|
||||
TransformTypeForObject => impl_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> ast::rmode {
|
||||
match self_type { sty_value => by_copy, _ => by_ref }
|
||||
}
|
||||
|
@ -93,7 +93,6 @@ use middle::typeck::check::method::{AutoderefReceiver};
|
||||
use middle::typeck::check::method::{AutoderefReceiverFlag};
|
||||
use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
|
||||
use middle::typeck::check::method::{CheckTraitsOnly, DontAutoderefReceiver};
|
||||
use middle::typeck::check::method::{TransformTypeNormally};
|
||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||
use middle::typeck::check::regionmanip::relate_free_regions;
|
||||
use middle::typeck::check::vtable::{LocationInfo, VtableContext};
|
||||
@ -101,9 +100,8 @@ use middle::typeck::CrateCtxt;
|
||||
use middle::typeck::infer::{resolve_type, force_tvar};
|
||||
use middle::typeck::infer;
|
||||
use middle::typeck::rscope::bound_self_region;
|
||||
use middle::typeck::rscope::{RegionError, RegionParameterization};
|
||||
use middle::typeck::rscope::{RegionError};
|
||||
use middle::typeck::rscope::region_scope;
|
||||
use middle::typeck::rscope;
|
||||
use middle::typeck::{isr_alist, lookup_def_ccx};
|
||||
use middle::typeck::no_params;
|
||||
use middle::typeck::{require_same_types, method_map, vtable_map};
|
||||
@ -280,7 +278,7 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
|
||||
}
|
||||
|
||||
pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
+self_info: Option<SelfInfo>,
|
||||
opt_self_info: Option<SelfInfo>,
|
||||
purity: ast::purity,
|
||||
fn_sig: &ty::FnSig,
|
||||
decl: &ast::fn_decl,
|
||||
@ -307,23 +305,28 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
// First, we have to replace any bound regions in the fn and self
|
||||
// types with free ones. The free region references will be bound
|
||||
// the node_id of the body block.
|
||||
|
||||
let (isr, self_info, fn_sig) = {
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, inherited_isr, self_info, fn_sig,
|
||||
|br| ty::re_free(ty::FreeRegion {scope_id: body.node.id,
|
||||
bound_region: br}))
|
||||
let (isr, opt_self_info, fn_sig) = {
|
||||
let opt_self_ty = opt_self_info.map(|i| i.self_ty);
|
||||
let (isr, opt_self_ty, fn_sig) =
|
||||
replace_bound_regions_in_fn_sig(
|
||||
tcx, inherited_isr, opt_self_ty, fn_sig,
|
||||
|br| ty::re_free(ty::FreeRegion {scope_id: body.node.id,
|
||||
bound_region: br}));
|
||||
let opt_self_info =
|
||||
opt_self_info.map(
|
||||
|si| SelfInfo {self_ty: opt_self_ty.get(), ..*si});
|
||||
(isr, opt_self_info, fn_sig)
|
||||
};
|
||||
|
||||
relate_free_regions(tcx, self_info.map(|s| s.self_ty), &fn_sig);
|
||||
relate_free_regions(tcx, opt_self_info.map(|s| s.self_ty), &fn_sig);
|
||||
|
||||
let arg_tys = fn_sig.inputs.map(|a| a.ty);
|
||||
let ret_ty = fn_sig.output;
|
||||
|
||||
debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)",
|
||||
arg_tys.map(|a| ppaux::ty_to_str(tcx, *a)),
|
||||
debug!("check_fn(arg_tys=%?, ret_ty=%?, opt_self_ty=%?)",
|
||||
arg_tys.map(|&a| ppaux::ty_to_str(tcx, a)),
|
||||
ppaux::ty_to_str(tcx, ret_ty),
|
||||
self_info.map(|s| ppaux::ty_to_str(tcx, s.self_ty)));
|
||||
opt_self_info.map(|si| ppaux::ty_to_str(tcx, si.self_ty)));
|
||||
|
||||
// ______________________________________________________________________
|
||||
// Create the function context. This is either derived from scratch or,
|
||||
@ -348,7 +351,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
}
|
||||
};
|
||||
|
||||
gather_locals(fcx, decl, body, arg_tys, self_info);
|
||||
gather_locals(fcx, decl, body, arg_tys, opt_self_info);
|
||||
check_block_with_expected(fcx, body, Some(ret_ty));
|
||||
|
||||
// We unify the tail expr's type with the
|
||||
@ -366,7 +369,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
None => ()
|
||||
}
|
||||
|
||||
for self_info.each |self_info| {
|
||||
for opt_self_info.each |self_info| {
|
||||
fcx.write_ty(self_info.self_id, self_info.self_ty);
|
||||
}
|
||||
for vec::each2(decl.inputs, arg_tys) |input, arg| {
|
||||
@ -379,7 +382,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::blk,
|
||||
arg_tys: &[ty::t],
|
||||
self_info: Option<SelfInfo>) {
|
||||
opt_self_info: Option<SelfInfo>) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
let assign: @fn(ast::node_id, Option<ty::t>) = |nid, ty_opt| {
|
||||
@ -398,7 +401,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
};
|
||||
|
||||
// Add the self parameter
|
||||
for self_info.each |self_info| {
|
||||
for opt_self_info.each |self_info| {
|
||||
assign(self_info.self_id, Some(self_info.self_ty));
|
||||
debug!("self is assigned to %s",
|
||||
fcx.infcx().ty_to_str(
|
||||
@ -484,26 +487,22 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
}
|
||||
|
||||
pub fn check_method(ccx: @mut CrateCtxt,
|
||||
method: @ast::method,
|
||||
self_ty: ty::t)
|
||||
method: @ast::method)
|
||||
{
|
||||
let self_info = if method.self_ty.node == ast::sty_static {None} else {
|
||||
let ty = method::transform_self_type_for_method(
|
||||
ccx.tcx,
|
||||
Some(ty::re_bound(ty::br_self)),
|
||||
self_ty,
|
||||
method.self_ty.node,
|
||||
TransformTypeNormally);
|
||||
Some(SelfInfo {self_ty: ty, self_id: method.self_id,
|
||||
span: method.self_ty.span})
|
||||
};
|
||||
let method_def_id = local_def(method.id);
|
||||
let method_ty = ty::method(ccx.tcx, method_def_id);
|
||||
let opt_self_info = method_ty.transformed_self_ty.map(|&ty| {
|
||||
SelfInfo {self_ty: ty,
|
||||
self_id: method.self_id,
|
||||
span: method.self_ty.span}
|
||||
});
|
||||
|
||||
check_bare_fn(
|
||||
ccx,
|
||||
&method.decl,
|
||||
&method.body,
|
||||
method.id,
|
||||
self_info
|
||||
opt_self_info
|
||||
);
|
||||
}
|
||||
|
||||
@ -575,15 +574,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(ref generics, _, ty, ref ms) => {
|
||||
ast::item_impl(_, _, _, 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);
|
||||
check_method(ccx, *m);
|
||||
}
|
||||
}
|
||||
ast::item_trait(_, _, ref trait_methods) => {
|
||||
@ -594,8 +590,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
|
||||
// bodies to check.
|
||||
}
|
||||
provided(m) => {
|
||||
let self_ty = ty::mk_self(ccx.tcx, local_def(it.id));
|
||||
check_method(ccx, m, self_ty);
|
||||
check_method(ccx, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use middle::ty;
|
||||
use middle::typeck::check::SelfInfo;
|
||||
|
||||
use middle::typeck::isr_alist;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::region_to_str;
|
||||
@ -26,29 +26,24 @@ use std::list::Cons;
|
||||
pub fn replace_bound_regions_in_fn_sig(
|
||||
tcx: ty::ctxt,
|
||||
isr: isr_alist,
|
||||
self_info: Option<SelfInfo>,
|
||||
opt_self_ty: Option<ty::t>,
|
||||
fn_sig: &ty::FnSig,
|
||||
mapf: &fn(ty::bound_region) -> ty::Region)
|
||||
-> (isr_alist, Option<SelfInfo>, ty::FnSig)
|
||||
-> (isr_alist, Option<ty::t>, ty::FnSig)
|
||||
{
|
||||
// Take self_info apart; the self_ty part is the only one we want
|
||||
// to update here.
|
||||
let self_ty = self_info.map(|s| s.self_ty);
|
||||
let rebuild_self_info = |t| self_info.map(|s| SelfInfo{self_ty: t, ..*s});
|
||||
|
||||
let mut all_tys = ty::tys_in_fn_sig(fn_sig);
|
||||
|
||||
for self_info.each |self_info| {
|
||||
all_tys.push(self_info.self_ty);
|
||||
for opt_self_ty.each |&self_ty| {
|
||||
all_tys.push(self_ty);
|
||||
}
|
||||
|
||||
for self_ty.each |t| { all_tys.push(*t) }
|
||||
for opt_self_ty.each |&t| { all_tys.push(t) }
|
||||
|
||||
debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \
|
||||
debug!("replace_bound_regions_in_fn_sig(self_ty=%?, fn_sig=%s, \
|
||||
all_tys=%?)",
|
||||
self_ty.map(|t| ppaux::ty_to_str(tcx, *t)),
|
||||
opt_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)),
|
||||
ppaux::fn_sig_to_str(tcx, fn_sig),
|
||||
all_tys.map(|t| ppaux::ty_to_str(tcx, *t)));
|
||||
all_tys.map(|&t| ppaux::ty_to_str(tcx, t)));
|
||||
let _i = indenter();
|
||||
|
||||
let isr = do create_bound_region_mapping(tcx, isr, all_tys) |br| {
|
||||
@ -58,20 +53,15 @@ pub fn replace_bound_regions_in_fn_sig(
|
||||
let new_fn_sig = ty::fold_sig(fn_sig, |t| {
|
||||
replace_bound_regions(tcx, isr, t)
|
||||
});
|
||||
let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, *t));
|
||||
let new_self_ty = opt_self_ty.map(|&t| replace_bound_regions(tcx, isr, t));
|
||||
|
||||
debug!("result of replace_bound_regions_in_fn_sig: self_info.self_ty=%?, \
|
||||
fn_sig=%s",
|
||||
t_self.map(|t| ppaux::ty_to_str(tcx, *t)),
|
||||
debug!("result of replace_bound_regions_in_fn_sig: \
|
||||
new_self_ty=%?, \
|
||||
fn_sig=%s",
|
||||
new_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)),
|
||||
ppaux::fn_sig_to_str(tcx, &new_fn_sig));
|
||||
|
||||
// Glue updated self_ty back together with its original def_id.
|
||||
let new_self_info: Option<SelfInfo> = match t_self {
|
||||
None => None,
|
||||
Some(t) => rebuild_self_info(t)
|
||||
};
|
||||
|
||||
return (isr, new_self_info, new_fn_sig);
|
||||
return (isr, new_self_ty, new_fn_sig);
|
||||
|
||||
// Takes `isr`, a (possibly empty) mapping from in-scope region
|
||||
// names ("isr"s) to their corresponding regions; `tys`, a list of
|
||||
@ -288,4 +278,4 @@ pub fn relate_free_regions(
|
||||
}
|
||||
|
||||
debug!("<< relate_free_regions");
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use middle::resolve::Impl;
|
||||
use middle::ty::{param_ty, substs};
|
||||
use middle::ty::{param_ty};
|
||||
use middle::ty;
|
||||
use middle::typeck::check::{FnCtxt, impl_self_ty};
|
||||
use middle::typeck::check::{structurally_resolved_type};
|
||||
@ -489,6 +489,8 @@ pub fn early_resolve_expr(ex: @ast::expr,
|
||||
match ex.node {
|
||||
ast::expr_path(*) => {
|
||||
for fcx.opt_node_ty_substs(ex.id) |substs| {
|
||||
debug!("vtable resolution on parameter bounds for expr %s",
|
||||
ex.repr(fcx.tcx()));
|
||||
let def = *cx.tcx.def_map.get(&ex.id);
|
||||
let did = ast_util::def_id_of_def(def);
|
||||
let item_ty = ty::lookup_item_type(cx.tcx, did);
|
||||
@ -518,6 +520,8 @@ pub fn early_resolve_expr(ex: @ast::expr,
|
||||
ast::expr_index(*) | ast::expr_method_call(*) => {
|
||||
match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) {
|
||||
Some(type_param_defs) => {
|
||||
debug!("vtable resolution on parameter bounds for method call %s",
|
||||
ex.repr(fcx.tcx()));
|
||||
if has_trait_bounds(*type_param_defs) {
|
||||
let callee_id = match ex.node {
|
||||
ast::expr_field(_, _, _) => ex.id,
|
||||
@ -537,6 +541,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
|
||||
}
|
||||
}
|
||||
ast::expr_cast(src, _) => {
|
||||
debug!("vtable resolution on expr %s", ex.repr(fcx.tcx()));
|
||||
let target_ty = fcx.expr_ty(ex);
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(target_def_id, ref target_substs, store) => {
|
||||
|
@ -24,7 +24,7 @@ use metadata::cstore::{CStore, iter_crate_data};
|
||||
use metadata::decoder::{dl_def, dl_field, dl_impl};
|
||||
use middle::resolve::{Impl, MethodInfo};
|
||||
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
|
||||
use middle::ty::{lookup_item_type, param_bounds, subst};
|
||||
use middle::ty::{lookup_item_type, subst};
|
||||
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
|
||||
|
@ -55,7 +55,7 @@ use syntax::ast_util::{local_def, split_trait_methods};
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::span;
|
||||
use syntax::codemap;
|
||||
use syntax::print::pprust::path_to_str;
|
||||
use syntax::print::pprust::{path_to_str, self_ty_to_str};
|
||||
use syntax::visit;
|
||||
use syntax::opt_vec::OptVec;
|
||||
use syntax::opt_vec;
|
||||
@ -453,31 +453,35 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
||||
|
||||
let impl_m = &cm.mty;
|
||||
|
||||
// FIXME(#2687)---this check is too strict. For example, a trait
|
||||
// method with self type `&self` or `&mut self` should be
|
||||
// implementable by an `&const self` method (the impl assumes less
|
||||
// than the trait provides).
|
||||
if impl_m.self_ty != trait_m.self_ty {
|
||||
if impl_m.self_ty == ast::sty_static {
|
||||
// Needs to be a fatal error because otherwise,
|
||||
// method::transform_self_type_for_method ICEs
|
||||
tcx.sess.span_fatal(cm.span,
|
||||
fmt!("method `%s` is declared as \
|
||||
static in its impl, but not in \
|
||||
its trait", *tcx.sess.str_of(impl_m.ident)));
|
||||
}
|
||||
else if trait_m.self_ty == ast::sty_static {
|
||||
tcx.sess.span_fatal(cm.span,
|
||||
fmt!("method `%s` is declared as \
|
||||
static in its trait, but not in \
|
||||
its impl", *tcx.sess.str_of(impl_m.ident)));
|
||||
}
|
||||
else {
|
||||
// Try to give more informative error messages about self typing
|
||||
// mismatches. Note that any mismatch will also be detected
|
||||
// below, where we construct a canonical function type that
|
||||
// includes the self parameter as a normal parameter. It's just
|
||||
// that the error messages you get out of this code are a bit more
|
||||
// inscrutable, particularly for cases where one method has no
|
||||
// self.
|
||||
match (&trait_m.self_ty, &impl_m.self_ty) {
|
||||
(&ast::sty_static, &ast::sty_static) => {}
|
||||
(&ast::sty_static, _) => {
|
||||
tcx.sess.span_err(
|
||||
cm.span,
|
||||
fmt!("method `%s`'s self type does \
|
||||
not match the trait method's \
|
||||
self type", *tcx.sess.str_of(impl_m.ident)));
|
||||
fmt!("method `%s` has a `%s` declaration in the impl, \
|
||||
but not in the trait",
|
||||
*tcx.sess.str_of(trait_m.ident),
|
||||
self_ty_to_str(impl_m.self_ty, tcx.sess.intr())));
|
||||
return;
|
||||
}
|
||||
(_, &ast::sty_static) => {
|
||||
tcx.sess.span_err(
|
||||
cm.span,
|
||||
fmt!("method `%s` has a `%s` declaration in the trait, \
|
||||
but not in the impl",
|
||||
*tcx.sess.str_of(trait_m.ident),
|
||||
self_ty_to_str(trait_m.self_ty, tcx.sess.intr())));
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
// Let the type checker catch other errors below
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,6 +543,51 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
||||
bound_region: ty::br_self});
|
||||
let self_ty = replace_bound_self(tcx, self_ty, dummy_self_r);
|
||||
|
||||
// We are going to create a synthetic fn type that includes
|
||||
// both the method's self argument and its normal arguments.
|
||||
// So a method like `fn(&self, a: uint)` would be converted
|
||||
// into a function `fn(self: &T, a: uint)`.
|
||||
let mut trait_fn_args = ~[];
|
||||
let mut impl_fn_args = ~[];
|
||||
|
||||
// For both the trait and the impl, create an argument to
|
||||
// represent the self argument (unless this is a static method).
|
||||
// This argument will have the *transformed* self type.
|
||||
for trait_m.transformed_self_ty.each |&t| {
|
||||
trait_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
|
||||
}
|
||||
for impl_m.transformed_self_ty.each |&t| {
|
||||
impl_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
|
||||
}
|
||||
|
||||
// Add in the normal arguments.
|
||||
trait_fn_args.push_all(trait_m.fty.sig.inputs);
|
||||
impl_fn_args.push_all(impl_m.fty.sig.inputs);
|
||||
|
||||
// Create a bare fn type for trait/impl that includes self argument
|
||||
let trait_fty =
|
||||
ty::mk_bare_fn(
|
||||
tcx,
|
||||
ty::BareFnTy {purity: trait_m.fty.purity,
|
||||
abis: trait_m.fty.abis,
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names:
|
||||
copy trait_m.fty.sig.bound_lifetime_names,
|
||||
inputs: trait_fn_args,
|
||||
output: trait_m.fty.sig.output
|
||||
}});
|
||||
let impl_fty =
|
||||
ty::mk_bare_fn(
|
||||
tcx,
|
||||
ty::BareFnTy {purity: impl_m.fty.purity,
|
||||
abis: impl_m.fty.abis,
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names:
|
||||
copy impl_m.fty.sig.bound_lifetime_names,
|
||||
inputs: impl_fn_args,
|
||||
output: impl_m.fty.sig.output
|
||||
}});
|
||||
|
||||
// Perform substitutions so that the trait/impl methods are expressed
|
||||
// in terms of the same set of type/region parameters:
|
||||
// - replace trait type parameters with those from `trait_substs`,
|
||||
@ -547,7 +596,6 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
||||
// that correspond to the parameters we will find on the impl
|
||||
// - replace self region with a fresh, dummy region
|
||||
let impl_fty = {
|
||||
let impl_fty = ty::mk_bare_fn(tcx, copy impl_m.fty);
|
||||
debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty));
|
||||
replace_bound_self(tcx, impl_fty, dummy_self_r)
|
||||
};
|
||||
@ -565,7 +613,6 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
||||
self_ty: Some(self_ty),
|
||||
tps: vec::append(trait_tps, dummy_tps)
|
||||
};
|
||||
let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty);
|
||||
debug!("trait_fty (pre-subst): %s substs=%s",
|
||||
trait_fty.repr(tcx), substs.repr(tcx));
|
||||
ty::subst(tcx, &substs, trait_fty)
|
||||
|
@ -180,12 +180,11 @@ impl region_scope for MethodRscope {
|
||||
})
|
||||
}
|
||||
fn self_region(&self, _span: span) -> Result<ty::Region, RegionError> {
|
||||
assert!(self.variance.is_some() || self.self_ty.is_borrowed());
|
||||
assert!(self.variance.is_some());
|
||||
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() {
|
||||
if !self.region_param_names.has_self() {
|
||||
return Err(RegionError {
|
||||
msg: ~"the `self` lifetime must be declared",
|
||||
replacement: ty::re_bound(ty::br_self)
|
||||
|
@ -750,6 +750,12 @@ impl Repr for ty::TraitStore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ty::vstore {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
vstore_to_str(tcx, *self)
|
||||
}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
|
@ -1002,15 +1002,6 @@ pub enum self_ty_ {
|
||||
sty_uniq(mutability) // `~self`
|
||||
}
|
||||
|
||||
impl self_ty_ {
|
||||
fn is_borrowed(&self) -> bool {
|
||||
match *self {
|
||||
sty_region(*) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type self_ty = spanned<self_ty_>;
|
||||
|
||||
#[auto_encode]
|
||||
|
@ -454,6 +454,7 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
|
||||
|
||||
// ugh: can't get this to compile with mut because of the
|
||||
// lack of flow sensitivity.
|
||||
#[cfg(stage0)]
|
||||
fn get_map(&self) -> &'self HashMap<K,@V> {
|
||||
match *self {
|
||||
BaseMapChain (~ref map) => map,
|
||||
@ -461,6 +462,18 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
|
||||
}
|
||||
}
|
||||
|
||||
// ugh: can't get this to compile with mut because of the
|
||||
// lack of flow sensitivity.
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
|
||||
match *self {
|
||||
BaseMapChain (~ref map) => map,
|
||||
ConsMapChain (~ref map,_) => map
|
||||
}
|
||||
}
|
||||
|
||||
// traits just don't work anywhere...?
|
||||
//pub impl Map<Name,SyntaxExtension> for MapChain {
|
||||
|
||||
|
@ -61,6 +61,7 @@ impl<T> OptVec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn get(&self, i: uint) -> &'self T {
|
||||
match *self {
|
||||
Empty => fail!(fmt!("Invalid index %u", i)),
|
||||
@ -68,6 +69,16 @@ impl<T> OptVec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[cfg(stage3)]
|
||||
fn get<'a>(&'a self, i: uint) -> &'a T {
|
||||
match *self {
|
||||
Empty => fail!(fmt!("Invalid index %u", i)),
|
||||
Vec(ref v) => &v[i]
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
@ -1633,6 +1633,10 @@ pub fn print_pat(s: @ps, &&pat: @ast::pat, refutable: bool) {
|
||||
(s.ann.post)(ann_node);
|
||||
}
|
||||
|
||||
pub fn self_ty_to_str(self_ty: ast::self_ty_, intr: @ident_interner) -> ~str {
|
||||
to_str(self_ty, |a, b| { print_self_ty(a, b); () }, intr)
|
||||
}
|
||||
|
||||
// Returns whether it printed anything
|
||||
pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool {
|
||||
match self_ty {
|
||||
|
Loading…
Reference in New Issue
Block a user