Fix lifetimes len diagnostics for fn pointers
This commit is contained in:
parent
d87c468b42
commit
e80fbd4bca
3 changed files with 47 additions and 27 deletions
|
|
@ -27,8 +27,8 @@ use hir_def::{
|
|||
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
|
||||
signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
|
||||
type_ref::{
|
||||
ConstRef, LifetimeRefId, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
|
||||
TypeRef, TypeRefId,
|
||||
ConstRef, FnType, LifetimeRefId, PathId, TraitBoundModifier, TraitRef as HirTraitRef,
|
||||
TypeBound, TypeRef, TypeRefId,
|
||||
},
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
|
|
@ -98,7 +98,7 @@ impl ImplTraitLoweringState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum LifetimeElisionKind<'db> {
|
||||
/// Create a new anonymous lifetime parameter and reference it.
|
||||
///
|
||||
|
|
@ -437,26 +437,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
|
|||
Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
|
||||
}
|
||||
TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
|
||||
TypeRef::Fn(fn_) => {
|
||||
let substs = self.with_shifted_in(
|
||||
DebruijnIndex::from_u32(1),
|
||||
|ctx: &mut TyLoweringContext<'_, '_>| {
|
||||
Tys::new_from_iter(
|
||||
interner,
|
||||
fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)),
|
||||
)
|
||||
},
|
||||
);
|
||||
Ty::new_fn_ptr(
|
||||
interner,
|
||||
Binder::dummy(FnSig {
|
||||
abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
|
||||
safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
|
||||
c_variadic: fn_.is_varargs,
|
||||
inputs_and_output: substs,
|
||||
}),
|
||||
)
|
||||
}
|
||||
TypeRef::Fn(fn_) => self.lower_fn_ptr(fn_),
|
||||
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
|
||||
TypeRef::ImplTrait(bounds) => {
|
||||
match self.impl_trait_mode.mode {
|
||||
|
|
@ -517,6 +498,30 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
|
|||
(ty, res)
|
||||
}
|
||||
|
||||
fn lower_fn_ptr(&mut self, fn_: &FnType) -> Ty<'db> {
|
||||
let interner = self.interner;
|
||||
let (params, ret_ty) = fn_.split_params_and_ret();
|
||||
let old_lifetime_elision = self.lifetime_elision;
|
||||
let mut args = Vec::with_capacity(fn_.params.len());
|
||||
self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx: &mut TyLoweringContext<'_, '_>| {
|
||||
ctx.lifetime_elision =
|
||||
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
|
||||
args.extend(params.iter().map(|&(_, tr)| ctx.lower_ty(tr)));
|
||||
ctx.lifetime_elision = LifetimeElisionKind::for_fn_ret(interner);
|
||||
args.push(ctx.lower_ty(ret_ty));
|
||||
});
|
||||
self.lifetime_elision = old_lifetime_elision;
|
||||
Ty::new_fn_ptr(
|
||||
interner,
|
||||
Binder::dummy(FnSig {
|
||||
abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
|
||||
safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
|
||||
c_variadic: fn_.is_varargs,
|
||||
inputs_and_output: Tys::new_from_slice(&args),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// This is only for `generic_predicates_for_param`, where we can't just
|
||||
/// lower the self types of the predicates since that could lead to cycles.
|
||||
/// So we just check here if the `type_ref` resolves to a generic param, and which.
|
||||
|
|
|
|||
|
|
@ -599,7 +599,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
|
|||
explicit_self_ty: Option<Ty<'db>>,
|
||||
lowering_assoc_type_generics: bool,
|
||||
) -> GenericArgs<'db> {
|
||||
let old_lifetime_elision = self.ctx.lifetime_elision.clone();
|
||||
let old_lifetime_elision = self.ctx.lifetime_elision;
|
||||
|
||||
if let Some(args) = self.current_or_prev_segment.args_and_bindings
|
||||
&& args.parenthesized != GenericArgsParentheses::No
|
||||
|
|
@ -640,7 +640,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
|
|||
explicit_self_ty,
|
||||
PathGenericsSource::Segment(self.current_segment_u32()),
|
||||
lowering_assoc_type_generics,
|
||||
self.ctx.lifetime_elision.clone(),
|
||||
self.ctx.lifetime_elision,
|
||||
);
|
||||
self.ctx.lifetime_elision = old_lifetime_elision;
|
||||
result
|
||||
|
|
@ -884,7 +884,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
|
|||
assoc_type: binding_idx as u32,
|
||||
},
|
||||
false,
|
||||
this.ctx.lifetime_elision.clone(),
|
||||
this.ctx.lifetime_elision,
|
||||
)
|
||||
});
|
||||
let args = GenericArgs::new_from_iter(
|
||||
|
|
@ -902,7 +902,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
|
|||
// `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
|
||||
LifetimeElisionKind::for_fn_ret(self.ctx.interner)
|
||||
} else {
|
||||
self.ctx.lifetime_elision.clone()
|
||||
self.ctx.lifetime_elision
|
||||
};
|
||||
self.with_lifetime_elision(lifetime_elision, |this| {
|
||||
match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
|
||||
|
|
|
|||
|
|
@ -100,4 +100,19 @@ fn foo<T: Fn(WithLifetime) -> WithLifetime>() {}
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_21430() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct S {
|
||||
f: fn(A<()>),
|
||||
}
|
||||
|
||||
struct A<'a, T> {
|
||||
a: &'a T,
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue