Skip to content

Commit 6f9c62d

Browse files
authored
Merge pull request #19733 from ShoyuVanilla/issue-19724
fix: Implement mut to const ptr cast for method resolution
2 parents 3bf5d7f + 4aa98bf commit 6f9c62d

File tree

2 files changed

+82
-13
lines changed

2 files changed

+82
-13
lines changed

crates/hir-ty/src/method_resolution.rs

+59-13
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,15 @@ impl From<Option<BlockId>> for VisibleFromModule {
515515
}
516516
}
517517

518+
#[derive(Debug, Clone)]
519+
pub enum AutorefOrPtrAdjustment {
520+
Autoref(Mutability),
521+
ToConstPtr,
522+
}
523+
518524
#[derive(Debug, Clone, Default)]
519525
pub struct ReceiverAdjustments {
520-
autoref: Option<Mutability>,
526+
autoref: Option<AutorefOrPtrAdjustment>,
521527
autoderefs: usize,
522528
unsize_array: bool,
523529
}
@@ -535,22 +541,43 @@ impl ReceiverAdjustments {
535541
}
536542
Some((kind, new_ty)) => {
537543
ty = new_ty.clone();
544+
let mutbl = match self.autoref {
545+
Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
546+
Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
547+
// FIXME should we know the mutability here, when autoref is `None`?
548+
None => None,
549+
};
538550
adjust.push(Adjustment {
539551
kind: Adjust::Deref(match kind {
540-
// FIXME should we know the mutability here, when autoref is `None`?
541-
AutoderefKind::Overloaded => Some(OverloadedDeref(self.autoref)),
552+
AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
542553
AutoderefKind::Builtin => None,
543554
}),
544555
target: new_ty,
545556
});
546557
}
547558
}
548559
}
549-
if let Some(m) = self.autoref {
560+
if let Some(autoref) = &self.autoref {
550561
let lt = table.new_lifetime_var();
551-
let a = Adjustment::borrow(m, ty, lt);
552-
ty = a.target.clone();
553-
adjust.push(a);
562+
match autoref {
563+
AutorefOrPtrAdjustment::Autoref(m) => {
564+
let a = Adjustment::borrow(*m, ty, lt);
565+
ty = a.target.clone();
566+
adjust.push(a);
567+
}
568+
AutorefOrPtrAdjustment::ToConstPtr => {
569+
if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) {
570+
let a = Adjustment {
571+
kind: Adjust::Pointer(PointerCast::MutToConstPointer),
572+
target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner),
573+
};
574+
ty = a.target.clone();
575+
adjust.push(a);
576+
} else {
577+
never!("`ToConstPtr` target is not a raw mutable pointer");
578+
}
579+
}
580+
};
554581
}
555582
if self.unsize_array {
556583
ty = 'it: {
@@ -575,8 +602,8 @@ impl ReceiverAdjustments {
575602
(ty, adjust)
576603
}
577604

578-
fn with_autoref(&self, m: Mutability) -> ReceiverAdjustments {
579-
Self { autoref: Some(m), ..*self }
605+
fn with_autoref(&self, a: AutorefOrPtrAdjustment) -> ReceiverAdjustments {
606+
Self { autoref: Some(a), ..*self }
580607
}
581608
}
582609

@@ -1051,7 +1078,7 @@ fn iterate_method_candidates_with_autoref(
10511078
let mut maybe_reborrowed = first_adjustment.clone();
10521079
if let Some((_, _, m)) = receiver_ty.value.as_reference() {
10531080
// Prefer reborrow of references to move
1054-
maybe_reborrowed.autoref = Some(m);
1081+
maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m));
10551082
maybe_reborrowed.autoderefs += 1;
10561083
}
10571084

@@ -1063,15 +1090,34 @@ fn iterate_method_candidates_with_autoref(
10631090
binders: receiver_ty.binders.clone(),
10641091
};
10651092

1066-
iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?;
1093+
iterate_method_candidates_by_receiver(
1094+
refed,
1095+
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
1096+
)?;
10671097

10681098
let ref_muted = Canonical {
10691099
value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone())
10701100
.intern(Interner),
1071-
binders: receiver_ty.binders,
1101+
binders: receiver_ty.binders.clone(),
10721102
};
10731103

1074-
iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
1104+
iterate_method_candidates_by_receiver(
1105+
ref_muted,
1106+
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
1107+
)?;
1108+
1109+
if let Some((ty, Mutability::Mut)) = receiver_ty.value.as_raw_ptr() {
1110+
let const_ptr_ty = Canonical {
1111+
value: TyKind::Raw(Mutability::Not, ty.clone()).intern(Interner),
1112+
binders: receiver_ty.binders,
1113+
};
1114+
iterate_method_candidates_by_receiver(
1115+
const_ptr_ty,
1116+
first_adjustment.with_autoref(AutorefOrPtrAdjustment::ToConstPtr),
1117+
)?;
1118+
}
1119+
1120+
ControlFlow::Continue(())
10751121
}
10761122

10771123
pub trait MethodCandidateCallback {

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

+23
Original file line numberDiff line numberDiff line change
@@ -2170,3 +2170,26 @@ fn main() {
21702170
"#,
21712171
);
21722172
}
2173+
2174+
#[test]
2175+
fn mut_to_const_pointer() {
2176+
check(
2177+
r#"
2178+
pub trait X {
2179+
fn perform(self) -> u64;
2180+
}
2181+
2182+
impl X for *const u8 {
2183+
fn perform(self) -> u64 {
2184+
42
2185+
}
2186+
}
2187+
2188+
fn test(x: *mut u8) {
2189+
let _v = x.perform();
2190+
// ^ adjustments: Pointer(MutToConstPointer)
2191+
// ^^^^^^^^^^^ type: u64
2192+
}
2193+
"#,
2194+
);
2195+
}

0 commit comments

Comments
 (0)