mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-28 20:16:58 +03:00
Auto merge of #45870 - mikeyhew:arbitrary_self_types, r=arielb1
Implement arbitrary_self_types r? @arielb1 cc @nikomatsakis Partial implementation of #44874. Supports trait and struct methods with arbitrary self types, as long as the type derefs (transitively) to `Self`. Doesn't support raw-pointer `self` yet. Methods with non-standard self types (i.e. anything other than `&self, &mut self, and Box<Self>`) are not object safe, because dynamic dispatch hasn't been implemented for them yet. I believe this is also a (partial) fix for #27941.
This commit is contained in:
@@ -633,11 +633,15 @@ fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'
|
||||
|
||||
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>) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
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 @@ pub fn error_msg(&self) -> Cow<'static, str> {
|
||||
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<Self>` 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<A>()`
|
||||
Generic,
|
||||
|
||||
/// arbitrary `self` type, e.g. `self: Rc<Self>`
|
||||
NonStandardSelfType,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
@@ -260,9 +268,16 @@ fn virtual_call_violation_for_method(self,
|
||||
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);
|
||||
|
||||
@@ -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<self>`, 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<P>(
|
||||
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,
|
||||
|
||||
@@ -1386,64 +1386,3 @@ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'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<self>`. 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
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 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) {
|
||||
|
||||
@@ -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 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
|
||||
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 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
|
||||
|
||||
debug!("check_method_receiver: sig={:?}", sig);
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
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));
|
||||
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)
|
||||
);
|
||||
|
||||
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
|
||||
let self_arg_ty = sig.inputs()[0];
|
||||
|
||||
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();
|
||||
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<Self>`")
|
||||
.code(DiagnosticId::Error("E0307".into()))
|
||||
.emit();
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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<Self>`")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4724,6 +4724,7 @@ fn description(&self) -> &str {
|
||||
// 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
|
||||
|
||||
@@ -409,6 +409,9 @@ pub fn new() -> 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! (
|
||||
|
||||
@@ -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 <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.
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
trait Foo {
|
||||
fn foo(self: Rc<Self>) -> usize;
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
fn foo(self: Rc<Self>) -> usize where Self: Sized;
|
||||
fn bar(self: Box<Self>) -> usize;
|
||||
}
|
||||
|
||||
impl Foo for usize {
|
||||
fn foo(self: Rc<Self>) -> usize {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar for usize {
|
||||
fn foo(self: Rc<Self>) -> usize {
|
||||
*self
|
||||
}
|
||||
|
||||
fn bar(self: Box<Self>) -> usize {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
fn make_foo() {
|
||||
let x = Box::new(5usize) as Box<Foo>;
|
||||
//~^ 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<std::boxed::Box<Foo>>`
|
||||
}
|
||||
|
||||
fn make_bar() {
|
||||
let x = Box::new(5usize) as Box<Bar>;
|
||||
x.bar();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -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 <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::rc::Rc;
|
||||
|
||||
trait Foo {
|
||||
fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for Bar {
|
||||
fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
impl S {
|
||||
fn f(self: *mut S) -> String { self.0 }
|
||||
//~^ ERROR mismatched method receiver
|
||||
//~^ ERROR invalid `self` type
|
||||
}
|
||||
|
||||
fn main() { S("".to_owned()).f(); }
|
||||
|
||||
@@ -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<T> {
|
||||
}
|
||||
|
||||
impl<T> Bar<T> {
|
||||
fn foo(self: Bar<isize>, x: isize) -> isize { //~ ERROR mismatched method receiver
|
||||
fn foo(self: Bar<isize>, x: isize) -> isize {
|
||||
//~^ ERROR invalid `self` type
|
||||
x
|
||||
}
|
||||
fn bar(self: &Bar<usize>, x: isize) -> isize { //~ ERROR mismatched method receiver
|
||||
fn bar(self: &Bar<usize>, x: isize) -> isize {
|
||||
//~^ ERROR invalid `self` type
|
||||
x
|
||||
}
|
||||
}
|
||||
@@ -45,12 +48,12 @@ fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
|
||||
//~^ ERROR mismatched method receiver
|
||||
fn dummy3(self: &&Bar<T>) {}
|
||||
//~^ ERROR mismatched method receiver
|
||||
//~| expected type `&&'a Bar<T>`
|
||||
//~| found type `&&Bar<T>`
|
||||
//~| expected type `&'a Bar<T>`
|
||||
//~| found type `&Bar<T>`
|
||||
//~| lifetime mismatch
|
||||
//~| ERROR mismatched method receiver
|
||||
//~| expected type `&&'a Bar<T>`
|
||||
//~| found type `&&Bar<T>`
|
||||
//~| expected type `&'a Bar<T>`
|
||||
//~| found type `&Bar<T>`
|
||||
//~| lifetime mismatch
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
// <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::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<Foo>) {} //~ ERROR E0308
|
||||
fn bar(self: Bar) -> i32 { 3 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(3, Bar.bar());
|
||||
}
|
||||
@@ -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 <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.
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
struct Foo {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn x(self: &Rc<Self>) -> i32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(self: Rc<Self>) -> i32 {
|
||||
self.y
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Rc::new(Foo {x: 3, y: 4});
|
||||
assert_eq!(3, foo.x());
|
||||
assert_eq!(4, foo.y());
|
||||
}
|
||||
@@ -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 <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.
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
trait Trait {
|
||||
fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32];
|
||||
}
|
||||
|
||||
impl Trait for Vec<i32> {
|
||||
fn trait_method<'a>(self: &'a Box<Rc<Self>>) -> &'a [i32] {
|
||||
&***self
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = vec![1,2,3];
|
||||
|
||||
assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method());
|
||||
}
|
||||
@@ -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 <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.
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
struct Foo<T: ?Sized>(T);
|
||||
|
||||
impl Foo<[u8]> {
|
||||
fn len(self: Rc<Self>) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let rc = Rc::new(Foo([1u8,2,3])) as Rc<Foo<[u8]>>;
|
||||
assert_eq!(3, rc.len());
|
||||
}
|
||||
@@ -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<Self>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user