implement basic inferring of lifetimes

This commit is contained in:
dfireBird 2024-06-29 10:36:39 +05:30
parent 4cd8dcf287
commit 8a4261aca8
No known key found for this signature in database
GPG key ID: 26D522CA5FC2B93D
14 changed files with 109 additions and 85 deletions

View file

@ -55,7 +55,7 @@ use triomphe::Arc;
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
error_lifetime, fold_tys, fold_tys,
generics::Generics, generics::Generics,
infer::{coerce::CoerceMany, unify::InferenceTable}, infer::{coerce::CoerceMany, unify::InferenceTable},
lower::ImplTraitLoweringMode, lower::ImplTraitLoweringMode,
@ -327,13 +327,13 @@ pub struct Adjustment {
} }
impl Adjustment { impl Adjustment {
pub fn borrow(m: Mutability, ty: Ty) -> Self { pub fn borrow(m: Mutability, ty: Ty, lt: Lifetime) -> Self {
let ty = TyKind::Ref(m, error_lifetime(), ty).intern(Interner); let ty = TyKind::Ref(m, lt.clone(), ty).intern(Interner);
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty } Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(lt, m)), target: ty }
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Adjust { pub enum Adjust {
/// Go from ! to any type. /// Go from ! to any type.
NeverToAny, NeverToAny,
@ -353,18 +353,18 @@ pub enum Adjust {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct OverloadedDeref(pub Option<Mutability>); pub struct OverloadedDeref(pub Option<Mutability>);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum AutoBorrow { pub enum AutoBorrow {
/// Converts from T to &T. /// Converts from T to &T.
Ref(Mutability), Ref(Lifetime, Mutability),
/// Converts from T to *T. /// Converts from T to *T.
RawPtr(Mutability), RawPtr(Mutability),
} }
impl AutoBorrow { impl AutoBorrow {
fn mutability(self) -> Mutability { fn mutability(&self) -> Mutability {
let (AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m)) = self; let (AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) = self;
m *m
} }
} }

View file

@ -474,7 +474,7 @@ impl InferenceContext<'_> {
fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment]) { fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment]) {
if let Some((last, rest)) = adjustment.split_last() { if let Some((last, rest)) = adjustment.split_last() {
match last.kind { match &last.kind {
Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => { Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => {
self.walk_expr_with_adjust(tgt_expr, rest) self.walk_expr_with_adjust(tgt_expr, rest)
} }

View file

@ -18,14 +18,13 @@ use triomphe::Arc;
use crate::{ use crate::{
autoderef::{Autoderef, AutoderefKind}, autoderef::{Autoderef, AutoderefKind},
db::HirDatabase, db::HirDatabase,
error_lifetime,
infer::{ infer::{
Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast, Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast,
TypeError, TypeMismatch, TypeError, TypeMismatch,
}, },
utils::ClosureSubst, utils::ClosureSubst,
Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Lifetime,
Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
}; };
use super::unify::InferenceTable; use super::unify::InferenceTable;
@ -301,7 +300,7 @@ impl InferenceTable<'_> {
// Examine the supertype and consider auto-borrowing. // Examine the supertype and consider auto-borrowing.
match to_ty.kind(Interner) { match to_ty.kind(Interner) {
TyKind::Raw(mt, _) => return self.coerce_ptr(from_ty, to_ty, *mt), TyKind::Raw(mt, _) => return self.coerce_ptr(from_ty, to_ty, *mt),
TyKind::Ref(mt, _, _) => return self.coerce_ref(from_ty, to_ty, *mt), TyKind::Ref(mt, lt, _) => return self.coerce_ref(from_ty, to_ty, *mt, lt),
_ => {} _ => {}
} }
@ -377,11 +376,17 @@ impl InferenceTable<'_> {
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`. /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
/// To match `A` with `B`, autoderef will be performed, /// To match `A` with `B`, autoderef will be performed,
/// calling `deref`/`deref_mut` where necessary. /// calling `deref`/`deref_mut` where necessary.
fn coerce_ref(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult { fn coerce_ref(
let from_mt = match from_ty.kind(Interner) { &mut self,
&TyKind::Ref(mt, _, _) => { from_ty: Ty,
coerce_mutabilities(mt, to_mt)?; to_ty: &Ty,
mt to_mt: Mutability,
to_lt: &Lifetime,
) -> CoerceResult {
let (_from_lt, from_mt) = match from_ty.kind(Interner) {
TyKind::Ref(mt, lt, _) => {
coerce_mutabilities(*mt, to_mt)?;
(lt.clone(), *mt) // clone is probably not good?
} }
_ => return self.unify_and(&from_ty, to_ty, identity), _ => return self.unify_and(&from_ty, to_ty, identity),
}; };
@ -427,8 +432,8 @@ impl InferenceTable<'_> {
// compare those. Note that this means we use the target // compare those. Note that this means we use the target
// mutability [1], since it may be that we are coercing // mutability [1], since it may be that we are coercing
// from `&mut T` to `&U`. // from `&mut T` to `&U`.
let lt = error_lifetime(); // FIXME: handle lifetimes correctly, see rustc let lt = to_lt; // FIXME: Involve rustc LUB and SUB flag checks
let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner); let derefd_from_ty = TyKind::Ref(to_mt, lt.clone(), referent_ty).intern(Interner);
match autoderef.table.try_unify(&derefd_from_ty, to_ty) { match autoderef.table.try_unify(&derefd_from_ty, to_ty) {
Ok(result) => { Ok(result) => {
found = Some(result.map(|()| derefd_from_ty)); found = Some(result.map(|()| derefd_from_ty));
@ -472,8 +477,10 @@ impl InferenceTable<'_> {
} }
let mut adjustments = auto_deref_adjust_steps(&autoderef); let mut adjustments = auto_deref_adjust_steps(&autoderef);
adjustments adjustments.push(Adjustment {
.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(to_mt)), target: ty.clone() }); kind: Adjust::Borrow(AutoBorrow::Ref(to_lt.clone(), to_mt)),
target: ty.clone(),
});
success(adjustments, ty, goals) success(adjustments, ty, goals)
} }
@ -621,11 +628,11 @@ impl InferenceTable<'_> {
(TyKind::Ref(from_mt, _, from_inner), &TyKind::Ref(to_mt, _, _)) => { (TyKind::Ref(from_mt, _, from_inner), &TyKind::Ref(to_mt, _, _)) => {
coerce_mutabilities(*from_mt, to_mt)?; coerce_mutabilities(*from_mt, to_mt)?;
let lt = error_lifetime(); let lt = self.new_lifetime_var();
Some(( Some((
Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() }, Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
Adjustment { Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(to_mt)), kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), to_mt)),
target: TyKind::Ref(to_mt, lt, from_inner.clone()).intern(Interner), target: TyKind::Ref(to_mt, lt, from_inner.clone()).intern(Interner),
}, },
)) ))

View file

@ -635,7 +635,10 @@ impl InferenceContext<'_> {
let inner_ty = self.infer_expr_inner(*expr, &expectation); let inner_ty = self.infer_expr_inner(*expr, &expectation);
match rawness { match rawness {
Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
Rawness::Ref => TyKind::Ref(mutability, error_lifetime(), inner_ty), Rawness::Ref => {
let lt = self.table.new_lifetime_var();
TyKind::Ref(mutability, lt, inner_ty)
}
} }
.intern(Interner) .intern(Interner)
} }
@ -786,7 +789,11 @@ impl InferenceContext<'_> {
adj.apply(&mut self.table, base_ty) adj.apply(&mut self.table, base_ty)
}); });
// mutability will be fixed up in `InferenceContext::infer_mut`; // mutability will be fixed up in `InferenceContext::infer_mut`;
adj.push(Adjustment::borrow(Mutability::Not, self_ty.clone())); adj.push(Adjustment::borrow(
Mutability::Not,
self_ty.clone(),
self.table.new_lifetime_var(),
));
self.write_expr_adj(*base, adj); self.write_expr_adj(*base, adj);
if let Some(func) = self if let Some(func) = self
.db .db
@ -991,7 +998,7 @@ impl InferenceContext<'_> {
match fn_x { match fn_x {
FnTrait::FnOnce => (), FnTrait::FnOnce => (),
FnTrait::FnMut => { FnTrait::FnMut => {
if let TyKind::Ref(Mutability::Mut, _, inner) = derefed_callee.kind(Interner) { if let TyKind::Ref(Mutability::Mut, lt, inner) = derefed_callee.kind(Interner) {
if adjustments if adjustments
.last() .last()
.map(|it| matches!(it.kind, Adjust::Borrow(_))) .map(|it| matches!(it.kind, Adjust::Borrow(_)))
@ -1000,15 +1007,27 @@ impl InferenceContext<'_> {
// prefer reborrow to move // prefer reborrow to move
adjustments adjustments
.push(Adjustment { kind: Adjust::Deref(None), target: inner.clone() }); .push(Adjustment { kind: Adjust::Deref(None), target: inner.clone() });
adjustments.push(Adjustment::borrow(Mutability::Mut, inner.clone())) adjustments.push(Adjustment::borrow(
Mutability::Mut,
inner.clone(),
lt.clone(),
))
} }
} else { } else {
adjustments.push(Adjustment::borrow(Mutability::Mut, derefed_callee.clone())); adjustments.push(Adjustment::borrow(
Mutability::Mut,
derefed_callee.clone(),
self.table.new_lifetime_var(),
));
} }
} }
FnTrait::Fn => { FnTrait::Fn => {
if !matches!(derefed_callee.kind(Interner), TyKind::Ref(Mutability::Not, _, _)) { if !matches!(derefed_callee.kind(Interner), TyKind::Ref(Mutability::Not, _, _)) {
adjustments.push(Adjustment::borrow(Mutability::Not, derefed_callee.clone())); adjustments.push(Adjustment::borrow(
Mutability::Not,
derefed_callee.clone(),
self.table.new_lifetime_var(),
));
} }
} }
} }
@ -1313,11 +1332,11 @@ impl InferenceContext<'_> {
Some(sig) => { Some(sig) => {
let p_left = &sig.params()[0]; let p_left = &sig.params()[0];
if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) { if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) {
if let &TyKind::Ref(mtbl, _, _) = p_left.kind(Interner) { if let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner) {
self.write_expr_adj( self.write_expr_adj(
lhs, lhs,
vec![Adjustment { vec![Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)), kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
target: p_left.clone(), target: p_left.clone(),
}], }],
); );
@ -1325,11 +1344,11 @@ impl InferenceContext<'_> {
} }
let p_right = &sig.params()[1]; let p_right = &sig.params()[1];
if matches!(op, BinaryOp::CmpOp(..)) { if matches!(op, BinaryOp::CmpOp(..)) {
if let &TyKind::Ref(mtbl, _, _) = p_right.kind(Interner) { if let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner) {
self.write_expr_adj( self.write_expr_adj(
rhs, rhs,
vec![Adjustment { vec![Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mtbl)), kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
target: p_right.clone(), target: p_right.clone(),
}], }],
); );

View file

@ -28,7 +28,7 @@ impl InferenceContext<'_> {
Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => (), Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => (),
Adjust::Deref(Some(d)) => *d = OverloadedDeref(Some(mutability)), Adjust::Deref(Some(d)) => *d = OverloadedDeref(Some(mutability)),
Adjust::Borrow(b) => match b { Adjust::Borrow(b) => match b {
AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m) => mutability = *m, AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m) => mutability = *m,
}, },
} }
} }
@ -125,7 +125,7 @@ impl InferenceContext<'_> {
.get_mut(&base) .get_mut(&base)
.and_then(|it| it.last_mut()); .and_then(|it| it.last_mut());
if let Some(Adjustment { if let Some(Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mutability)), kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
target, target,
}) = base_adjustments }) = base_adjustments
{ {

View file

@ -12,7 +12,6 @@ use stdx::TupleExt;
use crate::{ use crate::{
consteval::{try_const_usize, usize_const}, consteval::{try_const_usize, usize_const},
error_lifetime,
infer::{BindingMode, Expectation, InferenceContext, TypeMismatch}, infer::{BindingMode, Expectation, InferenceContext, TypeMismatch},
lower::lower_to_chalk_mutability, lower::lower_to_chalk_mutability,
primitive::UintTy, primitive::UintTy,
@ -394,19 +393,20 @@ impl InferenceContext<'_> {
expected: &Ty, expected: &Ty,
default_bm: BindingMode, default_bm: BindingMode,
) -> Ty { ) -> Ty {
let expectation = match expected.as_reference() { let (expectation_type, expectation_lt) = match expected.as_reference() {
Some((inner_ty, _lifetime, _exp_mut)) => inner_ty.clone(), Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime.clone()),
None => { None => {
let inner_ty = self.table.new_type_var(); let inner_ty = self.table.new_type_var();
let inner_lt = self.table.new_lifetime_var();
let ref_ty = let ref_ty =
TyKind::Ref(mutability, error_lifetime(), inner_ty.clone()).intern(Interner); TyKind::Ref(mutability, inner_lt.clone(), inner_ty.clone()).intern(Interner);
// Unification failure will be reported by the caller. // Unification failure will be reported by the caller.
self.unify(&ref_ty, expected); self.unify(&ref_ty, expected);
inner_ty (inner_ty, inner_lt)
} }
}; };
let subty = self.infer_pat(inner_pat, &expectation, default_bm); let subty = self.infer_pat(inner_pat, &expectation_type, default_bm);
TyKind::Ref(mutability, error_lifetime(), subty).intern(Interner) TyKind::Ref(mutability, expectation_lt, subty).intern(Interner)
} }
fn infer_bind_pat( fn infer_bind_pat(
@ -433,7 +433,8 @@ impl InferenceContext<'_> {
let bound_ty = match mode { let bound_ty = match mode {
BindingMode::Ref(mutability) => { BindingMode::Ref(mutability) => {
TyKind::Ref(mutability, error_lifetime(), inner_ty.clone()).intern(Interner) let inner_lt = self.table.new_lifetime_var();
TyKind::Ref(mutability, inner_lt, inner_ty.clone()).intern(Interner)
} }
BindingMode::Move => inner_ty.clone(), BindingMode::Move => inner_ty.clone(),
}; };

View file

@ -17,12 +17,12 @@ use triomphe::Arc;
use super::{InferOk, InferResult, InferenceContext, TypeError}; use super::{InferOk, InferResult, InferenceContext, TypeError};
use crate::{ use crate::{
consteval::unknown_const, db::HirDatabase, error_lifetime, fold_generic_args, consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts,
fold_tys_and_consts, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar,
ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
TyKind, VariableKind, WhereClause, WhereClause,
}; };
impl InferenceContext<'_> { impl InferenceContext<'_> {
@ -105,7 +105,7 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner), VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner),
// Chalk can sometimes return new lifetime variables. We just replace them by errors // Chalk can sometimes return new lifetime variables. We just replace them by errors
// for now. // for now.
VariableKind::Lifetime => error_lifetime().cast(Interner), VariableKind::Lifetime => ctx.new_lifetime_var().cast(Interner),
VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner), VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner),
}), }),
); );

View file

@ -542,7 +542,8 @@ impl ReceiverAdjustments {
} }
} }
if let Some(m) = self.autoref { if let Some(m) = self.autoref {
let a = Adjustment::borrow(m, ty); let lt = table.new_lifetime_var();
let a = Adjustment::borrow(m, ty, lt);
ty = a.target.clone(); ty = a.target.clone();
adjust.push(a); adjust.push(a);
} }

View file

@ -337,7 +337,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into()); self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
Ok(Some(current)) Ok(Some(current))
} }
Adjust::Borrow(AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m)) => { Adjust::Borrow(AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) => {
let Some((p, current)) = let Some((p, current)) =
self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)? self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)?
else { else {

View file

@ -26,6 +26,7 @@ use hir_def::{
AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
}; };
use hir_expand::{db::ExpandDatabase, FileRange, InFile}; use hir_expand::{db::ExpandDatabase, FileRange, InFile};
use itertools::Itertools;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use stdx::format_to; use stdx::format_to;
use syntax::{ use syntax::{
@ -94,7 +95,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
let mut had_annotations = false; let mut had_annotations = false;
let mut mismatches = FxHashMap::default(); let mut mismatches = FxHashMap::default();
let mut types = FxHashMap::default(); let mut types = FxHashMap::default();
let mut adjustments = FxHashMap::<_, Vec<_>>::default(); let mut adjustments = FxHashMap::default();
for (file_id, annotations) in db.extract_annotations() { for (file_id, annotations) in db.extract_annotations() {
for (range, expected) in annotations { for (range, expected) in annotations {
let file_range = FileRange { file_id, range }; let file_range = FileRange { file_id, range };
@ -107,13 +108,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
} else if expected.starts_with("adjustments:") { } else if expected.starts_with("adjustments:") {
adjustments.insert( adjustments.insert(
file_range, file_range,
expected expected.trim_start_matches("adjustments:").trim().to_owned(),
.trim_start_matches("adjustments:")
.trim()
.split(',')
.map(|it| it.trim().to_owned())
.filter(|it| !it.is_empty())
.collect(),
); );
} else { } else {
panic!("unexpected annotation: {expected}"); panic!("unexpected annotation: {expected}");
@ -200,7 +195,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
adjustments adjustments
.iter() .iter()
.map(|Adjustment { kind, .. }| format!("{kind:?}")) .map(|Adjustment { kind, .. }| format!("{kind:?}"))
.collect::<Vec<_>>() .join(", ")
); );
} }
} }

View file

@ -49,7 +49,7 @@ fn let_stmt_coerce() {
//- minicore: coerce_unsized //- minicore: coerce_unsized
fn test() { fn test() {
let x: &[isize] = &[1]; let x: &[isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not)), Pointer(Unsize)
let x: *const [isize] = &[1]; let x: *const [isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
} }
@ -96,7 +96,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
fn test() { fn test() {
let x = if true { let x = if true {
foo(&[1]) foo(&[1])
// ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?8, Not)), Pointer(Unsize)
} else { } else {
&[1] &[1]
}; };
@ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
fn test(i: i32) { fn test(i: i32) {
let x = match i { let x = match i {
2 => foo(&[2]), 2 => foo(&[2]),
// ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?10, Not)), Pointer(Unsize)
1 => &[1], 1 => &[1],
_ => &[3], _ => &[3],
}; };
@ -267,7 +267,7 @@ fn takes_ref_str(x: &str) {}
fn returns_string() -> String { loop {} } fn returns_string() -> String { loop {} }
fn test() { fn test() {
takes_ref_str(&{ returns_string() }); takes_ref_str(&{ returns_string() });
// ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref(Not)) // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{error}, Not))
} }
"#, "#,
); );
@ -849,8 +849,8 @@ impl core::cmp::PartialEq for Struct {
} }
fn test() { fn test() {
Struct == Struct; Struct == Struct;
// ^^^^^^ adjustments: Borrow(Ref(Not)) // ^^^^^^ adjustments: Borrow(Ref('{error}, Not))
// ^^^^^^ adjustments: Borrow(Ref(Not)) // ^^^^^^ adjustments: Borrow(Ref('{error}, Not))
}", }",
); );
} }
@ -866,7 +866,7 @@ impl core::ops::AddAssign for Struct {
} }
fn test() { fn test() {
Struct += Struct; Struct += Struct;
// ^^^^^^ adjustments: Borrow(Ref(Mut)) // ^^^^^^ adjustments: Borrow(Ref('{error}, Mut))
// ^^^^^^ adjustments: // ^^^^^^ adjustments:
}", }",
); );
@ -880,7 +880,7 @@ fn adjust_index() {
fn test() { fn test() {
let x = [1, 2, 3]; let x = [1, 2, 3];
x[2] = 6; x[2] = 6;
// ^ adjustments: Borrow(Ref(Mut)) // ^ adjustments: Borrow(Ref('?8, Mut))
} }
", ",
); );
@ -905,11 +905,11 @@ impl core::ops::IndexMut for StructMut {
} }
fn test() { fn test() {
Struct[0]; Struct[0];
// ^^^^^^ adjustments: Borrow(Ref(Not)) // ^^^^^^ adjustments: Borrow(Ref('?2, Not))
StructMut[0]; StructMut[0];
// ^^^^^^^^^ adjustments: Borrow(Ref(Not)) // ^^^^^^^^^ adjustments: Borrow(Ref('?5, Not))
&mut StructMut[0]; &mut StructMut[0];
// ^^^^^^^^^ adjustments: Borrow(Ref(Mut)) // ^^^^^^^^^ adjustments: Borrow(Ref('?8, Mut))
}", }",
); );
} }

View file

@ -1186,11 +1186,11 @@ fn test() {
89..109 '{ ... }': bool 89..109 '{ ... }': bool
99..103 'true': bool 99..103 'true': bool
123..167 '{ ...o(); }': () 123..167 '{ ...o(); }': ()
133..134 's': &'? S 133..134 's': &'static S
137..151 'unsafe { f() }': &'static S 137..151 'unsafe { f() }': &'static S
146..147 'f': fn f() -> &'static S 146..147 'f': fn f() -> &'static S
146..149 'f()': &'static S 146..149 'f()': &'static S
157..158 's': &'? S 157..158 's': &'static S
157..164 's.foo()': bool 157..164 's.foo()': bool
"#]], "#]],
); );
@ -1847,9 +1847,9 @@ impl Foo {
} }
fn test() { fn test() {
Foo.foo(); Foo.foo();
//^^^ adjustments: Borrow(Ref(Not)) //^^^ adjustments: Borrow(Ref('?1, Not))
(&Foo).foo(); (&Foo).foo();
// ^^^^ adjustments: Deref(None), Borrow(Ref(Not)) // ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not))
} }
"#, "#,
); );
@ -1863,7 +1863,7 @@ fn receiver_adjustment_unsize_array() {
fn test() { fn test() {
let a = [1, 2, 3]; let a = [1, 2, 3];
a.len(); a.len();
} //^ adjustments: Borrow(Ref(Not)), Pointer(Unsize) } //^ adjustments: Borrow(Ref('?7, Not)), Pointer(Unsize)
"#, "#,
); );
} }
@ -2076,7 +2076,7 @@ impl Foo {
} }
fn test() { fn test() {
Box::new(Foo).foo(); Box::new(Foo).foo();
//^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref(Not)) //^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not))
} }
"#, "#,
); );
@ -2094,7 +2094,7 @@ impl Foo {
use core::mem::ManuallyDrop; use core::mem::ManuallyDrop;
fn test() { fn test() {
ManuallyDrop::new(Foo).foo(); ManuallyDrop::new(Foo).foo();
//^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref(Not)) //^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?4, Not))
} }
"#, "#,
); );

View file

@ -1201,8 +1201,8 @@ fn infer_array() {
209..215 '[1, 2]': [i32; 2] 209..215 '[1, 2]': [i32; 2]
210..211 '1': i32 210..211 '1': i32
213..214 '2': i32 213..214 '2': i32
225..226 'i': [&'? str; 2] 225..226 'i': [&'static str; 2]
229..239 '["a", "b"]': [&'? str; 2] 229..239 '["a", "b"]': [&'static str; 2]
230..233 '"a"': &'static str 230..233 '"a"': &'static str
235..238 '"b"': &'static str 235..238 '"b"': &'static str
250..251 'b': [[&'? str; 1]; 2] 250..251 'b': [[&'? str; 1]; 2]

View file

@ -1179,7 +1179,8 @@ impl<'db> SemanticsImpl<'db> {
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => { hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => {
Adjust::Borrow(AutoBorrow::RawPtr(mutability(m))) Adjust::Borrow(AutoBorrow::RawPtr(mutability(m)))
} }
hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(m)) => { hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(_, m)) => {
// FIXME: Handle lifetimes here
Adjust::Borrow(AutoBorrow::Ref(mutability(m))) Adjust::Borrow(AutoBorrow::Ref(mutability(m)))
} }
hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc), hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc),