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 #13885. This does not remove `~self` from the language yet, however. [breaking-change]
This commit is contained in:
parent
459ffc2adc
commit
357d5cd96c
25 changed files with 633 additions and 157 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,
|
pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
|
||||||
def: ast::DefId)
|
def: ast::DefId)
|
||||||
-> (ast::Ident, ast::ExplicitSelf_)
|
-> (ast::Ident,
|
||||||
|
ty::ExplicitSelfCategory)
|
||||||
{
|
{
|
||||||
let cdata = cstore.get_crate_data(def.krate);
|
let cdata = cstore.get_crate_data(def.krate);
|
||||||
decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
|
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()
|
}).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 {
|
fn get_mutability(ch: u8) -> ast::Mutability {
|
||||||
match ch as char {
|
match ch as char {
|
||||||
'i' => ast::MutImmutable,
|
'i' => ast::MutImmutable,
|
||||||
|
@ -738,12 +738,15 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
|
||||||
|
|
||||||
let explicit_self_kind = string.as_bytes()[0];
|
let explicit_self_kind = string.as_bytes()[0];
|
||||||
match explicit_self_kind as char {
|
match explicit_self_kind as char {
|
||||||
's' => ast::SelfStatic,
|
's' => ty::StaticExplicitSelfCategory,
|
||||||
'v' => ast::SelfValue(special_idents::self_),
|
'v' => ty::ByValueExplicitSelfCategory,
|
||||||
'~' => ast::SelfUniq(special_idents::self_),
|
'~' => ty::ByBoxExplicitSelfCategory,
|
||||||
// FIXME(#4846) expl. region
|
// 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)
|
_ => 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
|
methods
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_method_name_and_explicit_self(
|
pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
|
||||||
intr: Rc<IdentInterner>,
|
cdata: Cmd,
|
||||||
cdata: Cmd,
|
id: ast::NodeId)
|
||||||
id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_)
|
-> (ast::Ident,
|
||||||
{
|
ty::ExplicitSelfCategory) {
|
||||||
let method_doc = lookup_item(id, cdata.data());
|
let method_doc = lookup_item(id, cdata.data());
|
||||||
let name = item_name(&*intr, method_doc);
|
let name = item_name(&*intr, method_doc);
|
||||||
let explicit_self = get_explicit_self(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 base_impl_did in implementations.borrow().iter() {
|
||||||
for &method_did in impl_methods.get(base_impl_did).iter() {
|
for &method_did in impl_methods.get(base_impl_did).iter() {
|
||||||
let m = ty::method(ecx.tcx, method_did);
|
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);
|
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) {
|
match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
|
||||||
Some(methods) => {
|
Some(methods) => {
|
||||||
for m in methods.iter() {
|
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);
|
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();
|
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);
|
ebml_w.start_tag(tag_item_trait_method_explicit_self);
|
||||||
|
|
||||||
// Encode the base self type.
|
// Encode the base self type.
|
||||||
match explicit_self {
|
match *explicit_self {
|
||||||
SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
|
ty::StaticExplicitSelfCategory => {
|
||||||
SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
|
ebml_w.writer.write(&[ 's' as u8 ]);
|
||||||
SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
|
}
|
||||||
SelfRegion(_, m, _) => {
|
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
|
// FIXME(#4846) encode custom lifetime
|
||||||
ebml_w.writer.write(&['&' as u8]);
|
ebml_w.writer.write(&['&' as u8]);
|
||||||
encode_mutability(ebml_w, m);
|
encode_mutability(ebml_w, m);
|
||||||
|
@ -748,10 +755,10 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
|
||||||
tag_item_method_tps);
|
tag_item_method_tps);
|
||||||
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
||||||
encode_visibility(ebml_w, method_ty.vis);
|
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;
|
let fn_style = method_ty.fty.fn_style;
|
||||||
match method_ty.explicit_self {
|
match method_ty.explicit_self {
|
||||||
ast::SelfStatic => {
|
ty::StaticExplicitSelfCategory => {
|
||||||
encode_family(ebml_w, fn_style_static_method_family(fn_style));
|
encode_family(ebml_w, fn_style_static_method_family(fn_style));
|
||||||
}
|
}
|
||||||
_ => encode_family(ebml_w, style_fn_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()));
|
encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
|
||||||
|
|
||||||
match method_ty.explicit_self {
|
match method_ty.explicit_self {
|
||||||
SelfStatic => {
|
ty::StaticExplicitSelfCategory => {
|
||||||
encode_family(ebml_w,
|
encode_family(ebml_w,
|
||||||
fn_style_static_method_family(
|
fn_style_static_method_family(
|
||||||
method_ty.fty.fn_style));
|
method_ty.fty.fn_style));
|
||||||
|
@ -1233,7 +1240,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||||
encode_attributes(ebml_w, m.attrs.as_slice());
|
encode_attributes(ebml_w, m.attrs.as_slice());
|
||||||
// If this is a static method, we've already encoded
|
// If this is a static method, we've already encoded
|
||||||
// this.
|
// this.
|
||||||
if method_ty.explicit_self != SelfStatic {
|
if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
|
||||||
// FIXME: I feel like there is something funny going on.
|
// FIXME: I feel like there is something funny going on.
|
||||||
let pty = ty::lookup_item_type(tcx, method_def_id);
|
let pty = ty::lookup_item_type(tcx, method_def_id);
|
||||||
encode_bounds_and_type(ebml_w, ecx, &pty);
|
encode_bounds_and_type(ebml_w, ecx, &pty);
|
||||||
|
|
|
@ -314,6 +314,16 @@ impl RegionMaps {
|
||||||
self.sub_free_region(sub_fr, super_fr)
|
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
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,14 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use driver::session::Session;
|
use driver::session::Session;
|
||||||
|
use lint;
|
||||||
use metadata::csearch;
|
use metadata::csearch;
|
||||||
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
||||||
use middle::def::*;
|
use middle::def::*;
|
||||||
use middle::lang_items::LanguageItems;
|
use middle::lang_items::LanguageItems;
|
||||||
use middle::pat_util::pat_bindings;
|
use middle::pat_util::pat_bindings;
|
||||||
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
|
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
|
||||||
use lint;
|
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
|
||||||
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
|
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
|
||||||
|
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
|
@ -287,6 +288,24 @@ enum ModulePrefixResult {
|
||||||
PrefixFound(Rc<Module>, uint)
|
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)]
|
#[deriving(PartialEq)]
|
||||||
enum NameSearchType {
|
enum NameSearchType {
|
||||||
/// We're doing a name search in order to resolve a `use` directive.
|
/// We're doing a name search in order to resolve a `use` directive.
|
||||||
|
@ -805,7 +824,8 @@ struct Resolver<'a> {
|
||||||
|
|
||||||
graph_root: NameBindings,
|
graph_root: NameBindings,
|
||||||
|
|
||||||
method_map: RefCell<FnvHashMap<(Name, DefId), ast::ExplicitSelf_>>,
|
method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
|
||||||
|
|
||||||
structs: FnvHashMap<DefId, Vec<Name>>,
|
structs: FnvHashMap<DefId, Vec<Name>>,
|
||||||
|
|
||||||
// The number of imports that are currently unresolved.
|
// The number of imports that are currently unresolved.
|
||||||
|
@ -1361,17 +1381,19 @@ impl<'a> Resolver<'a> {
|
||||||
let ident = ty_m.ident;
|
let ident = ty_m.ident;
|
||||||
|
|
||||||
// Add it as a name in the trait module.
|
// 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 => {
|
SelfStatic => {
|
||||||
// Static methods become `def_static_method`s.
|
// Static methods become `def_static_method`s.
|
||||||
DefStaticMethod(local_def(ty_m.id),
|
(DefStaticMethod(local_def(ty_m.id),
|
||||||
FromTrait(local_def(item.id)),
|
FromTrait(local_def(item.id)),
|
||||||
ty_m.fn_style)
|
ty_m.fn_style),
|
||||||
|
MethodIsStatic)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Non-static methods become `def_method`s.
|
// Non-static methods become `def_method`s.
|
||||||
DefMethod(local_def(ty_m.id),
|
(DefMethod(local_def(ty_m.id),
|
||||||
Some(local_def(item.id)))
|
Some(local_def(item.id))),
|
||||||
|
MethodIsNotStatic)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1382,8 +1404,9 @@ impl<'a> Resolver<'a> {
|
||||||
ty_m.span);
|
ty_m.span);
|
||||||
method_name_bindings.define_value(def, ty_m.span, true);
|
method_name_bindings.define_value(def, ty_m.span, true);
|
||||||
|
|
||||||
self.method_map.borrow_mut().insert((ident.name, def_id),
|
self.method_map
|
||||||
ty_m.explicit_self.node);
|
.borrow_mut()
|
||||||
|
.insert((ident.name, def_id), static_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
name_bindings.define_type(DefTrait(def_id), sp, is_public);
|
name_bindings.define_type(DefTrait(def_id), sp, is_public);
|
||||||
|
@ -1670,7 +1693,11 @@ impl<'a> Resolver<'a> {
|
||||||
trait method '{}'",
|
trait method '{}'",
|
||||||
token::get_ident(method_name));
|
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 {
|
if is_exported {
|
||||||
self.external_exports.insert(method_def_id);
|
self.external_exports.insert(method_def_id);
|
||||||
|
@ -3678,6 +3705,13 @@ impl<'a> Resolver<'a> {
|
||||||
this.resolve_type(&*argument.ty);
|
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);
|
this.resolve_type(&*ty_m.decl.output);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4009,7 +4043,14 @@ impl<'a> Resolver<'a> {
|
||||||
method.id,
|
method.id,
|
||||||
rib_kind);
|
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());
|
method.pe_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4765,7 +4806,7 @@ impl<'a> Resolver<'a> {
|
||||||
match containing_module.def_id.get() {
|
match containing_module.def_id.get() {
|
||||||
Some(def_id) => {
|
Some(def_id) => {
|
||||||
match self.method_map.borrow().find(&(ident.name, def_id)) {
|
match self.method_map.borrow().find(&(ident.name, def_id)) {
|
||||||
Some(x) if *x == SelfStatic => (),
|
Some(&MethodIsStatic) => (),
|
||||||
None => (),
|
None => (),
|
||||||
_ => {
|
_ => {
|
||||||
debug!("containing module was a trait or impl \
|
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);
|
let path_str = self.path_idents_to_string(&trait_ref.path);
|
||||||
|
|
||||||
match method_map.find(&(name, did)) {
|
match method_map.find(&(name, did)) {
|
||||||
Some(&SelfStatic) => return StaticTraitMethod(path_str),
|
Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
|
||||||
Some(_) => return TraitMethod,
|
Some(_) => return TraitMethod,
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,15 +502,12 @@ fn emit_vtable_methods(bcx: &Block,
|
||||||
ExprId(0),
|
ExprId(0),
|
||||||
substs.clone(),
|
substs.clone(),
|
||||||
vtables.clone());
|
vtables.clone());
|
||||||
match m.explicit_self {
|
if m.explicit_self == ty::ByValueExplicitSelfCategory {
|
||||||
ast::SelfValue(_) => {
|
fn_ref = trans_unboxing_shim(bcx,
|
||||||
fn_ref = trans_unboxing_shim(bcx,
|
fn_ref,
|
||||||
fn_ref,
|
&*m,
|
||||||
&*m,
|
m_id,
|
||||||
m_id,
|
substs.clone());
|
||||||
substs.clone());
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
fn_ref
|
fn_ref
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ pub struct Method {
|
||||||
pub ident: ast::Ident,
|
pub ident: ast::Ident,
|
||||||
pub generics: ty::Generics,
|
pub generics: ty::Generics,
|
||||||
pub fty: BareFnTy,
|
pub fty: BareFnTy,
|
||||||
pub explicit_self: ast::ExplicitSelf_,
|
pub explicit_self: ExplicitSelfCategory,
|
||||||
pub vis: ast::Visibility,
|
pub vis: ast::Visibility,
|
||||||
pub def_id: ast::DefId,
|
pub def_id: ast::DefId,
|
||||||
pub container: MethodContainer,
|
pub container: MethodContainer,
|
||||||
|
@ -98,7 +98,7 @@ impl Method {
|
||||||
pub fn new(ident: ast::Ident,
|
pub fn new(ident: ast::Ident,
|
||||||
generics: ty::Generics,
|
generics: ty::Generics,
|
||||||
fty: BareFnTy,
|
fty: BareFnTy,
|
||||||
explicit_self: ast::ExplicitSelf_,
|
explicit_self: ExplicitSelfCategory,
|
||||||
vis: ast::Visibility,
|
vis: ast::Visibility,
|
||||||
def_id: ast::DefId,
|
def_id: ast::DefId,
|
||||||
container: MethodContainer,
|
container: MethodContainer,
|
||||||
|
@ -311,6 +311,9 @@ pub struct ctxt {
|
||||||
/// (inferred) variance.
|
/// (inferred) variance.
|
||||||
pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
|
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
|
/// 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
|
/// 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
|
/// present in this map, it does not have a destructor. This map is
|
||||||
|
@ -1055,6 +1058,7 @@ pub fn mk_ctxt(s: Session,
|
||||||
ctxt {
|
ctxt {
|
||||||
named_region_map: named_region_map,
|
named_region_map: named_region_map,
|
||||||
item_variance_map: RefCell::new(DefIdMap::new()),
|
item_variance_map: RefCell::new(DefIdMap::new()),
|
||||||
|
variance_computed: Cell::new(false),
|
||||||
interner: RefCell::new(FnvHashMap::new()),
|
interner: RefCell::new(FnvHashMap::new()),
|
||||||
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
|
next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
|
||||||
sess: s,
|
sess: s,
|
||||||
|
@ -4767,3 +4771,13 @@ impl mc::Typer for ty::ctxt {
|
||||||
self.upvar_borrow_map.borrow().get_copy(&upvar_id)
|
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::const_eval;
|
||||||
use middle::def;
|
use middle::def;
|
||||||
use middle::lang_items::FnMutTraitLangItem;
|
use middle::lang_items::FnMutTraitLangItem;
|
||||||
use rl = middle::resolve_lifetime;
|
|
||||||
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck::TypeAndSubsts;
|
use middle::ty_fold::TypeFolder;
|
||||||
use middle::typeck::lookup_def_tcx;
|
|
||||||
use middle::typeck::rscope::RegionScope;
|
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 util::ppaux::Repr;
|
||||||
|
|
||||||
use std::rc::Rc;
|
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,
|
untransformed_self_ty: ty::t,
|
||||||
explicit_self: ast::ExplicitSelf
|
explicit_self: ast::ExplicitSelf,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_of_method<AC:AstConv>(
|
pub fn ty_of_method<AC:AstConv>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
fn_style: ast::FnStyle,
|
fn_style: ast::FnStyle,
|
||||||
untransformed_self_ty: ty::t,
|
untransformed_self_ty: ty::t,
|
||||||
explicit_self: ast::ExplicitSelf,
|
explicit_self: ast::ExplicitSelf,
|
||||||
decl: &ast::FnDecl)
|
decl: &ast::FnDecl)
|
||||||
-> ty::BareFnTy
|
-> (ty::BareFnTy, ty::ExplicitSelfCategory) {
|
||||||
{
|
let self_info = Some(SelfInfo {
|
||||||
ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
|
|
||||||
untransformed_self_ty: untransformed_self_ty,
|
untransformed_self_ty: untransformed_self_ty,
|
||||||
explicit_self: explicit_self
|
explicit_self: explicit_self,
|
||||||
}), decl)
|
});
|
||||||
|
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,
|
pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
|
||||||
fn_style: ast::FnStyle, abi: abi::Abi,
|
fn_style: ast::FnStyle, abi: abi::Abi,
|
||||||
decl: &ast::FnDecl) -> ty::BareFnTy {
|
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 ty_of_method_or_bare_fn<AC:AstConv>(
|
||||||
fn_style: ast::FnStyle, abi: abi::Abi,
|
this: &AC,
|
||||||
opt_self_info: Option<SelfInfo>,
|
id: ast::NodeId,
|
||||||
decl: &ast::FnDecl) -> ty::BareFnTy {
|
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");
|
debug!("ty_of_method_or_bare_fn");
|
||||||
|
|
||||||
// new region names that appear inside of the fn decl are bound to
|
// new region names that appear inside of the fn decl are bound to
|
||||||
// that function type
|
// that function type
|
||||||
let rb = rscope::BindingRscope::new(id);
|
let rb = rscope::BindingRscope::new(id);
|
||||||
|
|
||||||
|
let mut explicit_self_category_result = None;
|
||||||
let self_ty = opt_self_info.and_then(|self_info| {
|
let self_ty = opt_self_info.and_then(|self_info| {
|
||||||
match self_info.explicit_self.node {
|
// Figure out and record the explicit self category.
|
||||||
ast::SelfStatic => None,
|
let explicit_self_category =
|
||||||
ast::SelfValue(_) => {
|
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)
|
Some(self_info.untransformed_self_ty)
|
||||||
}
|
}
|
||||||
ast::SelfRegion(ref lifetime, mutability, _) => {
|
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
|
||||||
let region =
|
|
||||||
opt_ast_region_to_region(this, &rb,
|
|
||||||
self_info.explicit_self.span,
|
|
||||||
lifetime);
|
|
||||||
Some(ty::mk_rptr(this.tcx(), region,
|
Some(ty::mk_rptr(this.tcx(), region,
|
||||||
ty::mt {ty: self_info.untransformed_self_ty,
|
ty::mt {ty: self_info.untransformed_self_ty,
|
||||||
mutbl: mutability}))
|
mutbl: mutability}))
|
||||||
}
|
}
|
||||||
ast::SelfUniq(_) => {
|
ty::ByBoxExplicitSelfCategory => {
|
||||||
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
|
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)
|
_ => ast_ty_to_ty(this, &rb, &*decl.output)
|
||||||
};
|
};
|
||||||
|
|
||||||
return ty::BareFnTy {
|
(ty::BareFnTy {
|
||||||
fn_style: fn_style,
|
fn_style: fn_style,
|
||||||
abi: abi,
|
abi: abi,
|
||||||
sig: ty::FnSig {
|
sig: ty::FnSig {
|
||||||
|
@ -981,7 +996,83 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
|
||||||
output: output_ty,
|
output: output_ty,
|
||||||
variadic: decl.variadic
|
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>(
|
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(),
|
(&None, ty::UniqTraitStore) => ty::empty_builtin_bounds(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,9 +100,7 @@ use util::ppaux::Repr;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast::{DefId, SelfValue, SelfRegion};
|
use syntax::ast::{DefId, MutImmutable, MutMutable};
|
||||||
use syntax::ast::{SelfUniq, SelfStatic};
|
|
||||||
use syntax::ast::{MutMutable, MutImmutable};
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
@ -267,15 +265,15 @@ fn construct_transformed_self_ty_for_object(
|
||||||
obj_substs.types.pop(subst::SelfSpace).unwrap();
|
obj_substs.types.pop(subst::SelfSpace).unwrap();
|
||||||
|
|
||||||
match method_ty.explicit_self {
|
match method_ty.explicit_self {
|
||||||
ast::SelfStatic => {
|
StaticExplicitSelfCategory => {
|
||||||
tcx.sess.span_bug(span, "static method for object type receiver");
|
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,
|
let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
|
||||||
ty::empty_builtin_bounds());
|
ty::empty_builtin_bounds());
|
||||||
ty::mk_uniq(tcx, tr)
|
ty::mk_uniq(tcx, tr)
|
||||||
}
|
}
|
||||||
ast::SelfRegion(..) | ast::SelfUniq(..) => {
|
ByReferenceExplicitSelfCategory(..) | ByBoxExplicitSelfCategory => {
|
||||||
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
|
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
|
||||||
match ty::get(transformed_self_ty).sty {
|
match ty::get(transformed_self_ty).sty {
|
||||||
ty::ty_rptr(r, mt) => { // must be SelfRegion
|
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);
|
let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
|
||||||
match trait_methods.iter().position(|m| {
|
match trait_methods.iter().position(|m| {
|
||||||
m.explicit_self != ast::SelfStatic &&
|
m.explicit_self != ty::StaticExplicitSelfCategory &&
|
||||||
m.ident.name == self.m_name }) {
|
m.ident.name == self.m_name }) {
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
let method = trait_methods.get(pos).clone();
|
let method = trait_methods.get(pos).clone();
|
||||||
|
@ -1023,7 +1021,10 @@ impl<'a> LookupContext<'a> {
|
||||||
|
|
||||||
if self.report_statics == ReportStaticMethods {
|
if self.report_statics == ReportStaticMethods {
|
||||||
// lookup should only be called with ReportStaticMethods if a regular lookup failed
|
// 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,
|
self.tcx().sess.fileline_note(self.span,
|
||||||
"found defined static methods, maybe a `self` is missing?");
|
"found defined static methods, maybe a `self` is missing?");
|
||||||
|
@ -1100,7 +1101,8 @@ impl<'a> LookupContext<'a> {
|
||||||
self.enforce_drop_trait_limitations(candidate);
|
self.enforce_drop_trait_limitations(candidate);
|
||||||
|
|
||||||
// static methods should never have gotten this far:
|
// 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.
|
// Determine the values for the generic parameters of the method.
|
||||||
// If they were not explicitly supplied, just construct fresh
|
// If they were not explicitly supplied, just construct fresh
|
||||||
|
@ -1217,12 +1219,16 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match candidate.method_ty.explicit_self {
|
match candidate.method_ty.explicit_self {
|
||||||
ast::SelfStatic => { // reason (a) above
|
ty::StaticExplicitSelfCategory => { // reason (a) above
|
||||||
span_err!(self.tcx().sess, self.span, E0037,
|
self.tcx().sess.span_err(
|
||||||
"cannot call a method without a receiver through an object");
|
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
|
// reason (a) above
|
||||||
|
@ -1284,12 +1290,12 @@ impl<'a> LookupContext<'a> {
|
||||||
self.ty_to_string(rcvr_ty), candidate.repr(self.tcx()));
|
self.ty_to_string(rcvr_ty), candidate.repr(self.tcx()));
|
||||||
|
|
||||||
return match candidate.method_ty.explicit_self {
|
return match candidate.method_ty.explicit_self {
|
||||||
SelfStatic => {
|
StaticExplicitSelfCategory => {
|
||||||
debug!("(is relevant?) explicit self is static");
|
debug!("(is relevant?) explicit self is static");
|
||||||
self.report_statics == ReportStaticMethods
|
self.report_statics == ReportStaticMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfValue(_) => {
|
ByValueExplicitSelfCategory => {
|
||||||
debug!("(is relevant?) explicit self is by-value");
|
debug!("(is relevant?) explicit self is by-value");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_uniq(typ) => {
|
ty::ty_uniq(typ) => {
|
||||||
|
@ -1312,7 +1318,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfRegion(_, m, _) => {
|
ByReferenceExplicitSelfCategory(_, m) => {
|
||||||
debug!("(is relevant?) explicit self is a region");
|
debug!("(is relevant?) explicit self is a region");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_rptr(_, mt) => {
|
ty::ty_rptr(_, mt) => {
|
||||||
|
@ -1332,7 +1338,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfUniq(_) => {
|
ByBoxExplicitSelfCategory => {
|
||||||
debug!("(is relevant?) explicit self is a unique pointer");
|
debug!("(is relevant?) explicit self is a unique pointer");
|
||||||
match ty::get(rcvr_ty).sty {
|
match ty::get(rcvr_ty).sty {
|
||||||
ty::ty_uniq(typ) => {
|
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
|
// inscrutable, particularly for cases where one method has no
|
||||||
// self.
|
// self.
|
||||||
match (&trait_m.explicit_self, &impl_m.explicit_self) {
|
match (&trait_m.explicit_self, &impl_m.explicit_self) {
|
||||||
(&ast::SelfStatic, &ast::SelfStatic) => {}
|
(&ty::StaticExplicitSelfCategory,
|
||||||
(&ast::SelfStatic, _) => {
|
&ty::StaticExplicitSelfCategory) => {}
|
||||||
span_err!(tcx.sess, impl_m_span, E0047,
|
(&ty::StaticExplicitSelfCategory, _) => {
|
||||||
"method `{}` has a `{}` declaration in the impl, but not in the trait",
|
tcx.sess.span_err(
|
||||||
token::get_ident(trait_m.ident),
|
impl_m_span,
|
||||||
pprust::explicit_self_to_string(impl_m.explicit_self));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
(_, &ast::SelfStatic) => {
|
(_, &ty::StaticExplicitSelfCategory) => {
|
||||||
span_err!(tcx.sess, impl_m_span, E0048,
|
tcx.sess.span_err(
|
||||||
"method `{}` has a `{}` declaration in the trait, but not in the impl",
|
impl_m_span,
|
||||||
token::get_ident(trait_m.ident),
|
format!("method `{}` has a `{}` declaration in the trait, \
|
||||||
pprust::explicit_self_to_string(trait_m.explicit_self));
|
but not in the impl",
|
||||||
|
token::get_ident(trait_m.ident),
|
||||||
|
ppaux::explicit_self_category_to_str(
|
||||||
|
&trait_m.explicit_self)).as_slice());
|
||||||
return;
|
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::{ImplContainer, MethodContainer, TraitContainer};
|
||||||
use middle::ty::{Polytype};
|
use middle::ty::{Polytype};
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
|
use middle::ty_fold::TypeFolder;
|
||||||
use middle::typeck::astconv::{AstConv, ty_of_arg};
|
use middle::typeck::astconv::{AstConv, ty_of_arg};
|
||||||
use middle::typeck::astconv::{ast_ty_to_ty};
|
use middle::typeck::astconv::{ast_ty_to_ty};
|
||||||
use middle::typeck::astconv;
|
use middle::typeck::astconv;
|
||||||
|
use middle::typeck::infer;
|
||||||
use middle::typeck::rscope::*;
|
use middle::typeck::rscope::*;
|
||||||
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
|
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
|
||||||
|
use middle::typeck;
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
use util::ppaux::Repr;
|
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);
|
make_static_method_ty(ccx, &*ty_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,18 +270,26 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
||||||
m_fn_style: &ast::FnStyle,
|
m_fn_style: &ast::FnStyle,
|
||||||
m_decl: &ast::FnDecl) -> ty::Method
|
m_decl: &ast::FnDecl) -> ty::Method
|
||||||
{
|
{
|
||||||
let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));
|
let trait_self_ty = ty::mk_param(this.tcx,
|
||||||
let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty,
|
subst::SelfSpace,
|
||||||
*m_explicit_self, m_decl);
|
0,
|
||||||
let ty_generics =
|
local_def(trait_id));
|
||||||
ty_generics_for_fn_or_method(this,
|
let ty_generics = ty_generics_for_fn_or_method(
|
||||||
m_generics,
|
this,
|
||||||
(*trait_generics).clone());
|
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(
|
ty::Method::new(
|
||||||
*m_ident,
|
*m_ident,
|
||||||
ty_generics,
|
ty_generics,
|
||||||
fty,
|
fty,
|
||||||
m_explicit_self.node,
|
explicit_self_category,
|
||||||
// assume public, because this is only invoked on trait methods
|
// assume public, because this is only invoked on trait methods
|
||||||
ast::Public,
|
ast::Public,
|
||||||
local_def(*m_id),
|
local_def(*m_id),
|
||||||
|
@ -365,9 +377,13 @@ fn convert_methods(ccx: &CrateCtxt,
|
||||||
rcvr_visibility: ast::Visibility)
|
rcvr_visibility: ast::Visibility)
|
||||||
-> ty::Method
|
-> ty::Method
|
||||||
{
|
{
|
||||||
let fty = astconv::ty_of_method(ccx, m.id, m.pe_fn_style(),
|
let (fty, explicit_self_category) =
|
||||||
untransformed_rcvr_ty,
|
astconv::ty_of_method(ccx,
|
||||||
*m.pe_explicit_self(), m.pe_fn_decl());
|
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
|
// if the method specifies a visibility, use that, otherwise
|
||||||
// inherit the visibility from the impl (so `foo` in `pub impl
|
// 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(),
|
ty::Method::new(m.pe_ident(),
|
||||||
m_ty_generics,
|
m_ty_generics,
|
||||||
fty,
|
fty,
|
||||||
m.pe_explicit_self().node,
|
explicit_self_category,
|
||||||
method_vis,
|
method_vis,
|
||||||
local_def(m.id),
|
local_def(m.id),
|
||||||
container,
|
container,
|
||||||
|
@ -450,6 +466,13 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||||
it.vis
|
it.vis
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for method in ms.iter() {
|
||||||
|
check_method_self_type(ccx,
|
||||||
|
&BindingRscope::new(method.id),
|
||||||
|
selfty,
|
||||||
|
method.pe_explicit_self())
|
||||||
|
}
|
||||||
|
|
||||||
convert_methods(ccx,
|
convert_methods(ccx,
|
||||||
ImplContainer(local_def(it.id)),
|
ImplContainer(local_def(it.id)),
|
||||||
ms.as_slice(),
|
ms.as_slice(),
|
||||||
|
@ -464,6 +487,28 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||||
let trait_def = trait_def_of_item(ccx, it);
|
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.
|
// Run convert_methods on the provided methods.
|
||||||
let (_, provided_methods) =
|
let (_, provided_methods) =
|
||||||
split_trait_methods(trait_methods.as_slice());
|
split_trait_methods(trait_methods.as_slice());
|
||||||
|
@ -1240,3 +1285,36 @@ pub fn mk_item_substs(ccx: &CrateCtxt,
|
||||||
|
|
||||||
subst::Substs::new(types, regions)
|
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)
|
b_subst: &subst::Substs)
|
||||||
-> cres<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();
|
let mut substs = subst::Substs::empty();
|
||||||
|
|
||||||
for &space in subst::ParamSpace::all().iter() {
|
for &space in subst::ParamSpace::all().iter() {
|
||||||
|
@ -121,7 +125,18 @@ pub trait Combine {
|
||||||
|
|
||||||
let a_regions = a_subst.regions().get_slice(space);
|
let a_regions = a_subst.regions().get_slice(space);
|
||||||
let b_regions = b_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,
|
let regions = if_ok!(relate_region_params(self,
|
||||||
item_def_id,
|
item_def_id,
|
||||||
r_variances,
|
r_variances,
|
||||||
|
|
|
@ -13,16 +13,15 @@
|
||||||
|
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
|
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
|
||||||
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound,
|
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
|
||||||
ReLateBound};
|
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
|
||||||
use middle::ty::{ReScope, ReVar, ReSkolemized, BrFresh};
|
|
||||||
use middle::typeck::infer::cres;
|
use middle::typeck::infer::cres;
|
||||||
use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin, TypeTrace};
|
use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin, TypeTrace};
|
||||||
use middle::typeck::infer;
|
use middle::typeck::infer;
|
||||||
use middle::graph;
|
use middle::graph;
|
||||||
use middle::graph::{Direction, NodeIndex};
|
use middle::graph::{Direction, NodeIndex};
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::{Repr};
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::uint;
|
use std::uint;
|
||||||
|
@ -318,6 +317,11 @@ impl<'a> RegionVarBindings<'a> {
|
||||||
origin.repr(self.tcx));
|
origin.repr(self.tcx));
|
||||||
|
|
||||||
match (sub, sup) {
|
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(..), _) |
|
(ReEarlyBound(..), _) |
|
||||||
(ReLateBound(..), _) |
|
(ReLateBound(..), _) |
|
||||||
(_, ReEarlyBound(..)) |
|
(_, 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 terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
|
||||||
let constraints_cx = add_constraints_from_crate(terms_cx, krate);
|
let constraints_cx = add_constraints_from_crate(terms_cx, krate);
|
||||||
solve_constraints(constraints_cx);
|
solve_constraints(constraints_cx);
|
||||||
|
tcx.variance_computed.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
|
|
@ -14,7 +14,7 @@ use middle::subst;
|
||||||
use middle::subst::{VecPerParamSpace,Subst};
|
use middle::subst::{VecPerParamSpace,Subst};
|
||||||
use middle::ty::{ReSkolemized, ReVar};
|
use middle::ty::{ReSkolemized, ReVar};
|
||||||
use middle::ty::{BoundRegion, BrAnon, BrNamed};
|
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::{mt, t, ParamTy};
|
||||||
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
|
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
|
||||||
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
|
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) }
|
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,
|
// I believe these cases should not occur (except when debugging,
|
||||||
// perhaps)
|
// perhaps)
|
||||||
ty::ReInfer(_) | ty::ReEarlyBound(..) | ty::ReLateBound(..) => {
|
ty::ReInfer(_) | ty::ReLateBound(..) => {
|
||||||
(format!("lifetime {:?}", region), None)
|
(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,
|
pub fn parameterized(cx: &ctxt,
|
||||||
base: &str,
|
base: &str,
|
||||||
substs: &subst::Substs,
|
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 {
|
pub enum Attribute {
|
||||||
Word(String),
|
Word(String),
|
||||||
List(String, Vec<Attribute> ),
|
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 }
|
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 struct TyParam {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub did: ast::DefId,
|
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 {
|
pub enum TyParamBound {
|
||||||
RegionBound,
|
RegionBound,
|
||||||
TraitBound(Type)
|
TraitBound(Type)
|
||||||
|
@ -638,7 +638,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe use a Generic enum and use ~[Generic]?
|
// maybe use a Generic enum and use ~[Generic]?
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||||
pub struct Generics {
|
pub struct Generics {
|
||||||
pub lifetimes: Vec<Lifetime>,
|
pub lifetimes: Vec<Lifetime>,
|
||||||
pub type_params: Vec<TyParam>,
|
pub type_params: Vec<TyParam>,
|
||||||
|
@ -771,6 +771,7 @@ pub enum SelfTy {
|
||||||
SelfValue,
|
SelfValue,
|
||||||
SelfBorrowed(Option<Lifetime>, Mutability),
|
SelfBorrowed(Option<Lifetime>, Mutability),
|
||||||
SelfOwned,
|
SelfOwned,
|
||||||
|
SelfExplicit(Type),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<SelfTy> for ast::ExplicitSelf_ {
|
impl Clean<SelfTy> for ast::ExplicitSelf_ {
|
||||||
|
@ -779,7 +780,10 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
|
||||||
ast::SelfStatic => SelfStatic,
|
ast::SelfStatic => SelfStatic,
|
||||||
ast::SelfValue(_) => SelfValue,
|
ast::SelfValue(_) => SelfValue,
|
||||||
ast::SelfUniq(_) => SelfOwned,
|
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 struct ClosureDecl {
|
||||||
pub lifetimes: Vec<Lifetime>,
|
pub lifetimes: Vec<Lifetime>,
|
||||||
pub decl: FnDecl,
|
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 struct FnDecl {
|
||||||
pub inputs: Arguments,
|
pub inputs: Arguments,
|
||||||
pub output: Type,
|
pub output: Type,
|
||||||
|
@ -841,7 +845,7 @@ pub struct FnDecl {
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||||
pub struct Arguments {
|
pub struct Arguments {
|
||||||
pub values: Vec<Argument>,
|
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 struct Argument {
|
||||||
pub type_: Type,
|
pub type_: Type,
|
||||||
pub name: String,
|
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 {
|
pub enum RetStyle {
|
||||||
NoReturn,
|
NoReturn,
|
||||||
Return
|
Return
|
||||||
|
@ -991,22 +995,28 @@ impl Clean<Item> for ty::Method {
|
||||||
fn clean(&self) -> Item {
|
fn clean(&self) -> Item {
|
||||||
let cx = get_cx();
|
let cx = get_cx();
|
||||||
let (self_, sig) = match self.explicit_self {
|
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 => {
|
s => {
|
||||||
let sig = ty::FnSig {
|
let sig = ty::FnSig {
|
||||||
inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
|
inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
|
||||||
..self.fty.sig.clone()
|
..self.fty.sig.clone()
|
||||||
};
|
};
|
||||||
let s = match s {
|
let s = match s {
|
||||||
ast::SelfRegion(..) => {
|
ty::ByReferenceExplicitSelfCategory(..) => {
|
||||||
match ty::get(self.fty.sig.inputs[0]).sty {
|
match ty::get(*self.fty.sig.inputs[0]).sty {
|
||||||
ty::ty_rptr(r, mt) => {
|
ty::ty_rptr(r, mt) => {
|
||||||
SelfBorrowed(r.clean(), mt.mutbl.clean())
|
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)
|
(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
|
/// 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
|
/// 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.
|
/// it does not preserve mutability or boxes.
|
||||||
#[deriving(Clone, Encodable, Decodable)]
|
#[deriving(Clone, Encodable, Decodable, PartialEq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// structs/enums/traits (anything that'd be an ast::TyPath)
|
/// structs/enums/traits (anything that'd be an ast::TyPath)
|
||||||
ResolvedPath {
|
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 struct Path {
|
||||||
pub global: bool,
|
pub global: bool,
|
||||||
pub segments: Vec<PathSegment>,
|
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 struct PathSegment {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub lifetimes: Vec<Lifetime>,
|
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 struct BareFunctionDecl {
|
||||||
pub fn_style: ast::FnStyle,
|
pub fn_style: ast::FnStyle,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
|
|
|
@ -500,6 +500,9 @@ impl<'a> fmt::Show for Method<'a> {
|
||||||
args.push_str(format!("&{}self",
|
args.push_str(format!("&{}self",
|
||||||
MutableSpace(mtbl)).as_slice());
|
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() {
|
for (i, input) in d.inputs.values.iter().enumerate() {
|
||||||
if i > 0 || args.len() > 0 { args.push_str(", "); }
|
if i > 0 || args.len() > 0 { args.push_str(", "); }
|
||||||
|
|
|
@ -949,12 +949,14 @@ pub enum RetStyle {
|
||||||
pub enum ExplicitSelf_ {
|
pub enum ExplicitSelf_ {
|
||||||
/// No self
|
/// No self
|
||||||
SelfStatic,
|
SelfStatic,
|
||||||
/// `self
|
/// `self`
|
||||||
SelfValue(Ident),
|
SelfValue(Ident),
|
||||||
/// `&'lt self`, `&'lt mut self`
|
/// `&'lt self`, `&'lt mut self`
|
||||||
SelfRegion(Option<Lifetime>, Mutability, Ident),
|
SelfRegion(Option<Lifetime>, Mutability, Ident),
|
||||||
/// `~self`
|
/// `~self`
|
||||||
SelfUniq(Ident)
|
SelfUniq(Ident),
|
||||||
|
/// `self: TYPE`
|
||||||
|
SelfExplicit(P<Ty>, Ident),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
|
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
|
||||||
|
|
|
@ -344,6 +344,7 @@ pub trait Folder {
|
||||||
SelfRegion(ref lifetime, m, id) => {
|
SelfRegion(ref lifetime, m, id) => {
|
||||||
SelfRegion(fold_opt_lifetime(lifetime, self), 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::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
|
||||||
use ast::{StructVariantKind, BiSub};
|
use ast::{StructVariantKind, BiSub};
|
||||||
use ast::StrStyle;
|
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::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
|
||||||
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
|
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
|
||||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||||
|
@ -3843,7 +3843,15 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token::IDENT(..) if self.is_self_ident() => {
|
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) => {
|
token::BINOP(token::STAR) => {
|
||||||
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
|
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
|
||||||
|
@ -3851,7 +3859,9 @@ impl<'a> Parser<'a> {
|
||||||
self.bump();
|
self.bump();
|
||||||
let _mutability = if Parser::token_is_mutability(&self.token) {
|
let _mutability = if Parser::token_is_mutability(&self.token) {
|
||||||
self.parse_mutability()
|
self.parse_mutability()
|
||||||
} else { MutImmutable };
|
} else {
|
||||||
|
MutImmutable
|
||||||
|
};
|
||||||
if self.is_self_ident() {
|
if self.is_self_ident() {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
self.span_err(span, "cannot pass self by unsafe pointer");
|
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) &&
|
_ if Parser::token_is_mutability(&self.token) &&
|
||||||
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
|
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
|
||||||
mutbl_self = self.parse_mutability();
|
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) &&
|
_ if Parser::token_is_mutability(&self.token) &&
|
||||||
self.look_ahead(1, |t| *t == token::TILDE) &&
|
self.look_ahead(1, |t| *t == token::TILDE) &&
|
||||||
|
@ -3914,8 +3932,8 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
SelfValue(id) => parse_remaining_arguments!(id),
|
SelfValue(id) => parse_remaining_arguments!(id),
|
||||||
SelfRegion(_,_,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!(self.print_mutability(m));
|
||||||
try!(word(&mut self.s, "self"));
|
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);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,7 @@ pub fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||||
SelfRegion(ref lifetime, _, _) => {
|
SelfRegion(ref lifetime, _, _) => {
|
||||||
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
|
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() {}
|
||||||
|
|
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));
|
||||||
|
}
|
||||||
|
|
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));
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue