From e6015a6f05ece0378be1bdd8b2925770fb9e4a5d Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 16 Oct 2024 15:30:45 -0700 Subject: [PATCH] Improve diagnostics for the use of unstable library features - only emits one error/lint (instead of one per missing feature) per usage of unstable and body-unstable items - only emits one future-name-collision lint (instead of one per missing feature) for unstable trait items - makes diagnostics for unstable, soft-unstable, const-unstable, and body-unstable library features translatable, using common subdiagnostic structs. - adds notes with features, reasons, and issue links to const-unstability errors - adds notes with issue links to soft_unstable lints - on nightly, adds `#![feature]` crate attr help to soft_unstable lints - on nightly, adds compiler-upgrade-suggestion notes to const-unstable and soft_unstable diagnostics --- .../src/check_consts/check.rs | 4 +- .../rustc_const_eval/src/check_consts/ops.rs | 44 ++-- compiler/rustc_const_eval/src/errors.rs | 8 + compiler/rustc_hir_analysis/messages.ftl | 2 - .../rustc_hir_analysis/src/check/check.rs | 9 +- compiler/rustc_hir_analysis/src/check/mod.rs | 40 +--- compiler/rustc_hir_analysis/src/errors.rs | 12 +- compiler/rustc_hir_typeck/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/method/probe.rs | 14 +- .../rustc_lint/src/context/diagnostics.rs | 8 +- compiler/rustc_lint/src/lints.rs | 10 - compiler/rustc_lint_defs/src/lib.rs | 9 +- compiler/rustc_middle/messages.ftl | 19 ++ compiler/rustc_middle/src/error.rs | 70 +++++- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/middle/stability.rs | 204 ++++++++++++++---- compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_resolve/src/macros.rs | 55 +++-- compiler/rustc_session/src/errors.rs | 70 +++--- compiler/rustc_session/src/parse.rs | 16 +- tests/ui/borrowck/issue-64453.stderr | 2 + .../dont_promote_unstable_const_fn.stderr | 2 + .../min_const_fn_libstd_stability.stderr | 2 + ...in_const_unsafe_fn_libstd_stability.stderr | 1 + ...n_const_unsafe_fn_libstd_stability2.stderr | 1 + .../rustc-decodable-issue-123156.stderr | 2 + tests/ui/feature-gates/bench.stderr | 12 ++ ...ture-gate-rustc_encodable_decodable.stderr | 8 + .../const-eval-select-stability.stderr | 2 + tests/ui/lint/expansion-time.stderr | 6 + .../staged-api.stable.stderr | 5 + .../staged-api.unstable.stderr | 7 + ...stability-attribute-implies-missing.stderr | 3 + ...bility-attribute-implies-no-feature.stderr | 3 + .../soft-unstable.none.stderr | 74 +++---- tests/ui/stability-attribute/soft-unstable.rs | 8 +- .../two-unstables.none.stderr | 61 ++---- tests/ui/stability-attribute/two-unstables.rs | 13 +- .../two-unstables.some.stderr | 7 +- 39 files changed, 505 insertions(+), 318 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 72bc6e939d009..8d43cc6e915d5 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -716,7 +716,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let feature_gate_declared = gate_declared(feature); let implied_gate_declared = implied_by.is_some_and(gate_declared); if !feature_gate_declared && !implied_gate_declared { - bad_gates.push(feature); + bad_gates.push(gate.into()); continue; } @@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { continue; } - bad_gates.push(feature); + bad_gates.push(gate.into()); } if !bad_gates.is_empty() { self.check_op(ops::FnCallUnstable(callee, bad_gates)); diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index e343dddc23599..b2c7aefa3c725 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -8,6 +8,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; +use rustc_middle::middle::stability; use rustc_middle::mir::CallSource; use rustc_middle::span_bug; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; @@ -298,28 +299,35 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { /// /// Contains the names of the features that would allow the use of this function. #[derive(Debug)] -pub(crate) struct FnCallUnstable(pub DefId, pub Vec); +pub(crate) struct FnCallUnstable(pub DefId, pub Vec); impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - let FnCallUnstable(def_id, features) = self; - - let mut err = ccx - .dcx() - .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) }); - - // FIXME: make this translatable - #[allow(rustc::untranslatable_diagnostic)] - if ccx.is_const_stable_const_fn() { - err.help(fluent_generated::const_eval_const_stable); - } else if ccx.tcx.sess.is_nightly_build() && !features.is_empty() { - err.help(format!( - "add `#![feature({})]` to the crate attributes to enable", - features.iter().map(Symbol::as_str).intersperse(", ").collect::(), - )); - } + let FnCallUnstable(def_id, denials) = self; - err + let in_const_stable_context = ccx.is_const_stable_const_fn(); + // Only report unstable features when they're present. + let (features, info) = if denials.is_empty() { + (None, vec![]) + } else { + let (features, info) = stability::unstable_notes(&denials); + (Some(features), info) + }; + // Only suggest adding `#![feature]` if it could help. + let nightly_subdiags = if in_const_stable_context || denials.is_empty() { + vec![] + } else { + stability::unstable_nightly_subdiags(&ccx.tcx.sess, &denials, None) + }; + + ccx.dcx().create_err(errors::UnstableConstFn { + span, + def_path: ccx.tcx.def_path_str(def_id), + in_const_stable_context, + features, + info, + nightly_subdiags, + }) } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c943236affc56..afd9434d83264 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -115,6 +115,14 @@ pub(crate) struct UnstableConstFn { #[primary_span] pub span: Span, pub def_path: String, + #[help(const_eval_const_stable)] + pub in_const_stable_context: bool, + #[subdiagnostic] + pub features: Option, + #[subdiagnostic] + pub info: Vec, + #[subdiagnostic] + pub nightly_subdiags: Vec, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 568fe0c858360..bc48517d0883c 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -309,8 +309,6 @@ hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snip hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` .note = default implementation of `{$missing_item_name}` is unstable - .some_note = use of unstable library feature `{$feature}`: {$reason} - .none_note = use of unstable library feature `{$feature}` hir_analysis_missing_type_params = the type {$parameterCount -> diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1f96f4c59cc7c..8192789e35e2e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -933,14 +933,7 @@ fn check_impl_items_against_trait<'tcx>( let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); match tcx.eval_default_body_stability(trait_item_id, full_impl_span) { EvalResult::Deny { denials, .. } => { - for denial in denials { - default_body_is_unstable( - tcx, - full_impl_span, - trait_item_id, - denial.unstability, - ); - } + default_body_is_unstable(tcx, full_impl_span, trait_item_id, &denials); } // Unmarked default bodies are considered stable (at least for now). diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 6f273cbe11049..0e4e0e993d77d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -80,6 +80,7 @@ use rustc_index::bit_set::BitSet; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; +use rustc_middle::middle::stability; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt}; @@ -293,41 +294,22 @@ fn default_body_is_unstable( tcx: TyCtxt<'_>, impl_span: Span, item_did: DefId, - unstability: rustc_attr::Unstability, + denials: &[stability::EvalDenial], ) { - let rustc_attr::Unstability { feature, reason, issue, .. } = unstability; let missing_item_name = tcx.associated_item(item_did).name; - let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new()); - match reason.to_opt_reason() { - Some(r) => { - some_note = true; - reason_str = r.to_string(); - } - None => none_note = true, - }; - - let mut err = tcx.dcx().create_err(errors::MissingTraitItemUnstable { - span: impl_span, - some_note, - none_note, - missing_item_name, - feature, - reason: reason_str, - }); - let inject_span = item_did .as_local() .and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id))); - rustc_session::parse::add_feature_diagnostics_for_issue( - &mut err, - &tcx.sess, - feature, - rustc_feature::GateIssue::Library(issue), - false, - inject_span, - ); + let (features, info) = stability::unstable_notes(denials); + let nightly_subdiags = stability::unstable_nightly_subdiags(&tcx.sess, denials, inject_span); - err.emit(); + tcx.dcx().emit_err(errors::MissingTraitItemUnstable { + span: impl_span, + missing_item_name, + features, + info, + nightly_subdiags, + }); } /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions. diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index af4445a7fd48a..17fca01df9803 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -977,13 +977,13 @@ pub(crate) struct MissingOneOfTraitItem { pub(crate) struct MissingTraitItemUnstable { #[primary_span] pub span: Span, - #[note(hir_analysis_some_note)] - pub some_note: bool, - #[note(hir_analysis_none_note)] - pub none_note: bool, pub missing_item_name: Symbol, - pub feature: Symbol, - pub reason: String, + #[subdiagnostic] + pub features: rustc_middle::error::UnstableLibraryFeatureNote, + #[subdiagnostic] + pub info: Vec, + #[subdiagnostic] + pub nightly_subdiags: Vec, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6b0a897faba94..413bf103e63a5 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -4,6 +4,7 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index d6a2ff13c0542..488e434d22a12 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1329,10 +1329,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let stability::EvalResult::Deny { denials, .. } = self.tcx.eval_stability(candidate.item.def_id, None, self.span, None) { - uc.push(( - candidate.clone(), - denials.iter().map(|d| d.unstability.feature).collect(), - )); + uc.push((candidate.clone(), denials.iter().map(|d| d.feature).collect())); return false; } true @@ -1431,10 +1428,11 @@ impl<'tcx> Pick<'tcx> { tcx.disabled_nightly_features( lint, Some(scope_expr_id), - self.unstable_candidates.iter().flat_map(|(candidate, features)| { - features.iter().map(|feature| { - (format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), *feature) - }) + self.unstable_candidates.iter().map(|(candidate, features)| { + ( + format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), + features.iter().map(Symbol::as_str).intersperse(", ").collect::(), + ) }), ); }); diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 565c3c0425256..99878949b5984 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -382,8 +382,12 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::MacroRuleNeverUsed(n, name) => { lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag); } - BuiltinLintDiag::UnstableFeature(msg) => { - lints::UnstableFeature { msg }.decorate_lint(diag); + BuiltinLintDiag::SoftUnstableMacro { features } => { + let denials = features + .iter() + .map(|&(feature, reason, issue)| stability::EvalDenial { feature, reason, issue }) + .collect::>(); + stability::soft_unstable(sess, &denials, vec![]).decorate_lint(diag); } BuiltinLintDiag::AvoidUsingIntelSyntax => { lints::AvoidIntelSyntax.decorate_lint(diag); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 16cfae17d4020..0ca990727adf2 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2404,16 +2404,6 @@ pub(crate) struct MacroRuleNeverUsed { pub name: Symbol, } -pub(crate) struct UnstableFeature { - pub msg: DiagMessage, -} - -impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(self.msg); - } -} - #[derive(LintDiagnostic)] #[diag(lint_avoid_intel_syntax)] pub(crate) struct AvoidIntelSyntax; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c01fa5c54d65e..a18e7307e0940 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -2,13 +2,15 @@ #![warn(unreachable_pub)] // tidy-alphabetical-end +use std::num::NonZero; + use rustc_ast::node_id::NodeId; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::{DiagMessage, MultiSpan}; +use rustc_error_messages::MultiSpan; use rustc_hir::def::Namespace; use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; @@ -715,7 +717,10 @@ pub enum BuiltinLintDiag { MacroIsPrivate(Ident), UnusedMacroDefinition(Symbol), MacroRuleNeverUsed(usize, Symbol), - UnstableFeature(DiagMessage), + SoftUnstableMacro { + /// The name, optional reason, and issue number for each disabled unstable feature used. + features: Vec<(Symbol, Option, Option>)>, + }, AvoidUsingIntelSyntax, AvoidUsingAttSyntax, IncompleteInclude, diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 39485a324f2e2..25212a98a485b 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -102,6 +102,25 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$ middle_unknown_layout = the type `{$ty}` has an unknown layout +middle_unstable_library_feature = use of unstable library {$count -> + [one] feature {$features}{$single_feature_has_reason -> + [true] : {$reason_for_single_feature} + *[false] {""} + } + *[other] features {$features} +} + +middle_unstable_library_feature_issue = + see issue #{$issue} for more information{$show_feature -> + [true] {" "}about `{$feature}` + *[false] {""} + } + +middle_unstable_library_feature_reason = reason for `{$feature}`: {$reason} + +middle_unstable_library_feature_suggestion_for_allocator_api = + consider wrapping the inner types in tuple + middle_values_too_big = values of the type `{$ty}` are too big for the target architecture middle_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 5c2aa0005d405..c0eba72ff62b0 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,9 +1,10 @@ use std::fmt; +use std::num::NonZero; use std::path::PathBuf; use rustc_errors::codes::*; -use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage}; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, DiagSymbolList}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use crate::ty::Ty; @@ -164,3 +165,68 @@ pub struct TypeLengthLimit { pub path: PathBuf, pub type_length: usize, } + +#[derive(Diagnostic)] +#[diag(middle_unstable_library_feature, code = E0658)] +pub struct UnstableLibraryFeatureError { + #[primary_span] + pub span: Span, + pub features: DiagSymbolList, + pub count: usize, + pub single_feature_has_reason: bool, + pub reason_for_single_feature: String, + #[subdiagnostic] + pub info: Vec, + #[subdiagnostic] + pub nightly_subdiags: Vec, + #[subdiagnostic] + pub suggestions: Vec, +} + +/// Lint diagnostic for [`rustc_lint_defs::builtin::SOFT_UNSTABLE`] +#[derive(LintDiagnostic)] +#[diag(middle_unstable_library_feature)] +pub struct SoftUnstableLibraryFeature { + pub features: DiagSymbolList, + pub count: usize, + pub single_feature_has_reason: bool, + pub reason_for_single_feature: String, + #[subdiagnostic] + pub info: Vec, + #[subdiagnostic] + pub nightly_subdiags: Vec, + #[subdiagnostic] + pub suggestions: Vec, +} + +/// A note for other diagnostics which report unstable library features +#[derive(Subdiagnostic)] +#[note(middle_unstable_library_feature)] +pub struct UnstableLibraryFeatureNote { + pub features: DiagSymbolList, + pub count: usize, + pub single_feature_has_reason: bool, + pub reason_for_single_feature: String, +} + +#[derive(Subdiagnostic)] +pub enum UnstableLibraryFeatureInfo { + #[note(middle_unstable_library_feature_reason)] + Reason { reason: String, feature: Symbol }, + #[note(middle_unstable_library_feature_issue)] + Issue { issue: NonZero, feature: Symbol, show_feature: bool }, +} + +#[derive(Subdiagnostic)] +pub enum UnstableLibraryFeatureSugg { + #[suggestion( + middle_unstable_library_feature_suggestion_for_allocator_api, + code = "({snippet})", + applicability = "maybe-incorrect" + )] + ForAllocatorApi { + #[primary_span] + inner_types: Span, + snippet: String, + }, +} diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e9b73d25ba208..e98e8e579cd0f 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -48,6 +48,7 @@ #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(iter_from_coroutine)] +#![feature(iter_intersperse)] #![feature(let_chains)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index e66aa7b323d8d..e8344753831a9 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -8,22 +8,25 @@ use rustc_attr::{ self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, }; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee}; -use rustc_feature::GateIssue; +use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; +use rustc_session::errors::NightlyFeatureDiagnostic; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer}; -use rustc_session::parse::feature_err_issue; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; use tracing::debug; pub use self::StabilityLevel::*; +use crate::error::{ + SoftUnstableLibraryFeature, UnstableLibraryFeatureError, UnstableLibraryFeatureInfo, + UnstableLibraryFeatureNote, UnstableLibraryFeatureSugg, +}; use crate::ty::{self, TyCtxt}; #[derive(PartialEq, Clone, Copy, Debug)] @@ -104,31 +107,140 @@ impl<'tcx> Index<'tcx> { } } +/// Produces notes with reasons and issue numbers for missing unstable library features +pub fn unstable_notes( + denials: &[EvalDenial], +) -> (UnstableLibraryFeatureNote, Vec) { + use UnstableLibraryFeatureInfo::*; + + let count = denials.len(); + let features = denials.iter().map(|d| d.feature).collect(); + // if there's only one missing feature, put the reason for it on the same line + let (single_feature_has_reason, reason_for_single_feature) = match denials { + [EvalDenial { reason: Some(reason), .. }] => (true, reason.to_string()), + _ => (false, String::new()), + }; + let primary = UnstableLibraryFeatureNote { + features, + count, + single_feature_has_reason, + reason_for_single_feature, + }; + + let info = denials.iter().flat_map(|&EvalDenial { feature, reason, issue }| { + // don't repeat the reason if it's on the first line + let reason_info = if !single_feature_has_reason && let Some(reason) = reason { + Some(Reason { reason: reason.to_string(), feature }) + } else { + None + }; + // don't list the feature with the issue if there's only one feature or if it was just + // provided by a reason note + let show_feature = count > 1 && reason_info.is_none(); + let issue_info = issue.map(|issue| Issue { issue, feature, show_feature }); + + reason_info.into_iter().chain(issue_info) + }); + + (primary, info.collect()) +} + +/// Produces help/suggestions/notes for how to enable missing unstable features on nightly +pub fn unstable_nightly_subdiags( + sess: &Session, + denials: &[EvalDenial], + inject_span: Option, +) -> Vec { + if sess.is_nightly_build() { + let feature = denials.iter().map(|d| d.feature.as_str()).intersperse(", ").collect(); + + std::iter::once(if let Some(span) = inject_span { + NightlyFeatureDiagnostic::Suggestion { feature, span } + } else { + NightlyFeatureDiagnostic::Help { feature } + }) + .chain(NightlyFeatureDiagnostic::suggest_upgrade_compiler(sess)) + .collect() + } else { + vec![] + } +} + +/// Emits an error for the use of disabled unstable library features pub fn report_unstable( sess: &Session, - denial: EvalDenial, - is_soft: bool, + denials: &[EvalDenial], + suggestions: Vec, span: Span, - soft_handler: impl FnOnce(&'static Lint, Span, String), ) { - let attr::Unstability { feature, reason, issue, .. } = denial.unstability; + let (message, info) = unstable_notes(denials); + let UnstableLibraryFeatureNote { + features, + count, + single_feature_has_reason, + reason_for_single_feature, + } = message; + let nightly_subdiags = unstable_nightly_subdiags(sess, denials, None); + + sess.dcx().emit_err(UnstableLibraryFeatureError { + span, + features, + count, + single_feature_has_reason, + reason_for_single_feature, + info, + suggestions, + nightly_subdiags, + }); +} - let msg = match reason.to_opt_reason() { - Some(r) => format!("use of unstable library feature `{feature}`: {r}"), - None => format!("use of unstable library feature `{feature}`"), - }; +/// Constructs a lint diagnostic for [`SOFT_UNSTABLE`] +pub fn soft_unstable( + sess: &Session, + denials: &[EvalDenial], + suggestions: Vec, +) -> SoftUnstableLibraryFeature { + let (message, mut info) = unstable_notes(denials); + let UnstableLibraryFeatureNote { + features, + count, + single_feature_has_reason, + reason_for_single_feature, + } = message; + let nightly_subdiags = unstable_nightly_subdiags(sess, denials, None); + + // Since SOFT_UNSTABLE puts an issue link between the contents of `message` and `info`, + // always provide the feature name for context if the first info is an issue link. + if let Some(UnstableLibraryFeatureInfo::Issue { show_feature, .. }) = info.first_mut() { + *show_feature = true; + } - if is_soft { - soft_handler(SOFT_UNSTABLE, span, msg) - } else { - let mut err = feature_err_issue(sess, feature, span, GateIssue::Library(issue), msg); - if let Some((inner_types, msg, sugg, applicability)) = denial.suggestion { - err.span_suggestion(inner_types, msg, sugg, applicability); - } - err.emit(); + SoftUnstableLibraryFeature { + features, + count, + single_feature_has_reason, + reason_for_single_feature, + info, + suggestions, + nightly_subdiags, } } +/// Buffers a [`SOFT_UNSTABLE`] lint for soft-unstable macro usage +pub fn report_soft_unstable_macro( + lint_buffer: &mut LintBuffer, + denials: &[EvalDenial], + span: Span, + node_id: NodeId, +) { + lint_buffer.buffer_lint(SOFT_UNSTABLE, node_id, span, BuiltinLintDiag::SoftUnstableMacro { + features: denials + .iter() + .map(|&EvalDenial { feature, reason, issue }| (feature, reason, issue)) + .collect(), + }); +} + fn deprecation_lint(is_in_effect: bool) -> &'static Lint { if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE } } @@ -264,15 +376,24 @@ pub enum EvalResult { Allow, /// We cannot use the item because it is unstable and we did not enable the /// corresponding feature gates. - Deny { denials: Vec, is_soft: bool }, + Deny { denials: Vec, suggestions: Vec, is_soft: bool }, /// The item does not have the `#[stable]` or `#[unstable]` marker assigned. Unmarked, } /// An instance of a disabled feature required for an unstable item +#[derive(Debug)] pub struct EvalDenial { - pub unstability: attr::Unstability, - pub suggestion: Option<(Span, String, String, Applicability)>, + pub feature: Symbol, + pub reason: Option, + pub issue: Option>, +} + +impl<'a> From<&'a attr::Unstability> for EvalDenial { + fn from(unstab: &attr::Unstability) -> Self { + let reason = unstab.reason.to_opt_reason(); + EvalDenial { feature: unstab.feature, reason, issue: unstab.issue } + } } // See issue #38412. @@ -297,19 +418,17 @@ fn suggestion_for_allocator_api( def_id: DefId, span: Span, feature: Symbol, -) -> Option<(Span, String, String, Applicability)> { +) -> Option { if feature == sym::allocator_api { if let Some(trait_) = tcx.opt_parent(def_id) { if tcx.is_diagnostic_item(sym::Vec, trait_) { let sm = tcx.sess.psess.source_map(); let inner_types = sm.span_extend_to_prev_char(span, '<', true); if let Ok(snippet) = sm.span_to_snippet(inner_types) { - return Some(( + return Some(UnstableLibraryFeatureSugg::ForAllocatorApi { inner_types, - "consider wrapping the inner types in tuple".to_string(), - format!("({snippet})"), - Applicability::MaybeIncorrect, - )); + snippet, + }); } } } @@ -421,6 +540,7 @@ impl<'tcx> TyCtxt<'tcx> { } let mut denials = vec![]; + let mut suggestions = vec![]; for unstability in unstables { let &attr::Unstability { feature, issue, .. } = unstability; @@ -457,14 +577,14 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - let suggestion = suggestion_for_allocator_api(self, def_id, span, feature); - denials.push(EvalDenial { unstability: *unstability, suggestion }); + denials.push(unstability.into()); + suggestions.extend(suggestion_for_allocator_api(self, def_id, span, feature)); } if denials.is_empty() { EvalResult::Allow } else { - EvalResult::Deny { denials, is_soft: *is_soft } + EvalResult::Deny { denials, suggestions, is_soft: *is_soft } } } Some(_) => { @@ -516,13 +636,13 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - denials.push(EvalDenial { unstability: *unstability, suggestion: None }); + denials.push(unstability.into()); } if denials.is_empty() { EvalResult::Allow } else { - EvalResult::Deny { denials, is_soft: *is_soft } + EvalResult::Deny { denials, is_soft: *is_soft, suggestions: vec![] } } } Some(_) => { @@ -600,19 +720,21 @@ impl<'tcx> TyCtxt<'tcx> { allow_unstable: AllowUnstable, unmarked: impl FnOnce(Span, DefId), ) -> bool { - let soft_handler = |lint, span, msg: String| { - self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { - lint.primary_message(msg); - }) - }; let eval_result = self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable); let is_allowed = matches!(eval_result, EvalResult::Allow); match eval_result { EvalResult::Allow => {} - EvalResult::Deny { denials, is_soft } => { - for denial in denials { - report_unstable(self.sess, denial, is_soft, span, soft_handler); + EvalResult::Deny { denials, is_soft, suggestions } => { + if is_soft { + self.emit_node_span_lint( + SOFT_UNSTABLE, + id.unwrap_or(hir::CRATE_HIR_ID), + span, + soft_unstable(self.sess, &denials, suggestions), + ); + } else { + report_unstable(self.sess, &denials, suggestions, span); } } EvalResult::Unmarked => unmarked(span, def_id), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4e54c65adef53..5db1f8428e1f2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2936,22 +2936,22 @@ impl<'tcx> TyCtxt<'tcx> { self, diag: &mut Diag<'_, E>, hir_id: Option, - features: impl IntoIterator, + featuresets: impl IntoIterator, ) { if !self.sess.is_nightly_build() { return; } let span = hir_id.and_then(|id| self.crate_level_attribute_injection_span(id)); - for (desc, feature) in features { + for (desc, features) in featuresets { // FIXME: make this string translatable let msg = - format!("add `#![feature({feature})]` to the crate attributes to enable{desc}"); + format!("add `#![feature({features})]` to the crate attributes to enable{desc}"); if let Some(span) = span { diag.span_suggestion_verbose( span, msg, - format!("#![feature({feature})]\n"), + format!("#![feature({features})]\n"), Applicability::MaybeIncorrect, ); } else { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7af2e2b803e83..10a61bf634951 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -994,36 +994,31 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { node_id: NodeId, ) { let span = path.span; - if let Some(stability) = &ext.stability { - if let StabilityLevel::Unstable { unstables, is_soft } = &stability.level { - let is_allowed = |feature| { - self.tcx.features().declared_features.contains(&feature) - || span.allows_unstable(feature) - }; - for unstability in unstables { - let allowed_by_implication = - unstability.implied_by.is_some_and(|feature| is_allowed(feature)); - if !is_allowed(unstability.feature) && !allowed_by_implication { - let lint_buffer = &mut self.lint_buffer; - let soft_handler = |lint, span, msg: String| { - lint_buffer.buffer_lint( - lint, - node_id, - span, - BuiltinLintDiag::UnstableFeature( - // FIXME make this translatable - msg.into(), - ), - ) - }; - stability::report_unstable( - self.tcx.sess, - stability::EvalDenial { unstability: *unstability, suggestion: None }, - *is_soft, - span, - soft_handler, - ); - } + if let Some(stability) = &ext.stability + && let StabilityLevel::Unstable { unstables, is_soft } = &stability.level + { + let is_allowed = |feature| { + self.tcx.features().declared_features.contains(&feature) + || span.allows_unstable(feature) + }; + let allowed_by_implication = |unstability: &rustc_attr::Unstability| { + unstability.implied_by.is_some_and(|feature| is_allowed(feature)) + }; + let denials = unstables + .iter() + .filter(|u| !(is_allowed(u.feature) || allowed_by_implication(u))) + .map(|u| u.into()) + .collect::>(); + if !denials.is_empty() { + if *is_soft { + stability::report_soft_unstable_macro( + &mut self.lint_buffer, + &denials, + span, + node_id, + ); + } else { + stability::report_unstable(self.tcx.sess, &denials, vec![], span); } } } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index dbb74d1e2446e..b111b43f99ca2 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -11,6 +11,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; +use crate::Session; use crate::config::CrateType; use crate::parse::ParseSess; @@ -28,52 +29,41 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError { #[derive(Subdiagnostic)] #[note(session_feature_diagnostic_for_issue)] -pub(crate) struct FeatureDiagnosticForIssue { - pub(crate) n: NonZero, +pub struct FeatureDiagnosticForIssue { + pub n: NonZero, } #[derive(Subdiagnostic)] -#[note(session_feature_suggest_upgrade_compiler)] -pub(crate) struct SuggestUpgradeCompiler { - date: &'static str, -} - -impl SuggestUpgradeCompiler { - pub(crate) fn ui_testing() -> Self { - Self { date: "YYYY-MM-DD" } - } - - pub(crate) fn new() -> Option { - let date = option_env!("CFG_VER_DATE")?; - - Some(Self { date }) +pub enum NightlyFeatureDiagnostic { + #[help(session_feature_diagnostic_help)] + Help { feature: String }, + #[suggestion( + session_feature_diagnostic_suggestion, + applicability = "maybe-incorrect", + code = "#![feature({feature})]\n" + )] + Suggestion { + feature: String, + #[primary_span] + span: Span, + }, + #[help(session_cli_feature_diagnostic_help)] + CliHelp { feature: String }, + #[note(session_feature_suggest_upgrade_compiler)] + SuggestUpgradeCompiler { date: &'static str }, +} + +impl NightlyFeatureDiagnostic { + pub fn suggest_upgrade_compiler(sess: &Session) -> Option { + if sess.opts.unstable_opts.ui_testing { + Some(Self::SuggestUpgradeCompiler { date: "YYYY-MM-DD" }) + } else { + let date = option_env!("CFG_VER_DATE")?; + Some(Self::SuggestUpgradeCompiler { date }) + } } } -#[derive(Subdiagnostic)] -#[help(session_feature_diagnostic_help)] -pub(crate) struct FeatureDiagnosticHelp { - pub(crate) feature: Symbol, -} - -#[derive(Subdiagnostic)] -#[suggestion( - session_feature_diagnostic_suggestion, - applicability = "maybe-incorrect", - code = "#![feature({feature})]\n" -)] -pub struct FeatureDiagnosticSuggestion { - pub feature: Symbol, - #[primary_span] - pub span: Span, -} - -#[derive(Subdiagnostic)] -#[help(session_cli_feature_diagnostic_help)] -pub(crate) struct CliFeatureDiagnosticHelp { - pub(crate) feature: Symbol, -} - #[derive(Diagnostic)] #[diag(session_not_circumvent_feature)] pub(crate) struct NotCircumventFeature; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 3d44810e7dd36..7a9d8b28fd803 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -20,10 +20,7 @@ use rustc_span::{Span, Symbol}; use crate::Session; use crate::config::{Cfg, CheckCfg}; -use crate::errors::{ - CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, - FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler, -}; +use crate::errors::{FeatureDiagnosticForIssue, FeatureGateError, NightlyFeatureDiagnostic}; use crate::lint::builtin::UNSTABLE_SYNTAX_PRE_EXPANSION; use crate::lint::{BufferedEarlyLint, BuiltinLintDiag, Lint, LintId}; @@ -183,17 +180,16 @@ pub fn add_feature_diagnostics_for_issue( // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.psess.unstable_features.is_nightly_build() { + let feature = feature.to_string(); if feature_from_cli { - err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); + err.subdiagnostic(NightlyFeatureDiagnostic::CliHelp { feature }); } else if let Some(span) = inject_span { - err.subdiagnostic(FeatureDiagnosticSuggestion { feature, span }); + err.subdiagnostic(NightlyFeatureDiagnostic::Suggestion { feature, span }); } else { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); + err.subdiagnostic(NightlyFeatureDiagnostic::Help { feature }); } - if sess.opts.unstable_opts.ui_testing { - err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); - } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { + if let Some(suggestion) = NightlyFeatureDiagnostic::suggest_upgrade_compiler(sess) { err.subdiagnostic(suggestion); } } diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr index e671817633be4..9e964647a3ef5 100644 --- a/tests/ui/borrowck/issue-64453.stderr +++ b/tests/ui/borrowck/issue-64453.stderr @@ -4,7 +4,9 @@ error: `Arguments::<'a>::new_const` is not yet stable as a const fn LL | static settings_dir: String = format!(""); | ^^^^^^^^^^^ | + = note: use of unstable library feature `const_fmt_arguments_new` = help: add `#![feature(const_fmt_arguments_new)]` 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 error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const fn `format` in statics diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index 2e697b219c5a4..0029640a8535a 100644 --- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -4,7 +4,9 @@ error: `foo` is not yet stable as a const fn LL | const fn bar() -> u32 { foo() } | ^^^^^ | + = note: use of unstable library feature `foo` = help: add `#![feature(foo)]` 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[E0716]: temporary value dropped while borrowed --> $DIR/dont_promote_unstable_const_fn.rs:17:28 diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index fedc5a4809d65..02fee2c2dc8e7 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -5,6 +5,7 @@ LL | const fn bar() -> u32 { foo() } | ^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: `foo2` is not yet stable as a const fn --> $DIR/min_const_fn_libstd_stability.rs:25:26 @@ -38,6 +39,7 @@ LL | foo() | ^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: `foo2_gated` is not yet stable as a const fn --> $DIR/min_const_fn_libstd_stability.rs:44:32 diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 353b117efbc8f..5c817c5fb9b21 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -5,6 +5,7 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | ^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: `foo2` is not yet stable as a const fn --> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42 diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index e90ba9b912fe1..e97eac70806d4 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -5,6 +5,7 @@ LL | const unsafe fn bar() -> u32 { foo() } | ^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: `foo2` is not yet stable as a const fn --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33 diff --git a/tests/ui/derives/rustc-decodable-issue-123156.stderr b/tests/ui/derives/rustc-decodable-issue-123156.stderr index 93a993b90d814..918ee855167c0 100644 --- a/tests/ui/derives/rustc-decodable-issue-123156.stderr +++ b/tests/ui/derives/rustc-decodable-issue-123156.stderr @@ -7,4 +7,6 @@ LL | #[derive(RustcDecodable)] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = help: add `#![feature(rustc_encodable_decodable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr index de78e863012dd..5a38be1398842 100644 --- a/tests/ui/feature-gates/bench.stderr +++ b/tests/ui/feature-gates/bench.stderr @@ -6,6 +6,9 @@ LL | #[bench] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` 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: `#[deny(soft_unstable)]` on by default error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable @@ -16,6 +19,9 @@ LL | use bench as _; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` 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: aborting due to 2 previous errors @@ -28,6 +34,9 @@ LL | #[bench] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` 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: `#[deny(soft_unstable)]` on by default Future breakage diagnostic: @@ -39,5 +48,8 @@ LL | use bench as _; | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` 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: `#[deny(soft_unstable)]` on by default diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr index b949dbb9da21c..ad80cbdf817d4 100644 --- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr @@ -14,6 +14,8 @@ LL | RustcEncodable, | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = help: add `#![feature(rustc_encodable_decodable)]` 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: `#[deny(soft_unstable)]` on by default warning: use of deprecated macro `RustcEncodable`: rustc-serialize is deprecated and no longer supported @@ -32,6 +34,8 @@ LL | RustcDecodable, | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = help: add `#![feature(rustc_encodable_decodable)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: use of deprecated macro `RustcDecodable`: rustc-serialize is deprecated and no longer supported --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 @@ -51,6 +55,8 @@ LL | RustcEncodable, | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = help: add `#![feature(rustc_encodable_decodable)]` 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: `#[deny(soft_unstable)]` on by default Future breakage diagnostic: @@ -62,5 +68,7 @@ LL | RustcDecodable, | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = help: add `#![feature(rustc_encodable_decodable)]` 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: `#[deny(soft_unstable)]` on by default diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr index 335b9877aa008..8e1b360caf3e3 100644 --- a/tests/ui/intrinsics/const-eval-select-stability.stderr +++ b/tests/ui/intrinsics/const-eval-select-stability.stderr @@ -5,6 +5,8 @@ LL | const_eval_select((), nothing, log); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `const_eval_select` + = note: see issue #124625 for more information error: aborting due to 1 previous error diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr index f65627c2c0878..5846b0aeb947c 100644 --- a/tests/ui/lint/expansion-time.stderr +++ b/tests/ui/lint/expansion-time.stderr @@ -34,6 +34,9 @@ LL | #[bench] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date note: the lint level is defined here --> $DIR/expansion-time.rs:12:8 | @@ -78,6 +81,9 @@ LL | #[bench] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #50297 for more information about `test` + = help: add `#![feature(test)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date note: the lint level is defined here --> $DIR/expansion-time.rs:12:8 | diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index 6c07a253f5b09..29a473c9c9039 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -27,7 +27,9 @@ error: `::func` is not yet stable a LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | + = note: use of unstable library feature `unstable` = help: add `#![feature(unstable)]` 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: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:45:5 @@ -35,7 +37,9 @@ error: `::func` is not yet stable a LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | + = note: use of unstable library feature `unstable` = help: add `#![feature(unstable)]` 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: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:55:5 @@ -44,6 +48,7 @@ LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `unstable` error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index 1c772f13dd511..33c2ffd671c3d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -4,7 +4,9 @@ error: `::func` is not yet stable as a const fn LL | Foo::func(); | ^^^^^^^^^^^ | + = note: use of unstable library feature `foo` = help: add `#![feature(foo)]` 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: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:47:5 @@ -12,7 +14,9 @@ error: `::func` is not yet stable as a const fn LL | Foo::func(); | ^^^^^^^^^^^ | + = note: use of unstable library feature `foo` = help: add `#![feature(foo)]` 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: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:55:5 @@ -21,6 +25,7 @@ LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `unstable` error: `::func` is not yet stable as a const fn --> $DIR/staged-api.rs:57:5 @@ -29,6 +34,7 @@ LL | Foo::func(); | ^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: `const_context_not_const_stable` is not yet stable as a const fn --> $DIR/staged-api.rs:59:5 @@ -37,6 +43,7 @@ LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: const-stable functions can only call other const-stable functions + = note: use of unstable library feature `foo` error: aborting due to 5 previous errors diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr index 918d6ebf99226..10b65ee76ab77 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr @@ -10,7 +10,10 @@ error: `foobar` is not yet stable as a const fn LL | const VAR: u32 = foobar(); | ^^^^^^^^ | + = note: use of unstable library feature `const_foobar` + = note: see issue #1 for more information = help: add `#![feature(const_foobar)]` 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: aborting due to 2 previous errors diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr index 0a5f58288fa33..daa7ae12468bd 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr @@ -4,7 +4,10 @@ error: `foobar` is not yet stable as a const fn LL | foobar(); | ^^^^^^^^ | + = note: use of unstable library feature `const_foobar` + = note: see issue #1 for more information = help: add `#![feature(const_foobar)]` 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: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/soft-unstable.none.stderr b/tests/ui/stability-attribute/soft-unstable.none.stderr index cd34cafbdd4f4..0a68e64874e28 100644 --- a/tests/ui/stability-attribute/soft-unstable.none.stderr +++ b/tests/ui/stability-attribute/soft-unstable.none.stderr @@ -1,4 +1,4 @@ -error: use of unstable library feature `a` +error: use of unstable library features `a` and `b` --> $DIR/soft-unstable.rs:11:5 | LL | soft_unstable::mac!(); @@ -6,50 +6,31 @@ LL | soft_unstable::mac!(); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #1 for more information about `a` + = note: reason for `b`: reason b + = note: see issue #2 for more information + = help: add `#![feature(a, b)]` 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: `#[deny(soft_unstable)]` on by default -error: use of unstable library feature `b`: reason b - --> $DIR/soft-unstable.rs:11:5 - | -LL | soft_unstable::mac!(); - | ^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - -error: use of unstable library feature `c` - --> $DIR/soft-unstable.rs:16:5 +error: use of unstable library features `c` and `d` + --> $DIR/soft-unstable.rs:14:5 | LL | soft_unstable::something(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #3 for more information about `c` + = note: reason for `d`: reason d + = note: see issue #4 for more information + = help: add `#![feature(c, d)]` 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: use of unstable library feature `d`: reason d - --> $DIR/soft-unstable.rs:16:5 - | -LL | soft_unstable::something(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature `a` - --> $DIR/soft-unstable.rs:11:5 - | -LL | soft_unstable::mac!(); - | ^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -Future breakage diagnostic: -error: use of unstable library feature `b`: reason b +error: use of unstable library features `a` and `b` --> $DIR/soft-unstable.rs:11:5 | LL | soft_unstable::mac!(); @@ -57,27 +38,26 @@ LL | soft_unstable::mac!(); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #1 for more information about `a` + = note: reason for `b`: reason b + = note: see issue #2 for more information + = help: add `#![feature(a, b)]` 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: `#[deny(soft_unstable)]` on by default Future breakage diagnostic: -error: use of unstable library feature `c` - --> $DIR/soft-unstable.rs:16:5 - | -LL | soft_unstable::something(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -Future breakage diagnostic: -error: use of unstable library feature `d`: reason d - --> $DIR/soft-unstable.rs:16:5 +error: use of unstable library features `c` and `d` + --> $DIR/soft-unstable.rs:14:5 | LL | soft_unstable::something(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 + = note: see issue #3 for more information about `c` + = note: reason for `d`: reason d + = note: see issue #4 for more information + = help: add `#![feature(c, d)]` 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: `#[deny(soft_unstable)]` on by default diff --git a/tests/ui/stability-attribute/soft-unstable.rs b/tests/ui/stability-attribute/soft-unstable.rs index d47f174da3c0c..1c4078e66a9e0 100644 --- a/tests/ui/stability-attribute/soft-unstable.rs +++ b/tests/ui/stability-attribute/soft-unstable.rs @@ -9,13 +9,9 @@ extern crate soft_unstable; fn main() { soft_unstable::mac!(); - //[none]~^ ERROR use of unstable library feature `a` [soft_unstable] - //[none]~| WARNING this was previously accepted by the compiler but is being phased out - //[none]~| ERROR use of unstable library feature `b`: reason b [soft_unstable] + //[none]~^ ERROR use of unstable library features `a` and `b` [soft_unstable] //[none]~| WARNING this was previously accepted by the compiler but is being phased out soft_unstable::something(); - //[none]~^ ERROR use of unstable library feature `c` [soft_unstable] - //[none]~| WARNING this was previously accepted by the compiler but is being phased out - //[none]~| ERROR use of unstable library feature `d`: reason d [soft_unstable] + //[none]~^ ERROR use of unstable library features `c` and `d` [soft_unstable] //[none]~| WARNING this was previously accepted by the compiler but is being phased out } diff --git a/tests/ui/stability-attribute/two-unstables.none.stderr b/tests/ui/stability-attribute/two-unstables.none.stderr index bef40de29d777..cf0ee857ea329 100644 --- a/tests/ui/stability-attribute/two-unstables.none.stderr +++ b/tests/ui/stability-attribute/two-unstables.none.stderr @@ -1,65 +1,39 @@ -error[E0658]: use of unstable library feature `g`: reason g - --> $DIR/two-unstables.rs:26:5 +error[E0658]: use of unstable library features `g` and `h` + --> $DIR/two-unstables.rs:24:5 | LL | two_unstables::mac!(); | ^^^^^^^^^^^^^^^^^^ | + = note: reason for `g`: reason g = note: see issue #7 for more information - = help: add `#![feature(g)]` to the crate attributes to enable + = note: see issue #8 for more information about `h` + = help: add `#![feature(g, h)]` 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]: use of unstable library feature `h` - --> $DIR/two-unstables.rs:26:5 - | -LL | two_unstables::mac!(); - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #8 for more information - = help: add `#![feature(h)]` 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]: use of unstable library feature `a`: reason a +error[E0658]: use of unstable library features `a` and `b` --> $DIR/two-unstables.rs:15:16 | LL | struct Wrapper(two_unstables::Foo); | ^^^^^^^^^^^^^^^^^^ | + = note: reason for `a`: reason a = note: see issue #1 for more information - = help: add `#![feature(a)]` 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]: use of unstable library feature `b` - --> $DIR/two-unstables.rs:15:16 - | -LL | struct Wrapper(two_unstables::Foo); - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #2 for more information - = help: add `#![feature(b)]` to the crate attributes to enable + = note: see issue #2 for more information about `b` + = help: add `#![feature(a, b)]` 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[E0046]: not all trait items implemented, missing: `method` - --> $DIR/two-unstables.rs:20:1 + --> $DIR/two-unstables.rs:19:1 | LL | impl two_unstables::Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: default implementation of `method` is unstable - = note: use of unstable library feature `e`: reason e + = note: use of unstable library features `e` and `f` + = note: reason for `e`: reason e = note: see issue #5 for more information - = help: add `#![feature(e)]` 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[E0046]: not all trait items implemented, missing: `method` - --> $DIR/two-unstables.rs:20:1 - | -LL | impl two_unstables::Trait for Wrapper {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: default implementation of `method` is unstable - = note: use of unstable library feature `f` - = note: see issue #6 for more information - = help: add `#![feature(f)]` to the crate attributes to enable + = note: see issue #6 for more information about `f` + = help: add `#![feature(e, f)]` 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: `nothing` is not yet stable as a const fn @@ -68,9 +42,14 @@ error: `nothing` is not yet stable as a const fn LL | const USE_NOTHING: () = two_unstables::nothing(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: use of unstable library features `c` and `d` + = note: reason for `c`: reason c + = note: see issue #3 for more information + = note: see issue #4 for more information about `d` = help: add `#![feature(c, d)]` 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: aborting due to 7 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0658. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/stability-attribute/two-unstables.rs b/tests/ui/stability-attribute/two-unstables.rs index f81688aec32b5..fb5ad5154fe9b 100644 --- a/tests/ui/stability-attribute/two-unstables.rs +++ b/tests/ui/stability-attribute/two-unstables.rs @@ -13,18 +13,15 @@ const USE_NOTHING: () = two_unstables::nothing(); //[some]~^^ ERROR `nothing` is not yet stable as a const fn struct Wrapper(two_unstables::Foo); -//[none]~^ ERROR use of unstable library feature `a`: reason a [E0658] -//[none]~| ERROR use of unstable library feature `b` [E0658] -//[some]~^^^ ERROR use of unstable library feature `b` [E0658] +//[none]~^ ERROR use of unstable library features `a` and `b` [E0658] +//[some]~^^ ERROR use of unstable library feature `b` [E0658] impl two_unstables::Trait for Wrapper {} //[none]~^ ERROR not all trait items implemented, missing: `method` [E0046] -//[none]~| ERROR not all trait items implemented, missing: `method` [E0046] -//[some]~^^^ ERROR not all trait items implemented, missing: `method` [E0046] +//[some]~^^ ERROR not all trait items implemented, missing: `method` [E0046] fn main() { two_unstables::mac!(); - //[none]~^ ERROR use of unstable library feature `g`: reason g [E0658] - //[none]~| ERROR use of unstable library feature `h` [E0658] - //[some]~^^^ ERROR use of unstable library feature `g`: reason g [E0658] + //[none]~^ ERROR use of unstable library features `g` and `h` [E0658] + //[some]~^^ ERROR use of unstable library feature `g`: reason g [E0658] } diff --git a/tests/ui/stability-attribute/two-unstables.some.stderr b/tests/ui/stability-attribute/two-unstables.some.stderr index f73b368a64f63..99c8956d90f8b 100644 --- a/tests/ui/stability-attribute/two-unstables.some.stderr +++ b/tests/ui/stability-attribute/two-unstables.some.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `g`: reason g - --> $DIR/two-unstables.rs:26:5 + --> $DIR/two-unstables.rs:24:5 | LL | two_unstables::mac!(); | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | struct Wrapper(two_unstables::Foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0046]: not all trait items implemented, missing: `method` - --> $DIR/two-unstables.rs:20:1 + --> $DIR/two-unstables.rs:19:1 | LL | impl two_unstables::Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,10 @@ error: `nothing` is not yet stable as a const fn LL | const USE_NOTHING: () = two_unstables::nothing(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: use of unstable library feature `c`: reason c + = note: see issue #3 for more information = help: add `#![feature(c)]` 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: aborting due to 4 previous errors