Skip to content

Commit 357d5cd

Browse files
committed
librustc: Implement the fully-expanded, UFCS form of explicit self.
This makes two changes to region inference: (1) it allows region inference to relate early-bound regions; and (2) it allows regions to be related before variance runs. The former is needed because there is no relation between the two regions before region substitution happens, while the latter is needed because type collection has to run before variance. We assume that, before variance is inferred, that lifetimes are invariant. This is a conservative overapproximation. This relates to rust-lang#13885. This does not remove `~self` from the language yet, however. [breaking-change]
1 parent 459ffc2 commit 357d5cd

File tree

25 files changed

+633
-157
lines changed

25 files changed

+633
-157
lines changed

src/librustc/metadata/csearch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
132132

133133
pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
134134
def: ast::DefId)
135-
-> (ast::Ident, ast::ExplicitSelf_)
135+
-> (ast::Ident,
136+
ty::ExplicitSelfCategory)
136137
{
137138
let cdata = cstore.get_crate_data(def.krate);
138139
decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)

src/librustc/metadata/decoder.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
724724
}).collect()
725725
}
726726

727-
fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
727+
fn get_explicit_self(item: ebml::Doc) -> ty::ExplicitSelfCategory {
728728
fn get_mutability(ch: u8) -> ast::Mutability {
729729
match ch as char {
730730
'i' => ast::MutImmutable,
@@ -738,12 +738,15 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
738738

739739
let explicit_self_kind = string.as_bytes()[0];
740740
match explicit_self_kind as char {
741-
's' => ast::SelfStatic,
742-
'v' => ast::SelfValue(special_idents::self_),
743-
'~' => ast::SelfUniq(special_idents::self_),
741+
's' => ty::StaticExplicitSelfCategory,
742+
'v' => ty::ByValueExplicitSelfCategory,
743+
'~' => ty::ByBoxExplicitSelfCategory,
744744
// FIXME(#4846) expl. region
745-
'&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1]),
746-
special_idents::self_),
745+
'&' => {
746+
ty::ByReferenceExplicitSelfCategory(
747+
ty::ReEmpty,
748+
get_mutability(string.as_bytes()[1]))
749+
}
747750
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
748751
}
749752
}
@@ -761,11 +764,11 @@ pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
761764
methods
762765
}
763766

