Auto merge of #154123 - Zalathar:rollup-MUEvgV7, r=Zalathar

Rollup of 15 pull requests

Successful merges:

 - rust-lang/rust#152909 (sess: `-Zbranch-protection` is a target modifier)
 - rust-lang/rust#153556 (`impl` restriction lowering)
 - rust-lang/rust#154048 (Don't emit rustdoc `missing_doc_code_examples` lint on impl items)
 - rust-lang/rust#150935 (Introduce #[diagnostic::on_move(message)])
 - rust-lang/rust#152973 (remove -Csoft-float)
 - rust-lang/rust#153862 (Rename `cycle_check` to `find_cycle`)
 - rust-lang/rust#153992 (bootstrap: Optionally print a backtrace if a command fails)
 - rust-lang/rust#154019 (two smaller feature cleanups)
 - rust-lang/rust#154059 (tests: Activate `must_not_suspend` test for `MutexGuard` dropped before `await`)
 - rust-lang/rust#154075 (Rewrite `query_ensure_result`.)
 - rust-lang/rust#154082 (Updates derive_where and removes workaround)
 - rust-lang/rust#154084 (Preserve braces around `self` in use tree pretty printing)
 - rust-lang/rust#154086 (Insert space after float literal ending with `.` in pretty printer)
 - rust-lang/rust#154087 (Fix whitespace after fragment specifiers in macro pretty printing)
 - rust-lang/rust#154109 (tests: Add regression test for async closures involving HRTBs)
