Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17747 - ShoyuVanilla:issue-17734, r=Veykril
fix: Errors on method call inferences with elided lifetimes Fixes #17734 Currently, we are matching non-lifetime(type or const) generic arg to liftime argument position while building substs for method calling when there are elided lifetimes. This mismatch just make a subst for error lifetime and while this alone is not much a trouble, it also makes the mismatched type or const generic arg cannot be used in its proper place and this makes type inference failure
bors 2024-07-31
parent 4feec4b · parent a871730 · commit 8bbd23a
-rw-r--r--crates/hir-ty/src/infer/expr.rs64
-rw-r--r--crates/hir-ty/src/tests/regression.rs34
2 files changed, 74 insertions, 24 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 24479a027f..3d762b174a 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -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);
}
};
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index aa7b00b8de..b371e5856b 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2041,3 +2041,37 @@ 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::<'static, &()>();
+ // ^ 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>;
+}
+"#,
+ )
+}