Skip to content

Commit 5703346

Browse files
committed
Auto merge of rust-lang#15118 - alexkirsz:alexkirsz/resolve-deref-raw, r=Veykril
Follow raw pointers in autoderef chain when resolving methods with custom receiver Fixes rust-lang#15083 I believe this stopped working after alexkirsz/rust-analyzer@e797479
2 parents 691600a + 5991f0d commit 5703346

File tree

5 files changed

+61
-14
lines changed

5 files changed

+61
-14
lines changed

crates/hir-ty/src/autoderef.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn autoderef(
3636
) -> impl Iterator<Item = Ty> {
3737
let mut table = InferenceTable::new(db, env);
3838
let ty = table.instantiate_canonical(ty);
39-
let mut autoderef = Autoderef::new(&mut table, ty);
39+
let mut autoderef = Autoderef::new(&mut table, ty, false);
4040
let mut v = Vec::new();
4141
while let Some((ty, _steps)) = autoderef.next() {
4242
// `ty` may contain unresolved inference variables. Since there's no chance they would be
@@ -63,12 +63,13 @@ pub(crate) struct Autoderef<'a, 'db> {
6363
ty: Ty,
6464
at_start: bool,
6565
steps: Vec<(AutoderefKind, Ty)>,
66+
explicit: bool,
6667
}
6768

6869
impl<'a, 'db> Autoderef<'a, 'db> {
69-
pub(crate) fn new(table: &'a mut InferenceTable<'db>, ty: Ty) -> Self {
70+
pub(crate) fn new(table: &'a mut InferenceTable<'db>, ty: Ty, explicit: bool) -> Self {
7071
let ty = table.resolve_ty_shallow(&ty);
71-
Autoderef { table, ty, at_start: true, steps: Vec::new() }
72+
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit }
7273
}
7374

7475
pub(crate) fn step_count(&self) -> usize {
@@ -97,7 +98,7 @@ impl Iterator for Autoderef<'_, '_> {
9798
return None;
9899
}
99100

100-
let (kind, new_ty) = autoderef_step(self.table, self.ty.clone())?;
101+
let (kind, new_ty) = autoderef_step(self.table, self.ty.clone(), self.explicit)?;
101102

102103
self.steps.push((kind, self.ty.clone()));
103104
self.ty = new_ty;
@@ -109,8 +110,9 @@ impl Iterator for Autoderef<'_, '_> {
109110
pub(crate) fn autoderef_step(
110111
table: &mut InferenceTable<'_>,
111112
ty: Ty,
113+
explicit: bool,
112114
) -> Option<(AutoderefKind, Ty)> {
113-
if let Some(derefed) = builtin_deref(table, &ty, false) {
115+
if let Some(derefed) = builtin_deref(table, &ty, explicit) {
114116
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
115117
} else {
116118
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
@@ -124,7 +126,6 @@ pub(crate) fn builtin_deref<'ty>(
124126
) -> Option<&'ty Ty> {
125127
match ty.kind(Interner) {
126128
TyKind::Ref(.., ty) => Some(ty),
127-
// FIXME: Maybe accept this but diagnose if its not explicit?
128129
TyKind::Raw(.., ty) if explicit => Some(ty),
129130
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
130131
if crate::lang_items::is_box(table.db, adt) {

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

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

378378
let snapshot = self.snapshot();
379379

380-
let mut autoderef = Autoderef::new(self, from_ty.clone());
380+
let mut autoderef = Autoderef::new(self, from_ty.clone(), false);
381381
let mut first_error = None;
382382
let mut found = None;
383383

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl InferenceContext<'_> {
316316
}
317317
Expr::Call { callee, args, .. } => {
318318
let callee_ty = self.infer_expr(*callee, &Expectation::none());
319-
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
319+
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
320320
let (res, derefed_callee) = 'b: {
321321
// manual loop to be able to access `derefs.table`
322322
while let Some((callee_deref_ty, _)) = derefs.next() {
@@ -1385,7 +1385,7 @@ impl InferenceContext<'_> {
13851385
receiver_ty: &Ty,
13861386
name: &Name,
13871387
) -> Option<(Ty, Option<FieldId>, Vec<Adjustment>, bool)> {
1388-
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone());
1388+
let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false);
13891389
let mut private_field = None;
13901390
let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
13911391
let (field_id, parameters) = match derefed_ty.kind(Interner) {

crates/hir-ty/src/method_resolution.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ impl ReceiverAdjustments {
534534
let mut ty = table.resolve_ty_shallow(&ty);
535535
let mut adjust = Vec::new();
536536
for _ in 0..self.autoderefs {
537-
match autoderef::autoderef_step(table, ty.clone()) {
537+
match autoderef::autoderef_step(table, ty.clone(), true) {
538538
None => {
539539
never!("autoderef not possible for {:?}", ty);
540540
ty = TyKind::Error.intern(Interner);
@@ -1012,8 +1012,8 @@ fn iterate_method_candidates_by_receiver(
10121012
let snapshot = table.snapshot();
10131013
// We're looking for methods with *receiver* type receiver_ty. These could
10141014
// be found in any of the derefs of receiver_ty, so we have to go through
1015-
// that.
1016-
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone());
1015+
// that, including raw derefs.
1016+
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
10171017
while let Some((self_ty, _)) = autoderef.next() {
10181018
iterate_inherent_methods(
10191019
&self_ty,
@@ -1028,7 +1028,7 @@ fn iterate_method_candidates_by_receiver(
10281028

10291029
table.rollback_to(snapshot);
10301030

1031-
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone());
1031+
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
10321032
while let Some((self_ty, _)) = autoderef.next() {
10331033
iterate_trait_method_candidates(
10341034
&self_ty,
@@ -1504,7 +1504,7 @@ fn autoderef_method_receiver(
15041504
ty: Ty,
15051505
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
15061506
let mut deref_chain: Vec<_> = Vec::new();
1507-
let mut autoderef = autoderef::Autoderef::new(table, ty);
1507+
let mut autoderef = autoderef::Autoderef::new(table, ty, true);
15081508
while let Some((ty, derefs)) = autoderef.next() {
15091509
deref_chain.push((
15101510
autoderef.table.canonicalize(ty).value,

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

+46
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,52 @@ fn main() {
12151215
);
12161216
}
12171217

1218+
#[test]
1219+
fn inherent_method_deref_raw() {
1220+
check_types(
1221+
r#"
1222+
struct Val;
1223+
1224+
impl Val {
1225+
pub fn method(self: *const Val) -> u32 {
1226+
0
1227+
}
1228+
}
1229+
1230+
fn main() {
1231+
let foo: *const Val;
1232+
foo.method();
1233+
// ^^^^^^^^^^^^ u32
1234+
}
1235+
"#,
1236+
);
1237+
}
1238+
1239+
#[test]
1240+
fn trait_method_deref_raw() {
1241+
check_types(
1242+
r#"
1243+
trait Trait {
1244+
fn method(self: *const Self) -> u32;
1245+
}
1246+
1247+
struct Val;
1248+
1249+
impl Trait for Val {
1250+
fn method(self: *const Self) -> u32 {
1251+
0
1252+
}
1253+
}
1254+
1255+
fn main() {
1256+
let foo: *const Val;
1257+
foo.method();
1258+
// ^^^^^^^^^^^^ u32
1259+
}
1260+
"#,
1261+
);
1262+
}
1263+
12181264
#[test]
12191265
fn method_on_dyn_impl() {
12201266
check_types(

0 commit comments

Comments
 (0)