Skip to content

Rollup of 8 pull requests #135861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -2349,6 +2349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.report_missing_fields(
adt_ty,
path_span,
expr.span,
remaining_fields,
variant,
hir_fields,
@@ -2386,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
adt_ty: Ty<'tcx>,
span: Span,
full_span: Span,
remaining_fields: UnordMap<Ident, (FieldIdx, &ty::FieldDef)>,
variant: &'tcx ty::VariantDef,
hir_fields: &'tcx [hir::ExprField<'tcx>],
@@ -2425,6 +2427,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));

if remaining_fields.items().all(|(_, (_, field))| field.value.is_some())
&& self.tcx.sess.is_nightly_build()
{
let msg = format!(
"all remaining fields have default values, {you_can} use those values with `..`",
you_can = if self.tcx.features().default_field_values() {
"you can"
} else {
"if you added `#![feature(default_field_values)]` to your crate you could"
},
);
if let Some(hir_field) = hir_fields.last() {
err.span_suggestion_verbose(
hir_field.span.shrink_to_hi(),
msg,
", ..".to_string(),
Applicability::MachineApplicable,
);
} else if hir_fields.is_empty() {
err.span_suggestion_verbose(
span.shrink_to_hi().with_hi(full_span.hi()),
msg,
" { .. }".to_string(),
Applicability::MachineApplicable,
);
}
}

if let Some(hir_field) = hir_fields.last() {
self.suggest_fru_from_range_and_emit(hir_field, variant, args, err);
} else {
3 changes: 3 additions & 0 deletions library/core/src/prelude/common.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@ pub use crate::marker::{Copy, Send, Sized, Sync, Unpin};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
#[stable(feature = "async_closure", since = "1.85.0")]
#[doc(no_inline)]
pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};

// Re-exported functions
#[stable(feature = "core_prelude", since = "1.4.0")]
9 changes: 4 additions & 5 deletions library/std/src/keyword_docs.rs
Original file line number Diff line number Diff line change
@@ -2387,13 +2387,12 @@ mod async_keyword {}
/// [`async`]: ../std/keyword.async.html
mod await_keyword {}

// FIXME(dyn_compat_renaming): Update URL and link text.
#[doc(keyword = "dyn")]
//
/// `dyn` is a prefix of a [trait object]'s type.
///
/// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait`
/// are [dynamically dispatched]. To use the trait this way, it must be 'dyn-compatible'[^1].
/// are [dynamically dispatched]. To use the trait this way, it must be *dyn compatible*[^1].
///
/// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that
/// is being passed. That is, the type has been [erased].
@@ -2406,7 +2405,7 @@ mod await_keyword {}
/// the function pointer and then that function pointer is called.
///
/// See the Reference for more information on [trait objects][ref-trait-obj]
/// and [object safety][ref-obj-safety].
/// and [dyn compatibility][ref-dyn-compat].
///
/// ## Trade-offs
///
@@ -2419,9 +2418,9 @@ mod await_keyword {}
/// [trait object]: ../book/ch17-02-trait-objects.html
/// [dynamically dispatched]: https://en.wikipedia.org/wiki/Dynamic_dispatch
/// [ref-trait-obj]: ../reference/types/trait-object.html
/// [ref-obj-safety]: ../reference/items/traits.html#object-safety
/// [ref-dyn-compat]: ../reference/items/traits.html#dyn-compatibility
/// [erased]: https://en.wikipedia.org/wiki/Type_erasure
/// [^1]: Formerly known as 'object safe'.
/// [^1]: Formerly known as *object safe*.
mod dyn_keyword {}

#[doc(keyword = "union")]
3 changes: 0 additions & 3 deletions library/std/src/sys/pal/windows/fs.rs
Original file line number Diff line number Diff line change
@@ -328,9 +328,6 @@ impl File {
mem::size_of::<c::FILE_ALLOCATION_INFO>() as u32,
);
if result == 0 {
if api::get_last_error().code != 0 {
panic!("FILE_ALLOCATION_INFO failed!!!");
}
let eof = c::FILE_END_OF_FILE_INFO { EndOfFile: 0 };
let result = c::SetFileInformationByHandle(
handle.as_raw_handle(),
9 changes: 7 additions & 2 deletions src/ci/docker/run.sh
Original file line number Diff line number Diff line change
@@ -123,6 +123,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
build_args+=("--build-arg" "SCRIPT_ARG=${DOCKER_SCRIPT}")
fi

GHCR_BUILDKIT_IMAGE="ghcr.io/rust-lang/buildkit:buildx-stable-1"
# On non-CI jobs, we try to download a pre-built image from the rust-lang-ci
# ghcr.io registry. If it is not possible, we fall back to building the image
# locally.
@@ -140,7 +141,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
elif [[ "$PR_CI_JOB" == "1" ]];
then
# Enable a new Docker driver so that --cache-from works with a registry backend
docker buildx create --use --driver docker-container
# Use a custom image to avoid DockerHub rate limits
docker buildx create --use --driver docker-container \
--driver-opt image=${GHCR_BUILDKIT_IMAGE}

# Build the image using registry caching backend
retry docker \
@@ -156,7 +159,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
--password-stdin

# Enable a new Docker driver so that --cache-from/to works with a registry backend
docker buildx create --use --driver docker-container
# Use a custom image to avoid DockerHub rate limits
docker buildx create --use --driver docker-container \
--driver-opt image=${GHCR_BUILDKIT_IMAGE}

# Build the image using registry caching backend
retry docker \
2 changes: 2 additions & 0 deletions src/ci/github-actions/jobs.yml
Original file line number Diff line number Diff line change
@@ -48,6 +48,8 @@ runners:
<<: *base-job

- &job-aarch64-linux
# Free some disk space to avoid running out of space during the build.
free_disk: true
os: ubuntu-22.04-arm

envs:
10 changes: 9 additions & 1 deletion src/tools/run-make-support/src/external_deps/rustc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::str::FromStr as _;

use crate::command::Command;
use crate::env::env_var;
@@ -390,3 +391,10 @@ impl Rustc {
self
}
}

/// Query the sysroot path corresponding `rustc --print=sysroot`.
#[track_caller]
pub fn sysroot() -> PathBuf {
let path = rustc().print("sysroot").run().stdout_utf8();
PathBuf::from_str(path.trim()).unwrap()
}
1 change: 0 additions & 1 deletion src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
run-make/jobserver-error/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile
78 changes: 0 additions & 78 deletions tests/run-make/translation/Makefile

This file was deleted.

179 changes: 179 additions & 0 deletions tests/run-make/translation/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//! Smoke test for the rustc diagnostics translation infrastructure.
//!
//! # References
//!
//! - Current tracking issue: <https://github.com/rust-lang/rust/issues/132181>.
//! - Old tracking issue: <https://github.com/rust-lang/rust/issues/100717>
//! - Initial translation infra implementation: <https://github.com/rust-lang/rust/pull/95512>.
// This test uses symbolic links to stub out a fake sysroot to save testing time.
//@ needs-symlink

#![deny(warnings)]

use std::path::{Path, PathBuf};

use run_make_support::rustc::sysroot;
use run_make_support::{cwd, rfs, run_in_tmpdir, rustc};

fn main() {
builtin_fallback_bundle();
additional_primary_bundle();
missing_slug_prefers_fallback_bundle();
broken_primary_bundle_prefers_fallback_bundle();
locale_sysroot();
missing_sysroot();
file_sysroot();
}

/// Check that the test works normally, using the built-in fallback bundle.
fn builtin_fallback_bundle() {
rustc().input("test.rs").run_fail().assert_stderr_contains("struct literal body without path");
}

/// Check that a primary bundle can be loaded and will be preferentially used where possible.
fn additional_primary_bundle() {
rustc()
.input("test.rs")
.arg("-Ztranslate-additional-ftl=working.ftl")
.run_fail()
.assert_stderr_contains("this is a test message");
}

/// Check that a primary bundle without the desired message will use the fallback bundle.
fn missing_slug_prefers_fallback_bundle() {
rustc()
.input("test.rs")
.arg("-Ztranslate-additional-ftl=missing.ftl")
.run_fail()
.assert_stderr_contains("struct literal body without path");
}

/// Check that a primary bundle with a broken message (e.g. an interpolated variable is not
/// provided) will use the fallback bundle.
fn broken_primary_bundle_prefers_fallback_bundle() {
// FIXME(#135817): as of the rmake.rs port, the compiler actually ICEs on the additional
// `broken.ftl`, even though the original intention seems to be that it should gracefully
// failover to the fallback bundle.

rustc()
.env("RUSTC_ICE", "0") // disable ICE dump file, not needed
.input("test.rs")
.arg("-Ztranslate-additional-ftl=broken.ftl")
.run_fail()
.assert_exit_code(101);
}

#[track_caller]
fn shallow_symlink_dir_entries(src_dir: &Path, dst_dir: &Path) {
for entry in rfs::read_dir(src_dir) {
let entry = entry.unwrap();
let src_entry_path = entry.path();
let src_filename = src_entry_path.file_name().unwrap();
let meta = rfs::symlink_metadata(&src_entry_path);

if meta.is_symlink() || meta.is_file() {
rfs::symlink_file(&src_entry_path, dst_dir.join(src_filename));
} else if meta.is_dir() {
rfs::symlink_dir(&src_entry_path, dst_dir.join(src_filename));
} else {
unreachable!()
}
}
}

#[track_caller]
fn shallow_symlink_dir_entries_materialize_single_dir(
src_dir: &Path,
dst_dir: &Path,
dir_filename: &str,
) {
shallow_symlink_dir_entries(src_dir, dst_dir);

// On Windows, this would be a symlink-to-dir, so we have to remove with `remove_dir` instead.
#[cfg(windows)]
rfs::remove_dir(dst_dir.join(dir_filename));
#[cfg(not(windows))]
rfs::remove_file(dst_dir.join(dir_filename));

rfs::create_dir_all(dst_dir.join(dir_filename));
}

#[track_caller]
fn setup_fakeroot_parents() -> PathBuf {
let sysroot = sysroot();
let fakeroot = cwd().join("fakeroot");
rfs::create_dir_all(&fakeroot);
shallow_symlink_dir_entries_materialize_single_dir(&sysroot, &fakeroot, "lib");
shallow_symlink_dir_entries_materialize_single_dir(
&sysroot.join("lib"),
&fakeroot.join("lib"),
"rustlib",
);
shallow_symlink_dir_entries_materialize_single_dir(
&sysroot.join("lib").join("rustlib"),
&fakeroot.join("lib").join("rustlib"),
"src",
);
shallow_symlink_dir_entries(
&sysroot.join("lib").join("rustlib").join("src"),
&fakeroot.join("lib").join("rustlib").join("src"),
);
fakeroot
}

/// Check that a locale can be loaded from the sysroot given a language identifier by making a local
/// copy of the sysroot and adding the custom locale to it.
fn locale_sysroot() {
run_in_tmpdir(|| {
let fakeroot = setup_fakeroot_parents();

// When download-rustc is enabled, real sysroot will have a share directory. Delete the link
// to it.
let _ = std::fs::remove_file(fakeroot.join("share"));

let fake_locale_path = fakeroot.join("share").join("locale").join("zh-CN");
rfs::create_dir_all(&fake_locale_path);
rfs::symlink_file(
cwd().join("working.ftl"),
fake_locale_path.join("basic-translation.ftl"),
);

rustc()
.env("RUSTC_ICE", "0")
.input("test.rs")
.sysroot(&fakeroot)
.arg("-Ztranslate-lang=zh-CN")
.run_fail()
.assert_stderr_contains("this is a test message");
});
}

/// Check that the compiler errors out when the sysroot requested cannot be found. This test might
/// start failing if there actually exists a Klingon translation of rustc's error messages.
fn missing_sysroot() {
run_in_tmpdir(|| {
rustc()
.input("test.rs")
.arg("-Ztranslate-lang=tlh")
.run_fail()
.assert_stderr_contains("missing locale directory");
});
}

/// Check that the compiler errors out when the directory for the locale in the sysroot is actually
/// a file.
fn file_sysroot() {
run_in_tmpdir(|| {
let fakeroot = setup_fakeroot_parents();
rfs::create_dir_all(fakeroot.join("share").join("locale"));
rfs::write(fakeroot.join("share").join("locale").join("zh-CN"), b"not a dir");

rustc()
.input("test.rs")
.sysroot(&fakeroot)
.arg("-Ztranslate-lang=zh-CN")
.run_fail()
.assert_stderr_contains("is not a directory");
});
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ compile-flags: --test
// -Zpanic_abort_tests makes this test work on panic=abort targets and
// it's a no-op on panic=unwind targets
//@ compile-flags: --test -Zpanic_abort_tests
//@ run-pass

#![feature(core_intrinsics, generic_assert)]
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ compile-flags: --test
// -Zpanic_abort_tests makes this test work on panic=abort targets and
// it's a no-op on panic=unwind targets
//@ compile-flags: --test -Zpanic_abort_tests
// ignore-tidy-linelength
//@ run-pass

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
error[E0658]: default values on fields are experimental
--> $DIR/non-exhaustive-ctor.rs:9:22
|
LL | pub field: () = (),
| ^^^^^
|
= note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information
= help: add `#![feature(default_field_values)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: default values on fields are experimental
--> $DIR/non-exhaustive-ctor.rs:11:25
|
LL | pub field1: Priv = Priv,
| ^^^^^^^
|
= note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information
= help: add `#![feature(default_field_values)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: default values on fields are experimental
--> $DIR/non-exhaustive-ctor.rs:13:25
|
LL | pub field2: Priv = Priv,
| ^^^^^^^
|
= note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information
= help: add `#![feature(default_field_values)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0797]: base expression required after `..`
--> $DIR/non-exhaustive-ctor.rs:20:19
|
LL | let _ = S { .. }; // ok
| ^
|
help: add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields
|
LL + #![feature(default_field_values)]
|
help: add a base expression here
|
LL | let _ = S { ../* expr */ }; // ok
| ++++++++++

error[E0797]: base expression required after `..`
--> $DIR/non-exhaustive-ctor.rs:22:30
|
LL | let _ = S { field: (), .. }; // ok
| ^
|
help: add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields
|
LL + #![feature(default_field_values)]
|
help: add a base expression here
|
LL | let _ = S { field: (), ../* expr */ }; // ok
| ++++++++++

error[E0063]: missing fields `field`, `field1` and `field2` in initializer of `S`
--> $DIR/non-exhaustive-ctor.rs:24:13
|
LL | let _ = S { };
| ^ missing `field`, `field1` and `field2`
|
help: all remaining fields have default values, if you added `#![feature(default_field_values)]` to your crate you could use those values with `..`
|
LL | let _ = S { .. };
| ~~~~~~

error[E0063]: missing fields `field1` and `field2` in initializer of `S`
--> $DIR/non-exhaustive-ctor.rs:26:13
|
LL | let _ = S { field: () };
| ^ missing `field1` and `field2`
|
help: all remaining fields have default values, if you added `#![feature(default_field_values)]` to your crate you could use those values with `..`
|
LL | let _ = S { field: (), .. };
| ++++

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0063, E0658, E0797.
For more information about an error, try `rustc --explain E0063`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//@ revisions: enabled disabled
//@[enabled] run-rustfix
#![allow(private_interfaces, dead_code)]
#![cfg_attr(enabled, feature(default_field_values))]
use m::S;

mod m {
pub struct S {
pub field: () = (),
//[disabled]~^ ERROR default values on fields are experimental
pub field1: Priv = Priv,
//[disabled]~^ ERROR default values on fields are experimental
pub field2: Priv = Priv,
//[disabled]~^ ERROR default values on fields are experimental
}
struct Priv;
}

fn main() {
let _ = S { .. }; // ok
//[disabled]~^ ERROR base expression required after `..`
let _ = S { field: (), .. }; // ok
//[disabled]~^ ERROR base expression required after `..`
let _ = S { .. };
//~^ ERROR missing fields `field`, `field1` and `field2`
let _ = S { field: (), .. };
//~^ ERROR missing fields `field1` and `field2`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0063]: missing fields `field`, `field1` and `field2` in initializer of `S`
--> $DIR/non-exhaustive-ctor.rs:24:13
|
LL | let _ = S { };
| ^ missing `field`, `field1` and `field2`
|
help: all remaining fields have default values, you can use those values with `..`
|
LL | let _ = S { .. };
| ~~~~~~

error[E0063]: missing fields `field1` and `field2` in initializer of `S`
--> $DIR/non-exhaustive-ctor.rs:26:13
|
LL | let _ = S { field: () };
| ^ missing `field1` and `field2`
|
help: all remaining fields have default values, you can use those values with `..`
|
LL | let _ = S { field: (), .. };
| ++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0063`.
28 changes: 28 additions & 0 deletions tests/ui/structs/default-field-values/non-exhaustive-ctor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//@ revisions: enabled disabled
//@[enabled] run-rustfix
#![allow(private_interfaces, dead_code)]
#![cfg_attr(enabled, feature(default_field_values))]
use m::S;

mod m {
pub struct S {
pub field: () = (),
//[disabled]~^ ERROR default values on fields are experimental
pub field1: Priv = Priv,
//[disabled]~^ ERROR default values on fields are experimental
pub field2: Priv = Priv,
//[disabled]~^ ERROR default values on fields are experimental
}
struct Priv;
}

fn main() {
let _ = S { .. }; // ok
//[disabled]~^ ERROR base expression required after `..`
let _ = S { field: (), .. }; // ok
//[disabled]~^ ERROR base expression required after `..`
let _ = S { };
//~^ ERROR missing fields `field`, `field1` and `field2`
let _ = S { field: () };
//~^ ERROR missing fields `field1` and `field2`
}