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
@ -6,7 +6,10 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
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 limit::Limit;
|
||||
|
||||
@ -76,7 +79,7 @@ pub(crate) fn autoderef_step(
|
||||
table: &mut InferenceTable<'_>,
|
||||
ty: 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)))
|
||||
} else {
|
||||
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
|
||||
@ -99,26 +102,41 @@ pub fn autoderef(
|
||||
v.into_iter()
|
||||
}
|
||||
|
||||
pub(crate) fn deref(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
|
||||
let _p = profile::span("deref");
|
||||
autoderef_step(table, ty).map(|(_, ty)| ty)
|
||||
}
|
||||
|
||||
fn builtin_deref(ty: &Ty) -> Option<&Ty> {
|
||||
pub(crate) fn builtin_deref<'ty>(
|
||||
table: &mut InferenceTable<'_>,
|
||||
ty: &'ty Ty,
|
||||
explicit: bool,
|
||||
) -> Option<&'ty Ty> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
||||
// don't try to deref unknown variables
|
||||
return None;
|
||||
}
|
||||
|
||||
let db = table.db;
|
||||
let deref_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])?;
|
||||
|
@ -86,7 +86,7 @@ fn offset() {
|
||||
];
|
||||
let ar: *const [(u8, u8, u8)] = ar;
|
||||
let ar = ar as *const (u8, u8, u8);
|
||||
let element = offset(ar, 2);
|
||||
let element = *offset(ar, 2);
|
||||
element.1
|
||||
};
|
||||
"#,
|
||||
@ -113,7 +113,7 @@ fn arith_offset() {
|
||||
];
|
||||
let ar: *const [(u8, u8, u8)] = ar;
|
||||
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
|
||||
};
|
||||
"#,
|
||||
|
@ -661,11 +661,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
// FIXME: Note down method resolution her
|
||||
match op {
|
||||
UnaryOp::Deref => {
|
||||
if let Some(deref_trait) = self
|
||||
.db
|
||||
.lang_item(self.table.trait_env.krate, LangItem::Deref)
|
||||
.and_then(|l| l.as_trait())
|
||||
{
|
||||
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
||||
if let Some(deref_fn) =
|
||||
self.db.trait_data(deref_trait).method_by_name(&name![deref])
|
||||
{
|
||||
@ -678,7 +674,14 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
);
|
||||
}
|
||||
}
|
||||
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 => {
|
||||
match inner_ty.kind(Interner) {
|
||||
|
@ -854,9 +854,9 @@ fn test2(a1: *const A, a2: *mut A) {
|
||||
237..239 'a2': *mut A
|
||||
249..272 '{ ...2.b; }': ()
|
||||
255..257 'a1': *const A
|
||||
255..259 'a1.b': B
|
||||
255..259 'a1.b': {unknown}
|
||||
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;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.inner
|
||||
unsafe { &*self.inner }
|
||||
}
|
||||
}
|
||||
|
||||
@ -3062,23 +3062,25 @@ fn foo() {
|
||||
}"#,
|
||||
expect![[r#"
|
||||
154..158 'self': &Box<T>
|
||||
166..193 '{ ... }': &T
|
||||
176..187 '&self.inner': &*mut T
|
||||
177..181 'self': &Box<T>
|
||||
177..187 'self.inner': *mut T
|
||||
206..296 '{ ...&s); }': ()
|
||||
216..217 's': Option<i32>
|
||||
220..224 'None': Option<i32>
|
||||
234..235 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
269..282 'box (|ps| {})': Box<|&Option<i32>| -> ()>
|
||||
274..281 '|ps| {}': |&Option<i32>| -> ()
|
||||
275..277 'ps': &Option<i32>
|
||||
279..281 '{}': ()
|
||||
288..289 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
288..293 'f(&s)': ()
|
||||
290..292 '&s': &Option<i32>
|
||||
291..292 's': Option<i32>
|
||||
269..282: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|&Option<i32>| -> ()>
|
||||
166..205 '{ ... }': &T
|
||||
176..199 'unsafe...nner }': &T
|
||||
185..197 '&*self.inner': &T
|
||||
186..197 '*self.inner': T
|
||||
187..191 'self': &Box<T>
|
||||
187..197 'self.inner': *mut T
|
||||
218..308 '{ ...&s); }': ()
|
||||
228..229 's': Option<i32>
|
||||
232..236 'None': Option<i32>
|
||||
246..247 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
281..294 'box (|ps| {})': Box<|&Option<i32>| -> ()>
|
||||
286..293 '|ps| {}': |&Option<i32>| -> ()
|
||||
287..289 'ps': &Option<i32>
|
||||
291..293 '{}': ()
|
||||
300..301 'f': Box<dyn FnOnce(&Option<i32>)>
|
||||
300..305 'f(&s)': ()
|
||||
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 New Issue
Block a user