Auto merge of #138302 - matthiaskrgr:rollup-an2up80, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #136395 (Update to rand 0.9.0)
 - #137279 (Make some invalid codegen attr errors structured/translatable)
 - #137585 (Update documentation to consistently use 'm' in atomic synchronization example)
 - #137926 (Add a test for `-znostart-stop-gc` usage with LLD)
 - #138074 (Support `File::seek` for Hermit)
 - #138238 (Fix dyn -> param suggestion in struct ICEs)
 - #138270 (chore: Fix some comments)
 - #138286 (triagebot.toml: Don't label `test/rustdoc-json` as A-rustdoc-search (…)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-03-11 00:55:25 +00:00
commit 90384941aa
30 changed files with 436 additions and 178 deletions

View file

@ -2881,11 +2881,11 @@ dependencies = [
[[package]]
name = "rand_xoshiro"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41"
dependencies = [
"rand_core 0.6.4",
"rand_core 0.9.0",
]
[[package]]
@ -3155,7 +3155,7 @@ name = "rustc_abi"
version = "0.0.0"
dependencies = [
"bitflags",
"rand 0.8.5",
"rand 0.9.0",
"rand_xoshiro",
"rustc_data_structures",
"rustc_hashes",
@ -3789,7 +3789,7 @@ dependencies = [
name = "rustc_incremental"
version = "0.0.0"
dependencies = [
"rand 0.8.5",
"rand 0.9.0",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
@ -5176,8 +5176,8 @@ version = "0.1.0"
dependencies = [
"indicatif",
"num",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand 0.9.0",
"rand_chacha 0.9.0",
"rayon",
]

View file

@ -6,13 +6,13 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
rand = { version = "0.8.4", default-features = false, optional = true }
rand_xoshiro = { version = "0.6.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rand = { version = "0.9.0", default-features = false, optional = true }
rand_xoshiro = { version = "0.7.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_hashes = { path = "../rustc_hashes" }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -610,7 +610,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
Err(ErrorGuaranteed { .. }) => {
// We don't run dropck on HIR, and dropck looks inside fields of
// types, so there's no guarantee that it succeeds. We also
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
// can't rely on the `ErrorGuaranteed` from `fully_perform` here
// because it comes from delay_span_bug.
//
// Do this inside of a probe because we don't particularly care (or want)

View file

@ -18,6 +18,8 @@ codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing
codegen_ssa_autodiff_without_lto = using the autodiff feature requires using fat-lto
codegen_ssa_bare_instruction_set = `#[instruction_set]` requires an argument
codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
codegen_ssa_cgu_not_recorded =
@ -52,6 +54,10 @@ codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$err
codegen_ssa_error_writing_def_file =
Error writing .DEF file: {$error}
codegen_ssa_expected_name_value_pair = expected name value pair
codegen_ssa_expected_one_argument = expected one argument
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
@ -88,9 +94,17 @@ codegen_ssa_incorrect_cgu_reuse_type =
codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
codegen_ssa_invalid_argument = invalid argument
.help = valid inline arguments are `always` and `never`
codegen_ssa_invalid_instruction_set = invalid instruction set specified
codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
.note = the attribute requires exactly one argument
codegen_ssa_invalid_literal_value = invalid literal value
.label = value must be an integer between `0` and `255`
codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
@ -217,6 +231,8 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but
codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
codegen_ssa_multiple_instruction_set = cannot specify more than one instruction set
codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
.help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point
@ -229,6 +245,11 @@ codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't
codegen_ssa_null_on_export = `export_name` may not contain null characters
codegen_ssa_out_of_range_integer = integer value out of range
.label = value must be between `0` and `255`
codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
.note = {$output}
@ -236,6 +257,8 @@ codegen_ssa_read_file = failed to read file: {$message}
codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
codegen_ssa_requires_rust_abi = `#[track_caller]` requires Rust ABI
codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error}
codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
@ -356,6 +379,9 @@ codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
codegen_ssa_unexpected_parameter_name = unexpected parameter name
.label = expected `{$prefix_nops}` or `{$entry_nops}`
codegen_ssa_unknown_archive_kind =
Don't know how to build archive of type: {$kind}
@ -367,6 +393,8 @@ codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]`
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)

View file

@ -8,8 +8,6 @@ use rustc_ast::{MetaItem, MetaItemInner, attr};
use rustc_attr_parsing::ReprAttr::ReprAlign;
use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::codes::*;
use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
@ -236,13 +234,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().abi() != ExternAbi::Rust
{
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0737,
"`#[track_caller]` requires Rust ABI"
)
.emit();
tcx.dcx().emit_err(errors::RequiresRustAbi { span: attr.span() });
}
if is_closure
&& !tcx.features().closure_track_caller()
@ -263,13 +255,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if s.as_str().contains('\0') {
// `#[export_name = ...]` will be converted to a null-terminated string,
// so it may not contain any null characters.
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0648,
"`export_name` may not contain null characters"
)
.emit();
tcx.dcx().emit_err(errors::NullOnExport { span: attr.span() });
}
codegen_fn_attrs.export_name = Some(s);
mixed_export_name_no_mangle_lint_state.track_export_name(attr.span());
@ -394,47 +380,28 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
[sym::arm, sym::a32 | sym::t32]
if !tcx.sess.target.has_thumb_interworking =>
{
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0779,
"target does not support `#[instruction_set]`"
)
.emit();
tcx.dcx().emit_err(errors::UnsuportedInstructionSet {
span: attr.span(),
});
None
}
[sym::arm, sym::a32] => Some(InstructionSetAttr::ArmA32),
[sym::arm, sym::t32] => Some(InstructionSetAttr::ArmT32),
_ => {
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0779,
"invalid instruction set specified",
)
.emit();
tcx.dcx().emit_err(errors::InvalidInstructionSet {
span: attr.span(),
});
None
}
}
}
[] => {
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0778,
"`#[instruction_set]` requires an argument"
)
.emit();
tcx.dcx().emit_err(errors::BareInstructionSet { span: attr.span() });
None
}
_ => {
struct_span_code_err!(
tcx.dcx(),
attr.span(),
E0779,
"cannot specify more than one instruction set"
)
.emit();
tcx.dcx()
.emit_err(errors::MultipleInstructionSet { span: attr.span() });
None
}
})
@ -445,58 +412,38 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
let mut entry = None;
for item in l {
let Some(meta_item) = item.meta_item() else {
tcx.dcx().span_err(item.span(), "expected name value pair");
tcx.dcx().emit_err(errors::ExpectedNameValuePair { span: item.span() });
continue;
};
let Some(name_value_lit) = meta_item.name_value_literal() else {
tcx.dcx().span_err(item.span(), "expected name value pair");
tcx.dcx().emit_err(errors::ExpectedNameValuePair { span: item.span() });
continue;
};
fn emit_error_with_label(
tcx: TyCtxt<'_>,
span: Span,
error: impl Into<DiagMessage>,
label: impl Into<SubdiagMessage>,
) {
let mut err: rustc_errors::Diag<'_, _> =
tcx.dcx().struct_span_err(span, error);
err.span_label(span, label);
err.emit();
}
let attrib_to_write = match meta_item.name_or_empty() {
sym::prefix_nops => &mut prefix,
sym::entry_nops => &mut entry,
_ => {
emit_error_with_label(
tcx,
item.span(),
"unexpected parameter name",
format!("expected {} or {}", sym::prefix_nops, sym::entry_nops),
);
tcx.dcx().emit_err(errors::UnexpectedParameterName {
span: item.span(),
prefix_nops: sym::prefix_nops,
entry_nops: sym::entry_nops,
});
continue;
}
};
let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else {
emit_error_with_label(
tcx,
name_value_lit.span,
"invalid literal value",
"value must be an integer between `0` and `255`",
);
tcx.dcx().emit_err(errors::InvalidLiteralValue {
span: name_value_lit.span,
});
continue;
};
let Ok(val) = val.get().try_into() else {
emit_error_with_label(
tcx,
name_value_lit.span,
"integer value out of range",
"value must be between `0` and `255`",
);
tcx.dcx()
.emit_err(errors::OutOfRangeInteger { span: name_value_lit.span });
continue;
};
@ -533,7 +480,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
inline_span = Some(attr.span());
let [item] = &items[..] else {
struct_span_code_err!(tcx.dcx(), attr.span(), E0534, "expected one argument").emit();
tcx.dcx().emit_err(errors::ExpectedOneArgument { span: attr.span() });
return InlineAttr::None;
};
@ -542,9 +489,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
} else if item.has_name(sym::never) {
InlineAttr::Never
} else {
struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
.with_help("valid inline arguments are `always` and `never`")
.emit();
tcx.dcx().emit_err(errors::InvalidArgument { span: items[0].span() });
InlineAttr::None
}
@ -575,9 +520,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if !attr.has_name(sym::optimize) {
return ia;
}
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
if attr.is_word() {
err(attr.span(), "expected one argument");
tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() });
return ia;
}
let Some(ref items) = attr.meta_item_list() else {
@ -586,7 +530,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
inline_span = Some(attr.span());
let [item] = &items[..] else {
err(attr.span(), "expected one argument");
tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() });
return OptimizeAttr::Default;
};
if item.has_name(sym::size) {
@ -596,7 +540,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
} else if item.has_name(sym::none) {
OptimizeAttr::DoNotOptimize
} else {
err(item.span(), "invalid argument");
tcx.dcx().emit_err(errors::InvalidArgumentOptimize { span: item.span() });
OptimizeAttr::Default
}
});

