diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-06 09:33:52 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-24 17:48:27 +0000 |
| commit | 5f5e7a8eec4b69708005014ec322ba71caecdad1 (patch) | |
| tree | 51c8c7bf2d9681fe1170dc6709090f0136fccaca | |
| parent | fb7d25e97863e1a305bfeed6f418c5accc152123 (diff) | |
| download | rust-5f5e7a8eec4b69708005014ec322ba71caecdad1.tar.gz rust-5f5e7a8eec4b69708005014ec322ba71caecdad1.zip | |
Record in HIR whether lifetime elision was succesful.
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 63 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 5 |
7 files changed, 50 insertions, 34 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a00100ee0a8..88931766566 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -603,6 +603,7 @@ impl<'hir> LoweringContext<'_, 'hir> { output, c_variadic: false, implicit_self: hir::ImplicitSelfKind::None, + lifetime_elision_allowed: false, }); // 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); // 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 { 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 // closure argument types. 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 { def_id: self.local_def_id(closure_id), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8a7c3d357a0..2b47e908912 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { 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 { decl, @@ -659,7 +659,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Disallow `impl Trait` in foreign items. this.lower_fn_decl( fdec, - None, + i.id, sig.span, FnDeclKind::ExternFn, None, @@ -1247,7 +1247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.lower_fn_header(sig.header); let mut itctx = ImplTraitContext::Universal; 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) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 322055ca2c3..c6558f582eb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -327,7 +327,14 @@ enum 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 { FnDeclKind::Fn | FnDeclKind::Inherent => 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, unsafety: self.lower_unsafety(f.unsafety), 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), })) } @@ -1671,7 +1678,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_decl( &mut self, decl: &FnDecl, - fn_node_id: Option<NodeId>, + fn_node_id: NodeId, fn_span: Span, kind: FnDeclKind, make_ret_async: Option<(NodeId, Span)>, @@ -1686,23 +1693,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { inputs = &inputs[..inputs.len() - 1]; } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { - if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, &ImplTraitContext::Universal) + let itctx = if kind.param_impl_trait_allowed() { + ImplTraitContext::Universal } else { - self.lower_ty_direct( - ¶m.ty, - &ImplTraitContext::Disallowed(match kind { - FnDeclKind::Fn | FnDeclKind::Inherent => { - unreachable!("fn should allow in-band lifetimes") - } - FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam, - FnDeclKind::Closure => ImplTraitPosition::ClosureParam, - FnDeclKind::Pointer => ImplTraitPosition::PointerParam, - FnDeclKind::Trait => ImplTraitPosition::TraitParam, - FnDeclKind::Impl => ImplTraitPosition::ImplParam, - }), - ) - } + ImplTraitContext::Disallowed(match kind { + FnDeclKind::Fn | FnDeclKind::Inherent => { + unreachable!("fn should allow APIT") + } + FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam, + FnDeclKind::Closure => ImplTraitPosition::ClosureParam, + FnDeclKind::Pointer => ImplTraitPosition::PointerParam, + 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 { @@ -1725,22 +1730,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_async_fn_ret_ty( &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + fn_node_id, ret_id, matches!(kind, FnDeclKind::Trait), ) } else { match &decl.output { FnRetTy::Ty(ty) => { - let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => { - let fn_def_id = self.local_def_id(fn_node_id); - ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - in_trait: matches!(kind, FnDeclKind::Trait), - } + let mut context = if kind.return_impl_trait_allowed(self.tcx) { + let fn_def_id = self.local_def_id(fn_node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: matches!(kind, FnDeclKind::Trait), } - _ => ImplTraitContext::Disallowed(match kind { + } else { + ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1749,7 +1753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, FnDeclKind::Trait => ImplTraitPosition::TraitReturn, FnDeclKind::Impl => ImplTraitPosition::ImplReturn, - }), + }) }; hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } @@ -1761,6 +1765,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { inputs, output, 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| { let is_mutable_pat = matches!( arg.pat.kind, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6cba23c35cb..4ac783729e6 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2670,6 +2670,8 @@ pub struct FnDecl<'hir> { pub c_variadic: bool, /// Does the function have an implicit self? pub implicit_self: ImplicitSelfKind, + /// Is lifetime elision allowed. + pub lifetime_elision_allowed: bool, } /// Represents what type of implicit self a function has, if any. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0458c4abd3d..5ef5013cac1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -207,6 +207,8 @@ pub struct ResolverAstLowering { /// 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. 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)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5072d2aad16..4da124d1558 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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 output_rib = if let Ok(res) = elision_lifetime.as_ref() { + self.r.lifetime_elision_allowed.insert(fn_id); LifetimeRibKind::Elided(*res) } else { LifetimeRibKind::ElisionFailure diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f9ae3b58172..51d258594a8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1036,6 +1036,8 @@ pub struct Resolver<'a> { /// they are declared in the static array generated by proc_macro_harness. proc_macros: Vec<NodeId>, confused_type_with_std_module: FxHashMap<Span, Span>, + /// Whether lifetime elision was successful. + lifetime_elision_allowed: FxHashSet<NodeId>, effective_visibilities: EffectiveVisibilities, } @@ -1354,6 +1356,7 @@ impl<'a> Resolver<'a> { trait_impls: Default::default(), proc_macros: Default::default(), confused_type_with_std_module: Default::default(), + lifetime_elision_allowed: 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, trait_map: self.trait_map, builtin_macro_kinds: self.builtin_macro_kinds, + lifetime_elision_allowed: self.lifetime_elision_allowed, }; 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(), trait_map: self.trait_map.clone(), builtin_macro_kinds: self.builtin_macro_kinds.clone(), + lifetime_elision_allowed: self.lifetime_elision_allowed.clone(), }; ResolverOutputs { definitions, global_ctxt, ast_lowering } } |
