Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions compiler/rustc_ast_lowering/src/expr/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use rustc_middle::span_bug;
use rustc_span::Span;

use super::{LoweringContext, MoveExprState};
use crate::FnDeclKind;
use crate::diagnostics::{ClosureCannotBeStatic, CoroutineTooManyParameters};
use crate::{DiscardParams, FnDeclKind};

impl<'hir> LoweringContext<'_, 'hir> {
// Entry point for `ExprKind::Closure`. Plain closures go through
Expand Down Expand Up @@ -132,6 +132,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder,
capture_clause,
closure_id,
expr_hir_id,
constness,
movability,
decl,
Expand All @@ -158,6 +159,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
closure_hir_id: HirId,
constness: Const,
movability: Movability,
decl: &FnDecl,
Expand Down Expand Up @@ -204,7 +206,14 @@ 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, closure_id, FnDeclKind::Closure, None);
let fn_decl = self.lower_fn_decl(
decl,
closure_id,
closure_hir_id,
FnDeclKind::Closure,
None,
DiscardParams::No,
);

let c = self.arena.alloc(hir::Closure {
def_id: closure_def_id,
Expand Down Expand Up @@ -327,7 +336,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = self.lower_fn_decl(&decl, closure_id, FnDeclKind::Closure, None);
let fn_decl = self.lower_fn_decl(
&decl,
closure_id,
closure_hir_id,
FnDeclKind::Closure,
None,
DiscardParams::No,
);

if let Const::Yes(span) = constness {
self.dcx().span_err(span, "const coroutines are not supported");
Expand Down
36 changes: 30 additions & 6 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use super::diagnostics::{
};
use super::stability::{enabled_names, gate_unstable_abi};
use super::{
FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
RelaxedBoundForbiddenReason, RelaxedBoundPolicy,
DiscardParams, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy,
};
use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly};

Expand Down Expand Up @@ -332,7 +332,14 @@ impl<'hir> LoweringContext<'_, 'hir> {

let itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, itctx, |this| {
this.lower_fn_decl(decl, id, FnDeclKind::Fn, coroutine_marker)
this.lower_fn_decl(
decl,
id,
hir_id,
FnDeclKind::Fn,
coroutine_marker,
if body.is_none() { DiscardParams::Yes } else { DiscardParams::No },
)
});
let sig = hir::FnSig {
decl,
Expand Down Expand Up @@ -741,7 +748,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| {
(
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(fdec, i.id, FnDeclKind::ExternFn, None),
// Parameters are discarded because foreign functions don't have a body
this.lower_fn_decl(
fdec,
i.id,
hir_id,
FnDeclKind::ExternFn,
None,
DiscardParams::Yes,
),
this.lower_fn_params_to_idents(fdec),
)
});
Expand Down Expand Up @@ -965,9 +980,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics,
sig,
i.id,
hir_id,
FnDeclKind::Trait,
sig.header.coroutine_marker,
attrs,
// Parameters are discarded for functions without a body
DiscardParams::Yes,
);
if define_opaque.is_some() {
self.dcx().span_err(
Expand Down Expand Up @@ -1005,9 +1023,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics,
sig,
i.id,
hir_id,
FnDeclKind::Trait,
sig.header.coroutine_marker,
attrs,
DiscardParams::No,
);
self.lower_define_opaque(hir_id, &define_opaque);
(
Expand Down Expand Up @@ -1215,9 +1235,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics,
sig,
i.id,
hir_id,
if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
sig.header.coroutine_marker,
attrs,
if body.is_none() { DiscardParams::Yes } else { DiscardParams::No },
);
self.lower_define_opaque(hir_id, &define_opaque);

Expand Down Expand Up @@ -1660,15 +1682,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
generics: &Generics,
sig: &FnSig,
id: NodeId,
node_id: NodeId,
hir_id: HirId,
kind: FnDeclKind,
coroutine_marker: Option<CoroutineMarker>,
attrs: &[hir::Attribute],
discard_params: DiscardParams,
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs);
let itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, itctx, |this| {
this.lower_fn_decl(&sig.decl, id, kind, coroutine_marker)
this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker, discard_params)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
Expand Down
45 changes: 38 additions & 7 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,14 @@ enum GenericArgsMode {
Silence,
}

#[derive(Debug, Copy, Clone)]
Comment thread
JonathanBrouwer marked this conversation as resolved.
enum DiscardParams {
/// Should be used for functions without a body. Lowers the attributes on the parameter and then discards them.
Yes,
/// Should be used for functions with a body. Does not lower the attributes, as lowering of the parameters is done by `lower_body`.
No,
}

impl<'hir> LoweringContext<'_, 'hir> {
fn create_def(
&mut self,
Expand Down Expand Up @@ -1597,14 +1605,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::TyKind::Path(path)
}
TyKind::FnPtr(f) => {
let hir_id = self.lower_node_id(t.id);
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy {
let kind = hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy {
generic_params,
safety: self.lower_safety(f.safety, hir::Safety::Safe),
abi: self.lower_extern(f.ext),
decl: self.lower_fn_decl(&f.decl, t.id, FnDeclKind::Pointer, None),
decl: self.lower_fn_decl(
&f.decl,
t.id,
hir_id,
FnDeclKind::Pointer,
None,
DiscardParams::Yes,
),
param_idents: self.lower_fn_params_to_idents(&f.decl),
}))
}));
return hir::Ty { kind, span: self.lower_span(t.span), hir_id };
}
TyKind::UnsafeBinder(f) => {
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
Expand Down Expand Up @@ -1952,18 +1969,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
///
/// `decl`: the unlowered (AST) function declaration.
///
/// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given
/// `NodeId`.
/// `fn_node_id`: Node Id of the function.
///
/// `fn_hir_id`: Hir Id of the function. Used for attribute parsing.
///
/// `kind`: The kind of function.
///
/// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is
/// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details.
/// `coro`: If the function is a coroutine, information about the coroutine.
///
/// `discard_params`: if `DiscardParams::Yes`, the parameters are lowered and then discarded. Set this to `DiscardParams::Yes`
/// for functions without bodies, as attributes on parameters are otherwise not validated.
/// Set this to `DiscardParams::No` for functions with bodies, as lowering of the parameters is done by `lower_body`.
#[instrument(level = "debug", skip(self))]
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_node_id: NodeId,
fn_hir_id: HirId,
kind: FnDeclKind,
coro: Option<CoroutineMarker>,
discard_params: DiscardParams,
) -> &'hir hir::FnDecl<'hir> {
let c_variadic = decl.c_variadic();
let mut splatted = decl.splatted();
Expand All @@ -1978,6 +2003,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
inputs = &inputs[..inputs.len() - 1];
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if let DiscardParams::Yes = discard_params {
// FIXME This uses `fn_hir_id`, which is not correct, it should use the parameter hir id instead
// The parameter is currently not lowered for functions without bodies, so there is no place to store the lowered hir id
// This should be fixed by storing function parameters in the `hir::FnSig` instead of `hir::Body`
self.lower_attrs(fn_hir_id, &param.attrs, param.span, Target::Param);
}
let itctx = match kind {
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => {
ImplTraitContext::Universal
Expand Down
2 changes: 2 additions & 0 deletions library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
#![feature(slice_shift)]
#![feature(slice_split_once)]
#![feature(sliceindex_wrappers)]
#![feature(splat)]
#![feature(split_array)]
#![feature(split_as_slice)]
#![feature(std_internals)]
Expand All @@ -132,6 +133,7 @@
#![feature(unsize)]
#![feature(unwrap_infallible)]
// tidy-alphabetical-end
#![allow(incomplete_features)]
#![allow(internal_features)]
#![deny(implicit_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]
Expand Down
24 changes: 24 additions & 0 deletions tests/ui/attributes/attrs-on-params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,28 @@ fn function(#[inline] param: u32) {
//~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes
}

trait Test {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it's worth duplicating the trait, type, and extern tests in the splat feature gate test, up to you.

https://github.com/rust-lang/rust/blob/ada41e1ce81819f01577c0ee40ccbd6fc41384e8/tests/ui/feature-gates/feature-gate-splat.rs

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not worth duplicating the test

fn meow(
#[rustc_splat] a1: u32,
//~^ ERROR the `rustc_splat` attribute is an experimental feature
);
fn meow2(
#[rustc_splat(invalid)] a4: u32,
//~^ ERROR the `rustc_splat` attribute is an experimental feature
//~| ERROR malformed `rustc_splat` attribute input
);
}

type Meow = fn(
#[rustc_splat] a1: u32,
//~^ ERROR the `rustc_splat` attribute is an experimental feature
);

extern "Rust" {
fn meow2(
#[rustc_splat] a1: u32,
//~^ ERROR the `rustc_splat` attribute is an experimental feature
);
}

fn main() {}
62 changes: 61 additions & 1 deletion tests/ui/attributes/attrs-on-params.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,65 @@ LL | fn function(#[inline] param: u32) {
|
= help: the `inline` attribute can only be applied to functions

error: aborting due to 2 previous errors
error[E0658]: the `rustc_splat` attribute is an experimental feature
--> $DIR/attrs-on-params.rs:10:11
|
LL | #[rustc_splat] a1: u32,
| ^^^^^^^^^^^
|
= note: see issue #153629 <https://github.com/rust-lang/rust/issues/153629> for more information
= help: add `#![feature(splat)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: the `rustc_splat` attribute is experimental

error[E0658]: the `rustc_splat` attribute is an experimental feature
--> $DIR/attrs-on-params.rs:14:11
|
LL | #[rustc_splat(invalid)] a4: u32,
| ^^^^^^^^^^^
|
= note: see issue #153629 <https://github.com/rust-lang/rust/issues/153629> for more information
= help: add `#![feature(splat)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: the `rustc_splat` attribute is experimental

error[E0565]: malformed `rustc_splat` attribute input
--> $DIR/attrs-on-params.rs:14:11
|
LL | #[rustc_splat(invalid)] a4: u32,
| ^^^^^^^^^^^---------
| |
| didn't expect any arguments here
|
help: must be of the form
|
LL - #[rustc_splat(invalid)] a4: u32,
LL + #[rustc_splat] a4: u32,
|

error[E0658]: the `rustc_splat` attribute is an experimental feature
--> $DIR/attrs-on-params.rs:21:7
|
LL | #[rustc_splat] a1: u32,
| ^^^^^^^^^^^
|
= note: see issue #153629 <https://github.com/rust-lang/rust/issues/153629> for more information
= help: add `#![feature(splat)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: the `rustc_splat` attribute is experimental

error[E0658]: the `rustc_splat` attribute is an experimental feature
--> $DIR/attrs-on-params.rs:27:11
|
LL | #[rustc_splat] a1: u32,
| ^^^^^^^^^^^
|
= note: see issue #153629 <https://github.com/rust-lang/rust/issues/153629> for more information
= help: add `#![feature(splat)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: the `rustc_splat` attribute is experimental

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0565, E0658.
For more information about an error, try `rustc --explain E0565`.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ extern "C" {
//~^ ERROR documentation comments cannot be applied to function
#[must_use]
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
//~| WARN cannot be used on function params
//~| WARN previously accepted
/// Baz
//~^ ERROR documentation comments cannot be applied to function
#[no_mangle] b: i32,
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
//~| WARN cannot be used on function params
//~| WARN previously accepted
);
}

Expand All @@ -24,10 +28,14 @@ type FnType = fn(
//~^ ERROR documentation comments cannot be applied to function
#[must_use]
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
//~| WARN cannot be used on function params
//~| WARN previously accepted
/// Baz
//~^ ERROR documentation comments cannot be applied to function
#[no_mangle] b: i32,
//~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
//~| WARN cannot be used on function params
//~| WARN previously accepted
);

pub fn foo(
Expand Down
Loading
Loading