mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
fix: Implement mut to const ptr cast for method resolution
This commit is contained in:
parent
be7433328e
commit
4aa98bf1d7
@ -515,9 +515,15 @@ impl From<Option<BlockId>> for VisibleFromModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum AutorefOrPtrAdjustment {
|
||||||
|
Autoref(Mutability),
|
||||||
|
ToConstPtr,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ReceiverAdjustments {
|
pub struct ReceiverAdjustments {
|
||||||
autoref: Option<Mutability>,
|
autoref: Option<AutorefOrPtrAdjustment>,
|
||||||
autoderefs: usize,
|
autoderefs: usize,
|
||||||
unsize_array: bool,
|
unsize_array: bool,
|
||||||
}
|
}
|
||||||
@ -535,10 +541,15 @@ impl ReceiverAdjustments {
|
|||||||
}
|
}
|
||||||
Some((kind, new_ty)) => {
|
Some((kind, new_ty)) => {
|
||||||
ty = new_ty.clone();
|
ty = new_ty.clone();
|
||||||
|
let mutbl = match self.autoref {
|
||||||
|
Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
|
||||||
|
Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
|
||||||
|
// FIXME should we know the mutability here, when autoref is `None`?
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
adjust.push(Adjustment {
|
adjust.push(Adjustment {
|
||||||
kind: Adjust::Deref(match kind {
|
kind: Adjust::Deref(match kind {
|
||||||
// FIXME should we know the mutability here, when autoref is `None`?
|
AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
|
||||||
AutoderefKind::Overloaded => Some(OverloadedDeref(self.autoref)),
|
|
||||||
AutoderefKind::Builtin => None,
|
AutoderefKind::Builtin => None,
|
||||||
}),
|
}),
|
||||||
target: new_ty,
|
target: new_ty,
|
||||||
@ -546,11 +557,27 @@ impl ReceiverAdjustments {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(m) = self.autoref {
|
if let Some(autoref) = &self.autoref {
|
||||||
let lt = table.new_lifetime_var();
|
let lt = table.new_lifetime_var();
|
||||||
let a = Adjustment::borrow(m, ty, lt);
|
match autoref {
|
||||||
ty = a.target.clone();
|
AutorefOrPtrAdjustment::Autoref(m) => {
|
||||||
adjust.push(a);
|
let a = Adjustment::borrow(*m, ty, lt);
|
||||||
|
ty = a.target.clone();
|
||||||
|
adjust.push(a);
|
||||||
|
}
|
||||||
|
AutorefOrPtrAdjustment::ToConstPtr => {
|
||||||
|
if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) {
|
||||||
|
let a = Adjustment {
|
||||||
|
kind: Adjust::Pointer(PointerCast::MutToConstPointer),
|
||||||
|
target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner),
|
||||||
|
};
|
||||||
|
ty = a.target.clone();
|
||||||
|
adjust.push(a);
|
||||||
|
} else {
|
||||||
|
never!("`ToConstPtr` target is not a raw mutable pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if self.unsize_array {
|
if self.unsize_array {
|
||||||
ty = 'it: {
|
ty = 'it: {
|
||||||
@ -575,8 +602,8 @@ impl ReceiverAdjustments {
|
|||||||
(ty, adjust)
|
(ty, adjust)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_autoref(&self, m: Mutability) -> ReceiverAdjustments {
|
fn with_autoref(&self, a: AutorefOrPtrAdjustment) -> ReceiverAdjustments {
|
||||||
Self { autoref: Some(m), ..*self }
|
Self { autoref: Some(a), ..*self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,7 +1078,7 @@ fn iterate_method_candidates_with_autoref(
|
|||||||
let mut maybe_reborrowed = first_adjustment.clone();
|
let mut maybe_reborrowed = first_adjustment.clone();
|
||||||
if let Some((_, _, m)) = receiver_ty.value.as_reference() {
|
if let Some((_, _, m)) = receiver_ty.value.as_reference() {
|
||||||
// Prefer reborrow of references to move
|
// Prefer reborrow of references to move
|
||||||
maybe_reborrowed.autoref = Some(m);
|
maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m));
|
||||||
maybe_reborrowed.autoderefs += 1;
|
maybe_reborrowed.autoderefs += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,15 +1090,34 @@ fn iterate_method_candidates_with_autoref(
|
|||||||
binders: receiver_ty.binders.clone(),
|
binders: receiver_ty.binders.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?;
|
iterate_method_candidates_by_receiver(
|
||||||
|
refed,
|
||||||
|
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
|
||||||
|
)?;
|
||||||
|
|
||||||
let ref_muted = Canonical {
|
let ref_muted = Canonical {
|
||||||
value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone())
|
value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone())
|
||||||
.intern(Interner),
|
.intern(Interner),
|
||||||
binders: receiver_ty.binders,
|
binders: receiver_ty.binders.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
|
iterate_method_candidates_by_receiver(
|
||||||
|
ref_muted,
|
||||||
|
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if let Some((ty, Mutability::Mut)) = receiver_ty.value.as_raw_ptr() {
|
||||||
|
let const_ptr_ty = Canonical {
|
||||||
|
value: TyKind::Raw(Mutability::Not, ty.clone()).intern(Interner),
|
||||||
|
binders: receiver_ty.binders,
|
||||||
|
};
|
||||||
|
iterate_method_candidates_by_receiver(
|
||||||
|
const_ptr_ty,
|
||||||
|
first_adjustment.with_autoref(AutorefOrPtrAdjustment::ToConstPtr),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MethodCandidateCallback {
|
pub trait MethodCandidateCallback {
|
||||||
|
@ -2170,3 +2170,26 @@ fn main() {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_to_const_pointer() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
pub trait X {
|
||||||
|
fn perform(self) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl X for *const u8 {
|
||||||
|
fn perform(self) -> u64 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(x: *mut u8) {
|
||||||
|
let _v = x.perform();
|
||||||
|
// ^ adjustments: Pointer(MutToConstPointer)
|
||||||
|
// ^^^^^^^^^^^ type: u64
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user