mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-31 23:38:45 +00:00
Auto merge of #14440 - Veykril:deref-fix, r=Veykril
fix: Handle box and raw pointers correctly in builtin_deref
This commit is contained in:
commit
17e31b7d3b
5 changed files with 62 additions and 39 deletions
|
@ -6,7 +6,10 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use chalk_ir::cast::Cast;
|
use chalk_ir::cast::Cast;
|
||||||
use hir_def::lang_item::LangItem;
|
use hir_def::{
|
||||||
|
lang_item::{LangItem, LangItemTarget},
|
||||||
|
AdtId,
|
||||||
|
};
|
||||||
use hir_expand::name::name;
|
use hir_expand::name::name;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
|
|
||||||
|
@ -76,7 +79,7 @@ pub(crate) fn autoderef_step(
|
||||||
table: &mut InferenceTable<'_>,
|
table: &mut InferenceTable<'_>,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
) -> Option<(AutoderefKind, Ty)> {
|
) -> Option<(AutoderefKind, Ty)> {
|
||||||
if let Some(derefed) = builtin_deref(&ty) {
|
if let Some(derefed) = builtin_deref(table, &ty, false) {
|
||||||
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)?))
|
||||||
|
@ -99,26 +102,41 @@ pub fn autoderef(
|
||||||
v.into_iter()
|
v.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deref(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
|
pub(crate) fn builtin_deref<'ty>(
|
||||||
let _p = profile::span("deref");
|
table: &mut InferenceTable<'_>,
|
||||||
autoderef_step(table, ty).map(|(_, ty)| ty)
|
ty: &'ty Ty,
|
||||||
}
|
explicit: bool,
|
||||||
|
) -> Option<&'ty Ty> {
|
||||||
fn builtin_deref(ty: &Ty) -> Option<&Ty> {
|
|
||||||
match ty.kind(Interner) {
|
match ty.kind(Interner) {
|
||||||
TyKind::Ref(.., ty) | TyKind::Raw(.., ty) => Some(ty),
|
TyKind::Ref(.., ty) => Some(ty),
|
||||||
|
// FIXME: Maybe accept this but diagnose if its not explicit?
|
||||||
|
TyKind::Raw(.., ty) if explicit => Some(ty),
|
||||||
|
&TyKind::Adt(chalk_ir::AdtId(AdtId::StructId(strukt)), ref substs) => {
|
||||||
|
if Some(strukt)
|
||||||
|
== table
|
||||||
|
.db
|
||||||
|
.lang_item(table.trait_env.krate, LangItem::OwnedBox)
|
||||||
|
.and_then(LangItemTarget::as_struct)
|
||||||
|
{
|
||||||
|
substs.at(Interner, 0).ty(Interner)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deref_by_trait(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
|
pub(crate) fn deref_by_trait(
|
||||||
|
table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
|
||||||
|
ty: Ty,
|
||||||
|
) -> Option<Ty> {
|
||||||
let _p = profile::span("deref_by_trait");
|
let _p = profile::span("deref_by_trait");
|
||||||
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
||||||
// don't try to deref unknown variables
|
// don't try to deref unknown variables
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = table.db;
|
|
||||||
let deref_trait =
|
let deref_trait =
|
||||||
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
|
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
|
||||||
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
|
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn offset() {
|
||||||
];
|
];
|
||||||
let ar: *const [(u8, u8, u8)] = ar;
|
let ar: *const [(u8, u8, u8)] = ar;
|
||||||
let ar = ar as *const (u8, u8, u8);
|
let ar = ar as *const (u8, u8, u8);
|
||||||
let element = offset(ar, 2);
|
let element = *offset(ar, 2);
|
||||||
element.1
|
element.1
|
||||||
};
|
};
|
||||||
"#,
|
"#,
|
||||||
|
@ -113,7 +113,7 @@ fn arith_offset() {
|
||||||
];
|
];
|
||||||
let ar: *const [(u8, u8, u8)] = ar;
|
let ar: *const [(u8, u8, u8)] = ar;
|
||||||
let ar = ar as *const (u8, u8, u8);
|
let ar = ar as *const (u8, u8, u8);
|
||||||
let element = arith_offset(arith_offset(ar, 102), -100);
|
let element = *arith_offset(arith_offset(ar, 102), -100);
|
||||||
element.1
|
element.1
|
||||||
};
|
};
|
||||||
"#,
|
"#,
|
||||||
|
|
|
@ -661,11 +661,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
// FIXME: Note down method resolution her
|
// FIXME: Note down method resolution her
|
||||||
match op {
|
match op {
|
||||||
UnaryOp::Deref => {
|
UnaryOp::Deref => {
|
||||||
if let Some(deref_trait) = self
|
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
||||||
.db
|
|
||||||
.lang_item(self.table.trait_env.krate, LangItem::Deref)
|
|
||||||
.and_then(|l| l.as_trait())
|
|
||||||
{
|
|
||||||
if let Some(deref_fn) =
|
if let Some(deref_fn) =
|
||||||
self.db.trait_data(deref_trait).method_by_name(&name![deref])
|
self.db.trait_data(deref_trait).method_by_name(&name![deref])
|
||||||
{
|
{
|
||||||
|
@ -678,7 +674,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
autoderef::deref(&mut self.table, inner_ty).unwrap_or_else(|| self.err_ty())
|
if let Some(derefed) =
|
||||||
|
autoderef::builtin_deref(&mut self.table, &inner_ty, true)
|
||||||
|
{
|
||||||
|
self.resolve_ty_shallow(derefed)
|
||||||
|
} else {
|
||||||
|
autoderef::deref_by_trait(&mut self.table, inner_ty)
|
||||||
|
.unwrap_or_else(|| self.err_ty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UnaryOp::Neg => {
|
UnaryOp::Neg => {
|
||||||
match inner_ty.kind(Interner) {
|
match inner_ty.kind(Interner) {
|
||||||
|
|
|
@ -854,9 +854,9 @@ fn test2(a1: *const A, a2: *mut A) {
|
||||||
237..239 'a2': *mut A
|
237..239 'a2': *mut A
|
||||||
249..272 '{ ...2.b; }': ()
|
249..272 '{ ...2.b; }': ()
|
||||||
255..257 'a1': *const A
|
255..257 'a1': *const A
|
||||||
255..259 'a1.b': B
|
255..259 'a1.b': {unknown}
|
||||||
265..267 'a2': *mut A
|
265..267 'a2': *mut A
|
||||||
265..269 'a2.b': B
|
265..269 'a2.b': {unknown}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3051,7 +3051,7 @@ impl<T: ?Sized> core::ops::Deref for Box<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
&self.inner
|
unsafe { &*self.inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3062,23 +3062,25 @@ fn foo() {
|
||||||
}"#,
|
}"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
154..158 'self': &Box<T>
|
154..158 'self': &Box<T>
|
||||||
166..193 '{ ... }': &T
|
166..205 '{ ... }': &T
|
||||||
176..187 '&self.inner': &*mut T
|
176..199 'unsafe...nner }': &T
|
||||||
177..181 'self': &Box<T>
|
185..197 '&*self.inner': &T
|
||||||
177..187 'self.inner': *mut T
|
186..197 '*self.inner': T
|
||||||
206..296 '{ ...&s); }': ()
|
187..191 'self': &Box<T>
|
||||||
216..217 's': Option<i32>
|
187..197 'self.inner': *mut T
|
||||||
220..224 'None': Option<i32>
|
218..308 '{ ...&s); }': ()
|
||||||
234..235 'f': Box<dyn FnOnce(&Option<i32>)>
|
228..229 's': Option<i32>
|
||||||
269..282 'box (|ps| {})': Box<|&Option<i32>| -> ()>
|
232..236 'None': Option<i32>
|
||||||
274..281 '|ps| {}': |&Option<i32>| -> ()
|
246..247 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||||
275..277 'ps': &Option<i32>
|
281..294 'box (|ps| {})': Box<|&Option<i32>| -> ()>
|
||||||
279..281 '{}': ()
|
286..293 '|ps| {}': |&Option<i32>| -> ()
|
||||||
288..289 'f': Box<dyn FnOnce(&Option<i32>)>
|
287..289 'ps': &Option<i32>
|
||||||
288..293 'f(&s)': ()
|
291..293 '{}': ()
|
||||||
290..292 '&s': &Option<i32>
|
300..301 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||||
291..292 's': Option<i32>
|
300..305 'f(&s)': ()
|
||||||
269..282: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|&Option<i32>| -> ()>
|
302..304 '&s': &Option<i32>
|
||||||
|
303..304 's': Option<i32>
|
||||||
|
281..294: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|&Option<i32>| -> ()>
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue