-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
delegation: do not always generate first argument (pt. 1) #156798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b12acb0
474cf3a
376032f
72bdcbb
f75e1e6
eb94990
a51d4b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -56,7 +56,10 @@ use rustc_span::{Ident, Span, Symbol}; | |||||
| use smallvec::SmallVec; | ||||||
|
|
||||||
| use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults}; | ||||||
| use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee}; | ||||||
| use crate::errors::{ | ||||||
| CycleInDelegationSignatureResolution, DelegationAttemptedBlockWithDefsDeletion, | ||||||
| DelegationBlockSpecifiedWhenNoParams, UnresolvedDelegationCallee, | ||||||
| }; | ||||||
| use crate::{ | ||||||
| AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, | ||||||
| ResolverAstLoweringExt, | ||||||
|
|
@@ -122,9 +125,10 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); | ||||||
|
|
||||||
| // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356) | ||||||
| let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id) | ||||||
| let sig_id = if let Some(resolution_id) = | ||||||
| self.resolver.delegation_info(self.owner.def_id).and_then(|i| i.resolution_id) | ||||||
| { | ||||||
| self.get_sig_id(delegation_info.resolution_id, span) | ||||||
| self.get_sig_id(resolution_id, span) | ||||||
| } else { | ||||||
| self.dcx().span_delayed_bug( | ||||||
| span, | ||||||
|
|
@@ -142,11 +146,15 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
|
|
||||||
| let (param_count, c_variadic) = self.param_count(sig_id); | ||||||
|
|
||||||
| if !self.check_block_soundness(delegation, sig_id, is_method, param_count) { | ||||||
| return self.generate_delegation_error(span, delegation); | ||||||
| } | ||||||
|
|
||||||
| let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); | ||||||
|
|
||||||
| let (body_id, call_expr_id) = self.lower_delegation_body( | ||||||
| delegation, | ||||||
| is_method, | ||||||
| sig_id, | ||||||
| param_count, | ||||||
| &mut generics, | ||||||
| span, | ||||||
|
|
@@ -179,6 +187,48 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| fn check_block_soundness( | ||||||
| &self, | ||||||
| delegation: &Delegation, | ||||||
| sig_id: DefId, | ||||||
| is_method: bool, | ||||||
| param_count: usize, | ||||||
| ) -> bool { | ||||||
| let Some(block) = delegation.body.as_ref() else { return true }; | ||||||
|
|
||||||
| // Report an error if user has explicitly specified delegation's target expression | ||||||
| // in a single delegation when reused function has no params. | ||||||
| if param_count == 0 && matches!(delegation.source, DelegationSource::Single) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Otherwise we are missing e.g. a free function with zero params in a list. |
||||||
| self.dcx().emit_err(DelegationBlockSpecifiedWhenNoParams { span: block.span }); | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| // If there are definitions inside and we can't delete target expression, so report an error. | ||||||
| // FIXME(fn_delegation): support deletion of target expression with defs inside. | ||||||
| if !self.should_generate_block(delegation, sig_id, is_method) | ||||||
| && self | ||||||
| .resolver | ||||||
| .delegation_info(self.owner.def_id) | ||||||
| .is_some_and(|i| i.block_contains_defs) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it possible to detect this post-factum, instead of tracking things in advance through def collector? |
||||||
| { | ||||||
| self.dcx().emit_err(DelegationAttemptedBlockWithDefsDeletion { span: block.span }); | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| true | ||||||
| } | ||||||
|
|
||||||
| fn should_generate_block( | ||||||
| &self, | ||||||
| delegation: &Delegation, | ||||||
| sig_id: DefId, | ||||||
| is_method: bool, | ||||||
| ) -> bool { | ||||||
| is_method | ||||||
| || matches!(self.tcx.def_kind(sig_id), DefKind::Fn) | ||||||
| || matches!(delegation.source, DelegationSource::Single) | ||||||
| } | ||||||
|
|
||||||
| fn add_attrs_if_needed(&mut self, span: Span, sig_id: DefId) { | ||||||
| let new_attrs = | ||||||
| self.create_new_attrs(ATTRS_ADDITIONS, span, sig_id, self.attrs.get(&PARENT_ID)); | ||||||
|
|
@@ -243,9 +293,10 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| // it means that we refer to another delegation as a callee, so in order to obtain | ||||||
| // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it. | ||||||
| if let Some(local_id) = def_id.as_local() | ||||||
| && let Some(delegation_info) = self.resolver.delegation_info(local_id) | ||||||
| && let Some(resolution_id) = | ||||||
| self.resolver.delegation_info(local_id).and_then(|i| i.resolution_id) | ||||||
| { | ||||||
| def_id = delegation_info.resolution_id; | ||||||
| def_id = resolution_id; | ||||||
| if visited.contains(&def_id) { | ||||||
| // We encountered a cycle in the resolution, or delegation callee refers to non-existent | ||||||
| // entity, in this case emit an error. | ||||||
|
|
@@ -397,7 +448,7 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| fn lower_delegation_body( | ||||||
| &mut self, | ||||||
| delegation: &Delegation, | ||||||
| is_method: bool, | ||||||
| sig_id: DefId, | ||||||
| param_count: usize, | ||||||
| generics: &mut GenericsGenerationResults<'hir>, | ||||||
| span: Span, | ||||||
|
|
@@ -409,12 +460,15 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| let mut parameters: Vec<hir::Param<'_>> = Vec::with_capacity(param_count); | ||||||
| let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count); | ||||||
|
|
||||||
| let is_method = this.is_method(sig_id, span); | ||||||
|
|
||||||
| for idx in 0..param_count { | ||||||
| let (param, pat_node_id) = this.generate_param(is_method, idx, span); | ||||||
| parameters.push(param); | ||||||
|
|
||||||
| let arg = if let Some(block) = block | ||||||
| && idx == 0 | ||||||
| && this.should_generate_block(delegation, sig_id, is_method) | ||||||
| { | ||||||
| let mut self_resolver = SelfResolver { | ||||||
| ctxt: this, | ||||||
|
|
@@ -431,17 +485,6 @@ impl<'hir> LoweringContext<'_, 'hir> { | |||||
| args.push(arg); | ||||||
| } | ||||||
|
|
||||||
| // If we have no params in signature function but user still wrote some code in | ||||||
| // delegation body, then add this code as first arg, eventually an error will be shown, | ||||||
| // also nested delegations may need to access information about this code (#154332), | ||||||
| // so it is better to leave this code as opposed to bodies of extern functions, | ||||||
| // which are completely erased from existence. | ||||||
| if param_count == 0 | ||||||
| && let Some(block) = block | ||||||
| { | ||||||
| args.push(this.lower_target_expr(&block)); | ||||||
| } | ||||||
|
|
||||||
| let (final_expr, hir_id) = | ||||||
| this.finalize_body_lowering(delegation, args, generics, span); | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,9 +9,9 @@ use std::sync::Arc; | |||||
|
|
||||||
| use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; | ||||||
| use rustc_ast::{ | ||||||
| self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, Fn, | ||||||
| ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, | ||||||
| TyAlias, | ||||||
| self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, | ||||||
| DelegationSource, Fn, ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, | ||||||
| StmtKind, TraitAlias, TyAlias, | ||||||
| }; | ||||||
| use rustc_attr_parsing::AttributeParser; | ||||||
| use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; | ||||||
|
|
@@ -1461,7 +1461,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { | |||||
| let parent = self.parent_scope.module.expect_local(); | ||||||
| let expansion = self.parent_scope.expansion; | ||||||
| self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); | ||||||
| } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) | ||||||
| } else if !matches!(&item.kind, AssocItemKind::Delegation(d) if matches!(d.source, DelegationSource::Glob)) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| && ident.name != kw::Underscore | ||||||
| { | ||||||
| // Don't add underscore names, they cannot be looked up anyway. | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to #157248 (comment) this is sub-optimal from error recovery / diagnostics point of view, but that's not a first concern right now.
View changes since the review