From 357d5cd96caea4fbccb989dc4bf5eed71c785c1c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 6 May 2014 16:37:32 -0700 Subject: [PATCH 1/3] 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] --- src/librustc/metadata/csearch.rs | 3 +- src/librustc/metadata/decoder.rs | 25 +-- src/librustc/metadata/encoder.rs | 31 ++-- src/librustc/middle/region.rs | 10 ++ src/librustc/middle/resolve.rs | 67 ++++++-- src/librustc/middle/trans/meth.rs | 15 +- src/librustc/middle/ty.rs | 18 +- src/librustc/middle/typeck/astconv.rs | 158 ++++++++++++++---- src/librustc/middle/typeck/check/method.rs | 43 +++-- src/librustc/middle/typeck/check/mod.rs | 30 ++-- src/librustc/middle/typeck/collect.rs | 104 ++++++++++-- src/librustc/middle/typeck/infer/combine.rs | 19 ++- .../typeck/infer/region_inference/mod.rs | 12 +- src/librustc/middle/typeck/variance.rs | 1 + src/librustc/util/ppaux.rs | 28 +++- src/librustdoc/clean/mod.rs | 48 +++--- src/librustdoc/html/format.rs | 3 + src/libsyntax/ast.rs | 6 +- src/libsyntax/fold.rs | 1 + src/libsyntax/parse/parser.rs | 30 +++- src/libsyntax/print/pprust.rs | 5 + src/libsyntax/visit.rs | 1 + .../explicit-self-lifetime-mismatch.rs | 26 +++ .../compile-fail/ufcs-explicit-self-bad.rs | 49 ++++++ src/test/run-pass/ufcs-explicit-self.rs | 57 +++++++ 25 files changed, 633 insertions(+), 157 deletions(-) create mode 100644 src/test/compile-fail/explicit-self-lifetime-mismatch.rs create mode 100644 src/test/compile-fail/ufcs-explicit-self-bad.rs create mode 100644 src/test/run-pass/ufcs-explicit-self.rs diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 5ab8eeeb36055..0adc8e915c679 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -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) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index cc41223688ee0..094e83d2a4770 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -724,7 +724,7 @@ pub fn get_enum_variants(intr: Rc, cdata: Cmd, id: ast::NodeId, }).collect() } -fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ { +fn get_explicit_self(item: ebml::Doc) -> ty::ExplicitSelfCategory { fn get_mutability(ch: u8) -> ast::Mutability { match ch as char { 'i' => ast::MutImmutable, @@ -738,12 +738,15 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ { let explicit_self_kind = string.as_bytes()[0]; match explicit_self_kind as char { - 's' => ast::SelfStatic, - 'v' => ast::SelfValue(special_idents::self_), - '~' => ast::SelfUniq(special_idents::self_), + 's' => ty::StaticExplicitSelfCategory, + 'v' => ty::ByValueExplicitSelfCategory, + '~' => ty::ByBoxExplicitSelfCategory, // FIXME(#4846) expl. region - '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1]), - special_idents::self_), + '&' => { + ty::ByReferenceExplicitSelfCategory( + ty::ReEmpty, + get_mutability(string.as_bytes()[1])) + } _ => fail!("unknown self type code: `{}`", explicit_self_kind as char) } } @@ -761,11 +764,11 @@ pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec { methods } -pub fn get_method_name_and_explicit_self( - intr: Rc, - cdata: Cmd, - id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_) -{ +pub fn get_method_name_and_explicit_self(intr: Rc, + 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); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 0a050850fe907..3c9f32dcd2f85 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -402,7 +402,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext, for base_impl_did in implementations.borrow().iter() { for &method_did in impl_methods.get(base_impl_did).iter() { let m = ty::method(ecx.tcx, method_did); - if m.explicit_self == ast::SelfStatic { + if m.explicit_self == ty::StaticExplicitSelfCategory { encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident); } } @@ -421,7 +421,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext, match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) { Some(methods) => { for m in methods.iter() { - if m.explicit_self == ast::SelfStatic { + if m.explicit_self == ty::StaticExplicitSelfCategory { encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident); } } @@ -623,15 +623,22 @@ fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) { ebml_w.end_tag(); } -fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) { +fn encode_explicit_self(ebml_w: &mut Encoder, + explicit_self: &ty::ExplicitSelfCategory) { ebml_w.start_tag(tag_item_trait_method_explicit_self); // Encode the base self type. - match explicit_self { - SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); } - SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); } - SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); } - SelfRegion(_, m, _) => { + match *explicit_self { + ty::StaticExplicitSelfCategory => { + ebml_w.writer.write(&[ 's' as u8 ]); + } + ty::ByValueExplicitSelfCategory => { + ebml_w.writer.write(&[ 'v' as u8 ]); + } + ty::ByBoxExplicitSelfCategory => { + ebml_w.writer.write(&[ '~' as u8 ]); + } + ty::ByReferenceExplicitSelfCategory(_, m) => { // FIXME(#4846) encode custom lifetime ebml_w.writer.write(&['&' as u8]); encode_mutability(ebml_w, m); @@ -748,10 +755,10 @@ fn encode_method_ty_fields(ecx: &EncodeContext, tag_item_method_tps); encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_visibility(ebml_w, method_ty.vis); - encode_explicit_self(ebml_w, method_ty.explicit_self); + encode_explicit_self(ebml_w, &method_ty.explicit_self); let fn_style = method_ty.fty.fn_style; match method_ty.explicit_self { - ast::SelfStatic => { + ty::StaticExplicitSelfCategory => { encode_family(ebml_w, fn_style_static_method_family(fn_style)); } _ => encode_family(ebml_w, style_fn_family(fn_style)) @@ -1206,7 +1213,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(ebml_w, path.clone().chain(Some(elem).move_iter())); match method_ty.explicit_self { - SelfStatic => { + ty::StaticExplicitSelfCategory => { encode_family(ebml_w, fn_style_static_method_family( method_ty.fty.fn_style)); @@ -1233,7 +1240,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_attributes(ebml_w, m.attrs.as_slice()); // If this is a static method, we've already encoded // this. - if method_ty.explicit_self != SelfStatic { + if method_ty.explicit_self != ty::StaticExplicitSelfCategory { // FIXME: I feel like there is something funny going on. let pty = ty::lookup_item_type(tcx, method_def_id); encode_bounds_and_type(ebml_w, ecx, &pty); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index df4d3b7efe432..822a43f2619dc 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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 } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 40237e7984f6c..f00d7c36f5333 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -11,13 +11,14 @@ #![allow(non_camel_case_types)] use driver::session::Session; +use lint; use metadata::csearch; use metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; use middle::def::*; use middle::lang_items::LanguageItems; use middle::pat_util::pat_bindings; use middle::subst::{ParamSpace, FnSpace, TypeSpace}; -use lint; +use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory}; use util::nodemap::{NodeMap, DefIdSet, FnvHashMap}; use syntax::ast::*; @@ -287,6 +288,24 @@ enum ModulePrefixResult { PrefixFound(Rc, uint) } +#[deriving(Clone, Eq, PartialEq)] +enum MethodIsStaticFlag { + MethodIsNotStatic, + MethodIsStatic, +} + +impl MethodIsStaticFlag { + fn from_explicit_self_category(explicit_self_category: + ExplicitSelfCategory) + -> MethodIsStaticFlag { + if explicit_self_category == StaticExplicitSelfCategory { + MethodIsStatic + } else { + MethodIsNotStatic + } + } +} + #[deriving(PartialEq)] enum NameSearchType { /// We're doing a name search in order to resolve a `use` directive. @@ -805,7 +824,8 @@ struct Resolver<'a> { graph_root: NameBindings, - method_map: RefCell>, + method_map: RefCell>, + structs: FnvHashMap>, // The number of imports that are currently unresolved. @@ -1361,17 +1381,19 @@ impl<'a> Resolver<'a> { let ident = ty_m.ident; // Add it as a name in the trait module. - let def = match ty_m.explicit_self.node { + let (def, static_flag) = match ty_m.explicit_self.node { SelfStatic => { // Static methods become `def_static_method`s. - DefStaticMethod(local_def(ty_m.id), + (DefStaticMethod(local_def(ty_m.id), FromTrait(local_def(item.id)), - ty_m.fn_style) + ty_m.fn_style), + MethodIsStatic) } _ => { // Non-static methods become `def_method`s. - DefMethod(local_def(ty_m.id), - Some(local_def(item.id))) + (DefMethod(local_def(ty_m.id), + Some(local_def(item.id))), + MethodIsNotStatic) } }; @@ -1382,8 +1404,9 @@ impl<'a> Resolver<'a> { ty_m.span); method_name_bindings.define_value(def, ty_m.span, true); - self.method_map.borrow_mut().insert((ident.name, def_id), - ty_m.explicit_self.node); + self.method_map + .borrow_mut() + .insert((ident.name, def_id), static_flag); } name_bindings.define_type(DefTrait(def_id), sp, is_public); @@ -1670,7 +1693,11 @@ impl<'a> Resolver<'a> { trait method '{}'", token::get_ident(method_name)); - self.method_map.borrow_mut().insert((method_name.name, def_id), explicit_self); + self.method_map + .borrow_mut() + .insert((method_name.name, def_id), + MethodIsStaticFlag::from_explicit_self_category( + explicit_self)); if is_exported { self.external_exports.insert(method_def_id); @@ -3678,6 +3705,13 @@ impl<'a> Resolver<'a> { this.resolve_type(&*argument.ty); } + match ty_m.explicit_self.node { + SelfExplicit(ref typ, _) => { + this.resolve_type(*typ) + } + _ => {} + } + this.resolve_type(&*ty_m.decl.output); }); } @@ -4009,7 +4043,14 @@ impl<'a> Resolver<'a> { method.id, rib_kind); - self.resolve_function(rib_kind, Some(method.pe_fn_decl()), type_parameters, + match method.pe_explicit_self().node { + SelfExplicit(ref typ, _) => self.resolve_type(*typ), + _ => {} + } + + self.resolve_function(rib_kind, + Some(method.pe_fn_decl()), + type_parameters, method.pe_body()); } @@ -4765,7 +4806,7 @@ impl<'a> Resolver<'a> { match containing_module.def_id.get() { Some(def_id) => { match self.method_map.borrow().find(&(ident.name, def_id)) { - Some(x) if *x == SelfStatic => (), + Some(&MethodIsStatic) => (), None => (), _ => { debug!("containing module was a trait or impl \ @@ -5037,7 +5078,7 @@ impl<'a> Resolver<'a> { let path_str = self.path_idents_to_string(&trait_ref.path); match method_map.find(&(name, did)) { - Some(&SelfStatic) => return StaticTraitMethod(path_str), + Some(&MethodIsStatic) => return StaticTraitMethod(path_str), Some(_) => return TraitMethod, None => {} } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index f9c5f82fb29ac..53f0645cb8702 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -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 } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index dc69e3fd6399d..cfafe99090d58 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -85,7 +85,7 @@ pub struct Method { pub ident: ast::Ident, pub generics: ty::Generics, pub fty: BareFnTy, - pub explicit_self: ast::ExplicitSelf_, + pub explicit_self: ExplicitSelfCategory, pub vis: ast::Visibility, pub def_id: ast::DefId, pub container: MethodContainer, @@ -98,7 +98,7 @@ impl Method { pub fn new(ident: ast::Ident, generics: ty::Generics, fty: BareFnTy, - explicit_self: ast::ExplicitSelf_, + explicit_self: ExplicitSelfCategory, vis: ast::Visibility, def_id: ast::DefId, container: MethodContainer, @@ -311,6 +311,9 @@ pub struct ctxt { /// (inferred) variance. pub item_variance_map: RefCell>>, + /// True if the variance has been computed yet; false otherwise. + pub variance_computed: Cell, + /// A mapping from the def ID of an enum or struct type to the def ID /// of the method that implements its destructor. If the type is not /// present in this map, it does not have a destructor. This map is @@ -1055,6 +1058,7 @@ pub fn mk_ctxt(s: Session, ctxt { named_region_map: named_region_map, item_variance_map: RefCell::new(DefIdMap::new()), + variance_computed: Cell::new(false), interner: RefCell::new(FnvHashMap::new()), next_id: Cell::new(primitives::LAST_PRIMITIVE_ID), sess: s, @@ -4767,3 +4771,13 @@ impl mc::Typer for ty::ctxt { self.upvar_borrow_map.borrow().get_copy(&upvar_id) } } + +/// The category of explicit self. +#[deriving(Clone, Eq, PartialEq)] +pub enum ExplicitSelfCategory { + StaticExplicitSelfCategory, + ByValueExplicitSelfCategory, + ByReferenceExplicitSelfCategory(Region, ast::Mutability), + ByBoxExplicitSelfCategory, +} + diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 5ed92b305be0d..09557c94aa62a 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -52,13 +52,13 @@ use middle::const_eval; use middle::def; use middle::lang_items::FnMutTraitLangItem; -use rl = middle::resolve_lifetime; use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::ty; -use middle::typeck::TypeAndSubsts; -use middle::typeck::lookup_def_tcx; +use middle::ty_fold::TypeFolder; use middle::typeck::rscope::RegionScope; -use middle::typeck::rscope; +use middle::typeck::{TypeAndSubsts, infer, lookup_def_tcx, rscope}; +use middle::typeck; +use rl = middle::resolve_lifetime; use util::ppaux::Repr; use std::rc::Rc; @@ -900,58 +900,73 @@ pub fn ty_of_arg(this: &AC, rscope: &RS, a: &ast:: } } -struct SelfInfo { +struct SelfInfo<'a> { untransformed_self_ty: ty::t, - explicit_self: ast::ExplicitSelf + explicit_self: ast::ExplicitSelf, } pub fn ty_of_method( - this: &AC, - id: ast::NodeId, - fn_style: ast::FnStyle, - untransformed_self_ty: ty::t, - explicit_self: ast::ExplicitSelf, - decl: &ast::FnDecl) - -> ty::BareFnTy -{ - ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo { + this: &AC, + id: ast::NodeId, + fn_style: ast::FnStyle, + untransformed_self_ty: ty::t, + explicit_self: ast::ExplicitSelf, + decl: &ast::FnDecl) + -> (ty::BareFnTy, ty::ExplicitSelfCategory) { + let self_info = Some(SelfInfo { untransformed_self_ty: untransformed_self_ty, - explicit_self: explicit_self - }), decl) + explicit_self: explicit_self, + }); + let (bare_fn_ty, optional_explicit_self_category) = + ty_of_method_or_bare_fn(this, + id, + fn_style, + abi::Rust, + self_info, + decl); + (bare_fn_ty, optional_explicit_self_category.unwrap()) } pub fn ty_of_bare_fn(this: &AC, id: ast::NodeId, fn_style: ast::FnStyle, abi: abi::Abi, decl: &ast::FnDecl) -> ty::BareFnTy { - ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl) + let (bare_fn_ty, _) = + ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl); + bare_fn_ty } -fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, - fn_style: ast::FnStyle, abi: abi::Abi, - opt_self_info: Option, - decl: &ast::FnDecl) -> ty::BareFnTy { +fn ty_of_method_or_bare_fn( + this: &AC, + id: ast::NodeId, + fn_style: ast::FnStyle, + abi: abi::Abi, + opt_self_info: Option, + decl: &ast::FnDecl) + -> (ty::BareFnTy, + Option) { debug!("ty_of_method_or_bare_fn"); // new region names that appear inside of the fn decl are bound to // that function type let rb = rscope::BindingRscope::new(id); + let mut explicit_self_category_result = None; let self_ty = opt_self_info.and_then(|self_info| { - match self_info.explicit_self.node { - ast::SelfStatic => None, - ast::SelfValue(_) => { + // Figure out and record the explicit self category. + let explicit_self_category = + determine_explicit_self_category(this, &rb, &self_info); + explicit_self_category_result = Some(explicit_self_category); + match explicit_self_category { + ty::StaticExplicitSelfCategory => None, + ty::ByValueExplicitSelfCategory => { Some(self_info.untransformed_self_ty) } - ast::SelfRegion(ref lifetime, mutability, _) => { - let region = - opt_ast_region_to_region(this, &rb, - self_info.explicit_self.span, - lifetime); + ty::ByReferenceExplicitSelfCategory(region, mutability) => { Some(ty::mk_rptr(this.tcx(), region, ty::mt {ty: self_info.untransformed_self_ty, mutbl: mutability})) } - ast::SelfUniq(_) => { + ty::ByBoxExplicitSelfCategory => { Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)) } } @@ -972,7 +987,7 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, _ => ast_ty_to_ty(this, &rb, &*decl.output) }; - return ty::BareFnTy { + (ty::BareFnTy { fn_style: fn_style, abi: abi, sig: ty::FnSig { @@ -981,7 +996,83 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, output: output_ty, variadic: decl.variadic } - }; + }, explicit_self_category_result) +} + +fn determine_explicit_self_category( + 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( @@ -1098,3 +1189,4 @@ fn conv_builtin_bounds(tcx: &ty::ctxt, (&None, ty::UniqTraitStore) => ty::empty_builtin_bounds(), } } + diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 4787837093844..e12fae4f9501e 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -100,9 +100,7 @@ use util::ppaux::Repr; use std::collections::HashSet; use std::rc::Rc; -use syntax::ast::{DefId, SelfValue, SelfRegion}; -use syntax::ast::{SelfUniq, SelfStatic}; -use syntax::ast::{MutMutable, MutImmutable}; +use syntax::ast::{DefId, MutImmutable, MutMutable}; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token; @@ -267,15 +265,15 @@ fn construct_transformed_self_ty_for_object( obj_substs.types.pop(subst::SelfSpace).unwrap(); match method_ty.explicit_self { - ast::SelfStatic => { + StaticExplicitSelfCategory => { tcx.sess.span_bug(span, "static method for object type receiver"); } - ast::SelfValue(_) => { + ByValueExplicitSelfCategory => { let tr = ty::mk_trait(tcx, trait_def_id, obj_substs, ty::empty_builtin_bounds()); ty::mk_uniq(tcx, tr) } - ast::SelfRegion(..) | ast::SelfUniq(..) => { + ByReferenceExplicitSelfCategory(..) | ByBoxExplicitSelfCategory => { let transformed_self_ty = *method_ty.fty.sig.inputs.get(0); match ty::get(transformed_self_ty).sty { ty::ty_rptr(r, mt) => { // must be SelfRegion @@ -618,7 +616,7 @@ impl<'a> LookupContext<'a> { let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id); match trait_methods.iter().position(|m| { - m.explicit_self != ast::SelfStatic && + m.explicit_self != ty::StaticExplicitSelfCategory && m.ident.name == self.m_name }) { Some(pos) => { let method = trait_methods.get(pos).clone(); @@ -1023,7 +1021,10 @@ impl<'a> LookupContext<'a> { if self.report_statics == ReportStaticMethods { // lookup should only be called with ReportStaticMethods if a regular lookup failed - assert!(relevant_candidates.iter().all(|c| c.method_ty.explicit_self == SelfStatic)); + assert!(relevant_candidates.iter() + .all(|c| { + c.method_ty.explicit_self == ty::StaticExplicitSelfCategory + })); self.tcx().sess.fileline_note(self.span, "found defined static methods, maybe a `self` is missing?"); @@ -1100,7 +1101,8 @@ impl<'a> LookupContext<'a> { self.enforce_drop_trait_limitations(candidate); // static methods should never have gotten this far: - assert!(candidate.method_ty.explicit_self != SelfStatic); + assert!(candidate.method_ty.explicit_self != + ty::StaticExplicitSelfCategory); // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh @@ -1217,12 +1219,16 @@ impl<'a> LookupContext<'a> { } match candidate.method_ty.explicit_self { - ast::SelfStatic => { // reason (a) above - span_err!(self.tcx().sess, self.span, E0037, - "cannot call a method without a receiver through an object"); + ty::StaticExplicitSelfCategory => { // reason (a) above + self.tcx().sess.span_err( + self.span, + "cannot call a method without a receiver \ + through an object"); } - ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {} + ty::ByValueExplicitSelfCategory | + ty::ByReferenceExplicitSelfCategory(..) | + ty::ByBoxExplicitSelfCategory => {} } // reason (a) above @@ -1284,12 +1290,12 @@ impl<'a> LookupContext<'a> { self.ty_to_string(rcvr_ty), candidate.repr(self.tcx())); return match candidate.method_ty.explicit_self { - SelfStatic => { + StaticExplicitSelfCategory => { debug!("(is relevant?) explicit self is static"); self.report_statics == ReportStaticMethods } - SelfValue(_) => { + ByValueExplicitSelfCategory => { debug!("(is relevant?) explicit self is by-value"); match ty::get(rcvr_ty).sty { ty::ty_uniq(typ) => { @@ -1312,7 +1318,7 @@ impl<'a> LookupContext<'a> { } } - SelfRegion(_, m, _) => { + ByReferenceExplicitSelfCategory(_, m) => { debug!("(is relevant?) explicit self is a region"); match ty::get(rcvr_ty).sty { ty::ty_rptr(_, mt) => { @@ -1332,7 +1338,7 @@ impl<'a> LookupContext<'a> { } } - SelfUniq(_) => { + ByBoxExplicitSelfCategory => { debug!("(is relevant?) explicit self is a unique pointer"); match ty::get(rcvr_ty).sty { ty::ty_uniq(typ) => { @@ -1480,3 +1486,6 @@ impl Repr for RcvrMatchCondition { } } } + + + diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index bc4d1c73ffbf3..4f07f1121b7ce 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -862,19 +862,26 @@ fn compare_impl_method(tcx: &ty::ctxt, // inscrutable, particularly for cases where one method has no // self. match (&trait_m.explicit_self, &impl_m.explicit_self) { - (&ast::SelfStatic, &ast::SelfStatic) => {} - (&ast::SelfStatic, _) => { - span_err!(tcx.sess, impl_m_span, E0047, - "method `{}` has a `{}` declaration in the impl, but not in the trait", - token::get_ident(trait_m.ident), - pprust::explicit_self_to_string(impl_m.explicit_self)); + (&ty::StaticExplicitSelfCategory, + &ty::StaticExplicitSelfCategory) => {} + (&ty::StaticExplicitSelfCategory, _) => { + tcx.sess.span_err( + impl_m_span, + format!("method `{}` has a `{}` declaration in the impl, \ + but not in the trait", + token::get_ident(trait_m.ident), + ppaux::explicit_self_category_to_str( + &impl_m.explicit_self)).as_slice()); return; } - (_, &ast::SelfStatic) => { - span_err!(tcx.sess, impl_m_span, E0048, - "method `{}` has a `{}` declaration in the trait, but not in the impl", - token::get_ident(trait_m.ident), - pprust::explicit_self_to_string(trait_m.explicit_self)); + (_, &ty::StaticExplicitSelfCategory) => { + tcx.sess.span_err( + impl_m_span, + format!("method `{}` has a `{}` declaration in the trait, \ + but not in the impl", + token::get_ident(trait_m.ident), + ppaux::explicit_self_category_to_str( + &trait_m.explicit_self)).as_slice()); return; } _ => { @@ -4787,3 +4794,4 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { }); } } + diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index e21a7949ec799..eea26fbcfc73f 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -40,11 +40,14 @@ use middle::subst::{Substs}; use middle::ty::{ImplContainer, MethodContainer, TraitContainer}; use middle::ty::{Polytype}; use middle::ty; +use middle::ty_fold::TypeFolder; use middle::typeck::astconv::{AstConv, ty_of_arg}; use middle::typeck::astconv::{ast_ty_to_ty}; use middle::typeck::astconv; +use middle::typeck::infer; use middle::typeck::rscope::*; use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx}; +use middle::typeck; use util::ppaux; use util::ppaux::Repr; @@ -218,7 +221,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, } }); - if ty_method.explicit_self == ast::SelfStatic { + if ty_method.explicit_self == + ty::StaticExplicitSelfCategory { make_static_method_ty(ccx, &*ty_method); } @@ -266,18 +270,26 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, m_fn_style: &ast::FnStyle, m_decl: &ast::FnDecl) -> ty::Method { - let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id)); - let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty, - *m_explicit_self, m_decl); - let ty_generics = - ty_generics_for_fn_or_method(this, - m_generics, - (*trait_generics).clone()); + let trait_self_ty = ty::mk_param(this.tcx, + subst::SelfSpace, + 0, + local_def(trait_id)); + let ty_generics = ty_generics_for_fn_or_method( + this, + m_generics, + (*trait_generics).clone()); + let (fty, explicit_self_category) = + astconv::ty_of_method(this, + *m_id, + *m_fn_style, + trait_self_ty, + *m_explicit_self, + m_decl); ty::Method::new( *m_ident, ty_generics, fty, - m_explicit_self.node, + explicit_self_category, // assume public, because this is only invoked on trait methods ast::Public, local_def(*m_id), @@ -365,9 +377,13 @@ fn convert_methods(ccx: &CrateCtxt, rcvr_visibility: ast::Visibility) -> ty::Method { - let fty = astconv::ty_of_method(ccx, m.id, m.pe_fn_style(), - untransformed_rcvr_ty, - *m.pe_explicit_self(), m.pe_fn_decl()); + let (fty, explicit_self_category) = + astconv::ty_of_method(ccx, + m.id, + m.pe_fn_style(), + untransformed_rcvr_ty, + *m.pe_explicit_self(), + m.pe_fn_decl()); // if the method specifies a visibility, use that, otherwise // inherit the visibility from the impl (so `foo` in `pub impl @@ -381,7 +397,7 @@ fn convert_methods(ccx: &CrateCtxt, ty::Method::new(m.pe_ident(), m_ty_generics, fty, - m.pe_explicit_self().node, + explicit_self_category, method_vis, local_def(m.id), container, @@ -450,6 +466,13 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { it.vis }; + for method in ms.iter() { + check_method_self_type(ccx, + &BindingRscope::new(method.id), + selfty, + method.pe_explicit_self()) + } + convert_methods(ccx, ImplContainer(local_def(it.id)), ms.as_slice(), @@ -464,6 +487,28 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { ast::ItemTrait(_, _, _, ref trait_methods) => { let trait_def = trait_def_of_item(ccx, it); + for trait_method in trait_methods.iter() { + let self_type = ty::mk_param(ccx.tcx, + subst::SelfSpace, + 0, + local_def(it.id)); + match *trait_method { + ast::Required(ref type_method) => { + let rscope = BindingRscope::new(type_method.id); + check_method_self_type(ccx, + &rscope, + self_type, + &type_method.explicit_self) + } + ast::Provided(ref method) => { + check_method_self_type(ccx, + &BindingRscope::new(method.id), + self_type, + method.pe_explicit_self()) + } + } + } + // Run convert_methods on the provided methods. let (_, provided_methods) = split_trait_methods(trait_methods.as_slice()); @@ -1240,3 +1285,36 @@ pub fn mk_item_substs(ccx: &CrateCtxt, subst::Substs::new(types, regions) } + +/// Verifies that the explicit self type of a method matches the impl or +/// trait. +fn check_method_self_type( + 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(); + } + _ => {} + } +} + diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 1e33b1d5d0ebd..c3de120a0c393 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -111,7 +111,11 @@ pub trait Combine { b_subst: &subst::Substs) -> cres { - let variances = ty::item_variances(self.infcx().tcx, item_def_id); + let variances = if self.infcx().tcx.variance_computed.get() { + Some(ty::item_variances(self.infcx().tcx, item_def_id)) + } else { + None + }; let mut substs = subst::Substs::empty(); for &space in subst::ParamSpace::all().iter() { @@ -121,7 +125,18 @@ pub trait Combine { let a_regions = a_subst.regions().get_slice(space); let b_regions = b_subst.regions().get_slice(space); - let r_variances = variances.regions.get_slice(space); + + let mut invariance = Vec::new(); + let r_variances = match variances { + Some(ref variances) => variances.regions.get_slice(space), + None => { + for _ in a_regions.iter() { + invariance.push(ty::Invariant); + } + invariance.as_slice() + } + }; + let regions = if_ok!(relate_region_params(self, item_def_id, r_variances, diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 28240686dc358..d17553e9c39b3 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -13,16 +13,15 @@ use middle::ty; use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid}; -use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound, - ReLateBound}; -use middle::ty::{ReScope, ReVar, ReSkolemized, BrFresh}; +use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound}; +use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; use middle::typeck::infer::cres; use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin, TypeTrace}; use middle::typeck::infer; use middle::graph; use middle::graph::{Direction, NodeIndex}; use util::common::indenter; -use util::ppaux::{Repr}; +use util::ppaux::Repr; use std::cell::{Cell, RefCell}; use std::uint; @@ -318,6 +317,11 @@ impl<'a> RegionVarBindings<'a> { origin.repr(self.tcx)); match (sub, sup) { + (ReEarlyBound(..), ReEarlyBound(..)) => { + // This case is used only to make sure that explicitly-specified + // `Self` types match the real self type in implementations. + self.add_constraint(ConstrainRegSubReg(sub, sup), origin); + } (ReEarlyBound(..), _) | (ReLateBound(..), _) | (_, ReEarlyBound(..)) | diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 8b5d16620b0f5..a65aa0423a6d0 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -214,6 +214,7 @@ pub fn infer_variance(tcx: &ty::ctxt, let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate); let constraints_cx = add_constraints_from_crate(terms_cx, krate); solve_constraints(constraints_cx); + tcx.variance_computed.set(true); } /************************************************************************** diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 6526943955c92..e37bef98e4404 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -14,7 +14,7 @@ use middle::subst; use middle::subst::{VecPerParamSpace,Subst}; use middle::ty::{ReSkolemized, ReVar}; use middle::ty::{BoundRegion, BrAnon, BrNamed}; -use middle::ty::{BrFresh, ctxt}; +use middle::ty::{ReEarlyBound, BrFresh, ctxt}; use middle::ty::{mt, t, ParamTy}; use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty}; use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum}; @@ -130,9 +130,13 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) ReEmpty => { ("the empty lifetime".to_string(), None) } + ReEarlyBound(_, _, _, name) => { + (format!("{}", token::get_name(name)), None) + } + // I believe these cases should not occur (except when debugging, // perhaps) - ty::ReInfer(_) | ty::ReEarlyBound(..) | ty::ReLateBound(..) => { + ty::ReInfer(_) | ty::ReLateBound(..) => { (format!("lifetime {:?}", region), None) } }; @@ -421,6 +425,19 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { } } +pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory) + -> &'static str { + match *category { + ty::StaticExplicitSelfCategory => "static", + ty::ByValueExplicitSelfCategory => "self", + ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => { + "&mut self" + } + ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self", + ty::ByBoxExplicitSelfCategory => "Box", + } +} + pub fn parameterized(cx: &ctxt, base: &str, substs: &subst::Substs, @@ -1083,3 +1100,10 @@ impl Repr for region_inference::VarValue { } } } + +impl Repr for ty::ExplicitSelfCategory { + fn repr(&self, _: &ctxt) -> String { + explicit_self_category_to_str(self).to_string() + } +} + diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 54053d215dc3b..5be668853207f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -394,7 +394,7 @@ impl Clean for doctree::Module { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub enum Attribute { Word(String), List(String, Vec ), @@ -447,7 +447,7 @@ impl<'a> attr::AttrMetaMethods for &'a Attribute { fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc]> { None } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct TyParam { pub name: String, pub did: ast::DefId, @@ -479,7 +479,7 @@ impl Clean for ty::TypeParameterDef { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub enum TyParamBound { RegionBound, TraitBound(Type) @@ -638,7 +638,7 @@ impl Clean> for ty::Region { } // maybe use a Generic enum and use ~[Generic]? -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct Generics { pub lifetimes: Vec, pub type_params: Vec, @@ -771,6 +771,7 @@ pub enum SelfTy { SelfValue, SelfBorrowed(Option, Mutability), SelfOwned, + SelfExplicit(Type), } impl Clean for ast::ExplicitSelf_ { @@ -779,7 +780,10 @@ impl Clean for ast::ExplicitSelf_ { ast::SelfStatic => SelfStatic, ast::SelfValue(_) => SelfValue, ast::SelfUniq(_) => SelfOwned, - ast::SelfRegion(lt, mt, _) => SelfBorrowed(lt.clean(), mt.clean()), + ast::SelfRegion(lt, mt, _) => { + SelfBorrowed(lt.clean(), mt.clean()) + } + ast::SelfExplicit(typ, _) => SelfExplicit(typ.clean()), } } } @@ -809,7 +813,7 @@ impl Clean for doctree::Function { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct ClosureDecl { pub lifetimes: Vec, pub decl: FnDecl, @@ -833,7 +837,7 @@ impl Clean for ast::ClosureTy { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct FnDecl { pub inputs: Arguments, pub output: Type, @@ -841,7 +845,7 @@ pub struct FnDecl { pub attrs: Vec, } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct Arguments { pub values: Vec, } @@ -888,7 +892,7 @@ impl<'a> Clean for (ast::DefId, &'a ty::FnSig) { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct Argument { pub type_: Type, pub name: String, @@ -905,7 +909,7 @@ impl Clean for ast::Arg { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub enum RetStyle { NoReturn, Return @@ -991,22 +995,28 @@ impl Clean for ty::Method { fn clean(&self) -> Item { let cx = get_cx(); let (self_, sig) = match self.explicit_self { - ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()), + ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(), self.fty.sig.clone()), s => { let sig = ty::FnSig { inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)), ..self.fty.sig.clone() }; let s = match s { - ast::SelfRegion(..) => { - match ty::get(self.fty.sig.inputs[0]).sty { + ty::ByReferenceExplicitSelfCategory(..) => { + match ty::get(*self.fty.sig.inputs[0]).sty { ty::ty_rptr(r, mt) => { SelfBorrowed(r.clean(), mt.mutbl.clean()) } - _ => s.clean(), + _ => { + // FIXME(pcwalton): This is wrong. + SelfStatic + } } } - s => s.clean(), + _ => { + // FIXME(pcwalton): This is wrong. + SelfStatic + } }; (s, sig) } @@ -1032,7 +1042,7 @@ impl Clean for ty::Method { /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly /// it does not preserve mutability or boxes. -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub enum Type { /// structs/enums/traits (anything that'd be an ast::TyPath) ResolvedPath { @@ -1550,7 +1560,7 @@ impl Clean for syntax::codemap::Span { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct Path { pub global: bool, pub segments: Vec, @@ -1565,7 +1575,7 @@ impl Clean for ast::Path { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct PathSegment { pub name: String, pub lifetimes: Vec, @@ -1631,7 +1641,7 @@ impl Clean for doctree::Typedef { } } -#[deriving(Clone, Encodable, Decodable)] +#[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct BareFunctionDecl { pub fn_style: ast::FnStyle, pub generics: Generics, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f64a75c559e9b..d0f9b37cc4ce4 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -500,6 +500,9 @@ impl<'a> fmt::Show for Method<'a> { args.push_str(format!("&{}self", MutableSpace(mtbl)).as_slice()); } + clean::SelfExplicit(ref typ) => { + args.push_str(format!("self: {}", *typ).as_slice()); + } } for (i, input) in d.inputs.values.iter().enumerate() { if i > 0 || args.len() > 0 { args.push_str(", "); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 857cb4c0162ce..d9f14bfa15661 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -949,12 +949,14 @@ pub enum RetStyle { pub enum ExplicitSelf_ { /// No self SelfStatic, - /// `self + /// `self` SelfValue(Ident), /// `&'lt self`, `&'lt mut self` SelfRegion(Option, Mutability, Ident), /// `~self` - SelfUniq(Ident) + SelfUniq(Ident), + /// `self: TYPE` + SelfExplicit(P, Ident), } pub type ExplicitSelf = Spanned; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index fd786192cb48c..87c762af2e5bd 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -344,6 +344,7 @@ pub trait Folder { SelfRegion(ref lifetime, m, id) => { SelfRegion(fold_opt_lifetime(lifetime, self), m, id) } + SelfExplicit(ref typ, id) => SelfExplicit(self.fold_ty(*typ), id), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e0c94dffb5cae..bdfd928cfbcd8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -45,7 +45,7 @@ use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub}; use ast::StrStyle; -use ast::{SelfRegion, SelfStatic, SelfUniq, SelfValue}; +use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfUniq, SelfValue}; use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok}; use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; @@ -3843,7 +3843,15 @@ impl<'a> Parser<'a> { } } token::IDENT(..) if self.is_self_ident() => { - SelfValue(self.expect_self_ident()) + let self_ident = self.expect_self_ident(); + + // Determine whether this is the fully explicit form, `self: + // TYPE`. + if self.eat(&token::COLON) { + SelfExplicit(self.parse_ty(false), self_ident) + } else { + SelfValue(self_ident) + } } token::BINOP(token::STAR) => { // Possibly "*self" or "*mut self" -- not supported. Try to avoid @@ -3851,7 +3859,9 @@ impl<'a> Parser<'a> { self.bump(); let _mutability = if Parser::token_is_mutability(&self.token) { self.parse_mutability() - } else { MutImmutable }; + } else { + MutImmutable + }; if self.is_self_ident() { let span = self.span; self.span_err(span, "cannot pass self by unsafe pointer"); @@ -3863,7 +3873,15 @@ impl<'a> Parser<'a> { _ if Parser::token_is_mutability(&self.token) && self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => { mutbl_self = self.parse_mutability(); - SelfValue(self.expect_self_ident()) + let self_ident = self.expect_self_ident(); + + // Determine whether this is the fully explicit form, `self: + // TYPE`. + if self.eat(&token::COLON) { + SelfExplicit(self.parse_ty(false), self_ident) + } else { + SelfValue(self_ident) + } } _ if Parser::token_is_mutability(&self.token) && self.look_ahead(1, |t| *t == token::TILDE) && @@ -3914,8 +3932,8 @@ impl<'a> Parser<'a> { } SelfValue(id) => parse_remaining_arguments!(id), SelfRegion(_,_,id) => parse_remaining_arguments!(id), - SelfUniq(id) => parse_remaining_arguments!(id) - + SelfUniq(id) => parse_remaining_arguments!(id), + SelfExplicit(_,id) => parse_remaining_arguments!(id), }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d524622f8ecf5..428a15cb8cf74 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1859,6 +1859,11 @@ impl<'a> State<'a> { try!(self.print_mutability(m)); try!(word(&mut self.s, "self")); } + ast::SelfExplicit(ref typ, _) => { + try!(word(&mut self.s, "self")); + try!(self.word_space(":")); + try!(self.print_type(*typ)); + } } return Ok(true); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 795f19d0cfb06..6760d7a393205 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -215,6 +215,7 @@ pub fn walk_explicit_self>(visitor: &mut V, SelfRegion(ref lifetime, _, _) => { visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env) } + SelfExplicit(ref typ, _) => visitor.visit_ty(*typ, env.clone()), } } diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs new file mode 100644 index 0000000000000..285792e26b1bf --- /dev/null +++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs @@ -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 or the MIT license +// , 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() {} + diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs new file mode 100644 index 0000000000000..e5bad7e31b81e --- /dev/null +++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs @@ -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 or the MIT license +// , 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 { + f: T, +} + +impl Bar { + fn foo(self: Bar, x: int) -> int { //~ ERROR mismatched self type +//~^ ERROR not a valid type for `self` + x + } + fn bar(self: &Bar, 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)); +} + diff --git a/src/test/run-pass/ufcs-explicit-self.rs b/src/test/run-pass/ufcs-explicit-self.rs new file mode 100644 index 0000000000000..9ffb56c516af5 --- /dev/null +++ b/src/test/run-pass/ufcs-explicit-self.rs @@ -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 or the MIT license +// , 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, x: int) -> int { + self.f + x + } +} + +struct Bar { + f: T, +} + +impl Bar { + fn foo(self: Bar, x: int) -> int { + x + } + fn bar<'a>(self: &'a Bar, x: int) -> int { + x + } + fn baz(self: Bar, 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; + println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); +} + From fe49cbeb82deaa771dcaa4f512cb9f967beb5996 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Jul 2014 21:52:28 -0700 Subject: [PATCH 2/3] libsyntax: Remove `Send` from `PtrTy` in `deriving`. It'll be complex to port to the new explicit-self regime and it seems to be unused. --- src/libsyntax/ext/deriving/generic/ty.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index f6a39d7b2e6c1..06eb92e1b271b 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -25,8 +25,6 @@ use std::gc::Gc; /// The types of pointers pub enum PtrTy<'a> { - /// ~ - Send, /// &'lifetime mut Borrowed(Option<&'a str>, ast::Mutability), } @@ -138,9 +136,6 @@ impl<'a> Ty<'a> { Ptr(ref ty, ref ptr) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); match *ptr { - Send => { - cx.ty_uniq(span, raw_ty) - } Borrowed(ref lt, mutbl) => { let lt = mk_lifetime(cx, span, lt); cx.ty_rptr(span, raw_ty, lt, mutbl) @@ -260,7 +255,6 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option) let self_ty = respan( span, match *ptr { - Send => ast::SelfUniq(special_idents::self_), Borrowed(ref lt, mutbl) => { let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name)); ast::SelfRegion(lt, mutbl, special_idents::self_) From 00c70d1a803e62ccbe2545d5c5522f4dcd6953b9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Jul 2014 23:19:35 -0700 Subject: [PATCH 3/3] librustc: Allow the new UFCS explicit self in trait definitions, and remove `~self` from the test suite. --- src/librustdoc/clean/mod.rs | 2 +- src/test/compile-fail/issue-5153.rs | 4 ++-- src/test/compile-fail/lint-unused-mut-self.rs | 2 +- src/test/compile-fail/object-pointer-types.rs | 2 +- src/test/debuginfo/generic-method-on-generic-struct.rs | 2 +- src/test/debuginfo/method-on-enum.rs | 2 +- src/test/debuginfo/method-on-generic-struct.rs | 2 +- src/test/debuginfo/method-on-struct.rs | 2 +- src/test/debuginfo/method-on-trait.rs | 4 ++-- src/test/debuginfo/method-on-tuple-struct.rs | 2 +- src/test/debuginfo/self-in-default-method.rs | 2 +- src/test/debuginfo/self-in-generic-default-method.rs | 2 +- src/test/run-pass/autoderef-method-on-trait.rs | 4 ++-- src/test/run-pass/autoderef-method-twice-but-not-thrice.rs | 4 ++-- src/test/run-pass/autoderef-method-twice.rs | 4 ++-- src/test/run-pass/autoderef-method.rs | 4 ++-- src/test/run-pass/explicit-self-objects-uniq.rs | 4 ++-- src/test/run-pass/explicit-self.rs | 2 +- src/test/run-pass/issue-7320.rs | 2 +- src/test/run-pass/objects-owned-object-owned-method.rs | 4 ++-- src/test/run-pass/self-in-mut-slot-default-method.rs | 2 +- src/test/run-pass/uniq-self-in-mut-slot.rs | 4 ++-- 22 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5be668853207f..c94759d7d7e8d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1003,7 +1003,7 @@ impl Clean for ty::Method { }; let s = match s { 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) => { SelfBorrowed(r.clean(), mt.mutbl.clean()) } diff --git a/src/test/compile-fail/issue-5153.rs b/src/test/compile-fail/issue-5153.rs index f8c1a91464271..57a158d2438dd 100644 --- a/src/test/compile-fail/issue-5153.rs +++ b/src/test/compile-fail/issue-5153.rs @@ -11,11 +11,11 @@ // error-pattern: type `&Foo` does not implement any method in scope named `foo` trait Foo { - fn foo(~self); + fn foo(self: Box); } impl Foo for int { - fn foo(~self) { } + fn foo(self: Box) { } } fn main() { diff --git a/src/test/compile-fail/lint-unused-mut-self.rs b/src/test/compile-fail/lint-unused-mut-self.rs index 84c484a91e2c4..fc19a1ba06f9b 100644 --- a/src/test/compile-fail/lint-unused-mut-self.rs +++ b/src/test/compile-fail/lint-unused-mut-self.rs @@ -16,7 +16,7 @@ struct Foo; impl Foo { fn foo(mut self) {} //~ ERROR: variable does not need to be mutable - fn bar(mut ~self) {} //~ ERROR: variable does not need to be mutable + fn bar(mut self: Box) {} //~ ERROR: variable does not need to be mutable } fn main() {} diff --git a/src/test/compile-fail/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs index 8868ddd4dfa30..84e7f98a40dc2 100644 --- a/src/test/compile-fail/object-pointer-types.rs +++ b/src/test/compile-fail/object-pointer-types.rs @@ -13,7 +13,7 @@ trait Foo { fn borrowed(&self); fn borrowed_mut(&mut self); - fn owned(~self); + fn owned(self: Box); } fn borrowed_receiver(x: &Foo) { diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 0f05eea628213..2e43dcdeb498e 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -134,7 +134,7 @@ impl Struct { arg1 } - fn self_owned(~self, arg1: int, arg2: T2) -> int { + fn self_owned(self: Box>, arg1: int, arg2: T2) -> int { zzz(); // #break arg1 } diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index f3d723e88bc51..74f4882bd4bf4 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -136,7 +136,7 @@ impl Enum { arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: int, arg2: int) -> int { zzz(); // #break arg1 + arg2 } diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 489ea114e1f59..590a821fcb6e1 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -134,7 +134,7 @@ impl Struct { arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box>, arg1: int, arg2: int) -> int { zzz(); // #break arg1 + arg2 } diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index f2db6e3af471e..5ea89f1548915 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -133,7 +133,7 @@ impl Struct { self.x + arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: int, arg2: int) -> int { zzz(); // #break self.x + arg1 + arg2 } diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index e38aace11b93b..1fc136ac1f695 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -124,7 +124,7 @@ struct Struct { trait Trait { fn self_by_ref(&self, arg1: int, arg2: int) -> int; fn self_by_val(self, arg1: int, arg2: int) -> int; - fn self_owned(~self, arg1: int, arg2: int) -> int; + fn self_owned(self: Box, arg1: int, arg2: int) -> int; } impl Trait for Struct { @@ -139,7 +139,7 @@ impl Trait for Struct { self.x + arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: int, arg2: int) -> int { zzz(); // #break self.x + arg1 + arg2 } diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index 6f8a6182063b7..d4051e333c184 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -131,7 +131,7 @@ impl TupleStruct { arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: int, arg2: int) -> int { zzz(); // #break arg1 + arg2 } diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index ddca9bf0792f2..4268c0adcc396 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -133,7 +133,7 @@ trait Trait { arg1 + arg2 } - fn self_owned(~self, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: int, arg2: int) -> int { zzz(); // #break arg1 + arg2 } diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index 57ffc4a2e19d6..35f3dffa0b637 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -134,7 +134,7 @@ trait Trait { arg1 } - fn self_owned(~self, arg1: int, arg2: T) -> int { + fn self_owned(self: Box, arg1: int, arg2: T) -> int { zzz(); // #break arg1 } diff --git a/src/test/run-pass/autoderef-method-on-trait.rs b/src/test/run-pass/autoderef-method-on-trait.rs index e50825a401fc6..f13f598fda28c 100644 --- a/src/test/run-pass/autoderef-method-on-trait.rs +++ b/src/test/run-pass/autoderef-method-on-trait.rs @@ -10,11 +10,11 @@ trait double { - fn double(~self) -> uint; + fn double(self: Box) -> uint; } impl double for uint { - fn double(~self) -> uint { *self * 2u } + fn double(self: Box) -> uint { *self * 2u } } pub fn main() { diff --git a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs index 7acd54788a8c2..856ee686db30e 100644 --- a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs +++ b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs @@ -10,11 +10,11 @@ trait double { - fn double(~self) -> uint; + fn double(self: Box) -> uint; } impl double for Box { - fn double(~self) -> uint { **self * 2u } + fn double(self: Box>) -> uint { **self * 2u } } pub fn main() { diff --git a/src/test/run-pass/autoderef-method-twice.rs b/src/test/run-pass/autoderef-method-twice.rs index a8b6b6f74f4ff..94da61483eaae 100644 --- a/src/test/run-pass/autoderef-method-twice.rs +++ b/src/test/run-pass/autoderef-method-twice.rs @@ -9,11 +9,11 @@ // except according to those terms. trait double { - fn double(~self) -> uint; + fn double(self: Box) -> uint; } impl double for uint { - fn double(~self) -> uint { *self * 2u } + fn double(self: Box) -> uint { *self * 2u } } pub fn main() { diff --git a/src/test/run-pass/autoderef-method.rs b/src/test/run-pass/autoderef-method.rs index 4c4ebdc94f030..2e9751ce6acfc 100644 --- a/src/test/run-pass/autoderef-method.rs +++ b/src/test/run-pass/autoderef-method.rs @@ -9,11 +9,11 @@ // except according to those terms. trait double { - fn double(~self) -> uint; + fn double(self: Box) -> uint; } impl double for uint { - fn double(~self) -> uint { *self * 2u } + fn double(self: Box) -> uint { *self * 2u } } pub fn main() { diff --git a/src/test/run-pass/explicit-self-objects-uniq.rs b/src/test/run-pass/explicit-self-objects-uniq.rs index 595bb4f6b9e44..e566f218aa8f6 100644 --- a/src/test/run-pass/explicit-self-objects-uniq.rs +++ b/src/test/run-pass/explicit-self-objects-uniq.rs @@ -10,7 +10,7 @@ trait Foo { - fn f(~self); + fn f(self: Box); } struct S { @@ -18,7 +18,7 @@ struct S { } impl Foo for S { - fn f(~self) { + fn f(self: Box) { assert_eq!(self.x, 3); } } diff --git a/src/test/run-pass/explicit-self.rs b/src/test/run-pass/explicit-self.rs index 6c2e17046d3c1..32ac14ab18074 100644 --- a/src/test/run-pass/explicit-self.rs +++ b/src/test/run-pass/explicit-self.rs @@ -57,7 +57,7 @@ fn thing(x: A) -> thing { } impl thing { - pub fn bar(~self) -> int { self.x.a } + pub fn bar(self: Box) -> int { self.x.a } pub fn quux(&self) -> int { self.x.a } pub fn baz<'a>(&'a self) -> &'a A { &self.x } pub fn spam(self) -> int { self.x.a } diff --git a/src/test/run-pass/issue-7320.rs b/src/test/run-pass/issue-7320.rs index 99ed4288a7ec1..c7087f8e3a8ca 100644 --- a/src/test/run-pass/issue-7320.rs +++ b/src/test/run-pass/issue-7320.rs @@ -10,7 +10,7 @@ trait Foo { - fn foo(~self) { bar(self as Box); } + fn foo(self: Box) { bar(self as Box); } } fn bar(_b: Box) { } diff --git a/src/test/run-pass/objects-owned-object-owned-method.rs b/src/test/run-pass/objects-owned-object-owned-method.rs index 540593c43fbfd..14ddc5d660f0c 100644 --- a/src/test/run-pass/objects-owned-object-owned-method.rs +++ b/src/test/run-pass/objects-owned-object-owned-method.rs @@ -14,7 +14,7 @@ trait FooTrait { - fn foo(~self) -> uint; + fn foo(self: Box) -> uint; } struct BarStruct { @@ -22,7 +22,7 @@ struct BarStruct { } impl FooTrait for BarStruct { - fn foo(~self) -> uint { + fn foo(self: Box) -> uint { self.x } } diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs index 8ab27cfb4ee23..b4a46f34015a2 100644 --- a/src/test/run-pass/self-in-mut-slot-default-method.rs +++ b/src/test/run-pass/self-in-mut-slot-default-method.rs @@ -19,7 +19,7 @@ trait Changer { self } - fn change_again(mut ~self) -> Box { + fn change_again(mut self: Box) -> Box { self.set_to(45); self } diff --git a/src/test/run-pass/uniq-self-in-mut-slot.rs b/src/test/run-pass/uniq-self-in-mut-slot.rs index 3700e02051a69..4d7830e1cdca1 100644 --- a/src/test/run-pass/uniq-self-in-mut-slot.rs +++ b/src/test/run-pass/uniq-self-in-mut-slot.rs @@ -14,11 +14,11 @@ struct X { } trait Changer { - fn change(mut ~self) -> Box; + fn change(mut self: Box) -> Box; } impl Changer for X { - fn change(mut ~self) -> Box { + fn change(mut self: Box) -> Box { self.a = 55; self }