Skip to content

Commit

Permalink
auto merge of #14022 : pcwalton/rust/explicit-self, r=pnkfelix
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Jul 17, 2014
2 parents 459ffc2 + 00c70d1 commit 32cb44b
Show file tree
Hide file tree
Showing 47 changed files with 662 additions and 192 deletions.
3 changes: 2 additions & 1 deletion src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
25 changes: 14 additions & 11 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
}
}
Expand All @@ -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);
Expand Down
31 changes: 19 additions & 12 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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));
Expand All @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
67 changes: 54 additions & 13 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
};

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
});
}
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 => {}
}
Expand Down
15 changes: 6 additions & 9 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
18 changes: 16 additions & 2 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
}

Loading

0 comments on commit 32cb44b

Please sign in to comment.