Skip to content

Commit 3a163fa

Browse files
authored
Merge pull request #19012 from ShoyuVanilla/arbitrary-self
feat: Implement `arbitrary-self-types`
2 parents 0f6feb0 + f4dfbc3 commit 3a163fa

File tree

9 files changed

+129
-26
lines changed

9 files changed

+129
-26
lines changed

crates/hir-def/src/lang_item.rs

+1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ language_item_table! {
372372
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
373373
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
374374
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
375+
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
375376

376377
Fn, sym::fn_, fn_trait, Target::Trait, GenericRequirement::Exact(1);
377378
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);

crates/hir-ty/src/autoderef.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn autoderef(
3939
) -> impl Iterator<Item = Ty> {
4040
let mut table = InferenceTable::new(db, env);
4141
let ty = table.instantiate_canonical(ty);
42-
let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false);
42+
let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false, false);
4343
let mut v = Vec::new();
4444
while let Some((ty, _steps)) = autoderef.next() {
4545
// `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)>> {
8989
at_start: bool,
9090
steps: T,
9191
explicit: bool,
92+
use_receiver_trait: bool,
9293
}
9394

9495
impl<'table, 'db> Autoderef<'table, 'db> {
95-
pub(crate) fn new(table: &'table mut InferenceTable<'db>, ty: Ty, explicit: bool) -> Self {
96+
pub(crate) fn new(
97+
table: &'table mut InferenceTable<'db>,
98+
ty: Ty,
99+
explicit: bool,
100+
use_receiver_trait: bool,
101+
) -> Self {
96102
let ty = table.resolve_ty_shallow(&ty);
97-
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit }
103+
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait }
98104
}
99105

100106
pub(crate) fn steps(&self) -> &[(AutoderefKind, Ty)] {
@@ -107,9 +113,10 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
107113
table: &'table mut InferenceTable<'db>,
108114
ty: Ty,
109115
explicit: bool,
116+
use_receiver_trait: bool,
110117
) -> Self {
111118
let ty = table.resolve_ty_shallow(&ty);
112-
Autoderef { table, ty, at_start: true, steps: 0, explicit }
119+
Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait }
113120
}
114121
}
115122

@@ -137,7 +144,8 @@ impl<T: TrackAutoderefSteps> Iterator for Autoderef<'_, '_, T> {
137144
return None;
138145
}
139146

140-
let (kind, new_ty) = autoderef_step(self.table, self.ty.clone(), self.explicit)?;
147+
let (kind, new_ty) =
148+
autoderef_step(self.table, self.ty.clone(), self.explicit, self.use_receiver_trait)?;
141149

142150
self.steps.push(kind, &self.ty);
143151
self.ty = new_ty;
@@ -150,11 +158,12 @@ pub(crate) fn autoderef_step(
150158
table: &mut InferenceTable<'_>,
151159
ty: Ty,
152160
explicit: bool,
161+
use_receiver_trait: bool,
153162
) -> Option<(AutoderefKind, Ty)> {
154163
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
155164
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
156165
} else {
157-
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
166+
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?))
158167
}
159168
}
160169

@@ -176,21 +185,33 @@ pub(crate) fn builtin_deref<'ty>(
176185
pub(crate) fn deref_by_trait(
177186
table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
178187
ty: Ty,
188+
use_receiver_trait: bool,
179189
) -> Option<Ty> {
180190
let _p = tracing::info_span!("deref_by_trait").entered();
181191
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
182192
// don't try to deref unknown variables
183193
return None;
184194
}
185195

186-
let deref_trait =
187-
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
196+
let trait_id = || {
197+
if use_receiver_trait {
198+
if let Some(receiver) =
199+
db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
200+
{
201+
return Some(receiver);
202+
}
203+
}
204+
// Old rustc versions might not have `Receiver` trait.
205+
// Fallback to `Deref` if they don't
206+
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
207+
};
208+
let trait_id = trait_id()?;
188209
let target = db
189-
.trait_data(deref_trait)
210+
.trait_data(trait_id)
190211
.associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?;
191212

