Skip to content

Commit

Permalink
Auto merge of rust-lang#17747 - ShoyuVanilla:issue-17734, r=Veykril
Browse files Browse the repository at this point in the history
fix: Errors on method call inferences with elided lifetimes

Fixes rust-lang#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
  • Loading branch information
bors committed Jul 31, 2024
2 parents 51a0dd2 + 1b058b7 commit 9fb03f0
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 24 deletions.
64 changes: 40 additions & 24 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
};
Expand Down
34 changes: 34 additions & 0 deletions src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}
"#,
)
}

0 comments on commit 9fb03f0

Please sign in to comment.