764-
pub fn get_method_name_and_explicit_self(
765-
intr: Rc<IdentInterner>,
766-
cdata: Cmd,
767-
id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_)
768-
{
767+
pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
768+
cdata: Cmd,
769+
id: ast::NodeId)
770+
-> (ast::Ident,
771+
ty::ExplicitSelfCategory) {
769772
let method_doc = lookup_item(id, cdata.data());
770773
let name = item_name(&*intr, method_doc);
771774
let explicit_self = get_explicit_self(method_doc);

src/librustc/metadata/encoder.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
402402
for base_impl_did in implementations.borrow().iter() {
403403
for &method_did in impl_methods.get(base_impl_did).iter() {
404404
let m = ty::method(ecx.tcx, method_did);
405-
if m.explicit_self == ast::SelfStatic {
405+
if m.explicit_self == ty::StaticExplicitSelfCategory {
406406
encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
407407
}
408408
}
@@ -421,7 +421,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
421421
match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
422422
Some(methods) => {
423423
for m in methods.iter() {
424-
if m.explicit_self == ast::SelfStatic {
424+
if m.explicit_self == ty::StaticExplicitSelfCategory {
425425
encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
426426
}
427427
}
@@ -623,15 +623,22 @@ fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
623623
ebml_w.end_tag();
624624
}
625625

626-
fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
626+
fn encode_explicit_self(ebml_w: &mut Encoder,
627+
explicit_self: &ty::ExplicitSelfCategory) {
627628
ebml_w.start_tag(tag_item_trait_method_explicit_self);
628629

629630
// Encode the base self type.
630-
match explicit_self {
631-
SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
632-
SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
633-
SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
634-
SelfRegion(_, m, _) => {
631+
match *explicit_self {
632+
ty::StaticExplicitSelfCategory => {
633+
ebml_w.writer.write(&[ 's' as u8 ]);
634+
}
635+
ty::ByValueExplicitSelfCategory => {
636+
ebml_w.writer.write(&[ 'v' as u8 ]);
637+
}
638+
ty::ByBoxExplicitSelfCategory => {
639+
ebml_w.writer.write(&[ '~' as u8 ]);
640+
}
641+
ty::ByReferenceExplicitSelfCategory(_, m) => {
635642
// FIXME(#4846) encode custom lifetime
636643
ebml_w.writer.write(&['&' as u8]);
637644
encode_mutability(ebml_w, m);
@@ -748,10 +755,10 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
748755
tag_item_method_tps);
749756
encode_method_fty(ecx, ebml_w, &method_ty.fty);
750757
encode_visibility(ebml_w, method_ty.vis);
751-
encode_explicit_self(ebml_w, method_ty.explicit_self);
758+
encode_explicit_self(ebml_w, &method_ty.explicit_self);
752759
let fn_style = method_ty.fty.fn_style;
753760
match method_ty.explicit_self {
754-
ast::SelfStatic => {
761+
ty::StaticExplicitSelfCategory => {
755762
encode_family(ebml_w, fn_style_static_method_family(fn_style));
756763
}
757764
_ => encode_family(ebml_w, style_fn_family(fn_style))
@@ -1206,7 +1213,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
12061213
encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
12071214

12081215
match method_ty.explicit_self {
1209-
SelfStatic => {
1216+
ty::StaticExplicitSelfCategory => {
12101217
encode_family(ebml_w,
12111218
fn_style_static_method_family(
12121219
method_ty.fty.fn_style));
@@ -1233,7 +1240,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
12331240
encode_attributes(ebml_w, m.attrs.as_slice());
12341241
// If this is a static method, we've already encoded
12351242
// this.
1236-
if method_ty.explicit_self != SelfStatic {
1243+
if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
12371244
// FIXME: I feel like there is something funny going on.
12381245
let pty = ty::lookup_item_type(tcx, method_def_id);
12391246
encode_bounds_and_type(ebml_w, ecx, &pty);

src/librustc/middle/region.rs

+10
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ impl RegionMaps {
314314
self.sub_free_region(sub_fr, super_fr)
315315
}
316316

317+
(ty::ReEarlyBound(param_id_a, param_space_a, index_a, _),
318+
ty::ReEarlyBound(param_id_b, param_space_b, index_b, _)) => {
319+
// This case is used only to make sure that explicitly-
320+
// specified `Self` types match the real self type in
321+
// implementations.
322+
param_id_a == param_id_b &&
323+
param_space_a == param_space_b &&
324+
index_a == index_b
325+
}
326+
317327
_ => {
318328
false
319329
}

src/librustc/middle/resolve.rs

+54-13
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
#![allow(non_camel_case_types)]
1212

1313
use driver::session::Session;
14+
use lint;
1415
use metadata::csearch;
1516
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
1617
use middle::def::*;
1718
use middle::lang_items::LanguageItems;
1819
use middle::pat_util::pat_bindings;
1920
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
20-
use lint;
21+
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
2122
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
2223

2324
use syntax::ast::*;
@@ -287,6 +288,24 @@ enum ModulePrefixResult {
287288
PrefixFound(Rc<Module>, uint)
288289
}
289290

291+
#[deriving(Clone, Eq, PartialEq)]
292+
enum MethodIsStaticFlag {
293+
MethodIsNotStatic,
294+
MethodIsStatic,
295+
}
296+
297+
impl MethodIsStaticFlag {
298+
fn from_explicit_self_category(explicit_self_category:
299+
ExplicitSelfCategory)
300+
-> MethodIsStaticFlag {
301+
if explicit_self_category == StaticExplicitSelfCategory {
302+
MethodIsStatic
303+
} else {
304+
MethodIsNotStatic
305+
}
306+
}
307+
}
308+
290309
#[deriving(PartialEq)]
291310
enum NameSearchType {
292311
/// We're doing a name search in order to resolve a `use` directive.
@@ -805,7 +824,8 @@ struct Resolver<'a> {
805824

806825
graph_root: NameBindings,
807826

808-
method_map: RefCell<FnvHashMap<(Name, DefId), ast::ExplicitSelf_>>,
827+
method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
828+
809829
structs: FnvHashMap<DefId, Vec<Name>>,
810830

811831
// The number of imports that are currently unresolved.
@@ -1361,17 +1381,19 @@ impl<'a> Resolver<'a> {
13611381
let ident = ty_m.ident;
13621382

13631383
// Add it as a name in the trait module.
1364-
let def = match ty_m.explicit_self.node {
1384+
let (def, static_flag) = match ty_m.explicit_self.node {
13651385
SelfStatic => {
13661386
// Static methods become `def_static_method`s.
1367-
DefStaticMethod(local_def(ty_m.id),
1387+
(DefStaticMethod(local_def(ty_m.id),
13681388
FromTrait(local_def(item.id)),
1369-
ty_m.fn_style)
1389+
ty_m.fn_style),
1390+
MethodIsStatic)
13701391
}
13711392
_ => {
13721393
// Non-static methods become `def_method`s.
1373-
DefMethod(local_def(ty_m.id),
1374-
Some(local_def(item.id)))
1394+
(DefMethod(local_def(ty_m.id),
1395+
Some(local_def(item.id))),
1396+
MethodIsNotStatic)
13751397
}
13761398
};
13771399

@@ -1382,8 +1404,9 @@ impl<'a> Resolver<'a> {
13821404
ty_m.span);
13831405
method_name_bindings.define_value(def, ty_m.span, true);
13841406

1385-
self.method_map.borrow_mut().insert((ident.name, def_id),
1386-
ty_m.explicit_self.node);
1407+
self.method_map
1408+
.borrow_mut()
1409+
.insert((ident.name, def_id), static_flag);
13871410
}
13881411

13891412
name_bindings.define_type(DefTrait(def_id), sp, is_public);
@@ -1670,7 +1693,11 @@ impl<'a> Resolver<'a> {
16701693
trait method '{}'",
16711694
token::get_ident(method_name));
16721695

1673-
self.method_map.borrow_mut().insert((method_name.name, def_id), explicit_self);
1696+
self.method_map
1697+
.borrow_mut()
1698+
.insert((method_name.name, def_id),
1699+
MethodIsStaticFlag::from_explicit_self_category(
1700+
explicit_self));
16741701

16751702
if is_exported {
16761703
self.external_exports.insert(method_def_id);
@@ -3678,6 +3705,13 @@ impl<'a> Resolver<'a> {
36783705
this.resolve_type(&*argument.ty);
36793706
}
36803707

3708+
match ty_m.explicit_self.node {
3709+
SelfExplicit(ref typ, _) => {
3710+
this.resolve_type(*typ)
3711+
}
3712+
_ => {}
3713+
}
3714+
36813715
this.resolve_type(&*ty_m.decl.output);
36823716
});
36833717
}
@@ -4009,7 +4043,14 @@ impl<'a> Resolver<'a> {
40094043
method.id,
40104044
rib_kind);
40114045

4012-
self.resolve_function(rib_kind, Some(method.pe_fn_decl()), type_parameters,
4046+
match method.pe_explicit_self().node {
4047+
SelfExplicit(ref typ, _) => self.resolve_type(*typ),
4048+
_ => {}
4049+
}
4050+
4051+
self.resolve_function(rib_kind,
4052+
Some(method.pe_fn_decl()),
4053+
type_parameters,
40134054
method.pe_body());
40144055
}
40154056

@@ -4765,7 +4806,7 @@ impl<'a> Resolver<'a> {
47654806
match containing_module.def_id.get() {
47664807
Some(def_id) => {
47674808
match self.method_map.borrow().find(&(ident.name, def_id)) {
4768-
Some(x) if *x == SelfStatic => (),
4809+
Some(&MethodIsStatic) => (),
47694810
None => (),
47704811
_ => {
47714812
debug!("containing module was a trait or impl \
@@ -5037,7 +5078,7 @@ impl<'a> Resolver<'a> {
50375078
let path_str = self.path_idents_to_string(&trait_ref.path);
50385079

50395080
match method_map.find(&(name, did)) {
5040-
Some(&SelfStatic) => return StaticTraitMethod(path_str),
5081+
Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
50415082
Some(_) => return TraitMethod,
50425083
None => {}
50435084
}

src/librustc/middle/trans/meth.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -502,15 +502,12 @@ fn emit_vtable_methods(bcx: &Block,
502502
ExprId(0),
503503
substs.clone(),
504504
vtables.clone());
505-
match m.explicit_self {
506-
ast::SelfValue(_) => {
507-
fn_ref = trans_unboxing_shim(bcx,
508-
fn_ref,
509-
&*m,
510-
m_id,
511-
substs.clone());
512-
},
513-
_ => {}
505+
if m.explicit_self == ty::ByValueExplicitSelfCategory {
506+
fn_ref = trans_unboxing_shim(bcx,
507+
fn_ref,
508+
&*m,
509+
m_id,
510+
substs.clone());
514511
}
515512
fn_ref
516513
}

src/librustc/middle/ty.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub struct Method {
8585
pub ident: ast::Ident,
8686
pub generics: ty::Generics,
8787
pub fty: BareFnTy,
88-
pub explicit_self: ast::ExplicitSelf_,
88+
pub explicit_self: ExplicitSelfCategory,
8989
pub vis: ast::Visibility,
9090
pub def_id: ast::DefId,
9191
pub container: MethodContainer,
@@ -98,7 +98,7 @@ impl Method {
9898
pub fn new(ident: ast::Ident,
9999
generics: ty::Generics,
100100
fty: BareFnTy,
101-
explicit_self: ast::ExplicitSelf_,
101+
explicit_self: ExplicitSelfCategory,
102102
vis: ast::Visibility,
103103
def_id: ast::DefId,
104104
container: MethodContainer,
@@ -311,6 +311,9 @@ pub struct ctxt {
311311
/// (inferred) variance.
312312
pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
313313

314+
/// True if the variance has been computed yet; false otherwise.
315+
pub variance_computed: Cell<bool>,
316+
314317
/// A mapping from the def ID of an enum or struct type to the def ID
315318
/// of the method that implements its destructor. If the type is not
316319
/// present in this map, it does not have a destructor. This map is
@@ -1055,6 +1058,7 @@ pub fn mk_ctxt(s: Session,
10551058
ctxt {
10561059
named_region_map: named_region_map,
10571060
item_variance_map: RefCell::new(DefIdMap::new()),
1061+
variance_computed: Cell::new(false),
10581062
interner: RefCell::new(FnvHashMap::new()),
10591063
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
10601064
sess: s,
@@ -4767,3 +4771,13 @@ impl mc::Typer for ty::ctxt {
47674771
self.upvar_borrow_map.borrow().get_copy(&upvar_id)
47684772
}
47694773
}
4774+
4775+
/// The category of explicit self.
4776+
#[deriving(Clone, Eq, PartialEq)]
4777+
pub enum ExplicitSelfCategory {
4778+
StaticExplicitSelfCategory,
4779+
ByValueExplicitSelfCategory,
4780+
ByReferenceExplicitSelfCategory(Region, ast::Mutability),
4781+
ByBoxExplicitSelfCategory,
4782+
}
4783+

0 commit comments

Comments
 (0)