This commit is contained in:
bors
2026-03-20 07:22:03 +00:00
76 changed files with 1546 additions and 152 deletions
+2 -2
View File
@@ -1140,9 +1140,9 @@ version = "0.1.96"
[[package]]
name = "derive-where"
version = "1.6.0"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f"
checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
dependencies = [
"proc-macro2",
"quote",
@@ -329,6 +329,19 @@ fn print_crate_inner<'a>(
/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
/// - #73345: `#[allow(unused)]` must be printed rather than `# [allow(unused)]`
///
/// Returns `true` if both token trees are identifier-like tokens that would
/// merge into a single token if printed without a space between them.
/// E.g. `ident` + `where` would merge into `identwhere`.
fn idents_would_merge(tt1: &TokenTree, tt2: &TokenTree) -> bool {
fn is_ident_like(tt: &TokenTree) -> bool {
matches!(
tt,
TokenTree::Token(Token { kind: token::Ident(..) | token::NtIdent(..), .. }, _,)
)
}
is_ident_like(tt1) && is_ident_like(tt2)
}
fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
use Delimiter::*;
use TokenTree::{Delimited as Del, Token as Tok};
@@ -811,6 +824,13 @@ fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
if let Some(next) = iter.peek() {
if spacing == Spacing::Alone && space_between(tt, next) {
self.space();
} else if spacing != Spacing::Alone && idents_would_merge(tt, next) {
// When tokens from macro `tt` captures preserve their
// original `Joint`/`JointHidden` spacing, adjacent
// identifier-like tokens can be concatenated without a
// space (e.g. `$x:identwhere`). Insert a space to
// prevent this.
self.space();
}
}
}
@@ -260,12 +260,15 @@ fn print_expr_method_call(
//
// loop { break x; }.method();
//
self.print_expr_cond_paren(
receiver,
receiver.precedence() < ExprPrecedence::Unambiguous,
fixup.leftmost_subexpression_with_dot(),
);
let needs_paren = receiver.precedence() < ExprPrecedence::Unambiguous;
self.print_expr_cond_paren(receiver, needs_paren, fixup.leftmost_subexpression_with_dot());
// If the receiver is an unsuffixed float literal like `0.`, insert
// a space so the `.` of the method call doesn't merge with the
// trailing dot: `0. .method()` instead of `0..method()`.
if !needs_paren && expr_ends_with_dot(receiver) {
self.word(" ");
}
self.word(".");
self.print_ident(segment.ident);
if let Some(args) = &segment.args {
@@ -658,11 +661,15 @@ pub(super) fn print_expr_outer_attr_style(
);
}
ast::ExprKind::Field(expr, ident) => {
let needs_paren = expr.precedence() < ExprPrecedence::Unambiguous;
self.print_expr_cond_paren(
expr,
expr.precedence() < ExprPrecedence::Unambiguous,
needs_paren,
fixup.leftmost_subexpression_with_dot(),
);
if !needs_paren && expr_ends_with_dot(expr) {
self.word(" ");
}
self.word(".");
self.print_ident(*ident);
}
@@ -685,11 +692,15 @@ pub(super) fn print_expr_outer_attr_style(
let fake_prec = ExprPrecedence::LOr;
if let Some(e) = start {
let start_fixup = fixup.leftmost_subexpression_with_operator(true);
self.print_expr_cond_paren(
e,
start_fixup.precedence(e) < fake_prec,
start_fixup,
);
let needs_paren = start_fixup.precedence(e) < fake_prec;
self.print_expr_cond_paren(e, needs_paren, start_fixup);
// If the start expression is a float literal ending with
// `.`, we need a space before `..` or `..=` so that the
// dots don't merge. E.g. `0. ..45.` must not become
// `0...45.`.
if !needs_paren && expr_ends_with_dot(e) {
self.word(" ");
}
}
match limits {
ast::RangeLimits::HalfOpen => self.word(".."),
@@ -1025,3 +1036,18 @@ fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String
template.push('"');
template
}
/// Returns `true` if the printed representation of this expression ends with
/// a `.` character — specifically, an unsuffixed float literal like `0.` or
/// `45.`. This is used to insert whitespace before range operators (`..`,
/// `..=`) so that the dots don't merge (e.g. `0. ..45.` instead of `0...45.`).
fn expr_ends_with_dot(expr: &ast::Expr) -> bool {
match &expr.kind {
ast::ExprKind::Lit(token_lit) => {
token_lit.kind == token::Float
&& token_lit.suffix.is_none()
&& token_lit.symbol.as_str().ends_with('.')
}
_ => false,
}
}
@@ -881,7 +881,13 @@ fn print_use_tree(&mut self, tree: &ast::UseTree) {
}
if items.is_empty() {
self.word("{}");
} else if let [(item, _)] = items.as_slice() {
} else if let [(item, _)] = items.as_slice()
&& !item
.prefix
.segments
.first()
.is_some_and(|seg| seg.ident.name == rustc_span::symbol::kw::SelfLower)
{
self.print_use_tree(item);
} else {
let cb = self.cbox(INDENT_UNIT);
@@ -22,6 +22,7 @@
pub(crate) mod do_not_recommend;
pub(crate) mod on_const;
pub(crate) mod on_move;
pub(crate) mod on_unimplemented;
#[derive(Copy, Clone)]
@@ -32,6 +33,8 @@ pub(crate) enum Mode {
DiagnosticOnUnimplemented,
/// `#[diagnostic::on_const]`
DiagnosticOnConst,
/// `#[diagnostic::on_move]`
DiagnosticOnMove,
}
fn merge_directives<S: Stage>(
@@ -113,6 +116,13 @@ fn parse_directive_items<'p, S: Stage>(
span,
);
}
Mode::DiagnosticOnMove => {
cx.emit_lint(
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MalformedOnMoveAttr { span },
span,
);
}
}
continue;
}}
@@ -132,7 +142,7 @@ fn parse_directive_items<'p, S: Stage>(
Mode::RustcOnUnimplemented => {
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
Mode::DiagnosticOnUnimplemented |Mode::DiagnosticOnConst => {
Mode::DiagnosticOnUnimplemented |Mode::DiagnosticOnConst | Mode::DiagnosticOnMove => {
cx.emit_lint(
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::IgnoredDiagnosticOption {
@@ -0,0 +1,72 @@
use rustc_feature::template;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLintKind;
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::sym;
use crate::attributes::diagnostic::*;
use crate::attributes::prelude::*;
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
#[derive(Default)]
pub(crate) struct OnMoveParser {
span: Option<Span>,
directive: Option<(Span, Directive)>,
}
impl OnMoveParser {
fn parse<'sess, S: Stage>(
&mut self,
cx: &mut AcceptContext<'_, 'sess, S>,
args: &ArgParser,
mode: Mode,
) {
if !cx.features().diagnostic_on_move() {
return;
}
let span = cx.attr_span;
self.span = Some(span);
let Some(list) = args.list() else {
cx.emit_lint(
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::MissingOptionsForOnMove,
span,
);
return;
};
if list.is_empty() {
cx.emit_lint(
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
AttributeLintKind::OnMoveMalformedAttrExpectedLiteralOrDelimiter,
list.span,
);
return;
}
if let Some(directive) = parse_directive_items(cx, mode, list.mixed(), true) {
merge_directives(cx, &mut self.directive, (span, directive));
}
}
}
impl<S: Stage> AttributeParser<S> for OnMoveParser {
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
&[sym::diagnostic, sym::on_move],
template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
|this, cx, args| {
this.parse(cx, args, Mode::DiagnosticOnMove);
},
)];
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
if let Some(span) = self.span {
Some(AttributeKind::OnMove { span, directive: self.directive.map(|d| Box::new(d.1)) })
} else {
None
}
}
}
@@ -29,6 +29,7 @@
use crate::attributes::deprecation::*;
use crate::attributes::diagnostic::do_not_recommend::*;
use crate::attributes::diagnostic::on_const::*;
use crate::attributes::diagnostic::on_move::*;
use crate::attributes::diagnostic::on_unimplemented::*;
use crate::attributes::doc::*;
use crate::attributes::dummy::*;
@@ -149,6 +150,7 @@ mod late {
MacroUseParser,
NakedParser,
OnConstParser,
OnMoveParser,
OnUnimplementedParser,
RustcAlignParser,
RustcAlignStaticParser,
+15 -10
View File
@@ -324,18 +324,23 @@ pub(crate) fn cannot_act_on_moved_value(
verb: &str,
optional_adverb_for_moved: &str,
moved_path: Option<String>,
primary_message: Option<String>,
) -> Diag<'infcx> {
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
if let Some(primary_message) = primary_message {
struct_span_code_err!(self.dcx(), use_span, E0382, "{}", primary_message)
} else {
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
struct_span_code_err!(
self.dcx(),
use_span,
E0382,
"{} of {}moved value{}",
verb,
optional_adverb_for_moved,
moved_path,
)
struct_span_code_err!(
self.dcx(),
use_span,
E0382,
"{} of {}moved value{}",
verb,
optional_adverb_for_moved,
moved_path,
)
}
}
pub(crate) fn cannot_borrow_path_as_mutable_because(
@@ -6,12 +6,16 @@
use either::Either;
use hir::{ClosureKind, Path};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::attrs::diagnostic::FormatArgs;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField};
use rustc_hir::{
CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField, find_attr,
};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::{
@@ -138,6 +142,36 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
let partial_str = if is_partial_move { "partial " } else { "" };
let partially_str = if is_partial_move { "partially " } else { "" };
let (on_move_message, on_move_label, on_move_notes) = if let ty::Adt(item_def, args) =
self.body.local_decls[moved_place.local].ty.kind()
&& let Some(Some(directive)) = find_attr!(self.infcx.tcx, item_def.did(), OnMove { directive, .. } => directive)
{
let item_name = self.infcx.tcx.item_name(item_def.did()).to_string();
let mut generic_args: Vec<_> = self
.infcx
.tcx
.generics_of(item_def.did())
.own_params
.iter()
.filter_map(|param| Some((param.name, args[param.index as usize].to_string())))
.collect();
generic_args.push((kw::SelfUpper, item_name));
let args = FormatArgs {
this: String::new(),
trait_sugared: String::new(),
item_context: "",
generic_args,
};
(
directive.message.as_ref().map(|e| e.1.format(&args)),
directive.label.as_ref().map(|e| e.1.format(&args)),
directive.notes.iter().map(|e| e.format(&args)).collect(),
)
} else {
(None, None, ThinVec::new())
};
let mut err = self.cannot_act_on_moved_value(
span,
desired_action.as_noun(),
@@ -146,8 +180,13 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
moved_place,
DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
),
on_move_message,
);
for note in on_move_notes {
err.note(note);
}
let reinit_spans = maybe_reinitialized_locations
.iter()
.take(3)
@@ -275,12 +314,16 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
if needs_note {
if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span;
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move,
ty,
place: &note_msg,
span,
});
if let Some(on_move_label) = on_move_label {
err.span_label(span, on_move_label);
} else {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move,
ty,
place: &note_msg,
span,
});
}
} else {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
is_partial_move,
+2 -10
View File
@@ -23,9 +23,7 @@
use rustc_session::Session;
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext, sym};
use rustc_target::spec::{
Arch, CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel,
};
use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
use tracing::{debug, trace};
use crate::back::lto::{Buffer, ModuleBuffer};
@@ -206,13 +204,7 @@ pub(crate) fn target_machine_factory(
let reloc_model = to_llvm_relocation_model(sess.relocation_model());
let (opt_level, _) = to_llvm_opt_settings(optlvl);
let float_abi = if sess.target.arch == Arch::Arm && sess.opts.cg.soft_float {
llvm::FloatAbi::Soft
} else {
// `validate_commandline_args_with_session_available` has already warned about this being
// ignored. Let's make sure LLVM doesn't suddenly start using this flag on more targets.
to_llvm_float_abi(sess.target.llvm_floatabi)
};
let float_abi = to_llvm_float_abi(sess.target.llvm_floatabi);
let ffunction_sections =
sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections);
@@ -1587,6 +1587,7 @@ pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool
match sym {
sym::on_unimplemented | sym::do_not_recommend => true,
sym::on_const => features.diagnostic_on_const(),
sym::on_move => features.diagnostic_on_move(),
_ => false,
}
}
+2
View File
@@ -472,6 +472,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, derive_from, "1.91.0", Some(144889)),
/// Allows giving non-const impls custom diagnostic messages if attempted to be used as const
(unstable, diagnostic_on_const, "1.93.0", Some(143874)),
/// Allows giving on-move borrowck custom diagnostic messages for a type
(unstable, diagnostic_on_move, "CURRENT_RUSTC_VERSION", Some(150935)),
/// Allows `#[doc(cfg(...))]`.
(unstable, doc_cfg, "1.21.0", Some(43781)),
/// Allows `#[doc(masked)]`.
@@ -1180,13 +1180,18 @@ pub enum AttributeKind {
directive: Option<Box<Directive>>,
},
/// Represents `#[diagnostic::on_move]`
OnMove {
span: Span,
directive: Option<Box<Directive>>,
},
/// Represents `#[rustc_on_unimplemented]` and `#[diagnostic::on_unimplemented]`.
OnUnimplemented {
span: Span,
/// None if the directive was malformed in some way.
directive: Option<Box<Directive>>,
},
/// Represents `#[optimize(size|speed)]`
Optimize(OptimizeAttr, Span),
@@ -77,6 +77,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
NoStd(..) => No,
NonExhaustive(..) => Yes, // Needed for rustdoc
OnConst { .. } => Yes,
OnMove { .. } => Yes,
OnUnimplemented { .. } => Yes,
Optimize(..) => No,
PanicRuntime => No,
-1
View File
@@ -637,7 +637,6 @@ macro_rules! tracked {
tracked!(profile_use, Some(PathBuf::from("abc")));
tracked!(relocation_model, Some(RelocModel::Pic));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(soft_float, true);
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(target_cpu, Some(String::from("abc")));
@@ -498,6 +498,18 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
&AttributeLintKind::MissingOptionsForOnConst => {
lints::MissingOptionsForOnConstAttr.into_diag(dcx, level)
}
&AttributeLintKind::MalformedOnMoveAttr { span } => {
lints::MalformedOnMoveAttrLint { span }.into_diag(dcx, level)
}
&AttributeLintKind::OnMoveMalformedFormatLiterals { name } => {
lints::OnMoveMalformedFormatLiterals { name }.into_diag(dcx, level)
}
&AttributeLintKind::OnMoveMalformedAttrExpectedLiteralOrDelimiter => {
lints::OnMoveMalformedAttrExpectedLiteralOrDelimiter.into_diag(dcx, level)
}
&AttributeLintKind::MissingOptionsForOnMove => {
lints::MissingOptionsForOnMoveAttr.into_diag(dcx, level)
}
}
}
}
+29
View File
@@ -3953,6 +3953,11 @@ pub(crate) struct IgnoredDiagnosticOption {
#[help("at least one of the `message`, `note` and `label` options are expected")]
pub(crate) struct MissingOptionsForOnConstAttr;
#[derive(Diagnostic)]
#[diag("missing options for `on_move` attribute")]
#[help("at least one of the `message`, `note` and `label` options are expected")]
pub(crate) struct MissingOptionsForOnMoveAttr;
#[derive(Diagnostic)]
#[diag("malformed `on_unimplemented` attribute")]
#[help("only `message`, `note` and `label` are allowed as options")]
@@ -3973,3 +3978,27 @@ pub(crate) struct MalformedOnConstAttrLint {
#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")]
#[note("this method was used to add checks to the `Eq` derive macro")]
pub(crate) struct EqInternalMethodImplemented;
#[derive(Diagnostic)]
#[diag("unknown or malformed `on_move` attribute")]
#[help(
"only `message`, `note` and `label` are allowed as options. Their values must be string literals"
)]
pub(crate) struct MalformedOnMoveAttrLint {
#[label("invalid option found here")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag("unknown parameter `{$name}`")]
#[help("expect `Self` as format argument")]
pub(crate) struct OnMoveMalformedFormatLiterals {
pub name: Symbol,
}
#[derive(Diagnostic)]
#[diag("expected a literal or missing delimiter")]
#[help(
"only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma"
)]
pub(crate) struct OnMoveMalformedAttrExpectedLiteralOrDelimiter;
+8
View File
@@ -840,6 +840,9 @@ pub enum AttributeLintKind {
MalformedOnConstAttr {
span: Span,
},
MalformedOnMoveAttr {
span: Span,
},
MalformedDiagnosticFormat {
warning: FormatWarning,
},
@@ -855,6 +858,11 @@ pub enum AttributeLintKind {
},
MissingOptionsForOnUnimplemented,
MissingOptionsForOnConst,
MissingOptionsForOnMove,
OnMoveMalformedFormatLiterals {
name: Symbol,
},
OnMoveMalformedAttrExpectedLiteralOrDelimiter,
}
#[derive(Debug, Clone, HashStable_Generic)]
+27 -16
View File
@@ -77,23 +77,34 @@ pub(crate) fn query_ensure_result<'tcx, C, T>(
C: QueryCache<Value = Erased<Result<T, ErrorGuaranteed>>>,
Result<T, ErrorGuaranteed>: Erasable,
{
let convert = |value: Erased<Result<T, ErrorGuaranteed>>| -> Result<(), ErrorGuaranteed> {
match erase::restore_val(value) {
Ok(_) => Ok(()),
Err(guar) => Err(guar),
}
};
match try_get_cached(tcx, &query.cache, key) {
Some(value) => erase::restore_val(value).map(drop),
None => (query.execute_query_fn)(
tcx,
DUMMY_SP,
key,
QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
)
.map(erase::restore_val)
.map(|value| value.map(drop))
// Either we actually executed the query, which means we got a full `Result`,
// or we can just assume the query succeeded, because it was green in the
// incremental cache. If it is green, that means that the previous compilation
// that wrote to the incremental cache compiles successfully. That is only
// possible if the cache entry was `Ok(())`, so we emit that here, without
// actually encoding the `Result` in the cache or loading it from there.
.unwrap_or(Ok(())),
Some(value) => convert(value),
None => {
match (query.execute_query_fn)(
tcx,
DUMMY_SP,
key,
QueryMode::Ensure { ensure_mode: EnsureMode::Ok },
) {
// We executed the query. Convert the successful result.
Some(res) => convert(res),
// Reaching here means we didn't execute the query, but we can just assume the
// query succeeded, because it was green in the incremental cache. If it is green,
// that means that the previous compilation that wrote to the incremental cache
// compiles successfully. That is only possible if the cache entry was `Ok(())`, so
// we emit that here, without actually encoding the `Result` in the cache or
// loading it from there.
None => Ok(()),
}
}
}
}
+57
View File
@@ -74,6 +74,10 @@ struct DiagnosticOnConstOnlyForNonConstTraitImpls {
item_span: Span,
}
#[derive(Diagnostic)]
#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")]
struct DiagnosticOnMoveOnlyForAdt;
fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
match impl_item.kind {
hir::ImplItemKind::Const(..) => Target::AssocConst,
@@ -233,6 +237,9 @@ fn check_attributes(
Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)},
Attribute::Parsed(AttributeKind::OnUnimplemented{span, directive}) => {self.check_diagnostic_on_unimplemented(*span, hir_id, target,directive.as_deref())},
Attribute::Parsed(AttributeKind::OnConst{span, ..}) => {self.check_diagnostic_on_const(*span, hir_id, target, item)}
Attribute::Parsed(AttributeKind::OnMove { span, directive }) => {
self.check_diagnostic_on_move(*span, hir_id, target, directive.as_deref())
},
Attribute::Parsed(
// tidy-alphabetical-start
AttributeKind::RustcAllowIncoherentImpl(..)
@@ -684,6 +691,56 @@ fn check_diagnostic_on_const(
// The traits' or the impls'?
}
/// Checks if `#[diagnostic::on_move]` is applied to an ADT definition
fn check_diagnostic_on_move(
&self,
attr_span: Span,
hir_id: HirId,
target: Target,
directive: Option<&Directive>,
) {
if !matches!(target, Target::Enum | Target::Struct | Target::Union) {
self.tcx.emit_node_span_lint(
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
hir_id,
attr_span,
DiagnosticOnMoveOnlyForAdt,
);
}
if let Some(directive) = directive {
if let Node::Item(Item {
kind:
ItemKind::Struct(_, generics, _)
| ItemKind::Enum(_, generics, _)
| ItemKind::Union(_, generics, _),
..
}) = self.tcx.hir_node(hir_id)
{
directive.visit_params(&mut |argument_name, span| {
let has_generic = generics.params.iter().any(|p| {
if !matches!(p.kind, GenericParamKind::Lifetime { .. })
&& let ParamName::Plain(name) = p.name
&& name.name == argument_name
{
true
} else {
false
}
});
if !has_generic {
self.tcx.emit_node_span_lint(
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
hir_id,
span,
errors::OnMoveMalformedFormatLiterals { name: argument_name },
)
}
});
}
}
}
/// Checks if an `#[inline]` is applied to a function or a closure.
fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) {
match target {
+7
View File
@@ -1432,3 +1432,10 @@ pub(crate) struct UnknownFormatParameterForOnUnimplementedAttr {
#[help(r#"expect either a generic argument name or {"`{Self}`"} as format argument"#)]
pub help: bool,
}
#[derive(Diagnostic)]
#[diag("unknown parameter `{$name}`")]
#[help(r#"expect either a generic argument name or {"`{Self}`"} as format argument"#)]
pub(crate) struct OnMoveMalformedFormatLiterals {
pub name: Symbol,
}
+6 -6
View File
@@ -155,11 +155,11 @@ fn abstracted_waiters_of(job_map: &QueryJobMap<'_>, query: QueryJobId) -> Vec<Ab
result
}
/// Look for query cycles by doing a depth first search starting at `query`.
/// Looks for a query cycle by doing a depth first search starting at `query`.
/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
/// If a cycle is detected, this initial value is replaced with the span causing
/// the cycle.
fn cycle_check<'tcx>(
/// the cycle. `stack` will contain just the cycle on return if detected.
fn find_cycle<'tcx>(
job_map: &QueryJobMap<'tcx>,
query: QueryJobId,
span: Span,
@@ -190,7 +190,7 @@ fn cycle_check<'tcx>(
continue;
};
if let ControlFlow::Break(maybe_resumable) =
cycle_check(job_map, parent, abstracted_waiter.span, stack, visited)
find_cycle(job_map, parent, abstracted_waiter.span, stack, visited)
{
// Return the resumable waiter in `waiter.resumable` if present
return ControlFlow::Break(abstracted_waiter.resumable.or(maybe_resumable));
@@ -232,7 +232,7 @@ fn connected_to_root<'tcx>(
false
}
/// Looks for query cycles starting from the last query in `jobs`.
/// Looks for a query cycle using the last query in `jobs`.
/// If a cycle is found, all queries in the cycle is removed from `jobs` and
/// the function return true.
/// If a cycle was not found, the starting query is removed from `jobs` and
@@ -246,7 +246,7 @@ fn remove_cycle<'tcx>(
let mut stack = Vec::new();
// Look for a cycle starting with the last query in `jobs`
if let ControlFlow::Break(resumable) =
cycle_check(job_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited)
find_cycle(job_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited)
{
// The stack is a vector of pairs of spans and queries; reverse it so that
// the earlier entries require later entries
+4
View File
@@ -560,6 +560,10 @@ pub(crate) struct ExpectedModuleFound {
#[diag("cannot determine resolution for the visibility", code = E0578)]
pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag("trait implementation can only be restricted to ancestor modules")]
pub(crate) struct RestrictionAncestorOnly(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag("cannot use a tool module through an import")]
pub(crate) struct ToolModuleImported {
+39 -4
View File
@@ -452,6 +452,8 @@ pub(crate) enum PathSource<'a, 'ast, 'ra> {
DefineOpaques,
/// Resolving a macro
Macro,
/// Paths for module or crate root. Used for restrictions.
Module,
}
impl PathSource<'_, '_, '_> {
@@ -460,7 +462,8 @@ fn namespace(self) -> Namespace {
PathSource::Type
| PathSource::Trait(_)
| PathSource::Struct(_)
| PathSource::DefineOpaques => TypeNS,
| PathSource::DefineOpaques
| PathSource::Module => TypeNS,
PathSource::Expr(..)
| PathSource::Pat
| PathSource::TupleStruct(..)
@@ -485,7 +488,8 @@ fn defer_to_typeck(self) -> bool {
| PathSource::DefineOpaques
| PathSource::Delegation
| PathSource::PreciseCapturingArg(..)
| PathSource::Macro => false,
| PathSource::Macro
| PathSource::Module => false,
}
}
@@ -528,6 +532,7 @@ fn descr_expected(self) -> &'static str {
PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
PathSource::PreciseCapturingArg(..) => "type or const parameter",
PathSource::Macro => "macro",
PathSource::Module => "module",
}
}
@@ -626,6 +631,7 @@ pub(crate) fn is_expected(self, res: Res) -> bool {
),
PathSource::PreciseCapturingArg(MacroNS) => false,
PathSource::Macro => matches!(res, Res::Def(DefKind::Macro(_), _)),
PathSource::Module => matches!(res, Res::Def(DefKind::Mod, _)),
}
}
@@ -646,6 +652,12 @@ fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
(PathSource::PreciseCapturingArg(..), true) => E0799,
(PathSource::PreciseCapturingArg(..), false) => E0800,
(PathSource::Macro, _) => E0425,
// FIXME: There is no dedicated error code for this case yet.
// E0577 already covers the same situation for visibilities,
// so we reuse it here for now. It may make sense to generalize
// it for restrictions in the future.
(PathSource::Module, true) => E0577,
(PathSource::Module, false) => E0433,
}
}
}
@@ -2174,7 +2186,8 @@ fn resolve_elided_lifetimes_in_path(
| PathSource::Type
| PathSource::PreciseCapturingArg(..)
| PathSource::ReturnTypeNotation
| PathSource::Macro => false,
| PathSource::Macro
| PathSource::Module => false,
PathSource::Expr(..)
| PathSource::Pat
| PathSource::Struct(_)
@@ -2800,7 +2813,10 @@ fn resolve_item(&mut self, item: &'ast Item) {
self.diag_metadata.current_impl_items = None;
}
ItemKind::Trait(box Trait { generics, bounds, items, .. }) => {
ItemKind::Trait(box Trait { generics, bounds, items, impl_restriction, .. }) => {
// resolve paths for `impl` restrictions
self.resolve_impl_restriction_path(impl_restriction);
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
@@ -4389,6 +4405,25 @@ fn try_resolve_as_non_binding(
}
}
fn resolve_impl_restriction_path(&mut self, restriction: &'ast ast::ImplRestriction) {
match &restriction.kind {
ast::RestrictionKind::Unrestricted => (),
ast::RestrictionKind::Restricted { path, id, shorthand: _ } => {
self.smart_resolve_path(*id, &None, path, PathSource::Module);
if let Some(res) = self.r.partial_res_map[&id].full_res()
&& let Some(def_id) = res.opt_def_id()
{
if !self.r.is_accessible_from(
Visibility::Restricted(def_id),
self.parent_scope.module,
) {
self.r.dcx().create_err(errors::RestrictionAncestorOnly(path.span)).emit();
}
}
}
}
}
// High-level and context dependent path resolution routine.
// Resolves the path and records the resolution into definition map.
// If resolution fails tries several techniques to find likely
+1 -1
View File
@@ -707,7 +707,7 @@ fn smart_resolve_macro_path(
}
const DIAG_ATTRS: &[Symbol] =
&[sym::on_unimplemented, sym::do_not_recommend, sym::on_const];
&[sym::on_unimplemented, sym::do_not_recommend, sym::on_const, sym::on_move];
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
&& let [namespace, attribute, ..] = &*path.segments
-11
View File
@@ -517,17 +517,6 @@ pub(crate) struct FailedToCreateProfiler {
pub(crate) err: String,
}
#[derive(Diagnostic)]
#[diag("`-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets")]
#[note("this may become a hard error in a future version of Rust")]
pub(crate) struct SoftFloatIgnored;
#[derive(Diagnostic)]
#[diag("`-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead")]
#[note("it will be removed or ignored in a future version of Rust")]
#[note("see issue #129893 <https://github.com/rust-lang/rust/issues/129893> for more information")]
pub(crate) struct SoftFloatDeprecated;
#[derive(Diagnostic)]
#[diag("unexpected `--cfg {$cfg}` flag")]
#[note("config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`")]
+2
View File
@@ -1,5 +1,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![feature(const_option_ops)]
#![feature(const_trait_impl)]
#![feature(default_field_values)]
#![feature(iter_intersperse)]
#![feature(macro_derive)]
+35 -19
View File
@@ -611,7 +611,7 @@ macro_rules! options {
$parse:ident,
[$dep_tracking_marker:ident $( $tmod:ident )?],
$desc:expr
$(, is_deprecated_and_do_nothing: $dnn:literal )?)
$(, removed: $removed:ident )?)
),* ,) =>
(
#[derive(Clone)]
@@ -667,7 +667,7 @@ pub fn gather_target_modifiers(
pub const $stat: OptionDescrs<$struct_name> =
&[ $( OptionDesc{ name: stringify!($opt), setter: $optmod::$opt,
type_desc: desc::$parse, desc: $desc, is_deprecated_and_do_nothing: false $( || $dnn )?,
type_desc: desc::$parse, desc: $desc, removed: None $( .or(Some(RemovedOption::$removed)) )?,
tmod: tmod_enum_opt!($struct_name, $tmod_enum_name, $opt, $($tmod),*) } ),* ];
mod $optmod {
@@ -705,6 +705,12 @@ macro_rules! redirect_field {
type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
type OptionDescrs<O> = &'static [OptionDesc<O>];
/// Indicates whether a removed option should warn or error.
enum RemovedOption {
Warn,
Err,
}
pub struct OptionDesc<O> {
name: &'static str,
setter: OptionSetter<O>,
@@ -712,7 +718,7 @@ pub struct OptionDesc<O> {
type_desc: &'static str,
// description for option from options table
desc: &'static str,
is_deprecated_and_do_nothing: bool,
removed: Option<RemovedOption>,
tmod: Option<OptionsTargetModifiers>,
}
@@ -743,18 +749,18 @@ fn build_options<O: Default>(
let option_to_lookup = key.replace('-', "_");
match descrs.iter().find(|opt_desc| opt_desc.name == option_to_lookup) {
Some(OptionDesc {
name: _,
setter,
type_desc,
desc,
is_deprecated_and_do_nothing,
tmod,
}) => {
if *is_deprecated_and_do_nothing {
Some(OptionDesc { name: _, setter, type_desc, desc, removed, tmod }) => {
if let Some(removed) = removed {
// deprecation works for prefixed options only
assert!(!prefix.is_empty());
early_dcx.early_warn(format!("`-{prefix} {key}`: {desc}"));
match removed {
RemovedOption::Warn => {
early_dcx.early_warn(format!("`-{prefix} {key}`: {desc}"))
}
RemovedOption::Err => {
early_dcx.early_fatal(format!("`-{prefix} {key}`: {desc}"))
}
}
}
if !setter(&mut op, value) {
match value {
@@ -783,6 +789,7 @@ fn build_options<O: Default>(
#[allow(non_upper_case_globals)]
mod desc {
pub(crate) const parse_ignore: &str = "<ignored>"; // should not be user-visible
pub(crate) const parse_no_value: &str = "no value";
pub(crate) const parse_bool: &str =
"one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`";
@@ -889,6 +896,12 @@ pub mod parse {
pub(crate) use super::*;
pub(crate) const MAX_THREADS_CAP: usize = 256;
/// Ignore the value. Used for removed options where we don't actually want to store
/// anything in the session.
pub(crate) fn parse_ignore(_slot: &mut (), _v: Option<&str>) -> bool {
true
}
/// This is for boolean options that don't take a value, and are true simply
/// by existing on the command-line.
///
@@ -2059,7 +2072,7 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
ar: String = (String::new(), parse_string, [UNTRACKED],
"this option is deprecated and does nothing",
is_deprecated_and_do_nothing: true),
removed: Warn),
#[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")]
code_model: Option<CodeModel> = (None, parse_code_model, [TRACKED],
"choose the code model to use (`rustc --print code-models` for details)"),
@@ -2098,7 +2111,7 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
inline_threshold: Option<u32> = (None, parse_opt_number, [UNTRACKED],
"this option is deprecated and does nothing \
(consider using `-Cllvm-args=--inline-threshold=...`)",
is_deprecated_and_do_nothing: true),
removed: Warn),
#[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
"instrument the generated code to support LLVM source-based code coverage reports \
@@ -2139,7 +2152,7 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
no_stack_check: bool = (false, parse_no_value, [UNTRACKED],
"this option is deprecated and does nothing",
is_deprecated_and_do_nothing: true),
removed: Warn),
no_vectorize_loops: bool = (false, parse_no_value, [TRACKED],
"disable loop vectorization optimization passes"),
no_vectorize_slp: bool = (false, parse_no_value, [TRACKED],
@@ -2173,8 +2186,11 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
"set rpath values in libs/exes (default: no)"),
save_temps: bool = (false, parse_bool, [UNTRACKED],
"save all temporary output files during compilation (default: no)"),
soft_float: bool = (false, parse_bool, [TRACKED],
"deprecated option: use soft float ABI (*eabihf targets only) (default: no)"),
#[rustc_lint_opt_deny_field_access("documented to do nothing")]
soft_float: () = ((), parse_ignore, [UNTRACKED],
"this option has been removed \
(use a corresponding *eabi target instead)",
removed: Err),
#[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")]
split_debuginfo: Option<SplitDebuginfo> = (None, parse_split_debuginfo, [TRACKED],
"how to handle split-debuginfo, a platform-specific option"),
@@ -2240,7 +2256,7 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
(default: no)"),
box_noalias: bool = (true, parse_bool, [TRACKED],
"emit noalias metadata for box (default: yes)"),
branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED],
branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED TARGET_MODIFIER],
"set options for branch target identification and pointer authentication on AArch64"),
build_sdylib_interface: bool = (false, parse_bool, [UNTRACKED],
"whether the stable interface is being built"),
-10
View File
@@ -1360,16 +1360,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
}
}
if sess.opts.cg.soft_float {
if sess.target.arch == Arch::Arm {
sess.dcx().emit_warn(errors::SoftFloatDeprecated);
} else {
// All `use_softfp` does is the equivalent of `-mfloat-abi` in GCC/clang, which only exists on ARM targets.
// We document this flag to only affect `*eabihf` targets, so let's show a warning for all other targets.
sess.dcx().emit_warn(errors::SoftFloatIgnored);
}
}
}
/// Holds data on the current incremental compilation session, if there is one.
+2
View File
@@ -797,6 +797,7 @@
diagnostic,
diagnostic_namespace,
diagnostic_on_const,
diagnostic_on_move,
dialect,
direct,
discriminant_kind,
@@ -1407,6 +1408,7 @@
omit_gdb_pretty_printer_section,
on,
on_const,
on_move,
on_unimplemented,
opaque,
opaque_generic_const_args,
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2024"
# tidy-alphabetical-start
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
derive-where = "1.2.7"
derive-where = "1.6.1"
ena = "0.14.4"
indexmap = "2.0.0"
rustc-hash = "2.0.0"
+3 -17
View File
@@ -26,11 +26,7 @@
/// for more details.
///
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)]
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner, T)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct Binder<I: Interner, T> {
@@ -365,12 +361,7 @@ fn visit_region(&mut self, r: I::Region) -> Self::Result {
/// `instantiate`.
///
/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Ord; I: Interner, T: Ord)]
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)]
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Hash, Debug; I: Interner, T)]
#[derive(GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
@@ -964,12 +955,7 @@ pub enum BoundVarIndexKind {
/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
/// regions/types/consts within the same universe simply have an unknown relationship to one
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
#[derive_where(Ord; I: Interner, T: Ord)]
#[derive_where(Copy; I: Interner, T: Copy)]
#[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)]
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash; I: Interner, T)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(
feature = "nightly",
+1 -2
View File
@@ -107,8 +107,6 @@
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
#![feature(disjoint_bitor)]
#![feature(internal_impls_macro)]
#![feature(link_cfg)]
#![feature(offset_of_enum)]
#![feature(panic_internals)]
#![feature(pattern_type_macro)]
@@ -144,6 +142,7 @@
#![feature(intra_doc_pointers)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_cfg)]
#![feature(link_llvm_intrinsics)]
#![feature(macro_metavar_expr)]
#![feature(macro_metavar_expr_concat)]
-3
View File
@@ -52,9 +52,6 @@
/// u32,
/// }
/// ```
#[unstable(feature = "internal_impls_macro", issue = "none")]
// Allow implementations of `UnsizedConstParamTy` even though std cannot use that feature.
#[allow_internal_unstable(const_param_ty_trait)]
macro marker_impls {
( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
$(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {}
+8 -8
View File
@@ -275,9 +275,7 @@
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(core_float_math)]
#![feature(decl_macro)]
#![feature(deprecated_suggestion)]
#![feature(doc_cfg)]
@@ -287,16 +285,11 @@
#![feature(f16)]
#![feature(f128)]
#![feature(ffi_const)]
#![feature(formatting_options)]
#![feature(funnel_shifts)]
#![feature(intra_doc_pointers)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(lang_items)]
#![feature(link_cfg)]
#![feature(linkage)]
#![feature(macro_metavar_expr_concat)]
#![feature(maybe_uninit_fill)]
#![feature(min_specialization)]
#![feature(must_not_suspend)]
#![feature(needs_panic_runtime)]
@@ -314,7 +307,6 @@
#![feature(try_blocks)]
#![feature(try_trait_v2)]
#![feature(type_alias_impl_trait)]
#![feature(uint_carryless_mul)]
// tidy-alphabetical-end
//
// Library features (core):
@@ -325,6 +317,8 @@
#![feature(char_internals)]
#![feature(clone_to_uninit)]
#![feature(const_convert)]
#![feature(const_default)]
#![feature(core_float_math)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(cstr_display)]
@@ -340,13 +334,18 @@
#![feature(float_minimum_maximum)]
#![feature(fmt_internals)]
#![feature(fn_ptr_trait)]
#![feature(formatting_options)]
#![feature(funnel_shifts)]
#![feature(generic_atomic)]
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
#![feature(hint_must_use)]
#![feature(int_from_ascii)]
#![feature(ip)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_fill)]
#![feature(panic_can_unwind)]
#![feature(panic_internals)]
#![feature(pin_coerce_unsized_trait)]
@@ -364,6 +363,7 @@
#![feature(sync_unsafe_cell)]
#![feature(temporary_niche_types)]
#![feature(ub_checks)]
#![feature(uint_carryless_mul)]
#![feature(used_with_arg)]
// tidy-alphabetical-end
//
+11
View File
@@ -7,6 +7,7 @@
//! relevant to command execution in the bootstrap process. This includes settings such as
//! dry-run mode, verbosity level, and failure behavior.
use std::backtrace::{Backtrace, BacktraceStatus};
use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Formatter};
@@ -930,6 +931,16 @@ enum FailureReason {
if stderr.captures() {
writeln!(error_message, "\n--- STDERR vvv\n{}", output.stderr().trim()).unwrap();
}
let backtrace = if exec_ctx.verbosity > 1 {
Backtrace::force_capture()
} else if matches!(command.failure_behavior, BehaviorOnFailure::Ignore) {
Backtrace::disabled()
} else {
Backtrace::capture()
};
if matches!(backtrace.status(), BacktraceStatus::Captured) {
writeln!(error_message, "\n--- BACKTRACE vvv\n{backtrace}").unwrap();
}
match command.failure_behavior {
BehaviorOnFailure::DelayFail => {
@@ -79,8 +79,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
// check for trait impl
| clean::ImplItem(box clean::Impl { trait_: Some(_), .. })
| clean::ImplItem(_)
)
{
return false;
-1
View File
@@ -1475,7 +1475,6 @@ ui/lint/issue-97094.rs
ui/lint/issue-99387.rs
ui/lint/let_underscore/issue-119696-err-on-fn.rs
ui/lint/let_underscore/issue-119697-extra-let.rs
ui/lint/must_not_suspend/issue-89562.rs
ui/lint/unused/issue-103320-must-use-ops.rs
ui/lint/unused/issue-104397.rs
ui/lint/unused/issue-105061-array-lint.rs
@@ -1,4 +1,4 @@
//@ compile-flags: -C no-prepopulate-passes -Zbranch-protection=bti
//@ compile-flags: -C no-prepopulate-passes -Zbranch-protection=bti -Cunsafe-allow-abi-mismatch=branch-protection
//@ assembly-output: emit-asm
//@ needs-asm-support
//@ only-aarch64
+8
View File
@@ -0,0 +1,8 @@
//@ pp-exact
fn main() {
let _ = 0. ..45.;
let _ = 0. ..=360.;
let _ = 0. ..;
let _ = 0. .to_string();
}
@@ -0,0 +1,24 @@
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:macro-fragment-specifier-whitespace.pp
// Test that fragment specifier names in macro definitions are properly
// separated from the following keyword/identifier token when pretty-printed.
// This is a regression test for a bug where `$x:ident` followed by `where`
// was pretty-printed as `$x:identwhere` (an invalid fragment specifier).
macro_rules! outer {
($d:tt $($params:tt)*) =>
{
#[macro_export] macro_rules! inner
{ ($($params)* where $d($rest:tt)*) => {}; }
};
}
#[macro_export]
macro_rules! inner { ($x:ident where $ ($rest : tt)*) => {}; }
fn main() {}
@@ -0,0 +1,19 @@
//@ pretty-mode:expanded
//@ pp-exact:macro-fragment-specifier-whitespace.pp
// Test that fragment specifier names in macro definitions are properly
// separated from the following keyword/identifier token when pretty-printed.
// This is a regression test for a bug where `$x:ident` followed by `where`
// was pretty-printed as `$x:identwhere` (an invalid fragment specifier).
macro_rules! outer {
($d:tt $($params:tt)*) => {
#[macro_export]
macro_rules! inner {
($($params)* where $d($rest:tt)*) => {};
}
};
}
outer!($ $x:ident);
fn main() {}
+10
View File
@@ -0,0 +1,10 @@
//@ pp-exact
//@ edition:2021
#![allow(unused_imports)]
// Braces around `self` must be preserved, because `use foo::self` is not valid Rust.
use std::io::{self};
use std::fmt::{self, Debug};
fn main() {}
@@ -32,6 +32,7 @@ fn main() {
.opt_level("2")
.linker(&env_var("CLANG"))
.link_arg("-fuse-ld=lld")
.arg("-Cunsafe-allow-abi-mismatch=branch-protection")
.arg("-Zbranch-protection=bti,gcs,pac-ret,leaf")
.input("test.rs")
.output("test.bin")
@@ -15,7 +15,11 @@
fn main() {
build_native_static_lib("test");
rustc().arg("-Zbranch-protection=bti,gcs,pac-ret,leaf").input("test.rs").run();
rustc()
.arg("-Cunsafe-allow-abi-mismatch=branch-protection")
.arg("-Zbranch-protection=bti,gcs,pac-ret,leaf")
.input("test.rs")
.run();
run("test");
cc().arg("-v")
.arg("-c")
@@ -25,7 +29,11 @@ fn main() {
.run();
let obj_file = if is_windows_msvc() { "test.obj" } else { "test" };
llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
rustc().arg("-Zbranch-protection=bti,gcs,pac-ret,leaf").input("test.rs").run();
rustc()
.arg("-Cunsafe-allow-abi-mismatch=branch-protection")
.arg("-Zbranch-protection=bti,gcs,pac-ret,leaf")
.input("test.rs")
.run();
run("test");
// FIXME: +pc was only recently added to LLVM
@@ -37,6 +45,10 @@ fn main() {
// .run();
// let obj_file = if is_windows_msvc() { "test.obj" } else { "test" };
// llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
// rustc().arg("-Zbranch-protection=bti,pac-ret,pc,leaf").input("test.rs").run();
// rustc()
// .arg("-Cunsafe-allow-abi-mismatch=branch-protection")
// .arg("-Zbranch-protection=bti,pac-ret,pc,leaf")
// .input("test.rs")
// .run();
// run("test");
}
@@ -78,7 +78,11 @@ fn clone(&self) -> Self {
}
}
impl Struct { // No doc or code example and it's fine!
pub fn bar() {}
//~^ ERROR missing code example in this documentation
//~| ERROR missing documentation for an associated function
}
/// doc
///
@@ -1,3 +1,15 @@
error: missing documentation for an associated function
--> $DIR/lint-missing-doc-code-example.rs:82:5
|
LL | pub fn bar() {}
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-missing-doc-code-example.rs:2:9
|
LL | #![deny(missing_docs)]
| ^^^^^^^^^^^^
error: missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:38:3
|
@@ -28,5 +40,11 @@ error: missing code example in this documentation
LL | /// Doc
| ^^^^^^^
error: aborting due to 4 previous errors
error: missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:82:5
|
LL | pub fn bar() {}
| ^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
@@ -0,0 +1,33 @@
//! Regresssion test for <https://github.com/rust-lang/rust/issues/59337>.
//@ edition:2018
//@ check-pass
use std::future::Future;
trait Foo<'a> {
type Future: Future<Output = u8> + 'a;
fn start(self, f: &'a u8) -> Self::Future;
}
impl<'a, Fn, Fut> Foo<'a> for Fn
where
Fn: FnOnce(&'a u8) -> Fut,
Fut: Future<Output = u8> + 'a,
{
type Future = Fut;
fn start(self, f: &'a u8) -> Self::Future { (self)(f) }
}
fn foo<F>(f: F) where F: for<'a> Foo<'a> {
let bar = 5;
f.start(&bar);
}
fn main() {
foo(async move | f: &u8 | { *f });
foo({ async fn baz(f: &u8) -> u8 { *f } baz });
}
@@ -0,0 +1,8 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo",
label = "Bar",
)]
#[derive(Debug)]
pub struct Foo;
@@ -0,0 +1,14 @@
//@ aux-build:other.rs
extern crate other;
use other::Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo
}
@@ -0,0 +1,21 @@
error[E0382]: Foo
--> $DIR/error_is_shown_in_downstream_crates.rs:12:15
|
LL | let foo = Foo;
| --- Bar
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/error_is_shown_in_downstream_crates.rs:7:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,17 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo",
label = "Bar",
)]
#[derive(Debug)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo
}
@@ -0,0 +1,29 @@
error[E0382]: Foo
--> $DIR/on_move_simple.rs:15:15
|
LL | let foo = Foo;
| --- Bar
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/on_move_simple.rs:10:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/on_move_simple.rs:8:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,32 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo for {Self}",
label = "Bar for {Self}",
)]
#[derive(Debug)]
struct Foo;
#[diagnostic::on_move(
message="Foo for {X}",
label="Bar for {X}",
)]
struct MyType<X> {
_x: X,
}
fn takes_foo(_: Foo) {}
fn takes_mytype<X>(_: MyType<X>) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo for Foo
let mytype = MyType { _x: 0 };
takes_mytype(mytype);
let baz = mytype;
//~^ERROR Foo for i32
}
@@ -0,0 +1,55 @@
error[E0382]: Foo for Foo
--> $DIR/on_move_with_format.rs:25:15
|
LL | let foo = Foo;
| --- Bar for Foo
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/on_move_with_format.rs:18:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/on_move_with_format.rs:8:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error[E0382]: Foo for i32
--> $DIR/on_move_with_format.rs:30:15
|
LL | let mytype = MyType { _x: 0 };
| ------ Bar for i32
LL | takes_mytype(mytype);
| ------ value moved here
LL | let baz = mytype;
| ^^^^^^ value used here after move
|
note: consider changing this parameter type in function `takes_mytype` to borrow instead if owning the value isn't necessary
--> $DIR/on_move_with_format.rs:20:23
|
LL | fn takes_mytype<X>(_: MyType<X>) {}
| ------------ ^^^^^^^^^ this parameter takes ownership of the value
| |
| in this function
note: if `MyType<i32>` implemented `Clone`, you could clone the value
--> $DIR/on_move_with_format.rs:14:1
|
LL | struct MyType<X> {
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_mytype(mytype);
| ------ you could clone this value
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,22 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "first message",
label = "first label",
)]
#[diagnostic::on_move(
message = "second message",
//~^ WARN `message` is ignored due to previous definition of `message` [malformed_diagnostic_attributes]
label = "second label",
//~^ WARN `label` is ignored due to previous definition of `label` [malformed_diagnostic_attributes]
)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR first message
}
@@ -0,0 +1,49 @@
warning: `message` is ignored due to previous definition of `message`
--> $DIR/report_warning_on_duplicated_options.rs:8:5
|
LL | message = "first message",
| ------------------------- `message` is first declared here
...
LL | message = "second message",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `message` is later redundantly declared here
|
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: `label` is ignored due to previous definition of `label`
--> $DIR/report_warning_on_duplicated_options.rs:10:5
|
LL | label = "first label",
| --------------------- `label` is first declared here
...
LL | label = "second label",
| ^^^^^^^^^^^^^^^^^^^^^^ `label` is later redundantly declared here
error[E0382]: first message
--> $DIR/report_warning_on_duplicated_options.rs:20:15
|
LL | let foo = Foo;
| --- first label
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_duplicated_options.rs:15:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_duplicated_options.rs:13:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 2 warnings emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,18 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo {Baz}",
//~^WARN unknown parameter `Baz`
label = "Bar",
)]
#[derive(Debug)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo
}
@@ -0,0 +1,38 @@
warning: unknown parameter `Baz`
--> $DIR/report_warning_on_invalid_formats.rs:4:21
|
LL | message = "Foo {Baz}",
| ^^^
|
= help: expect either a generic argument name or `{Self}` as format argument
= note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: Foo {Baz}
--> $DIR/report_warning_on_invalid_formats.rs:16:15
|
LL | let foo = Foo;
| --- Bar
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_invalid_formats.rs:11:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_invalid_formats.rs:9:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,14 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move = "foo"]
//~^WARN missing options for `on_move` attribute [malformed_diagnostic_attributes]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR use of moved value: `foo`
}
@@ -0,0 +1,38 @@
warning: missing options for `on_move` attribute
--> $DIR/report_warning_on_invalid_meta_item_syntax.rs:3:1
|
LL | #[diagnostic::on_move = "foo"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: at least one of the `message`, `note` and `label` options are expected
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: use of moved value: `foo`
--> $DIR/report_warning_on_invalid_meta_item_syntax.rs:12:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_invalid_meta_item_syntax.rs:7:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_invalid_meta_item_syntax.rs:5:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,18 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
//~^ WARN expected a literal or missing delimiter [malformed_diagnostic_attributes]
//~| HELP only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma
message = "Foo"
label = "Bar",
)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR use of moved value: `foo`
}
@@ -0,0 +1,44 @@
warning: expected a literal or missing delimiter
--> $DIR/report_warning_on_malformed_options_without_delimiters.rs:3:22
|
LL | #[diagnostic::on_move(
| ______________________^
LL | |
LL | |
LL | | message = "Foo"
LL | | label = "Bar",
LL | | )]
| |_^
|
= help: only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: use of moved value: `foo`
--> $DIR/report_warning_on_malformed_options_without_delimiters.rs:16:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_malformed_options_without_delimiters.rs:11:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_malformed_options_without_delimiters.rs:9:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,18 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
//~^ WARN expected a literal or missing delimiter [malformed_diagnostic_attributes]
//~| HELP only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma
message = Foo,
label = "Bar",
)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR use of moved value: `foo`
}
@@ -0,0 +1,44 @@
warning: expected a literal or missing delimiter
--> $DIR/report_warning_on_malformed_options_without_literals.rs:3:22
|
LL | #[diagnostic::on_move(
| ______________________^
LL | |
LL | |
LL | | message = Foo,
LL | | label = "Bar",
LL | | )]
| |_^
|
= help: only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: use of moved value: `foo`
--> $DIR/report_warning_on_malformed_options_without_literals.rs:16:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_malformed_options_without_literals.rs:11:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_malformed_options_without_literals.rs:9:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,14 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move]
//~^WARN missing options for `on_move` attribute [malformed_diagnostic_attributes]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR use of moved value: `foo`
}
@@ -0,0 +1,38 @@
warning: missing options for `on_move` attribute
--> $DIR/report_warning_on_missing_options.rs:3:1
|
LL | #[diagnostic::on_move]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: at least one of the `message`, `note` and `label` options are expected
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: use of moved value: `foo`
--> $DIR/report_warning_on_missing_options.rs:12:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_missing_options.rs:7:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_missing_options.rs:5:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,23 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo",
label = "Bar",
)]
struct Foo;
#[diagnostic::on_move(
//~^WARN `#[diagnostic::on_move]` can only be applied to enums, structs or unions
message = "Foo",
label = "Bar",
)]
trait MyTrait {}
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo
}
@@ -0,0 +1,41 @@
warning: `#[diagnostic::on_move]` can only be applied to enums, structs or unions
--> $DIR/report_warning_on_non_adt.rs:9:1
|
LL | / #[diagnostic::on_move(
LL | |
LL | | message = "Foo",
LL | | label = "Bar",
LL | | )]
| |__^
|
= note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: Foo
--> $DIR/report_warning_on_non_adt.rs:21:15
|
LL | let foo = Foo;
| --- Bar
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_non_adt.rs:16:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_non_adt.rs:7:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,19 @@
#![feature(diagnostic_on_move)]
#[diagnostic::on_move(
message = "Foo",
label = "Bar",
baz="Baz"
//~^WARN unknown or malformed `on_move` attribute
//~|HELP only `message`, `note` and `label` are allowed as options. Their values must be string literals
)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR Foo
}
@@ -0,0 +1,38 @@
warning: unknown or malformed `on_move` attribute
--> $DIR/report_warning_on_unknown_options.rs:6:5
|
LL | baz="Baz"
| ^^^^^^^^^ invalid option found here
|
= help: only `message`, `note` and `label` are allowed as options. Their values must be string literals
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
error[E0382]: Foo
--> $DIR/report_warning_on_unknown_options.rs:17:15
|
LL | let foo = Foo;
| --- Bar
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/report_warning_on_unknown_options.rs:12:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/report_warning_on_unknown_options.rs:10:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,18 @@
//! This is an unusual feature gate test, as it doesn't test the feature
//! gate, but the fact that not adding the feature gate will cause the
//! diagnostic to not emit the custom diagnostic message
//!
#[diagnostic::on_move(
message = "Foo"
)]
#[derive(Debug)]
struct Foo;
fn takes_foo(_: Foo) {}
fn main() {
let foo = Foo;
takes_foo(foo);
let bar = foo;
//~^ERROR use of moved value: `foo`
}
@@ -0,0 +1,29 @@
error[E0382]: use of moved value: `foo`
--> $DIR/feature-gate-diagnostic-on-move.rs:16:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | takes_foo(foo);
| --- value moved here
LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/feature-gate-diagnostic-on-move.rs:11:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/feature-gate-diagnostic-on-move.rs:9:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | takes_foo(foo);
| --- you could clone this value
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0382`.
@@ -0,0 +1,85 @@
#![feature(impl_restriction)]
#![expect(incomplete_features)]
pub mod a {
pub enum E {}
pub mod d {}
pub mod b {
pub mod c {}
// We do not use crate-relative paths here, since we follow the
// "uniform paths" approach used for type/expression paths.
pub impl(in a::b) trait T1 {} //~ ERROR cannot find module or crate `a` in this scope [E0433]
pub impl(in ::std) trait T2 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in self::c) trait T3 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in super::d) trait T4 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in crate::c) trait T5 {} //~ ERROR cannot find module `c` in the crate root [E0433]
pub impl(in super::E) trait T6 {} //~ ERROR expected module, found enum `super::E` [E0577]
pub impl(in super::super::super) trait T7 {} //~ ERROR too many leading `super` keywords [E0433]
// OK paths
pub impl(crate) trait T8 {}
pub impl(self) trait T9 {}
pub impl(super) trait T10 {}
pub impl(in crate::a) trait T11 {}
pub impl(in super::super) trait T12 {}
// Check if we can resolve paths referring to modules declared later.
pub impl(in self::f) trait L1 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in super::G) trait L2 {} //~ ERROR expected module, found enum `super::G` [E0577]
pub impl(in super::h) trait L3 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub mod f {}
}
pub enum G {}
pub mod h {}
}
pub impl(in crate::a) trait T13 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in crate::a::E) trait T14 {} //~ ERROR expected module, found enum `crate::a::E` [E0577]
pub impl(crate) trait T15 {}
pub impl(self) trait T16 {}
pub impl(super) trait T17 {} //~ ERROR too many leading `super` keywords [E0433]
// Check if we can resolve paths referring to modules declared later.
pub impl(in crate::j) trait L4 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in crate::I) trait L5 {} //~ ERROR expected module, found enum `crate::I` [E0577]
pub enum I {}
pub mod j {}
// Check if we can resolve `use`d paths.
mod m1 {
pub impl(in crate::m2) trait U1 {} // OK
}
use m1 as m2;
mod m3 {
mod m4 {
pub impl(in crate::m2) trait U2 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in m6) trait U3 {} // OK
pub impl(in m6::m5) trait U4 {} //~ ERROR trait implementation can only be restricted to ancestor modules
pub impl(in m7) trait U5 {} //~ ERROR expected module, found enum `m7` [E0577]
use crate::m3 as m6;
use crate::m3::E as m7;
}
mod m5 {}
pub enum E {}
}
fn main() {}
@@ -0,0 +1,140 @@
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:14:21
|
LL | pub impl(in ::std) trait T2 {}
| ^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:16:21
|
LL | pub impl(in self::c) trait T3 {}
| ^^^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:18:21
|
LL | pub impl(in super::d) trait T4 {}
| ^^^^^^^^
error[E0433]: too many leading `super` keywords
--> $DIR/restriction_resolution_errors.rs:24:35
|
LL | pub impl(in super::super::super) trait T7 {}
| ^^^^^ there are too many leading `super` keywords
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:34:21
|
LL | pub impl(in self::f) trait L1 {}
| ^^^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:38:21
|
LL | pub impl(in super::h) trait L3 {}
| ^^^^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:47:13
|
LL | pub impl(in crate::a) trait T13 {}
| ^^^^^^^^
error[E0433]: too many leading `super` keywords
--> $DIR/restriction_resolution_errors.rs:54:10
|
LL | pub impl(super) trait T17 {}
| ^^^^^ there are too many leading `super` keywords
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:57:13
|
LL | pub impl(in crate::j) trait L4 {}
| ^^^^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:73:21
|
LL | pub impl(in crate::m2) trait U2 {}
| ^^^^^^^^^
error: trait implementation can only be restricted to ancestor modules
--> $DIR/restriction_resolution_errors.rs:75:21
|
LL | pub impl(in m6::m5) trait U4 {}
| ^^^^^^
error[E0433]: cannot find module or crate `a` in this scope
--> $DIR/restriction_resolution_errors.rs:12:21
|
LL | pub impl(in a::b) trait T1 {}
| ^ use of unresolved module or unlinked crate `a`
|
help: there is a crate or module with a similar name
|
LL - pub impl(in a::b) trait T1 {}
LL + pub impl(in c::b) trait T1 {}
|
help: consider importing this module
|
LL + use a;
|
error[E0433]: cannot find module `c` in the crate root
--> $DIR/restriction_resolution_errors.rs:20:28
|
LL | pub impl(in crate::c) trait T5 {}
| ^ not found in the crate root
error[E0577]: expected module, found enum `super::E`
--> $DIR/restriction_resolution_errors.rs:22:21
|
LL | pub impl(in super::E) trait T6 {}
| ^^^^^^^^ not a module
error[E0577]: expected module, found enum `super::G`
--> $DIR/restriction_resolution_errors.rs:36:21
|
LL | pub impl(in super::G) trait L2 {}
| ^^^^^^^^ not a module
error[E0577]: expected module, found enum `crate::a::E`
--> $DIR/restriction_resolution_errors.rs:49:13
|
LL | pub mod b {
| --------- similarly named module `b` defined here
...
LL | pub impl(in crate::a::E) trait T14 {}
| ^^^^^^^^^^^
|
help: a module with a similar name exists
|
LL - pub impl(in crate::a::E) trait T14 {}
LL + pub impl(in crate::a::b) trait T14 {}
|
error[E0577]: expected module, found enum `crate::I`
--> $DIR/restriction_resolution_errors.rs:59:13
|
LL | pub mod a {
| --------- similarly named module `a` defined here
...
LL | pub impl(in crate::I) trait L5 {}
| ^^^^^^^^
|
help: a module with a similar name exists
|
LL - pub impl(in crate::I) trait L5 {}
LL + pub impl(in crate::a) trait L5 {}
|
error[E0577]: expected module, found enum `m7`
--> $DIR/restriction_resolution_errors.rs:76:21
|
LL | pub impl(in m7) trait U5 {}
| ^^ not a module
error: aborting due to 18 previous errors
Some errors have detailed explanations: E0433, E0577.
For more information about an error, try `rustc --explain E0433`.
@@ -1,9 +1,13 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/89562>
//@ edition:2018
//@ run-pass
#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
use std::sync::Mutex;
// Copied from the issue. Allow-by-default for now, so run-pass
pub async fn foo() {
let foo = Mutex::new(1);
let lock = foo.lock().unwrap();