Auto merge of #131980 - matthiaskrgr:rollup-iy5nw71, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #131814 (`optimize` attribute applied to things other than methods/functions/c…)
 - #131927 (Check for filecheck directives in files marked `skip-filecheck`)
 - #131967 (Remove `lower_mono_bounds`)
 - #131973 (fix(rustdoc-json-types): document rustc-hash feature)
 - #131976 (feat(rustdoc-json-types): mark simple enums as copy)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-20 21:40:21 +00:00
commit 7ed1a51b25
15 changed files with 160 additions and 123 deletions

View File

@ -13,6 +13,7 @@
use super::ItemCtxt; use super::ItemCtxt;
use super::predicates_of::assert_only_contains_predicates_from; use super::predicates_of::assert_only_contains_predicates_from;
use crate::bounds::Bounds;
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
/// For associated types we include both bounds written on the type /// For associated types we include both bounds written on the type
@ -36,7 +37,8 @@ fn associated_type_bounds<'tcx>(
); );
let icx = ItemCtxt::new(tcx, assoc_item_def_id); let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter); let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Associated types are implicitly sized unless a `?Sized` bound is found // Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
@ -303,7 +305,8 @@ fn opaque_type_bounds<'tcx>(
) -> &'tcx [(ty::Clause<'tcx>, Span)] { ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_reduced_queries!({ ty::print::with_reduced_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id); let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.lowerer().lower_mono_bounds(item_ty, hir_bounds, filter); let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found // Opaque types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
debug!(?bounds); debug!(?bounds);

View File

@ -181,9 +181,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// on a trait we must also consider the bounds that follow the trait's name, // on a trait we must also consider the bounds that follow the trait's name,
// like `trait Foo: A + B + C`. // like `trait Foo: A + B + C`.
if let Some(self_bounds) = is_trait { if let Some(self_bounds) = is_trait {
let bounds = icx.lowerer().lower_mono_bounds( let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(
tcx.types.self_param, tcx.types.self_param,
self_bounds, self_bounds,
&mut bounds,
ty::List::empty(),
PredicateFilter::All, PredicateFilter::All,
); );
predicates.extend(bounds.clauses(tcx)); predicates.extend(bounds.clauses(tcx));
@ -265,9 +268,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
} }
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
icx.lowerer().lower_poly_bounds( icx.lowerer().lower_bounds(
ty, ty,
bound_pred.bounds.iter(), bound_pred.bounds,
&mut bounds, &mut bounds,
bound_vars, bound_vars,
PredicateFilter::All, PredicateFilter::All,
@ -626,7 +629,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
bug!("trait_def_id {trait_def_id:?} is not an item"); bug!("trait_def_id {trait_def_id:?} is not an item");
}; };
let (generics, bounds) = match item.kind { let (generics, superbounds) = match item.kind {
hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
_ => span_bug!(item.span, "super_predicates invoked on non-trait"), _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
@ -635,7 +638,8 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
let icx = ItemCtxt::new(tcx, trait_def_id); let icx = ItemCtxt::new(tcx, trait_def_id);
let self_param_ty = tcx.types.self_param; let self_param_ty = tcx.types.self_param;
let superbounds = icx.lowerer().lower_mono_bounds(self_param_ty, bounds, filter); let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics( let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(
generics, generics,
@ -646,7 +650,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
// Combine the two lists to form the complete set of superbounds: // Combine the two lists to form the complete set of superbounds:
let implied_bounds = let implied_bounds =
&*tcx.arena.alloc_from_iter(superbounds.clauses(tcx).chain(where_bounds_that_match)); &*tcx.arena.alloc_from_iter(bounds.clauses(tcx).chain(where_bounds_that_match));
debug!(?implied_bounds); debug!(?implied_bounds);
// Now require that immediate supertraits are lowered, which will, in // Now require that immediate supertraits are lowered, which will, in
@ -834,9 +838,9 @@ fn probe_ty_param_bounds_in_generics(
}; };
let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
self.lowerer().lower_poly_bounds( self.lowerer().lower_bounds(
bound_ty, bound_ty,
predicate.bounds.iter(), predicate.bounds,
&mut bounds, &mut bounds,
bound_vars, bound_vars,
filter, filter,

View File

@ -142,7 +142,7 @@ pub(crate) fn add_sized_bound(
/// There is an implied binder around `param_ty` and `hir_bounds`. /// There is an implied binder around `param_ty` and `hir_bounds`.
/// See `lower_poly_trait_ref` for more details. /// See `lower_poly_trait_ref` for more details.
#[instrument(level = "debug", skip(self, hir_bounds, bounds))] #[instrument(level = "debug", skip(self, hir_bounds, bounds))]
pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'tcx>>>( pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<'tcx>>>(
&self, &self,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
hir_bounds: I, hir_bounds: I,
@ -212,35 +212,6 @@ pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound
} }
} }
/// Lower HIR bounds into `bounds` given the self type `param_ty` and *no* overarching late-bound vars.
///
/// ### Example
///
/// ```ignore (illustrative)
/// fn foo<T: Bar + Baz>() { }
/// // ^ ^^^^^^^^^ hir_bounds
/// // param_ty
/// ```
pub(crate) fn lower_mono_bounds(
&self,
param_ty: Ty<'tcx>,
hir_bounds: &[hir::GenericBound<'tcx>],
predicate_filter: PredicateFilter,
) -> Bounds<'tcx> {
let mut bounds = Bounds::default();
self.lower_poly_bounds(
param_ty,
hir_bounds.iter(),
&mut bounds,
ty::List::empty(),
predicate_filter,
);
debug!(?bounds);
bounds
}
/// Lower an associated item constraint from the HIR into `bounds`. /// Lower an associated item constraint from the HIR into `bounds`.
/// ///
/// ### A Note on Binders /// ### A Note on Binders
@ -444,9 +415,9 @@ pub(super) fn lower_assoc_item_constraint(
// parameter to have a skipped binder. // parameter to have a skipped binder.
let param_ty = let param_ty =
Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
self.lower_poly_bounds( self.lower_bounds(
param_ty, param_ty,
hir_bounds.iter(), hir_bounds,
bounds, bounds,
projection_ty.bound_vars(), projection_ty.bound_vars(),
predicate_filter, predicate_filter,

View File

@ -553,9 +553,9 @@ passes_only_has_effect_on =
*[unspecified] (unspecified--this is a compiler bug) *[unspecified] (unspecified--this is a compiler bug)
} }
passes_optimize_not_fn_or_closure = passes_optimize_invalid_target =
attribute should be applied to function or closure attribute applied to an invalid target
.label = not a function or closure .label = invalid target
passes_outer_crate_level_attr = passes_outer_crate_level_attr =
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`

View File

@ -124,7 +124,7 @@ fn check_attributes(
} }
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
[sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target),
[sym::optimize, ..] => self.check_optimize(hir_id, attr, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
[sym::no_sanitize, ..] => { [sym::no_sanitize, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr, span, target) self.check_applied_to_fn_or_method(hir_id, attr, span, target)
} }
@ -433,23 +433,19 @@ fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) {
/// Checks that `#[optimize(..)]` is applied to a function/closure/method, /// Checks that `#[optimize(..)]` is applied to a function/closure/method,
/// or to an impl block or module. /// or to an impl block or module.
// FIXME(#128488): this should probably be elevated to an error? fn check_optimize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) { let is_valid = matches!(
match target { target,
Target::Fn Target::Fn
| Target::Closure | Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl );
| Target::Mod => {} if !is_valid {
self.dcx().emit_err(errors::OptimizeInvalidTarget {
_ => { attr_span: attr.span,
self.tcx.emit_node_span_lint( defn_span: span,
UNUSED_ATTRIBUTES, on_crate: hir_id == CRATE_HIR_ID,
hir_id, });
attr.span,
errors::OptimizeNotFnOrClosure,
);
}
} }
} }

View File

@ -76,9 +76,15 @@ pub(crate) struct CoverageNotFnOrClosure {
pub defn_span: Span, pub defn_span: Span,
} }
#[derive(LintDiagnostic)] #[derive(Diagnostic)]
#[diag(passes_optimize_not_fn_or_closure)] #[diag(passes_optimize_invalid_target)]
pub(crate) struct OptimizeNotFnOrClosure; pub(crate) struct OptimizeInvalidTarget {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
pub on_crate: bool,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn)] #[diag(passes_should_be_applied_to_fn)]

View File

@ -2,6 +2,18 @@
//! //!
//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`] //! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
//! struct is the root of the JSON blob and all other items are contained within. //! struct is the root of the JSON blob and all other items are contained within.
//!
//! We expose a `rustc-hash` feature that is disabled by default. This feature switches the
//! [`std::collections::HashMap`] for [`rustc_hash::FxHashMap`] to improve the performance of said
//! `HashMap` in specific situations.
//!
//! `cargo-semver-checks` for example, saw a [-3% improvement][1] when benchmarking using the
//! `aws_sdk_ec2` JSON output (~500MB of JSON). As always, we recommend measuring the impact before
//! turning this feature on, as [`FxHashMap`][2] only concerns itself with hash speed, and may
//! increase the number of collisions.
//!
//! [1]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/rustc-hash.20and.20performance.20of.20rustdoc-types/near/474855731
//! [2]: https://crates.io/crates/rustc-hash
#[cfg(not(feature = "rustc-hash"))] #[cfg(not(feature = "rustc-hash"))]
use std::collections::HashMap; use std::collections::HashMap;
@ -305,10 +317,10 @@ pub enum AssocItemConstraintKind {
// FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types. // FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types.
pub struct Id(pub u32); pub struct Id(pub u32);
/// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any aditional info. /// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any additional info.
/// ///
/// Part of [`ItemSummary`]. /// Part of [`ItemSummary`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ItemKind { pub enum ItemKind {
/// A module declaration, e.g. `mod foo;` or `mod foo {}` /// A module declaration, e.g. `mod foo;` or `mod foo {}`
@ -698,7 +710,7 @@ pub enum Abi {
Aapcs { unwind: bool }, Aapcs { unwind: bool },
/// Can be specified as `extern "win64"`. /// Can be specified as `extern "win64"`.
Win64 { unwind: bool }, Win64 { unwind: bool },
/// Can be specifed as `extern "sysv64"`. /// Can be specified as `extern "sysv64"`.
SysV64 { unwind: bool }, SysV64 { unwind: bool },
/// Can be specified as `extern "system"`. /// Can be specified as `extern "system"`.
System { unwind: bool }, System { unwind: bool },
@ -892,7 +904,7 @@ pub enum GenericBound {
} }
/// A set of modifiers applied to a trait. /// A set of modifiers applied to a trait.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum TraitBoundModifier { pub enum TraitBoundModifier {
/// Marks the absence of a modifier. /// Marks the absence of a modifier.
@ -996,7 +1008,7 @@ pub enum Type {
QualifiedPath { QualifiedPath {
/// The name of the associated type in the parent type. /// The name of the associated type in the parent type.
/// ///
/// ```ignore (incomplete expresssion) /// ```ignore (incomplete expression)
/// <core::array::IntoIter<u32, 42> as Iterator>::Item /// <core::array::IntoIter<u32, 42> as Iterator>::Item
/// // ^^^^ /// // ^^^^
/// ``` /// ```
@ -1083,7 +1095,7 @@ pub struct FunctionSignature {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Trait { pub struct Trait {
/// Whether the trait is marked `auto` and is thus implemented automatically /// Whether the trait is marked `auto` and is thus implemented automatically
/// for all aplicable types. /// for all applicable types.
pub is_auto: bool, pub is_auto: bool,
/// Whether the trait is marked as `unsafe`. /// Whether the trait is marked as `unsafe`.
pub is_unsafe: bool, pub is_unsafe: bool,
@ -1193,7 +1205,7 @@ pub struct ProcMacro {
} }
/// The way a [`ProcMacro`] is declared to be used. /// The way a [`ProcMacro`] is declared to be used.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum MacroKind { pub enum MacroKind {
/// A bang macro `foo!()`. /// A bang macro `foo!()`.

View File

@ -129,6 +129,9 @@ pub fn files_for_miropt_test(
out.push(MiroptTestFile { expected_file, from_file, to_file }); out.push(MiroptTestFile { expected_file, from_file, to_file });
} }
if !run_filecheck && l.trim_start().starts_with("// CHECK") {
panic!("error: test contains filecheck directive but is marked `skip-filecheck`");
}
} }
MiroptTest { run_filecheck, suffix, files: out, passes } MiroptTest { run_filecheck, suffix, files: out, passes }

View File

@ -1,4 +1,3 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//! Tests that we can propagate into places that are projections into unions //! Tests that we can propagate into places that are projections into unions
//@ compile-flags: -Zunsound-mir-opts -C debuginfo=full //@ compile-flags: -Zunsound-mir-opts -C debuginfo=full
@ -8,7 +7,7 @@ fn val() -> u32 {
// EMIT_MIR union.main.DestinationPropagation.diff // EMIT_MIR union.main.DestinationPropagation.diff
fn main() { fn main() {
// CHECK-LABEL: fn args( // CHECK-LABEL: fn main(
// CHECK: {{_.*}} = Un { us: const 1_u32 }; // CHECK: {{_.*}} = Un { us: const 1_u32 };
union Un { union Un {
us: u32, us: u32,

View File

@ -1,4 +1,3 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
// This test is a mirror of codegen/issue-59352.rs. // This test is a mirror of codegen/issue-59352.rs.
// The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case

View File

@ -3,11 +3,13 @@
#![deny(unused_attributes)] #![deny(unused_attributes)]
#![allow(dead_code)] #![allow(dead_code)]
#[optimize(speed)] //~ ERROR attribute should be applied to function or closure //@ edition: 2018
#[optimize(speed)] //~ ERROR attribute applied to an invalid target
struct F; struct F;
fn invalid() { fn invalid() {
#[optimize(speed)] //~ ERROR attribute should be applied to function or closure #[optimize(speed)] //~ ERROR attribute applied to an invalid target
{ {
1 1
}; };
@ -16,13 +18,25 @@ fn invalid() {
#[optimize(speed)] #[optimize(speed)]
fn valid() {} fn valid() {}
#[optimize(speed)] #[optimize(speed)] //~ ERROR attribute applied to an invalid target
mod valid_module {} mod valid_module {}
#[optimize(speed)] #[optimize(speed)] //~ ERROR attribute applied to an invalid target
impl F {} impl F {}
fn main() { fn main() {
let _ = #[optimize(speed)] let _ = #[optimize(speed)]
(|| 1); (|| 1);
} }
use std::future::Future;
fn async_block() -> impl Future<Output = ()> {
#[optimize(speed)]
async { }
}
#[optimize(speed)]
async fn async_fn() {
()
}

View File

@ -1,20 +1,36 @@
error: attribute should be applied to function or closure error: attribute applied to an invalid target
--> $DIR/optimize.rs:6:1 --> $DIR/optimize.rs:8:1
| |
LL | #[optimize(speed)] LL | #[optimize(speed)]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
| LL | struct F;
note: the lint level is defined here | --------- invalid target
--> $DIR/optimize.rs:3:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: attribute should be applied to function or closure error: attribute applied to an invalid target
--> $DIR/optimize.rs:10:5 --> $DIR/optimize.rs:12:5
| |
LL | #[optimize(speed)] LL | #[optimize(speed)]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
LL | / {
LL | | 1
LL | | };
| |_____- invalid target
error: aborting due to 2 previous errors error: attribute applied to an invalid target
--> $DIR/optimize.rs:21:1
|
LL | #[optimize(speed)]
| ^^^^^^^^^^^^^^^^^^
LL | mod valid_module {}
| ------------------- invalid target
error: attribute applied to an invalid target
--> $DIR/optimize.rs:24:1
|
LL | #[optimize(speed)]
| ^^^^^^^^^^^^^^^^^^
LL | impl F {}
| --------- invalid target
error: aborting due to 4 previous errors

View File

@ -0,0 +1,40 @@
//@ edition: 2024
//@ compile-flags: -Zunstable-options
//@ run-pass
#![feature(gen_blocks)]
#![feature(optimize_attribute)]
#![feature(stmt_expr_attributes)]
#![feature(async_iterator)]
#![allow(dead_code)]
// make sure that other attributes e.g. `optimize` can be applied to gen blocks and functions
fn main() { }
fn optimize_gen_block() -> impl Iterator<Item = ()> {
#[optimize(speed)]
gen { yield (); }
}
#[optimize(speed)]
gen fn optimize_gen_fn() -> i32 {
yield 1;
yield 2;
yield 3;
}
#[optimize(speed)]
async gen fn optimize_async_gen_fn() -> i32 {
yield 1;
yield 2;
yield 3;
}
use std::async_iter::AsyncIterator;
pub fn deduce() -> impl AsyncIterator<Item = ()> {
#[optimize(size)]
async gen {
yield ();
}
}

View File

@ -1,8 +1,4 @@
#![crate_type="rlib"] #![crate_type="rlib"]
#![optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature
#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature
mod module {
#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature #[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature
fn size() {} fn size() {}
@ -14,5 +10,3 @@ fn speed() {}
//~^ ERROR the `#[optimize]` attribute is an experimental feature //~^ ERROR the `#[optimize]` attribute is an experimental feature
//~| ERROR E0722 //~| ERROR E0722
fn not_known() {} fn not_known() {}
}

View File

@ -1,15 +1,5 @@
error[E0658]: the `#[optimize]` attribute is an experimental feature error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:2:1 --> $DIR/feature-gate-optimize_attribute.rs:3:1
|
LL | #![optimize(speed)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/54882> for more information
= help: add `#![feature(optimize_attribute)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:4:1
| |
LL | #[optimize(size)] LL | #[optimize(size)]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
@ -19,17 +9,7 @@ LL | #[optimize(size)]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[optimize]` attribute is an experimental feature error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:7:1 --> $DIR/feature-gate-optimize_attribute.rs:6:1
|
LL | #[optimize(size)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #54882 <https://github.com/rust-lang/rust/issues/54882> for more information
= help: add `#![feature(optimize_attribute)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:10:1
| |
LL | #[optimize(speed)] LL | #[optimize(speed)]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
@ -39,7 +19,7 @@ LL | #[optimize(speed)]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: the `#[optimize]` attribute is an experimental feature error[E0658]: the `#[optimize]` attribute is an experimental feature
--> $DIR/feature-gate-optimize_attribute.rs:13:1 --> $DIR/feature-gate-optimize_attribute.rs:9:1
| |
LL | #[optimize(banana)] LL | #[optimize(banana)]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -49,12 +29,12 @@ LL | #[optimize(banana)]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0722]: invalid argument error[E0722]: invalid argument
--> $DIR/feature-gate-optimize_attribute.rs:13:12 --> $DIR/feature-gate-optimize_attribute.rs:9:12
| |
LL | #[optimize(banana)] LL | #[optimize(banana)]
| ^^^^^^ | ^^^^^^
error: aborting due to 6 previous errors error: aborting due to 4 previous errors
Some errors have detailed explanations: E0658, E0722. Some errors have detailed explanations: E0658, E0722.
For more information about an error, try `rustc --explain E0658`. For more information about an error, try `rustc --explain E0658`.