View file

@ -135,6 +135,110 @@ pub(crate) struct NoSavedObjectFile<'a> {
pub cgu_name: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_requires_rust_abi, code = E0737)]
pub(crate) struct RequiresRustAbi {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_null_on_export, code = E0648)]
pub(crate) struct NullOnExport {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_unsupported_instruction_set, code = E0779)]
pub(crate) struct UnsuportedInstructionSet {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_instruction_set, code = E0779)]
pub(crate) struct InvalidInstructionSet {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_bare_instruction_set, code = E0778)]
pub(crate) struct BareInstructionSet {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_multiple_instruction_set, code = E0779)]
pub(crate) struct MultipleInstructionSet {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_name_value_pair)]
pub(crate) struct ExpectedNameValuePair {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_unexpected_parameter_name)]
pub(crate) struct UnexpectedParameterName {
#[primary_span]
#[label]
pub span: Span,
pub prefix_nops: Symbol,
pub entry_nops: Symbol,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_literal_value)]
pub(crate) struct InvalidLiteralValue {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_out_of_range_integer)]
pub(crate) struct OutOfRangeInteger {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_one_argument, code = E0534)]
pub(crate) struct ExpectedOneArgument {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_one_argument, code = E0722)]
pub(crate) struct ExpectedOneArgumentOptimize {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_argument, code = E0535)]
#[help]
pub(crate) struct InvalidArgument {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_argument, code = E0722)]
pub(crate) struct InvalidArgumentOptimize {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_copy_path_buf)]
pub(crate) struct CopyPathBuf {

View file

@ -363,7 +363,7 @@ pub trait Visitor<'v>: Sized {
/// See the doc comments on [`Ty`] for an explanation of what it means for a type to be
/// ambiguous.
///
/// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
/// The [`Visitor::visit_infer`] method should be overridden in order to handle infer vars.
fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) -> Self::Result {
walk_ty(self, t)
}
@ -374,7 +374,7 @@ pub trait Visitor<'v>: Sized {
/// See the doc comments on [`ConstArg`] for an explanation of what it means for a const to be
/// ambiguous.
///
/// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
/// The [`Visitor::visit_infer`] method should be overridden in order to handle infer vars.
fn visit_const_arg(&mut self, c: &'v ConstArg<'v, AmbigArg>) -> Self::Result {
walk_ambig_const_arg(self, c)
}

View file

@ -78,13 +78,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
if self_ty.span.edition().at_least_rust_2021() {
let msg = "expected a type, found a trait";
let label = "you can add the `dyn` keyword if you want a trait object";
let mut diag =
rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg);
let mut diag = rustc_errors::struct_span_code_err!(
self.dcx(),
self_ty.span,
E0782,
"{}",
"expected a type, found a trait"
);
if self_ty.span.can_be_used_for_suggestions()
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
&& !self.maybe_suggest_dyn_trait(self_ty, label, sugg, &mut diag)
&& !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
{
self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag);
}
@ -123,31 +126,62 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
/// For a struct or enum with an invalid bare trait object field, suggest turning
/// it into a generic type bound.
fn maybe_suggest_add_generic_impl_trait(
&self,
self_ty: &hir::Ty<'_>,
diag: &mut Diag<'_>,
) -> bool {
let tcx = self.tcx();
let msg = "you might be missing a type parameter";
let mut sugg = vec![];
let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
match parent_item.kind {
hir::ItemKind::Struct(_, generics) | hir::ItemKind::Enum(_, generics) => {
sugg.push((
generics.where_clause_span,
format!(
"<T: {}>",
self.tcx().sess.source_map().span_to_snippet(self_ty.span).unwrap()
),
));
sugg.push((self_ty.span, "T".to_string()));
let parent_hir_id = tcx.parent_hir_id(self_ty.hir_id);
let parent_item = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
let generics = match tcx.hir_node_by_def_id(parent_item) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Struct(variant, generics), ..
}) => {
if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
return false;
}
generics
}
_ => {}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(def, generics), .. }) => {
if !def
.variants
.iter()
.flat_map(|variant| variant.data.fields().iter())
.any(|field| field.hir_id == parent_hir_id)
{
return false;
}
generics
}
_ => return false,
};
let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
return false;
};
let param = "TUV"
.chars()
.map(|c| c.to_string())
.chain((0..).map(|i| format!("P{i}")))
.find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
.expect("we definitely can find at least one param name to generate");
let mut sugg = vec![(self_ty.span, param.to_string())];
if let Some(insertion_span) = generics.span_for_param_suggestion() {
sugg.push((insertion_span, format!(", {param}: {}", rendered_ty)));
} else {
sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty)));
}
diag.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
diag.multipart_suggestion_verbose(
"you might be missing a type parameter",
sugg,
Applicability::MachineApplicable,
);
true
}
/// Make sure that we are in the condition to suggest the blanket implementation.
@ -198,32 +232,59 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
/// Try our best to approximate when adding `dyn` would be helpful for a bare
/// trait object.
///
/// Right now, this is if the type is either directly nested in another ty,
/// or if it's in the tail field within a struct. This approximates what the
/// user would've gotten on edition 2015, except for the case where we have
/// an *obvious* knock-on `Sized` error.
fn maybe_suggest_dyn_trait(
&self,
self_ty: &hir::Ty<'_>,
label: &str,
sugg: Vec<(Span, String)>,
diag: &mut Diag<'_>,
) -> bool {
let tcx = self.tcx();
let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
// If the parent item is an enum, don't suggest the dyn trait.
if let hir::ItemKind::Enum(..) = parent_item.kind {
return false;
}
// Look at the direct HIR parent, since we care about the relationship between
// the type and the thing that directly encloses it.
match tcx.parent_hir_node(self_ty.hir_id) {
// These are all generally ok. Namely, when a trait object is nested
// into another expression or ty, it's either very certain that they
// missed the ty (e.g. `&Trait`) or it's not really possible to tell
// what their intention is, so let's not give confusing suggestions and
// just mention `dyn`. The user can make up their mind what to do here.
hir::Node::Ty(_)
| hir::Node::Expr(_)
| hir::Node::PatExpr(_)
| hir::Node::PathSegment(_)
| hir::Node::AssocItemConstraint(_)
| hir::Node::TraitRef(_)
| hir::Node::Item(_)
| hir::Node::WherePredicate(_) => {}
// If the parent item is a struct, check if self_ty is the last field.
if let hir::ItemKind::Struct(variant_data, _) = parent_item.kind {
if variant_data.fields().last().unwrap().ty.span != self_ty.span {
return false;
hir::Node::Field(field) => {
// Enums can't have unsized fields, fields can only have an unsized tail field.
if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Struct(variant, _), ..
}) = tcx.parent_hir_node(field.hir_id)
&& variant
.fields()
.last()
.is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
{
// Ok
} else {
return false;
}
}
_ => return false,
}
// FIXME: Only emit this suggestion if the trait is dyn-compatible.
diag.multipart_suggestion_verbose(
label.to_string(),
"you can add the `dyn` keyword if you want a trait object",
sugg,
Applicability::MachineApplicable,
);

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
rand = "0.8.4"
rand = "0.9.0"
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }

