mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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:
+2
-2
@@ -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,
|
||||
|
||||
@@ -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: ¬e_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: ¬e_msg,
|
||||
span,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
|
||||
is_partial_move,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}`")]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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`
|
||||
}
|
||||
+38
@@ -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`.
|
||||
+18
@@ -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`
|
||||
}
|
||||
+44
@@ -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`.
|
||||
+18
@@ -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`
|
||||
}
|
||||
+44
@@ -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`.
|
||||
+5
-1
@@ -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();
|
||||
Reference in New Issue
Block a user