mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
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
This commit is contained in:
commit
8bbd23ade9
2 changed files with 74 additions and 24 deletions
|
@ -12,7 +12,7 @@ use hir_def::{
|
||||||
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
||||||
},
|
},
|
||||||
lang_item::{LangItem, LangItemTarget},
|
lang_item::{LangItem, LangItemTarget},
|
||||||
path::{GenericArgs, Path},
|
path::{GenericArg, GenericArgs, Path},
|
||||||
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
|
@ -1851,29 +1851,45 @@ impl InferenceContext<'_> {
|
||||||
if let Some(generic_args) = generic_args {
|
if let Some(generic_args) = generic_args {
|
||||||
// if args are provided, it should be all of them, but we can't rely on that
|
// 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;
|
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 mut args = generic_args.args.iter().peekable();
|
||||||
{
|
for kind_id in def_generics.iter_self_id().take(self_params) {
|
||||||
let arg = generic_arg_to_chalk(
|
let arg = args.peek();
|
||||||
self.db,
|
let arg = match (kind_id, arg) {
|
||||||
kind_id,
|
// Lifetimes can be elided.
|
||||||
arg,
|
// Once we have implemented lifetime elision correctly,
|
||||||
self,
|
// this should be handled in a proper way.
|
||||||
|this, type_ref| this.make_ty(type_ref),
|
(
|
||||||
|this, c, ty| {
|
GenericParamId::LifetimeParamId(_),
|
||||||
const_or_path_to_chalk(
|
None | Some(GenericArg::Type(_) | GenericArg::Const(_)),
|
||||||
this.db,
|
) => error_lifetime().cast(Interner),
|
||||||
&this.resolver,
|
|
||||||
this.owner.into(),
|
// If we run out of `generic_args`, stop pushing substs
|
||||||
ty,
|
(_, None) => break,
|
||||||
c,
|
|
||||||
ParamLoweringMode::Placeholder,
|
// Normal cases
|
||||||
|| this.generics(),
|
(_, Some(_)) => generic_arg_to_chalk(
|
||||||
DebruijnIndex::INNERMOST,
|
self.db,
|
||||||
)
|
kind_id,
|
||||||
},
|
args.next().unwrap(), // `peek()` is `Some(_)`, so guaranteed no panic
|
||||||
|this, lt_ref| this.make_lifetime(lt_ref),
|
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);
|
substs.push(arg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue