Record in HIR whether lifetime elision was succesful.
This commit is contained in:
parent
fb7d25e978
commit
5f5e7a8eec
@ -603,6 +603,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
output,
|
output,
|
||||||
c_variadic: false,
|
c_variadic: false,
|
||||||
implicit_self: hir::ImplicitSelfKind::None,
|
implicit_self: hir::ImplicitSelfKind::None,
|
||||||
|
lifetime_elision_allowed: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
|
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
|
||||||
@ -907,7 +908,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||||
// Lower outside new scope to preserve `is_in_loop_condition`.
|
// Lower outside new scope to preserve `is_in_loop_condition`.
|
||||||
let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
|
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
let c = self.arena.alloc(hir::Closure {
|
let c = self.arena.alloc(hir::Closure {
|
||||||
def_id: self.local_def_id(closure_id),
|
def_id: self.local_def_id(closure_id),
|
||||||
@ -1017,7 +1018,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// have to conserve the state of being inside a loop condition for the
|
// have to conserve the state of being inside a loop condition for the
|
||||||
// closure argument types.
|
// closure argument types.
|
||||||
let fn_decl =
|
let fn_decl =
|
||||||
self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
|
self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
let c = self.arena.alloc(hir::Closure {
|
let c = self.arena.alloc(hir::Closure {
|
||||||
def_id: self.local_def_id(closure_id),
|
def_id: self.local_def_id(closure_id),
|
||||||
|
@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let mut itctx = ImplTraitContext::Universal;
|
let mut itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
|
||||||
let ret_id = asyncness.opt_return_id();
|
let ret_id = asyncness.opt_return_id();
|
||||||
this.lower_fn_decl(&decl, Some(id), *fn_sig_span, FnDeclKind::Fn, ret_id)
|
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
|
||||||
});
|
});
|
||||||
let sig = hir::FnSig {
|
let sig = hir::FnSig {
|
||||||
decl,
|
decl,
|
||||||
@ -659,7 +659,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// Disallow `impl Trait` in foreign items.
|
// Disallow `impl Trait` in foreign items.
|
||||||
this.lower_fn_decl(
|
this.lower_fn_decl(
|
||||||
fdec,
|
fdec,
|
||||||
None,
|
i.id,
|
||||||
sig.span,
|
sig.span,
|
||||||
FnDeclKind::ExternFn,
|
FnDeclKind::ExternFn,
|
||||||
None,
|
None,
|
||||||
@ -1247,7 +1247,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
let mut itctx = ImplTraitContext::Universal;
|
let mut itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
|
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
|
||||||
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
|
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
|
||||||
});
|
});
|
||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,14 @@ enum FnDeclKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FnDeclKind {
|
impl FnDeclKind {
|
||||||
fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
fn param_impl_trait_allowed(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
||||||
match self {
|
match self {
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => true,
|
FnDeclKind::Fn | FnDeclKind::Inherent => true,
|
||||||
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
|
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
|
||||||
@ -1267,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
generic_params,
|
generic_params,
|
||||||
unsafety: self.lower_unsafety(f.unsafety),
|
unsafety: self.lower_unsafety(f.unsafety),
|
||||||
abi: self.lower_extern(f.ext),
|
abi: self.lower_extern(f.ext),
|
||||||
decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
|
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
|
||||||
param_names: self.lower_fn_params_to_names(&f.decl),
|
param_names: self.lower_fn_params_to_names(&f.decl),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1671,7 +1678,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
fn lower_fn_decl(
|
fn lower_fn_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
fn_node_id: Option<NodeId>,
|
fn_node_id: NodeId,
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
kind: FnDeclKind,
|
kind: FnDeclKind,
|
||||||
make_ret_async: Option<(NodeId, Span)>,
|
make_ret_async: Option<(NodeId, Span)>,
|
||||||
@ -1686,23 +1693,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
inputs = &inputs[..inputs.len() - 1];
|
inputs = &inputs[..inputs.len() - 1];
|
||||||
}
|
}
|
||||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
|
||||||
if fn_node_id.is_some() {
|
let itctx = if kind.param_impl_trait_allowed() {
|
||||||
self.lower_ty_direct(¶m.ty, &ImplTraitContext::Universal)
|
ImplTraitContext::Universal
|
||||||
} else {
|
} else {
|
||||||
self.lower_ty_direct(
|
ImplTraitContext::Disallowed(match kind {
|
||||||
¶m.ty,
|
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||||
&ImplTraitContext::Disallowed(match kind {
|
unreachable!("fn should allow APIT")
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
}
|
||||||
unreachable!("fn should allow in-band lifetimes")
|
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
|
||||||
}
|
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
|
||||||
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
|
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
|
||||||
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
|
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
|
||||||
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
|
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
|
||||||
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
|
})
|
||||||
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
|
};
|
||||||
}),
|
self.lower_ty_direct(¶m.ty, &itctx)
|
||||||
)
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let output = if let Some((ret_id, span)) = make_ret_async {
|
let output = if let Some((ret_id, span)) = make_ret_async {
|
||||||
@ -1725,22 +1730,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
self.lower_async_fn_ret_ty(
|
self.lower_async_fn_ret_ty(
|
||||||
&decl.output,
|
&decl.output,
|
||||||
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
|
fn_node_id,
|
||||||
ret_id,
|
ret_id,
|
||||||
matches!(kind, FnDeclKind::Trait),
|
matches!(kind, FnDeclKind::Trait),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
match &decl.output {
|
match &decl.output {
|
||||||
FnRetTy::Ty(ty) => {
|
FnRetTy::Ty(ty) => {
|
||||||
let mut context = match fn_node_id {
|
let mut context = if kind.return_impl_trait_allowed(self.tcx) {
|
||||||
Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
let fn_def_id = self.local_def_id(fn_node_id);
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
in_trait: matches!(kind, FnDeclKind::Trait),
|
||||||
in_trait: matches!(kind, FnDeclKind::Trait),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => ImplTraitContext::Disallowed(match kind {
|
} else {
|
||||||
|
ImplTraitContext::Disallowed(match kind {
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||||
unreachable!("fn should allow in-band lifetimes")
|
unreachable!("fn should allow in-band lifetimes")
|
||||||
}
|
}
|
||||||
@ -1749,7 +1753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
|
||||||
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
|
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
|
||||||
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
|
||||||
}),
|
})
|
||||||
};
|
};
|
||||||
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
|
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
|
||||||
}
|
}
|
||||||
@ -1761,6 +1765,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
inputs,
|
inputs,
|
||||||
output,
|
output,
|
||||||
c_variadic,
|
c_variadic,
|
||||||
|
lifetime_elision_allowed: self.resolver.lifetime_elision_allowed.contains(&fn_node_id),
|
||||||
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
|
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
|
||||||
let is_mutable_pat = matches!(
|
let is_mutable_pat = matches!(
|
||||||
arg.pat.kind,
|
arg.pat.kind,
|
||||||
|
@ -2670,6 +2670,8 @@ pub struct FnDecl<'hir> {
|
|||||||
pub c_variadic: bool,
|
pub c_variadic: bool,
|
||||||
/// Does the function have an implicit self?
|
/// Does the function have an implicit self?
|
||||||
pub implicit_self: ImplicitSelfKind,
|
pub implicit_self: ImplicitSelfKind,
|
||||||
|
/// Is lifetime elision allowed.
|
||||||
|
pub lifetime_elision_allowed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents what type of implicit self a function has, if any.
|
/// Represents what type of implicit self a function has, if any.
|
||||||
|
@ -207,6 +207,8 @@ pub struct ResolverAstLowering {
|
|||||||
/// A small map keeping true kinds of built-in macros that appear to be fn-like on
|
/// A small map keeping true kinds of built-in macros that appear to be fn-like on
|
||||||
/// the surface (`macro` items in libcore), but are actually attributes or derives.
|
/// the surface (`macro` items in libcore), but are actually attributes or derives.
|
||||||
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
|
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
|
||||||
|
/// List functions and methods for which lifetime elision was successful.
|
||||||
|
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -1838,6 +1838,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||||||
|
|
||||||
let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
|
let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
|
||||||
let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
|
let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
|
||||||
|
self.r.lifetime_elision_allowed.insert(fn_id);
|
||||||
LifetimeRibKind::Elided(*res)
|
LifetimeRibKind::Elided(*res)
|
||||||
} else {
|
} else {
|
||||||
LifetimeRibKind::ElisionFailure
|
LifetimeRibKind::ElisionFailure
|
||||||
|
@ -1036,6 +1036,8 @@ pub struct Resolver<'a> {
|
|||||||
/// they are declared in the static array generated by proc_macro_harness.
|
/// they are declared in the static array generated by proc_macro_harness.
|
||||||
proc_macros: Vec<NodeId>,
|
proc_macros: Vec<NodeId>,
|
||||||
confused_type_with_std_module: FxHashMap<Span, Span>,
|
confused_type_with_std_module: FxHashMap<Span, Span>,
|
||||||
|
/// Whether lifetime elision was successful.
|
||||||
|
lifetime_elision_allowed: FxHashSet<NodeId>,
|
||||||
|
|
||||||
effective_visibilities: EffectiveVisibilities,
|
effective_visibilities: EffectiveVisibilities,
|
||||||
}
|
}
|
||||||
@ -1354,6 +1356,7 @@ impl<'a> Resolver<'a> {
|
|||||||
trait_impls: Default::default(),
|
trait_impls: Default::default(),
|
||||||
proc_macros: Default::default(),
|
proc_macros: Default::default(),
|
||||||
confused_type_with_std_module: Default::default(),
|
confused_type_with_std_module: Default::default(),
|
||||||
|
lifetime_elision_allowed: Default::default(),
|
||||||
effective_visibilities: Default::default(),
|
effective_visibilities: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1448,6 +1451,7 @@ impl<'a> Resolver<'a> {
|
|||||||
def_id_to_node_id: self.def_id_to_node_id,
|
def_id_to_node_id: self.def_id_to_node_id,
|
||||||
trait_map: self.trait_map,
|
trait_map: self.trait_map,
|
||||||
builtin_macro_kinds: self.builtin_macro_kinds,
|
builtin_macro_kinds: self.builtin_macro_kinds,
|
||||||
|
lifetime_elision_allowed: self.lifetime_elision_allowed,
|
||||||
};
|
};
|
||||||
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
||||||
}
|
}
|
||||||
@ -1491,6 +1495,7 @@ impl<'a> Resolver<'a> {
|
|||||||
def_id_to_node_id: self.def_id_to_node_id.clone(),
|
def_id_to_node_id: self.def_id_to_node_id.clone(),
|
||||||
trait_map: self.trait_map.clone(),
|
trait_map: self.trait_map.clone(),
|
||||||
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
|
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
|
||||||
|
lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
|
||||||
};
|
};
|
||||||
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user