192213
let projection = {
193-
let b = TyBuilder::subst_for_def(db, deref_trait, None);
214+
let b = TyBuilder::subst_for_def(db, trait_id, None);
194215
if b.remaining() != 1 {
195216
// the Target type + Deref trait should only have one generic parameter,
196217
// namely Deref's Self type

crates/hir-ty/src/infer/coerce.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ impl InferenceTable<'_> {
420420

421421
let snapshot = self.snapshot();
422422

423-
let mut autoderef = Autoderef::new(self, from_ty.clone(), false);
423+
let mut autoderef = Autoderef::new(self, from_ty.clone(), false, false);
424424
let mut first_error = None;
425425
let mut found = None;
426426

crates/hir-ty/src/infer/expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ impl InferenceContext<'_> {
487487
}
488488
Expr::Call { callee, args, .. } => {
489489
let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes);
490-
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
490+
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false, true);
491491
let (res, derefed_callee) = loop {
492492
let Some((callee_deref_ty, _)) = derefs.next() else {
493493
break (None, callee_ty.clone());
@@ -854,7 +854,7 @@ impl InferenceContext<'_> {
854854
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
855855
self.resolve_ty_shallow(derefed)
856856
} else {
857-
deref_by_trait(&mut self.table, inner_ty)
857+
deref_by_trait(&mut self.table, inner_ty, false)
858858
.unwrap_or_else(|| self.err_ty())
859859
}
860860
}
@@ -1718,7 +1718,7 @@ impl InferenceContext<'_> {
17181718
receiver_ty: &Ty,
17191719
name: &Name,
17201720
) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> {
1721-
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false);
1721+
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false, false);
17221722
let mut private_field = None;
17231723
let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
17241724
let (field_id, parameters) = match derefed_ty.kind(Interner) {

crates/hir-ty/src/method_resolution.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ impl ReceiverAdjustments {
528528
let mut ty = table.resolve_ty_shallow(&ty);
529529
let mut adjust = Vec::new();
530530
for _ in 0..self.autoderefs {
531-
match autoderef::autoderef_step(table, ty.clone(), true) {
531+
match autoderef::autoderef_step(table, ty.clone(), true, false) {
532532
None => {
533533
never!("autoderef not possible for {:?}", ty);
534534
ty = TyKind::Error.intern(Interner);
@@ -1106,7 +1106,8 @@ fn iterate_method_candidates_by_receiver(
11061106
// be found in any of the derefs of receiver_ty, so we have to go through
11071107
// that, including raw derefs.
11081108
table.run_in_snapshot(|table| {
1109-
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
1109+
let mut autoderef =
1110+
autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
11101111
while let Some((self_ty, _)) = autoderef.next() {
11111112
iterate_inherent_methods(
11121113
&self_ty,
@@ -1123,7 +1124,8 @@ fn iterate_method_candidates_by_receiver(
11231124
ControlFlow::Continue(())
11241125
})?;
11251126
table.run_in_snapshot(|table| {
1126-
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
1127+
let mut autoderef =
1128+
autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
11271129
while let Some((self_ty, _)) = autoderef.next() {
11281130
if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
11291131
// don't try to resolve methods on unknown types
@@ -1709,7 +1711,7 @@ fn autoderef_method_receiver(
17091711
ty: Ty,
17101712
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
17111713
let mut deref_chain: Vec<_> = Vec::new();
1712-
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false);
1714+
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false, true);
17131715
while let Some((ty, derefs)) = autoderef.next() {
17141716
deref_chain.push((
17151717
autoderef.table.canonicalize(ty),

crates/hir-ty/src/tests/method_resolution.rs

+39-8
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,7 @@ fn foo<T: Trait>(a: &T) {
13431343
fn autoderef_visibility_field() {
13441344
check(
13451345
r#"
1346-
//- minicore: deref
1346+
//- minicore: receiver
13471347
mod a {
13481348
pub struct Foo(pub char);
13491349
pub struct Bar(i32);
@@ -1375,7 +1375,7 @@ fn autoderef_visibility_method() {
13751375
cov_mark::check!(autoderef_candidate_not_visible);
13761376
check(
13771377
r#"
1378-
//- minicore: deref
1378+
//- minicore: receiver
13791379
mod a {
13801380
pub struct Foo(pub char);
13811381
impl Foo {
@@ -1741,7 +1741,7 @@ fn main() {
17411741
fn deref_fun_1() {
17421742
check_types(
17431743
r#"
1744-
//- minicore: deref
1744+
//- minicore: receiver
17451745
17461746
struct A<T, U>(T, U);
17471747
struct B<T>(T);
@@ -1782,7 +1782,7 @@ fn test() {
17821782
fn deref_fun_2() {
17831783
check_types(
17841784
r#"
1785-
//- minicore: deref
1785+
//- minicore: receiver
17861786
17871787
struct A<T, U>(T, U);
17881788
struct B<T>(T);
@@ -1903,7 +1903,7 @@ pub fn test(generic_args: impl Into<Foo>) {
19031903
fn bad_inferred_reference_2() {
19041904
check_no_mismatches(
19051905
r#"
1906-
//- minicore: deref
1906+
//- minicore: receiver
19071907
trait ExactSizeIterator {
19081908
fn len(&self) -> usize;
19091909
}
@@ -2054,7 +2054,7 @@ fn foo() {
20542054
fn box_deref_is_builtin() {
20552055
check(
20562056
r#"
2057-
//- minicore: deref
2057+
//- minicore: receiver
20582058
use core::ops::Deref;
20592059
20602060
#[lang = "owned_box"]
@@ -2087,7 +2087,7 @@ fn test() {
20872087
fn manually_drop_deref_is_not_builtin() {
20882088
check(
20892089
r#"
2090-
//- minicore: manually_drop, deref
2090+
//- minicore: manually_drop, receiver
20912091
struct Foo;
20922092
impl Foo {
20932093
fn foo(&self) {}
@@ -2105,7 +2105,7 @@ fn test() {
21052105
fn mismatched_args_due_to_supertraits_with_deref() {
21062106
check_no_mismatches(
21072107
r#"
2108-
//- minicore: deref
2108+
//- minicore: receiver
21092109
use core::ops::Deref;
21102110
21112111
trait Trait1 {
@@ -2139,3 +2139,34 @@ fn problem_method<T: Trait3>() {
21392139
"#,
21402140
);
21412141
}
2142+
2143+
#[test]
2144+
fn receiver_without_deref_impl() {
2145+
check(
2146+
r#"
2147+
//- minicore: receiver
2148+
use core::ops::Receiver;
2149+
2150+
struct Foo;
2151+
2152+
impl Foo {
2153+
fn foo1(self: &Bar) -> i32 { 42 }
2154+
fn foo2(self: Bar) -> bool { true }
2155+
}
2156+
2157+
struct Bar;
2158+
2159+
impl Receiver for Bar {
2160+
type Target = Foo;
2161+
}
2162+
2163+
fn main() {
2164+
let bar = Bar;
2165+
let _v1 = bar.foo1();
2166+
//^^^ type: i32
2167+
let _v2 = bar.foo2();
2168+
//^^^ type: bool
2169+
}
2170+
"#,
2171+
);
2172+
}

crates/ide-completion/src/completions/dot.rs

+30
Original file line numberDiff line numberDiff line change
@@ -1475,4 +1475,34 @@ async fn bar() {
14751475
"#,
14761476
);
14771477
}
1478+
1479+
#[test]
1480+
fn receiver_without_deref_impl_completion() {
1481+
check_no_kw(
1482+
r#"
1483+
//- minicore: receiver
1484+
use core::ops::Receiver;
1485+
1486+
struct Foo;
1487+
1488+
impl Foo {
1489+
fn foo(self: Bar) {}
1490+
}
1491+
1492+
struct Bar;
1493+
1494+
impl Receiver for Bar {
1495+
type Target = Foo;
1496+
}
1497+
1498+
fn main() {
1499+
let bar = Bar;
1500+
bar.$0
1501+
}
1502+
"#,
1503+
expect![[r#"
1504+
me foo() fn(self: Bar)
1505+
"#]],
1506+
);
1507+
}
14781508
}

crates/intern/src/symbol/symbols.rs

+1
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ define_symbols! {
394394
RangeToInclusive,
395395
Ready,
396396
receiver,
397+
receiver_target,
397398
recursion_limit,
398399
register_attr,
399400
register_tool,

crates/test-utils/src/minicore.rs

+17
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
//! pin:
5454
//! pointee: copy, send, sync, ord, hash, unpin
5555
//! range:
56+
//! receiver: deref
5657
//! result:
5758
//! send: sized
5859
//! size_of: sized
@@ -513,10 +514,26 @@ pub mod ops {
513514
fn deref_mut(&mut self) -> &mut Self::Target;
514515
}
515516
// endregion:deref_mut
517+
518+
// region:receiver
519+
#[lang = "receiver"]
520+
pub trait Receiver {
521+
#[lang = "receiver_target"]
522+
type Target: ?Sized;
523+
}
524+
525+
impl<P: ?Sized, T: ?Sized> Receiver for P
526+
where
527+
P: Deref<Target = T>,
528+
{
529+
type Target = T;
530+
}
531+
// endregion:receiver
516532
}
517533
pub use self::deref::{
518534
Deref,
519535
DerefMut, // :deref_mut
536+
Receiver, // :receiver
520537
};
521538
// endregion:deref
522539

0 commit comments

Comments
 (0)