1
Fork 0

auto merge of #14022 : pcwalton/rust/explicit-self, r=pnkfelix

r? @nikomatsakis
This commit is contained in:
bors 2014-07-17 06:21:21 +00:00
commit 32cb44bfff
47 changed files with 662 additions and 192 deletions

View file

@ -132,7 +132,8 @@ pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
def: ast::DefId)
-> (ast::Ident, ast::ExplicitSelf_)
-> (ast::Ident,
ty::ExplicitSelfCategory)
{
let cdata = cstore.get_crate_data(def.krate);
decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)

View file

@ -724,7 +724,7 @@ pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
}).collect()
}
fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
fn get_explicit_self(item: ebml::Doc) -> ty::ExplicitSelfCategory {
fn get_mutability(ch: u8) -> ast::Mutability {
match ch as char {
'i' => ast::MutImmutable,
@ -738,12 +738,15 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
's' => ast::SelfStatic,
'v' => ast::SelfValue(special_idents::self_),
'~' => ast::SelfUniq(special_idents::self_),
's' => ty::StaticExplicitSelfCategory,
'v' => ty::ByValueExplicitSelfCategory,
'~' => ty::ByBoxExplicitSelfCategory,
// FIXME(#4846) expl. region
'&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1]),
special_idents::self_),
'&' => {
ty::ByReferenceExplicitSelfCategory(
ty::ReEmpty,
get_mutability(string.as_bytes()[1]))
}
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
}
}
@ -761,11 +764,11 @@ pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
methods
}
pub fn get_method_name_and_explicit_self(
intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_)
{
pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
cdata: Cmd,
id: ast::NodeId)
-> (ast::Ident,
ty::ExplicitSelfCategory) {
let method_doc = lookup_item(id, cdata.data());
let name = item_name(&*intr, method_doc);
let explicit_self = get_explicit_self(method_doc);

View file

@ -402,7 +402,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
for base_impl_did in implementations.borrow().iter() {
for &method_did in impl_methods.get(base_impl_did).iter() {
let m = ty::method(ecx.tcx, method_did);
if m.explicit_self == ast::SelfStatic {
if m.explicit_self == ty::StaticExplicitSelfCategory {
encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
}
}
@ -421,7 +421,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
Some(methods) => {
for m in methods.iter() {
if m.explicit_self == ast::SelfStatic {
if m.explicit_self == ty::StaticExplicitSelfCategory {
encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
}
}
@ -623,15 +623,22 @@ fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
ebml_w.end_tag();
}
fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
fn encode_explicit_self(ebml_w: &mut Encoder,
explicit_self: &ty::ExplicitSelfCategory) {
ebml_w.start_tag(tag_item_trait_method_explicit_self);
// Encode the base self type.
match explicit_self {
SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
SelfRegion(_, m, _) => {
match *explicit_self {
ty::StaticExplicitSelfCategory => {
ebml_w.writer.write(&[ 's' as u8 ]);
}
ty::ByValueExplicitSelfCategory => {
ebml_w.writer.write(&[ 'v' as u8 ]);
}
ty::ByBoxExplicitSelfCategory => {
ebml_w.writer.write(&[ '~' as u8 ]);
}
ty::ByReferenceExplicitSelfCategory(_, m) => {
// FIXME(#4846) encode custom lifetime
ebml_w.writer.write(&['&' as u8]);
encode_mutability(ebml_w, m);
@ -748,10 +755,10 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
tag_item_method_tps);
encode_method_fty(ecx, ebml_w, &method_ty.fty);
encode_visibility(ebml_w, method_ty.vis);
encode_explicit_self(ebml_w, method_ty.explicit_self);
encode_explicit_self(ebml_w, &method_ty.explicit_self);
let fn_style = method_ty.fty.fn_style;
match method_ty.explicit_self {
ast::SelfStatic => {
ty::StaticExplicitSelfCategory => {
encode_family(ebml_w, fn_style_static_method_family(fn_style));
}
_ => encode_family(ebml_w, style_fn_family(fn_style))
@ -1206,7 +1213,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
match method_ty.explicit_self {
SelfStatic => {
ty::StaticExplicitSelfCategory => {
encode_family(ebml_w,
fn_style_static_method_family(
method_ty.fty.fn_style));
@ -1233,7 +1240,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_attributes(ebml_w, m.attrs.as_slice());
// If this is a static method, we've already encoded
// this.
if method_ty.explicit_self != SelfStatic {
if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
// FIXME: I feel like there is something funny going on.
let pty = ty::lookup_item_type(tcx, method_def_id);
encode_bounds_and_type(ebml_w, ecx, &pty);

View file

@ -314,6 +314,16 @@ impl RegionMaps {
self.sub_free_region(sub_fr, super_fr)
}
(ty::ReEarlyBound(param_id_a, param_space_a, index_a, _),
ty::ReEarlyBound(param_id_b, param_space_b, index_b, _)) => {
// This case is used only to make sure that explicitly-
// specified `Self` types match the real self type in
// implementations.
param_id_a == param_id_b &&
param_space_a == param_space_b &&
index_a == index_b
}
_ => {
false
}

View file

@ -11,13 +11,14 @@
#![allow(non_camel_case_types)]
use driver::session::Session;
use lint;
use metadata::csearch;
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
use middle::def::*;
use middle::lang_items::LanguageItems;
use middle::pat_util::pat_bindings;
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
use lint;
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use syntax::ast::*;
@ -287,6 +288,24 @@ enum ModulePrefixResult {
PrefixFound(Rc<Module>, uint)
}
#[deriving(Clone, Eq, PartialEq)]
enum MethodIsStaticFlag {
MethodIsNotStatic,
MethodIsStatic,
}
impl MethodIsStaticFlag {
fn from_explicit_self_category(explicit_self_category:
ExplicitSelfCategory)
-> MethodIsStaticFlag {
if explicit_self_category == StaticExplicitSelfCategory {
MethodIsStatic
} else {
MethodIsNotStatic
}
}
}
#[deriving(PartialEq)]
enum NameSearchType {
/// We're doing a name search in order to resolve a `use` directive.
@ -805,7 +824,8 @@ struct Resolver<'a> {
graph_root: NameBindings,
method_map: RefCell<FnvHashMap<(Name, DefId), ast::ExplicitSelf_>>,
method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
structs: FnvHashMap<DefId, Vec<Name>>,
// The number of imports that are currently unresolved.
@ -1361,17 +1381,19 @@ impl<'a> Resolver<'a> {
let ident = ty_m.ident;
// Add it as a name in the trait module.
let def = match ty_m.explicit_self.node {
let (def, static_flag) = match ty_m.explicit_self.node {
SelfStatic => {
// Static methods become `def_static_method`s.
DefStaticMethod(local_def(ty_m.id),
(DefStaticMethod(local_def(ty_m.id),
FromTrait(local_def(item.id)),
ty_m.fn_style)
ty_m.fn_style),
MethodIsStatic)
}
_ => {
// Non-static methods become `def_method`s.
DefMethod(local_def(ty_m.id),
Some(local_def(item.id)))
(DefMethod(local_def(ty_m.id),
Some(local_def(item.id))),
MethodIsNotStatic)
}
};
@ -1382,8 +1404,9 @@ impl<'a> Resolver<'a> {
ty_m.span);
method_name_bindings.define_value(def, ty_m.span, true);
self.method_map.borrow_mut().insert((ident.name, def_id),
ty_m.explicit_self.node);
self.method_map
.borrow_mut()
.insert((ident.name, def_id), static_flag);
}
name_bindings.define_type(DefTrait(def_id), sp, is_public);
@ -1670,7 +1693,11 @@ impl<'a> Resolver<'a> {
trait method '{}'",
token::get_ident(method_name));
self.method_map.borrow_mut().insert((method_name.name, def_id), explicit_self);
self.method_map
.borrow_mut()
.insert((method_name.name, def_id),
MethodIsStaticFlag::from_explicit_self_category(
explicit_self));
if is_exported {
self.external_exports.insert(method_def_id);
@ -3678,6 +3705,13 @@ impl<'a> Resolver<'a> {
this.resolve_type(&*argument.ty);
}
match ty_m.explicit_self.node {
SelfExplicit(ref typ, _) => {
this.resolve_type(*typ)
}
_ => {}
}
this.resolve_type(&*ty_m.decl.output);
});
}
@ -4009,7 +4043,14 @@ impl<'a> Resolver<'a> {
method.id,
rib_kind);
self.resolve_function(rib_kind, Some(method.pe_fn_decl()), type_parameters,
match method.pe_explicit_self().node {
SelfExplicit(ref typ, _) => self.resolve_type(*typ),
_ => {}
}
self.resolve_function(rib_kind,
Some(method.pe_fn_decl()),
type_parameters,
method.pe_body());
}
@ -4765,7 +4806,7 @@ impl<'a> Resolver<'a> {
match containing_module.def_id.get() {
Some(def_id) => {
match self.method_map.borrow().find(&(ident.name, def_id)) {
Some(x) if *x == SelfStatic => (),
Some(&MethodIsStatic) => (),
None => (),
_ => {
debug!("containing module was a trait or impl \
@ -5037,7 +5078,7 @@ impl<'a> Resolver<'a> {
let path_str = self.path_idents_to_string(&trait_ref.path);
match method_map.find(&(name, did)) {
Some(&SelfStatic) => return StaticTraitMethod(path_str),
Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
Some(_) => return TraitMethod,
None => {}
}

View file

@ -502,15 +502,12 @@ fn emit_vtable_methods(bcx: &Block,
ExprId(0),
substs.clone(),
vtables.clone());
match m.explicit_self {
ast::SelfValue(_) => {
fn_ref = trans_unboxing_shim(bcx,
fn_ref,
&*m,
m_id,
substs.clone());
},
_ => {}
if m.explicit_self == ty::ByValueExplicitSelfCategory {
fn_ref = trans_unboxing_shim(bcx,
fn_ref,
&*m,
m_id,
substs.clone());
}
fn_ref
}

View file

@ -85,7 +85,7 @@ pub struct Method {
pub ident: ast::Ident,
pub generics: ty::Generics,
pub fty: BareFnTy,
pub explicit_self: ast::ExplicitSelf_,
pub explicit_self: ExplicitSelfCategory,
pub vis: ast::Visibility,
pub def_id: ast::DefId,
pub container: MethodContainer,
@ -98,7 +98,7 @@ impl Method {
pub fn new(ident: ast::Ident,
generics: ty::Generics,
fty: BareFnTy,
explicit_self: ast::ExplicitSelf_,
explicit_self: ExplicitSelfCategory,
vis: ast::Visibility,
def_id: ast::DefId,
container: MethodContainer,
@ -311,6 +311,9 @@ pub struct ctxt {
/// (inferred) variance.
pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
/// True if the variance has been computed yet; false otherwise.
pub variance_computed: Cell<bool>,
/// A mapping from the def ID of an enum or struct type to the def ID
/// of the method that implements its destructor. If the type is not
/// present in this map, it does not have a destructor. This map is
@ -1055,6 +1058,7 @@ pub fn mk_ctxt(s: Session,
ctxt {
named_region_map: named_region_map,
item_variance_map: RefCell::new(DefIdMap::new()),
variance_computed: Cell::new(false),
interner: RefCell::new(FnvHashMap::new()),
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
sess: s,
@ -4767,3 +4771,13 @@ impl mc::Typer for ty::ctxt {
self.upvar_borrow_map.borrow().get_copy(&upvar_id)
}
}
/// The category of explicit self.
#[deriving(Clone, Eq, PartialEq)]
pub enum ExplicitSelfCategory {
StaticExplicitSelfCategory,
ByValueExplicitSelfCategory,
ByReferenceExplicitSelfCategory(Region, ast::Mutability),
ByBoxExplicitSelfCategory,
}

View file

@ -52,13 +52,13 @@
use middle::const_eval;
use middle::def;
use middle::lang_items::FnMutTraitLangItem;
use rl = middle::resolve_lifetime;
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::ty;
use middle::typeck::TypeAndSubsts;
use middle::typeck::lookup_def_tcx;
use middle::ty_fold::TypeFolder;
use middle::typeck::rscope::RegionScope;
use middle::typeck::rscope;
use middle::typeck::{TypeAndSubsts, infer, lookup_def_tcx, rscope};
use middle::typeck;
use rl = middle::resolve_lifetime;
use util::ppaux::Repr;
use std::rc::Rc;
@ -900,58 +900,73 @@ pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::
}
}
struct SelfInfo {
struct SelfInfo<'a> {
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf
explicit_self: ast::ExplicitSelf,
}
pub fn ty_of_method<AC:AstConv>(
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf,
decl: &ast::FnDecl)
-> ty::BareFnTy
{
ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf,
decl: &ast::FnDecl)
-> (ty::BareFnTy, ty::ExplicitSelfCategory) {
let self_info = Some(SelfInfo {
untransformed_self_ty: untransformed_self_ty,
explicit_self: explicit_self
}), decl)
explicit_self: explicit_self,
});
let (bare_fn_ty, optional_explicit_self_category) =
ty_of_method_or_bare_fn(this,
id,
fn_style,
abi::Rust,
self_info,
decl);
(bare_fn_ty, optional_explicit_self_category.unwrap())
}
pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
fn_style: ast::FnStyle, abi: abi::Abi,
decl: &ast::FnDecl) -> ty::BareFnTy {
ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl)
let (bare_fn_ty, _) =
ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl);
bare_fn_ty
}
fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
fn_style: ast::FnStyle, abi: abi::Abi,
opt_self_info: Option<SelfInfo>,
decl: &ast::FnDecl) -> ty::BareFnTy {
fn ty_of_method_or_bare_fn<AC:AstConv>(
this: &AC,
id: ast::NodeId,
fn_style: ast::FnStyle,
abi: abi::Abi,
opt_self_info: Option<SelfInfo>,
decl: &ast::FnDecl)
-> (ty::BareFnTy,
Option<ty::ExplicitSelfCategory>) {
debug!("ty_of_method_or_bare_fn");
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = rscope::BindingRscope::new(id);
let mut explicit_self_category_result = None;
let self_ty = opt_self_info.and_then(|self_info| {
match self_info.explicit_self.node {
ast::SelfStatic => None,
ast::SelfValue(_) => {
// Figure out and record the explicit self category.
let explicit_self_category =
determine_explicit_self_category(this, &rb, &self_info);
explicit_self_category_result = Some(explicit_self_category);
match explicit_self_category {
ty::StaticExplicitSelfCategory => None,
ty::ByValueExplicitSelfCategory => {
Some(self_info.untransformed_self_ty)
}
ast::SelfRegion(ref lifetime, mutability, _) => {
let region =
opt_ast_region_to_region(this, &rb,
self_info.explicit_self.span,
lifetime);
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
Some(ty::mk_rptr(this.tcx(), region,
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
ast::SelfUniq(_) => {
ty::ByBoxExplicitSelfCategory => {
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
}
}
@ -972,7 +987,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
_ => ast_ty_to_ty(this, &rb, &*decl.output)
};
return ty::BareFnTy {
(ty::BareFnTy {
fn_style: fn_style,
abi: abi,
sig: ty::FnSig {
@ -981,7 +996,83 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
output: output_ty,
variadic: decl.variadic
}
};
}, explicit_self_category_result)
}
fn determine_explicit_self_category<AC:AstConv,
RS:RegionScope>(
this: &AC,
rscope: &RS,
self_info: &SelfInfo)
-> ty::ExplicitSelfCategory {
match self_info.explicit_self.node {
ast::SelfStatic => ty::StaticExplicitSelfCategory,
ast::SelfValue(_) => ty::ByValueExplicitSelfCategory,
ast::SelfRegion(ref lifetime, mutability, _) => {
let region =
opt_ast_region_to_region(this,
rscope,
self_info.explicit_self.span,
lifetime);
ty::ByReferenceExplicitSelfCategory(region, mutability)
}
ast::SelfUniq(_) => ty::ByBoxExplicitSelfCategory,
ast::SelfExplicit(ast_type, _) => {
let explicit_type = ast_ty_to_ty(this, rscope, ast_type);
{
let inference_context = infer::new_infer_ctxt(this.tcx());
let expected_self = self_info.untransformed_self_ty;
let actual_self = explicit_type;
let result = infer::mk_eqty(
&inference_context,
false,
infer::Misc(self_info.explicit_self.span),
expected_self,
actual_self);
match result {
Ok(_) => {
inference_context.resolve_regions_and_report_errors();
return ty::ByValueExplicitSelfCategory
}
Err(_) => {}
}
}
match ty::get(explicit_type).sty {
ty::ty_rptr(region, tm) => {
typeck::require_same_types(
this.tcx(),
None,
false,
self_info.explicit_self.span,
self_info.untransformed_self_ty,
tm.ty,
|| "not a valid type for `self`".to_owned());
return ty::ByReferenceExplicitSelfCategory(region,
tm.mutbl)
}
ty::ty_uniq(typ) => {
typeck::require_same_types(
this.tcx(),
None,
false,
self_info.explicit_self.span,
self_info.untransformed_self_ty,
typ,
|| "not a valid type for `self`".to_owned());
return ty::ByBoxExplicitSelfCategory
}
_ => {
this.tcx()
.sess
.span_err(self_info.explicit_self.span,
"not a valid type for `self`");
return ty::ByValueExplicitSelfCategory
}
}
}
}
}
pub fn ty_of_closure<AC:AstConv>(
@ -1098,3 +1189,4 @@ fn conv_builtin_bounds(tcx: &ty::ctxt,
(&None, ty::UniqTraitStore) => ty::empty_builtin_bounds(),
}
}

View file

@ -100,9 +100,7 @@ use util::ppaux::Repr;
use std::collections::HashSet;
use std::rc::Rc;
use syntax::ast::{DefId, SelfValue, SelfRegion};
use syntax::ast::{SelfUniq, SelfStatic};
use syntax::ast::{MutMutable, MutImmutable};
use syntax::ast::{DefId, MutImmutable, MutMutable};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
@ -267,15 +265,15 @@ fn construct_transformed_self_ty_for_object(
obj_substs.types.pop(subst::SelfSpace).unwrap();
match method_ty.explicit_self {
ast::SelfStatic => {
StaticExplicitSelfCategory => {
tcx.sess.span_bug(span, "static method for object type receiver");
}
ast::SelfValue(_) => {
ByValueExplicitSelfCategory => {
let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
ty::empty_builtin_bounds());
ty::mk_uniq(tcx, tr)
}
ast::SelfRegion(..) | ast::SelfUniq(..) => {
ByReferenceExplicitSelfCategory(..) | ByBoxExplicitSelfCategory => {
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
match ty::get(transformed_self_ty).sty {
ty::ty_rptr(r, mt) => { // must be SelfRegion
@ -618,7 +616,7 @@ impl<'a> LookupContext<'a> {
let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
match trait_methods.iter().position(|m| {
m.explicit_self != ast::SelfStatic &&
m.explicit_self != ty::StaticExplicitSelfCategory &&
m.ident.name == self.m_name }) {
Some(pos) => {
let method = trait_methods.get(pos).clone();
@ -1023,7 +1021,10 @@ impl<'a> LookupContext<'a> {
if self.report_statics == ReportStaticMethods {
// lookup should only be called with ReportStaticMethods if a regular lookup failed
assert!(relevant_candidates.iter().all(|c| c.method_ty.explicit_self == SelfStatic));
assert!(relevant_candidates.iter()
.all(|c| {
c.method_ty.explicit_self == ty::StaticExplicitSelfCategory
}));
self.tcx().sess.fileline_note(self.span,
"found defined static methods, maybe a `self` is missing?");
@ -1100,7 +1101,8 @@ impl<'a> LookupContext<'a> {
self.enforce_drop_trait_limitations(candidate);
// static methods should never have gotten this far:
assert!(candidate.method_ty.explicit_self != SelfStatic);
assert!(candidate.method_ty.explicit_self !=
ty::StaticExplicitSelfCategory);
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
@ -1217,12 +1219,16 @@ impl<'a> LookupContext<'a> {
}
match candidate.method_ty.explicit_self {
ast::SelfStatic => { // reason (a) above
span_err!(self.tcx().sess, self.span, E0037,
"cannot call a method without a receiver through an object");
ty::StaticExplicitSelfCategory => { // reason (a) above
self.tcx().sess.span_err(
self.span,
"cannot call a method without a receiver \
through an object");
}
ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {}
ty::ByValueExplicitSelfCategory |
ty::ByReferenceExplicitSelfCategory(..) |
ty::ByBoxExplicitSelfCategory => {}
}
// reason (a) above
@ -1284,12 +1290,12 @@ impl<'a> LookupContext<'a> {
self.ty_to_string(rcvr_ty), candidate.repr(self.tcx()));
return match candidate.method_ty.explicit_self {
SelfStatic => {
StaticExplicitSelfCategory => {
debug!("(is relevant?) explicit self is static");
self.report_statics == ReportStaticMethods
}
SelfValue(_) => {
ByValueExplicitSelfCategory => {
debug!("(is relevant?) explicit self is by-value");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {
@ -1312,7 +1318,7 @@ impl<'a> LookupContext<'a> {
}
}
SelfRegion(_, m, _) => {
ByReferenceExplicitSelfCategory(_, m) => {
debug!("(is relevant?) explicit self is a region");
match ty::get(rcvr_ty).sty {
ty::ty_rptr(_, mt) => {
@ -1332,7 +1338,7 @@ impl<'a> LookupContext<'a> {
}
}
SelfUniq(_) => {
ByBoxExplicitSelfCategory => {
debug!("(is relevant?) explicit self is a unique pointer");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {
@ -1480,3 +1486,6 @@ impl Repr for RcvrMatchCondition {
}
}
}

View file

@ -862,19 +862,26 @@ fn compare_impl_method(tcx: &ty::ctxt,
// inscrutable, particularly for cases where one method has no
// self.
match (&trait_m.explicit_self, &impl_m.explicit_self) {
(&ast::SelfStatic, &ast::SelfStatic) => {}
(&ast::SelfStatic, _) => {
span_err!(tcx.sess, impl_m_span, E0047,
"method `{}` has a `{}` declaration in the impl, but not in the trait",
token::get_ident(trait_m.ident),
pprust::explicit_self_to_string(impl_m.explicit_self));
(&ty::StaticExplicitSelfCategory,
&ty::StaticExplicitSelfCategory) => {}
(&ty::StaticExplicitSelfCategory, _) => {
tcx.sess.span_err(
impl_m_span,
format!("method `{}` has a `{}` declaration in the impl, \
but not in the trait",
token::get_ident(trait_m.ident),
ppaux::explicit_self_category_to_str(
&impl_m.explicit_self)).as_slice());
return;
}
(_, &ast::SelfStatic) => {
span_err!(tcx.sess, impl_m_span, E0048,
"method `{}` has a `{}` declaration in the trait, but not in the impl",
token::get_ident(trait_m.ident),
pprust::explicit_self_to_string(trait_m.explicit_self));
(_, &ty::StaticExplicitSelfCategory) => {
tcx.sess.span_err(
impl_m_span,
format!("method `{}` has a `{}` declaration in the trait, \
but not in the impl",
token::get_ident(trait_m.ident),
ppaux::explicit_self_category_to_str(
&trait_m.explicit_self)).as_slice());
return;
}
_ => {
@ -4787,3 +4794,4 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
});
}
}

View file

@ -40,11 +40,14 @@ use middle::subst::{Substs};
use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
use middle::ty::{Polytype};
use middle::ty;
use middle::ty_fold::TypeFolder;
use middle::typeck::astconv::{AstConv, ty_of_arg};
use middle::typeck::astconv::{ast_ty_to_ty};
use middle::typeck::astconv;
use middle::typeck::infer;
use middle::typeck::rscope::*;
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
use middle::typeck;
use util::ppaux;
use util::ppaux::Repr;
@ -218,7 +221,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
}
});
if ty_method.explicit_self == ast::SelfStatic {
if ty_method.explicit_self ==
ty::StaticExplicitSelfCategory {
make_static_method_ty(ccx, &*ty_method);
}
@ -266,18 +270,26 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
m_fn_style: &ast::FnStyle,
m_decl: &ast::FnDecl) -> ty::Method
{
let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));
let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty,
*m_explicit_self, m_decl);
let ty_generics =
ty_generics_for_fn_or_method(this,
m_generics,
(*trait_generics).clone());
let trait_self_ty = ty::mk_param(this.tcx,
subst::SelfSpace,
0,
local_def(trait_id));
let ty_generics = ty_generics_for_fn_or_method(
this,
m_generics,
(*trait_generics).clone());
let (fty, explicit_self_category) =
astconv::ty_of_method(this,
*m_id,
*m_fn_style,
trait_self_ty,
*m_explicit_self,
m_decl);
ty::Method::new(
*m_ident,
ty_generics,
fty,
m_explicit_self.node,
explicit_self_category,
// assume public, because this is only invoked on trait methods
ast::Public,
local_def(*m_id),
@ -365,9 +377,13 @@ fn convert_methods(ccx: &CrateCtxt,
rcvr_visibility: ast::Visibility)
-> ty::Method
{
let fty = astconv::ty_of_method(ccx, m.id, m.pe_fn_style(),
untransformed_rcvr_ty,
*m.pe_explicit_self(), m.pe_fn_decl());
let (fty, explicit_self_category) =
astconv::ty_of_method(ccx,
m.id,
m.pe_fn_style(),
untransformed_rcvr_ty,
*m.pe_explicit_self(),
m.pe_fn_decl());
// if the method specifies a visibility, use that, otherwise
// inherit the visibility from the impl (so `foo` in `pub impl
@ -381,7 +397,7 @@ fn convert_methods(ccx: &CrateCtxt,
ty::Method::new(m.pe_ident(),
m_ty_generics,
fty,
m.pe_explicit_self().node,
explicit_self_category,
method_vis,
local_def(m.id),
container,
@ -450,6 +466,13 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
it.vis
};
for method in ms.iter() {
check_method_self_type(ccx,
&BindingRscope::new(method.id),
selfty,
method.pe_explicit_self())
}
convert_methods(ccx,
ImplContainer(local_def(it.id)),
ms.as_slice(),
@ -464,6 +487,28 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
ast::ItemTrait(_, _, _, ref trait_methods) => {
let trait_def = trait_def_of_item(ccx, it);
for trait_method in trait_methods.iter() {
let self_type = ty::mk_param(ccx.tcx,
subst::SelfSpace,
0,
local_def(it.id));
match *trait_method {
ast::Required(ref type_method) => {
let rscope = BindingRscope::new(type_method.id);
check_method_self_type(ccx,
&rscope,
self_type,
&type_method.explicit_self)
}
ast::Provided(ref method) => {
check_method_self_type(ccx,
&BindingRscope::new(method.id),
self_type,
method.pe_explicit_self())
}
}
}
// Run convert_methods on the provided methods.
let (_, provided_methods) =
split_trait_methods(trait_methods.as_slice());
@ -1240,3 +1285,36 @@ pub fn mk_item_substs(ccx: &CrateCtxt,
subst::Substs::new(types, regions)
}
/// Verifies that the explicit self type of a method matches the impl or
/// trait.
fn check_method_self_type<RS:RegionScope>(
crate_context: &CrateCtxt,
rs: &RS,
required_type: ty::t,
explicit_self: &ast::ExplicitSelf) {
match explicit_self.node {
ast::SelfExplicit(ref ast_type, _) => {
let typ = crate_context.to_ty(rs, *ast_type);
let base_type = match ty::get(typ).sty {
ty::ty_rptr(_, tm) => tm.ty,
ty::ty_uniq(typ) => typ,
_ => typ,
};
let infcx = infer::new_infer_ctxt(crate_context.tcx);
drop(typeck::require_same_types(crate_context.tcx,
Some(&infcx),
false,
explicit_self.span,
base_type,
required_type,
|| {
format!("mismatched self type: expected `{}`",
ppaux::ty_to_string(crate_context.tcx, required_type))
}));
infcx.resolve_regions_and_report_errors();
}
_ => {}
}
}

View file

@ -111,7 +111,11 @@ pub trait Combine {
b_subst: &subst::Substs)
-> cres<subst::Substs>
{
let variances = ty::item_variances(self.infcx().tcx, item_def_id);
let variances = if self.infcx().tcx.variance_computed.get() {
Some(ty::item_variances(self.infcx().tcx, item_def_id))
} else {
None
};
let mut substs = subst::Substs::empty();
for &space in subst::ParamSpace::all().iter() {
@ -121,7 +125,18 @@ pub trait Combine {
let a_regions = a_subst.regions().get_slice(space);
let b_regions = b_subst.regions().get_slice(space);
let r_variances = variances.regions.get_slice(space);
let mut invariance = Vec::new();
let r_variances = match variances {
Some(ref variances) => variances.regions.get_slice(space),
None => {
for _ in a_regions.iter() {
invariance.push(ty::Invariant);
}
invariance.as_slice()
}
};
let regions = if_ok!(relate_region_params(self,
item_def_id,
r_variances,

View file

@ -13,16 +13,15 @@
use middle::ty;
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound,
ReLateBound};
use middle::ty::{ReScope, ReVar, ReSkolemized, BrFresh};
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use middle::typeck::infer::cres;
use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin, TypeTrace};
use middle::typeck::infer;
use middle::graph;
use middle::graph::{Direction, NodeIndex};
use util::common::indenter;
use util::ppaux::{Repr};
use util::ppaux::Repr;
use std::cell::{Cell, RefCell};
use std::uint;
@ -318,6 +317,11 @@ impl<'a> RegionVarBindings<'a> {
origin.repr(self.tcx));
match (sub, sup) {
(ReEarlyBound(..), ReEarlyBound(..)) => {
// This case is used only to make sure that explicitly-specified
// `Self` types match the real self type in implementations.
self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
}
(ReEarlyBound(..), _) |
(ReLateBound(..), _) |
(_, ReEarlyBound(..)) |

View file

@ -214,6 +214,7 @@ pub fn infer_variance(tcx: &ty::ctxt,
let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
let constraints_cx = add_constraints_from_crate(terms_cx, krate);
solve_constraints(constraints_cx);
tcx.variance_computed.set(true);
}
/**************************************************************************

View file

@ -14,7 +14,7 @@ use middle::subst;
use middle::subst::{VecPerParamSpace,Subst};
use middle::ty::{ReSkolemized, ReVar};
use middle::ty::{BoundRegion, BrAnon, BrNamed};
use middle::ty::{BrFresh, ctxt};
use middle::ty::{ReEarlyBound, BrFresh, ctxt};
use middle::ty::{mt, t, ParamTy};
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
@ -130,9 +130,13 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
ReEmpty => { ("the empty lifetime".to_string(), None) }
ReEarlyBound(_, _, _, name) => {
(format!("{}", token::get_name(name)), None)
}
// I believe these cases should not occur (except when debugging,
// perhaps)
ty::ReInfer(_) | ty::ReEarlyBound(..) | ty::ReLateBound(..) => {
ty::ReInfer(_) | ty::ReLateBound(..) => {
(format!("lifetime {:?}", region), None)
}
};
@ -421,6 +425,19 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
}
}
pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
-> &'static str {
match *category {
ty::StaticExplicitSelfCategory => "static",
ty::ByValueExplicitSelfCategory => "self",
ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
"&mut self"
}
ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
ty::ByBoxExplicitSelfCategory => "Box<self>",
}
}
pub fn parameterized(cx: &ctxt,
base: &str,
substs: &subst::Substs,
@ -1083,3 +1100,10 @@ impl Repr for region_inference::VarValue {
}
}
}
impl Repr for ty::ExplicitSelfCategory {
fn repr(&self, _: &ctxt) -> String {
explicit_self_category_to_str(self).to_string()
}
}

View file

@ -394,7 +394,7 @@ impl Clean<Item> for doctree::Module {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub enum Attribute {
Word(String),
List(String, Vec<Attribute> ),
@ -447,7 +447,7 @@ impl<'a> attr::AttrMetaMethods for &'a Attribute {
fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc<ast::MetaItem>]> { None }
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct TyParam {
pub name: String,
pub did: ast::DefId,
@ -479,7 +479,7 @@ impl Clean<TyParam> for ty::TypeParameterDef {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub enum TyParamBound {
RegionBound,
TraitBound(Type)
@ -638,7 +638,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
}
// maybe use a Generic enum and use ~[Generic]?
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,
pub type_params: Vec<TyParam>,
@ -771,6 +771,7 @@ pub enum SelfTy {
SelfValue,
SelfBorrowed(Option<Lifetime>, Mutability),
SelfOwned,
SelfExplicit(Type),
}
impl Clean<SelfTy> for ast::ExplicitSelf_ {
@ -779,7 +780,10 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
ast::SelfStatic => SelfStatic,
ast::SelfValue(_) => SelfValue,
ast::SelfUniq(_) => SelfOwned,
ast::SelfRegion(lt, mt, _) => SelfBorrowed(lt.clean(), mt.clean()),
ast::SelfRegion(lt, mt, _) => {
SelfBorrowed(lt.clean(), mt.clean())
}
ast::SelfExplicit(typ, _) => SelfExplicit(typ.clean()),
}
}
}
@ -809,7 +813,7 @@ impl Clean<Item> for doctree::Function {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct ClosureDecl {
pub lifetimes: Vec<Lifetime>,
pub decl: FnDecl,
@ -833,7 +837,7 @@ impl Clean<ClosureDecl> for ast::ClosureTy {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct FnDecl {
pub inputs: Arguments,
pub output: Type,
@ -841,7 +845,7 @@ pub struct FnDecl {
pub attrs: Vec<Attribute>,
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct Arguments {
pub values: Vec<Argument>,
}
@ -888,7 +892,7 @@ impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct Argument {
pub type_: Type,
pub name: String,
@ -905,7 +909,7 @@ impl Clean<Argument> for ast::Arg {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub enum RetStyle {
NoReturn,
Return
@ -991,22 +995,28 @@ impl Clean<Item> for ty::Method {
fn clean(&self) -> Item {
let cx = get_cx();
let (self_, sig) = match self.explicit_self {
ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(), self.fty.sig.clone()),
s => {
let sig = ty::FnSig {
inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
..self.fty.sig.clone()
};
let s = match s {
ast::SelfRegion(..) => {
ty::ByReferenceExplicitSelfCategory(..) => {
match ty::get(self.fty.sig.inputs[0]).sty {
ty::ty_rptr(r, mt) => {
SelfBorrowed(r.clean(), mt.mutbl.clean())
}
_ => s.clean(),
_ => {
// FIXME(pcwalton): This is wrong.
SelfStatic
}
}
}
s => s.clean(),
_ => {
// FIXME(pcwalton): This is wrong.
SelfStatic
}
};
(s, sig)
}
@ -1032,7 +1042,7 @@ impl Clean<Item> for ty::Method {
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
/// it does not preserve mutability or boxes.
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub enum Type {
/// structs/enums/traits (anything that'd be an ast::TyPath)
ResolvedPath {
@ -1550,7 +1560,7 @@ impl Clean<Span> for syntax::codemap::Span {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct Path {
pub global: bool,
pub segments: Vec<PathSegment>,
@ -1565,7 +1575,7 @@ impl Clean<Path> for ast::Path {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct PathSegment {
pub name: String,
pub lifetimes: Vec<Lifetime>,
@ -1631,7 +1641,7 @@ impl Clean<Item> for doctree::Typedef {
}
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone, Encodable, Decodable, PartialEq)]
pub struct BareFunctionDecl {
pub fn_style: ast::FnStyle,
pub generics: Generics,

View file

@ -500,6 +500,9 @@ impl<'a> fmt::Show for Method<'a> {
args.push_str(format!("&amp;{}self",
MutableSpace(mtbl)).as_slice());
}
clean::SelfExplicit(ref typ) => {
args.push_str(format!("self: {}", *typ).as_slice());
}
}
for (i, input) in d.inputs.values.iter().enumerate() {
if i > 0 || args.len() > 0 { args.push_str(", "); }

View file

@ -949,12 +949,14 @@ pub enum RetStyle {
pub enum ExplicitSelf_ {
/// No self
SelfStatic,
/// `self
/// `self`
SelfValue(Ident),
/// `&'lt self`, `&'lt mut self`
SelfRegion(Option<Lifetime>, Mutability, Ident),
/// `~self`
SelfUniq(Ident)
SelfUniq(Ident),
/// `self: TYPE`
SelfExplicit(P<Ty>, Ident),
}
pub type ExplicitSelf = Spanned<ExplicitSelf_>;

View file

@ -25,8 +25,6 @@ use std::gc::Gc;
/// The types of pointers
pub enum PtrTy<'a> {
/// ~
Send,
/// &'lifetime mut
Borrowed(Option<&'a str>, ast::Mutability),
}
@ -138,9 +136,6 @@ impl<'a> Ty<'a> {
Ptr(ref ty, ref ptr) => {
let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
match *ptr {
Send => {
cx.ty_uniq(span, raw_ty)
}
Borrowed(ref lt, mutbl) => {
let lt = mk_lifetime(cx, span, lt);
cx.ty_rptr(span, raw_ty, lt, mutbl)
@ -260,7 +255,6 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
let self_ty = respan(
span,
match *ptr {
Send => ast::SelfUniq(special_idents::self_),
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
ast::SelfRegion(lt, mutbl, special_idents::self_)

View file

@ -344,6 +344,7 @@ pub trait Folder {
SelfRegion(ref lifetime, m, id) => {
SelfRegion(fold_opt_lifetime(lifetime, self), m, id)
}
SelfExplicit(ref typ, id) => SelfExplicit(self.fold_ty(*typ), id),
}
}

View file

@ -45,7 +45,7 @@ use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
use ast::{SelfRegion, SelfStatic, SelfUniq, SelfValue};
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfUniq, SelfValue};
use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
@ -3843,7 +3843,15 @@ impl<'a> Parser<'a> {
}
}
token::IDENT(..) if self.is_self_ident() => {
SelfValue(self.expect_self_ident())
let self_ident = self.expect_self_ident();
// Determine whether this is the fully explicit form, `self:
// TYPE`.
if self.eat(&token::COLON) {
SelfExplicit(self.parse_ty(false), self_ident)
} else {
SelfValue(self_ident)
}
}
token::BINOP(token::STAR) => {
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
@ -3851,7 +3859,9 @@ impl<'a> Parser<'a> {
self.bump();
let _mutability = if Parser::token_is_mutability(&self.token) {
self.parse_mutability()
} else { MutImmutable };
} else {
MutImmutable
};
if self.is_self_ident() {
let span = self.span;
self.span_err(span, "cannot pass self by unsafe pointer");
@ -3863,7 +3873,15 @@ impl<'a> Parser<'a> {
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
mutbl_self = self.parse_mutability();
SelfValue(self.expect_self_ident())
let self_ident = self.expect_self_ident();
// Determine whether this is the fully explicit form, `self:
// TYPE`.
if self.eat(&token::COLON) {
SelfExplicit(self.parse_ty(false), self_ident)
} else {
SelfValue(self_ident)
}
}
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| *t == token::TILDE) &&
@ -3914,8 +3932,8 @@ impl<'a> Parser<'a> {
}
SelfValue(id) => parse_remaining_arguments!(id),
SelfRegion(_,_,id) => parse_remaining_arguments!(id),
SelfUniq(id) => parse_remaining_arguments!(id)
SelfUniq(id) => parse_remaining_arguments!(id),
SelfExplicit(_,id) => parse_remaining_arguments!(id),
};

View file

@ -1859,6 +1859,11 @@ impl<'a> State<'a> {
try!(self.print_mutability(m));
try!(word(&mut self.s, "self"));
}
ast::SelfExplicit(ref typ, _) => {
try!(word(&mut self.s, "self"));
try!(self.word_space(":"));
try!(self.print_type(*typ));
}
}
return Ok(true);
}

View file

@ -215,6 +215,7 @@ pub fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
SelfRegion(ref lifetime, _, _) => {
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
}
SelfExplicit(ref typ, _) => visitor.visit_ty(*typ, env.clone()),
}
}

View file

@ -0,0 +1,26 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo<'a,'b> {
x: &'a int,
y: &'b int,
}
impl<'a,'b> Foo<'a,'b> {
// The number of errors is related to the way invariance works.
fn bar(self: Foo<'b,'a>) {}
//~^ ERROR mismatched types: expected `Foo<'a,'b>` but found `Foo<'b,'a>`
//~^^ ERROR mismatched types: expected `Foo<'a,'b>` but found `Foo<'b,'a>`
//~^^^ ERROR mismatched types: expected `Foo<'b,'a>` but found `Foo<'a,'b>`
//~^^^^ ERROR mismatched types: expected `Foo<'b,'a>` but found `Foo<'a,'b>`
}
fn main() {}

View file

@ -11,11 +11,11 @@
// error-pattern: type `&Foo` does not implement any method in scope named `foo`
trait Foo {
fn foo(~self);
fn foo(self: Box<Self>);
}
impl Foo for int {
fn foo(~self) { }
fn foo(self: Box<int>) { }
}
fn main() {

View file

@ -16,7 +16,7 @@
struct Foo;
impl Foo {
fn foo(mut self) {} //~ ERROR: variable does not need to be mutable
fn bar(mut ~self) {} //~ ERROR: variable does not need to be mutable
fn bar(mut self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable
}
fn main() {}

View file

@ -13,7 +13,7 @@ trait Foo {
fn borrowed(&self);
fn borrowed_mut(&mut self);
fn owned(~self);
fn owned(self: Box<Self>);
}
fn borrowed_receiver(x: &Foo) {

View file

@ -0,0 +1,49 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::owned::Box;
struct Foo {
f: int,
}
impl Foo {
fn foo(self: int, x: int) -> int { //~ ERROR mismatched self type
//~^ ERROR not a valid type for `self`
self.f + x
}
}
struct Bar<T> {
f: T,
}
impl<T> Bar<T> {
fn foo(self: Bar<int>, x: int) -> int { //~ ERROR mismatched self type
//~^ ERROR not a valid type for `self`
x
}
fn bar(self: &Bar<uint>, x: int) -> int { //~ ERROR mismatched self type
//~^ ERROR not a valid type for `self`
x
}
}
fn main() {
let foo = box Foo {
f: 1,
};
println!("{}", foo.foo(2));
let bar = box Bar {
f: 1,
};
println!("{} {}", bar.foo(2), bar.bar(2));
}

View file

@ -134,7 +134,7 @@ impl<T1> Struct<T1> {
arg1
}
fn self_owned<T2>(~self, arg1: int, arg2: T2) -> int {
fn self_owned<T2>(self: Box<Struct<T1>>, arg1: int, arg2: T2) -> int {
zzz(); // #break
arg1
}

View file

@ -136,7 +136,7 @@ impl Enum {
arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<Enum>, arg1: int, arg2: int) -> int {
zzz(); // #break
arg1 + arg2
}

View file

@ -134,7 +134,7 @@ impl<T> Struct<T> {
arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<Struct<T>>, arg1: int, arg2: int) -> int {
zzz(); // #break
arg1 + arg2
}

View file

@ -133,7 +133,7 @@ impl Struct {
self.x + arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<Struct>, arg1: int, arg2: int) -> int {
zzz(); // #break
self.x + arg1 + arg2
}

View file

@ -124,7 +124,7 @@ struct Struct {
trait Trait {
fn self_by_ref(&self, arg1: int, arg2: int) -> int;
fn self_by_val(self, arg1: int, arg2: int) -> int;
fn self_owned(~self, arg1: int, arg2: int) -> int;
fn self_owned(self: Box<Self>, arg1: int, arg2: int) -> int;
}
impl Trait for Struct {
@ -139,7 +139,7 @@ impl Trait for Struct {
self.x + arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<Struct>, arg1: int, arg2: int) -> int {
zzz(); // #break
self.x + arg1 + arg2
}

View file

@ -131,7 +131,7 @@ impl TupleStruct {
arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<TupleStruct>, arg1: int, arg2: int) -> int {
zzz(); // #break
arg1 + arg2
}

View file

@ -133,7 +133,7 @@ trait Trait {
arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
fn self_owned(self: Box<Self>, arg1: int, arg2: int) -> int {
zzz(); // #break
arg1 + arg2
}

View file

@ -134,7 +134,7 @@ trait Trait {
arg1
}
fn self_owned<T>(~self, arg1: int, arg2: T) -> int {
fn self_owned<T>(self: Box<Self>, arg1: int, arg2: T) -> int {
zzz(); // #break
arg1
}

View file

@ -10,11 +10,11 @@
trait double {
fn double(~self) -> uint;
fn double(self: Box<Self>) -> uint;
}
impl double for uint {
fn double(~self) -> uint { *self * 2u }
fn double(self: Box<uint>) -> uint { *self * 2u }
}
pub fn main() {

View file

@ -10,11 +10,11 @@
trait double {
fn double(~self) -> uint;
fn double(self: Box<Self>) -> uint;
}
impl double for Box<uint> {
fn double(~self) -> uint { **self * 2u }
fn double(self: Box<Box<uint>>) -> uint { **self * 2u }
}
pub fn main() {

View file

@ -9,11 +9,11 @@
// except according to those terms.
trait double {
fn double(~self) -> uint;
fn double(self: Box<Self>) -> uint;
}
impl double for uint {
fn double(~self) -> uint { *self * 2u }
fn double(self: Box<uint>) -> uint { *self * 2u }
}
pub fn main() {

View file

@ -9,11 +9,11 @@
// except according to those terms.
trait double {
fn double(~self) -> uint;
fn double(self: Box<Self>) -> uint;
}
impl double for uint {
fn double(~self) -> uint { *self * 2u }
fn double(self: Box<uint>) -> uint { *self * 2u }
}
pub fn main() {

View file

@ -10,7 +10,7 @@
trait Foo {
fn f(~self);
fn f(self: Box<Self>);
}
struct S {
@ -18,7 +18,7 @@ struct S {
}
impl Foo for S {
fn f(~self) {
fn f(self: Box<S>) {
assert_eq!(self.x, 3);
}
}

View file

@ -57,7 +57,7 @@ fn thing(x: A) -> thing {
}
impl thing {
pub fn bar(~self) -> int { self.x.a }
pub fn bar(self: Box<thing>) -> int { self.x.a }
pub fn quux(&self) -> int { self.x.a }
pub fn baz<'a>(&'a self) -> &'a A { &self.x }
pub fn spam(self) -> int { self.x.a }

View file

@ -10,7 +10,7 @@
trait Foo {
fn foo(~self) { bar(self as Box<Foo>); }
fn foo(self: Box<Self>) { bar(self as Box<Foo>); }
}
fn bar(_b: Box<Foo>) { }

View file

@ -14,7 +14,7 @@
trait FooTrait {
fn foo(~self) -> uint;
fn foo(self: Box<Self>) -> uint;
}
struct BarStruct {
@ -22,7 +22,7 @@ struct BarStruct {
}
impl FooTrait for BarStruct {
fn foo(~self) -> uint {
fn foo(self: Box<BarStruct>) -> uint {
self.x
}
}

View file

@ -19,7 +19,7 @@ trait Changer {
self
}
fn change_again(mut ~self) -> Box<Self> {
fn change_again(mut self: Box<Self>) -> Box<Self> {
self.set_to(45);
self
}

View file

@ -0,0 +1,57 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::owned::Box;
struct Foo {
f: int,
}
impl Foo {
fn foo(self: Foo, x: int) -> int {
self.f + x
}
fn bar(self: &Foo, x: int) -> int {
self.f + x
}
fn baz(self: Box<Foo>, x: int) -> int {
self.f + x
}
}
struct Bar<T> {
f: T,
}
impl<T> Bar<T> {
fn foo(self: Bar<T>, x: int) -> int {
x
}
fn bar<'a>(self: &'a Bar<T>, x: int) -> int {
x
}
fn baz(self: Bar<T>, x: int) -> int {
x
}
}
fn main() {
let foo = box Foo {
f: 1,
};
println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2));
let bar = box Bar {
f: 1,
};
println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2));
let bar: Box<Bar<int>> = bar;
println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2));
}

View file

@ -14,11 +14,11 @@ struct X {
}
trait Changer {
fn change(mut ~self) -> Box<Self>;
fn change(mut self: Box<Self>) -> Box<Self>;
}
impl Changer for X {
fn change(mut ~self) -> Box<X> {
fn change(mut self: Box<X>) -> Box<X> {
self.a = 55;
self
}