View file

@ -108,7 +108,7 @@ use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use rand::{RngCore, thread_rng};
use rand::{RngCore, rng};
use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::svh::Svh;
@ -445,7 +445,7 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result<bo
fn generate_session_dir_path(crate_dir: &Path) -> PathBuf {
let timestamp = timestamp_to_string(SystemTime::now());
debug!("generate_session_dir_path: timestamp = {}", timestamp);
let random_number = thread_rng().next_u32();
let random_number = rng().next_u32();
debug!("generate_session_dir_path: random_number = {}", random_number);
// Chop the first 3 characters off the timestamp. Those 3 bytes will be zero for a while.

View file

@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
return;
}
// At least one of the fields with a default value have been overriden in
// At least one of the fields with a default value have been overridden in
// the `Default` implementation. We suggest removing it and relying on `..`
// instead.
let any_default_field_given =

View file

@ -146,9 +146,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",

View file

@ -3998,24 +3998,24 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
///
/// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
/// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
/// exist operations X and Y, both operating on some atomic object 'M' such
/// exist operations X and Y, both operating on some atomic object 'm' such
/// that A is sequenced before X, Y is sequenced before B and Y observes
/// the change to M. This provides a happens-before dependence between A and B.
/// the change to m. This provides a happens-before dependence between A and B.
///
/// ```text
/// Thread 1 Thread 2
///
/// fence(Release); A --------------
/// x.store(3, Relaxed); X --------- |
/// m.store(3, Relaxed); X --------- |
/// | |
/// | |
/// -------------> Y if x.load(Relaxed) == 3 {
/// -------------> Y if m.load(Relaxed) == 3 {
/// |-------> B fence(Acquire);
/// ...
/// }
/// ```
///
/// Note that in the example above, it is crucial that the accesses to `x` are atomic. Fences cannot
/// Note that in the example above, it is crucial that the accesses to `m` are atomic. Fences cannot
/// be used to establish synchronization among non-atomic accesses in different threads. However,
/// thanks to the happens-before relationship between A and B, any non-atomic accesses that
/// happen-before A are now also properly synchronized with any non-atomic accesses that

View file

@ -73,7 +73,7 @@ fortanix-sgx-abi = { version = "0.5.0", features = [
], public = true }
[target.'cfg(target_os = "hermit")'.dependencies]
hermit-abi = { version = "0.4.0", features = [
hermit-abi = { version = "0.5.0", features = [
'rustc-dep-of-std',
], public = true }

View file

@ -417,12 +417,12 @@ impl File {
Ok(())
}
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
Err(Error::from_raw_os_error(22))
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
self.0.seek(pos)
}
pub fn tell(&self) -> io::Result<u64> {
self.seek(SeekFrom::Current(0))
self.0.tell()
}
pub fn duplicate(&self) -> io::Result<File> {

View file

@ -2,8 +2,8 @@
use super::hermit_abi;
use crate::cmp;
use crate::io::{self, IoSlice, IoSliceMut, Read};
use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd, *};
use crate::io::{self, IoSlice, IoSliceMut, Read, SeekFrom};
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys::{cvt, unsupported};
use crate::sys_common::{AsInner, FromInner, IntoInner};
@ -66,9 +66,26 @@ impl FileDesc {
true
}
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
let (whence, pos) = match pos {
// Casting to `i64` is fine, too large values will end up as
// negative which will cause an error in `lseek`.
SeekFrom::Start(off) => (hermit_abi::SEEK_SET, off as i64),
SeekFrom::End(off) => (hermit_abi::SEEK_END, off),
SeekFrom::Current(off) => (hermit_abi::SEEK_CUR, off),
};
let n = cvt(unsafe { hermit_abi::lseek(self.as_raw_fd(), pos as isize, whence) })?;
Ok(n as u64)
}
pub fn tell(&self) -> io::Result<u64> {
self.seek(SeekFrom::Current(0))
}
pub fn duplicate(&self) -> io::Result<FileDesc> {
self.duplicate_path(&[])
}
pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> {
unsupported()
}

View file

@ -67,7 +67,7 @@ have default field values.
## Lints
When manually implementing the `Default` trait for a type that has default
field values, if any of these are overriden in the impl the
field values, if any of these are overridden in the impl the
`default_overrides_default_fields` lint will trigger. This lint is in place
to avoid surprising diverging behavior between `S { .. }` and
`S::default()`, where using the same type in both ways could result in

View file

@ -7,8 +7,8 @@ publish = false
[dependencies]
indicatif = { version = "0.17.8", default-features = false }
num = "0.4.3"
rand = "0.8.5"
rand_chacha = "0.3"
rand = "0.9.0"
rand_chacha = "0.9.0"
rayon = "1"
[lib]

View file

@ -6,7 +6,7 @@ use std::ops::Range;
use std::sync::Mutex;
use rand::Rng;
use rand::distributions::{Distribution, Standard};
use rand::distr::{Distribution, StandardUniform};
use rand_chacha::ChaCha8Rng;
use rand_chacha::rand_core::SeedableRng;
@ -47,7 +47,7 @@ impl<F: Float> Fuzz<F> {
impl<F: Float> Generator<F> for Fuzz<F>
where
Standard: Distribution<<F as Float>::Int>,
StandardUniform: Distribution<<F as Float>::Int>,
{
const SHORT_NAME: &'static str = "fuzz";
@ -74,13 +74,13 @@ where
impl<F: Float> Iterator for Fuzz<F>
where
Standard: Distribution<<F as Float>::Int>,
StandardUniform: Distribution<<F as Float>::Int>,
{
type Item = <Self as Generator<F>>::WriteCtx;
fn next(&mut self) -> Option<Self::Item> {
let _ = self.iter.next()?;
let i: F::Int = self.rng.gen();
let i: F::Int = self.rng.random();
Some(F::from_bits(i))
}

View file

@ -3,7 +3,7 @@ use std::fmt::Write;
use std::marker::PhantomData;
use std::ops::{Range, RangeInclusive};
use rand::distributions::{Distribution, Uniform};
use rand::distr::{Distribution, Uniform};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
@ -40,7 +40,7 @@ impl<F: Float> Generator<F> for RandDigits<F> {
fn new() -> Self {
let rng = ChaCha8Rng::from_seed(SEED);
let range = Uniform::from(0..10);
let range = Uniform::try_from(0..10).unwrap();
Self { rng, iter: 0..ITERATIONS, uniform: range, marker: PhantomData }
}
@ -55,11 +55,11 @@ impl<F: Float> Iterator for RandDigits<F> {
fn next(&mut self) -> Option<Self::Item> {
let _ = self.iter.next()?;
let num_digits = self.rng.gen_range(POSSIBLE_NUM_DIGITS);
let has_decimal = self.rng.gen_bool(0.2);
let has_exp = self.rng.gen_bool(0.2);
let num_digits = self.rng.random_range(POSSIBLE_NUM_DIGITS);
let has_decimal = self.rng.random_bool(0.2);
let has_exp = self.rng.random_bool(0.2);
let dec_pos = if has_decimal { Some(self.rng.gen_range(0..num_digits)) } else { None };
let dec_pos = if has_decimal { Some(self.rng.random_range(0..num_digits)) } else { None };
let mut s = String::with_capacity(num_digits);
@ -75,7 +75,7 @@ impl<F: Float> Iterator for RandDigits<F> {
}
if has_exp {
let exp = self.rng.gen_range(EXP_RANGE);
let exp = self.rng.random_range(EXP_RANGE);
write!(s, "e{exp}").unwrap();
}

View file

@ -10,7 +10,7 @@ use std::sync::OnceLock;
use std::sync::atomic::{AtomicU64, Ordering};
use std::{fmt, time};
use rand::distributions::{Distribution, Standard};
use rand::distr::{Distribution, StandardUniform};
use rayon::prelude::*;
use time::{Duration, Instant};
use traits::{Float, Generator, Int};
@ -132,7 +132,7 @@ fn register_float<F: Float>(tests: &mut Vec<TestInfo>, cfg: &Config)
where
RangeInclusive<F::Int>: Iterator<Item = F::Int>,
<F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
Standard: Distribution<<F as traits::Float>::Int>,
StandardUniform: Distribution<<F as traits::Float>::Int>,
{
if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
// Only run exhaustive tests if there is a chance of completion.

View file

@ -1,11 +1,12 @@
//! Checks the licenses of third-party dependencies.
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use std::fs::{File, read_dir};
use std::io::Write;
use std::path::Path;
use build_helper::ci::CiEnv;
use cargo_metadata::semver::Version;
use cargo_metadata::{Metadata, Package, PackageId};
#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
@ -445,6 +446,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"wit-bindgen-rt@0.33.0", // via wasi
"writeable",
"yoke",
"yoke-derive",
@ -802,7 +804,17 @@ fn check_permitted_dependencies(
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
for permitted in permitted_dependencies {
if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
fn compare(pkg: &Package, permitted: &str) -> bool {
if let Some((name, version)) = permitted.split_once("@") {
let Ok(version) = Version::parse(version) else {
return false;
};
pkg.name == name && pkg.version == version
} else {
pkg.name == permitted
}
}
if !deps.iter().any(|dep_id| compare(pkg_from_id(metadata, dep_id), permitted)) {
tidy_error!(
bad,
"could not find allowed package `{permitted}`\n\
@ -813,14 +825,30 @@ fn check_permitted_dependencies(
}
// Get in a convenient form.
let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
let permitted_dependencies: HashMap<_, _> = permitted_dependencies
.iter()
.map(|s| {
if let Some((name, version)) = s.split_once('@') {
(name, Version::parse(version).ok())
} else {
(*s, None)
}
})
.collect();
for dep in deps {
let dep = pkg_from_id(metadata, dep);
// If this path is in-tree, we don't require it to be explicitly permitted.
if dep.source.is_some() && !permitted_dependencies.contains(dep.name.as_str()) {
tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
has_permitted_dep_error = true;
if dep.source.is_some() {
let is_eq = if let Some(version) = permitted_dependencies.get(dep.name.as_str()) {
if let Some(version) = version { version == &dep.version } else { true }
} else {
false
};
if !is_eq {
tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
has_permitted_dep_error = true;
}
}
}

View file

@ -3,7 +3,7 @@
//
// It should work, but due to interactions between how #[cfg]s are
// expanded, the lint machinery and the check-cfg impl, we
// miss the #[allow], althrough we probably shoudln't.
// miss the #[allow], althrough we probably shouldn't.
//
// cf. https://github.com/rust-lang/rust/issues/124735
//

View file

@ -7,6 +7,12 @@ fn function(x: &SomeTrait, y: Box<SomeTrait>) {
//~^ ERROR expected a type, found a trait
}
// Regression test for <https://github.com/rust-lang/rust/issues/138211>.
extern "C" {
fn foo() -> *const SomeTrait;
//~^ ERROR expected a type, found a trait
}
trait SomeTrait {}
fn main() {}

View file

@ -29,6 +29,17 @@ help: you can add the `dyn` keyword if you want a trait object
LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) {
| +++
error[E0782]: expected a type, found a trait
--> $DIR/dyn-2021-edition-error.rs:12:24
|
LL | fn foo() -> *const SomeTrait;
| ^^^^^^^^^
|
help: you can add the `dyn` keyword if you want a trait object
|
LL | fn foo() -> *const dyn SomeTrait;
| +++
error[E0782]: expected a type, found a trait
--> $DIR/dyn-2021-edition-error.rs:6:14
|
@ -40,6 +51,6 @@ help: you can add the `dyn` keyword if you want a trait object
LL | let _x: &dyn SomeTrait = todo!();
| +++
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0782`.

View file

@ -13,7 +13,6 @@ struct Foo2 {
//~^ ERROR expected a type, found a trait
}
enum Enum1 {
A(Trait),
//~^ ERROR expected a type, found a trait
@ -26,5 +25,17 @@ enum Enum2 {
//~^ ERROR expected a type, found a trait
}
// Regression test for <https://github.com/rust-lang/rust/issues/138229>.
pub struct InWhereClause
where
Trait:, {}
//~^ ERROR expected a type, found a trait
struct HasGenerics<T> {
f: Trait,
//~^ ERROR expected a type, found a trait
t: T,
}
fn main() {}

View file

@ -22,7 +22,7 @@ LL | b: dyn Trait,
| +++
error[E0782]: expected a type, found a trait
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:18:7
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:17:7
|
LL | A(Trait),
| ^^^^^
@ -34,7 +34,7 @@ LL ~ A(T),
|
error[E0782]: expected a type, found a trait
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:25:7
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:24:7
|
LL | B(Trait),
| ^^^^^
@ -46,6 +46,29 @@ LL | A(u32),
LL ~ B(T),
|
error: aborting due to 4 previous errors
error[E0782]: expected a type, found a trait
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:35:8
|
LL | f: Trait,
| ^^^^^
|
help: you might be missing a type parameter
|
LL ~ struct HasGenerics<T, U: Trait> {
LL ~ f: U,
|
error[E0782]: expected a type, found a trait
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:31:5
|
LL | Trait:, {}
| ^^^^^
|
help: you can add the `dyn` keyword if you want a trait object
|
LL | dyn Trait:, {}
| +++
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0782`.

View file

@ -0,0 +1,25 @@
// This test checks that encapsulation symbols are not garbage collected by the linker.
// LLD will remove them by default, so this test checks that we pass `-znostart-stop-gc` to LLD
// to avoid that behavior. Without that flag, the test should fail.
// This test is inspired by the behavior of the linkme crate.
//
//@ build-pass
//@ only-x86_64-unknown-linux-gnu
unsafe extern "Rust" {
// The __start_ section name is magical for the linker,
// It will put link sections named EXTERNFNS after it.
#[link_name = "__start_EXTERNFNS"]
static SECTION_START: fn();
}
#[used]
#[unsafe(link_section = "EXTERNFNS")]
static EXTERN_FN_LOCAL: fn() = extern_fn;
fn extern_fn() {}
fn main() {
// We need to reference the SECTION_START symbol to avoid it being garbage collected
let slice = unsafe { SECTION_START };
}

View file

@ -20,7 +20,7 @@ error: unexpected parameter name
--> $DIR/patchable-function-entry-attribute.rs:13:46
|
LL | #[patchable_function_entry(prefix_nops = 10, something = 0)]
| ^^^^^^^^^^^^^ expected prefix_nops or entry_nops
| ^^^^^^^^^^^^^ expected `prefix_nops` or `entry_nops`
error: must specify at least one parameter
--> $DIR/patchable-function-entry-attribute.rs:16:1

View file

@ -274,7 +274,7 @@ trigger_files = [
[autolabel."A-rustdoc-search"]
trigger_files = [
"src/librustdoc/html/static/js/search.js",
"tests/rustdoc-js",
"tests/rustdoc-js/",
"tests/rustdoc-js-std",
]