fix: Errors on method call inferences with elided lifetimes

This commit is contained in:
Shoyu Vanilla 2024-07-31 02:36:44 +09:00
parent 4feec4b0c1
commit 92a6e51b20
2 changed files with 72 additions and 24 deletions

View file

@ -12,7 +12,7 @@ use hir_def::{
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
},
lang_item::{LangItem, LangItemTarget},
path::{GenericArgs, Path},
path::{GenericArg, GenericArgs, Path},
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
};
use hir_expand::name::Name;
@ -1851,29 +1851,45 @@ impl InferenceContext<'_> {
if let Some(generic_args) = generic_args {
// if args are provided, it should be all of them, but we can't rely on that
let self_params = type_params + const_params + lifetime_params;
for (arg, kind_id) in
generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params)
{
let arg = generic_arg_to_chalk(
self.db,
kind_id,
arg,
self,
|this, type_ref| this.make_ty(type_ref),
|this, c, ty| {
const_or_path_to_chalk(
this.db,
&this.resolver,
this.owner.into(),
ty,
c,
ParamLoweringMode::Placeholder,
|| this.generics(),
DebruijnIndex::INNERMOST,
)
},
|this, lt_ref| this.make_lifetime(lt_ref),
);
let mut args = generic_args.args.iter().peekable();
for kind_id in def_generics.iter_self_id().take(self_params) {
let arg = args.peek();
let arg = match (kind_id, arg) {
// Lifetimes can be elided.
// Once we have implemented lifetime elision correctly,
// this should be handled in a proper way.
(
GenericParamId::LifetimeParamId(_),
None | Some(GenericArg::Type(_) | GenericArg::Const(_)),
) => error_lifetime().cast(Interner),
// If we run out of `generic_args`, stop pushing substs
(_, None) => break,
// Normal cases
(_, Some(_)) => generic_arg_to_chalk(
self.db,
kind_id,
args.next().unwrap(), // `peek()` is `Some(_)`, so guaranteed no panic
self,
|this, type_ref| this.make_ty(type_ref),
|this, c, ty| {
const_or_path_to_chalk(
this.db,
&this.resolver,
this.owner.into(),
ty,
c,
ParamLoweringMode::Placeholder,
|| this.generics(),
DebruijnIndex::INNERMOST,
)
},
|this, lt_ref| this.make_lifetime(lt_ref),
),
};
substs.push(arg);
}
};

View file

@ -2041,3 +2041,35 @@ fn main() {
"#,
);
}
#[test]
fn issue_17734() {
check_types(
r#"
fn test() {
let x = S::foo::<'static, &()>(&S);
// ^ Wrap<'?, ()>
let x = S::foo::<&()>(&S);
// ^ Wrap<'?, ()>
let x = S.foo::<&()>();
// ^ Wrap<'?, ()>
}
struct S;
impl S {
pub fn foo<'a, T: Trait<'a>>(&'a self) -> T::Proj {
loop {}
}
}
struct Wrap<'a, T>(T);
trait Trait<'a> {
type Proj;
}
impl<'a, T> Trait<'a> for &'a T {
type Proj = Wrap<'a, T>;
}
"#,
)
}