diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 8351be490767a..4c8a72512f1d0 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -633,11 +633,15 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { debug!("RegionVarBindings: add_constraint({:?})", constraint); - if self.constraints.borrow_mut().insert(constraint, origin).is_none() { + // never overwrite an existing (constraint, origin) - only insert one if it isn't + // present in the map yet. This prevents origins from outside the snapshot being + // replaced with "less informative" origins e.g. during calls to `can_eq` + self.constraints.borrow_mut().entry(constraint).or_insert_with(|| { if self.in_snapshot() { self.undo_log.borrow_mut().push(AddConstraint(constraint)); } - } + origin + }); } fn add_verify(&self, verify: Verify<'tcx>) { diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1e9816095ea2e..facd6350e196c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -23,6 +23,7 @@ use hir::def_id::DefId; use traits; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::subst::Substs; +use ty::util::ExplicitSelf; use std::borrow::Cow; use syntax::ast; @@ -57,6 +58,10 @@ impl ObjectSafetyViolation { in its arguments or return type", name).into(), ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => format!("method `{}` has generic type parameters", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::NonStandardSelfType) => + format!("method `{}` has a non-standard `self` type. Only `&self`, \ + `&mut self`, and `Box` are currently supported \ + for trait objects", name).into(), ObjectSafetyViolation::AssociatedConst(name) => format!("the trait cannot contain associated consts like `{}`", name).into(), } @@ -74,6 +79,9 @@ pub enum MethodViolationCode { /// e.g., `fn foo()` Generic, + + /// arbitrary `self` type, e.g. `self: Rc` + NonStandardSelfType, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -260,9 +268,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return Some(MethodViolationCode::StaticMethod); } + let sig = self.fn_sig(method.def_id); + + let self_ty = self.mk_self_type(); + let self_arg_ty = sig.skip_binder().inputs()[0]; + if let ExplicitSelf::Other = ExplicitSelf::determine(self_arg_ty, |ty| ty == self_ty) { + return Some(MethodViolationCode::NonStandardSelfType); + } + // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = self.fn_sig(method.def_id); for input_ty in &sig.skip_binder().inputs()[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 39842a543b54b..d12a973017d9b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -12,6 +12,7 @@ use hir::def_id::{DefId, LOCAL_CRATE}; use hir::map::DefPathData; +use hir; use ich::NodeIdHashingMode; use middle::const_val::ConstVal; use traits::{self, Reveal}; @@ -1178,6 +1179,58 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, layout } +pub enum ExplicitSelf<'tcx> { + ByValue, + ByReference(ty::Region<'tcx>, hir::Mutability), + ByBox, + Other +} + +impl<'tcx> ExplicitSelf<'tcx> { + /// Categorizes an explicit self declaration like `self: SomeType` + /// into either `self`, `&self`, `&mut self`, `Box`, or + /// `Other`. + /// This is mainly used to require the arbitrary_self_types feature + /// in the case of `Other`, to improve error messages in the common cases, + /// and to make `Other` non-object-safe. + /// + /// Examples: + /// + /// ``` + /// impl<'a> Foo for &'a T { + /// // Legal declarations: + /// fn method1(self: &&'a T); // ExplicitSelf::ByReference + /// fn method2(self: &'a T); // ExplicitSelf::ByValue + /// fn method3(self: Box<&'a T>); // ExplicitSelf::ByBox + /// fn method4(self: Rc<&'a T>); // ExplicitSelf::Other + /// + /// // Invalid cases will be caught by `check_method_receiver`: + /// fn method_err1(self: &'a mut T); // ExplicitSelf::Other + /// fn method_err2(self: &'static T) // ExplicitSelf::ByValue + /// fn method_err3(self: &&T) // ExplicitSelf::ByReference + /// } + /// ``` + /// + pub fn determine

( + self_arg_ty: Ty<'tcx>, + is_self_ty: P + ) -> ExplicitSelf<'tcx> + where + P: Fn(Ty<'tcx>) -> bool + { + use self::ExplicitSelf::*; + + match self_arg_ty.sty { + _ if is_self_ty(self_arg_ty) => ByValue, + ty::TyRef(region, ty::TypeAndMut { ty, mutbl}) if is_self_ty(ty) => { + ByReference(region, mutbl) + } + ty::TyAdt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox, + _ => Other + } + } +} + pub fn provide(providers: &mut ty::maps::Providers) { *providers = ty::maps::Providers { is_copy_raw, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0bcdcd3691ef9..95b19616e5e63 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1386,64 +1386,3 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { vec } } - -pub enum ExplicitSelf<'tcx> { - ByValue, - ByReference(ty::Region<'tcx>, hir::Mutability), - ByBox -} - -impl<'tcx> ExplicitSelf<'tcx> { - /// We wish to (for now) categorize an explicit self - /// declaration like `self: SomeType` into either `self`, - /// `&self`, `&mut self`, or `Box`. We do this here - /// by some simple pattern matching. A more precise check - /// is done later in `check_method_receiver()`. - /// - /// Examples: - /// - /// ``` - /// impl Foo for &T { - /// // Legal declarations: - /// fn method1(self: &&T); // ExplicitSelf::ByReference - /// fn method2(self: &T); // ExplicitSelf::ByValue - /// fn method3(self: Box<&T>); // ExplicitSelf::ByBox - /// - /// // Invalid cases will be caught later by `check_method_receiver`: - /// fn method_err1(self: &mut T); // ExplicitSelf::ByReference - /// } - /// ``` - /// - /// To do the check we just count the number of "modifiers" - /// on each type and compare them. If they are the same or - /// the impl has more, we call it "by value". Otherwise, we - /// look at the outermost modifier on the method decl and - /// call it by-ref, by-box as appropriate. For method1, for - /// example, the impl type has one modifier, but the method - /// type has two, so we end up with - /// ExplicitSelf::ByReference. - pub fn determine(untransformed_self_ty: Ty<'tcx>, - self_arg_ty: Ty<'tcx>) - -> ExplicitSelf<'tcx> { - fn count_modifiers(ty: Ty) -> usize { - match ty.sty { - ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1, - ty::TyAdt(def, _) if def.is_box() => count_modifiers(ty.boxed_ty()) + 1, - _ => 0, - } - } - - let impl_modifiers = count_modifiers(untransformed_self_ty); - let method_modifiers = count_modifiers(self_arg_ty); - - if impl_modifiers >= method_modifiers { - ExplicitSelf::ByValue - } else { - match self_arg_ty.sty { - ty::TyRef(r, mt) => ExplicitSelf::ByReference(r, mt.mutbl), - ty::TyAdt(def, _) if def.is_box() => ExplicitSelf::ByBox, - _ => ExplicitSelf::ByValue, - } - } - } -} diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 554a858bcc173..2c44c40d83d49 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -13,6 +13,7 @@ use rustc::infer::{self, InferOk}; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region; use rustc::ty::{self, TyCtxt}; +use rustc::ty::util::ExplicitSelf; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; @@ -21,7 +22,6 @@ use rustc::util::common::ErrorReported; use syntax_pos::Span; use super::{Inherited, FnCtxt}; -use astconv::ExplicitSelf; /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. @@ -503,12 +503,17 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TraitContainer(_) => tcx.mk_self_type() }; let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); - match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { - ExplicitSelf::ByValue => "self".to_string(), - ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), - ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), - _ => format!("self: {}", self_arg_ty) - } + let param_env = ty::ParamEnv::empty(Reveal::All); + + tcx.infer_ctxt().enter(|infcx| { + let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); + match ExplicitSelf::determine(self_arg_ty, can_eq_self) { + ExplicitSelf::ByValue => "self".to_string(), + ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), + ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), + _ => format!("self: {}", self_arg_ty) + } + }) }; match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 483af08cabfce..37cf67fe53ef6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -8,19 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use astconv::ExplicitSelf; use check::{Inherited, FnCtxt}; use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::middle::lang_items; use syntax::ast; +use syntax::feature_gate::{self, GateIssue}; use syntax_pos::Span; -use errors::DiagnosticBuilder; +use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; @@ -451,8 +452,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { method: &ty::AssociatedItem, self_ty: Ty<'tcx>) { - // check that the type of the method's receiver matches the - // method's first parameter. + // check that the method has a valid receiver type, given the type `Self` debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty); @@ -468,26 +468,57 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { debug!("check_method_receiver: sig={:?}", sig); + let self_ty = fcx.normalize_associated_types_in(span, &self_ty); + let self_ty = fcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_ty) + ); + let self_arg_ty = sig.inputs()[0]; - let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) { - ExplicitSelf::ByValue => self_ty, - ExplicitSelf::ByReference(region, mutbl) => { - fcx.tcx.mk_ref(region, ty::TypeAndMut { - ty: self_ty, - mutbl, - }) + + let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); + let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); + let self_arg_ty = fcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_arg_ty) + ); + + let mut autoderef = fcx.autoderef(span, self_arg_ty); + + loop { + if let Some((potential_self_ty, _)) = autoderef.next() { + debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", + potential_self_ty, self_ty); + + if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { + autoderef.finalize(); + if let Some(mut err) = fcx.demand_eqtype_with_origin( + &cause, self_ty, potential_self_ty) { + err.emit(); + } + break + } + } else { + fcx.tcx.sess.diagnostic().mut_span_err( + span, &format!("invalid `self` type: {:?}", self_arg_ty)) + .note(&format!("type must be `{:?}` or a type that dereferences to it`", self_ty)) + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .code(DiagnosticId::Error("E0307".into())) + .emit(); + return } - ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty) - }; - let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty); - let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id, - &ty::Binder(rcvr_ty)); + } - debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); + let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); + let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); - if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty) { - err.emit(); + if let ExplicitSelf::Other = self_kind { + if !fcx.tcx.sess.features.borrow().arbitrary_self_types { + feature_gate::feature_err(&fcx.tcx.sess.parse_sess, "arbitrary_self_types", span, + GateIssue::Language, "arbitrary `self` types are unstable") + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .emit(); + } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 0c3a88a8e9a7e..73bec697d492e 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4724,6 +4724,7 @@ register_diagnostics! { // E0247, // E0248, // value used as a type, now reported earlier during resolution as E0412 // E0249, + E0307, // invalid method `self` type // E0319, // trait impls for defaulted traits allowed just for structs/enums // E0372, // coherence not object safe E0377, // the trait `CoerceUnsized` may only be implemented for a coercion diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a69bf53ee14a3..b6cb3ac13081f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -409,6 +409,9 @@ declare_features! ( // extern types (active, extern_types, "1.23.0", Some(43467)), + + // Allow trait methods with arbitrary self types + (active, arbitrary_self_types, "1.23.0", Some(44874)), ); declare_features! ( diff --git a/src/test/compile-fail/arbitrary-self-types-not-object-safe.rs b/src/test/compile-fail/arbitrary-self-types-not-object-safe.rs new file mode 100644 index 0000000000000..6b10739bd8e59 --- /dev/null +++ b/src/test/compile-fail/arbitrary-self-types-not-object-safe.rs @@ -0,0 +1,55 @@ +// Copyright 2017 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. +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +trait Foo { + fn foo(self: Rc) -> usize; +} + +trait Bar { + fn foo(self: Rc) -> usize where Self: Sized; + fn bar(self: Box) -> usize; +} + +impl Foo for usize { + fn foo(self: Rc) -> usize { + *self + } +} + +impl Bar for usize { + fn foo(self: Rc) -> usize { + *self + } + + fn bar(self: Box) -> usize { + *self + } +} + +fn make_foo() { + let x = Box::new(5usize) as Box; + //~^ ERROR E0038 + //~| NOTE method `foo` has a non-standard `self` type + //~| NOTE the trait `Foo` cannot be made into an object + //~| ERROR E0038 + //~| NOTE method `foo` has a non-standard `self` type + //~| NOTE the trait `Foo` cannot be made into an object + //~| NOTE requirements on the impl of `std::ops::CoerceUnsized>` +} + +fn make_bar() { + let x = Box::new(5usize) as Box; + x.bar(); +} + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs b/src/test/compile-fail/feature-gate-arbitrary-self-types.rs new file mode 100644 index 0000000000000..ff0306f199310 --- /dev/null +++ b/src/test/compile-fail/feature-gate-arbitrary-self-types.rs @@ -0,0 +1,27 @@ +// Copyright 2017 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::rc::Rc; + +trait Foo { + fn foo(self: Rc>); //~ ERROR arbitrary `self` types are unstable +} + +struct Bar; + +impl Foo for Bar { + fn foo(self: Rc>) {} //~ ERROR arbitrary `self` types are unstable +} + +impl Bar { + fn bar(self: Box>) {} //~ ERROR arbitrary `self` types are unstable +} + +fn main() {} diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs index 664d62e87ae61..1d5ef4360dc1e 100644 --- a/src/test/compile-fail/issue-17740.rs +++ b/src/test/compile-fail/issue-17740.rs @@ -15,12 +15,12 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { //~^ mismatched method receiver - //~| expected type `&mut Foo<'a>` - //~| found type `&mut Foo<'_>` + //~| expected type `Foo<'a>` + //~| found type `Foo<'_>` //~| lifetime mismatch //~| mismatched method receiver - //~| expected type `&mut Foo<'a>` - //~| found type `&mut Foo<'_>` + //~| expected type `Foo<'a>` + //~| found type `Foo<'_>` //~| lifetime mismatch } } diff --git a/src/test/compile-fail/issue-26194.rs b/src/test/compile-fail/issue-26194.rs index ef91188c5d166..7ddd56229ceb7 100644 --- a/src/test/compile-fail/issue-26194.rs +++ b/src/test/compile-fail/issue-26194.rs @@ -12,7 +12,7 @@ struct S(String); impl S { fn f(self: *mut S) -> String { self.0 } - //~^ ERROR mismatched method receiver + //~^ ERROR invalid `self` type } fn main() { S("".to_owned()).f(); } diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs index a98b7cd43090f..a0d1f2dc3312e 100644 --- a/src/test/compile-fail/ufcs-explicit-self-bad.rs +++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs @@ -15,7 +15,8 @@ struct Foo { } impl Foo { - fn foo(self: isize, x: isize) -> isize { //~ ERROR mismatched method receiver + fn foo(self: isize, x: isize) -> isize { + //~^ ERROR invalid `self` type self.f + x } } @@ -25,10 +26,12 @@ struct Bar { } impl Bar { - fn foo(self: Bar, x: isize) -> isize { //~ ERROR mismatched method receiver + fn foo(self: Bar, x: isize) -> isize { + //~^ ERROR invalid `self` type x } - fn bar(self: &Bar, x: isize) -> isize { //~ ERROR mismatched method receiver + fn bar(self: &Bar, x: isize) -> isize { + //~^ ERROR invalid `self` type x } } @@ -45,12 +48,12 @@ impl<'a, T> SomeTrait for &'a Bar { //~^ ERROR mismatched method receiver fn dummy3(self: &&Bar) {} //~^ ERROR mismatched method receiver - //~| expected type `&&'a Bar` - //~| found type `&&Bar` + //~| expected type `&'a Bar` + //~| found type `&Bar` //~| lifetime mismatch //~| ERROR mismatched method receiver - //~| expected type `&&'a Bar` - //~| found type `&&Bar` + //~| expected type `&'a Bar` + //~| found type `&Bar` //~| lifetime mismatch } diff --git a/src/test/compile-fail/E0308-2.rs b/src/test/run-pass/arbitrary_self_types_silly.rs similarity index 61% rename from src/test/compile-fail/E0308-2.rs rename to src/test/run-pass/arbitrary_self_types_silly.rs index 8c9fc9551561d..755a8d7ea294f 100644 --- a/src/test/compile-fail/E0308-2.rs +++ b/src/test/run-pass/arbitrary_self_types_silly.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -7,14 +7,23 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - -use std::rc::Rc; +#![feature(arbitrary_self_types)] struct Foo; +struct Bar; + +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} impl Foo { - fn x(self: Rc) {} //~ ERROR E0308 + fn bar(self: Bar) -> i32 { 3 } } fn main() { + assert_eq!(3, Bar.bar()); } diff --git a/src/test/run-pass/arbitrary_self_types_struct.rs b/src/test/run-pass/arbitrary_self_types_struct.rs new file mode 100644 index 0000000000000..961717de0463e --- /dev/null +++ b/src/test/run-pass/arbitrary_self_types_struct.rs @@ -0,0 +1,33 @@ +// Copyright 2017 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. +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct Foo { + x: i32, + y: i32, +} + +impl Foo { + fn x(self: &Rc) -> i32 { + self.x + } + + fn y(self: Rc) -> i32 { + self.y + } +} + +fn main() { + let foo = Rc::new(Foo {x: 3, y: 4}); + assert_eq!(3, foo.x()); + assert_eq!(4, foo.y()); +} diff --git a/src/test/run-pass/arbitrary_self_types_trait.rs b/src/test/run-pass/arbitrary_self_types_trait.rs new file mode 100644 index 0000000000000..e74d614dd6bd9 --- /dev/null +++ b/src/test/run-pass/arbitrary_self_types_trait.rs @@ -0,0 +1,28 @@ +// Copyright 2017 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. +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +trait Trait { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32]; +} + +impl Trait for Vec { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32] { + &***self + } +} + +fn main() { + let v = vec![1,2,3]; + + assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method()); +} diff --git a/src/test/run-pass/arbitrary_self_types_unsized_struct.rs b/src/test/run-pass/arbitrary_self_types_unsized_struct.rs new file mode 100644 index 0000000000000..8dc40e7aab111 --- /dev/null +++ b/src/test/run-pass/arbitrary_self_types_unsized_struct.rs @@ -0,0 +1,25 @@ +// Copyright 2017 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. +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct Foo(T); + +impl Foo<[u8]> { + fn len(self: Rc) -> usize { + self.0.len() + } +} + +fn main() { + let rc = Rc::new(Foo([1u8,2,3])) as Rc>; + assert_eq!(3, rc.len()); +} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index 117b109780b15..e12fb57f15dc9 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -1,11 +1,11 @@ -error[E0308]: mismatched method receiver +error[E0307]: invalid `self` type: &SomeType --> $DIR/issue-27522.rs:16:22 | 16 | fn handler(self: &SomeType); - | ^^^^^^^^^ expected Self, found struct `SomeType` + | ^^^^^^^^^ | - = note: expected type `&Self` - found type `&SomeType` + = note: type must be `Self` or a type that dereferences to it` + = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` error: aborting due to previous error diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index f73dff4f73d0e..adeabd91302ce 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -1,10 +1,15 @@ -error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/static-lifetime.rs:13:20 | 13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^^^^^^^^ | - = note: type must satisfy the static lifetime +note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 13:1 + --> $DIR/static-lifetime.rs:13:1 + | +13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: but lifetime parameter must outlive the static lifetime error: aborting due to previous error