mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 21:13:37 +00:00
fix: Errors on method call inferences with elided lifetimes
This commit is contained in:
parent
4feec4b0c1
commit
92a6e51b20
2 changed files with 72 additions and 24 deletions
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue