Auto merge of #147140 - Zalathar:rollup-rtnqek7, r=Zalathar
Rollup of 7 pull requests Successful merges: - rust-lang/rust#133477 (Detect tuple structs that are unconstructable due to re-export) - rust-lang/rust#146929 (compiletest: Remove old-output-capture and become a stage0 bootstrap tool) - rust-lang/rust#146979 (constify Default on Nanoseconds) - rust-lang/rust#147092 (Do not compute optimized MIR if code does not type-check.) - rust-lang/rust#147112 (all 48 keywords in just 300 characters) - rust-lang/rust#147122 (Fix some crash-test directives) - rust-lang/rust#147127 (Add a leading dash to linker plugin arguments in the gcc codegen) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7af913fc90
38 changed files with 359 additions and 311 deletions
|
|
@ -165,6 +165,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
""
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"cranelift"
|
||||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
use rustc_session::config::{InstrumentCoverage, Lto};
|
||||
match sess.lto() {
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ impl CodegenBackend for GccCodegenBackend {
|
|||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"gcc"
|
||||
}
|
||||
|
||||
fn init(&self, _sess: &Session) {
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -232,6 +232,10 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"llvm"
|
||||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
llvm_util::init(sess); // Make sure llvm is inited
|
||||
}
|
||||
|
|
@ -350,7 +354,14 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
|
||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||
// This should produce either a finished executable or library.
|
||||
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs);
|
||||
link_binary(
|
||||
sess,
|
||||
&LlvmArchiveBuilderBuilder,
|
||||
codegen_results,
|
||||
metadata,
|
||||
outputs,
|
||||
self.name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ pub fn link_binary(
|
|||
codegen_results: CodegenResults,
|
||||
metadata: EncodedMetadata,
|
||||
outputs: &OutputFilenames,
|
||||
codegen_backend: &'static str,
|
||||
) {
|
||||
let _timer = sess.timer("link_binary");
|
||||
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||
|
|
@ -154,6 +155,7 @@ pub fn link_binary(
|
|||
&codegen_results,
|
||||
&metadata,
|
||||
path.as_ref(),
|
||||
codegen_backend,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -680,6 +682,7 @@ fn link_natively(
|
|||
codegen_results: &CodegenResults,
|
||||
metadata: &EncodedMetadata,
|
||||
tmpdir: &Path,
|
||||
codegen_backend: &'static str,
|
||||
) {
|
||||
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
||||
let (linker_path, flavor) = linker_and_flavor(sess);
|
||||
|
|
@ -705,6 +708,7 @@ fn link_natively(
|
|||
codegen_results,
|
||||
metadata,
|
||||
self_contained_components,
|
||||
codegen_backend,
|
||||
);
|
||||
|
||||
linker::disable_localization(&mut cmd);
|
||||
|
|
@ -2208,6 +2212,7 @@ fn linker_with_args(
|
|||
codegen_results: &CodegenResults,
|
||||
metadata: &EncodedMetadata,
|
||||
self_contained_components: LinkSelfContainedComponents,
|
||||
codegen_backend: &'static str,
|
||||
) -> Command {
|
||||
let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
|
||||
let cmd = &mut *super::linker::get_linker(
|
||||
|
|
@ -2216,6 +2221,7 @@ fn linker_with_args(
|
|||
flavor,
|
||||
self_contained_components.are_any_components_enabled(),
|
||||
&codegen_results.crate_info.target_cpu,
|
||||
codegen_backend,
|
||||
);
|
||||
let link_output_kind = link_output_kind(sess, crate_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ pub(crate) fn get_linker<'a>(
|
|||
flavor: LinkerFlavor,
|
||||
self_contained: bool,
|
||||
target_cpu: &'a str,
|
||||
codegen_backend: &'static str,
|
||||
) -> Box<dyn Linker + 'a> {
|
||||
let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe");
|
||||
|
||||
|
|
@ -154,6 +155,7 @@ pub(crate) fn get_linker<'a>(
|
|||
is_ld: cc == Cc::No,
|
||||
is_gnu: flavor.is_gnu(),
|
||||
uses_lld: flavor.uses_lld(),
|
||||
codegen_backend,
|
||||
}) as Box<dyn Linker>,
|
||||
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
|
@ -367,6 +369,7 @@ struct GccLinker<'a> {
|
|||
is_ld: bool,
|
||||
is_gnu: bool,
|
||||
uses_lld: bool,
|
||||
codegen_backend: &'static str,
|
||||
}
|
||||
|
||||
impl<'a> GccLinker<'a> {
|
||||
|
|
@ -423,9 +426,15 @@ impl<'a> GccLinker<'a> {
|
|||
if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
|
||||
self.link_arg(&format!("-plugin-opt=sample-profile={}", path.display()));
|
||||
};
|
||||
let prefix = if self.codegen_backend == "gcc" {
|
||||
// The GCC linker plugin requires a leading dash.
|
||||
"-"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
self.link_args(&[
|
||||
&format!("-plugin-opt={opt_level}"),
|
||||
&format!("-plugin-opt=mcpu={}", self.target_cpu),
|
||||
&format!("-plugin-opt={prefix}{opt_level}"),
|
||||
&format!("-plugin-opt={prefix}mcpu={}", self.target_cpu),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ pub trait CodegenBackend {
|
|||
/// Called before `init` so that all other functions are able to emit translatable diagnostics.
|
||||
fn locale_resource(&self) -> &'static str;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
fn init(&self, _sess: &Session) {}
|
||||
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
|
||||
|
|
@ -96,7 +98,14 @@ pub trait CodegenBackend {
|
|||
metadata: EncodedMetadata,
|
||||
outputs: &OutputFilenames,
|
||||
) {
|
||||
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
|
||||
link_binary(
|
||||
sess,
|
||||
&ArArchiveBuilderBuilder,
|
||||
codegen_results,
|
||||
metadata,
|
||||
outputs,
|
||||
self.name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1122,18 +1122,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
|
||||
sess.time("layout_testing", || layout_test::test_layout(tcx));
|
||||
sess.time("abi_testing", || abi_test::test_abi(tcx));
|
||||
|
||||
// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
|
||||
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
|
||||
// in MIR optimizations that may only be reachable through codegen, or other codepaths
|
||||
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
|
||||
if tcx.sess.opts.unstable_opts.validate_mir {
|
||||
sess.time("ensuring_final_MIR_is_computable", || {
|
||||
tcx.par_hir_body_owners(|def_id| {
|
||||
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the type-checking, region checking and other miscellaneous analysis
|
||||
|
|
@ -1199,6 +1187,20 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
|
|||
// we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
|
||||
let _ = tcx.all_diagnostic_items(());
|
||||
});
|
||||
|
||||
// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
|
||||
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
|
||||
// in MIR optimizations that may only be reachable through codegen, or other codepaths
|
||||
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
|
||||
// Nevertheless, wait after type checking is finished, as optimizing code that does not
|
||||
// type-check is very prone to ICEs.
|
||||
if tcx.sess.opts.unstable_opts.validate_mir {
|
||||
sess.time("ensuring_final_MIR_is_computable", || {
|
||||
tcx.par_hir_body_owners(|def_id| {
|
||||
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the codegen backend, after which the AST and analysis can
|
||||
|
|
|
|||
|
|
@ -901,6 +901,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
binding,
|
||||
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
|
||||
parent_scope,
|
||||
module,
|
||||
finalize,
|
||||
shadowing,
|
||||
);
|
||||
|
|
@ -1025,6 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
binding: Option<NameBinding<'ra>>,
|
||||
shadowed_glob: Option<NameBinding<'ra>>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
module: Module<'ra>,
|
||||
finalize: Finalize,
|
||||
shadowing: Shadowing,
|
||||
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
|
||||
|
|
@ -1076,6 +1078,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||
}
|
||||
|
||||
// If we encounter a re-export for a type with private fields, it will not be able to
|
||||
// be constructed through this re-export. We track that case here to expand later
|
||||
// privacy errors with appropriate information.
|
||||
if let Res::Def(_, def_id) = binding.res() {
|
||||
let struct_ctor = match def_id.as_local() {
|
||||
Some(def_id) => self.struct_constructors.get(&def_id).cloned(),
|
||||
None => {
|
||||
let ctor = self.cstore().ctor_untracked(def_id);
|
||||
ctor.map(|(ctor_kind, ctor_def_id)| {
|
||||
let ctor_res = Res::Def(
|
||||
DefKind::Ctor(rustc_hir::def::CtorOf::Struct, ctor_kind),
|
||||
ctor_def_id,
|
||||
);
|
||||
let ctor_vis = self.tcx.visibility(ctor_def_id);
|
||||
let field_visibilities = self
|
||||
.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.map(|field_id| self.tcx.visibility(field_id))
|
||||
.collect();
|
||||
(ctor_res, ctor_vis, field_visibilities)
|
||||
})
|
||||
}
|
||||
};
|
||||
if let Some((_, _, fields)) = struct_ctor
|
||||
&& fields.iter().any(|vis| !self.is_accessible_from(*vis, module))
|
||||
{
|
||||
self.inaccessible_ctor_reexport.insert(path_span, binding.span);
|
||||
}
|
||||
}
|
||||
|
||||
self.record_use(ident, binding, used);
|
||||
return Ok(binding);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1942,44 +1942,77 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
return true;
|
||||
};
|
||||
|
||||
let update_message =
|
||||
|this: &mut Self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>| {
|
||||
match source {
|
||||
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||
PathSource::TupleStruct(_, pattern_spans) => {
|
||||
err.primary_message(
|
||||
"cannot match against a tuple struct which contains private fields",
|
||||
);
|
||||
|
||||
// Use spans of the tuple struct pattern.
|
||||
Some(Vec::from(*pattern_spans))
|
||||
}
|
||||
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
||||
PathSource::Expr(Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
span: call_span,
|
||||
..
|
||||
})) => {
|
||||
err.primary_message(
|
||||
"cannot initialize a tuple struct which contains private fields",
|
||||
);
|
||||
this.suggest_alternative_construction_methods(
|
||||
def_id,
|
||||
err,
|
||||
path.span,
|
||||
*call_span,
|
||||
&args[..],
|
||||
);
|
||||
// Use spans of the tuple struct definition.
|
||||
this.r
|
||||
.field_idents(def_id)
|
||||
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
|
||||
if let Some(use_span) = self.r.inaccessible_ctor_reexport.get(&span)
|
||||
&& is_accessible
|
||||
{
|
||||
err.span_note(
|
||||
*use_span,
|
||||
"the type is accessed through this re-export, but the type's constructor \
|
||||
is not visible in this import's scope due to private fields",
|
||||
);
|
||||
if is_accessible
|
||||
&& fields
|
||||
.iter()
|
||||
.all(|vis| self.r.is_accessible_from(*vis, self.parent_scope.module))
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"the type can be constructed directly, because its fields are \
|
||||
available from the current scope",
|
||||
// Using `tcx.def_path_str` causes the compiler to hang.
|
||||
// We don't need to handle foreign crate types because in that case you
|
||||
// can't access the ctor either way.
|
||||
format!(
|
||||
"crate{}", // The method already has leading `::`.
|
||||
self.r.tcx.def_path(def_id).to_string_no_crate_verbose(),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
update_message(self, err, &source);
|
||||
}
|
||||
if !is_expected(ctor_def) || is_accessible {
|
||||
return true;
|
||||
}
|
||||
|
||||
let field_spans = match source {
|
||||
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||
PathSource::TupleStruct(_, pattern_spans) => {
|
||||
err.primary_message(
|
||||
"cannot match against a tuple struct which contains private fields",
|
||||
);
|
||||
|
||||
// Use spans of the tuple struct pattern.
|
||||
Some(Vec::from(pattern_spans))
|
||||
}
|
||||
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
||||
PathSource::Expr(Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
span: call_span,
|
||||
..
|
||||
})) => {
|
||||
err.primary_message(
|
||||
"cannot initialize a tuple struct which contains private fields",
|
||||
);
|
||||
self.suggest_alternative_construction_methods(
|
||||
def_id,
|
||||
err,
|
||||
path.span,
|
||||
*call_span,
|
||||
&args[..],
|
||||
);
|
||||
// Use spans of the tuple struct definition.
|
||||
self.r
|
||||
.field_idents(def_id)
|
||||
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let field_spans = update_message(self, err, &source);
|
||||
|
||||
if let Some(spans) =
|
||||
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
|
||||
|
|
|
|||
|
|
@ -1167,6 +1167,11 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(),
|
||||
|
||||
/// When a type is re-exported that has an inaccessible constructor because it has fields that
|
||||
/// are inaccessible from the import's scope, we mark that as the type won't be able to be built
|
||||
/// through the re-export. We use this information to extend the existing diagnostic.
|
||||
inaccessible_ctor_reexport: FxHashMap<Span, Span>,
|
||||
|
||||
arenas: &'ra ResolverArenas<'ra>,
|
||||
dummy_binding: NameBinding<'ra>,
|
||||
builtin_types_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
|
||||
|
|
@ -1595,6 +1600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
glob_map: Default::default(),
|
||||
used_imports: FxHashSet::default(),
|
||||
maybe_unused_trait_imports: Default::default(),
|
||||
inaccessible_ctor_reexport: Default::default(),
|
||||
|
||||
arenas,
|
||||
dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ impl Nanoseconds {
|
|||
pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) };
|
||||
}
|
||||
|
||||
impl Default for Nanoseconds {
|
||||
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
|
||||
impl const Default for Nanoseconds {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use crate::core::build_steps::compile::{
|
|||
};
|
||||
use crate::core::build_steps::tool;
|
||||
use crate::core::build_steps::tool::{
|
||||
COMPILETEST_ALLOW_FEATURES, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode,
|
||||
get_tool_target_compiler, prepare_tool_cargo,
|
||||
SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
|
||||
prepare_tool_cargo,
|
||||
};
|
||||
use crate::core::builder::{
|
||||
self, Alias, Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
|
||||
|
|
@ -654,7 +654,7 @@ macro_rules! tool_check_step {
|
|||
// The part of this path after the final '/' is also used as a display name.
|
||||
path: $path:literal
|
||||
$(, alt_path: $alt_path:literal )*
|
||||
// Closure that returns `Mode` based on the passed `&Builder<'_>`
|
||||
// `Mode` to use when checking this tool
|
||||
, mode: $mode:expr
|
||||
// Subset of nightly features that are allowed to be used when checking
|
||||
$(, allow_features: $allow_features:expr )?
|
||||
|
|
@ -682,8 +682,7 @@ macro_rules! tool_check_step {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let target = run.target;
|
||||
let builder = run.builder;
|
||||
let mode = $mode(builder);
|
||||
let mode: Mode = $mode;
|
||||
|
||||
let compiler = prepare_compiler_for_check(run.builder, target, mode);
|
||||
|
||||
|
|
@ -704,7 +703,7 @@ macro_rules! tool_check_step {
|
|||
_value
|
||||
};
|
||||
let extra_features: &[&str] = &[$($($enable_features),*)?];
|
||||
let mode = $mode(builder);
|
||||
let mode: Mode = $mode;
|
||||
run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features);
|
||||
}
|
||||
|
||||
|
|
@ -767,57 +766,50 @@ fn run_tool_check_step(
|
|||
tool_check_step!(Rustdoc {
|
||||
path: "src/tools/rustdoc",
|
||||
alt_path: "src/librustdoc",
|
||||
mode: |_builder| Mode::ToolRustcPrivate
|
||||
mode: Mode::ToolRustcPrivate
|
||||
});
|
||||
// Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead
|
||||
// of a submodule. Since the SourceType only drives the deny-warnings
|
||||
// behavior, treat it as in-tree so that any new warnings in clippy will be
|
||||
// rejected.
|
||||
tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(CargoMiri {
|
||||
path: "src/tools/miri/cargo-miri",
|
||||
mode: |_builder| Mode::ToolRustcPrivate
|
||||
});
|
||||
tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(RustAnalyzer {
|
||||
path: "src/tools/rust-analyzer",
|
||||
mode: |_builder| Mode::ToolRustcPrivate,
|
||||
mode: Mode::ToolRustcPrivate,
|
||||
allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
|
||||
enable_features: ["in-rust-tree"],
|
||||
});
|
||||
tool_check_step!(MiroptTestTools {
|
||||
path: "src/tools/miropt-test-tools",
|
||||
mode: |_builder| Mode::ToolBootstrap
|
||||
mode: Mode::ToolBootstrap
|
||||
});
|
||||
// We want to test the local std
|
||||
tool_check_step!(TestFloatParse {
|
||||
path: "src/tools/test-float-parse",
|
||||
mode: |_builder| Mode::ToolStd,
|
||||
mode: Mode::ToolStd,
|
||||
allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
|
||||
});
|
||||
tool_check_step!(FeaturesStatusDump {
|
||||
path: "src/tools/features-status-dump",
|
||||
mode: |_builder| Mode::ToolBootstrap
|
||||
mode: Mode::ToolBootstrap
|
||||
});
|
||||
|
||||
tool_check_step!(Bootstrap {
|
||||
path: "src/bootstrap",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
|
||||
|
||||
// `run-make-support` will be built as part of suitable run-make compiletest test steps, but support
|
||||
// check to make it easier to work on.
|
||||
tool_check_step!(RunMakeSupport {
|
||||
path: "src/tools/run-make-support",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
tool_check_step!(CoverageDump {
|
||||
path: "src/tools/coverage-dump",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
|
|
@ -825,23 +817,18 @@ tool_check_step!(CoverageDump {
|
|||
// so this is mainly for people working on compiletest to run locally.
|
||||
tool_check_step!(Compiletest {
|
||||
path: "src/tools/compiletest",
|
||||
mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
|
||||
Mode::ToolBootstrap
|
||||
} else {
|
||||
Mode::ToolStd
|
||||
},
|
||||
allow_features: COMPILETEST_ALLOW_FEATURES,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false,
|
||||
});
|
||||
|
||||
tool_check_step!(Linkchecker {
|
||||
path: "src/tools/linkchecker",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
tool_check_step!(BumpStage0 {
|
||||
path: "src/tools/bump-stage0",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ use crate::core::build_steps::llvm::get_llvm_version;
|
|||
use crate::core::build_steps::run::get_completion_paths;
|
||||
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
|
||||
use crate::core::build_steps::tool::{
|
||||
self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType,
|
||||
TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool, ToolTargetBuildMode, get_tool_target_compiler,
|
||||
self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
|
||||
ToolTargetBuildMode, get_tool_target_compiler,
|
||||
};
|
||||
use crate::core::build_steps::toolstate::ToolState;
|
||||
use crate::core::build_steps::{compile, dist, llvm};
|
||||
|
|
@ -36,7 +36,7 @@ use crate::utils::helpers::{
|
|||
linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
|
||||
};
|
||||
use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
|
||||
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, envify};
|
||||
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
|
||||
|
||||
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
|
||||
|
||||
|
|
@ -786,26 +786,26 @@ impl Step for CompiletestTest {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let host = self.host;
|
||||
|
||||
// Now that compiletest uses only stable Rust, building it always uses
|
||||
// the stage 0 compiler. However, some of its unit tests need to be able
|
||||
// to query information from an in-tree compiler, so we treat `--stage`
|
||||
// as selecting the stage of that secondary compiler.
|
||||
|
||||
if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
|
||||
eprintln!("\
|
||||
ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail
|
||||
ERROR: `--stage 0` causes compiletest to query information from the stage0 (precompiled) compiler, instead of the in-tree compiler, which can cause some tests to fail inappropriately
|
||||
NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`."
|
||||
);
|
||||
crate::exit!(1);
|
||||
}
|
||||
|
||||
let compiler = builder.compiler(builder.top_stage, host);
|
||||
debug!(?compiler);
|
||||
let bootstrap_compiler = builder.compiler(0, host);
|
||||
let staged_compiler = builder.compiler(builder.top_stage, host);
|
||||
|
||||
// We need `ToolStd` for the locally-built sysroot because
|
||||
// compiletest uses unstable features of the `test` crate.
|
||||
builder.std(compiler, host);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
// compiletest uses libtest internals; make it use the in-tree std to make sure it never
|
||||
// breaks when std sources change.
|
||||
Mode::ToolStd,
|
||||
bootstrap_compiler,
|
||||
Mode::ToolBootstrap,
|
||||
host,
|
||||
Kind::Test,
|
||||
"src/tools/compiletest",
|
||||
|
|
@ -816,9 +816,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
// Used for `compiletest` self-tests to have the path to the *staged* compiler. Getting this
|
||||
// right is important, as `compiletest` is intended to only support one target spec JSON
|
||||
// format, namely that of the staged compiler.
|
||||
cargo.env("TEST_RUSTC", builder.rustc(compiler));
|
||||
cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
|
||||
|
||||
cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
|
||||
run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,7 +380,6 @@ macro_rules! bootstrap_tool {
|
|||
($(
|
||||
$name:ident, $path:expr, $tool_name:expr
|
||||
$(,is_external_tool = $external:expr)*
|
||||
$(,is_unstable_tool = $unstable:expr)*
|
||||
$(,allow_features = $allow_features:expr)?
|
||||
$(,submodules = $submodules:expr)?
|
||||
$(,artifact_kind = $artifact_kind:expr)?
|
||||
|
|
@ -438,19 +437,11 @@ macro_rules! bootstrap_tool {
|
|||
}
|
||||
)*
|
||||
|
||||
let is_unstable = false $(|| $unstable)*;
|
||||
let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest;
|
||||
|
||||
builder.ensure(ToolBuild {
|
||||
build_compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: $tool_name,
|
||||
mode: if is_unstable && !compiletest_wants_stage0 {
|
||||
// use in-tree libraries for unstable features
|
||||
Mode::ToolStd
|
||||
} else {
|
||||
Mode::ToolBootstrap
|
||||
},
|
||||
mode: Mode::ToolBootstrap,
|
||||
path: $path,
|
||||
source_type: if false $(|| $external)* {
|
||||
SourceType::Submodule
|
||||
|
|
@ -483,8 +474,6 @@ macro_rules! bootstrap_tool {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "internal_output_capture";
|
||||
|
||||
bootstrap_tool!(
|
||||
// This is marked as an external tool because it includes dependencies
|
||||
// from submodules. Trying to keep the lints in sync between all the repos
|
||||
|
|
@ -495,7 +484,7 @@ bootstrap_tool!(
|
|||
Tidy, "src/tools/tidy", "tidy";
|
||||
Linkchecker, "src/tools/linkchecker", "linkchecker";
|
||||
CargoTest, "src/tools/cargotest", "cargotest";
|
||||
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
|
||||
Compiletest, "src/tools/compiletest", "compiletest";
|
||||
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
||||
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
|
||||
RustInstaller, "src/tools/rust-installer", "rust-installer";
|
||||
|
|
@ -509,8 +498,7 @@ bootstrap_tool!(
|
|||
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
|
||||
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
|
||||
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
|
||||
// rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
|
||||
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
|
||||
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test";
|
||||
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
|
||||
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
|
||||
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
|
||||
|
|
|
|||
|
|
@ -2004,21 +2004,6 @@ mod snapshot {
|
|||
.render_steps(), @"[check] rustc 0 <host> -> Compiletest 1 <host>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_compiletest_stage1_libtest() {
|
||||
let ctx = TestCtx::new();
|
||||
insta::assert_snapshot!(
|
||||
ctx.config("check")
|
||||
.path("compiletest")
|
||||
.args(&["--set", "build.compiletest-use-stage0-libtest=false"])
|
||||
.render_steps(), @r"
|
||||
[build] llvm <host>
|
||||
[build] rustc 0 <host> -> rustc 1 <host>
|
||||
[build] rustc 1 <host> -> std 1 <host>
|
||||
[check] rustc 1 <host> -> Compiletest 2 <host>
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_codegen() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
@ -2145,6 +2130,17 @@ mod snapshot {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiletest_self_test() {
|
||||
let ctx = TestCtx::new();
|
||||
let steps = ctx.config("test").arg("compiletest").render_steps();
|
||||
insta::assert_snapshot!(steps, @r"
|
||||
[build] llvm <host>
|
||||
[build] rustc 0 <host> -> rustc 1 <host>
|
||||
[build] rustdoc 0 <host>
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiletest_suites_stage1() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
|
|||
|
|
@ -310,9 +310,6 @@ pub struct Config {
|
|||
/// sources.
|
||||
pub compiletest_allow_stage0: bool,
|
||||
|
||||
/// Whether to use the precompiled stage0 libtest with compiletest.
|
||||
pub compiletest_use_stage0_libtest: bool,
|
||||
|
||||
/// Default value for `--extra-checks`
|
||||
pub tidy_extra_checks: Option<String>,
|
||||
pub is_running_on_ci: bool,
|
||||
|
|
@ -497,7 +494,8 @@ impl Config {
|
|||
optimized_compiler_builtins: build_optimized_compiler_builtins,
|
||||
jobs: build_jobs,
|
||||
compiletest_diff_tool: build_compiletest_diff_tool,
|
||||
compiletest_use_stage0_libtest: build_compiletest_use_stage0_libtest,
|
||||
// No longer has any effect; kept (for now) to avoid breaking people's configs.
|
||||
compiletest_use_stage0_libtest: _,
|
||||
tidy_extra_checks: build_tidy_extra_checks,
|
||||
ccache: build_ccache,
|
||||
exclude: build_exclude,
|
||||
|
|
@ -1197,7 +1195,6 @@ impl Config {
|
|||
compiler_docs: build_compiler_docs.unwrap_or(false),
|
||||
compiletest_allow_stage0: build_compiletest_allow_stage0.unwrap_or(false),
|
||||
compiletest_diff_tool: build_compiletest_diff_tool,
|
||||
compiletest_use_stage0_libtest: build_compiletest_use_stage0_libtest.unwrap_or(true),
|
||||
config: toml_path,
|
||||
configure_args: build_configure_args.unwrap_or_default(),
|
||||
control_flow_guard: rust_control_flow_guard.unwrap_or(false),
|
||||
|
|
|
|||
|
|
@ -47,11 +47,17 @@ use crate::str::FromStr;
|
|||
#[macro_export]
|
||||
macro_rules! define_config {
|
||||
($(#[$attr:meta])* struct $name:ident {
|
||||
$($field:ident: Option<$field_ty:ty> = $field_key:literal,)*
|
||||
$(
|
||||
$(#[$field_attr:meta])*
|
||||
$field:ident: Option<$field_ty:ty> = $field_key:literal,
|
||||
)*
|
||||
}) => {
|
||||
$(#[$attr])*
|
||||
pub struct $name {
|
||||
$(pub $field: Option<$field_ty>,)*
|
||||
$(
|
||||
$(#[$field_attr])*
|
||||
pub $field: Option<$field_ty>,
|
||||
)*
|
||||
}
|
||||
|
||||
impl Merge for $name {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ define_config! {
|
|||
jobs: Option<u32> = "jobs",
|
||||
compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
|
||||
compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0",
|
||||
/// No longer has any effect; kept (for now) to avoid breaking people's configs.
|
||||
/// FIXME(#146929): Remove this in 2026.
|
||||
compiletest_use_stage0_libtest: Option<bool> = "compiletest-use-stage0-libtest",
|
||||
tidy_extra_checks: Option<String> = "tidy-extra-checks",
|
||||
ccache: Option<StringOrBool> = "ccache",
|
||||
|
|
|
|||
|
|
@ -327,8 +327,8 @@ pub enum Mode {
|
|||
ToolTarget,
|
||||
|
||||
/// Build a tool which uses the locally built std, placing output in the
|
||||
/// "stageN-tools" directory. Its usage is quite rare, mainly used by
|
||||
/// compiletest which needs libtest.
|
||||
/// "stageN-tools" directory. Its usage is quite rare; historically it was
|
||||
/// needed by compiletest, but now it is mainly used by `test-float-parse`.
|
||||
ToolStd,
|
||||
|
||||
/// Build a tool which uses the `rustc_private` mechanism, and thus
|
||||
|
|
|
|||
|
|
@ -557,8 +557,13 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
|||
summary: "New option `build.windows-rc` that will override which resource compiler on Windows will be used to compile Rust.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 99999,
|
||||
change_id: 147046,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "The `rust.use-lld` option has been renamed to `rust.bootstrap-override-lld`. Note that it only serves for overriding the linker used when building Rust code in bootstrap to be LLD.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 146929,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "`compiletest` is now always built with the stage 0 compiler, so `build.compiletest-use-stage0-libtest` has no effect.",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -661,18 +661,10 @@ pub struct Config {
|
|||
pub builtin_cfg_names: OnceLock<HashSet<String>>,
|
||||
pub supported_crate_types: OnceLock<HashSet<String>>,
|
||||
|
||||
/// FIXME: this is why we still need to depend on *staged* `std`, it's because we currently rely
|
||||
/// on `#![feature(internal_output_capture)]` for [`std::io::set_output_capture`] to implement
|
||||
/// `libtest`-esque `--no-capture`.
|
||||
///
|
||||
/// FIXME: rename this to the more canonical `no_capture`, or better, invert this to `capture`
|
||||
/// to avoid `!nocapture` double-negatives.
|
||||
pub nocapture: bool,
|
||||
|
||||
/// True if the experimental new output-capture implementation should be
|
||||
/// used, avoiding the need for `#![feature(internal_output_capture)]`.
|
||||
pub new_output_capture: bool,
|
||||
|
||||
/// Needed both to construct [`build_helper::git::GitConfig`].
|
||||
pub nightly_branch: String,
|
||||
pub git_merge_commit_email: String,
|
||||
|
|
@ -790,7 +782,6 @@ impl Config {
|
|||
builtin_cfg_names: Default::default(),
|
||||
supported_crate_types: Default::default(),
|
||||
nocapture: Default::default(),
|
||||
new_output_capture: Default::default(),
|
||||
nightly_branch: Default::default(),
|
||||
git_merge_commit_email: Default::default(),
|
||||
profiler_runtime: Default::default(),
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ use std::borrow::Cow;
|
|||
use std::collections::HashMap;
|
||||
use std::hash::{BuildHasherDefault, DefaultHasher};
|
||||
use std::num::NonZero;
|
||||
use std::sync::{Arc, Mutex, mpsc};
|
||||
use std::{env, hint, io, mem, panic, thread};
|
||||
use std::sync::{Arc, mpsc};
|
||||
use std::{env, hint, mem, panic, thread};
|
||||
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
|
|
@ -130,10 +130,6 @@ fn run_test_inner(
|
|||
panic_hook::set_capture_buf(Default::default());
|
||||
}
|
||||
|
||||
if let CaptureKind::Old { ref buf } = capture {
|
||||
io::set_output_capture(Some(Arc::clone(buf)));
|
||||
}
|
||||
|
||||
let stdout = capture.stdout();
|
||||
let stderr = capture.stderr();
|
||||
|
||||
|
|
@ -144,9 +140,6 @@ fn run_test_inner(
|
|||
// Forward any captured panic message to (captured) stderr.
|
||||
write!(stderr, "{panic_buf}");
|
||||
}
|
||||
if matches!(capture, CaptureKind::Old { .. }) {
|
||||
io::set_output_capture(None);
|
||||
}
|
||||
|
||||
let outcome = match (should_panic, panic_payload) {
|
||||
(ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestOutcome::Succeeded,
|
||||
|
|
@ -167,31 +160,24 @@ enum CaptureKind {
|
|||
/// runners, whose output is always captured.)
|
||||
None,
|
||||
|
||||
/// Use the old output-capture implementation, which relies on the unstable
|
||||
/// library feature `#![feature(internal_output_capture)]`.
|
||||
Old { buf: Arc<Mutex<Vec<u8>>> },
|
||||
|
||||
/// Use the new output-capture implementation, which only uses stable Rust.
|
||||
New { buf: output_capture::CaptureBuf },
|
||||
/// Capture all console output that would be printed by test runners via
|
||||
/// their `stdout` and `stderr` trait objects, or via the custom panic hook.
|
||||
Capture { buf: output_capture::CaptureBuf },
|
||||
}
|
||||
|
||||
impl CaptureKind {
|
||||
fn for_config(config: &Config) -> Self {
|
||||
if config.nocapture {
|
||||
Self::None
|
||||
} else if config.new_output_capture {
|
||||
Self::New { buf: output_capture::CaptureBuf::new() }
|
||||
} else {
|
||||
// Create a capure buffer for `io::set_output_capture`.
|
||||
Self::Old { buf: Default::default() }
|
||||
Self::Capture { buf: output_capture::CaptureBuf::new() }
|
||||
}
|
||||
}
|
||||
|
||||
fn should_set_panic_hook(&self) -> bool {
|
||||
match self {
|
||||
Self::None => false,
|
||||
Self::Old { .. } => true,
|
||||
Self::New { .. } => true,
|
||||
Self::Capture { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,16 +191,15 @@ impl CaptureKind {
|
|||
|
||||
fn capture_buf_or<'a>(&'a self, fallback: &'a dyn ConsoleOut) -> &'a dyn ConsoleOut {
|
||||
match self {
|
||||
Self::None | Self::Old { .. } => fallback,
|
||||
Self::New { buf } => buf,
|
||||
Self::None => fallback,
|
||||
Self::Capture { buf } => buf,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> Option<Vec<u8>> {
|
||||
match self {
|
||||
Self::None => None,
|
||||
Self::Old { buf } => Some(buf.lock().unwrap_or_else(|e| e.into_inner()).to_vec()),
|
||||
Self::New { buf } => Some(buf.into_inner().into()),
|
||||
Self::Capture { buf } => Some(buf.into_inner().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
#![crate_name = "compiletest"]
|
||||
// Needed by the "new" test executor that does not depend on libtest.
|
||||
// FIXME(Zalathar): We should be able to get rid of `internal_output_capture`,
|
||||
// by having `runtest` manually capture all of its println-like output instead.
|
||||
// That would result in compiletest being written entirely in stable Rust!
|
||||
#![feature(internal_output_capture)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
@ -178,12 +173,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
// FIXME: Temporarily retained so we can point users to `--no-capture`
|
||||
.optflag("", "nocapture", "")
|
||||
.optflag("", "no-capture", "don't capture stdout/stderr of tests")
|
||||
.optopt(
|
||||
"N",
|
||||
"new-output-capture",
|
||||
"enables or disables the new output-capture implementation",
|
||||
"off|on",
|
||||
)
|
||||
.optflag("", "profiler-runtime", "is the profiler runtime enabled for this target")
|
||||
.optflag("h", "help", "show this message")
|
||||
.reqopt("", "channel", "current Rust channel", "CHANNEL")
|
||||
|
|
@ -480,14 +469,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
supported_crate_types: OnceLock::new(),
|
||||
|
||||
nocapture: matches.opt_present("no-capture"),
|
||||
new_output_capture: {
|
||||
let value = matches
|
||||
.opt_str("new-output-capture")
|
||||
.or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok())
|
||||
.unwrap_or_else(|| "on".to_owned());
|
||||
parse_bool_option(&value)
|
||||
.unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given"))
|
||||
},
|
||||
|
||||
nightly_branch: matches.opt_str("nightly-branch").unwrap(),
|
||||
git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
|
||||
|
|
@ -503,19 +484,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses the same set of boolean values accepted by rustc command-line arguments.
|
||||
///
|
||||
/// Accepting all of these values is more complicated than just picking one
|
||||
/// pair, but has the advantage that contributors who are used to rustc
|
||||
/// shouldn't have to think about which values are legal.
|
||||
fn parse_bool_option(value: &str) -> Option<bool> {
|
||||
match value {
|
||||
"off" | "no" | "n" | "false" => Some(false),
|
||||
"on" | "yes" | "y" | "true" => Some(true),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opt_str(maybestr: &Option<String>) -> &str {
|
||||
match *maybestr {
|
||||
None => "(none)",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ known-bug: rust-lang/rust#125772
|
||||
//@ only-x86_64
|
||||
//@ only-64bit
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
struct Outer<const A: i64, const B: i64>();
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
//@ known-bug: rust-lang/rust#129095
|
||||
//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir
|
||||
|
||||
#![feature(adt_const_params, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {
|
||||
BYTES
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(function_with_bytes::<b"AAAAA">(), &[0x41, 0x41, 0x41, 0x41]);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//@ known-bug: #131292
|
||||
//@ only-x86_64
|
||||
//@ needs-asm-support
|
||||
use std::arch::asm;
|
||||
|
||||
unsafe fn f6() {
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
//@ known-bug: #134175
|
||||
//@compile-flags: -Zvalidate-mir -Zinline-mir=yes
|
||||
use std::vec::IntoIter;
|
||||
|
||||
pub(crate) trait Foo: Iterator<Item = <Self as Foo>::Key> {
|
||||
type Key;
|
||||
}
|
||||
|
||||
impl Foo for IntoIter<i16> {}
|
||||
|
||||
fn sum_foo<F: Foo<Key = i32>>(f: F) -> i32 {
|
||||
f.fold(0, |a, b| a + b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = sum_foo(vec![11, 10, 1].into_iter());
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
//@ known-bug: #134654
|
||||
//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir
|
||||
//@ only-x86_64
|
||||
|
||||
#![feature(adt_const_params, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn function_with_bytes<const BYTES:
|
||||
&'static [u8; 0xa9008fb6c9d81e42_0e25730562a601c8_u128]>() -> &'static [u8] {
|
||||
BYTES
|
||||
}
|
||||
|
||||
fn main() {
|
||||
function_with_bytes::<b"aa">() == &[];
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
//@ known-bug: #135570
|
||||
//@compile-flags: -Zvalidate-mir -Zmir-enable-passes=+Inline -Copt-level=0 -Zmir-enable-passes=+GVN
|
||||
//@ only-x86_64
|
||||
|
||||
#![feature(adt_const_params, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn function_with_bytes<const BYTES: &'static [u8; 0xc7b889180b67b07d_bc1a3c88783d35b5_u128]>(
|
||||
) -> &'static [u8] {
|
||||
BYTES
|
||||
}
|
||||
|
||||
fn main() {
|
||||
function_with_bytes::<b"aa">() == &[];
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
//@ known-bug: #136381
|
||||
//@ compile-flags: -Zvalidate-mir -Zmir-enable-passes=+GVN
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
trait A {}
|
||||
trait B: A {
|
||||
fn c(&self);
|
||||
}
|
||||
impl B for i32 {
|
||||
fn c(self) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let baz: &dyn B = &1;
|
||||
let bar: &dyn A = baz;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
//@ known-bug: #137190
|
||||
//@ compile-flags: -Zmir-opt-level=2 -Zvalidate-mir
|
||||
trait A {
|
||||
fn b(&self);
|
||||
}
|
||||
trait C: A {}
|
||||
impl C for () {}
|
||||
fn main() {
|
||||
(&() as &dyn C as &dyn A).b();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
//@ known-bug: #137468
|
||||
//@ compile-flags: -Copt-level=0 -Zmir-enable-passes=+GVN -Zvalidate-mir
|
||||
trait Supertrait<T> {}
|
||||
|
||||
trait Identity {
|
||||
type Selff;
|
||||
}
|
||||
|
||||
trait Trait<P>: Supertrait<()> + Supertrait<<P as Identity>::Selff> {}
|
||||
|
||||
impl<P> Trait<P> for () {}
|
||||
|
||||
fn main() {
|
||||
let x: &dyn Trait<()> = &();
|
||||
let x: &dyn Supertrait<()> = x;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//@ compile-flags: -g -Copt-level=0 -Z verify-llvm-ir
|
||||
//@ known-bug: #34127
|
||||
//@ only-x86_64
|
||||
//@ only-64bit
|
||||
|
||||
pub fn main() {
|
||||
let _a = [(); 1 << 63];
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ impl CodegenBackend for TheBackend {
|
|||
""
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"the-backend"
|
||||
}
|
||||
|
||||
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
|
||||
Box::new(CodegenResults {
|
||||
modules: vec![],
|
||||
|
|
|
|||
30
tests/ui/keyword/soup.rs
Normal file
30
tests/ui/keyword/soup.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//@ edition:2024
|
||||
//@ check-pass
|
||||
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_abi)]
|
||||
#![allow(unused_macros)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(unreachable_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
// all 48 keywords in 300 characters
|
||||
mod x {
|
||||
pub(super) struct X;
|
||||
use Ok;
|
||||
impl X {
|
||||
pub(in crate) async fn x(self: Self, x: &'static &'_ dyn for<> Fn()) where {
|
||||
unsafe extern { safe fn x(); }
|
||||
macro_rules! x { () => {}; }
|
||||
if 'x: loop {
|
||||
return match while let true = break 'x false { continue } {
|
||||
ref x => { &raw mut x; async { const { enum A {} } }.await as () },
|
||||
};
|
||||
} { type x = X; } else { move || { trait x { } union B { x: () } }; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
//@ run-rustfix
|
||||
pub use my_mod::Foo;
|
||||
//~^ NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
//~| NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
|
||||
mod my_mod {
|
||||
pub struct Foo(u32);
|
||||
|
||||
mod my_sub_mod {
|
||||
fn my_func() {
|
||||
let crate::my_mod::Foo(x) = crate::my_mod::Foo(42);
|
||||
//~^ ERROR cannot initialize a tuple struct which contains private fields
|
||||
//~| HELP the type can be constructed directly, because its fields are available from the current scope
|
||||
//~| ERROR cannot match against a tuple struct which contains private fields
|
||||
//~| HELP the type can be constructed directly, because its fields are available from the current scope
|
||||
}
|
||||
}
|
||||
}
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
//@ run-rustfix
|
||||
pub use my_mod::Foo;
|
||||
//~^ NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
//~| NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
|
||||
mod my_mod {
|
||||
pub struct Foo(u32);
|
||||
|
||||
mod my_sub_mod {
|
||||
fn my_func() {
|
||||
let crate::Foo(x) = crate::Foo(42);
|
||||
//~^ ERROR cannot initialize a tuple struct which contains private fields
|
||||
//~| HELP the type can be constructed directly, because its fields are available from the current scope
|
||||
//~| ERROR cannot match against a tuple struct which contains private fields
|
||||
//~| HELP the type can be constructed directly, because its fields are available from the current scope
|
||||
}
|
||||
}
|
||||
}
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
error[E0423]: cannot initialize a tuple struct which contains private fields
|
||||
--> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:12:33
|
||||
|
|
||||
LL | let crate::Foo(x) = crate::Foo(42);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
--> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:3:9
|
||||
|
|
||||
LL | pub use my_mod::Foo;
|
||||
| ^^^^^^^^^^^
|
||||
help: the type can be constructed directly, because its fields are available from the current scope
|
||||
|
|
||||
LL | let crate::Foo(x) = crate::my_mod::Foo(42);
|
||||
| ++++++++
|
||||
|
||||
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||
--> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:12:17
|
||||
|
|
||||
LL | let crate::Foo(x) = crate::Foo(42);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields
|
||||
--> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:3:9
|
||||
|
|
||||
LL | pub use my_mod::Foo;
|
||||
| ^^^^^^^^^^^
|
||||
help: the type can be constructed directly, because its fields are available from the current scope
|
||||
|
|
||||
LL | let crate::my_mod::Foo(x) = crate::Foo(42);
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0423, E0532.
|
||||
For more information about an error, try `rustc --explain E0423`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue