From 822c3203c65a16bbe14c1b92894ad7fd72ebb432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 28 May 2024 08:36:00 +0000 Subject: [PATCH 01/19] remove legacy rustsrc folder --- src/ci/docker/run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 22dcb808c743e..a4c59b3067ead 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -270,7 +270,6 @@ else args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION" args="$args --volume $objdir:/checkout/obj" args="$args --volume $HOME/.cargo:/cargo" - args="$args --volume $HOME/rustsrc:$HOME/rustsrc" args="$args --volume /tmp/toolstate:/tmp/toolstate" id=$(id -u) From f0273664ce275afe78a25b75f001b77d09186113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 28 May 2024 08:52:33 +0000 Subject: [PATCH 02/19] document DIST_TRY_BUILD --- src/ci/github-actions/jobs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 05470eebf014b..174aaeec6b50f 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -61,6 +61,12 @@ envs: try: <<: *production + # The following env var activates faster `try` builds in `opt-dist` by, e.g. + # - building only the more commonly useful components (we rarely need e.g. rust-docs in try + # builds) + # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain + # + # If you *want* these to happen however, temporarily uncomment it before triggering a try build. DIST_TRY_BUILD: 1 auto: From 7cd732f990ec341efdac53f6519a44b72e07861f Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 29 May 2024 14:19:09 +0200 Subject: [PATCH 03/19] Avoid `mut` and simplify initialization of `TASK_QUEUE` --- library/std/src/sys/pal/sgx/thread.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 7d271e6d2b65d..d70c6e31fb73b 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -15,7 +15,7 @@ pub use self::task_queue::JoinNotifier; mod task_queue { use super::wait_notify; - use crate::sync::{Mutex, MutexGuard, Once}; + use crate::sync::{Mutex, MutexGuard}; pub type JoinHandle = wait_notify::Waiter; @@ -32,6 +32,8 @@ mod task_queue { done: JoinNotifier, } + unsafe impl Send for Task {} + impl Task { pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); @@ -45,18 +47,12 @@ mod task_queue { } } - #[cfg_attr(test, linkage = "available_externally")] - #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"] - static TASK_QUEUE_INIT: Once = Once::new(); #[cfg_attr(test, linkage = "available_externally")] #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"] - static mut TASK_QUEUE: Option>> = None; + static TASK_QUEUE: Mutex> = Mutex::new(Vec::new()); pub(super) fn lock() -> MutexGuard<'static, Vec> { - unsafe { - TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default())); - TASK_QUEUE.as_ref().unwrap().lock().unwrap() - } + TASK_QUEUE.lock().unwrap() } } From c3de4b3aad6a2be86d4711086267e21660bf2b23 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 2 Jun 2024 12:40:07 +0000 Subject: [PATCH 04/19] Handle all GVN binops in a single place. --- compiler/rustc_mir_transform/src/gvn.rs | 70 ++++++++++++++----------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fadb5edefdfb1..548e4e309360e 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -223,7 +223,6 @@ enum Value<'tcx> { NullaryOp(NullOp<'tcx>, Ty<'tcx>), UnaryOp(UnOp, VnIndex), BinaryOp(BinOp, VnIndex, VnIndex), - CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead Cast { kind: CastKind, value: VnIndex, @@ -508,17 +507,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?; val.into() } - CheckedBinaryOp(bin_op, lhs, rhs) => { - let lhs = self.evaluated[lhs].as_ref()?; - let lhs = self.ecx.read_immediate(lhs).ok()?; - let rhs = self.evaluated[rhs].as_ref()?; - let rhs = self.ecx.read_immediate(rhs).ok()?; - let val = self - .ecx - .binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs) - .ok()?; - val.into() - } Cast { kind, value, from: _, to } => match kind { CastKind::IntToInt | CastKind::IntToFloat => { let value = self.evaluated[value].as_ref()?; @@ -829,17 +817,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let lhs = lhs?; let rhs = rhs?; - if let Some(op) = op.overflowing_to_wrapping() { - if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) { - return Some(value); - } - Value::CheckedBinaryOp(op, lhs, rhs) - } else { - if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) { - return Some(value); - } - Value::BinaryOp(op, lhs, rhs) + if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) { + return Some(value); } + Value::BinaryOp(op, lhs, rhs) } Rvalue::UnaryOp(op, ref mut arg) => { let arg = self.simplify_operand(arg, location)?; @@ -970,7 +951,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn simplify_binary( &mut self, op: BinOp, - checked: bool, lhs_ty: Ty<'tcx>, lhs: VnIndex, rhs: VnIndex, @@ -999,22 +979,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { use Either::{Left, Right}; let a = as_bits(lhs).map_or(Right(lhs), Left); let b = as_bits(rhs).map_or(Right(rhs), Left); + let result = match (op, a, b) { // Neutral elements. - (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p)) + ( + BinOp::Add + | BinOp::AddWithOverflow + | BinOp::AddUnchecked + | BinOp::BitOr + | BinOp::BitXor, + Left(0), + Right(p), + ) | ( BinOp::Add + | BinOp::AddWithOverflow + | BinOp::AddUnchecked | BinOp::BitOr | BinOp::BitXor | BinOp::Sub + | BinOp::SubWithOverflow + | BinOp::SubUnchecked | BinOp::Offset | BinOp::Shl | BinOp::Shr, Right(p), Left(0), ) - | (BinOp::Mul, Left(1), Right(p)) - | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p, + | (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p)) + | ( + BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::Div, + Right(p), + Left(1), + ) => p, // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size. (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p)) if ones == layout.size.truncate(u128::MAX) @@ -1023,10 +1020,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { p } // Absorbing elements. - (BinOp::Mul | BinOp::BitAnd, _, Left(0)) + ( + BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd, + _, + Left(0), + ) | (BinOp::Rem, _, Left(1)) | ( - BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr, + BinOp::Mul + | BinOp::MulWithOverflow + | BinOp::MulUnchecked + | BinOp::Div + | BinOp::Rem + | BinOp::BitAnd + | BinOp::Shl + | BinOp::Shr, Left(0), _, ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), @@ -1038,7 +1046,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty) } // Sub/Xor with itself. - (BinOp::Sub | BinOp::BitXor, a, b) if a == b => { + (BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b) + if a == b => + { self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty) } // Comparison: @@ -1052,7 +1062,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { _ => return None, }; - if checked { + if op.is_overflowing() { let false_val = self.insert_bool(false); Some(self.insert_tuple(vec![result, false_val])) } else { From f4b060e452fa00a04f20ad7a0ec140fda48f3b50 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 11:18:46 -0600 Subject: [PATCH 05/19] Add more ABI test cases. --- .../miri/tests/pass/function_calls/abi_compat.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 136660a305aff..0cfcd532ff4b2 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -83,12 +83,24 @@ fn main() { test_abi_compat(main as fn(), id:: as fn(i32) -> i32); // - 1-ZST test_abi_compat((), [0u8; 0]); - // - Guaranteed null-pointer-optimizations (RFC 3391). + // - Guaranteed Option null-pointer-optimizations (RFC 3391). test_abi_compat(&0u32 as *const u32, Some(&0u32)); test_abi_compat(main as fn(), Some(main as fn())); test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap())); test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32))); - test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap()))); + test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap()))); + // - Guaranteed Result does the same as Option (RFC 3391) + test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32)); + test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn())); + test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap())); + test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32))); + test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap()))); + // - Guaranteed Result also does the same as Option (RFC 3391) + test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32)); + test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn())); + test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap())); + test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32))); + test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap()))); // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible // with the wrapped field. From f67a0eb2b72294f108051381cbc833c295aadad9 Mon Sep 17 00:00:00 2001 From: bohan Date: Tue, 4 Jun 2024 12:40:41 +0800 Subject: [PATCH 06/19] resolve: mark it undetermined if single import is not has any bindings --- compiler/rustc_resolve/src/ident.rs | 29 +++++++++++++++++-- compiler/rustc_resolve/src/imports.rs | 4 +-- tests/crashes/124490.rs | 16 ---------- tests/crashes/125013-1.rs | 5 ---- tests/crashes/125013-2.rs | 16 ---------- .../imports/cycle-import-in-diff-module-0.rs | 14 +++++++++ .../imports/cycle-import-in-diff-module-1.rs | 14 +++++++++ .../shadow-glob-module-resolution-1.rs | 17 +++++++++++ .../shadow-glob-module-resolution-1.stderr | 23 +++++++++++++++ .../shadow-glob-module-resolution-2.rs | 19 ++++++++++++ .../shadow-glob-module-resolution-2.stderr | 26 +++++++++++++++++ 11 files changed, 142 insertions(+), 41 deletions(-) delete mode 100644 tests/crashes/124490.rs delete mode 100644 tests/crashes/125013-1.rs delete mode 100644 tests/crashes/125013-2.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-0.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.stderr create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.stderr diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 57db765c07e55..78bd3c4e49f2e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -965,6 +965,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // if it can then our result is not determined and can be invalidated. for single_import in &resolution.single_imports { let Some(import_vis) = single_import.vis.get() else { + // This branch handles a cycle in single imports, which occurs + // when we've previously captured the `vis` value during an import + // process. + // + // For example: + // ``` + // use a::b; + // use b as a; + // ``` + // 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the + // current module. + // 2. Encounter the import `use b as a`, which is a `single_import` for `a`, + // and try to find `b` in the current module. + // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`. + // This leads to entering this branch. continue; }; if !self.is_accessible_from(import_vis, parent_scope.module) { @@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named imports. continue; } + let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; - let ImportKind::Single { source: ident, .. } = single_import.kind else { + let ImportKind::Single { source: ident, source_bindings, .. } = &single_import.kind + else { unreachable!(); }; + if binding.map_or(false, |binding| binding.module().is_some()) + && source_bindings.iter().all(|binding| matches!(binding.get(), Err(Undetermined))) + { + // This branch allows the binding to be defined or updated later, + // avoiding module inconsistency between the resolve process and the finalize process. + // See more details in #124840 + return Err((Undetermined, Weak::No)); + } match self.resolve_ident_in_module( module, - ident, + *ident, ns, &single_import.parent_scope, None, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6bbde26db3443..27ea7760f5893 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -352,9 +352,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, nonglob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if glob_binding.res() != nonglob_binding.res() - && key.ns == MacroNS + if key.ns == MacroNS && nonglob_binding.expansion != LocalExpnId::ROOT + && glob_binding.res() != nonglob_binding.res() { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, diff --git a/tests/crashes/124490.rs b/tests/crashes/124490.rs deleted file mode 100644 index 9f605c32cf261..0000000000000 --- a/tests/crashes/124490.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#124490 -use io::{self as std}; -use std::collections::{self as io}; - -mod a { - pub mod b { - pub mod c {} - } -} - -use a::*; - -use b::c; -use c as b; - -fn main() {} diff --git a/tests/crashes/125013-1.rs b/tests/crashes/125013-1.rs deleted file mode 100644 index ae66d7a146698..0000000000000 --- a/tests/crashes/125013-1.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -use io::{self as std}; -use std::ops::Deref::{self as io}; -pub fn main() {} diff --git a/tests/crashes/125013-2.rs b/tests/crashes/125013-2.rs deleted file mode 100644 index a14c8a76b63ee..0000000000000 --- a/tests/crashes/125013-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -mod a { - pub mod b { - pub mod c { - pub trait D {} - } - } -} - -use a::*; - -use e as b; -use b::c::D as e; - -fn main() { } diff --git a/tests/ui/imports/cycle-import-in-diff-module-0.rs b/tests/ui/imports/cycle-import-in-diff-module-0.rs new file mode 100644 index 0000000000000..962603a89716c --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-0.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// https://github.com/rust-lang/rust/pull/124840#issuecomment-2098148587 + +mod a { + pub(crate) use crate::S; +} +mod b { + pub struct S; +} +use self::a::S; +use self::b::*; + +fn main() {} diff --git a/tests/ui/imports/cycle-import-in-diff-module-1.rs b/tests/ui/imports/cycle-import-in-diff-module-1.rs new file mode 100644 index 0000000000000..8c67df376c3f9 --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-1.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// similar `cycle-import-in-diff-module-0.rs` + +mod a { + pub(crate) use crate::s; +} +mod b { + pub mod s {} +} +use self::b::*; +use self::a::s; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.rs b/tests/ui/imports/shadow-glob-module-resolution-1.rs new file mode 100644 index 0000000000000..ba1e65cddc652 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.rs @@ -0,0 +1,17 @@ +// https://github.com/rust-lang/rust/issues/124490 + +mod a { + pub mod b { + pub mod c {} + } +} + +use a::*; + +use b::c; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import +//~| ERROR: unresolved import `b::c` +use c as b; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.stderr b/tests/ui/imports/shadow-glob-module-resolution-1.stderr new file mode 100644 index 0000000000000..f9135963fe99e --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.stderr @@ -0,0 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `b::c` + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs new file mode 100644 index 0000000000000..36bd72658ae84 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs @@ -0,0 +1,19 @@ +// https://github.com/rust-lang/rust/issues/125013 + +mod a { + pub mod b { + pub mod c { + pub trait D {} + } + } +} + +use a::*; + +use e as b; +//~^ ERROR: unresolved import `e` +use b::c::D as e; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import + +fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr new file mode 100644 index 0000000000000..644fcb8416289 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr @@ -0,0 +1,26 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `e` + --> $DIR/shadow-glob-module-resolution-2.rs:13:5 + | +LL | use e as b; + | -^^^^^ + | | + | no `e` in the root + | help: a similar name exists in the module: `a` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. From 9b2e41a21800bcd56c5ce3307ab7e484f83d51b3 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:22:12 +0200 Subject: [PATCH 07/19] Pass function for `Thread` as `Send` to `Thread::imp` --- library/std/src/thread/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 22215873933d6..83e27dfb746c2 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -561,7 +561,8 @@ impl Builder { let main = Box::new(main); // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. - let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) }; + let main = + unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) }; Ok(JoinInner { // SAFETY: @@ -1544,7 +1545,7 @@ struct Packet<'scope, T> { // The type `T` should already always be Send (otherwise the thread could not // have been created) and the Packet is Sync because all access to the // `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {} +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} impl<'scope, T> Drop for Packet<'scope, T> { fn drop(&mut self) { From b8c6008fbcb0a1f9f8af1ad7b6b196c950351b67 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:50:44 +0200 Subject: [PATCH 08/19] Store `Task::p` as `dyn FnOnce() + Send` --- library/std/src/sys/pal/sgx/thread.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index d70c6e31fb73b..2d936b09c708f 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -28,14 +28,14 @@ mod task_queue { } pub(super) struct Task { - p: Box, + p: Box, done: JoinNotifier, } unsafe impl Send for Task {} impl Task { - pub(super) fn new(p: Box) -> (Task, JoinHandle) { + pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); let done = JoinNotifier(Some(done)); (Task { p, done }, recv) @@ -97,7 +97,7 @@ pub mod wait_notify { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, p: Box) -> io::Result { + pub unsafe fn new(_stack: usize, p: Box) -> io::Result { let mut queue_lock = task_queue::lock(); unsafe { usercalls::launch_thread()? }; let (task, handle) = task_queue::Task::new(p); From 8db363c44b1512b5ba30b10ac3ad915228276375 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:50:59 +0200 Subject: [PATCH 09/19] Let compiler auto impl `Send` for `Task` --- library/std/src/sys/pal/sgx/thread.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 2d936b09c708f..446cdd18b7e42 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -32,8 +32,6 @@ mod task_queue { done: JoinNotifier, } - unsafe impl Send for Task {} - impl Task { pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); From 5e8df95dbb445b2891610a9e46ce31c2b615bc09 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 13:01:16 +0000 Subject: [PATCH 10/19] Manual rustfmt --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 58eb0c2817987..5f73b3b618f5f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1419,8 +1419,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx().span_delayed_bug( span, format!( - "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", - ), + "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", + ), ); } } From 14f9c63759b67ad725dbecb003bcb7752fc92d69 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 06:32:35 +0000 Subject: [PATCH 11/19] Show that it will pick up the entirely wrong function as a private candidate --- src/tools/tidy/src/ui_tests.rs | 2 +- ...3498.stderr => issue-53498.different_name.stderr} | 2 +- tests/ui/issues/issue-53498.rs | 9 ++++++++- tests/ui/issues/issue-53498.same_name.stderr | 12 ++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) rename tests/ui/issues/{issue-53498.stderr => issue-53498.different_name.stderr} (91%) create mode 100644 tests/ui/issues/issue-53498.same_name.stderr diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index cce0fb2c1a25b..37ce335c9a3dd 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1674; +const ISSUES_ENTRY_LIMIT: u32 = 1675; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issues/issue-53498.stderr b/tests/ui/issues/issue-53498.different_name.stderr similarity index 91% rename from tests/ui/issues/issue-53498.stderr rename to tests/ui/issues/issue-53498.different_name.stderr index 61a1aedf50821..45ee858ac9215 100644 --- a/tests/ui/issues/issue-53498.stderr +++ b/tests/ui/issues/issue-53498.different_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/issue-53498.rs:16:27 + --> $DIR/issue-53498.rs:21:27 | LL | fn foo() {} | -------- private associated function defined here diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs index 9e0437c46f4bd..816d3f9e448fa 100644 --- a/tests/ui/issues/issue-53498.rs +++ b/tests/ui/issues/issue-53498.rs @@ -1,3 +1,5 @@ +//@ revisions: same_name different_name + pub mod test { pub struct A; pub struct B; @@ -8,10 +10,15 @@ pub mod test { } impl Foo { + #[cfg(same_name)] fn foo() {} + #[cfg(different_name)] + fn bar() {} } } fn main() { - test::Foo::::foo(); //~ ERROR associated function `foo` is private + test::Foo::::foo(); + //[same_name]~^ ERROR associated function `foo` is private + //[different_name]~^^ ERROR associated function `foo` is private } diff --git a/tests/ui/issues/issue-53498.same_name.stderr b/tests/ui/issues/issue-53498.same_name.stderr new file mode 100644 index 0000000000000..45ee858ac9215 --- /dev/null +++ b/tests/ui/issues/issue-53498.same_name.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `foo` is private + --> $DIR/issue-53498.rs:21:27 + | +LL | fn foo() {} + | -------- private associated function defined here +... +LL | test::Foo::::foo(); + | ^^^ private associated function + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0624`. From 7d151fa3b015ad1dbac18933c58db3413a964534 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 15:51:21 +0000 Subject: [PATCH 12/19] Turn a delayed bug back into a normal bug by winnowing private method candidates instead of assuming any candidate of the right name will apply. --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 28 ++++++++++++++----- .../issues/issue-53498.different_name.stderr | 13 +++++---- tests/ui/issues/issue-53498.rs | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 5f73b3b618f5f..4bd73dc6c9425 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1072,7 +1072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ImplContainer => { if segments.len() == 1 { // `::assoc` will end up here, and so - // can `T::assoc`. It this came from an + // can `T::assoc`. If this came from an // inherent impl, we need to record the // `T` for posterity (see `UserSelfTy` for // details). @@ -1416,7 +1416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { - self.dcx().span_delayed_bug( + self.dcx().span_bug( span, format!( "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 12ced49f92ff7..ab0f16bd87d07 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -41,6 +41,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{ use rustc_trait_selection::traits::query::CanonicalTyGoal; use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; +use std::cell::Cell; use std::cell::RefCell; use std::cmp::max; use std::iter; @@ -76,8 +77,12 @@ pub(crate) struct ProbeContext<'a, 'tcx> { /// requested name (by edit distance) allow_similar_names: bool, + /// List of potential private candidates. Will be trimmed to ones that + /// actually apply and then the result inserted into `private_candidate` + private_candidates: Vec>, + /// Some(candidate) if there is a private candidate - private_candidate: Option<(DefKind, DefId)>, + private_candidate: Cell>, /// Collects near misses when the candidate functions are missing a `self` keyword and is only /// used for error reporting @@ -581,7 +586,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { orig_steps_var_values, steps, allow_similar_names: false, - private_candidate: None, + private_candidates: Vec::new(), + private_candidate: Cell::new(None), static_candidates: RefCell::new(Vec::new()), unsatisfied_predicates: RefCell::new(Vec::new()), scope_expr_id, @@ -593,7 +599,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.inherent_candidates.clear(); self.extension_candidates.clear(); self.impl_dups.clear(); - self.private_candidate = None; + self.private_candidates.clear(); + self.private_candidate.set(None); self.static_candidates.borrow_mut().clear(); self.unsatisfied_predicates.borrow_mut().clear(); } @@ -617,9 +624,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { self.extension_candidates.push(candidate); } - } else if self.private_candidate.is_none() { - self.private_candidate = - Some((candidate.item.kind.as_def_kind(), candidate.item.def_id)); + } else { + self.private_candidates.push(candidate); } } @@ -1171,7 +1177,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut possibly_unsatisfied_predicates = Vec::new(); for (kind, candidates) in - &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] + [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] { debug!("searching {} candidates", kind); let res = self.consider_candidates( @@ -1185,6 +1191,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + if self.private_candidate.get().is_none() { + if let Some(Ok(pick)) = + self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None) + { + self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id))); + } + } + // `pick_method` may be called twice for the same self_ty if no stable methods // match. Only extend once. if unstable_candidates.is_some() { diff --git a/tests/ui/issues/issue-53498.different_name.stderr b/tests/ui/issues/issue-53498.different_name.stderr index 45ee858ac9215..fc765f2e75d3f 100644 --- a/tests/ui/issues/issue-53498.different_name.stderr +++ b/tests/ui/issues/issue-53498.different_name.stderr @@ -1,12 +1,15 @@ -error[E0624]: associated function `foo` is private +error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope --> $DIR/issue-53498.rs:21:27 | -LL | fn foo() {} - | -------- private associated function defined here +LL | pub struct Foo(T); + | ----------------- function or associated item `foo` not found for this struct ... LL | test::Foo::::foo(); - | ^^^ private associated function + | ^^^ function or associated item not found in `Foo` + | + = note: the function or associated item was found for + - `Foo` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0624`. +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs index 816d3f9e448fa..64eb3a0c5fd4e 100644 --- a/tests/ui/issues/issue-53498.rs +++ b/tests/ui/issues/issue-53498.rs @@ -20,5 +20,5 @@ pub mod test { fn main() { test::Foo::::foo(); //[same_name]~^ ERROR associated function `foo` is private - //[different_name]~^^ ERROR associated function `foo` is private + //[different_name]~^^ ERROR no function or associated item named `foo` found for struct `Foo` } From 7894a1148371e4d0fa665c183615a76f9e2ec656 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:26:40 +0000 Subject: [PATCH 13/19] Move tests to a more appropriate directory --- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/{issues => privacy}/issue-53498.different_name.stderr | 0 tests/ui/{issues => privacy}/issue-53498.rs | 0 tests/ui/{issues => privacy}/issue-53498.same_name.stderr | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/{issues => privacy}/issue-53498.different_name.stderr (100%) rename tests/ui/{issues => privacy}/issue-53498.rs (100%) rename tests/ui/{issues => privacy}/issue-53498.same_name.stderr (100%) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 37ce335c9a3dd..f2eeda339d80e 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1675; +const ISSUES_ENTRY_LIMIT: u32 = 1672; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issues/issue-53498.different_name.stderr b/tests/ui/privacy/issue-53498.different_name.stderr similarity index 100% rename from tests/ui/issues/issue-53498.different_name.stderr rename to tests/ui/privacy/issue-53498.different_name.stderr diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/privacy/issue-53498.rs similarity index 100% rename from tests/ui/issues/issue-53498.rs rename to tests/ui/privacy/issue-53498.rs diff --git a/tests/ui/issues/issue-53498.same_name.stderr b/tests/ui/privacy/issue-53498.same_name.stderr similarity index 100% rename from tests/ui/issues/issue-53498.same_name.stderr rename to tests/ui/privacy/issue-53498.same_name.stderr From 81895065bb541b9e79f402d2446c1c83243b37d0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:32:53 +0000 Subject: [PATCH 14/19] Give test a more useful name --- src/tools/tidy/src/issues.txt | 1 - ...ferent_name.stderr => ufc-method-call.different_name.stderr} | 2 +- tests/ui/privacy/{issue-53498.rs => ufc-method-call.rs} | 0 ...-53498.same_name.stderr => ufc-method-call.same_name.stderr} | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) rename tests/ui/privacy/{issue-53498.different_name.stderr => ufc-method-call.different_name.stderr} (93%) rename tests/ui/privacy/{issue-53498.rs => ufc-method-call.rs} (100%) rename tests/ui/privacy/{issue-53498.same_name.stderr => ufc-method-call.same_name.stderr} (90%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 398a6fd0fbaaa..a6ba8959f0c5d 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2445,7 +2445,6 @@ ui/issues/issue-53300.rs ui/issues/issue-53333.rs ui/issues/issue-53348.rs ui/issues/issue-53419.rs -ui/issues/issue-53498.rs ui/issues/issue-53568.rs ui/issues/issue-5358-1.rs ui/issues/issue-53728.rs diff --git a/tests/ui/privacy/issue-53498.different_name.stderr b/tests/ui/privacy/ufc-method-call.different_name.stderr similarity index 93% rename from tests/ui/privacy/issue-53498.different_name.stderr rename to tests/ui/privacy/ufc-method-call.different_name.stderr index fc765f2e75d3f..80321b1c11cb4 100644 --- a/tests/ui/privacy/issue-53498.different_name.stderr +++ b/tests/ui/privacy/ufc-method-call.different_name.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope - --> $DIR/issue-53498.rs:21:27 + --> $DIR/ufc-method-call.rs:21:27 | LL | pub struct Foo(T); | ----------------- function or associated item `foo` not found for this struct diff --git a/tests/ui/privacy/issue-53498.rs b/tests/ui/privacy/ufc-method-call.rs similarity index 100% rename from tests/ui/privacy/issue-53498.rs rename to tests/ui/privacy/ufc-method-call.rs diff --git a/tests/ui/privacy/issue-53498.same_name.stderr b/tests/ui/privacy/ufc-method-call.same_name.stderr similarity index 90% rename from tests/ui/privacy/issue-53498.same_name.stderr rename to tests/ui/privacy/ufc-method-call.same_name.stderr index 45ee858ac9215..c66ae0a6b2527 100644 --- a/tests/ui/privacy/issue-53498.same_name.stderr +++ b/tests/ui/privacy/ufc-method-call.same_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/issue-53498.rs:21:27 + --> $DIR/ufc-method-call.rs:21:27 | LL | fn foo() {} | -------- private associated function defined here From ffb1b2c14809ae5d15a078a9cce5299865d7dd73 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:34:16 +0000 Subject: [PATCH 15/19] Add test description --- tests/ui/privacy/ufc-method-call.different_name.stderr | 2 +- tests/ui/privacy/ufc-method-call.rs | 6 ++++++ tests/ui/privacy/ufc-method-call.same_name.stderr | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/ui/privacy/ufc-method-call.different_name.stderr b/tests/ui/privacy/ufc-method-call.different_name.stderr index 80321b1c11cb4..16496c480dd12 100644 --- a/tests/ui/privacy/ufc-method-call.different_name.stderr +++ b/tests/ui/privacy/ufc-method-call.different_name.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope - --> $DIR/ufc-method-call.rs:21:27 + --> $DIR/ufc-method-call.rs:27:27 | LL | pub struct Foo(T); | ----------------- function or associated item `foo` not found for this struct diff --git a/tests/ui/privacy/ufc-method-call.rs b/tests/ui/privacy/ufc-method-call.rs index 64eb3a0c5fd4e..525d9a9eee904 100644 --- a/tests/ui/privacy/ufc-method-call.rs +++ b/tests/ui/privacy/ufc-method-call.rs @@ -1,3 +1,9 @@ +//! This test used to report that the method call cannot +//! call the private method `Foo::foo`, even though the user +//! explicitly selected `Foo::foo`. This is because we only +//! looked for methods of the right name, without properly checking +//! the `Self` type + //@ revisions: same_name different_name pub mod test { diff --git a/tests/ui/privacy/ufc-method-call.same_name.stderr b/tests/ui/privacy/ufc-method-call.same_name.stderr index c66ae0a6b2527..194ba42cbf985 100644 --- a/tests/ui/privacy/ufc-method-call.same_name.stderr +++ b/tests/ui/privacy/ufc-method-call.same_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/ufc-method-call.rs:21:27 + --> $DIR/ufc-method-call.rs:27:27 | LL | fn foo() {} | -------- private associated function defined here From 874670399c43c58a6e21d46662979fb4fb8a0b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 1 Jun 2024 23:44:59 +0200 Subject: [PATCH 16/19] Orphanck: Consider opaque types to never cover type parameters --- .../src/traits/coherence.rs | 59 ++++++++----------- ...k-opaque-types-not-covering.classic.stderr | 21 +++++++ ...heck-opaque-types-not-covering.next.stderr | 21 +++++++ .../orphan-check-opaque-types-not-covering.rs | 31 ++++++++++ ...erence.stderr => coherence.classic.stderr} | 2 +- .../coherence.next.stderr | 14 +++++ tests/ui/type-alias-impl-trait/coherence.rs | 2 + 7 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.rs rename tests/ui/type-alias-impl-trait/{coherence.stderr => coherence.classic.stderr} (95%) create mode 100644 tests/ui/type-alias-impl-trait/coherence.next.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ebdb032dc0e25..c81f5ac6e6efb 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -924,11 +924,12 @@ where } } - ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => { - if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) { - bug!("unexpected ty param in alias ty"); - } - + // A rigid alias may normalize to anything. + // * If it references an infer var, placeholder or bound ty, it may + // normalize to that, so we have to treat it as an uncovered ty param. + // * Otherwise it may normalize to any non-type-generic type + // be it local or non-local. + ty::Alias(kind, _) => { if ty.has_type_flags( ty::TypeFlags::HAS_TY_PLACEHOLDER | ty::TypeFlags::HAS_TY_BOUND @@ -948,7 +949,24 @@ where } } } else { - ControlFlow::Continue(()) + // Regarding *opaque types* specifically, we choose to treat them as non-local, + // even those that appear within the same crate. This seems somewhat surprising + // at first, but makes sense when you consider that opaque types are supposed + // to hide the underlying type *within the same crate*. When an opaque type is + // used from outside the module where it is declared, it should be impossible to + // observe anything about it other than the traits that it implements. + // + // The alternative would be to look at the underlying type to determine whether + // or not the opaque type itself should be considered local. + // + // However, this could make it a breaking change to switch the underlying hidden + // type from a local type to a remote type. This would violate the rule that + // opaque types should be completely opaque apart from the traits that they + // implement, so we don't use this behavior. + // Addendum: Moreover, revealing the underlying type is likely to cause cycle + // errors as we rely on coherence / the specialization graph during typeck. + + self.found_non_local_ty(ty) } } @@ -990,35 +1008,6 @@ where // auto trait impl applies. There will never be multiple impls, so we can just // act as if it were a local type here. ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Alias(ty::Opaque, ..) => { - // This merits some explanation. - // Normally, opaque types are not involved when performing - // coherence checking, since it is illegal to directly - // implement a trait on an opaque type. However, we might - // end up looking at an opaque type during coherence checking - // if an opaque type gets used within another type (e.g. as - // the type of a field) when checking for auto trait or `Sized` - // impls. This requires us to decide whether or not an opaque - // type should be considered 'local' or not. - // - // We choose to treat all opaque types as non-local, even - // those that appear within the same crate. This seems - // somewhat surprising at first, but makes sense when - // you consider that opaque types are supposed to hide - // the underlying type *within the same crate*. When an - // opaque type is used from outside the module - // where it is declared, it should be impossible to observe - // anything about it other than the traits that it implements. - // - // The alternative would be to look at the underlying type - // to determine whether or not the opaque type itself should - // be considered local. However, this could make it a breaking change - // to switch the underlying ('defining') type from a local type - // to a remote type. This would violate the rule that opaque - // types should be completely opaque apart from the traits - // that they implement, so we don't use this behavior. - self.found_non_local_ty(ty) - } }; // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so // the first type we visit is always the self type. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr new file mode 100644 index 0000000000000..44f76f321cf10 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + | +LL | impl foreign::Trait0 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + | +LL | impl foreign::Trait1 for Opaque {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr new file mode 100644 index 0000000000000..44f76f321cf10 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + | +LL | impl foreign::Trait0 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + | +LL | impl foreign::Trait1 for Opaque {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs new file mode 100644 index 0000000000000..8dc02b081c51d --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs @@ -0,0 +1,31 @@ +// Opaque types never cover type parameters. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +#![feature(type_alias_impl_trait)] + +type Identity = impl Sized; + +fn define_identity(x: T) -> Identity { + x +} + +impl foreign::Trait0 for Identity {} +//~^ ERROR type parameter `T` must be covered by another type + +type Opaque = impl Sized; + +fn define_local() -> Opaque { + Local +} + +impl foreign::Trait1 for Opaque {} +//~^ ERROR type parameter `T` must be covered by another type + +struct Local; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr similarity index 95% rename from tests/ui/type-alias-impl-trait/coherence.stderr rename to tests/ui/type-alias-impl-trait/coherence.classic.stderr index 266a532a1db19..ff059bc5806de 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence.rs:14:1 + --> $DIR/coherence.rs:16:1 | LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr new file mode 100644 index 0000000000000..dab2786c1f0fb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence.rs:16:1 + | +LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- + | | | + | | `AliasOfForeignType<()>` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs index 641c0fac17a64..760e5210c5b7a 100644 --- a/tests/ui/type-alias-impl-trait/coherence.rs +++ b/tests/ui/type-alias-impl-trait/coherence.rs @@ -1,4 +1,6 @@ //@ aux-build:foreign-crate.rs +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] extern crate foreign_crate; From 54b2e86db7f522294254ae5e4572feba28e0b929 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jun 2024 12:56:38 +1000 Subject: [PATCH 17/19] Port `tests/run-make-fulldeps/issue-19371` to ui-fulldeps --- src/tools/compiletest/src/header.rs | 10 +++++ tests/run-make-fulldeps/issue-19371/Makefile | 9 ----- .../run-compiler-twice.rs} | 38 ++++++++++++------- 3 files changed, 34 insertions(+), 23 deletions(-) delete mode 100644 tests/run-make-fulldeps/issue-19371/Makefile rename tests/{run-make-fulldeps/issue-19371/foo.rs => ui-fulldeps/run-compiler-twice.rs} (65%) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a2cdf800a9717..f8400801a3c53 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1267,6 +1267,8 @@ fn expand_variables(mut value: String, config: &Config) -> String { const CWD: &str = "{{cwd}}"; const SRC_BASE: &str = "{{src-base}}"; const BUILD_BASE: &str = "{{build-base}}"; + const SYSROOT_BASE: &str = "{{sysroot-base}}"; + const TARGET_LINKER: &str = "{{target-linker}}"; if value.contains(CWD) { let cwd = env::current_dir().unwrap(); @@ -1281,6 +1283,14 @@ fn expand_variables(mut value: String, config: &Config) -> String { value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy()); } + if value.contains(SYSROOT_BASE) { + value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_string_lossy()); + } + + if value.contains(TARGET_LINKER) { + value = value.replace(TARGET_LINKER, config.target_linker.as_deref().unwrap_or("")); + } + value } diff --git a/tests/run-make-fulldeps/issue-19371/Makefile b/tests/run-make-fulldeps/issue-19371/Makefile deleted file mode 100644 index edec68f086232..0000000000000 --- a/tests/run-make-fulldeps/issue-19371/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../../run-make/tools.mk - -# This test ensures that rustc compile_input can be called twice in one task -# without causing a panic. -# The program needs the path to rustc to get sysroot. - -all: - $(RUSTC) foo.rs - $(call RUN,foo $(TMPDIR) $(RUSTC)) diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/ui-fulldeps/run-compiler-twice.rs similarity index 65% rename from tests/run-make-fulldeps/issue-19371/foo.rs rename to tests/ui-fulldeps/run-compiler-twice.rs index 327c99a02c6fe..02748626723d9 100644 --- a/tests/run-make-fulldeps/issue-19371/foo.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -1,3 +1,13 @@ +//@ edition: 2021 +//@ run-pass +//@ run-flags: {{sysroot-base}} {{target-linker}} +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) + +// Regression test for . +// +// This test ensures that `compile_input` can be called twice in one task +// without causing a panic. + #![feature(rustc_private)] extern crate rustc_driver; @@ -5,12 +15,12 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; +use std::path::{Path, PathBuf}; + use rustc_interface::interface; use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes}; use rustc_span::FileName; -use std::path::PathBuf; - fn main() { let src = r#" fn main() {} @@ -18,28 +28,28 @@ fn main() { let args: Vec = std::env::args().collect(); - if args.len() < 4 { - panic!("expected rustc path"); + if args.len() < 2 { + panic!("expected sysroot (and optional linker)"); } - let tmpdir = PathBuf::from(&args[1]); - - let mut sysroot = PathBuf::from(&args[3]); - sysroot.pop(); - sysroot.pop(); + let sysroot = PathBuf::from(&args[1]); + let linker = args.get(2).map(PathBuf::from); - compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); + // compiletest sets the current dir to `output_base_dir` when running. + let tmpdir = std::env::current_dir().unwrap().join("tmp"); + std::fs::create_dir_all(&tmpdir).unwrap(); - compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); + compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref()); + compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref()); } -fn compile(code: String, output: PathBuf, sysroot: PathBuf) { +fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) { let mut opts = Options::default(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.maybe_sysroot = Some(sysroot); - if let Ok(linker) = std::env::var("RUSTC_LINKER") { - opts.cg.linker = Some(linker.into()); + if let Some(linker) = linker { + opts.cg.linker = Some(linker.to_owned()); } let name = FileName::anon_source_code(&code); From b710404f3b3990af8eebe2e168f6465535dfcc82 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 3 Jun 2024 20:13:31 -0400 Subject: [PATCH 18/19] Update the interpreter to handle the new cases --- .../src/interpret/terminator.rs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 0649bb5617cee..cbfe25ca8df51 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Unwrap types that are guaranteed a null-pointer-optimization fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> { - // Check if this is `Option` wrapping some type. - let inner = match layout.ty.kind() { - ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => { - args[0].as_type().unwrap() - } - _ => { - // Not an `Option`. - return Ok(layout); + // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and + // another type. + let ty::Adt(def, args) = layout.ty.kind() else { + // Not an ADT, so definitely no NPO. + return Ok(layout); + }; + let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) { + // The wrapped type is the only arg. + self.layout_of(args[0].as_type().unwrap())? + } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) { + // We want to extract which (if any) of the args is not a 1-ZST. + let lhs = self.layout_of(args[0].as_type().unwrap())?; + let rhs = self.layout_of(args[1].as_type().unwrap())?; + if lhs.is_1zst() { + rhs + } else if rhs.is_1zst() { + lhs + } else { + return Ok(layout); // no NPO } + } else { + return Ok(layout); // no NPO }; - let inner = self.layout_of(inner)?; + // Check if the inner type is one of the NPO-guaranteed ones. // For that we first unpeel transparent *structs* (but not unions). let is_npo = |def: AdtDef<'tcx>| { From e704858b0b41b72da9645f9a51e2e55a482fa5c4 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 5 Jun 2024 14:28:42 +0000 Subject: [PATCH 19/19] Update description of the `IsTerminal` example --- library/std/src/io/stdio.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index c8968b74b12d1..9aee2bb5e1c5c 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1190,9 +1190,8 @@ pub trait IsTerminal: crate::sealed::Sealed { /// /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable` /// it will print: `Hello foo`. - /// - If you instead run the example interactively by running the executable directly, it will - /// panic with the message "Expected input to be piped to the process". - /// + /// - If you instead run the example interactively by running `path/to/executable` directly, it will + /// prompt for input. /// /// [changes]: io#platform-specific-behavior /// [`Stdin`]: crate::io::Stdin