auto merge of #14022 : pcwalton/rust/explicit-self, r=pnkfelix
r? @nikomatsakis
This commit is contained in:
commit
32cb44bfff
47 changed files with 662 additions and 192 deletions
|
@ -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)
|
||||
|
|
|
@ -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>,
|
||||
pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 => {}
|
||||
}
|
||||
|
|
|
@ -502,15 +502,12 @@ fn emit_vtable_methods(bcx: &Block,
|
|||
ExprId(0),
|
||||
substs.clone(),
|
||||
vtables.clone());
|
||||
match m.explicit_self {
|
||||
ast::SelfValue(_) => {
|
||||
if m.explicit_self == ty::ByValueExplicitSelfCategory {
|
||||
fn_ref = trans_unboxing_shim(bcx,
|
||||
fn_ref,
|
||||
&*m,
|
||||
m_id,
|
||||
substs.clone());
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
fn_ref
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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,9 +900,9 @@ 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>(
|
||||
|
@ -912,46 +912,61 @@ pub fn ty_of_method<AC:AstConv>(
|
|||
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 {
|
||||
-> (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,
|
||||
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 {
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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",
|
||||
(&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),
|
||||
pprust::explicit_self_to_string(impl_m.explicit_self));
|
||||
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",
|
||||
(_, &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),
|
||||
pprust::explicit_self_to_string(trait_m.explicit_self));
|
||||
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) {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
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(),
|
||||
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());
|
||||
*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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(..)) |
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -500,6 +500,9 @@ impl<'a> fmt::Show for Method<'a> {
|
|||
args.push_str(format!("&{}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(", "); }
|
||||
|
|
|
@ -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_>;
|
||||
|
|
|
@ -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_)
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
26
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
Normal file
26
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
Normal 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() {}
|
||||
|
|
@ -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() {
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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) {
|
||||
|
|
49
src/test/compile-fail/ufcs-explicit-self-bad.rs
Normal file
49
src/test/compile-fail/ufcs-explicit-self-bad.rs
Normal 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));
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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>) { }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
57
src/test/run-pass/ufcs-explicit-self.rs
Normal file
57
src/test/run-pass/ufcs-explicit-self.rs
Normal 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));
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue