about summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering/src
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-04-25 05:04:32 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-04-25 05:04:32 +0000
commitff6fc757815055923e7f7ff73eaed8f9cbcfba75 (patch)
treebfd3766e077a0f447004b74063ad40ec02cd00e3 /compiler/rustc_ast_lowering/src
parentbed7caf20638dde1822553d432f6fe213baf4eae (diff)
parentcb3752d20e0f5d24348062211102a08d46fbecff (diff)
downloadrust-ff6fc757815055923e7f7ff73eaed8f9cbcfba75.tar.gz
rust-ff6fc757815055923e7f7ff73eaed8f9cbcfba75.zip
Merge from rustc
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs117
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs4
4 files changed, 103 insertions, 44 deletions
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f4d5e71bade..a1e5c275c18 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -49,7 +49,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::ResolverAstLowering;
+use rustc_middle::ty::{Asyncness, ResolverAstLowering};
 use rustc_span::{symbol::Ident, Span};
 use rustc_target::spec::abi;
 use std::iter;
@@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return false;
         };
         if let Some(local_sig_id) = sig_id.as_local() {
-            self.resolver.has_self.contains(&local_sig_id)
+            self.resolver.delegation_fn_sigs[&local_sig_id].has_self
         } else {
             match self.tcx.def_kind(sig_id) {
                 DefKind::Fn => false,
@@ -82,13 +82,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         delegation: &Delegation,
         item_id: NodeId,
     ) -> DelegationResults<'hir> {
-        let span = delegation.path.segments.last().unwrap().ident.span;
+        let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
         let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
         match sig_id {
             Ok(sig_id) => {
-                let decl = self.lower_delegation_decl(sig_id, span);
-                let sig = self.lower_delegation_sig(span, decl);
-                let body_id = self.lower_delegation_body(sig.decl, delegation);
+                let (param_count, c_variadic) = self.param_count(sig_id);
+                let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
+                let sig = self.lower_delegation_sig(sig_id, decl, span);
+                let body_id = self.lower_delegation_body(delegation, param_count, span);
 
                 let generics = self.lower_delegation_generics(span);
                 DelegationResults { body_id, sig, generics }
@@ -123,34 +124,47 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    // Function parameter count, including C variadic `...` if present.
+    fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
+        if let Some(local_sig_id) = sig_id.as_local() {
+            // Map may be filled incorrectly due to recursive delegation.
+            // Error will be emmited later during HIR ty lowering.
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => (sig.param_count, sig.c_variadic),
+                None => (0, false),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            (sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
+        }
+    }
+
     fn lower_delegation_decl(
         &mut self,
         sig_id: DefId,
-        param_span: Span,
+        param_count: usize,
+        c_variadic: bool,
+        span: Span,
     ) -> &'hir hir::FnDecl<'hir> {
-        let args_count = if let Some(local_sig_id) = sig_id.as_local() {
-            // Map may be filled incorrectly due to recursive delegation.
-            // Error will be emitted later during HIR ty lowering.
-            self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
-        } else {
-            self.tcx.fn_arg_names(sig_id).len()
-        };
-        let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty {
+        // The last parameter in C variadic functions is skipped in the signature,
+        // like during regular lowering.
+        let decl_param_count = param_count - c_variadic as usize;
+        let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
-            span: self.lower_span(param_span),
+            span,
         }));
 
         let output = self.arena.alloc(hir::Ty {
             hir_id: self.next_id(),
             kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
-            span: self.lower_span(param_span),
+            span,
         });
 
         self.arena.alloc(hir::FnDecl {
             inputs,
             output: hir::FnRetTy::Return(output),
-            c_variadic: false,
+            c_variadic,
             lifetime_elision_allowed: true,
             implicit_self: hir::ImplicitSelfKind::None,
         })
@@ -158,35 +172,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_delegation_sig(
         &mut self,
-        span: Span,
+        sig_id: DefId,
         decl: &'hir hir::FnDecl<'hir>,
+        span: Span,
     ) -> hir::FnSig<'hir> {
-        hir::FnSig {
-            decl,
-            header: hir::FnHeader {
-                unsafety: hir::Unsafety::Normal,
-                constness: hir::Constness::NotConst,
-                asyncness: hir::IsAsync::NotAsync,
-                abi: abi::Abi::Rust,
-            },
-            span: self.lower_span(span),
-        }
+        let header = if let Some(local_sig_id) = sig_id.as_local() {
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => self.lower_fn_header(sig.header),
+                None => self.generate_header_error(),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            let asyncness = match self.tcx.asyncness(sig_id) {
+                Asyncness::Yes => hir::IsAsync::Async(span),
+                Asyncness::No => hir::IsAsync::NotAsync,
+            };
+            hir::FnHeader {
+                unsafety: sig.unsafety,
+                constness: self.tcx.constness(sig_id),
+                asyncness,
+                abi: sig.abi,
+            }
+        };
+        hir::FnSig { decl, header, span }
     }
 
-    fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
+    fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) {
         let pat_node_id = self.next_node_id();
         let pat_id = self.lower_node_id(pat_node_id);
         let pat = self.arena.alloc(hir::Pat {
             hir_id: pat_id,
             kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
-            span: ty.span,
+            span,
             default_binding_modes: false,
         });
 
-        (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
+        (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
     }
 
-    fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
+    fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
         let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
             ident: Ident::empty(),
             hir_id: self.next_id(),
@@ -195,20 +219,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
             infer_args: false,
         }));
 
-        let path =
-            self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
+        let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
 
         hir::Expr {
             hir_id: self.next_id(),
             kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
-            span: ty.span,
+            span,
         }
     }
 
     fn lower_delegation_body(
         &mut self,
-        decl: &'hir hir::FnDecl<'hir>,
         delegation: &Delegation,
+        param_count: usize,
+        span: Span,
     ) -> BodyId {
         let path = self.lower_qpath(
             delegation.id,
@@ -224,8 +248,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let mut parameters: Vec<hir::Param<'_>> = Vec::new();
             let mut args: Vec<hir::Expr<'hir>> = Vec::new();
 
-            for (idx, param_ty) in decl.inputs.iter().enumerate() {
-                let (param, pat_node_id) = this.generate_param(param_ty);
+            for idx in 0..param_count {
+                let (param, pat_node_id) = this.generate_param(span);
                 parameters.push(param);
 
                 let arg = if let Some(block) = block
@@ -245,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 } else {
                     let pat_hir_id = this.lower_node_id(pat_node_id);
-                    this.generate_arg(param_ty, pat_hir_id)
+                    this.generate_arg(pat_hir_id, span)
                 };
                 args.push(arg);
             }
@@ -304,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             implicit_self: hir::ImplicitSelfKind::None,
         });
 
-        let sig = self.lower_delegation_sig(span, decl);
+        let header = self.generate_header_error();
+        let sig = hir::FnSig { decl, header, span };
+
         let body_id = self.lower_body(|this| {
             let expr =
                 hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
@@ -312,6 +338,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         });
         DelegationResults { generics, body_id, sig }
     }
+
+    fn generate_header_error(&self) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: hir::Unsafety::Normal,
+            constness: hir::Constness::NotConst,
+            asyncness: hir::IsAsync::NotAsync,
+            abi: abi::Abi::Rust,
+        }
+    }
 }
 
 struct SelfResolver<'a> {
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 6799513a323..6f70e135c72 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_yield_in_closure)]
+pub(crate) struct YieldInClosure {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
+    pub suggestion: Option<Span>,
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2305cc07795..5cc05d7336e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -8,6 +8,7 @@ use super::errors::{
 };
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use crate::errors::YieldInClosure;
 use crate::{FnDeclKind, ImplTraitPosition};
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
@@ -217,6 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         binder,
                         *capture_clause,
                         e.id,
+                        hir_id,
                         *constness,
                         *movability,
                         fn_decl,
@@ -955,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         constness: Const,
         movability: Movability,
         decl: &FnDecl,
@@ -965,8 +968,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
         let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
-            let mut coroutine_kind = None;
+            let mut coroutine_kind = if this
+                .attrs
+                .get(&closure_hir_id.local_id)
+                .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
+            {
+                Some(hir::CoroutineKind::Coroutine(Movability::Movable))
+            } else {
+                None
+            };
             let body_id = this.lower_fn_body(decl, |this| {
+                this.coroutine_kind = coroutine_kind;
                 let e = this.lower_expr_mut(body);
                 coroutine_kind = this.coroutine_kind;
                 e
@@ -1565,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     )
                     .emit();
                 }
+                let suggestion = self.current_item.map(|s| s.shrink_to_lo());
+                self.dcx().emit_err(YieldInClosure { span, suggestion });
                 self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
+
                 false
             }
         };
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e4c633aa324..dcce54d66c2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 body,
                 ..
             }) => {
-                self.with_new_scopes(ident.span, |this| {
+                self.with_new_scopes(*fn_sig_span, |this| {
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
@@ -1344,7 +1344,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
             hir::IsAsync::Async(span)
         } else {