Auto merge of #139949 - matthiaskrgr:rollup-pxc5tsx, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #138632 (Stabilize `cfg_boolean_literals`)
 - #139416 (unstable book; document `macro_metavar_expr_concat`)
 - #139782 (Consistent with treating Ctor Call as Struct in liveness analysis)
 - #139885 (document RUSTC_BOOTSTRAP, RUSTC_OVERRIDE_VERSION_STRING, and -Z allow-features in the unstable book)
 - #139904 (Explicitly annotate edition for `unpretty=expanded` and `unpretty=hir` tests)
 - #139932 (transmutability: Refactor tests for simplicity)
 - #139944 (Move eager translation to a method on Diag)
 - #139948 (git: ignore `60600a6fa4` for blame purposes)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-17 11:21:54 +00:00
commit 883f9f72e8
240 changed files with 1038 additions and 978 deletions

View file

@ -31,3 +31,5 @@ ec2cc761bc7067712ecc7734502f703fe3b024c8
c682aa162b0d41e21cc6748f4fecfe01efb69d1f c682aa162b0d41e21cc6748f4fecfe01efb69d1f
# reformat with updated edition 2024 # reformat with updated edition 2024
1fcae03369abb4c2cc180cd5a49e1f4440a81300 1fcae03369abb4c2cc180cd5a49e1f4440a81300
# Breaking up of compiletest runtest.rs
60600a6fa403216bfd66e04f948b1822f6450af7

View file

@ -2,7 +2,7 @@
use rustc_ast::ParamKindOrd; use rustc_ast::ParamKindOrd;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol}; use rustc_span::{Ident, Span, Symbol};
@ -394,11 +394,7 @@ pub(crate) struct EmptyLabelManySpans(pub Vec<Span>);
// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each // The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
impl Subdiagnostic for EmptyLabelManySpans { impl Subdiagnostic for EmptyLabelManySpans {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
diag.span_labels(self.0, ""); diag.span_labels(self.0, "");
} }
} }
@ -749,11 +745,7 @@ pub(crate) struct StableFeature {
} }
impl Subdiagnostic for StableFeature { impl Subdiagnostic for StableFeature {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
diag.arg("name", self.name); diag.arg("name", self.name);
diag.arg("since", self.since); diag.arg("since", self.since);
diag.help(fluent::ast_passes_stable_since); diag.help(fluent::ast_passes_stable_since);

View file

@ -7,7 +7,6 @@ use rustc_session::config::ExpectedValues;
use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::lint::builtin::UNEXPECTED_CFGS;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::symbol::kw;
use rustc_span::{Span, Symbol, sym}; use rustc_span::{Span, Symbol, sym};
use crate::session_diagnostics::{self, UnsupportedLiteralReason}; use crate::session_diagnostics::{self, UnsupportedLiteralReason};
@ -89,20 +88,6 @@ pub fn eval_condition(
let cfg = match cfg { let cfg = match cfg {
MetaItemInner::MetaItem(meta_item) => meta_item, MetaItemInner::MetaItem(meta_item) => meta_item,
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
if let Some(features) = features {
// we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
// and `true`, and we want to keep the former working without feature gate
gate_cfg(
&(
if *b { kw::True } else { kw::False },
sym::cfg_boolean_literals,
|features: &Features| features.cfg_boolean_literals(),
),
cfg.span(),
sess,
features,
);
}
return *b; return *b;
} }
_ => { _ => {

View file

@ -1,7 +1,7 @@
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
SubdiagMessageOp, Subdiagnostic, Subdiagnostic,
}; };
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol}; use rustc_span::{Ident, Span, Symbol};
@ -684,13 +684,9 @@ pub(crate) struct FormatUnusedArg {
// Allow the singular form to be a subdiagnostic of the multiple-unused // Allow the singular form to be a subdiagnostic of the multiple-unused
// form of diagnostic. // form of diagnostic.
impl Subdiagnostic for FormatUnusedArg { impl Subdiagnostic for FormatUnusedArg {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
diag.arg("named", self.named); diag.arg("named", self.named);
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg);
diag.span_label(self.span, msg); diag.span_label(self.span, msg);
} }
} }

View file

@ -6,7 +6,7 @@ use rustc_abi::WrappingRange;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
MultiSpan, SubdiagMessageOp, Subdiagnostic, MultiSpan, Subdiagnostic,
}; };
use rustc_hir::ConstContext; use rustc_hir::ConstContext;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@ -290,11 +290,7 @@ pub struct FrameNote {
} }
impl Subdiagnostic for FrameNote { impl Subdiagnostic for FrameNote {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
diag.arg("times", self.times); diag.arg("times", self.times);
diag.arg("where_", self.where_); diag.arg("where_", self.where_);
diag.arg("instance", self.instance); diag.arg("instance", self.instance);
@ -302,7 +298,7 @@ impl Subdiagnostic for FrameNote {
if self.has_label && !self.span.is_dummy() { if self.has_label && !self.span.is_dummy() {
span.push_span_label(self.span, fluent::const_eval_frame_note_last); span.push_span_label(self.span, fluent::const_eval_frame_note_last);
} }
let msg = f(diag, fluent::const_eval_frame_note.into()); let msg = diag.eagerly_translate(fluent::const_eval_frame_note);
diag.span_note(span, msg); diag.span_note(span, msg);
} }
} }

View file

@ -181,22 +181,9 @@ where
Self: Sized, Self: Sized,
{ {
/// Add a subdiagnostic to an existing diagnostic. /// Add a subdiagnostic to an existing diagnostic.
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
self.add_to_diag_with(diag, &|_, m| m);
}
/// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
/// (to optionally perform eager translation).
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
f: &F,
);
} }
pub trait SubdiagMessageOp<G: EmissionGuarantee> =
Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage;
/// Trait implemented by lint types. This should not be implemented manually. Instead, use /// Trait implemented by lint types. This should not be implemented manually. Instead, use
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
#[rustc_diagnostic_item = "LintDiagnostic"] #[rustc_diagnostic_item = "LintDiagnostic"]
@ -1227,15 +1214,21 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
/// interpolated variables). /// interpolated variables).
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]
pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self { pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
let dcx = self.dcx; subdiagnostic.add_to_diag(self);
subdiagnostic.add_to_diag_with(self, &|diag, msg| {
let args = diag.args.iter();
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
dcx.eagerly_translate(msg, args)
});
self self
} }
/// Fluent variables are not namespaced from each other, so when
/// `Diagnostic`s and `Subdiagnostic`s use the same variable name,
/// one value will clobber the other. Eagerly translating the
/// diagnostic uses the variables defined right then, before the
/// clobbering occurs.
pub fn eagerly_translate(&self, msg: impl Into<SubdiagMessage>) -> SubdiagMessage {
let args = self.args.iter();
let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into());
self.dcx.eagerly_translate(msg, args)
}
with_fn! { with_span, with_fn! { with_span,
/// Add a span. /// Add a span.
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]

View file

@ -19,7 +19,7 @@ use {rustc_ast as ast, rustc_hir as hir};
use crate::diagnostic::DiagLocation; use crate::diagnostic::DiagLocation;
use crate::{ use crate::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level,
SubdiagMessageOp, Subdiagnostic, fluent_generated as fluent, Subdiagnostic, fluent_generated as fluent,
}; };
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display); pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
@ -384,11 +384,7 @@ pub struct SingleLabelManySpans {
pub label: &'static str, pub label: &'static str,
} }
impl Subdiagnostic for SingleLabelManySpans { impl Subdiagnostic for SingleLabelManySpans {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
diag.span_labels(self.spans, self.label); diag.span_labels(self.spans, self.label);
} }
} }

View file

@ -47,7 +47,7 @@ pub use codes::*;
pub use diagnostic::{ pub use diagnostic::{
BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString, BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString,
Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag, Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag,
SubdiagMessageOp, Subdiagnostic, Subdiagnostic,
}; };
pub use diagnostic_impls::{ pub use diagnostic_impls::{
DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,

View file

@ -95,6 +95,8 @@ declare_features! (
(accepted, c_unwind, "1.81.0", Some(74990)), (accepted, c_unwind, "1.81.0", Some(74990)),
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
(accepted, cfg_attr_multi, "1.33.0", Some(54881)), (accepted, cfg_attr_multi, "1.33.0", Some(54881)),
/// Allows the use of `#[cfg(<true/false>)]`.
(accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)),
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
(accepted, cfg_doctest, "1.40.0", Some(62210)), (accepted, cfg_doctest, "1.40.0", Some(62210)),
/// Enables `#[cfg(panic = "...")]` config key. /// Enables `#[cfg(panic = "...")]` config key.

View file

@ -391,8 +391,6 @@ declare_features! (
(unstable, async_trait_bounds, "1.85.0", Some(62290)), (unstable, async_trait_bounds, "1.85.0", Some(62290)),
/// Allows using C-variadics. /// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)), (unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg(<true/false>)]`.
(unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled. /// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
(unstable, cfg_contract_checks, "1.86.0", Some(128044)), (unstable, cfg_contract_checks, "1.86.0", Some(128044)),
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.

View file

@ -5,7 +5,7 @@ use std::borrow::Cow;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg, MultiSpan, Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg, MultiSpan,
SubdiagMessageOp, Subdiagnostic, Subdiagnostic,
}; };
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
@ -270,11 +270,7 @@ pub(crate) struct SuggestAnnotations {
pub suggestions: Vec<SuggestAnnotation>, pub suggestions: Vec<SuggestAnnotation>,
} }
impl Subdiagnostic for SuggestAnnotations { impl Subdiagnostic for SuggestAnnotations {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
if self.suggestions.is_empty() { if self.suggestions.is_empty() {
return; return;
} }
@ -337,11 +333,7 @@ pub(crate) struct TypeMismatchFruTypo {
} }
impl Subdiagnostic for TypeMismatchFruTypo { impl Subdiagnostic for TypeMismatchFruTypo {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
// Only explain that `a ..b` is a range if it's split up // Only explain that `a ..b` is a range if it's split up
@ -599,11 +591,7 @@ pub(crate) struct RemoveSemiForCoerce {
} }
impl Subdiagnostic for RemoveSemiForCoerce { impl Subdiagnostic for RemoveSemiForCoerce {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let mut multispan: MultiSpan = self.semi.into(); let mut multispan: MultiSpan = self.semi.into();
multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret);
@ -778,20 +766,16 @@ pub(crate) enum CastUnknownPointerSub {
} }
impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
match self { match self {
CastUnknownPointerSub::To(span) => { CastUnknownPointerSub::To(span) => {
let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); let msg = diag.eagerly_translate(fluent::hir_typeck_label_to);
diag.span_label(span, msg); diag.span_label(span, msg);
let msg = f(diag, crate::fluent_generated::hir_typeck_note); let msg = diag.eagerly_translate(fluent::hir_typeck_note);
diag.note(msg); diag.note(msg);
} }
CastUnknownPointerSub::From(span) => { CastUnknownPointerSub::From(span) => {
let msg = f(diag, crate::fluent_generated::hir_typeck_label_from); let msg = diag.eagerly_translate(fluent::hir_typeck_label_from);
diag.span_label(span, msg); diag.span_label(span, msg);
} }
} }

View file

@ -1,5 +1,5 @@
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level; use rustc_session::lint::Level;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
@ -26,11 +26,7 @@ pub(crate) enum OverruledAttributeSub {
} }
impl Subdiagnostic for OverruledAttributeSub { impl Subdiagnostic for OverruledAttributeSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
OverruledAttributeSub::DefaultSource { id } => { OverruledAttributeSub::DefaultSource { id } => {
diag.note(fluent::lint_default_source); diag.note(fluent::lint_default_source);

View file

@ -3,9 +3,7 @@ use std::ops::ControlFlow;
use hir::intravisit::{self, Visitor}; use hir::intravisit::{self, Visitor};
use rustc_ast::Recovered; use rustc_ast::Recovered;
use rustc_errors::{ use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle};
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
};
use rustc_hir::{self as hir, HirIdSet}; use rustc_hir::{self as hir, HirIdSet};
use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::adjustment::Adjust;
@ -327,11 +325,7 @@ struct IfLetRescopeRewrite {
} }
impl Subdiagnostic for IfLetRescopeRewrite { impl Subdiagnostic for IfLetRescopeRewrite {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
let mut suggestions = vec![]; let mut suggestions = vec![];
for match_head in self.match_heads { for match_head in self.match_heads {
match match_head { match match_head {
@ -360,7 +354,7 @@ impl Subdiagnostic for IfLetRescopeRewrite {
.chain(repeat('}').take(closing_brackets.count)) .chain(repeat('}').take(closing_brackets.count))
.collect(), .collect(),
)); ));
let msg = f(diag, crate::fluent_generated::lint_suggestion); let msg = diag.eagerly_translate(crate::fluent_generated::lint_suggestion);
diag.multipart_suggestion_with_style( diag.multipart_suggestion_with_style(
msg, msg,
suggestions, suggestions,

View file

@ -6,7 +6,7 @@ use rustc_abi::ExternAbi;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle,
}; };
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -449,11 +449,7 @@ pub(crate) struct BuiltinUnpermittedTypeInitSub {
} }
impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let mut err = self.err; let mut err = self.err;
loop { loop {
if let Some(span) = err.span { if let Some(span) = err.span {
@ -504,11 +500,7 @@ pub(crate) struct BuiltinClashingExternSub<'a> {
} }
impl Subdiagnostic for BuiltinClashingExternSub<'_> { impl Subdiagnostic for BuiltinClashingExternSub<'_> {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let mut expected_str = DiagStyledString::new(); let mut expected_str = DiagStyledString::new();
expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
let mut found_str = DiagStyledString::new(); let mut found_str = DiagStyledString::new();
@ -824,11 +816,7 @@ pub(crate) struct HiddenUnicodeCodepointsDiagLabels {
} }
impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
for (c, span) in self.spans { for (c, span) in self.spans {
diag.span_label(span, format!("{c:?}")); diag.span_label(span, format!("{c:?}"));
} }
@ -842,11 +830,7 @@ pub(crate) enum HiddenUnicodeCodepointsDiagSub {
// Used because of multiple multipart_suggestion and note // Used because of multiple multipart_suggestion and note
impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
HiddenUnicodeCodepointsDiagSub::Escape { spans } => { HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
diag.multipart_suggestion_with_style( diag.multipart_suggestion_with_style(
@ -1015,11 +999,7 @@ pub(crate) struct NonBindingLetSub {
} }
impl Subdiagnostic for NonBindingLetSub { impl Subdiagnostic for NonBindingLetSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
if can_suggest_binding { if can_suggest_binding {
@ -1303,11 +1283,7 @@ pub(crate) enum NonSnakeCaseDiagSub {
} }
impl Subdiagnostic for NonSnakeCaseDiagSub { impl Subdiagnostic for NonSnakeCaseDiagSub {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
NonSnakeCaseDiagSub::Label { span } => { NonSnakeCaseDiagSub::Label { span } => {
diag.span_label(span, fluent::lint_label); diag.span_label(span, fluent::lint_label);
@ -1629,11 +1605,7 @@ pub(crate) enum OverflowingBinHexSign {
} }
impl Subdiagnostic for OverflowingBinHexSign { impl Subdiagnostic for OverflowingBinHexSign {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
OverflowingBinHexSign::Positive => { OverflowingBinHexSign::Positive => {
diag.note(fluent::lint_positive_note); diag.note(fluent::lint_positive_note);

View file

@ -20,14 +20,12 @@ use crate::diagnostics::utils::{
/// The central struct for constructing the `add_to_diag` method from an annotated struct. /// The central struct for constructing the `add_to_diag` method from an annotated struct.
pub(crate) struct SubdiagnosticDerive { pub(crate) struct SubdiagnosticDerive {
diag: syn::Ident, diag: syn::Ident,
f: syn::Ident,
} }
impl SubdiagnosticDerive { impl SubdiagnosticDerive {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let diag = format_ident!("diag"); let diag = format_ident!("diag");
let f = format_ident!("f"); Self { diag }
Self { diag, f }
} }
pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream { pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
@ -86,19 +84,16 @@ impl SubdiagnosticDerive {
}; };
let diag = &self.diag; let diag = &self.diag;
let f = &self.f;
// FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here?
#[allow(keyword_idents_2024)] #[allow(keyword_idents_2024)]
let ret = structure.gen_impl(quote! { let ret = structure.gen_impl(quote! {
gen impl rustc_errors::Subdiagnostic for @Self { gen impl rustc_errors::Subdiagnostic for @Self {
fn add_to_diag_with<__G, __F>( fn add_to_diag<__G>(
self, self,
#diag: &mut rustc_errors::Diag<'_, __G>, #diag: &mut rustc_errors::Diag<'_, __G>,
#f: &__F
) where ) where
__G: rustc_errors::EmissionGuarantee, __G: rustc_errors::EmissionGuarantee,
__F: rustc_errors::SubdiagMessageOp<__G>,
{ {
#implementation #implementation
} }
@ -384,11 +379,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
Ok(quote! {}) Ok(quote! {})
} }
"subdiagnostic" => { "subdiagnostic" => {
let f = &self.parent.f;
let diag = &self.parent.diag; let diag = &self.parent.diag;
let binding = &info.binding; let binding = &info.binding;
self.has_subdiagnostic = true; self.has_subdiagnostic = true;
Ok(quote! { #binding.add_to_diag_with(#diag, #f); }) Ok(quote! { #binding.add_to_diag(#diag); })
} }
_ => { _ => {
let mut span_attrs = vec![]; let mut span_attrs = vec![];
@ -531,12 +525,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
let span_field = self.span_field.value_ref(); let span_field = self.span_field.value_ref();
let diag = &self.parent.diag; let diag = &self.parent.diag;
let f = &self.parent.f;
let mut calls = TokenStream::new(); let mut calls = TokenStream::new();
for (kind, slug, no_span) in kind_slugs { for (kind, slug, no_span) in kind_slugs {
let message = format_ident!("__message"); let message = format_ident!("__message");
calls.extend( calls.extend(
quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); }, quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); },
); );
let name = format_ident!( let name = format_ident!(

View file

@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
MultiSpan, SubdiagMessageOp, Subdiagnostic, pluralize, MultiSpan, Subdiagnostic, pluralize,
}; };
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
@ -546,11 +546,7 @@ pub(crate) struct UnsafeNotInheritedLintNote {
} }
impl Subdiagnostic for UnsafeNotInheritedLintNote { impl Subdiagnostic for UnsafeNotInheritedLintNote {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
let body_start = self.body_span.shrink_to_lo(); let body_start = self.body_span.shrink_to_lo();
let body_end = self.body_span.shrink_to_hi(); let body_end = self.body_span.shrink_to_hi();
@ -1031,11 +1027,7 @@ pub(crate) struct Variant {
} }
impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
diag.arg("ty", self.ty); diag.arg("ty", self.ty);
let mut spans = MultiSpan::from(self.adt_def_span); let mut spans = MultiSpan::from(self.adt_def_span);
@ -1117,11 +1109,7 @@ pub(crate) struct Rust2024IncompatiblePatSugg {
} }
impl Subdiagnostic for Rust2024IncompatiblePatSugg { impl Subdiagnostic for Rust2024IncompatiblePatSugg {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
// Format and emit explanatory notes about default binding modes. Reversing the spans' order // Format and emit explanatory notes about default binding modes. Reversing the spans' order
// means if we have nested spans, the innermost ones will be visited first. // means if we have nested spans, the innermost ones will be visited first.
for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() {

View file

@ -512,23 +512,17 @@ struct LocalLabel<'a> {
/// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order
impl Subdiagnostic for LocalLabel<'_> { impl Subdiagnostic for LocalLabel<'_> {
fn add_to_diag_with< fn add_to_diag<G: rustc_errors::EmissionGuarantee>(self, diag: &mut rustc_errors::Diag<'_, G>) {
G: rustc_errors::EmissionGuarantee,
F: rustc_errors::SubdiagMessageOp<G>,
>(
self,
diag: &mut rustc_errors::Diag<'_, G>,
f: &F,
) {
diag.arg("name", self.name); diag.arg("name", self.name);
diag.arg("is_generated_name", self.is_generated_name); diag.arg("is_generated_name", self.is_generated_name);
diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024);
let msg = f(diag, crate::fluent_generated::mir_transform_tail_expr_local.into()); let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local);
diag.span_label(self.span, msg); diag.span_label(self.span, msg);
for dtor in self.destructors { for dtor in self.destructors {
dtor.add_to_diag_with(diag, f); dtor.add_to_diag(diag);
} }
let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue); let msg =
diag.eagerly_translate(crate::fluent_generated::mir_transform_label_local_epilogue);
diag.span_label(self.span, msg); diag.span_label(self.span, msg);
} }
} }

View file

@ -7,8 +7,7 @@ use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{Path, Visibility}; use rustc_ast::{Path, Visibility};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, SubdiagMessageOp, Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic,
Subdiagnostic,
}; };
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::errors::ExprParenthesesNeeded; use rustc_session::errors::ExprParenthesesNeeded;
@ -1550,11 +1549,7 @@ pub(crate) struct FnTraitMissingParen {
} }
impl Subdiagnostic for FnTraitMissingParen { impl Subdiagnostic for FnTraitMissingParen {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
diag.span_suggestion_short( diag.span_suggestion_short(
self.span.shrink_to_hi(), self.span.shrink_to_hi(),

View file

@ -5,7 +5,7 @@ use rustc_ast::Label;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
MultiSpan, SubdiagMessageOp, Subdiagnostic, MultiSpan, Subdiagnostic,
}; };
use rustc_hir::{self as hir, ExprKind, Target}; use rustc_hir::{self as hir, ExprKind, Target};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@ -1852,11 +1852,7 @@ pub(crate) struct UnusedVariableStringInterp {
} }
impl Subdiagnostic for UnusedVariableStringInterp { impl Subdiagnostic for UnusedVariableStringInterp {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
diag.multipart_suggestion( diag.multipart_suggestion(
crate::fluent_generated::passes_string_interpolation_only_works, crate::fluent_generated::passes_string_interpolation_only_works,

View file

@ -1020,7 +1020,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
} }
hir::ExprKind::Call(ref f, args) => { hir::ExprKind::Call(ref f, args) => {
let succ = self.check_is_ty_uninhabited(expr, succ); let is_ctor = |f: &Expr<'_>| matches!(f.kind, hir::ExprKind::Path(hir::QPath::Resolved(_, path)) if matches!(path.res, rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Ctor(_, _), _)));
let succ =
if !is_ctor(f) { self.check_is_ty_uninhabited(expr, succ) } else { succ };
let succ = self.propagate_through_exprs(args, succ); let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(f, succ) self.propagate_through_expr(f, succ)
} }

View file

@ -1,4 +1,4 @@
use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_span::Span; use rustc_span::Span;
@ -55,11 +55,7 @@ pub struct Overlap {
} }
impl Subdiagnostic for Overlap { impl Subdiagnostic for Overlap {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
let Overlap { span, range } = self; let Overlap { span, range } = self;
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
@ -103,11 +99,7 @@ pub struct GappedRange {
} }
impl Subdiagnostic for GappedRange { impl Subdiagnostic for GappedRange {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
let GappedRange { span, gap, first_range } = self; let GappedRange { span, gap, first_range } = self;
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`

View file

@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{ use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
}; };
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
@ -107,11 +107,7 @@ pub enum AdjustSignatureBorrow {
} }
impl Subdiagnostic for AdjustSignatureBorrow { impl Subdiagnostic for AdjustSignatureBorrow {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
AdjustSignatureBorrow::Borrow { to_borrow } => { AdjustSignatureBorrow::Borrow { to_borrow } => {
diag.arg("len", to_borrow.len()); diag.arg("len", to_borrow.len());
@ -381,11 +377,7 @@ pub enum RegionOriginNote<'a> {
} }
impl Subdiagnostic for RegionOriginNote<'_> { impl Subdiagnostic for RegionOriginNote<'_> {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let mut label_or_note = |span, msg: DiagMessage| { let mut label_or_note = |span, msg: DiagMessage| {
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
@ -446,11 +438,7 @@ pub enum LifetimeMismatchLabels {
} }
impl Subdiagnostic for LifetimeMismatchLabels { impl Subdiagnostic for LifetimeMismatchLabels {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
match self { match self {
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
diag.span_label(param_span, fluent::trait_selection_declared_different); diag.span_label(param_span, fluent::trait_selection_declared_different);
@ -495,11 +483,7 @@ pub struct AddLifetimeParamsSuggestion<'a> {
} }
impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let mut mk_suggestion = || { let mut mk_suggestion = || {
let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
else { else {
@ -689,11 +673,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
} }
impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
mut self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
self.unmet_requirements self.unmet_requirements
.push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static);
diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req);
@ -1008,17 +988,13 @@ pub struct ConsiderBorrowingParamHelp {
} }
impl Subdiagnostic for ConsiderBorrowingParamHelp { impl Subdiagnostic for ConsiderBorrowingParamHelp {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
let mut type_param_span: MultiSpan = self.spans.clone().into(); let mut type_param_span: MultiSpan = self.spans.clone().into();
for &span in &self.spans { for &span in &self.spans {
// Seems like we can't call f() here as Into<DiagMessage> is required // Seems like we can't call f() here as Into<DiagMessage> is required
type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
} }
let msg = f(diag, fluent::trait_selection_tid_param_help.into()); let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help);
diag.span_help(type_param_span, msg); diag.span_help(type_param_span, msg);
} }
} }
@ -1053,18 +1029,14 @@ pub struct DynTraitConstraintSuggestion {
} }
impl Subdiagnostic for DynTraitConstraintSuggestion { impl Subdiagnostic for DynTraitConstraintSuggestion {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
let mut multi_span: MultiSpan = vec![self.span].into(); let mut multi_span: MultiSpan = vec![self.span].into();
multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
multi_span multi_span
.push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into()); let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note);
diag.span_note(multi_span, msg); diag.span_note(multi_span, msg);
let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into()); let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion);
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
self.span.shrink_to_hi(), self.span.shrink_to_hi(),
msg, msg,
@ -1101,11 +1073,7 @@ pub struct ReqIntroducedLocations {
} }
impl Subdiagnostic for ReqIntroducedLocations { impl Subdiagnostic for ReqIntroducedLocations {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
mut self,
diag: &mut Diag<'_, G>,
f: &F,
) {
for sp in self.spans { for sp in self.spans {
self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
} }
@ -1114,7 +1082,7 @@ impl Subdiagnostic for ReqIntroducedLocations {
self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
} }
self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into()); let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by);
diag.span_note(self.span, msg); diag.span_note(self.span, msg);
} }
} }
@ -1513,13 +1481,9 @@ pub struct SuggestTuplePatternMany {
} }
impl Subdiagnostic for SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
diag.arg("path", self.path); diag.arg("path", self.path);
let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into()); let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many);
diag.multipart_suggestions( diag.multipart_suggestions(
message, message,
self.compatible_variants.into_iter().map(|variant| { self.compatible_variants.into_iter().map(|variant| {
@ -1752,11 +1716,7 @@ pub struct AddPreciseCapturingAndParams {
} }
impl Subdiagnostic for AddPreciseCapturingAndParams { impl Subdiagnostic for AddPreciseCapturingAndParams {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
diag.arg("new_lifetime", self.new_lifetime); diag.arg("new_lifetime", self.new_lifetime);
diag.multipart_suggestion_verbose( diag.multipart_suggestion_verbose(
fluent::trait_selection_precise_capturing_new_but_apit, fluent::trait_selection_precise_capturing_new_but_apit,
@ -1896,11 +1856,7 @@ pub struct AddPreciseCapturingForOvercapture {
} }
impl Subdiagnostic for AddPreciseCapturingForOvercapture { impl Subdiagnostic for AddPreciseCapturingForOvercapture {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
_f: &F,
) {
let applicability = if self.apit_spans.is_empty() { let applicability = if self.apit_spans.is_empty() {
Applicability::MachineApplicable Applicability::MachineApplicable
} else { } else {

View file

@ -1,4 +1,4 @@
use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic}; use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic};
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
@ -162,17 +162,13 @@ impl RegionExplanation<'_> {
} }
impl Subdiagnostic for RegionExplanation<'_> { impl Subdiagnostic for RegionExplanation<'_> {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
diag.arg("pref_kind", self.prefix); diag.arg("pref_kind", self.prefix);
diag.arg("suff_kind", self.suffix); diag.arg("suff_kind", self.suffix);
diag.arg("desc_kind", self.desc.kind); diag.arg("desc_kind", self.desc.kind);
diag.arg("desc_arg", self.desc.arg); diag.arg("desc_arg", self.desc.arg);
let msg = f(diag, fluent::trait_selection_region_explanation.into()); let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation);
if let Some(span) = self.desc.span { if let Some(span) = self.desc.span {
diag.span_note(span, msg); diag.span_note(span, msg);
} else { } else {

View file

@ -1,93 +1,115 @@
use itertools::Itertools; use itertools::Itertools;
use super::query_context::test::{Def, UltraMinimal}; use super::query_context::test::{Def, UltraMinimal};
use crate::maybe_transmutable::MaybeTransmutableQuery; use crate::{Answer, Assume, Reason, layout};
use crate::{Reason, layout};
type Tree = layout::Tree<Def, !>;
type Dfa = layout::Dfa<!>;
trait Representation {
fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!>;
}
impl Representation for Tree {
fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
.answer()
}
}
impl Representation for Dfa {
fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
.answer()
}
}
fn is_transmutable<R: Representation + Clone>(
src: &R,
dst: &R,
assume: Assume,
) -> crate::Answer<!> {
let src = src.clone();
let dst = dst.clone();
// The only dimension of the transmutability analysis we want to test
// here is the safety analysis. To ensure this, we disable all other
// toggleable aspects of the transmutability analysis.
R::is_transmutable(src, dst, assume)
}
mod safety { mod safety {
use super::*; use super::*;
use crate::Answer; use crate::Answer;
type Tree = layout::Tree<Def, !>;
const DST_HAS_SAFETY_INVARIANTS: Answer<!> = const DST_HAS_SAFETY_INVARIANTS: Answer<!> =
Answer::No(crate::Reason::DstMayHaveSafetyInvariants); Answer::No(crate::Reason::DstMayHaveSafetyInvariants);
fn is_transmutable(src: &Tree, dst: &Tree, assume_safety: bool) -> crate::Answer<!> {
let src = src.clone();
let dst = dst.clone();
// The only dimension of the transmutability analysis we want to test
// here is the safety analysis. To ensure this, we disable all other
// toggleable aspects of the transmutability analysis.
let assume = crate::Assume {
alignment: true,
lifetimes: true,
validity: true,
safety: assume_safety,
};
crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
.answer()
}
#[test] #[test]
fn src_safe_dst_safe() { fn src_safe_dst_safe() {
let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes); assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes);
assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); assert_eq!(
is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
Answer::Yes
);
} }
#[test] #[test]
fn src_safe_dst_unsafe() { fn src_safe_dst_unsafe() {
let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS); assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS);
assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); assert_eq!(
is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
Answer::Yes
);
} }
#[test] #[test]
fn src_unsafe_dst_safe() { fn src_unsafe_dst_safe() {
let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes); assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes);
assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); assert_eq!(
is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
Answer::Yes
);
} }
#[test] #[test]
fn src_unsafe_dst_unsafe() { fn src_unsafe_dst_unsafe() {
let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS); assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS);
assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); assert_eq!(
is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
Answer::Yes
);
} }
} }
mod bool { mod bool {
use super::*; use super::*;
use crate::Answer;
#[test] #[test]
fn should_permit_identity_transmutation_tree() { fn should_permit_identity_transmutation_tree() {
let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new( let src = Tree::bool();
layout::Tree::<Def, !>::bool(), assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes);
layout::Tree::<Def, !>::bool(), assert_eq!(
crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }),
UltraMinimal, Answer::Yes
) );
.answer();
assert_eq!(answer, Answer::Yes);
} }
#[test] #[test]
fn should_permit_identity_transmutation_dfa() { fn should_permit_identity_transmutation_dfa() {
let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new( let src = Dfa::bool();
layout::Dfa::<!>::bool(), assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes);
layout::Dfa::<!>::bool(), assert_eq!(
crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }),
UltraMinimal, Answer::Yes
) );
.answer();
assert_eq!(answer, Answer::Yes);
} }
#[test] #[test]
@ -122,13 +144,7 @@ mod bool {
if src_set.is_subset(&dst_set) { if src_set.is_subset(&dst_set) {
assert_eq!( assert_eq!(
Answer::Yes, Answer::Yes,
MaybeTransmutableQuery::new( is_transmutable(&src_layout, &dst_layout, Assume::default()),
src_layout.clone(),
dst_layout.clone(),
crate::Assume { validity: false, ..crate::Assume::default() },
UltraMinimal,
)
.answer(),
"{:?} SHOULD be transmutable into {:?}", "{:?} SHOULD be transmutable into {:?}",
src_layout, src_layout,
dst_layout dst_layout
@ -136,13 +152,11 @@ mod bool {
} else if !src_set.is_disjoint(&dst_set) { } else if !src_set.is_disjoint(&dst_set) {
assert_eq!( assert_eq!(
Answer::Yes, Answer::Yes,
MaybeTransmutableQuery::new( is_transmutable(
src_layout.clone(), &src_layout,
dst_layout.clone(), &dst_layout,
crate::Assume { validity: true, ..crate::Assume::default() }, Assume { validity: true, ..Assume::default() }
UltraMinimal, ),
)
.answer(),
"{:?} SHOULD be transmutable (assuming validity) into {:?}", "{:?} SHOULD be transmutable (assuming validity) into {:?}",
src_layout, src_layout,
dst_layout dst_layout
@ -150,13 +164,7 @@ mod bool {
} else { } else {
assert_eq!( assert_eq!(
Answer::No(Reason::DstIsBitIncompatible), Answer::No(Reason::DstIsBitIncompatible),
MaybeTransmutableQuery::new( is_transmutable(&src_layout, &dst_layout, Assume::default()),
src_layout.clone(),
dst_layout.clone(),
crate::Assume { validity: false, ..crate::Assume::default() },
UltraMinimal,
)
.answer(),
"{:?} should NOT be transmutable into {:?}", "{:?} should NOT be transmutable into {:?}",
src_layout, src_layout,
dst_layout dst_layout

0
diff Normal file
View file

View file

@ -0,0 +1,14 @@
# `allow-features`
This feature is perma-unstable and has no tracking issue.
----
This flag allows limiting the features which can be enabled with `#![feature(...)]` attributes.
By default, all features are allowed on nightly and no features are allowed on stable or beta (but see [`RUSTC_BOOTSTRAP`]).
Features are comma-separated, for example `-Z allow-features=ffi_pure,f16`.
If the flag is present, any feature listed will be allowed and any feature not listed will be disallowed.
Any unrecognized feature is ignored.
[`RUSTC_BOOTSTRAP`]: ./rustc-bootstrap.html

View file

@ -0,0 +1,56 @@
# `RUSTC_BOOTSTRAP`
This feature is perma-unstable and has no tracking issue.
----
The `RUSTC_BOOTSTRAP` environment variable tells rustc to act as if it is a nightly compiler;
in particular, it allows `#![feature(...)]` attributes and `-Z` flags even on the stable release channel.
Setting `RUSTC_BOOTSTRAP=1` instructs rustc to enable this for all crates.
Setting `RUSTC_BOOTSTRAP=crate_name` instructs rustc to only apply this to crates named `crate_name`.
Setting `RUSTC_BOOTSTRAP=-1` instructs rustc to act as if it is a stable compiler, even on the nightly release channel.
Cargo disallows setting `cargo::rustc-env=RUSTC_BOOTSTRAP` in build scripts.
Build systems can limit the features they enable with [`-Z allow-features=feature1,feature2`][Z-allow-features].
Crates can fully opt out of unstable features by using [`#![forbid(unstable_features)]`][unstable-features] at the crate root (or any other way of enabling lints, such as `-F unstable-features`).
[Z-allow-features]: ./allow-features.html
[unstable-features]: ../../rustc/lints/listing/allowed-by-default.html#unstable-features
## Why does this environment variable exist?
`RUSTC_BOOTSTRAP`, as the name suggests, is used for bootstrapping the compiler from an earlier version.
In particular, nightly is built with beta, and beta is built with stable.
Since the standard library and compiler both use unstable features, `RUSTC_BOOTSTRAP` is required so that we can use the previous version to build them.
## Why is this environment variable so easy to use for people not in the rust project?
Originally, `RUSTC_BOOTSTRAP` required passing in a hash of the previous compiler version, to discourage using it for any purpose other than bootstrapping.
That constraint was later relaxed; see <https://github.com/rust-lang/rust/issues/36548> for the discussion that happened at that time.
People have at various times proposed re-adding the technical constraints.
However, doing so is extremely disruptive for several major projects that we very much want to keep using the latest stable toolchain version, such as Firefox, Rust for Linux, and Chromium.
We continue to allow `RUSTC_BOOTSTRAP` until we can come up with an alternative that does not disrupt our largest constituents.
## Stability policy
Despite being usable on stable, this is an unstable feature.
Like any other unstable feature, we reserve the right to change or remove this feature in the future, as well as any other unstable feature that it enables.
Using this feature opts you out of the normal stability/backwards compatibility guarantee of stable.
Although we do not take technical measures to prevent it from being used, we strongly discourage using this feature.
If at all possible, please contribute to stabilizing the features you care about instead of bypassing the Rust project's stability policy.
For library crates, we especially discourage the use of this feature.
The crates depending on you do not know that you use this feature, have little recourse if it breaks, and can be used in contexts that are hard to predict.
For libraries that do use this feature, please document the versions you support (including a *maximum* as well as minimum version), and a mechanism to disable it.
If you do not have a mechanism to disable the use of `RUSTC_BOOTSTRAP`, consider removing its use altogether, such that people can only use your library if they are already using a nightly toolchain.
This leaves the choice of whether to opt-out of Rust's stability guarantees up to the end user building their code.
## History
- [Allowed without a hash](https://github.com/rust-lang/rust/pull/37265) ([discussion](https://github.com/rust-lang/rust/issues/36548))
- [Extended to crate names](https://github.com/rust-lang/rust/pull/77802) ([discussion](https://github.com/rust-lang/cargo/issues/7088))
- [Disallowed for build scripts](https://github.com/rust-lang/cargo/pull/9181) ([discussion](https://github.com/rust-lang/compiler-team/issues/350))
- [Extended to emulate stable](https://github.com/rust-lang/rust/pull/132993) ([discussion](https://github.com/rust-lang/rust/issues/123404))

View file

@ -0,0 +1,39 @@
# `RUSTC_OVERRIDE_VERSION_STRING`
This feature is perma-unstable and has no tracking issue.
----
The `RUSTC_OVERRIDE_VERSION_STRING` environment variable overrides the version reported by `rustc --version`. For example:
```console
$ rustc --version
rustc 1.87.0-nightly (43f0014ef 2025-03-25)
$ env RUSTC_OVERRIDE_VERSION_STRING=1.81.0-nightly rustc --version
rustc 1.81.0-nightly
```
Note that the version string is completely overwritten; i.e. rustc discards commit hash and commit date information unless it is explicitly included in the environment variable. The string only applies to the "release" part of the version; for example:
```console
$ RUSTC_OVERRIDE_VERSION_STRING="1.81.0-nightly (aaaaaaaaa 2025-03-22)" rustc -vV
rustc 1.81.0-nightly (aaaaaaaaa 2025-03-22)
binary: rustc
commit-hash: 43f0014ef0f242418674f49052ed39b70f73bc1c
commit-date: 2025-03-25
host: x86_64-unknown-linux-gnu
release: 1.81.0-nightly (aaaaaaaaa 2025-03-22)
LLVM version: 20.1.1
```
Note here that `commit-hash` and `commit-date` do not match the values in the string, and `release` includes the fake hash and date.
This variable has no effect on whether or not unstable features are allowed to be used. It only affects the output of `--version`.
## Why does this environment variable exist?
Various library crates have incomplete or incorrect feature detection.
This environment variable allows bisecting crates that do incorrect detection with `version_check::supports_feature`.
This is not intended to be used for any other case (and, except for bisection, is not particularly useful).
See <https://github.com/rust-lang/rust/pull/124339> for further discussion.

View file

@ -1,22 +0,0 @@
# `cfg_boolean_literals`
The tracking issue for this feature is: [#131204]
[#131204]: https://github.com/rust-lang/rust/issues/131204
------------------------
The `cfg_boolean_literals` feature makes it possible to use the `true`/`false`
literal as cfg predicate. They always evaluate to true/false respectively.
## Examples
```rust
#![feature(cfg_boolean_literals)]
#[cfg(true)]
const A: i32 = 5;
#[cfg(all(false))]
const A: i32 = 58 * 89;
```

View file

@ -0,0 +1,133 @@
# `macro_metavar_expr_concat`
The tracking issue for this feature is: [#124225]
------------------------
In stable Rust, there is no way to create new identifiers by joining identifiers to literals or other identifiers without using procedural macros such as [`paste`].
`#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression.
> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise
> independent. It replaces the old unstable feature [`concat_idents`].
> This is an experimental feature; it and its syntax will require a RFC before stabilization.
### Overview
`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers:
```rust
#![feature(macro_metavar_expr_concat)]
macro_rules! create_some_structs {
($name:ident) => {
pub struct ${ concat(First, $name) };
pub struct ${ concat(Second, $name) };
pub struct ${ concat(Third, $name) };
}
}
create_some_structs!(Thing);
```
This macro invocation expands to:
```rust
pub struct FirstThing;
pub struct SecondThing;
pub struct ThirdThing;
```
### Syntax
This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]).
`concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals.
### Examples
#### Create a function or method with a concatenated name
```rust
#![feature(macro_metavar_expr_concat)]
macro_rules! make_getter {
($name:ident, $field: ident, $ret:ty) => {
impl $name {
pub fn ${ concat(get_, $field) }(&self) -> &$ret {
&self.$field
}
}
}
}
pub struct Thing {
description: String,
}
make_getter!(Thing, description, String);
```
This expands to:
```rust
pub struct Thing {
description: String,
}
impl Thing {
pub fn get_description(&self) -> &String {
&self.description
}
}
```
#### Create names for macro generated tests
```rust
#![feature(macro_metavar_expr_concat)]
macro_rules! test_math {
($integer:ident) => {
#[test]
fn ${ concat(test_, $integer, _, addition) } () {
let a: $integer = 73;
let b: $integer = 42;
assert_eq!(a + b, 115)
}
#[test]
fn ${ concat(test_, $integer, _, subtraction) } () {
let a: $integer = 73;
let b: $integer = 42;
assert_eq!(a - b, 31)
}
}
}
test_math!(i32);
test_math!(u64);
test_math!(u128);
```
Running this returns the following output:
```text
running 6 tests
test test_i32_subtraction ... ok
test test_i32_addition ... ok
test test_u128_addition ... ok
test test_u128_subtraction ... ok
test test_u64_addition ... ok
test test_u64_subtraction ... ok
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
[`paste`]: https://crates.io/crates/paste
[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html
[`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html
[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md
[`concat_idents`]: ../library-features/concat-idents.md
[#124225]: https://github.com/rust-lang/rust/issues/124225
[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html

View file

@ -0,0 +1,10 @@
# `macro_metavar_expr`
The tracking issue for this feature is: [#83527]
------------------------
> This feature is not to be confused with [`macro_metavar_expr_concat`].
[`macro_metavar_expr_concat`]: ./macro-metavar-expr-concat.md
[#83527]: https://github.com/rust-lang/rust/issues/83527

View file

@ -6,6 +6,8 @@ The tracking issue for this feature is: [#29599]
------------------------ ------------------------
> This feature is expected to be superseded by [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md).
The `concat_idents` feature adds a macro for concatenating multiple identifiers The `concat_idents` feature adds a macro for concatenating multiple identifiers
into one identifier. into one identifier.

View file

@ -3789,35 +3789,6 @@ The tracking issue for this feature is: [#64797]
[#64797]: https://github.com/rust-lang/rust/issues/64797 [#64797]: https://github.com/rust-lang/rust/issues/64797
------------------------ ------------------------
"##,
default_severity: Severity::Allow,
warn_since: None,
deny_since: None,
},
Lint {
label: "cfg_boolean_literals",
description: r##"# `cfg_boolean_literals`
The tracking issue for this feature is: [#131204]
[#131204]: https://github.com/rust-lang/rust/issues/131204
------------------------
The `cfg_boolean_literals` feature makes it possible to use the `true`/`false`
literal as cfg predicate. They always evaluate to true/false respectively.
## Examples
```rust
#![feature(cfg_boolean_literals)]
#[cfg(true)]
const A: i32 = 5;
#[cfg(all(false))]
const A: i32 = 58 * 89;
```
"##, "##,
default_severity: Severity::Allow, default_severity: Severity::Allow,
warn_since: None, warn_since: None,

View file

@ -2,7 +2,7 @@
fn main() {} fn main() {}
#[cfg(FALSE)] #[cfg(false)]
fn syntax() { fn syntax() {
let _ = #[attr] []; let _ = #[attr] [];
let _ = #[attr] [0]; let _ = #[attr] [0];

View file

@ -4,5 +4,5 @@
fn main() {} fn main() {}
#[cfg(FALSE)] #[cfg(false)]
enum Foo { pub V, } enum Foo { pub V, }

View file

@ -1,6 +1,6 @@
//@ pp-exact //@ pp-exact
#[cfg(FALSE)] #[cfg(false)]
fn simple_attr() { fn simple_attr() {
#[attr] #[attr]
@ -10,21 +10,21 @@ fn simple_attr() {
if true {} if true {}
} }
#[cfg(FALSE)] #[cfg(false)]
fn if_else_chain() { fn if_else_chain() {
#[first_attr] #[first_attr]
if true {} else if false {} else {} if true {} else if false {} else {}
} }
#[cfg(FALSE)] #[cfg(false)]
fn if_let() { fn if_let() {
#[attr] #[attr]
if let Some(_) = Some(true) {} if let Some(_) = Some(true) {}
} }
#[cfg(FALSE)] #[cfg(false)]
fn let_attr_if() { fn let_attr_if() {
let _ = #[attr] if let _ = 0 {}; let _ = #[attr] if let _ = 0 {};
let _ = #[attr] if true {}; let _ = #[attr] if true {};

View file

@ -4,7 +4,7 @@
fn main() {} fn main() {}
#[cfg(FALSE)] #[cfg(false)]
extern "C" { extern "C" {
static X: u8; static X: u8;
type X; type X;
@ -14,7 +14,7 @@ extern "C" {
pub fn foo(); pub fn foo();
} }
#[cfg(FALSE)] #[cfg(false)]
trait T { trait T {
const X: u8; const X: u8;
type X; type X;
@ -30,7 +30,7 @@ trait T {
pub default fn foo(); pub default fn foo();
} }
#[cfg(FALSE)] #[cfg(false)]
impl T for S { impl T for S {
const X: u8; const X: u8;
type X; type X;

View file

@ -1,6 +1,5 @@
//@ check-pass //@ check-pass
#![feature(cfg_boolean_literals)]
#![feature(doc_cfg)] #![feature(doc_cfg)]
#[doc(cfg(false))] #[doc(cfg(false))]

View file

@ -1,10 +1,6 @@
// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))` // #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))`
#![feature(doc_cfg)] #![feature(doc_cfg)]
// `cfg_boolean_literals`
#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change
pub fn cfg_boolean_literals() {}
// `cfg_version` // `cfg_version`
#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change #[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change
pub fn cfg_sanitize() {} pub fn cfg_sanitize() {}

View file

@ -1,15 +1,5 @@
error[E0658]: `cfg(false)` is experimental and subject to change
--> $DIR/doc-cfg-unstable.rs:5:11
|
LL | #[doc(cfg(false))]
| ^^^^^
|
= note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
= help: add `#![feature(cfg_boolean_literals)]` 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]: `cfg(sanitize)` is experimental and subject to change error[E0658]: `cfg(sanitize)` is experimental and subject to change
--> $DIR/doc-cfg-unstable.rs:9:11 --> $DIR/doc-cfg-unstable.rs:5:11
| |
LL | #[doc(cfg(sanitize = "thread"))] LL | #[doc(cfg(sanitize = "thread"))]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -18,6 +8,6 @@ LL | #[doc(cfg(sanitize = "thread"))]
= help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable = help: add `#![feature(cfg_sanitize)]` 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: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -15,7 +15,7 @@ extern crate rustc_span;
use rustc_errors::{ use rustc_errors::{
Diag, DiagCtxtHandle, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level, Diag, DiagCtxtHandle, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level,
LintDiagnostic, SubdiagMessage, SubdiagMessageOp, Subdiagnostic, LintDiagnostic, SubdiagMessage, Subdiagnostic,
}; };
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span; use rustc_span::Span;
@ -56,10 +56,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for TranslatableInDiagnostic {
pub struct UntranslatableInAddtoDiag; pub struct UntranslatableInAddtoDiag;
impl Subdiagnostic for UntranslatableInAddtoDiag { impl Subdiagnostic for UntranslatableInAddtoDiag {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(
self, self,
diag: &mut Diag<'_, G>, diag: &mut Diag<'_, G>,
f: &F,
) { ) {
diag.note("untranslatable diagnostic"); diag.note("untranslatable diagnostic");
//~^ ERROR diagnostics should be created using translatable messages //~^ ERROR diagnostics should be created using translatable messages
@ -69,10 +68,9 @@ impl Subdiagnostic for UntranslatableInAddtoDiag {
pub struct TranslatableInAddtoDiag; pub struct TranslatableInAddtoDiag;
impl Subdiagnostic for TranslatableInAddtoDiag { impl Subdiagnostic for TranslatableInAddtoDiag {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( fn add_to_diag<G: EmissionGuarantee>(
self, self,
diag: &mut Diag<'_, G>, diag: &mut Diag<'_, G>,
f: &F,
) { ) {
diag.note(crate::fluent_generated::no_crate_note); diag.note(crate::fluent_generated::no_crate_note);
} }

View file

@ -11,19 +11,19 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:64:19 --> $DIR/diagnostics.rs:63:19
| |
LL | diag.note("untranslatable diagnostic"); LL | diag.note("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:85:19 --> $DIR/diagnostics.rs:83:19
| |
LL | diag.note("untranslatable diagnostic"); LL | diag.note("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
--> $DIR/diagnostics.rs:99:21 --> $DIR/diagnostics.rs:97:21
| |
LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -35,37 +35,37 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
--> $DIR/diagnostics.rs:102:21 --> $DIR/diagnostics.rs:100:21
| |
LL | let _diag = dcx.struct_err("untranslatable diagnostic"); LL | let _diag = dcx.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^ | ^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:102:32 --> $DIR/diagnostics.rs:100:32
| |
LL | let _diag = dcx.struct_err("untranslatable diagnostic"); LL | let _diag = dcx.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:120:7 --> $DIR/diagnostics.rs:118:7
| |
LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:122:50 --> $DIR/diagnostics.rs:120:50
| |
LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:124:7 --> $DIR/diagnostics.rs:122:7
| |
LL | f("untranslatable diagnostic", "untranslatable diagnostic"); LL | f("untranslatable diagnostic", "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages error: diagnostics should be created using translatable messages
--> $DIR/diagnostics.rs:124:36 --> $DIR/diagnostics.rs:122:36
| |
LL | f("untranslatable diagnostic", "untranslatable diagnostic"); LL | f("untranslatable diagnostic", "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,4 +1,5 @@
//@ needs-asm-support //@ needs-asm-support
//@ check-pass //@ check-pass
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
core::arch::global_asm!("x: .byte 42"); core::arch::global_asm!("x: .byte 42");

View file

@ -7,4 +7,5 @@ extern crate std;
//@ needs-asm-support //@ needs-asm-support
//@ check-pass //@ check-pass
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
global_asm! ("x: .byte 42"); global_asm! ("x: .byte 42");

View file

@ -1,4 +1,4 @@
fn main() { fn main() {
#[cfg(FALSE)] #[cfg(false)]
<() as module>::mac!(); //~ ERROR macros cannot use qualified paths <() as module>::mac!(); //~ ERROR macros cannot use qualified paths
} }

View file

@ -11,7 +11,7 @@ fn f() {
}; };
} }
#[cfg(FALSE)] #[cfg(false)]
fn g() { fn g() {
let _ = async { let _ = async {
for await _i in core::async_iter::from_iter(0..3) { for await _i in core::async_iter::from_iter(0..3) {

View file

@ -3,11 +3,11 @@
struct S; struct S;
impl S { impl S {
#[cfg(FALSE)] #[cfg(false)]
unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
} }
#[cfg(FALSE)] #[cfg(false)]
unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
// Ensure that `-Z crate-attr=cfg(FALSE)` can comment out the whole crate // Ensure that `-Z crate-attr=cfg(false)` can comment out the whole crate
//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(FALSE) //@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(false)
//@ check-pass //@ check-pass
// NOTE: duplicate items are load-bearing // NOTE: duplicate items are load-bearing

View file

@ -1,6 +1,6 @@
//@ check-pass //@ check-pass
#[cfg(FALSE)] #[cfg(false)]
auto trait Foo {} auto trait Foo {}
//~^ WARN `auto` traits are unstable //~^ WARN `auto` traits are unstable
//~| WARN unstable syntax can change at any point in the future, causing a hard error! //~| WARN unstable syntax can change at any point in the future, causing a hard error!

View file

@ -1,4 +1,4 @@
// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. // `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// This crate has no such attribute, therefore this crate does link to libstd. // This crate has no such attribute, therefore this crate does link to libstd.
#![cfg(FALSE)] #![cfg(false)]

View file

@ -1,5 +1,5 @@
// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. // `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// Therefore this crate does link to libstd. // Therefore this crate does link to libstd.
#![cfg(FALSE)] #![cfg(false)]
#![no_std] #![no_std]

View file

@ -1,8 +1,8 @@
// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. // `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// Therefore this crate doesn't link to libstd. // Therefore this crate doesn't link to libstd.
//@ no-prefer-dynamic //@ no-prefer-dynamic
#![no_std] #![no_std]
#![crate_type = "lib"] #![crate_type = "lib"]
#![cfg(FALSE)] #![cfg(false)]

View file

@ -1,8 +1,8 @@
pub mod inner { pub mod inner {
#[cfg(FALSE)] #[cfg(false)]
pub fn uwu() {} pub fn uwu() {}
#[cfg(FALSE)] #[cfg(false)]
pub mod doesnt_exist { pub mod doesnt_exist {
pub fn hello() {} pub fn hello() {}
} }

View file

@ -0,0 +1,14 @@
/// Test that placing a `cfg(true)` and `cfg(false)` on the same item result in
//. it being disabled.`
#[cfg(false)]
#[cfg(true)]
fn foo() {}
#[cfg(true)]
#[cfg(false)]
fn foo() {}
fn main() {
foo(); //~ ERROR cannot find function `foo` in this scope
}

View file

@ -0,0 +1,9 @@
error[E0425]: cannot find function `foo` in this scope
--> $DIR/both-true-false.rs:13:5
|
LL | foo();
| ^^^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0425`.

View file

@ -1,10 +1,10 @@
// Features above `cfg(FALSE)` are in effect in a fully unconfigured crate (issue #104633). // Features above `cfg(false)` are in effect in a fully unconfigured crate (issue #104633).
//@ check-pass //@ check-pass
//@ compile-flags: --crate-type lib //@ compile-flags: --crate-type lib
#![feature(decl_macro)] #![feature(decl_macro)]
#![cfg(FALSE)] #![cfg(false)]
#![feature(box_patterns)] #![feature(box_patterns)]
macro mac() {} // OK macro mac() {} // OK

View file

@ -3,7 +3,7 @@
// check that cfg correctly chooses between the macro impls (see also // check that cfg correctly chooses between the macro impls (see also
// cfg-macros-foo.rs) // cfg-macros-foo.rs)
#[cfg(FALSE)] #[cfg(false)]
#[macro_use] #[macro_use]
mod foo { mod foo {
macro_rules! bar { macro_rules! bar {

View file

@ -11,7 +11,7 @@ fn foo(f: Foo) {
Foo::Bar => {}, Foo::Bar => {},
#[cfg(not(FALSE))] #[cfg(not(FALSE))]
Foo::Baz => {}, Foo::Baz => {},
#[cfg(FALSE)] #[cfg(false)]
Basdfwe => {} Basdfwe => {}
} }
} }

View file

@ -6,7 +6,7 @@
#[cfg_eval] #[cfg_eval]
fn main() { fn main() {
#[cfg_eval] #[cfg_eval]
let _ = #[cfg(FALSE)] 0; let _ = #[cfg(false)] 0;
//~^ ERROR removing an expression is not supported in this position //~^ ERROR removing an expression is not supported in this position
//~| ERROR expected expression, found `;` //~| ERROR expected expression, found `;`
//~| ERROR removing an expression is not supported in this position //~| ERROR removing an expression is not supported in this position

View file

@ -1,19 +1,19 @@
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/cfg-stmt-recovery.rs:9:13 --> $DIR/cfg-stmt-recovery.rs:9:13
| |
LL | let _ = #[cfg(FALSE)] 0; LL | let _ = #[cfg(false)] 0;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: expected expression, found `;` error: expected expression, found `;`
--> $DIR/cfg-stmt-recovery.rs:9:28 --> $DIR/cfg-stmt-recovery.rs:9:28
| |
LL | let _ = #[cfg(FALSE)] 0; LL | let _ = #[cfg(false)] 0;
| ^ expected expression | ^ expected expression
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/cfg-stmt-recovery.rs:9:13 --> $DIR/cfg-stmt-recovery.rs:9:13
| |
LL | let _ = #[cfg(FALSE)] 0; LL | let _ = #[cfg(false)] 0;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -7,47 +7,47 @@
fn main() { fn main() {
let a = 413; let a = 413;
#[cfg(FALSE)] #[cfg(false)]
let a = (); let a = ();
assert_eq!(a, 413); assert_eq!(a, 413);
let mut b = 612; let mut b = 612;
#[cfg(FALSE)] #[cfg(false)]
{ {
b = 1111; b = 1111;
} }
assert_eq!(b, 612); assert_eq!(b, 612);
#[cfg(FALSE)] #[cfg(false)]
undefined_fn(); undefined_fn();
#[cfg(FALSE)] #[cfg(false)]
undefined_macro!(); undefined_macro!();
#[cfg(FALSE)] #[cfg(false)]
undefined_macro![]; undefined_macro![];
#[cfg(FALSE)] #[cfg(false)]
undefined_macro!{}; undefined_macro!{};
// pretty printer bug... // pretty printer bug...
// #[cfg(FALSE)] // #[cfg(false)]
// undefined_macro!{} // undefined_macro!{}
let () = (#[cfg(FALSE)] 341,); // Should this also work on parens? let () = (#[cfg(false)] 341,); // Should this also work on parens?
let t = (1, #[cfg(FALSE)] 3, 4); let t = (1, #[cfg(false)] 3, 4);
assert_eq!(t, (1, 4)); assert_eq!(t, (1, 4));
let f = |_: u32, _: u32| (); let f = |_: u32, _: u32| ();
f(2, 1, #[cfg(FALSE)] 6); f(2, 1, #[cfg(false)] 6);
let _: u32 = a.clone(#[cfg(FALSE)] undefined); let _: u32 = a.clone(#[cfg(false)] undefined);
let _: [(); 0] = [#[cfg(FALSE)] 126]; let _: [(); 0] = [#[cfg(false)] 126];
let t = [#[cfg(FALSE)] 1, 2, 6]; let t = [#[cfg(false)] 1, 2, 6];
assert_eq!(t, [2, 6]); assert_eq!(t, [2, 6]);
{ {
let r; let r;
#[cfg(FALSE)] #[cfg(false)]
(r = 5); (r = 5);
#[cfg(not(FALSE))] #[cfg(not(FALSE))]
(r = 10); (r = 10);
@ -75,7 +75,7 @@ fn main() {
612 612
}); });
assert_eq!((#[cfg(FALSE)] 1, #[cfg(not(FALSE))] 2), (2,)); assert_eq!((#[cfg(false)] 1, #[cfg(not(FALSE))] 2), (2,));
assert_eq!(n, 612); assert_eq!(n, 612);
// check that lints work // check that lints work

View file

@ -0,0 +1,9 @@
/// Test that `--cfg false` doesn't cause `cfg(false)` to evaluate to `true`
//@ compile-flags: --cfg false
#[cfg(false)]
fn foo() {}
fn main() {
foo(); //~ ERROR cannot find function `foo` in this scope
}

View file

@ -0,0 +1,9 @@
error[E0425]: cannot find function `foo` in this scope
--> $DIR/cmdline-false.rs:8:5
|
LL | foo();
| ^^^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0425`.

View file

@ -6,16 +6,16 @@
// Crate use statements // Crate use statements
#[cfg(FALSE)] #[cfg(false)]
use flippity; use flippity;
#[cfg(FALSE)] #[cfg(false)]
static b: bool = false; static b: bool = false;
static b: bool = true; static b: bool = true;
mod rustrt { mod rustrt {
#[cfg(FALSE)] #[cfg(false)]
extern "C" { extern "C" {
// This symbol doesn't exist and would be a link error if this // This symbol doesn't exist and would be a link error if this
// module was codegened // module was codegened
@ -25,12 +25,12 @@ mod rustrt {
extern "C" {} extern "C" {}
} }
#[cfg(FALSE)] #[cfg(false)]
type t = isize; type t = isize;
type t = bool; type t = bool;
#[cfg(FALSE)] #[cfg(false)]
enum tg { enum tg {
foo, foo,
} }
@ -39,12 +39,12 @@ enum tg {
bar, bar,
} }
#[cfg(FALSE)] #[cfg(false)]
struct r { struct r {
i: isize, i: isize,
} }
#[cfg(FALSE)] #[cfg(false)]
fn r(i: isize) -> r { fn r(i: isize) -> r {
r { i: i } r { i: i }
} }
@ -57,7 +57,7 @@ fn r(i: isize) -> r {
r { i: i } r { i: i }
} }
#[cfg(FALSE)] #[cfg(false)]
mod m { mod m {
// This needs to parse but would fail in typeck. Since it's not in // This needs to parse but would fail in typeck. Since it's not in
// the current config it should not be typechecked. // the current config it should not be typechecked.
@ -69,7 +69,7 @@ mod m {
mod m { mod m {
// Submodules have slightly different code paths than the top-level // Submodules have slightly different code paths than the top-level
// module, so let's make sure this jazz works here as well // module, so let's make sure this jazz works here as well
#[cfg(FALSE)] #[cfg(false)]
pub fn f() {} pub fn f() {}
pub fn f() {} pub fn f() {}
@ -77,7 +77,7 @@ mod m {
// Since the FALSE configuration isn't defined main will just be // Since the FALSE configuration isn't defined main will just be
// parsed, but nothing further will be done with it // parsed, but nothing further will be done with it
#[cfg(FALSE)] #[cfg(false)]
pub fn main() { pub fn main() {
panic!() panic!()
} }
@ -93,14 +93,14 @@ pub fn main() {
} }
fn test_in_fn_ctxt() { fn test_in_fn_ctxt() {
#[cfg(FALSE)] #[cfg(false)]
fn f() { fn f() {
panic!() panic!()
} }
fn f() {} fn f() {}
f(); f();
#[cfg(FALSE)] #[cfg(false)]
static i: isize = 0; static i: isize = 0;
static i: isize = 1; static i: isize = 1;
assert_eq!(i, 1); assert_eq!(i, 1);
@ -109,7 +109,7 @@ fn test_in_fn_ctxt() {
mod test_foreign_items { mod test_foreign_items {
pub mod rustrt { pub mod rustrt {
extern "C" { extern "C" {
#[cfg(FALSE)] #[cfg(false)]
pub fn write() -> String; pub fn write() -> String;
pub fn write() -> String; pub fn write() -> String;
} }
@ -117,7 +117,7 @@ mod test_foreign_items {
} }
mod test_use_statements { mod test_use_statements {
#[cfg(FALSE)] #[cfg(false)]
use flippity_foo; use flippity_foo;
} }
@ -127,24 +127,24 @@ mod test_methods {
} }
impl Fooable for Foo { impl Fooable for Foo {
#[cfg(FALSE)] #[cfg(false)]
fn what(&self) {} fn what(&self) {}
fn what(&self) {} fn what(&self) {}
#[cfg(FALSE)] #[cfg(false)]
fn the(&self) {} fn the(&self) {}
fn the(&self) {} fn the(&self) {}
} }
trait Fooable { trait Fooable {
#[cfg(FALSE)] #[cfg(false)]
fn what(&self); fn what(&self);
fn what(&self); fn what(&self);
#[cfg(FALSE)] #[cfg(false)]
fn the(&self); fn the(&self);
fn the(&self); fn the(&self);

View file

@ -12,7 +12,7 @@ LL | pub mod doesnt_exist {
note: the item is gated here note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:5:5 --> $DIR/auxiliary/cfged_out.rs:5:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in crate `cfged_out` error[E0425]: cannot find function `uwu` in crate `cfged_out`
@ -35,7 +35,7 @@ LL | pub fn uwu() {}
note: the item is gated here note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:2:5 --> $DIR/auxiliary/cfged_out.rs:2:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0425]: cannot find function `meow` in module `cfged_out::inner::right` error[E0425]: cannot find function `meow` in module `cfged_out::inner::right`

View file

@ -1,10 +1,10 @@
pub mod inner { pub mod inner {
#[cfg(FALSE)] #[cfg(false)]
mod gone { mod gone {
pub fn uwu() {} pub fn uwu() {}
} }
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
pub use super::uwu; pub use super::uwu;
//~^ NOTE found an item that was configured out //~^ NOTE found an item that was configured out
} }
@ -14,7 +14,7 @@ pub use a::x;
//~| NOTE no `x` in `a` //~| NOTE no `x` in `a`
mod a { mod a {
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
pub fn x() {} pub fn x() {}
//~^ NOTE found an item that was configured out //~^ NOTE found an item that was configured out
} }
@ -25,10 +25,10 @@ pub use b::{x, y};
//~| NOTE no `y` in `b` //~| NOTE no `y` in `b`
mod b { mod b {
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
pub fn x() {} pub fn x() {}
//~^ NOTE found an item that was configured out //~^ NOTE found an item that was configured out
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
pub fn y() {} pub fn y() {}
//~^ NOTE found an item that was configured out //~^ NOTE found an item that was configured out
} }

View file

@ -12,7 +12,7 @@ LL | pub fn x() {}
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-reexport.rs:17:5 --> $DIR/diagnostics-reexport.rs:17:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0432]: unresolved imports `b::x`, `b::y` error[E0432]: unresolved imports `b::x`, `b::y`
@ -31,7 +31,7 @@ LL | pub fn x() {}
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-reexport.rs:28:5 --> $DIR/diagnostics-reexport.rs:28:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
note: found an item that was configured out note: found an item that was configured out
--> $DIR/diagnostics-reexport.rs:32:12 --> $DIR/diagnostics-reexport.rs:32:12
@ -41,7 +41,7 @@ LL | pub fn y() {}
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-reexport.rs:31:5 --> $DIR/diagnostics-reexport.rs:31:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in module `inner` error[E0425]: cannot find function `uwu` in module `inner`
@ -58,7 +58,7 @@ LL | pub use super::uwu;
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-reexport.rs:7:5 --> $DIR/diagnostics-reexport.rs:7:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,11 +1,11 @@
#![allow(unexpected_cfgs)] // since we want to recognize them as unexpected #![allow(unexpected_cfgs)] // since we want to recognize them as unexpected
pub mod inner { pub mod inner {
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
pub fn uwu() {} pub fn uwu() {}
//~^ NOTE found an item that was configured out //~^ NOTE found an item that was configured out
#[cfg(FALSE)] //~ NOTE the item is gated here #[cfg(false)] //~ NOTE the item is gated here
//~^ NOTE the item is gated here //~^ NOTE the item is gated here
//~| NOTE the item is gated here //~| NOTE the item is gated here
pub mod doesnt_exist { pub mod doesnt_exist {

View file

@ -12,7 +12,7 @@ LL | pub mod doesnt_exist {
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5 --> $DIR/diagnostics-same-crate.rs:8:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0432]: unresolved import `super::inner::doesnt_exist` error[E0432]: unresolved import `super::inner::doesnt_exist`
@ -29,7 +29,7 @@ LL | pub mod doesnt_exist {
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5 --> $DIR/diagnostics-same-crate.rs:8:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
@ -46,7 +46,7 @@ LL | pub mod doesnt_exist {
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5 --> $DIR/diagnostics-same-crate.rs:8:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in module `inner` error[E0425]: cannot find function `uwu` in module `inner`
@ -63,7 +63,7 @@ LL | pub fn uwu() {}
note: the item is gated here note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:4:5 --> $DIR/diagnostics-same-crate.rs:4:5
| |
LL | #[cfg(FALSE)] LL | #[cfg(false)]
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0425]: cannot find function `meow` in module `inner::right` error[E0425]: cannot find function `meow` in module `inner::right`

View file

@ -1,7 +1,6 @@
//@ run-pass //@ run-pass
#![feature(link_cfg)] #![feature(link_cfg)]
#![feature(cfg_boolean_literals)]
#[cfg(true)] #[cfg(true)]
fn foo() -> bool { fn foo() -> bool {

View file

@ -12,7 +12,7 @@
//@ compile-flags: --check-cfg=cfg() --cfg=unknown_but_active_cfg //@ compile-flags: --check-cfg=cfg() --cfg=unknown_but_active_cfg
#[allow(unexpected_cfgs)] #[allow(unexpected_cfgs)]
#[cfg(FALSE)] #[cfg(unknown_and_inactive_cfg)]
//~^ WARNING unexpected `cfg` condition name //~^ WARNING unexpected `cfg` condition name
fn bar() {} fn bar() {}

View file

@ -1,10 +1,10 @@
warning: unexpected `cfg` condition name: `FALSE` warning: unexpected `cfg` condition name: `unknown_and_inactive_cfg`
--> $DIR/allow-same-level.rs:15:7 --> $DIR/allow-same-level.rs:15:7
| |
LL | #[cfg(FALSE)] LL | #[cfg(unknown_and_inactive_cfg)]
| ^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
| |
= help: to expect this configuration use `--check-cfg=cfg(FALSE)` = help: to expect this configuration use `--check-cfg=cfg(unknown_and_inactive_cfg)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default = note: `#[warn(unexpected_cfgs)]` on by default

View file

@ -6,7 +6,7 @@
#![allow(unexpected_cfgs)] #![allow(unexpected_cfgs)]
#[cfg(FALSE)] #[cfg(false)]
fn bar() {} fn bar() {}
fn foo() { fn foo() {

View file

@ -6,7 +6,7 @@
#[allow(unexpected_cfgs)] #[allow(unexpected_cfgs)]
mod aa { mod aa {
#[cfg(FALSE)] #[cfg(false)]
fn bar() {} fn bar() {}
} }

View file

@ -7,6 +7,7 @@ extern crate std;
//@ revisions: normal expanded //@ revisions: normal expanded
//@[expanded] check-pass //@[expanded] check-pass
//@[expanded]compile-flags: -Zunpretty=expanded //@[expanded]compile-flags: -Zunpretty=expanded
//@ edition: 2015
extern "路濫狼á́́" fn foo() {} extern "路濫狼á́́" fn foo() {}

View file

@ -1,5 +1,5 @@
error[E0703]: invalid ABI: found `路濫狼á́́` error[E0703]: invalid ABI: found `路濫狼á́́`
--> $DIR/unicode.rs:5:8 --> $DIR/unicode.rs:6:8
| |
LL | extern "路濫狼á́́" fn foo() {} LL | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^^ invalid ABI | ^^^^^^^^^ invalid ABI

View file

@ -1,6 +1,7 @@
//@ revisions: normal expanded //@ revisions: normal expanded
//@[expanded] check-pass //@[expanded] check-pass
//@[expanded]compile-flags: -Zunpretty=expanded //@[expanded]compile-flags: -Zunpretty=expanded
//@ edition: 2015
extern "路濫狼á́́" fn foo() {} //[normal]~ ERROR invalid ABI extern "路濫狼á́́" fn foo() {} //[normal]~ ERROR invalid ABI

View file

@ -1,18 +1,18 @@
//@ compile-flags:--cfg yes --check-cfg=cfg(yes,no) //@ compile-flags:--cfg yes --check-cfg=cfg(yes,no)
fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(FALSE)] T>() {} fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(false)] T>() {}
fn f_ty<#[cfg(FALSE)] 'a: 'a, #[cfg(yes)] T>() {} fn f_ty<#[cfg(false)] 'a: 'a, #[cfg(yes)] T>() {}
type FnGood = for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> fn(); // OK type FnGood = for<#[cfg(yes)] 'a, #[cfg(false)] T> fn(); // OK
type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn(); type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn();
//~^ ERROR only lifetime parameters can be used in this context //~^ ERROR only lifetime parameters can be used in this context
type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> Copy; // OK type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(false)] T> Copy; // OK
type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy; type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy;
//~^ ERROR only lifetime parameters can be used in this context //~^ ERROR only lifetime parameters can be used in this context
struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> u8: Copy; // OK struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(false)] T> u8: Copy; // OK
struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy; struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy;
//~^ ERROR only lifetime parameters can be used in this context //~^ ERROR only lifetime parameters can be used in this context
fn f_lt_no<#[cfg_attr(FALSE, unknown)] 'a>() {} // OK fn f_lt_no<#[cfg_attr(FALSE, unknown)] 'a>() {} // OK

View file

@ -31,7 +31,7 @@ LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
error[E0658]: only lifetime parameters can be used in this context error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:7:48 --> $DIR/cfg-generic-params.rs:7:48
| |
LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn(); LL | type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn();
| ^ | ^
| |
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
@ -41,7 +41,7 @@ LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn();
error[E0658]: only lifetime parameters can be used in this context error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:11:54 --> $DIR/cfg-generic-params.rs:11:54
| |
LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy; LL | type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy;
| ^ | ^
| |
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
@ -51,7 +51,7 @@ LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy;
error[E0658]: only lifetime parameters can be used in this context error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:15:57 --> $DIR/cfg-generic-params.rs:15:57
| |
LL | struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy; LL | struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy;
| ^ | ^
| |
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information

View file

@ -1 +1 @@
#![cfg(FALSE)] //~ ERROR `main` function not found in crate `cfg_in_crate_1` #![cfg(false)] //~ ERROR `main` function not found in crate `cfg_in_crate_1`

View file

@ -1,7 +1,7 @@
error[E0601]: `main` function not found in crate `cfg_in_crate_1` error[E0601]: `main` function not found in crate `cfg_in_crate_1`
--> $DIR/cfg-in-crate-1.rs:1:15 --> $DIR/cfg-in-crate-1.rs:1:15
| |
LL | #![cfg(FALSE)] LL | #![cfg(false)]
| ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -2,10 +2,10 @@
#![feature(custom_test_frameworks)] #![feature(custom_test_frameworks)]
fn main() { fn main() {
let _ = #[cfg(FALSE)] (); let _ = #[cfg(false)] ();
//~^ ERROR removing an expression is not supported in this position //~^ ERROR removing an expression is not supported in this position
let _ = 1 + 2 + #[cfg(FALSE)] 3; let _ = 1 + 2 + #[cfg(false)] 3;
//~^ ERROR removing an expression is not supported in this position //~^ ERROR removing an expression is not supported in this position
let _ = [1, 2, 3][#[cfg(FALSE)] 1]; let _ = [1, 2, 3][#[cfg(false)] 1];
//~^ ERROR removing an expression is not supported in this position //~^ ERROR removing an expression is not supported in this position
} }

View file

@ -1,19 +1,19 @@
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:5:13 --> $DIR/cfg-non-opt-expr.rs:5:13
| |
LL | let _ = #[cfg(FALSE)] (); LL | let _ = #[cfg(false)] ();
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:7:21 --> $DIR/cfg-non-opt-expr.rs:7:21
| |
LL | let _ = 1 + 2 + #[cfg(FALSE)] 3; LL | let _ = 1 + 2 + #[cfg(false)] 3;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:9:23 --> $DIR/cfg-non-opt-expr.rs:9:23
| |
LL | let _ = [1, 2, 3][#[cfg(FALSE)] 1]; LL | let _ = [1, 2, 3][#[cfg(false)] 1];
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,3 +1,3 @@
//@ ignore-test (auxiliary, used by other tests) //@ ignore-test (auxiliary, used by other tests)
#![cfg_attr(all(), cfg(FALSE))] #![cfg_attr(all(), cfg(false))]

View file

@ -1,6 +1,7 @@
// Test the AST pretty printer correctly handles default values for const generics // Test the AST pretty printer correctly handles default values for const generics
//@ check-pass //@ check-pass
//@ compile-flags: -Z unpretty=expanded //@ compile-flags: -Z unpretty=expanded
//@ edition: 2015
#![crate_type = "lib"] #![crate_type = "lib"]

View file

@ -3,6 +3,7 @@
// Test the AST pretty printer correctly handles default values for const generics // Test the AST pretty printer correctly handles default values for const generics
//@ check-pass //@ check-pass
//@ compile-flags: -Z unpretty=expanded //@ compile-flags: -Z unpretty=expanded
//@ edition: 2015
#![crate_type = "lib"] #![crate_type = "lib"]
#[prelude_import] #[prelude_import]

View file

@ -1,6 +1,6 @@
fn main() {} fn main() {}
#[cfg(FALSE)] #[cfg(false)]
fn container() { fn container() {
const unsafe WhereIsFerris Now() {} const unsafe WhereIsFerris Now() {}
//~^ ERROR expected one of `extern` or `fn` //~^ ERROR expected one of `extern` or `fn`

View file

@ -1,6 +1,6 @@
fn main() {} fn main() {}
#[cfg(FALSE)] #[cfg(false)]
fn container() { fn container() {
const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
//~^ ERROR expected `fn` //~^ ERROR expected `fn`

View file

@ -6,7 +6,7 @@
mod to_reuse { mod to_reuse {
use crate::S; use crate::S;
pub fn foo<'a>(#[cfg(FALSE)] a: u8, _b: &'a S) -> u32 { pub fn foo<'a>(#[cfg(false)] a: u8, _b: &'a S) -> u32 {
1 1
} }
} }

View file

@ -1,6 +1,7 @@
//@ check-pass //@ check-pass
//@ proc-macro: another-proc-macro.rs //@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition:2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]

View file

@ -3,6 +3,7 @@
//@ check-pass //@ check-pass
//@ proc-macro: another-proc-macro.rs //@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition:2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]
#[prelude_import] #[prelude_import]

View file

@ -1,5 +1,6 @@
//@ check-pass //@ check-pass
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]
use std::marker::CoercePointee; use std::marker::CoercePointee;

View file

@ -2,6 +2,7 @@
#![no_std] #![no_std]
//@ check-pass //@ check-pass
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]
#[prelude_import] #[prelude_import]
use ::std::prelude::rust_2015::*; use ::std::prelude::rust_2015::*;

View file

@ -7,6 +7,7 @@
//@ check-pass //@ check-pass
//@ proc-macro: another-proc-macro.rs //@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]

View file

@ -9,6 +9,7 @@
//@ check-pass //@ check-pass
//@ proc-macro: another-proc-macro.rs //@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded //@ compile-flags: -Zunpretty=expanded
//@ edition: 2015
#![feature(derive_coerce_pointee)] #![feature(derive_coerce_pointee)]
#[prelude_import] #[prelude_import]

View file

@ -1,5 +1,5 @@
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
fn main() { fn main() {
let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression let _ = #[cfg(false)] if true {}; //~ ERROR removing an expression
} }

View file

@ -1,7 +1,7 @@
error: removing an expression is not supported in this position error: removing an expression is not supported in this position
--> $DIR/bad-cfg.rs:4:13 --> $DIR/bad-cfg.rs:4:13
| |
LL | let _ = #[cfg(FALSE)] if true {}; LL | let _ = #[cfg(false)] if true {};
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,12 +1,12 @@
//@ check-pass //@ check-pass
#[cfg(FALSE)] #[cfg(false)]
fn simple_attr() { fn simple_attr() {
#[attr] if true {} #[attr] if true {}
#[allow_warnings] if true {} #[allow_warnings] if true {}
} }
#[cfg(FALSE)] #[cfg(false)]
fn if_else_chain() { fn if_else_chain() {
#[first_attr] if true { #[first_attr] if true {
} else if false { } else if false {
@ -14,20 +14,20 @@ fn if_else_chain() {
} }
} }
#[cfg(FALSE)] #[cfg(false)]
fn if_let() { fn if_let() {
#[attr] if let Some(_) = Some(true) {} #[attr] if let Some(_) = Some(true) {}
} }
fn bar() { fn bar() {
#[cfg(FALSE)] #[cfg(false)]
if true { if true {
let x: () = true; // Should not error due to the #[cfg(FALSE)] let x: () = true; // Should not error due to the #[cfg(false)]
} }
#[cfg_attr(not(FALSE), cfg(FALSE))] #[cfg_attr(not(FALSE), cfg(false))]
if true { if true {
let a: () = true; // Should not error due to the applied #[cfg(FALSE)] let a: () = true; // Should not error due to the applied #[cfg(false)]
} }
} }

View file

@ -1,11 +1,11 @@
#[cfg(FALSE)] #[cfg(false)]
fn if_else_parse_error() { fn if_else_parse_error() {
if true { if true {
} #[attr] else if false { //~ ERROR expected } #[attr] else if false { //~ ERROR expected
} }
} }
#[cfg(FALSE)] #[cfg(false)]
fn else_attr_ifparse_error() { fn else_attr_ifparse_error() {
if true { if true {
} else #[attr] if false { //~ ERROR outer attributes are not allowed } else #[attr] if false { //~ ERROR outer attributes are not allowed
@ -13,7 +13,7 @@ fn else_attr_ifparse_error() {
} }
} }
#[cfg(FALSE)] #[cfg(false)]
fn else_parse_error() { fn else_parse_error() {
if true { if true {
} else if false { } else if false {

View file

@ -3,7 +3,7 @@
fn main() { fn main() {
let x = 1; let x = 1;
#[cfg(FALSE)] #[cfg(false)]
if false { if false {
x = 2; x = 2;
} else if true { } else if true {

Some files were not shown because too many files have changed in this diff Show more