Skip to content

Commit a2555b9

Browse files
committed
fix: Errors on method call inferences with elided lifetimes
1 parent 51a0dd2 commit a2555b9

File tree

2 files changed

+72
-24
lines changed

2 files changed

+72
-24
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use hir_def::{
1212
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
1313
},
1414
lang_item::{LangItem, LangItemTarget},
15-
path::{GenericArgs, Path},
15+
path::{GenericArg, GenericArgs, Path},
1616
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
1717
};
1818
use hir_expand::name::Name;
@@ -1851,29 +1851,45 @@ impl InferenceContext<'_> {
18511851
if let Some(generic_args) = generic_args {
18521852
// if args are provided, it should be all of them, but we can't rely on that
18531853
let self_params = type_params + const_params + lifetime_params;
1854-
for (arg, kind_id) in
1855-
generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params)
1856-
{
1857-
let arg = generic_arg_to_chalk(
1858-
self.db,
1859-
kind_id,
1860-
arg,
1861-
self,
1862-
|this, type_ref| this.make_ty(type_ref),
1863-
|this, c, ty| {
1864-
const_or_path_to_chalk(
1865-
this.db,
1866-
&this.resolver,
1867-
this.owner.into(),
1868-
ty,
1869-
c,
1870-
ParamLoweringMode::Placeholder,
1871-
|| this.generics(),
1872-
DebruijnIndex::INNERMOST,
1873-
)
1874-
},
1875-
|this, lt_ref| this.make_lifetime(lt_ref),
1876-
);
1854+
1855+
let mut args = generic_args.args.iter().peekable();
1856+
for kind_id in def_generics.iter_self_id().take(self_params) {
1857+
let arg = args.peek();
1858+
let arg = match (kind_id, arg) {
1859+
// Lifetimes can be elided.
1860+
// Once we have implemented lifetime elision correctly,
1861+
// this should be handled in a proper way.
1862+
(
1863+
GenericParamId::LifetimeParamId(_),
1864+
None | Some(GenericArg::Type(_) | GenericArg::Const(_)),
1865+
) => error_lifetime().cast(Interner),
1866+
1867+
// If we run out of `generic_args`, stop pushing substs
1868+
(_, None) => break,
1869+
1870+
// Normal cases
1871+
(_, Some(_)) => generic_arg_to_chalk(
1872+
self.db,
1873+
kind_id,
1874+
args.next().unwrap(), // `peek()` is `Some(_)`, so guaranteed no panic
1875+
self,
1876+
|this, type_ref| this.make_ty(type_ref),
1877+
|this, c, ty| {
1878+
const_or_path_to_chalk(
1879+
this.db,
1880+
&this.resolver,
1881+
this.owner.into(),
1882+
ty,
1883+
c,
1884+
ParamLoweringMode::Placeholder,
1885+
|| this.generics(),
1886+
DebruijnIndex::INNERMOST,
1887+
)
1888+
},
1889+
|this, lt_ref| this.make_lifetime(lt_ref),
1890+
),
1891+
};
1892+
18771893
substs.push(arg);
18781894
}
18791895
};

src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,3 +2041,35 @@ fn main() {
20412041
"#,
20422042
);
20432043
}
2044+
2045+
#[test]
2046+
fn issue_17734() {
2047+
check_types(
2048+
r#"
2049+
fn test() {
2050+
let x = S::foo::<'static, &()>(&S);
2051+
// ^ Wrap<'?, ()>
2052+
let x = S::foo::<&()>(&S);
2053+
// ^ Wrap<'?, ()>
2054+
let x = S.foo::<&()>();
2055+
// ^ Wrap<'?, ()>
2056+
}
2057+
2058+
struct S;
2059+
2060+
impl S {
2061+
pub fn foo<'a, T: Trait<'a>>(&'a self) -> T::Proj {
2062+
loop {}
2063+
}
2064+
}
2065+
2066+
struct Wrap<'a, T>(T);
2067+
trait Trait<'a> {
2068+
type Proj;
2069+
}
2070+
impl<'a, T> Trait<'a> for &'a T {
2071+
type Proj = Wrap<'a, T>;
2072+
}
2073+
"#,
2074+
)
2075+
}

0 commit comments

Comments
 (0)