mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +00:00
Merge pull request #19012 from ShoyuVanilla/arbitrary-self
feat: Implement `arbitrary-self-types`
This commit is contained in:
commit
3a163faba1
9 changed files with 129 additions and 26 deletions
|
|
@ -372,6 +372,7 @@ language_item_table! {
|
||||||
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
|
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||||
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||||
|
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
|
||||||
|
|
||||||
Fn, sym::fn_, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
Fn, sym::fn_, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ pub fn autoderef(
|
||||||
) -> impl Iterator<Item = Ty> {
|
) -> impl Iterator<Item = Ty> {
|
||||||
let mut table = InferenceTable::new(db, env);
|
let mut table = InferenceTable::new(db, env);
|
||||||
let ty = table.instantiate_canonical(ty);
|
let ty = table.instantiate_canonical(ty);
|
||||||
let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false);
|
let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false, false);
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
while let Some((ty, _steps)) = autoderef.next() {
|
while let Some((ty, _steps)) = autoderef.next() {
|
||||||
// `ty` may contain unresolved inference variables. Since there's no chance they would be
|
// `ty` may contain unresolved inference variables. Since there's no chance they would be
|
||||||
|
|
@ -89,12 +89,18 @@ pub(crate) struct Autoderef<'table, 'db, T = Vec<(AutoderefKind, Ty)>> {
|
||||||
at_start: bool,
|
at_start: bool,
|
||||||
steps: T,
|
steps: T,
|
||||||
explicit: bool,
|
explicit: bool,
|
||||||
|
use_receiver_trait: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'table, 'db> Autoderef<'table, 'db> {
|
impl<'table, 'db> Autoderef<'table, 'db> {
|
||||||
pub(crate) fn new(table: &'table mut InferenceTable<'db>, ty: Ty, explicit: bool) -> Self {
|
pub(crate) fn new(
|
||||||
|
table: &'table mut InferenceTable<'db>,
|
||||||
|
ty: Ty,
|
||||||
|
explicit: bool,
|
||||||
|
use_receiver_trait: bool,
|
||||||
|
) -> Self {
|
||||||
let ty = table.resolve_ty_shallow(&ty);
|
let ty = table.resolve_ty_shallow(&ty);
|
||||||
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit }
|
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn steps(&self) -> &[(AutoderefKind, Ty)] {
|
pub(crate) fn steps(&self) -> &[(AutoderefKind, Ty)] {
|
||||||
|
|
@ -107,9 +113,10 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
|
||||||
table: &'table mut InferenceTable<'db>,
|
table: &'table mut InferenceTable<'db>,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
explicit: bool,
|
explicit: bool,
|
||||||
|
use_receiver_trait: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ty = table.resolve_ty_shallow(&ty);
|
let ty = table.resolve_ty_shallow(&ty);
|
||||||
Autoderef { table, ty, at_start: true, steps: 0, explicit }
|
Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +144,8 @@ impl<T: TrackAutoderefSteps> Iterator for Autoderef<'_, '_, T> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (kind, new_ty) = autoderef_step(self.table, self.ty.clone(), self.explicit)?;
|
let (kind, new_ty) =
|
||||||
|
autoderef_step(self.table, self.ty.clone(), self.explicit, self.use_receiver_trait)?;
|
||||||
|
|
||||||
self.steps.push(kind, &self.ty);
|
self.steps.push(kind, &self.ty);
|
||||||
self.ty = new_ty;
|
self.ty = new_ty;
|
||||||
|
|
@ -150,11 +158,12 @@ pub(crate) fn autoderef_step(
|
||||||
table: &mut InferenceTable<'_>,
|
table: &mut InferenceTable<'_>,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
explicit: bool,
|
explicit: bool,
|
||||||
|
use_receiver_trait: bool,
|
||||||
) -> Option<(AutoderefKind, Ty)> {
|
) -> Option<(AutoderefKind, Ty)> {
|
||||||
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
|
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
|
||||||
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
|
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
|
||||||
} else {
|
} else {
|
||||||
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
|
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +185,7 @@ pub(crate) fn builtin_deref<'ty>(
|
||||||
pub(crate) fn deref_by_trait(
|
pub(crate) fn deref_by_trait(
|
||||||
table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
|
table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
|
use_receiver_trait: bool,
|
||||||
) -> Option<Ty> {
|
) -> Option<Ty> {
|
||||||
let _p = tracing::info_span!("deref_by_trait").entered();
|
let _p = tracing::info_span!("deref_by_trait").entered();
|
||||||
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
||||||
|
|
@ -183,14 +193,25 @@ pub(crate) fn deref_by_trait(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let deref_trait =
|
let trait_id = || {
|
||||||
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
|
if use_receiver_trait {
|
||||||
|
if let Some(receiver) =
|
||||||
|
db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
|
||||||
|
{
|
||||||
|
return Some(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Old rustc versions might not have `Receiver` trait.
|
||||||
|
// Fallback to `Deref` if they don't
|
||||||
|
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
|
||||||
|
};
|
||||||
|
let trait_id = trait_id()?;
|
||||||
let target = db
|
let target = db
|
||||||
.trait_data(deref_trait)
|
.trait_data(trait_id)
|
||||||
.associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?;
|
.associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?;
|
||||||
|
|
||||||
let projection = {
|
let projection = {
|
||||||
let b = TyBuilder::subst_for_def(db, deref_trait, None);
|
let b = TyBuilder::subst_for_def(db, trait_id, None);
|
||||||
if b.remaining() != 1 {
|
if b.remaining() != 1 {
|
||||||
// the Target type + Deref trait should only have one generic parameter,
|
// the Target type + Deref trait should only have one generic parameter,
|
||||||
// namely Deref's Self type
|
// namely Deref's Self type
|
||||||
|
|
|
||||||
|
|
@ -420,7 +420,7 @@ impl InferenceTable<'_> {
|
||||||
|
|
||||||
let snapshot = self.snapshot();
|
let snapshot = self.snapshot();
|
||||||
|
|
||||||
let mut autoderef = Autoderef::new(self, from_ty.clone(), false);
|
let mut autoderef = Autoderef::new(self, from_ty.clone(), false, false);
|
||||||
let mut first_error = None;
|
let mut first_error = None;
|
||||||
let mut found = None;
|
let mut found = None;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -487,7 +487,7 @@ impl InferenceContext<'_> {
|
||||||
}
|
}
|
||||||
Expr::Call { callee, args, .. } => {
|
Expr::Call { callee, args, .. } => {
|
||||||
let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes);
|
let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes);
|
||||||
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
|
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false, true);
|
||||||
let (res, derefed_callee) = loop {
|
let (res, derefed_callee) = loop {
|
||||||
let Some((callee_deref_ty, _)) = derefs.next() else {
|
let Some((callee_deref_ty, _)) = derefs.next() else {
|
||||||
break (None, callee_ty.clone());
|
break (None, callee_ty.clone());
|
||||||
|
|
@ -854,7 +854,7 @@ impl InferenceContext<'_> {
|
||||||
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
|
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
|
||||||
self.resolve_ty_shallow(derefed)
|
self.resolve_ty_shallow(derefed)
|
||||||
} else {
|
} else {
|
||||||
deref_by_trait(&mut self.table, inner_ty)
|
deref_by_trait(&mut self.table, inner_ty, false)
|
||||||
.unwrap_or_else(|| self.err_ty())
|
.unwrap_or_else(|| self.err_ty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1718,7 +1718,7 @@ impl InferenceContext<'_> {
|
||||||
receiver_ty: &Ty,
|
receiver_ty: &Ty,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> {
|
) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> {
|
||||||
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false);
|
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false, false);
|
||||||
let mut private_field = None;
|
let mut private_field = None;
|
||||||
let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
|
let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
|
||||||
let (field_id, parameters) = match derefed_ty.kind(Interner) {
|
let (field_id, parameters) = match derefed_ty.kind(Interner) {
|
||||||
|
|
|
||||||
|
|
@ -528,7 +528,7 @@ impl ReceiverAdjustments {
|
||||||
let mut ty = table.resolve_ty_shallow(&ty);
|
let mut ty = table.resolve_ty_shallow(&ty);
|
||||||
let mut adjust = Vec::new();
|
let mut adjust = Vec::new();
|
||||||
for _ in 0..self.autoderefs {
|
for _ in 0..self.autoderefs {
|
||||||
match autoderef::autoderef_step(table, ty.clone(), true) {
|
match autoderef::autoderef_step(table, ty.clone(), true, false) {
|
||||||
None => {
|
None => {
|
||||||
never!("autoderef not possible for {:?}", ty);
|
never!("autoderef not possible for {:?}", ty);
|
||||||
ty = TyKind::Error.intern(Interner);
|
ty = TyKind::Error.intern(Interner);
|
||||||
|
|
@ -1106,7 +1106,8 @@ fn iterate_method_candidates_by_receiver(
|
||||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||||
// that, including raw derefs.
|
// that, including raw derefs.
|
||||||
table.run_in_snapshot(|table| {
|
table.run_in_snapshot(|table| {
|
||||||
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
|
let mut autoderef =
|
||||||
|
autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
|
||||||
while let Some((self_ty, _)) = autoderef.next() {
|
while let Some((self_ty, _)) = autoderef.next() {
|
||||||
iterate_inherent_methods(
|
iterate_inherent_methods(
|
||||||
&self_ty,
|
&self_ty,
|
||||||
|
|
@ -1123,7 +1124,8 @@ fn iterate_method_candidates_by_receiver(
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
})?;
|
})?;
|
||||||
table.run_in_snapshot(|table| {
|
table.run_in_snapshot(|table| {
|
||||||
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
|
let mut autoderef =
|
||||||
|
autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
|
||||||
while let Some((self_ty, _)) = autoderef.next() {
|
while let Some((self_ty, _)) = autoderef.next() {
|
||||||
if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
|
if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
|
||||||
// don't try to resolve methods on unknown types
|
// don't try to resolve methods on unknown types
|
||||||
|
|
@ -1709,7 +1711,7 @@ fn autoderef_method_receiver(
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
|
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
|
||||||
let mut deref_chain: Vec<_> = Vec::new();
|
let mut deref_chain: Vec<_> = Vec::new();
|
||||||
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false);
|
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false, true);
|
||||||
while let Some((ty, derefs)) = autoderef.next() {
|
while let Some((ty, derefs)) = autoderef.next() {
|
||||||
deref_chain.push((
|
deref_chain.push((
|
||||||
autoderef.table.canonicalize(ty),
|
autoderef.table.canonicalize(ty),
|
||||||
|
|
|
||||||
|
|
@ -1343,7 +1343,7 @@ fn foo<T: Trait>(a: &T) {
|
||||||
fn autoderef_visibility_field() {
|
fn autoderef_visibility_field() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
mod a {
|
mod a {
|
||||||
pub struct Foo(pub char);
|
pub struct Foo(pub char);
|
||||||
pub struct Bar(i32);
|
pub struct Bar(i32);
|
||||||
|
|
@ -1375,7 +1375,7 @@ fn autoderef_visibility_method() {
|
||||||
cov_mark::check!(autoderef_candidate_not_visible);
|
cov_mark::check!(autoderef_candidate_not_visible);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
mod a {
|
mod a {
|
||||||
pub struct Foo(pub char);
|
pub struct Foo(pub char);
|
||||||
impl Foo {
|
impl Foo {
|
||||||
|
|
@ -1741,7 +1741,7 @@ fn main() {
|
||||||
fn deref_fun_1() {
|
fn deref_fun_1() {
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
|
|
||||||
struct A<T, U>(T, U);
|
struct A<T, U>(T, U);
|
||||||
struct B<T>(T);
|
struct B<T>(T);
|
||||||
|
|
@ -1782,7 +1782,7 @@ fn test() {
|
||||||
fn deref_fun_2() {
|
fn deref_fun_2() {
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
|
|
||||||
struct A<T, U>(T, U);
|
struct A<T, U>(T, U);
|
||||||
struct B<T>(T);
|
struct B<T>(T);
|
||||||
|
|
@ -1903,7 +1903,7 @@ pub fn test(generic_args: impl Into<Foo>) {
|
||||||
fn bad_inferred_reference_2() {
|
fn bad_inferred_reference_2() {
|
||||||
check_no_mismatches(
|
check_no_mismatches(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
trait ExactSizeIterator {
|
trait ExactSizeIterator {
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
@ -2054,7 +2054,7 @@ fn foo() {
|
||||||
fn box_deref_is_builtin() {
|
fn box_deref_is_builtin() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
|
||||||
#[lang = "owned_box"]
|
#[lang = "owned_box"]
|
||||||
|
|
@ -2087,7 +2087,7 @@ fn test() {
|
||||||
fn manually_drop_deref_is_not_builtin() {
|
fn manually_drop_deref_is_not_builtin() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: manually_drop, deref
|
//- minicore: manually_drop, receiver
|
||||||
struct Foo;
|
struct Foo;
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn foo(&self) {}
|
fn foo(&self) {}
|
||||||
|
|
@ -2105,7 +2105,7 @@ fn test() {
|
||||||
fn mismatched_args_due_to_supertraits_with_deref() {
|
fn mismatched_args_due_to_supertraits_with_deref() {
|
||||||
check_no_mismatches(
|
check_no_mismatches(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: deref
|
//- minicore: receiver
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
|
||||||
trait Trait1 {
|
trait Trait1 {
|
||||||
|
|
@ -2139,3 +2139,34 @@ fn problem_method<T: Trait3>() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn receiver_without_deref_impl() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: receiver
|
||||||
|
use core::ops::Receiver;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo1(self: &Bar) -> i32 { 42 }
|
||||||
|
fn foo2(self: Bar) -> bool { true }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
impl Receiver for Bar {
|
||||||
|
type Target = Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bar = Bar;
|
||||||
|
let _v1 = bar.foo1();
|
||||||
|
//^^^ type: i32
|
||||||
|
let _v2 = bar.foo2();
|
||||||
|
//^^^ type: bool
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1475,4 +1475,34 @@ async fn bar() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn receiver_without_deref_impl_completion() {
|
||||||
|
check_no_kw(
|
||||||
|
r#"
|
||||||
|
//- minicore: receiver
|
||||||
|
use core::ops::Receiver;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self: Bar) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
impl Receiver for Bar {
|
||||||
|
type Target = Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bar = Bar;
|
||||||
|
bar.$0
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
me foo() fn(self: Bar)
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -394,6 +394,7 @@ define_symbols! {
|
||||||
RangeToInclusive,
|
RangeToInclusive,
|
||||||
Ready,
|
Ready,
|
||||||
receiver,
|
receiver,
|
||||||
|
receiver_target,
|
||||||
recursion_limit,
|
recursion_limit,
|
||||||
register_attr,
|
register_attr,
|
||||||
register_tool,
|
register_tool,
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
//! pin:
|
//! pin:
|
||||||
//! pointee: copy, send, sync, ord, hash, unpin
|
//! pointee: copy, send, sync, ord, hash, unpin
|
||||||
//! range:
|
//! range:
|
||||||
|
//! receiver: deref
|
||||||
//! result:
|
//! result:
|
||||||
//! send: sized
|
//! send: sized
|
||||||
//! size_of: sized
|
//! size_of: sized
|
||||||
|
|
@ -513,10 +514,26 @@ pub mod ops {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target;
|
fn deref_mut(&mut self) -> &mut Self::Target;
|
||||||
}
|
}
|
||||||
// endregion:deref_mut
|
// endregion:deref_mut
|
||||||
|
|
||||||
|
// region:receiver
|
||||||
|
#[lang = "receiver"]
|
||||||
|
pub trait Receiver {
|
||||||
|
#[lang = "receiver_target"]
|
||||||
|
type Target: ?Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: ?Sized, T: ?Sized> Receiver for P
|
||||||
|
where
|
||||||
|
P: Deref<Target = T>,
|
||||||
|
{
|
||||||
|
type Target = T;
|
||||||
|
}
|
||||||
|
// endregion:receiver
|
||||||
}
|
}
|
||||||
pub use self::deref::{
|
pub use self::deref::{
|
||||||
Deref,
|
Deref,
|
||||||
DerefMut, // :deref_mut
|
DerefMut, // :deref_mut
|
||||||
|
Receiver, // :receiver
|
||||||
};
|
};
|
||||||
// endregion:deref
|
// endregion:deref
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue