mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
implement basic inferring of lifetimes
This commit is contained in:
parent
4cd8dcf287
commit
8a4261aca8
14 changed files with 109 additions and 85 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|
|
@ -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(),
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(", ")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}",
|
}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue