diff options
327 files changed, 3322 insertions, 1427 deletions
diff --git a/Cargo.lock b/Cargo.lock index 3d0f9e8844e..28db4063996 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.92" +version = "0.1.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64518f1ae689f74db058bbfb3238dfe6eb53f59f4ae712f1ff4348628522e190" +checksum = "76630810d973ecea3dbf611e1b7aecfb1012751ef1ff8de3998f89014a166781" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index acca1a1477f..a4e0e773a81 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, move_from_desc: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { - struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,) + struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc) } /// Signal an error due to an attempt to move out of the interior diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7119510849a..5c365e98f0b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -705,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx .explicit_item_bounds(def_id) .subst_iter_copied(tcx, substs) - .find_map(find_fn_kind_from_did), + .find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))), ty::Closure(_, substs) => match substs.as_closure().kind() { ty::ClosureKind::Fn => Some(hir::Mutability::Not), ty::ClosureKind::FnMut => Some(hir::Mutability::Mut), diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0a897272d35..e164e98539b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -50,7 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; -use crate::renumber::RegionCtxt; use crate::session_diagnostics::MoveUnsized; use crate::{ borrow_set::BorrowSet, @@ -1040,9 +1039,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .collect(); let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| { - self.infcx.next_nll_region_var( + self.infcx.next_nll_region_var_in_universe( NllRegionVariableOrigin::Existential { from_forall: false }, - || RegionCtxt::Unknown, + ty::UniverseIndex::ROOT, ) }); diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index fe4483104ee..140853db695 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -8,7 +8,7 @@ use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; pub(crate) struct Expander(pub bool); @@ -22,7 +22,7 @@ impl MultiItemModifier for Expander { _: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { let sess = ecx.sess; - if report_bad_target(sess, &item, span) { + if report_bad_target(sess, &item, span).is_err() { // We don't want to pass inappropriate targets to derive macros to avoid // follow up errors, all other errors below are recoverable. return ExpandResult::Ready(vec![item]); @@ -103,7 +103,11 @@ fn dummy_annotatable() -> Annotatable { }) } -fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { +fn report_bad_target( + sess: &Session, + item: &Annotatable, + span: Span, +) -> Result<(), ErrorGuaranteed> { let item_kind = match item { Annotatable::Item(item) => Some(&item.kind), Annotatable::Stmt(stmt) => match &stmt.kind { @@ -116,9 +120,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { let bad_target = !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..))); if bad_target { - sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }); + return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() })); } - bad_target + Ok(()) } fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index fcc68010a34..d7a92dac50f 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_expand::base::*; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{FileNameDisplayPreference, Span}; +use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span}; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -128,12 +128,15 @@ pub fn expand_test_or_bench( }; }; - // has_*_signature will report any errors in the type so compilation + // check_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors // would be spurious. - if (!is_bench && !has_test_signature(cx, &item)) - || (is_bench && !has_bench_signature(cx, &item)) - { + let check_result = if is_bench { + check_bench_signature(cx, &item, &fn_) + } else { + check_test_signature(cx, &item, &fn_) + }; + if check_result.is_err() { return if is_stmt { vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] } else { @@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { } } -fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { +fn check_test_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let sd = &cx.sess.parse_sess.span_diagnostic; - match &i.kind { - ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { - if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); - return false; - } - if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); - return false; - } - // If the termination trait is active, the compiler will check that the output - // type implements the `Termination` trait as `libtest` enforces that. - let has_output = match &sig.decl.output { - ast::FnRetTy::Default(..) => false, - ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, - _ => true, - }; - - if !sig.decl.inputs.is_empty() { - sd.span_err(i.span, "functions used as tests can not have any arguments"); - return false; - } + if let ast::Unsafe::Yes(span) = f.sig.header.unsafety { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); + } - if has_should_panic_attr && has_output { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - return false; - } + if let ast::Async::Yes { span, .. } = f.sig.header.asyncness { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); + } - if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) - { - sd.span_err( - i.span, - "functions used as tests can not have any non-lifetime generic parameters", - ); - return false; - } + // If the termination trait is active, the compiler will check that the output + // type implements the `Termination` trait as `libtest` enforces that. + let has_output = match &f.sig.decl.output { + ast::FnRetTy::Default(..) => false, + ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, + _ => true, + }; - true - } - _ => { - // should be unreachable because `is_test_fn_item` should catch all non-fn items - debug_assert!(false); - false - } + if !f.sig.decl.inputs.is_empty() { + return Err(sd.span_err(i.span, "functions used as tests can not have any arguments")); } -} -fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = match &i.kind { - // N.B., inadequate check, but we're running - // well before resolve, can't get too deep. - ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1, - _ => false, - }; + if has_should_panic_attr && has_output { + return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`")); + } + + if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) { + return Err(sd.span_err( + i.span, + "functions used as tests can not have any non-lifetime generic parameters", + )); + } + + Ok(()) +} - if !has_sig { - cx.sess.parse_sess.span_diagnostic.span_err( +fn check_bench_signature( + cx: &ExtCtxt<'_>, + i: &ast::Item, + f: &ast::Fn, +) -> Result<(), ErrorGuaranteed> { + // N.B., inadequate check, but we're running + // well before resolve, can't get too deep. + if f.sig.decl.inputs.len() != 1 { + return Err(cx.sess.parse_sess.span_diagnostic.span_err( i.span, "functions used as benches must have \ signature `fn(&mut Bencher) -> impl Termination`", - ); + )); } - has_sig + Ok(()) } diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml index 42fb35e738f..556c6444833 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml @@ -20,9 +20,9 @@ jobs: matrix: libgccjit_version: - { gcc: "libgccjit.so", artifacts_branch: "master" } - commands: [ - "--test-successful-rustc --nb-parts 2 --current-part 0", - "--test-successful-rustc --nb-parts 2 --current-part 1", + cargo_runner: [ + "sde -future -rtm_mode full --", + "", ] steps: @@ -36,6 +36,20 @@ jobs: - name: Install packages run: sudo apt-get install ninja-build ripgrep + - name: Install Intel Software Development Emulator + if: ${{ matrix.cargo_runner }} + run: | + mkdir intel-sde + cd intel-sde + dir=sde-external-9.14.0-2022-10-25-lin + file=$dir.tar.xz + wget https://downloadmirror.intel.com/751535/$file + tar xvf $file + sudo mkdir /usr/share/intel-sde + sudo cp -r $dir/* /usr/share/intel-sde + sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde + sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64 + - name: Download artifact uses: dawidd6/action-download-artifact@v2 with: @@ -91,6 +105,10 @@ jobs: ./prepare_build.sh ./build.sh --release --release-sysroot cargo test + + - name: Clean + if: ${{ !matrix.cargo_runner }} + run: | ./clean_all.sh - name: Prepare dependencies @@ -107,10 +125,18 @@ jobs: args: --release - name: Run tests + if: ${{ !matrix.cargo_runner }} run: | ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore - name: Run stdarch tests + if: ${{ !matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test + + - name: Run stdarch tests + if: ${{ matrix.cargo_runner }} + run: | + cd build_sysroot/sysroot_src/library/stdarch/ + STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore index 12ed5667563..c5ed7de200c 100644 --- a/compiler/rustc_codegen_gcc/.gitignore +++ b/compiler/rustc_codegen_gcc/.gitignore @@ -23,3 +23,5 @@ benchmarks tools/llvm-project tools/llvmint tools/llvmint-2 +# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics. +llvm diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 0f2e152f8ce..1c8754bf675 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -35,7 +35,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3" +source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" dependencies = [ "gccjit_sys", ] @@ -43,7 +43,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3" +source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984" dependencies = [ "libc", ] diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index bb741943892..a93637d9038 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -193,7 +193,7 @@ Using git-subtree with `rustc` requires a patched git to make it work. The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493). Use the following instructions to install it: -``` +```bash git clone git@github.com:tqc/git.git cd git git checkout tqc/subtree @@ -204,6 +204,21 @@ make cp git-subtree ~/bin ``` +Then, do a sync with this command: + +```bash +PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name +cd ../rustc_codegen_gcc +git checkout master +git pull +git checkout sync_branch_name +git merge master +``` + +TODO: write a script that does the above. + +https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725 + ### How to use [mem-trace](https://github.com/antoyo/mem-trace) `rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. diff --git a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml index cfadf47cc3f..a84f86a8218 100644 --- a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml +++ b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml @@ -9,6 +9,7 @@ compiler_builtins = "0.1" alloc = { path = "./sysroot_src/library/alloc" } std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } test = { path = "./sysroot_src/library/test" } +proc_macro = { path = "./sysroot_src/library/proc_macro" } [patch.crates-io] rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } diff --git a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh index 56768bbf1d0..71b3876bac2 100755 --- a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh +++ b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh @@ -29,10 +29,10 @@ git config user.name || git config user.name "None" git commit -m "Initial commit" -q for file in $(ls ../../patches/ | grep -v patcha); do -echo "[GIT] apply" $file -git apply ../../patches/$file -git add -A -git commit --no-gpg-sign -m "Patch $file" + echo "[GIT] apply" $file + git apply ../../patches/$file + git add -A + git commit --no-gpg-sign -m "Patch $file" done popd diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index c27b610f2ab..0cd7e6047c2 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -451,6 +451,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { drop_in_place(to_drop); } +#[lang = "unpin"] +pub auto trait Unpin {} + #[lang = "deref"] pub trait Deref { type Target: ?Sized; @@ -488,10 +491,23 @@ pub struct Box<T: ?Sized, A: Allocator = Global>(Unique<T>, A); impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {} +impl<T> Box<T> { + pub fn new(val: T) -> Box<T> { + unsafe { + let size = intrinsics::size_of::<T>(); + let ptr = libc::malloc(size); + intrinsics::copy(&val as *const T as *const u8, ptr, size); + Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global) + } + } +} + impl<T: ?Sized, A: Allocator> Drop for Box<T, A> { fn drop(&mut self) { - // inner value is dropped by compiler - libc::free(self.pointer.0 as *mut u8); + // inner value is dropped by compiler. + unsafe { + libc::free(self.0.pointer.0 as *mut u8); + } } } diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index cff26077740..b93d6859706 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -168,6 +168,9 @@ fn main() { world as Box<dyn SomeTrait>; assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8); + assert_eq!(intrinsics::bitreverse(0xddccu16), 0x33bbu16); + assert_eq!(intrinsics::bitreverse(0xffee_ddccu32), 0x33bb77ffu32); + assert_eq!(intrinsics::bitreverse(0x1234_5678_ffee_ddccu64), 0x33bb77ff1e6a2c48u64); assert_eq!(intrinsics::bswap(0xabu8), 0xabu8); assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16); diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs index 5c171c49fd1..18f2ddcde12 100644 --- a/compiler/rustc_codegen_gcc/example/std_example.rs +++ b/compiler/rustc_codegen_gcc/example/std_example.rs @@ -58,6 +58,7 @@ fn main() { assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); + assert_eq!(0x1234_5678_ffee_ddcc_1234_5678_ffee_ddccu128.reverse_bits(), 0x33bb77ff1e6a2c4833bb77ff1e6a2c48u128); let _d = 0i128.checked_div(2i128); let _d = 0u128.checked_div(2u128); diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/failing-ui-tests.txt index 8539e27ea6a..801464daae9 100644 --- a/compiler/rustc_codegen_gcc/failing-ui-tests.txt +++ b/compiler/rustc_codegen_gcc/failing-ui-tests.txt @@ -54,8 +54,8 @@ tests/ui/issues/issue-40883.rs tests/ui/issues/issue-43853.rs tests/ui/issues/issue-47364.rs tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs -tests/ui/rfc-2091-track-caller/std-panic-locations.rs -tests/ui/rfcs/rfc1857-drop-order.rs +tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs +tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/simd/issue-89193.rs @@ -66,3 +66,5 @@ tests/ui/generator/panic-safe.rs tests/ui/issues/issue-14875.rs tests/ui/issues/issue-29948.rs tests/ui/panic-while-printing.rs +tests/ui/enum-discriminant/get_discr.rs +tests/ui/panics/nested_panic_caught.rs diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch deleted file mode 100644 index ee5ba449fb8..00000000000 --- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch +++ /dev/null @@ -1,49 +0,0 @@ -From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001 -From: bjorn3 <bjorn3@users.noreply.github.com> -Date: Sun, 24 Nov 2019 15:34:06 +0100 -Subject: [PATCH] [core] Ignore failing tests - ---- - library/core/tests/iter.rs | 4 ++++ - library/core/tests/num/bignum.rs | 10 ++++++++++ - library/core/tests/num/mod.rs | 5 +++-- - library/core/tests/time.rs | 1 + - 4 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs -index 4bc44e9..8e3c7a4 100644 ---- a/library/core/tests/array.rs -+++ b/library/core/tests/array.rs -@@ -242,6 +242,7 @@ fn iterator_drops() { - assert_eq!(i.get(), 5); - } - -+/* - // This test does not work on targets without panic=unwind support. - // To work around this problem, test is marked is should_panic, so it will - // be automagically skipped on unsuitable targets, such as -@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() { - assert_eq!(COUNTER.load(Relaxed), 0); - panic!("test succeeded") - } -+*/ - - #[test] - fn empty_array_is_always_default() { -@@ -304,6 +304,7 @@ fn array_map() { - assert_eq!(b, [1, 2, 3]); - } - -+/* - // See note on above test for why `should_panic` is used. - #[test] - #[should_panic(expected = "test succeeded")] -@@ -332,6 +333,7 @@ fn array_map_drop_safety() { - assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create); - panic!("test succeeded") - } -+*/ - - #[test] - fn cell_allows_array_cycle() { --- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index 933ecd45baa..ebb04d0069c 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-03-02" +channel = "nightly-2023-06-19" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 250aa79f8d6..4c3b7f5036c 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -518,7 +518,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); } } - } } diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index db841b1b524..eb0cce19b85 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -2,9 +2,13 @@ use gccjit::FnAttribute; use gccjit::Function; use rustc_attr::InstructionSetAttr; +#[cfg(feature="master")] +use rustc_attr::InlineAttr; use rustc_codegen_ssa::target_features::tied_target_features; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty; +#[cfg(feature="master")] +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_session::Session; use rustc_span::symbol::sym; use smallvec::{smallvec, SmallVec}; @@ -67,6 +71,24 @@ fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { } } +/// Get GCC attribute for the provided inline heuristic. +#[cfg(feature="master")] +#[inline] +fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Option<FnAttribute<'gcc>> { + match inline { + InlineAttr::Hint => Some(FnAttribute::Inline), + InlineAttr::Always => Some(FnAttribute::AlwaysInline), + InlineAttr::Never => { + if cx.sess().target.arch != "amdgpu" { + Some(FnAttribute::NoInline) + } else { + None + } + } + InlineAttr::None => None, + } +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( @@ -77,6 +99,23 @@ pub fn from_fn_attrs<'gcc, 'tcx>( ) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); + #[cfg(feature="master")] + { + let inline = + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + InlineAttr::Never + } + else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { + InlineAttr::Hint + } + else { + codegen_fn_attrs.inline + }; + if let Some(attr) = inline_attr(cx, inline) { + func.add_attribute(attr); + } + } + let function_features = codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::<Vec<&str>>(); diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index f9ea0f00456..43d0aafbd50 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -181,6 +181,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }) .collect(); + debug_assert_eq!(casted_args.len(), args.len()); + Cow::Owned(casted_args) } @@ -207,7 +209,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let func_name = format!("{:?}", func_ptr); - let casted_args: Vec<_> = param_types + let mut casted_args: Vec<_> = param_types .into_iter() .zip(args.iter()) .enumerate() @@ -237,6 +239,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }) .collect(); + // NOTE: to take into account variadic functions. + for i in casted_args.len()..args.len() { + casted_args.push(args[i]); + } + Cow::Owned(casted_args) } @@ -280,8 +287,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } } - fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { - let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); + fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + let gcc_func = + match func_ptr.get_type().dyncast_function_ptr_type() { + Some(func) => func, + None => { + // NOTE: due to opaque pointers now being used, we need to cast here. + let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr"); + func_ptr = self.context.new_cast(None, func_ptr, typ); + new_func_type + }, + }; let func_name = format!("{:?}", func_ptr); let previous_arg_count = args.len(); let orig_args = args; @@ -424,16 +440,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().end_with_void_return(None) } - fn ret(&mut self, value: RValue<'gcc>) { - let value = - if self.structs_as_pointer.borrow().contains(&value) { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - value.dereference(None).to_rvalue() - } - else { - value - }; + fn ret(&mut self, mut value: RValue<'gcc>) { + if self.structs_as_pointer.borrow().contains(&value) { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + value = value.dereference(None).to_rvalue(); + } + let expected_return_type = self.current_func().get_return_type(); + if !expected_return_type.is_compatible_with(value.get_type()) { + // NOTE: due to opaque pointers now being used, we need to cast here. + value = self.context.new_cast(None, value, expected_return_type); + } self.llbb().end_with_return(None, value); } @@ -719,17 +736,25 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { unimplemented!(); } - fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> { + fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { let block = self.llbb(); let function = block.get_function(); // NOTE: instead of returning the dereference here, we have to assign it to a variable in // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. - // TODO(antoyo): handle align of the load instruction. - let ptr = self.context.new_cast(None, ptr, pointee_ty.make_pointer()); + // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type. + // Ideally, we shouldn't need to do this check. + let aligned_type = + if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type { + pointee_ty + } + else { + pointee_ty.get_aligned(align.bytes()) + }; + let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer()); let deref = ptr.dereference(None).to_rvalue(); unsafe { RETURN_VALUE_COUNT += 1 }; - let loaded_value = function.new_local(None, pointee_ty, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); + let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); block.add_assignment(None, loaded_value, deref); loaded_value.to_rvalue() } @@ -909,7 +934,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.context.new_bitcast(None, result, ptr_type) } - fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + // NOTE: due to opaque pointers now being used, we need to cast here. + let ptr = self.context.new_cast(None, ptr, typ.make_pointer()); // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified). let mut indices = indices.into_iter(); let index = indices.next().expect("first index in inbounds_gep"); @@ -938,6 +965,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { element.get_address(None) } else if let Some(struct_type) = value_type.is_struct() { + // NOTE: due to opaque pointers now being used, we need to bitcast here. + let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer()); ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) } else { @@ -1356,7 +1385,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn call( &mut self, - _typ: Type<'gcc>, + typ: Type<'gcc>, _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, @@ -1370,7 +1399,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(func, args, funclet) + self.function_ptr_call(typ, func, args, funclet) }; if let Some(_fn_abi) = fn_abi { // TODO(bjorn3): Apply function attributes @@ -1843,7 +1872,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { #[cfg(feature="master")] let (cond, element_type) = { - let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type"); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type"); let then_val_element_type = then_val_vector_type.get_element_type(); let then_val_element_size = then_val_element_type.get_size(); diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 33e3b0baa92..d8a1fd315c0 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::FnAttribute; +use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue}; use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods}; use rustc_middle::span_bug; @@ -234,7 +234,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ); if !self.tcx.is_reachable_non_generic(def_id) { - // TODO(antoyo): set visibility. + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Visibility(Visibility::Hidden)); } global diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index 4748e7e4be2..493626c3cf5 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -132,7 +132,7 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll pub fn mangle_name(name: &str) -> String { name.replace(|char: char| { if !char.is_alphanumeric() && char != '_' { - debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char); + debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char); true } else { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs index 8a4559355ea..438eab78943 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs @@ -2967,10 +2967,6 @@ match name { "llvm.nvvm.clz.ll" => "__nvvm_clz_ll", "llvm.nvvm.cos.approx.f" => "__nvvm_cos_approx_f", "llvm.nvvm.cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f", - "llvm.nvvm.cp.async.ca.shared.global.16" => "__nvvm_cp_async_ca_shared_global_16", - "llvm.nvvm.cp.async.ca.shared.global.4" => "__nvvm_cp_async_ca_shared_global_4", - "llvm.nvvm.cp.async.ca.shared.global.8" => "__nvvm_cp_async_ca_shared_global_8", - "llvm.nvvm.cp.async.cg.shared.global.16" => "__nvvm_cp_async_cg_shared_global_16", "llvm.nvvm.cp.async.commit.group" => "__nvvm_cp_async_commit_group", "llvm.nvvm.cp.async.mbarrier.arrive" => "__nvvm_cp_async_mbarrier_arrive", "llvm.nvvm.cp.async.mbarrier.arrive.noinc" => "__nvvm_cp_async_mbarrier_arrive_noinc", @@ -3086,18 +3082,8 @@ match name { "llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16", "llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2", "llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "llvm.nvvm.fma.rn.ftz.f16" => "__nvvm_fma_rn_ftz_f16", - "llvm.nvvm.fma.rn.ftz.f16x2" => "__nvvm_fma_rn_ftz_f16x2", - "llvm.nvvm.fma.rn.ftz.relu.f16" => "__nvvm_fma_rn_ftz_relu_f16", - "llvm.nvvm.fma.rn.ftz.relu.f16x2" => "__nvvm_fma_rn_ftz_relu_f16x2", - "llvm.nvvm.fma.rn.ftz.sat.f16" => "__nvvm_fma_rn_ftz_sat_f16", - "llvm.nvvm.fma.rn.ftz.sat.f16x2" => "__nvvm_fma_rn_ftz_sat_f16x2", "llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "llvm.nvvm.fma.rn.relu.f16" => "__nvvm_fma_rn_relu_f16", - "llvm.nvvm.fma.rn.relu.f16x2" => "__nvvm_fma_rn_relu_f16x2", - "llvm.nvvm.fma.rn.sat.f16" => "__nvvm_fma_rn_sat_f16", - "llvm.nvvm.fma.rn.sat.f16x2" => "__nvvm_fma_rn_sat_f16x2", "llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d", "llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f", "llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f", @@ -3111,32 +3097,18 @@ match name { "llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16", "llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2", "llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f", - "llvm.nvvm.fmax.ftz.f16" => "__nvvm_fmax_ftz_f16", - "llvm.nvvm.fmax.ftz.f16x2" => "__nvvm_fmax_ftz_f16x2", "llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f", - "llvm.nvvm.fmax.ftz.nan.f16" => "__nvvm_fmax_ftz_nan_f16", - "llvm.nvvm.fmax.ftz.nan.f16x2" => "__nvvm_fmax_ftz_nan_f16x2", "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f", - "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16", - "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16x2", "llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f", - "llvm.nvvm.fmax.ftz.xorsign.abs.f16" => "__nvvm_fmax_ftz_xorsign_abs_f16", - "llvm.nvvm.fmax.ftz.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_xorsign_abs_f16x2", "llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16", "llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2", "llvm.nvvm.fmax.nan.f" => "__nvvm_fmax_nan_f", - "llvm.nvvm.fmax.nan.f16" => "__nvvm_fmax_nan_f16", - "llvm.nvvm.fmax.nan.f16x2" => "__nvvm_fmax_nan_f16x2", "llvm.nvvm.fmax.nan.xorsign.abs.bf16" => "__nvvm_fmax_nan_xorsign_abs_bf16", "llvm.nvvm.fmax.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmax.nan.xorsign.abs.f" => "__nvvm_fmax_nan_xorsign_abs_f", - "llvm.nvvm.fmax.nan.xorsign.abs.f16" => "__nvvm_fmax_nan_xorsign_abs_f16", - "llvm.nvvm.fmax.nan.xorsign.abs.f16x2" => "__nvvm_fmax_nan_xorsign_abs_f16x2", "llvm.nvvm.fmax.xorsign.abs.bf16" => "__nvvm_fmax_xorsign_abs_bf16", "llvm.nvvm.fmax.xorsign.abs.bf16x2" => "__nvvm_fmax_xorsign_abs_bf16x2", "llvm.nvvm.fmax.xorsign.abs.f" => "__nvvm_fmax_xorsign_abs_f", - "llvm.nvvm.fmax.xorsign.abs.f16" => "__nvvm_fmax_xorsign_abs_f16", - "llvm.nvvm.fmax.xorsign.abs.f16x2" => "__nvvm_fmax_xorsign_abs_f16x2", "llvm.nvvm.fmin.bf16" => "__nvvm_fmin_bf16", "llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2", "llvm.nvvm.fmin.d" => "__nvvm_fmin_d", @@ -3144,32 +3116,18 @@ match name { "llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16", "llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2", "llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f", - "llvm.nvvm.fmin.ftz.f16" => "__nvvm_fmin_ftz_f16", - "llvm.nvvm.fmin.ftz.f16x2" => "__nvvm_fmin_ftz_f16x2", "llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f", - "llvm.nvvm.fmin.ftz.nan.f16" => "__nvvm_fmin_ftz_nan_f16", - "llvm.nvvm.fmin.ftz.nan.f16x2" => "__nvvm_fmin_ftz_nan_f16x2", "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f", - "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16", - "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16x2", "llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f", - "llvm.nvvm.fmin.ftz.xorsign.abs.f16" => "__nvvm_fmin_ftz_xorsign_abs_f16", - "llvm.nvvm.fmin.ftz.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_xorsign_abs_f16x2", "llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16", "llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2", "llvm.nvvm.fmin.nan.f" => "__nvvm_fmin_nan_f", - "llvm.nvvm.fmin.nan.f16" => "__nvvm_fmin_nan_f16", - "llvm.nvvm.fmin.nan.f16x2" => "__nvvm_fmin_nan_f16x2", "llvm.nvvm.fmin.nan.xorsign.abs.bf16" => "__nvvm_fmin_nan_xorsign_abs_bf16", "llvm.nvvm.fmin.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_nan_xorsign_abs_bf16x2", "llvm.nvvm.fmin.nan.xorsign.abs.f" => "__nvvm_fmin_nan_xorsign_abs_f", - "llvm.nvvm.fmin.nan.xorsign.abs.f16" => "__nvvm_fmin_nan_xorsign_abs_f16", - "llvm.nvvm.fmin.nan.xorsign.abs.f16x2" => "__nvvm_fmin_nan_xorsign_abs_f16x2", "llvm.nvvm.fmin.xorsign.abs.bf16" => "__nvvm_fmin_xorsign_abs_bf16", "llvm.nvvm.fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2", "llvm.nvvm.fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f", - "llvm.nvvm.fmin.xorsign.abs.f16" => "__nvvm_fmin_xorsign_abs_f16", - "llvm.nvvm.fmin.xorsign.abs.f16x2" => "__nvvm_fmin_xorsign_abs_f16x2", "llvm.nvvm.fns" => "__nvvm_fns", "llvm.nvvm.h2f" => "__nvvm_h2f", "llvm.nvvm.i2d.rm" => "__nvvm_i2d_rm", @@ -7895,6 +7853,10 @@ match name { "llvm.x86.subborrow.u64" => "__builtin_ia32_subborrow_u64", "llvm.x86.tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "llvm.x86.tbm.bextri.u64" => "__builtin_ia32_bextri_u64", + "llvm.x86.tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal", + "llvm.x86.tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", "llvm.x86.tdpbf16ps" => "__builtin_ia32_tdpbf16ps", "llvm.x86.tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal", "llvm.x86.tdpbssd" => "__builtin_ia32_tdpbssd", diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs index 0edec566be3..f28348380d7 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -313,6 +313,13 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc let new_args = args.to_vec(); args = vec![new_args[1], new_args[0], new_args[2], new_args[3], new_args[4]].into(); }, + "__builtin_ia32_vpshrdv_v8di" | "__builtin_ia32_vpshrdv_v4di" | "__builtin_ia32_vpshrdv_v2di" | + "__builtin_ia32_vpshrdv_v16si" | "__builtin_ia32_vpshrdv_v8si" | "__builtin_ia32_vpshrdv_v4si" | + "__builtin_ia32_vpshrdv_v32hi" | "__builtin_ia32_vpshrdv_v16hi" | "__builtin_ia32_vpshrdv_v8hi" => { + // The first two arguments are reversed, compared to LLVM. + let new_args = args.to_vec(); + args = vec![new_args[1], new_args[0], new_args[2]].into(); + }, _ => (), } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 60176874747..a31fee39918 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -551,141 +551,52 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let context = &self.cx.context; let result = match width { - 8 => { - // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 4)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA)); - let left = self.lshr(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55)); - let right = self.shl(right, context.new_rvalue_from_int(typ, 1)); - let step3 = self.or(left, right); - - step3 - }, - 16 => { - // First step. - let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 1)); - let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 1)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 2)); - let step2 = self.or(left, right); - - // Third step. - let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 4)); - let step3 = self.or(left, right); - - // Fourth step. - let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF)); - let left = self.shl(left, context.new_rvalue_from_int(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00)); - let right = self.lshr(right, context.new_rvalue_from_int(typ, 8)); - let step4 = self.or(left, right); + 8 | 16 | 32 | 64 => { + let mask = ((1u128 << width) - 1) as u64; + let (m0, m1, m2) = if width > 16 { + ( + context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64), + context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64), + context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64), + ) + } else { + ( + context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32), + context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32), + context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32), + ) + }; + let one = context.new_rvalue_from_int(typ, 1); + let two = context.new_rvalue_from_int(typ, 2); + let four = context.new_rvalue_from_int(typ, 4); - step4 - }, - 32 => { - // TODO(antoyo): Refactor with other implementations. // First step. - let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 1)); - let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 1)); + let left = self.lshr(value, one); + let left = self.and(left, m0); + let right = self.and(value, m0); + let right = self.shl(right, one); let step1 = self.or(left, right); // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 2)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 2)); + let left = self.lshr(step1, two); + let left = self.and(left, m1); + let right = self.and(step1, m1); + let right = self.shl(right, two); let step2 = self.or(left, right); // Third step. - let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 4)); - let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 4)); + let left = self.lshr(step2, four); + let left = self.and(left, m2); + let right = self.and(step2, m2); + let right = self.shl(right, four); let step3 = self.or(left, right); // Fourth step. - let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 8)); - let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 8)); - let step4 = self.or(left, right); - - // Fifth step. - let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 16)); - let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000)); - let right = self.lshr(right, context.new_rvalue_from_long(typ, 16)); - let step5 = self.or(left, right); - - step5 - }, - 64 => { - // First step. - let left = self.shl(value, context.new_rvalue_from_long(typ, 32)); - let right = self.lshr(value, context.new_rvalue_from_long(typ, 32)); - let step1 = self.or(left, right); - - // Second step. - let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF)); - let left = self.shl(left, context.new_rvalue_from_long(typ, 15)); - let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead? - let right = self.lshr(right, context.new_rvalue_from_long(typ, 17)); - let step2 = self.or(left, right); - - // Third step. - let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10)); - let left = self.xor(step2, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 10)); - let left = self.or(temp, left); - let step3 = self.xor(left, step2); - - // Fourth step. - let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4)); - let left = self.xor(step3, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 4)); - let left = self.or(temp, left); - let step4 = self.xor(left, step3); - - // Fifth step. - let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2)); - let left = self.xor(step4, left); - let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842)); - - let left = self.shl(temp, context.new_rvalue_from_long(typ, 2)); - let left = self.or(temp, left); - let step5 = self.xor(left, step4); - - step5 + if width == 8 { + step3 + } else { + self.gcc_bswap(step3, width) + } }, 128 => { // TODO(antoyo): find a more efficient implementation? diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index b59c3a64f57..9115cf97119 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -165,10 +165,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty } ); + let arg1 = args[0].immediate(); + // NOTE: we get different vector types for the same vector type and libgccjit doesn't + // compare them as equal, so bitcast. + // FIXME(antoyo): allow comparing vector types as equal in libgccjit. + let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type()); return Ok(compare_simd_types( bx, - args[0].immediate(), - args[1].immediate(), + arg1, + arg2, in_elem, llret_ty, cmp_op, @@ -341,7 +346,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // endian and MSB-first for big endian. let vector = args[0].immediate(); - let vector_type = vector.get_type().dyncast_vector().expect("vector type"); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let vector_type = vector.get_type().unqualified().dyncast_vector().expect("vector type"); let elem_type = vector_type.get_element_type(); let expected_int_bits = in_len.max(8); @@ -848,7 +854,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (true, true) => { // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition // TODO(antoyo): improve using conditional operators if possible. - let arg_type = lhs.get_type(); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); // TODO(antoyo): convert lhs and rhs to unsigned. let sum = lhs + rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); @@ -878,7 +885,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( res & cmp }, (true, false) => { - let arg_type = lhs.get_type(); + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); // TODO(antoyo): this uses the same algorithm from saturating add, but add the // negative of the right operand. Find a proper subtraction algorithm. let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index ea013c4428c..2a6b642782d 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -111,6 +111,8 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&self, sess: &Session) { + #[cfg(feature="master")] + gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); if sess.lto() != Lto::No { sess.emit_warning(LTONotSupported {}); } diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 30a3fe67b85..74f016cf90a 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -383,8 +383,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { unimplemented!(); } - fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { - // FIXME(antoyo): return correct type. - self.type_void() + fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { + let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self); + self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic) } } diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh index 6139892aefc..592997b8ab9 100755 --- a/compiler/rustc_codegen_gcc/test.sh +++ b/compiler/rustc_codegen_gcc/test.sh @@ -214,12 +214,14 @@ function setup_rustc() { rm config.toml || true cat > config.toml <<EOF +changelog-seen = 2 + [rust] codegen-backends = [] deny-warnings = false [build] -cargo = "$(which cargo)" +cargo = "$(rustup which cargo)" local-rebuild = true rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc" @@ -237,7 +239,7 @@ EOF function asm_tests() { setup_rustc - echo "[TEST] rustc test suite" + echo "[TEST] rustc asm test suite" RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/assembly/asm --rustc-args "$RUSTC_ARGS" } @@ -338,6 +340,8 @@ function test_rustc() { for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do rm $test done + rm tests/ui/consts/const_cmp_type_id.rs + rm tests/ui/consts/issue-73976-monomorphic.rs git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4ccef98afc3..51ac441a7a4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -320,7 +320,6 @@ pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportInfo #[derive(Clone)] pub struct CodegenContext<B: WriteBackendMethods> { // Resources needed when running LTO - pub backend: B, pub prof: SelfProfilerRef, pub lto: Lto, pub save_temps: bool, @@ -338,14 +337,10 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub msvc_imps_needed: bool, pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, - pub target_pointer_width: u32, pub target_arch: String, - pub debuginfo: config::DebugInfo, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, - /// Number of cgus excluding the allocator/metadata modules - pub total_cgus: usize, /// Handler to use for diagnostics produced during codegen. pub diag_emitter: SharedEmitter, /// LLVM optimizations for which we want to print remarks. @@ -441,7 +436,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>( target_cpu: String, metadata: EncodedMetadata, metadata_module: Option<CompiledModule>, - total_cgus: usize, ) -> OngoingCodegen<B> { let (coordinator_send, coordinator_receive) = channel(); let sess = tcx.sess; @@ -469,7 +463,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>( shared_emitter, codegen_worker_send, coordinator_receive, - total_cgus, sess.jobserver.clone(), Arc::new(regular_config), Arc::new(metadata_config), @@ -685,7 +678,7 @@ fn produce_final_output_artifacts( // These are used in linking steps and will be cleaned up afterward. } -pub enum WorkItem<B: WriteBackendMethods> { +pub(crate) enum WorkItem<B: WriteBackendMethods> { /// Optimize a newly codegened, totally unoptimized module. Optimize(ModuleCodegen<B::Module>), /// Copy the post-LTO artifacts from the incremental cache to the output @@ -731,7 +724,8 @@ impl<B: WriteBackendMethods> WorkItem<B> { } } -enum WorkItemResult<B: WriteBackendMethods> { +/// A result produced by the backend. +pub(crate) enum WorkItemResult<B: WriteBackendMethods> { Compiled(CompiledModule), NeedsLink(ModuleCodegen<B::Module>), NeedsFatLTO(FatLTOInput<B>), @@ -923,38 +917,41 @@ fn finish_intra_module_work<B: ExtraBackendMethods>( } } -pub enum Message<B: WriteBackendMethods> { +/// Messages sent to the coordinator. +pub(crate) enum Message<B: WriteBackendMethods> { + /// A jobserver token has become available. Sent from the jobserver helper + /// thread. Token(io::Result<Acquired>), - NeedsFatLTO { - result: FatLTOInput<B>, - worker_id: usize, - }, - NeedsThinLTO { - name: String, - thin_buffer: B::ThinBuffer, - worker_id: usize, - }, - NeedsLink { - module: ModuleCodegen<B::Module>, - worker_id: usize, - }, - Done { - result: Result<CompiledModule, Option<WorkerFatalError>>, - worker_id: usize, - }, - CodegenDone { - llvm_work_item: WorkItem<B>, - cost: u64, - }, + + /// The backend has finished processing a work item for a codegen unit. + /// Sent from a backend worker thread. + WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize }, + + /// The frontend has finished generating something (backend IR or a + /// post-LTO artifact) for a codegen unit, and it should be passed to the + /// backend. Sent from the main thread. + CodegenDone { llvm_work_item: WorkItem<B>, cost: u64 }, + + /// Similar to `CodegenDone`, but for reusing a pre-LTO artifact + /// Sent from the main thread. AddImportOnlyModule { module_data: SerializedModule<B::ModuleBuffer>, work_product: WorkProduct, }, + + /// The frontend has finished generating everything for all codegen units. + /// Sent from the main thread. CodegenComplete, - CodegenItem, + + /// Some normal-ish compiler error occurred, and codegen should be wound + /// down. Sent from the main thread. CodegenAborted, } +/// A message sent from the coordinator thread to the main thread telling it to +/// process another codegen unit. +pub struct CguMessage; + type DiagnosticArgName<'source> = Cow<'source, str>; struct Diagnostic { @@ -976,9 +973,8 @@ fn start_executing_work<B: ExtraBackendMethods>( tcx: TyCtxt<'_>, crate_info: &CrateInfo, shared_emitter: SharedEmitter, - codegen_worker_send: Sender<Message<B>>, + codegen_worker_send: Sender<CguMessage>, coordinator_receive: Receiver<Box<dyn Any + Send>>, - total_cgus: usize, jobserver: Client, regular_config: Arc<ModuleConfig>, metadata_config: Arc<ModuleConfig>, @@ -1046,7 +1042,6 @@ fn start_executing_work<B: ExtraBackendMethods>( }; let backend_features = tcx.global_backend_features(()); let cgcx = CodegenContext::<B> { - backend: backend.clone(), crate_types: sess.crate_types().to_vec(), each_linked_rlib_for_lto, lto: sess.lto(), @@ -1067,13 +1062,10 @@ fn start_executing_work<B: ExtraBackendMethods>( metadata_module_config: metadata_config, allocator_module_config: allocator_config, tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features), - total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), - target_pointer_width: tcx.sess.target.pointer_width, target_arch: tcx.sess.target.arch.to_string(), - debuginfo: tcx.sess.opts.debuginfo, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, }; @@ -1235,10 +1227,19 @@ fn start_executing_work<B: ExtraBackendMethods>( let mut needs_thin_lto = Vec::new(); let mut lto_import_only_modules = Vec::new(); let mut started_lto = false; - let mut codegen_aborted = false; - // This flag tracks whether all items have gone through codegens - let mut codegen_done = false; + /// Possible state transitions: + /// - Ongoing -> Completed + /// - Ongoing -> Aborted + /// - Completed -> Aborted + #[derive(Debug, PartialEq)] + enum CodegenState { + Ongoing, + Completed, + Aborted, + } + use CodegenState::*; + let mut codegen_state = Ongoing; // This is the queue of LLVM work items that still need processing. let mut work_items = Vec::<(WorkItem<B>, u64)>::new(); @@ -1258,10 +1259,10 @@ fn start_executing_work<B: ExtraBackendMethods>( // wait for all existing work to finish, so many of the conditions here // only apply if codegen hasn't been aborted as they represent pending // work to be done. - while !codegen_done + while codegen_state == Ongoing || running > 0 || main_thread_worker_state == MainThreadWorkerState::LLVMing - || (!codegen_aborted + || (codegen_state == Completed && !(work_items.is_empty() && needs_fat_lto.is_empty() && needs_thin_lto.is_empty() @@ -1271,7 +1272,7 @@ fn start_executing_work<B: ExtraBackendMethods>( // While there are still CGUs to be codegened, the coordinator has // to decide how to utilize the compiler processes implicit Token: // For codegenning more CGU or for running them through LLVM. - if !codegen_done { + if codegen_state == Ongoing { if main_thread_worker_state == MainThreadWorkerState::Idle { // Compute the number of workers that will be running once we've taken as many // items from the work queue as we can, plus one for the main thread. It's not @@ -1284,9 +1285,9 @@ fn start_executing_work<B: ExtraBackendMethods>( let anticipated_running = running + additional_running + 1; if !queue_full_enough(work_items.len(), anticipated_running) { - // The queue is not full enough, codegen more items: - if codegen_worker_send.send(Message::CodegenItem).is_err() { - panic!("Could not send Message::CodegenItem to main thread") + // The queue is not full enough, process more codegen units: + if codegen_worker_send.send(CguMessage).is_err() { + panic!("Could not send CguMessage to main thread") } main_thread_worker_state = MainThreadWorkerState::Codegenning; } else { @@ -1308,10 +1309,7 @@ fn start_executing_work<B: ExtraBackendMethods>( spawn_work(cgcx, item); } } - } else if codegen_aborted { - // don't queue up any more work if codegen was aborted, we're - // just waiting for our existing children to finish - } else { + } else if codegen_state == Completed { // If we've finished everything related to normal codegen // then it must be the case that we've got some LTO work to do. // Perform the serial work here of figuring out what we're @@ -1378,11 +1376,15 @@ fn start_executing_work<B: ExtraBackendMethods>( // Already making good use of that token } } + } else { + // Don't queue up any more work if codegen was aborted, we're + // just waiting for our existing children to finish. + assert!(codegen_state == Aborted); } // Spin up what work we can, only doing this while we've got available // parallelism slots and work left to spawn. - while !codegen_aborted && !work_items.is_empty() && running < tokens.len() { + while codegen_state != Aborted && !work_items.is_empty() && running < tokens.len() { let (item, _) = work_items.pop().unwrap(); maybe_start_llvm_timer(prof, cgcx.config(item.module_kind()), &mut llvm_start_time); @@ -1434,8 +1436,7 @@ fn start_executing_work<B: ExtraBackendMethods>( Err(e) => { let msg = &format!("failed to acquire jobserver token: {}", e); shared_emitter.fatal(msg); - codegen_done = true; - codegen_aborted = true; + codegen_state = Aborted; } } } @@ -1463,7 +1464,9 @@ fn start_executing_work<B: ExtraBackendMethods>( } Message::CodegenComplete => { - codegen_done = true; + if codegen_state != Aborted { + codegen_state = Completed; + } assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning); main_thread_worker_state = MainThreadWorkerState::Idle; } @@ -1475,58 +1478,59 @@ fn start_executing_work<B: ExtraBackendMethods>( // then conditions above will ensure no more work is spawned but // we'll keep executing this loop until `running` hits 0. Message::CodegenAborted => { - codegen_done = true; - codegen_aborted = true; + codegen_state = Aborted; } - Message::Done { result: Ok(compiled_module), worker_id } => { + + Message::WorkItem { result, worker_id } => { free_worker(worker_id); - match compiled_module.kind { - ModuleKind::Regular => { - compiled_modules.push(compiled_module); + + match result { + Ok(WorkItemResult::Compiled(compiled_module)) => { + match compiled_module.kind { + ModuleKind::Regular => { + compiled_modules.push(compiled_module); + } + ModuleKind::Allocator => { + assert!(compiled_allocator_module.is_none()); + compiled_allocator_module = Some(compiled_module); + } + ModuleKind::Metadata => bug!("Should be handled separately"), + } } - ModuleKind::Allocator => { - assert!(compiled_allocator_module.is_none()); - compiled_allocator_module = Some(compiled_module); + Ok(WorkItemResult::NeedsLink(module)) => { + needs_link.push(module); + } + Ok(WorkItemResult::NeedsFatLTO(fat_lto_input)) => { + assert!(!started_lto); + needs_fat_lto.push(fat_lto_input); + } + Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => { + assert!(!started_lto); + needs_thin_lto.push((name, thin_buffer)); + } + Err(Some(WorkerFatalError)) => { + // Like `CodegenAborted`, wait for remaining work to finish. + codegen_state = Aborted; + } + Err(None) => { + // If the thread failed that means it panicked, so + // we abort immediately. + bug!("worker thread panicked"); } - ModuleKind::Metadata => bug!("Should be handled separately"), } } - Message::NeedsLink { module, worker_id } => { - free_worker(worker_id); - needs_link.push(module); - } - Message::NeedsFatLTO { result, worker_id } => { - assert!(!started_lto); - free_worker(worker_id); - needs_fat_lto.push(result); - } - Message::NeedsThinLTO { name, thin_buffer, worker_id } => { - assert!(!started_lto); - free_worker(worker_id); - needs_thin_lto.push((name, thin_buffer)); - } + Message::AddImportOnlyModule { module_data, work_product } => { assert!(!started_lto); - assert!(!codegen_done); + assert_eq!(codegen_state, Ongoing); assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning); lto_import_only_modules.push((module_data, work_product)); main_thread_worker_state = MainThreadWorkerState::Idle; } - // If the thread failed that means it panicked, so we abort immediately. - Message::Done { result: Err(None), worker_id: _ } => { - bug!("worker thread panicked"); - } - Message::Done { result: Err(Some(WorkerFatalError)), worker_id } => { - // Similar to CodegenAborted, wait for remaining work to finish. - free_worker(worker_id); - codegen_done = true; - codegen_aborted = true; - } - Message::CodegenItem => bug!("the coordinator should not receive codegen requests"), } } - if codegen_aborted { + if codegen_state == Aborted { return Err(()); } @@ -1641,22 +1645,11 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B> fn drop(&mut self) { let worker_id = self.worker_id; let msg = match self.result.take() { - Some(Ok(WorkItemResult::Compiled(m))) => { - Message::Done::<B> { result: Ok(m), worker_id } - } - Some(Ok(WorkItemResult::NeedsLink(m))) => { - Message::NeedsLink::<B> { module: m, worker_id } - } - Some(Ok(WorkItemResult::NeedsFatLTO(m))) => { - Message::NeedsFatLTO::<B> { result: m, worker_id } - } - Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => { - Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id } - } + Some(Ok(result)) => Message::WorkItem::<B> { result: Ok(result), worker_id }, Some(Err(FatalError)) => { - Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id } + Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)), worker_id } } - None => Message::Done::<B> { result: Err(None), worker_id }, + None => Message::WorkItem::<B> { result: Err(None), worker_id }, }; drop(self.coordinator_send.send(Box::new(msg))); } @@ -1879,7 +1872,7 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> { pub metadata: EncodedMetadata, pub metadata_module: Option<CompiledModule>, pub crate_info: CrateInfo, - pub codegen_worker_receive: Receiver<Message<B>>, + pub codegen_worker_receive: Receiver<CguMessage>, pub shared_emitter_main: SharedEmitterMain, pub output_filenames: Arc<OutputFilenames>, pub coordinator: Coordinator<B>, @@ -1953,10 +1946,9 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { pub fn wait_for_signal_to_codegen_item(&self) { match self.codegen_worker_receive.recv() { - Ok(Message::CodegenItem) => { - // Nothing to do + Ok(CguMessage) => { + // Ok to proceed. } - Ok(_) => panic!("unexpected message"), Err(_) => { // One of the LLVM threads must have panicked, fall through so // error handling can be reached. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 6abc56d5975..28f3c23364c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -580,7 +580,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( ) -> OngoingCodegen<B> { // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { - let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1); + let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None); ongoing_codegen.codegen_finished(tcx); @@ -631,14 +631,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>( }) }); - let ongoing_codegen = start_async_codegen( - backend.clone(), - tcx, - target_cpu, - metadata, - metadata_module, - codegen_units.len(), - ); + let ongoing_codegen = + start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module); // Codegen an allocator shim, if necessary. if let Some(kind) = allocator_kind_for_codegen(tcx) { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 0db96d4e735..984cc1557a4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -97,6 +97,7 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_error_messages::DEFAULT_LOCALE_RESOURCE, + rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, @@ -329,7 +330,7 @@ fn run_compiler( return; } let should_stop = - print_crate_info(&***compiler.codegen_backend(), compiler.session(), false); + print_crate_info(&**compiler.codegen_backend(), compiler.session(), false); if should_stop == Compilation::Stop { return; @@ -351,7 +352,7 @@ fn run_compiler( interface::run_compiler(config, |compiler| { let sess = compiler.session(); - let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true) + let should_stop = print_crate_info(&**compiler.codegen_backend(), sess, true) .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader())) .and_then(|| try_process_rlink(sess, compiler)); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 70fc66947df..5e5001bc8b4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3743,6 +3743,29 @@ impl<'hir> Node<'hir> { } } + /// Get the type for constants, assoc types, type aliases and statics. + pub fn ty(self) -> Option<&'hir Ty<'hir>> { + match self { + Node::Item(it) => match it.kind { + ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => { + Some(ty) + } + _ => None, + }, + Node::TraitItem(it) => match it.kind { + TraitItemKind::Const(ty, _) => Some(ty), + TraitItemKind::Type(_, ty) => ty, + _ => None, + }, + Node::ImplItem(it) => match it.kind { + ImplItemKind::Const(ty, _) => Some(ty), + ImplItemKind::Type(ty) => Some(ty), + _ => None, + }, + _ => None, + } + } + pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> { match self { Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty), diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index e4eb0e6abd4..d29601e9008 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -412,7 +412,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() - && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder + && tcx.is_impl_trait_in_trait(alias_ty.def_id) { alias_ty } else { diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 7f060af2245..dc17ef7048d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -122,9 +122,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let all_candidate_names: Vec<_> = all_candidates() .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) - .filter_map( - |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None }, - ) + .filter_map(|item| { + if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type { + Some(item.name) + } else { + None + } + }) .collect(); if let (Some(suggested_name), true) = ( @@ -159,9 +163,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .flat_map(|trait_def_id| { self.tcx().associated_items(*trait_def_id).in_definition_order() }) - .filter_map( - |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None }, - ) + .filter_map(|item| { + if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type { + Some(item.name) + } else { + None + } + }) .collect(); if let (Some(suggested_name), true) = ( diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 22aa3c7ff08..a7e81f41c69 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { check_union(tcx, id.owner_id.def_id); } DefKind::OpaqueTy => { - let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty(); - if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin + let origin = tcx.opaque_type_origin(id.owner_id.def_id); + if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 1dfe053b215..596c5518086 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -409,9 +409,7 @@ fn fn_sig_suggestion<'tcx>( output = if let ty::Alias(_, alias_ty) = *output.kind() { tcx.explicit_item_bounds(alias_ty.def_id) .subst_iter_copied(tcx, alias_ty.substs) - .find_map(|(bound, _)| { - bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty() - }) + .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty()) .unwrap_or_else(|| { span_bug!( ident.span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 51e9b4c4501..744eb036933 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1086,7 +1086,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt wfcx.infcx, wfcx.param_env, wfcx.body_def_id, - normalized_bound, + normalized_bound.as_predicate(), bound_span, ) }); @@ -1543,8 +1543,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind() && self.seen.insert(unshifted_opaque_ty.def_id) && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local() - && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty() - && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin + && let origin = tcx.opaque_type_origin(opaque_def_id) + && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin && source == self.fn_def_id { let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| { @@ -1562,7 +1562,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { self.wfcx.infcx, self.wfcx.param_env, self.wfcx.body_def_id, - bound, + bound.as_predicate(), bound_span, )); // Set the debruijn index back to innermost here, since we already eagerly diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 5f35678d95d..958313fee6f 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -19,7 +19,7 @@ fn associated_type_bounds<'tcx>( assoc_item_def_id: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { +) -> &'tcx [(ty::Clause<'tcx>, Span)] { let item_ty = tcx.mk_projection( assoc_item_def_id.to_def_id(), InternalSubsts::identity_for_item(tcx, assoc_item_def_id), @@ -33,8 +33,11 @@ fn associated_type_bounds<'tcx>( let trait_def_id = tcx.local_parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); - let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { - match pred.kind().skip_binder() { + let bounds_from_parent = trait_predicates + .predicates + .iter() + .copied() + .filter(|(pred, _)| match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty, ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { proj.projection_ty.self_ty() == item_ty @@ -43,15 +46,10 @@ fn associated_type_bounds<'tcx>( outlives.0 == item_ty } _ => false, - } - }); + }) + .map(|(pred, span)| (pred.expect_clause(), span)); - let all_bounds = tcx.arena.alloc_from_iter( - bounds - .clauses() - .map(|(clause, span)| (clause.as_predicate(), span)) - .chain(bounds_from_parent), - ); + let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); debug!( "associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id.to_def_id()), @@ -71,7 +69,7 @@ fn opaque_type_bounds<'tcx>( ast_bounds: &'tcx [hir::GenericBound<'tcx>], item_ty: Ty<'tcx>, span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { +) -> &'tcx [(ty::Clause<'tcx>, Span)] { ty::print::with_no_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); @@ -79,15 +77,14 @@ fn opaque_type_bounds<'tcx>( icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); - tcx.arena - .alloc_from_iter(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span))) + tcx.arena.alloc_from_iter(bounds.clauses()) }) } pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> { +) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { match tcx.opt_rpitit_info(def_id.to_def_id()) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. @@ -139,11 +136,8 @@ pub(super) fn explicit_item_bounds( pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, -) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> { +) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> { tcx.explicit_item_bounds(def_id).map_bound(|bounds| { - tcx.mk_predicates_from_iter(util::elaborate( - tcx, - bounds.iter().map(|&(bound, _span)| bound), - )) + tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound))) }) } diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 98f4a8e00ef..48624cefe4d 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt}; +use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -17,7 +17,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; } -fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::ClauseKind<'_>, Span)] { +fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] { let id = tcx.hir().local_def_id_to_hir_id(item_def_id); if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) @@ -52,7 +52,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau if tcx.has_attr(item_def_id, sym::rustc_outlives) { let mut pred: Vec<String> = predicates .iter() - .map(|(out_pred, _)| match out_pred { + .map(|(out_pred, _)| match out_pred.kind().skip_binder() { ty::ClauseKind::RegionOutlives(p) => p.to_string(), ty::ClauseKind::TypeOutlives(p) => p.to_string(), err => bug!("unexpected clause {:?}", err), @@ -104,13 +104,15 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { |(ty::OutlivesPredicate(kind1, region2), &span)| { match kind1.unpack() { GenericArgKind::Type(ty1) => Some(( - ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)), + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)) + .to_predicate(tcx), span, )), GenericArgKind::Lifetime(region1) => Some(( ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( region1, *region2, - )), + )) + .to_predicate(tcx), span, )), GenericArgKind::Const(_) => { diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 8bb9ca2acf2..23d8da88a45 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -162,28 +162,25 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc // which thus mentions `'a` and should thus accept hidden types that borrow 'a // instead of requiring an additional `+ 'a`. match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: _, substs, .. }, constness: _, polarity: _, - })) => { + }) => { for subst in &substs[1..] { subst.visit_with(&mut collector); } } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty: ty::AliasTy { substs, .. }, term, - })) => { + }) => { for subst in &substs[1..] { subst.visit_with(&mut collector); } term.visit_with(&mut collector); } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - _, - region, - ))) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_, region)) => { region.visit_with(&mut collector); } _ => { diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index a07580fe72d..c7fa27da1ac 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -536,33 +536,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for ty in [first_ty, second_ty] { - for (pred, _) in self + for (clause, _) in self .tcx .explicit_item_bounds(rpit_def_id) .subst_iter_copied(self.tcx, substs) { - let pred = pred.kind().rebind(match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { + let pred = clause.kind().rebind(match clause.kind().skip_binder() { + ty::ClauseKind::Trait(trait_pred) => { // FIXME(rpitit): This will need to be fixed when we move to associated types assert!(matches!( *trait_pred.trait_ref.self_ty().kind(), ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. }) if def_id == rpit_def_id && substs == alias_substs )); - ty::PredicateKind::Clause(ty::ClauseKind::Trait( - trait_pred.with_self_ty(self.tcx, ty), - )) + ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty)) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection( - mut proj_pred, - )) => { + ty::ClauseKind::Projection(mut proj_pred) => { assert!(matches!( *proj_pred.projection_ty.self_ty().kind(), ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. }) if def_id == rpit_def_id && substs == alias_substs )); proj_pred = proj_pred.with_self_ty(self.tcx, ty); - ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_pred)) + ty::ClauseKind::Projection(proj_pred) } _ => continue, }); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 69ccbf0b58f..0a1b639af51 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -92,10 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.check_pat_top(¶m.pat, param_ty, ty_span, None); // Check that argument is Sized. - // The check for a non-trivial pattern is a hack to avoid duplicate warnings - // for simple cases like `fn foo(x: Trait)`, - // where we would error once on the parameter as a whole, and once on the binding `x`. - if param.pat.simple_ident().is_none() && !params_can_be_unsized { + if !params_can_be_unsized { fcx.require_type_is_sized( param_ty, param.pat.span, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 94b37fb3450..c64b64e925a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -174,7 +174,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self .deduce_closure_signature_from_predicates( expected_ty, - self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), + self.tcx + .explicit_item_bounds(def_id) + .subst_iter_copied(self.tcx, substs) + .map(|(c, s)| (c.as_predicate(), s)), ), ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { @@ -717,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .explicit_item_bounds(def_id) .subst_iter_copied(self.tcx, substs) - .find_map(|(p, s)| get_future_output(p, s))?, + .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return None, ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self .tcx .explicit_item_bounds(proj.def_id) .subst_iter_copied(self.tcx, proj.substs) - .find_map(|(p, s)| get_future_output(p, s))?, + .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, _ => span_bug!( self.tcx.def_span(expr_def_id), "async fn generator return type not an inference variable: {ret_ty}" diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index dabe7749cb6..fdbb153ec7d 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -577,7 +577,7 @@ fn check_must_not_suspend_ty<'tcx>( let mut has_emitted = false; for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) = + if let ty::ClauseKind::Trait(ref poly_trait_predicate) = predicate.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e759fd6bc94..762176ecfc7 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -12,6 +12,7 @@ use rustc_hir::def::DefKind; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; @@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } else { - // Encountered a real ambiguity, so abort the lookup. If `ty` is not - // an `Err`, report the right "type annotations needed" error pointing - // to it. + // Ended up encountering a type variable when doing autoderef, + // but it may not be a type variable after processing obligations + // in our local `FnCtxt`, so don't call `structurally_resolved_type`. let ty = &bad_ty.ty; let ty = self .probe_instantiate_query_response(span, &orig_values, ty) .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); - let ty = self.structurally_resolved_type(span, ty.value); - assert!(matches!(ty.kind(), ty::Error(_))); + let ty = self.resolve_vars_if_possible(ty.value); + let guar = match *ty.kind() { + ty::Infer(ty::TyVar(_)) => self + .err_ctxt() + .emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true) + .emit(), + ty::Error(guar) => guar, + _ => bug!("unexpected bad final type in method autoderef"), + }; + self.demand_eqtype(span, ty, self.tcx.ty_error(guar)); return Err(MethodError::NoMatch(NoMatchData { static_candidates: Vec::new(), unsatisfied_predicates: Vec::new(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 63370eec10b..15213c4b023 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -408,9 +408,9 @@ impl<'tcx> InferCtxt<'tcx> { predicate .kind() .map_bound(|kind| match kind { - ty::PredicateKind::Clause(ty::ClauseKind::Projection( - projection_predicate, - )) if projection_predicate.projection_ty.def_id == item_def_id => { + ty::ClauseKind::Projection(projection_predicate) + if projection_predicate.projection_ty.def_id == item_def_id => + { projection_predicate.term.ty() } _ => None, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index a723dc3f079..2a32f0b5047 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -260,7 +260,8 @@ impl<T> Trait<T> for X { (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => { if tcx.is_type_alias_impl_trait(alias.def_id) { if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) { - diag.span_note(tcx.def_span(body_owner_def_id), "\ + let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id)); + diag.span_note(sp, "\ this item must have the opaque type in its signature \ in order to be able to register hidden types"); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9526ed144c3..7dbc18908d5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1474,6 +1474,7 @@ impl<'tcx> InferCtxt<'tcx> { /// universes. Updates `self.universe` to that new universe. pub fn create_next_universe(&self) -> ty::UniverseIndex { let u = self.universe.get().next_universe(); + debug!("create_next_universe {u:?}"); self.universe.set(u); u } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3cb1788dc19..3098b8bc2f9 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -378,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> { DefiningAnchor::Bind(bind) => bind, }; - let origin = self.opaque_type_origin_unchecked(def_id); + let origin = self.tcx.opaque_type_origin(def_id); let in_definition_scope = match origin { // Async `impl Trait` hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, @@ -395,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> { }; in_definition_scope.then_some(origin) } - - /// Returns the origin of the opaque type `def_id` even if we are not in its - /// defining scope. - #[instrument(skip(self), level = "trace", ret)] - fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin { - self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin - } } /// Visitor that requires that (almost) all regions in the type visited outlive @@ -649,9 +642,7 @@ impl<'tcx> InferCtxt<'tcx> { ct_op: |ct| ct, }); - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() { if projection.term.references_error() { // No point on adding any obligations since there's a type error involved. obligations.clear(); diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 59ae2ce6c60..871171f9447 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -296,7 +296,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { trace!("{:#?}", bounds.skip_binder()); bounds .subst_iter(tcx, alias_ty.substs) - .filter_map(|p| p.to_opt_type_outlives()) + .filter_map(|p| p.as_type_outlives_clause()) .filter_map(|p| p.no_bound_vars()) .map(|OutlivesPredicate(_, r)| r) } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 00d4934b749..26919872952 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -167,13 +167,33 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { } } +impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.0.as_predicate() + } + + fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + (predicate.expect_clause(), self.1) + } + + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + (predicate.expect_clause(), self.1) + } +} + impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { fn predicate(&self) -> ty::Predicate<'tcx> { self.as_predicate() } fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - predicate.as_clause().unwrap() + predicate.expect_clause() } fn child_with_derived_cause( @@ -183,7 +203,7 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - predicate.as_clause().unwrap() + predicate.expect_clause() } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5e3ea71f0e7..54dabb75764 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -36,7 +36,7 @@ pub type Result<T> = result::Result<T, ErrorGuaranteed>; /// Created by passing [`Config`] to [`run_compiler`]. pub struct Compiler { pub(crate) sess: Lrc<Session>, - codegen_backend: Lrc<Box<dyn CodegenBackend>>, + codegen_backend: Lrc<dyn CodegenBackend>, pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>, pub(crate) override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>, } @@ -45,7 +45,7 @@ impl Compiler { pub fn session(&self) -> &Lrc<Session> { &self.sess } - pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> { + pub fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> { &self.codegen_backend } pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> { @@ -318,7 +318,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se let compiler = Compiler { sess: Lrc::new(sess), - codegen_backend: Lrc::new(codegen_backend), + codegen_backend: Lrc::from(codegen_backend), register_lints: config.register_lints, override_queries: config.override_queries, }; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index d1ba748d7af..8c4cdc6696a 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -115,7 +115,7 @@ impl<'tcx> Queries<'tcx> { fn session(&self) -> &Lrc<Session> { &self.compiler.sess } - fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> { + fn codegen_backend(&self) -> &Lrc<dyn CodegenBackend> { self.compiler.codegen_backend() } @@ -259,7 +259,7 @@ impl<'tcx> Queries<'tcx> { // Hook for UI tests. Self::check_for_rustc_errors_attr(tcx); - Ok(passes::start_codegen(&***self.codegen_backend(), tcx)) + Ok(passes::start_codegen(&**self.codegen_backend(), tcx)) }) } @@ -324,7 +324,7 @@ impl<'tcx> Queries<'tcx> { pub struct Linker { // compilation inputs sess: Lrc<Session>, - codegen_backend: Lrc<Box<dyn CodegenBackend>>, + codegen_backend: Lrc<dyn CodegenBackend>, // compilation outputs dep_graph: DepGraph, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9fb83bec993..5c5ec452850 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1984,12 +1984,12 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( - inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)], + inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)], def_id: DefId, ) -> Vec<ty::Region<'tcx>> { inferred_outlives .iter() - .filter_map(|(clause, _)| match *clause { + .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b), _ => None, @@ -2000,12 +2000,12 @@ impl ExplicitOutlivesRequirements { } fn lifetimes_outliving_type<'tcx>( - inferred_outlives: &'tcx [(ty::ClauseKind<'tcx>, Span)], + inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)], index: u32, ) -> Vec<ty::Region<'tcx>> { inferred_outlives .iter() - .filter_map(|(clause, _)| match *clause { + .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { a.is_param(index).then_some(b) } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 61c23b4c255..63a56806a45 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // Liberate bound regions in the predicate since we // don't actually care about lifetimes in this check. let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); - let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = predicate else { + let ty::ClauseKind::Projection(proj) = predicate else { continue; }; // Only check types, since those are the only things that may @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { ( ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)), + ty::ClauseKind::Trait(trait_pred), ) => Some(AddBound { suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), trait_ref: trait_pred.print_modifiers_and_trait_path(), diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e0033c48edb..5015b751eee 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -289,9 +289,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { .filter_only_self() .find_map(|(pred, _span)| { // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait( - ref poly_trait_predicate, - )) = pred.kind().skip_binder() + if let ty::ClauseKind::Trait(ref poly_trait_predicate) = + pred.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 53ece08ac3d..cbb4458d1d4 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3464,7 +3464,8 @@ declare_lint! { /// out an update in your own time. pub LONG_RUNNING_CONST_EVAL, Deny, - "detects long const eval operations" + "detects long const eval operations", + report_in_external_macro } declare_lint! { diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index b37dc826d28..84b18a62028 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -54,7 +54,7 @@ fn path_to_string(path: &syn::Path) -> String { /// Returns an error diagnostic on span `span` with msg `msg`. #[must_use] -pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { +pub(crate) fn span_err<T: Into<String>>(span: impl MultiSpan, msg: T) -> Diagnostic { Diagnostic::spanned(span, Level::Error, msg) } @@ -77,11 +77,9 @@ pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic { let span = attr.span().unwrap(); let path = path_to_string(attr.path()); match attr.meta { - Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")), - Meta::NameValue(_) => { - span_err(span, &format!("`#[{path} = ...]` is not a valid attribute")) - } - Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")), + Meta::Path(_) => span_err(span, format!("`#[{path}]` is not a valid attribute")), + Meta::NameValue(_) => span_err(span, format!("`#[{path} = ...]` is not a valid attribute")), + Meta::List(_) => span_err(span, format!("`#[{path}(...)]` is not a valid attribute")), } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index e3d9eb96574..e8dc986914e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -200,7 +200,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { throw_span_err!( attr.span().unwrap(), - &format!( + format!( "diagnostic slug must be first argument of a `#[{name}(...)]` attribute" ) ); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 85dd9f6a3ce..12563292181 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -347,7 +347,7 @@ pub(crate) trait HasFieldMap { None => { span_err( span.unwrap(), - &format!("`{field}` doesn't refer to a field on this type"), + format!("`{field}` doesn't refer to a field on this type"), ) .emit(); quote! { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 21cbab54293..90014bd9267 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -25,7 +25,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::GeneratorDiagnosticData; -use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility}; +use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::{Decodable, Decoder}; use rustc_session::cstore::{ @@ -642,6 +642,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx } } +impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { + ty::codec::RefDecodable::decode(d) + } +} + impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { decoder.read_lazy() @@ -854,7 +860,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> { + ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { let lazy = self.root.tables.explicit_item_bounds.get(self, index); let output = if lazy.is_default() { &mut [] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 12f3a0fc2c2..eee29d2090a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1138,8 +1138,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::InlineConst => true, DefKind::OpaqueTy => { - let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty(); - if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin + let origin = tcx.opaque_type_origin(def_id); + if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index d11308196ea..9cffd96f4a3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -375,8 +375,8 @@ define_tables! { is_type_alias_impl_trait: Table<DefIndex, bool>, attr_flags: Table<DefIndex, AttrFlags>, def_path_hashes: Table<DefIndex, DefPathHash>, - explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>, - inferred_outlives_of: Table<DefIndex, LazyArray<(ty::ClauseKind<'static>, Span)>>, + explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, + inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>, opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>, diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 1511e255235..ca735d52314 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -231,7 +231,7 @@ pub struct CodegenUnit<'tcx> { /// as well as the crate name and disambiguator. name: Symbol, items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>, - size_estimate: Option<usize>, + size_estimate: usize, primary: bool, /// True if this is CGU is used to hold code coverage information for dead code, /// false otherwise. @@ -269,7 +269,7 @@ impl<'tcx> CodegenUnit<'tcx> { CodegenUnit { name, items: Default::default(), - size_estimate: None, + size_estimate: 0, primary: false, is_code_coverage_dead_code_cgu: false, } @@ -320,23 +320,21 @@ impl<'tcx> CodegenUnit<'tcx> { base_n::encode(hash, base_n::CASE_INSENSITIVE) } - pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) { + pub fn compute_size_estimate(&mut self, tcx: TyCtxt<'tcx>) { // Estimate the size of a codegen unit as (approximately) the number of MIR // statements it corresponds to. - self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum()); + self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum(); } #[inline] - /// Should only be called if [`create_size_estimate`] has previously been called. + /// Should only be called if [`compute_size_estimate`] has previously been called. /// - /// [`create_size_estimate`]: Self::create_size_estimate + /// [`compute_size_estimate`]: Self::compute_size_estimate pub fn size_estimate(&self) -> usize { + // Items are never zero-sized, so if we have items the estimate must be + // non-zero, unless we forgot to call `compute_size_estimate` first. + assert!(self.items.is_empty() || self.size_estimate != 0); self.size_estimate - .expect("create_size_estimate must be called before getting a size_estimate") - } - - pub fn modify_size_estimate(&mut self, delta: usize) { - *self.size_estimate.as_mut().unwrap() += delta; } pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 440dede1700..5d6a477b9ad 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -346,7 +346,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -373,7 +373,7 @@ rustc_queries! { /// ``` /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> { + query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } @@ -647,7 +647,7 @@ rustc_queries! { /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). - query inferred_outlives_of(key: DefId) -> &'tcx [(ty::ClauseKind<'tcx>, Span)] { + query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 105667ba1e6..220118ae5cc 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -798,7 +798,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx> } } -impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::ClauseKind<'tcx>, Span)] { +impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { RefDecodable::decode(d) diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index ff8cd904ef8..248251e1ef5 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> } } +impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> { + fn encode(&self, e: &mut E) { + self.as_predicate().encode(e); + } +} + impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> { fn encode(&self, e: &mut E) { self.kind().encode(e); @@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> } } +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> { + fn decode(decoder: &mut D) -> ty::Clause<'tcx> { + let pred: ty::Predicate<'tcx> = Decodable::decode(decoder); + pred.expect_clause() + } +} + impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> { fn decode(decoder: &mut D) -> Self { let len = decoder.read_usize(); @@ -365,9 +378,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for [(ty::ClauseKind<'tcx>, Span)] -{ +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2b4f69167bf..1f9cf2c6448 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -25,10 +25,10 @@ use crate::traits::solve::{ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData, }; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid, - GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, - PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions, - TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, FloatTy, FloatVar, + FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, + ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, + ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast::{self as ast, attr}; @@ -141,7 +141,9 @@ pub struct CtxtInterners<'tcx> { region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>, predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>, + // FIXME(clause): remove this when all usages are moved to predicate predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, + clauses: InternedSet<'tcx, List<Clause<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, const_: InternedSet<'tcx, ConstData<'tcx>>, @@ -167,6 +169,7 @@ impl<'tcx> CtxtInterners<'tcx> { canonical_var_infos: Default::default(), predicate: Default::default(), predicates: Default::default(), + clauses: Default::default(), projs: Default::default(), place_elems: Default::default(), const_: Default::default(), @@ -1189,6 +1192,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { self.visibility(def_id).expect_local() } + + /// Returns the origin of the opaque type `def_id`. + #[instrument(skip(self), level = "trace", ret)] + pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin { + self.hir().expect_item(def_id).expect_opaque_ty().origin + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1533,6 +1542,7 @@ slice_interners!( canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), predicates: intern_predicates(Predicate<'tcx>), + clauses: intern_clauses(Clause<'tcx>), projs: pub mk_projs(ProjectionKind), place_elems: pub mk_place_elems(PlaceElem<'tcx>), bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), @@ -1564,7 +1574,7 @@ impl<'tcx> TyCtxt<'tcx> { let future_trait = self.require_lang_item(LangItem::Future, None); self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { - let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() else { + let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { return false; }; trait_predicate.trait_ref.def_id == future_trait @@ -2084,6 +2094,13 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_predicates(preds) } + pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> { + // FIXME consider asking the input slice to be sorted to avoid + // re-interning permutations, in which case that would be asserted + // here. + self.intern_clauses(preds) + } + pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, @@ -2135,6 +2152,14 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_predicates(xs)) } + pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>, + { + T::collect_and_apply(iter, |xs| self.mk_clauses(xs)) + } + pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c5a306fdf1f..c1d6856d33c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> { Ok(layout) => { return Ok(SizeSkeleton::Known(layout.size)); } - Err(err) => err, + Err(err @ LayoutError::Unknown(_)) => err, + // We can't extract SizeSkeleton info from other layout errors + Err( + e @ LayoutError::Cycle + | e @ LayoutError::SizeOverflow(_) + | e @ LayoutError::NormalizationFailure(..), + ) => return Err(e), }; match *ty.kind() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cd459130827..0e604fdf6f4 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -602,6 +602,24 @@ impl<'tcx> Clause<'tcx> { None } } + + pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } + + pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> { + let clause = self.kind(); + if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -713,7 +731,7 @@ pub struct CratePredicatesMap<'tcx> { /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. // FIXME(clause): should this be a `Clause`? - pub predicates: FxHashMap<DefId, &'tcx [(ClauseKind<'tcx>, Span)]>, + pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>, } impl<'tcx> Predicate<'tcx> { @@ -1243,7 +1261,21 @@ impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))) + tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) + } +} + +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.as_predicate() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 97d13822adc..cc2b26a5e14 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -128,6 +128,7 @@ parameterized_over_tcx! { ty::TraitRef, ty::Const, ty::Predicate, + ty::Clause, ty::ClauseKind, ty::GeneratorDiagnosticData, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fdcc608bf8e..7afda73862d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -928,7 +928,7 @@ pub trait PrettyPrinter<'tcx>: let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ty::ClauseKind::Trait(pred) => { let trait_ref = bound_predicate.rebind(pred.trait_ref); // Don't print + Sized, but rather + ?Sized if absent. @@ -939,7 +939,7 @@ pub trait PrettyPrinter<'tcx>: self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits); } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { + ty::ClauseKind::Projection(pred) => { let proj_ref = bound_predicate.rebind(pred); let trait_ref = proj_ref.required_poly_trait_ref(tcx); @@ -953,7 +953,7 @@ pub trait PrettyPrinter<'tcx>: &mut fn_traits, ); } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => { + ty::ClauseKind::TypeOutlives(outlives) => { lifetimes.push(outlives.1); } _ => {} diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index e53e1e0a54c..959bf032a83 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -666,10 +666,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> { self, folder: &mut F, ) -> Result<Self, F::Error> { - Ok(folder - .try_fold_predicate(self.as_predicate())? - .as_clause() - .expect("no sensible folder would do this")) + Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause()) } } @@ -713,6 +710,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> { } } +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) + } +} + impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> { fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3b63b08de5b..c0627ab5c01 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1584,7 +1584,7 @@ pub struct EarlyBoundRegion { impl fmt::Debug for EarlyBoundRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, {}", self.index, self.name) + write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) } } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 9f58cce2769..029fb2e9ba0 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1824,7 +1824,7 @@ fn check_must_not_suspend_ty<'tcx>( let mut has_emitted = false; for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref poly_trait_predicate)) = + if let ty::ClauseKind::Trait(ref poly_trait_predicate) = predicate.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 531644f0b84..97e3748b8b8 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -125,7 +125,7 @@ struct PartitioningCx<'a, 'tcx> { usage_map: &'a UsageMap<'tcx>, } -struct PlacedRootMonoItems<'tcx> { +struct PlacedMonoItems<'tcx> { /// The codegen units, sorted by name to make things deterministic. codegen_units: Vec<CodegenUnit<'tcx>>, @@ -150,18 +150,13 @@ where let cx = &PartitioningCx { tcx, usage_map }; - // In the first step, we place all regular monomorphizations into their - // respective 'home' codegen unit. Regular monomorphizations are all - // functions and statics defined in the local crate. - let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - let mut placed = place_root_mono_items(cx, mono_items); + // Place all mono items into a codegen unit. `place_mono_items` is + // responsible for initializing the CGU size estimates. + let PlacedMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = { + let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_items"); + let placed = place_mono_items(cx, mono_items); - for cgu in &mut placed.codegen_units { - cgu.create_size_estimate(tcx); - } - - debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats); + debug_dump(tcx, "PLACE", &placed.codegen_units, placed.unique_inlined_stats); placed }; @@ -175,23 +170,8 @@ where debug_dump(tcx, "MERGE", &codegen_units, unique_inlined_stats); } - // In the next step, we use the inlining map to determine which additional - // monomorphizations have to go into each codegen unit. These additional - // monomorphizations can be drop-glue, functions from external crates, and - // local functions the definition of which is marked with `#[inline]`. - { - let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(cx, &mut codegen_units); - - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); - } - - debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); - } - - // Next we try to make as many symbols "internal" as possible, so LLVM has - // more freedom to optimize. + // Make as many symbols "internal" as possible, so LLVM has more freedom to + // optimize. if !tcx.sess.link_dead_code() { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(cx, &mut codegen_units, internalization_candidates); @@ -212,10 +192,7 @@ where codegen_units } -fn place_root_mono_items<'tcx, I>( - cx: &PartitioningCx<'_, 'tcx>, - mono_items: I, -) -> PlacedRootMonoItems<'tcx> +fn place_mono_items<'tcx, I>(cx: &PartitioningCx<'_, 'tcx>, mono_items: I) -> PlacedMonoItems<'tcx> where I: Iterator<Item = MonoItem<'tcx>>, { @@ -236,6 +213,8 @@ where let mut num_unique_inlined_items = 0; let mut unique_inlined_items_size = 0; for mono_item in mono_items { + // Handle only root items directly here. Inlined items are handled at + // the bottom of the loop based on reachability. match mono_item.instantiation_mode(cx.tcx) { InstantiationMode::GloballyShared { .. } => {} InstantiationMode::LocalCopy => { @@ -248,7 +227,7 @@ where let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item); let is_volatile = is_incremental_build && mono_item.is_generic_fn(); - let codegen_unit_name = match characteristic_def_id { + let cgu_name = match characteristic_def_id { Some(def_id) => compute_codegen_unit_name( cx.tcx, cgu_name_builder, @@ -259,9 +238,7 @@ where None => fallback_cgu_name(cgu_name_builder), }; - let codegen_unit = codegen_units - .entry(codegen_unit_name) - .or_insert_with(|| CodegenUnit::new(codegen_unit_name)); + let cgu = codegen_units.entry(cgu_name).or_insert_with(|| CodegenUnit::new(cgu_name)); let mut can_be_internalized = true; let (linkage, visibility) = mono_item_linkage_and_visibility( @@ -274,23 +251,56 @@ where internalization_candidates.insert(mono_item); } - codegen_unit.items_mut().insert(mono_item, (linkage, visibility)); + cgu.items_mut().insert(mono_item, (linkage, visibility)); + + // Get all inlined items that are reachable from `mono_item` without + // going via another root item. This includes drop-glue, functions from + // external crates, and local functions the definition of which is + // marked with `#[inline]`. + let mut reachable_inlined_items = FxHashSet::default(); + get_reachable_inlined_items(cx.tcx, mono_item, cx.usage_map, &mut reachable_inlined_items); + + // Add those inlined items. It's possible an inlined item is reachable + // from multiple root items within a CGU, which is fine, it just means + // the `insert` will be a no-op. + for inlined_item in reachable_inlined_items { + // This is a CGU-private copy. + cgu.items_mut().insert(inlined_item, (Linkage::Internal, Visibility::Default)); + } } // Always ensure we have at least one CGU; otherwise, if we have a // crate with just types (for example), we could wind up with no CGU. if codegen_units.is_empty() { - let codegen_unit_name = fallback_cgu_name(cgu_name_builder); - codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name)); + let cgu_name = fallback_cgu_name(cgu_name_builder); + codegen_units.insert(cgu_name, CodegenUnit::new(cgu_name)); } let mut codegen_units: Vec<_> = codegen_units.into_values().collect(); codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str())); - PlacedRootMonoItems { + for cgu in codegen_units.iter_mut() { + cgu.compute_size_estimate(cx.tcx); + } + + return PlacedMonoItems { codegen_units, internalization_candidates, unique_inlined_stats: (num_unique_inlined_items, unique_inlined_items_size), + }; + + fn get_reachable_inlined_items<'tcx>( + tcx: TyCtxt<'tcx>, + item: MonoItem<'tcx>, + usage_map: &UsageMap<'tcx>, + visited: &mut FxHashSet<MonoItem<'tcx>>, + ) { + usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| { + let is_new = visited.insert(inlined_item); + if is_new { + get_reachable_inlined_items(tcx, inlined_item, usage_map, visited); + } + }); } } @@ -314,7 +324,7 @@ fn merge_codegen_units<'tcx>( // worse generated code. So we don't allow CGUs smaller than this (unless // there is just one CGU, of course). Note that CGU sizes of 100,000+ are // common in larger programs, so this isn't all that large. - const NON_INCR_MIN_CGU_SIZE: usize = 1000; + const NON_INCR_MIN_CGU_SIZE: usize = 1800; // Repeatedly merge the two smallest codegen units as long as: // - we have more CGUs than the upper limit, or @@ -338,9 +348,11 @@ fn merge_codegen_units<'tcx>( let mut smallest = codegen_units.pop().unwrap(); let second_smallest = codegen_units.last_mut().unwrap(); - // Move the mono-items from `smallest` to `second_smallest` - second_smallest.modify_size_estimate(smallest.size_estimate()); + // Move the items from `smallest` to `second_smallest`. Some of them + // may be duplicate inlined items, in which case the destination CGU is + // unaffected. Recalculate size estimates afterwards. second_smallest.items_mut().extend(smallest.items_mut().drain()); + second_smallest.compute_size_estimate(cx.tcx); // Record that `second_smallest` now contains all the stuff that was // in `smallest` before. @@ -406,43 +418,6 @@ fn merge_codegen_units<'tcx>( codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str())); } -fn place_inlined_mono_items<'tcx>( - cx: &PartitioningCx<'_, 'tcx>, - codegen_units: &mut [CodegenUnit<'tcx>], -) { - for cgu in codegen_units.iter_mut() { - // Collect all inlined items that need to be available in this codegen unit. - let mut reachable_inlined_items = FxHashSet::default(); - for root in cgu.items().keys() { - // Get all inlined items that are reachable from it without going - // via another root item. - get_reachable_inlined_items(cx.tcx, *root, cx.usage_map, &mut reachable_inlined_items); - } - - // Add all monomorphizations that are not already there. - for inlined_item in reachable_inlined_items { - assert!(!cgu.items().contains_key(&inlined_item)); - - // This is a CGU-private copy. - cgu.items_mut().insert(inlined_item, (Linkage::Internal, Visibility::Default)); - } - } - - fn get_reachable_inlined_items<'tcx>( - tcx: TyCtxt<'tcx>, - item: MonoItem<'tcx>, - usage_map: &UsageMap<'tcx>, - visited: &mut FxHashSet<MonoItem<'tcx>>, - ) { - usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| { - let is_new = visited.insert(inlined_item); - if is_new { - get_reachable_inlined_items(tcx, inlined_item, usage_map, visited); - } - }); - } -} - fn internalize_symbols<'tcx>( cx: &PartitioningCx<'_, 'tcx>, codegen_units: &mut [CodegenUnit<'tcx>], diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b897a6198e3..8a848e5db62 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -114,6 +114,12 @@ trait DefIdVisitor<'tcx> { ) -> ControlFlow<Self::BreakTy> { self.skeleton().visit_predicates(predicates) } + fn visit_clauses( + &mut self, + predicates: &[(ty::Clause<'tcx>, Span)], + ) -> ControlFlow<Self::BreakTy> { + self.skeleton().visit_clauses(predicates) + } } struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> { @@ -159,42 +165,23 @@ where } } - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { - trait_ref, - constness: _, - polarity: _, - })) => self.visit_trait(trait_ref), - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty, - term, - })) => { + fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> { + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => { + self.visit_trait(trait_ref) + } + ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { term.visit_with(self)?; self.visit_projection_ty(projection_ty) } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - ty, - _region, - ))) => ty.visit_with(self), - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => { - ControlFlow::Continue(()) - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), + ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()), + ty::ClauseKind::ConstArgHasType(ct, ty) => { ct.visit_with(self)?; ty.visit_with(self) } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => ct.visit_with(self), - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => arg.visit_with(self), - - ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate), + ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), + ty::ClauseKind::WellFormed(arg) => arg.visit_with(self), } } @@ -203,7 +190,16 @@ where predicates: ty::GenericPredicates<'tcx>, ) -> ControlFlow<V::BreakTy> { let ty::GenericPredicates { parent: _, predicates } = predicates; - predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate)) + predicates.iter().try_for_each(|&(predicate, _span)| { + let clause = predicate + .as_clause() + .unwrap_or_else(|| bug!("unexpected predicate: {:?}", predicate)); + self.visit_clause(clause) + }) + } + + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> { + clauses.iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) } } @@ -307,10 +303,7 @@ where // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - self.visit_predicates(ty::GenericPredicates { - parent: None, - predicates: tcx.explicit_item_bounds(def_id).skip_binder(), - })?; + self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?; } } // These types don't have their own def-ids (but may have subcomponents @@ -1814,10 +1807,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn bounds(&mut self) -> &mut Self { self.in_primary_interface = false; - self.visit_predicates(ty::GenericPredicates { - parent: None, - predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(), - }); + self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder()); self } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 539b4a1d5e7..d77fb922e84 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -103,6 +103,7 @@ pub(crate) struct ImportSuggestion { pub descr: &'static str, pub path: Path, pub accessible: bool, + pub via_import: bool, /// An extra note that should be issued if this item is suggested pub note: Option<String>, } @@ -140,9 +141,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut reported_spans = FxHashSet::default(); - for error in &self.privacy_errors { + for error in std::mem::take(&mut self.privacy_errors) { if reported_spans.insert(error.dedup_span) { - self.report_privacy_error(error); + self.report_privacy_error(&error); } } } @@ -1256,6 +1257,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path, accessible: child_accessible, note, + via_import, }); } } @@ -1609,8 +1611,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { - let PrivacyError { ident, binding, .. } = *privacy_error; + fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { + let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } = + *privacy_error; let res = binding.res(); let ctor_fields_span = self.ctor_fields_span(binding); @@ -1627,6 +1630,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident); err.span_label(ident.span, format!("private {}", descr)); + if let Some((this_res, outer_ident)) = outermost_res { + let import_suggestions = self.lookup_import_candidates( + outer_ident, + this_res.ns().unwrap_or(Namespace::TypeNS), + &parent_scope, + &|res: Res| res == this_res, + ); + let point_to_def = !show_candidates( + self.tcx, + &mut err, + Some(dedup_span.until(outer_ident.span.shrink_to_hi())), + &import_suggestions, + Instead::Yes, + FoundUse::Yes, + DiagnosticMode::Import, + vec![], + "", + ); + // If we suggest importing a public re-export, don't point at the definition. + if point_to_def && ident.span != outer_ident.span { + err.span_label( + outer_ident.span, + format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()), + ); + } + } + let mut non_exhaustive = None; // If an ADT is foreign and marked as `non_exhaustive`, then that's // probably why we have the privacy error. @@ -2455,7 +2485,8 @@ pub(crate) fn import_candidates( /// When an entity with a given name is not available in scope, we search for /// entities with that name in all crates. This method allows outputting the -/// results of this search in a programmer-friendly way +/// results of this search in a programmer-friendly way. If any entities are +/// found and suggested, returns `true`, otherwise returns `false`. fn show_candidates( tcx: TyCtxt<'_>, err: &mut Diagnostic, @@ -2467,19 +2498,19 @@ fn show_candidates( mode: DiagnosticMode, path: Vec<Segment>, append: &str, -) { +) -> bool { if candidates.is_empty() { - return; + return false; } - let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> = + let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> = Vec::new(); - let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> = + let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> = Vec::new(); candidates.iter().for_each(|c| { (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings }) - .push((path_names_to_string(&c.path), c.descr, c.did, &c.note)) + .push((path_names_to_string(&c.path), c.descr, c.did, &c.note, c.via_import)) }); // we want consistent results across executions, but candidates are produced @@ -2493,20 +2524,25 @@ fn show_candidates( } if !accessible_path_strings.is_empty() { - let (determiner, kind, name) = if accessible_path_strings.len() == 1 { - ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0)) - } else { - ("one of these", "items", String::new()) - }; + let (determiner, kind, name, through) = + if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] { + ( + "this", + *descr, + format!(" `{name}`"), + if *via_import { " through its public re-export" } else { "" }, + ) + } else { + ("one of these", "items", String::new(), "") + }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let DiagnosticMode::Pattern = mode { format!( - "if you meant to match on {}{}{}, use the full path in the pattern", - kind, instead, name + "if you meant to match on {kind}{instead}{name}, use the full path in the pattern", ) } else { - format!("consider importing {} {}{}", determiner, kind, instead) + format!("consider importing {determiner} {kind}{through}{instead}") }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { @@ -2522,7 +2558,7 @@ fn show_candidates( accessible_path_strings.into_iter().map(|a| a.0), Applicability::MaybeIncorrect, ); - return; + return true; } DiagnosticMode::Import => ("", ""), DiagnosticMode::Normal => ("use ", ";\n"), @@ -2563,6 +2599,7 @@ fn show_candidates( err.help(msg); } + true } else if !matches!(mode, DiagnosticMode::Import) { assert!(!inaccessible_path_strings.is_empty()); @@ -2571,13 +2608,9 @@ fn show_candidates( } else { "" }; - if inaccessible_path_strings.len() == 1 { - let (name, descr, def_id, note) = &inaccessible_path_strings[0]; + if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] { let msg = format!( - "{}{} `{}`{} exists but is inaccessible", - prefix, - descr, - name, + "{prefix}{descr} `{name}`{} exists but is inaccessible", if let DiagnosticMode::Pattern = mode { ", which" } else { "" } ); @@ -2594,11 +2627,11 @@ fn show_candidates( err.note(note.to_string()); } } else { - let (_, descr_first, _, _) = &inaccessible_path_strings[0]; + let (_, descr_first, _, _, _) = &inaccessible_path_strings[0]; let descr = if inaccessible_path_strings .iter() .skip(1) - .all(|(_, descr, _, _)| descr == descr_first) + .all(|(_, descr, _, _, _)| descr == descr_first) { descr_first } else { @@ -2611,7 +2644,7 @@ fn show_candidates( let mut has_colon = false; let mut spans = Vec::new(); - for (name, _, def_id, _) in &inaccessible_path_strings { + for (name, _, def_id, _, _) in &inaccessible_path_strings { if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { let span = tcx.source_span(local_def_id); let span = tcx.sess.source_map().guess_head_span(span); @@ -2637,6 +2670,9 @@ fn show_candidates( err.span_note(multi_span, msg); } + true + } else { + false } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index e29a1626aed..e5fa062967f 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -893,6 +893,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident, binding, dedup_span: path_span, + outermost_res: None, + parent_scope: *parent_scope, }); } else { return Err((Determined, Weak::No)); @@ -1369,6 +1371,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut allow_super = true; let mut second_binding = None; + // We'll provide more context to the privacy errors later, up to `len`. + let privacy_errors_len = self.privacy_errors.len(); + for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id); let record_segment_res = |this: &mut Self, res| { @@ -1506,6 +1511,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { second_binding = Some(binding); } let res = binding.res(); + + // Mark every privacy error in this path with the res to the last element. This allows us + // to detect the item the user cares about and either find an alternative import, or tell + // the user it is not accessible. + for error in &mut self.privacy_errors[privacy_errors_len..] { + error.outermost_res = Some((res, ident)); + } + let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 47d8e5993fd..c458fc872aa 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -609,7 +609,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { if errors.is_empty() { return; } @@ -679,6 +679,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => {} } } + + match &import.kind { + ImportKind::Single { source, .. } => { + if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get() + && let Some(module) = module.opt_def_id() + { + self.find_cfg_stripped(&mut diag, &source.name, module) + } + }, + _ => {} + } } diag.emit(); @@ -792,6 +803,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; let prev_ambiguity_errors_len = self.ambiguity_errors.len(); let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span); + + // We'll provide more context to the privacy errors later, up to `len`. + let privacy_errors_len = self.privacy_errors.len(); + let path_res = self.resolve_path( &import.module_path, None, @@ -931,6 +946,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => unreachable!(), }; + if self.privacy_errors.len() != privacy_errors_len { + // Get the Res for the last element, so that we can point to alternative ways of + // importing it if available. + let mut path = import.module_path.clone(); + path.push(Segment::from_ident(ident)); + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = + self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding) + { + let res = module.res().map(|r| (r, ident)); + for error in &mut self.privacy_errors[privacy_errors_len..] { + error.outermost_res = res; + } + } + } + let mut all_ns_err = true; self.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7284b33f09d..475772734ff 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1831,6 +1831,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { path, accessible: true, note: None, + via_import: false, }, )); } else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 82b333fee28..8c1cd2f1557 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -689,10 +689,13 @@ impl<'a> NameBindingKind<'a> { } } +#[derive(Debug)] struct PrivacyError<'a> { ident: Ident, binding: &'a NameBinding<'a>, dedup_span: Span, + outermost_res: Option<(Res, Ident)>, + parent_scope: ParentScope<'a>, } #[derive(Debug)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index edf95949d32..270d8331602 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1613,7 +1613,7 @@ options! { plt: Option<bool> = (None, parse_opt_bool, [TRACKED], "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries - (default: PLT is disabled if full relro is enabled)"), + (default: PLT is disabled if full relro is enabled on x86_64)"), polonius: bool = (false, parse_bool, [TRACKED], "enable polonius-based borrow-checker (default: no)"), polymorphize: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5feea83edb6..ea5beb6f8be 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1009,11 +1009,11 @@ impl Session { self.edition().rust_2024() } - /// Returns `true` if we cannot skip the PLT for shared library calls. + /// Returns `true` if we should use the PLT for shared library calls. pub fn needs_plt(&self) -> bool { - // Check if the current target usually needs PLT to be enabled. + // Check if the current target usually wants PLT to be enabled. // The user can use the command line flag to override it. - let needs_plt = self.target.needs_plt; + let want_plt = self.target.plt_by_default; let dbg_opts = &self.opts.unstable_opts; @@ -1025,8 +1025,8 @@ impl Session { let full_relro = RelroLevel::Full == relro_level; // If user didn't explicitly forced us to use / skip the PLT, - // then try to skip it where possible. - dbg_opts.plt.unwrap_or(needs_plt || !full_relro) + // then use it unless the target doesn't want it by default or the full relro forces it on. + dbg_opts.plt.unwrap_or(want_plt || !full_relro) } /// Checks if LLVM lifetime markers should be emitted. diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index bb7c39ff26b..f7cdfa71c4b 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,10 +1,10 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{opts, tvos_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::Arm64; Target { - llvm_target: "arm64-apple-tvos".into(), + llvm_target: tvos_llvm_target(arch).into(), pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(), arch: arch.target_arch(), diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/apple/tests.rs index 3c90a5e7e93..3b23ddadcc4 100644 --- a/compiler/rustc_target/src/spec/apple/tests.rs +++ b/compiler/rustc_target/src/spec/apple/tests.rs @@ -30,6 +30,9 @@ fn macos_link_environment_unmodified() { for target in all_macos_targets { // macOS targets should only remove information for cross-compiling, but never // for the host. - assert_eq!(target.link_env_remove, crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET"]); + assert_eq!( + target.link_env_remove, + crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET"], + ); } } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index ff224631828..8a8d1ab95e8 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -240,7 +240,12 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which // may occur when we're linking a custom build script while targeting iOS for example. if let Ok(sdkroot) = env::var("SDKROOT") { - if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") + if sdkroot.contains("iPhoneOS.platform") + || sdkroot.contains("iPhoneSimulator.platform") + || sdkroot.contains("AppleTVOS.platform") + || sdkroot.contains("AppleTVSimulator.platform") + || sdkroot.contains("WatchOS.platform") + || sdkroot.contains("WatchSimulator.platform") { env_remove.push("SDKROOT".into()) } @@ -249,6 +254,7 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", // although this is apparently ignored when using the linker at "/usr/bin/ld". env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into()); + env_remove.push("TVOS_DEPLOYMENT_TARGET".into()); env_remove.into() } else { // Otherwise if cross-compiling for a different OS/SDK, remove any part @@ -299,6 +305,16 @@ fn tvos_lld_platform_version() -> String { format!("{major}.{minor}") } +pub fn tvos_llvm_target(arch: Arch) -> String { + let (major, minor) = tvos_deployment_target(); + format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor) +} + +pub fn tvos_sim_llvm_target(arch: Arch) -> String { + let (major, minor) = tvos_deployment_target(); + format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor) +} + fn watchos_deployment_target() -> (u32, u32) { // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0)) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0f26b703536..c15a330ee74 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1670,7 +1670,7 @@ pub struct TargetOptions { pub static_position_independent_executables: bool, /// Determines if the target always requires using the PLT for indirect /// library calls or not. This controls the default value of the `-Z plt` flag. - pub needs_plt: bool, + pub plt_by_default: bool, /// Either partial, full, or off. Full RELRO makes the dynamic linker /// resolve all symbols at startup and marks the GOT read-only before /// starting the program, preventing overwriting the GOT. @@ -1992,7 +1992,7 @@ impl Default for TargetOptions { no_default_libraries: true, position_independent_executables: false, static_position_independent_executables: false, - needs_plt: false, + plt_by_default: true, relro_level: RelroLevel::None, pre_link_objects: Default::default(), post_link_objects: Default::default(), @@ -2665,7 +2665,7 @@ impl Target { key!(no_default_libraries, bool); key!(position_independent_executables, bool); key!(static_position_independent_executables, bool); - key!(needs_plt, bool); + key!(plt_by_default, bool); key!(relro_level, RelroLevel)?; key!(archive_format); key!(allow_asm, bool); @@ -2921,7 +2921,7 @@ impl ToJson for Target { target_option_val!(no_default_libraries); target_option_val!(position_independent_executables); target_option_val!(static_position_independent_executables); - target_option_val!(needs_plt); + target_option_val!(plt_by_default); target_option_val!(relro_level); target_option_val!(archive_format); target_option_val!(allow_asm); diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs index 76de7d20c4c..2ec4d9569e3 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -1,12 +1,13 @@ -use super::apple_base::{opts, Arch}; +use super::apple_base::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let arch = Arch::X86_64_sim; Target { - llvm_target: "x86_64-apple-tvos".into(), + llvm_target: tvos_sim_llvm_target(arch).into(), pointer_width: 64, - data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(), + data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + .into(), arch: arch.target_arch(), options: TargetOptions { max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs index cba6fda19dc..a7ed74f4721 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs @@ -63,6 +63,7 @@ pub fn target() -> Target { linker: Some("rust-lld".into()), max_atomic_width: Some(64), cpu: "x86-64".into(), + plt_by_default: false, features: "+rdrnd,+rdseed,+lvi-cfi,+lvi-load-hardening".into(), llvm_args: cvs!["--x86-experimental-lvi-inline-asm-hardening"], position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs index a3bdb5f5465..c110674fd87 100644 --- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, T pub fn target() -> Target { let mut base = super::android_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; // https://developer.android.com/ndk/guides/abis.html#86-64 base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs index 6fb2dfd807a..8424757df07 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs @@ -10,6 +10,7 @@ pub fn target() -> Target { arch: "x86_64".into(), options: TargetOptions { cpu: "x86-64".into(), + plt_by_default: false, max_atomic_width: Some(64), pre_link_args: TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs index d2906d6c4ae..e2c59d2938e 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs @@ -4,6 +4,7 @@ pub fn target() -> Target { let mut base = super::solaris_base::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.vendor = "pc".into(); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs index 37feaa9dbbf..1b8885c34da 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR base.add_pre_link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs index 039bc2bd2bb..8f5e398a0be 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { let mut base = super::windows_gnullvm_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.linker = Some("x86_64-w64-mingw32-clang".into()); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs index 081806aa698..6b897ca7070 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs @@ -3,6 +3,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs index 0f31ea86b3f..650065f6330 100644 --- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs @@ -4,6 +4,7 @@ pub fn target() -> Target { let mut base = super::solaris_base::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.vendor = "sun".into(); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs index 67ce3768db0..3b8e75977b5 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::dragonfly_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs index b41e5842aad..b2d91d09996 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::freebsd_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs index a3231d19f4c..bee93541960 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs @@ -3,6 +3,7 @@ use crate::spec::{SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::fuchsia_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::X86; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs index 9a7a3b501cf..16ed3150e6e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::haiku_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs index fb1af33f80a..74ef2527c36 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs @@ -3,6 +3,7 @@ use crate::spec::{StackProbeType, Target}; pub fn target() -> Target { let mut base = super::hermit_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.features = "+rdrnd,+rdseed".into(); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs index ca5b62e279c..9259cfe5f0e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs @@ -4,6 +4,7 @@ pub fn target() -> Target { let mut base = super::illumos_base::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs index 26da7e80011..912d289c47f 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs @@ -3,6 +3,7 @@ use crate::spec::{PanicStrategy, Target}; pub fn target() -> Target { let mut base = super::l4re_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.panic_strategy = PanicStrategy::Abort; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index deb15c02c68..2f970f87cc6 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 626d5b480c6..5469d02c592 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { base.has_thread_local = false; // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI // breaks code gen. See LLVM bug 36743 - base.needs_plt = true; + base.plt_by_default = true; Target { llvm_target: "x86_64-unknown-linux-gnux32".into(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs index bf4cf7d7bec..7154f5fa306 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs index 74c434935ba..2e7bf34f7d2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, T pub fn target() -> Target { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs index 43c5ce78ce3..fe3b24f2d4a 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs @@ -10,6 +10,7 @@ use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { cpu: "x86-64".into(), + plt_by_default: false, max_atomic_width: Some(64), stack_probes: StackProbeType::X86, position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs index 8e4d42a0aca..86fa9bf7ed2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::openbsd_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs index b47f15cf578..decc9736782 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::redox_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs index a7ae17839da..67664a74710 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs @@ -10,6 +10,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::uefi_msvc_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs index c3eaa6939bb..1a9d2a57182 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR base.add_pre_link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs index b2769350bf6..1ae403fa83f 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs @@ -3,6 +3,7 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); Target { diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs index 365ade6bcf9..a7c4aaecf91 100644 --- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs @@ -3,6 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::vxworks_base::opts(); base.cpu = "x86-64".into(); + base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::X86; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index f2a39faf383..cde8a52cdec 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -522,13 +522,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs) { - if let Some(clause) = assumption.as_clause() { - match G::consider_alias_bound_candidate(self, goal, clause) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) - } - Err(NoSolution) => (), + match G::consider_alias_bound_candidate(self, goal, assumption) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }) } + Err(NoSolution) => (), } } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 97b86a06c8c..439cf788ab4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -353,7 +353,11 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( // FIXME(associated_const_equality): Also add associated consts to // the requirements here. if item.kind == ty::AssocKind::Type { - requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs)); + requirements.extend( + tcx.item_bounds(item.def_id) + .subst_iter(tcx, trait_ref.substs) + .map(|clause| clause.as_predicate()), + ); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 75a92af714b..557341f7ac8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1049,6 +1049,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { + let ty = self.resolve_vars_if_possible(ty); match self.tcx.sess.opts.unstable_opts.trait_solver { TraitSolver::Classic => { // WF predicates cannot themselves make @@ -2382,17 +2383,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() { let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count(); - let message = if non_blanket_impl_count == 1 { - "use the fully-qualified path to the only available implementation".to_string() - } else { + // If there is only one implementation of the trait, suggest using it. + // Otherwise, use a placeholder comment for the implementation. + let (message, impl_suggestion) = if non_blanket_impl_count == 1 {( + "use the fully-qualified path to the only available implementation".to_string(), + format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity()) + )} else {( format!( "use a fully-qualified path to a specific available implementation ({} found)", non_blanket_impl_count - ) - }; + ), + "</* self type */ as ".to_string() + )}; let mut suggestions = vec![( path.span.shrink_to_lo(), - format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity()) + impl_suggestion )]; if let Some(generic_arg) = trait_path_segment.args { let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 966c4a7dcf3..71d2380f234 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1157,7 +1157,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = pred.kind().skip_binder() + if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() // args tuple will always be substs[1] && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() @@ -2724,6 +2724,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let msg = format!("required by this bound in `{short_item_name}`"); multispan.push_span_label(span, msg); err.span_note(multispan, descr); + if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() + && let ty::ClauseKind::Trait(trait_pred) = clause + { + let def_id = trait_pred.def_id(); + let visible_item = if let Some(local) = def_id.as_local() { + // Check for local traits being reachable. + let vis = &self.tcx.resolutions(()).effective_visibilities; + // Account for non-`pub` traits in the root of the local crate. + let is_locally_reachable = self.tcx.parent(def_id).is_crate_root(); + vis.is_reachable(local) || is_locally_reachable + } else { + // Check for foreign traits being reachable. + self.tcx.visible_parent_map(()).get(&def_id).is_some() + }; + if let DefKind::Trait = tcx.def_kind(item_def_id) && !visible_item { + // FIXME(estebank): extend this to search for all the types that do + // implement this trait and list them. + err.note(format!( + "`{short_item_name}` is a \"sealed trait\", because to implement \ + it you also need to implelement `{}`, which is not accessible; \ + this is usually done to force you to use one of the provided \ + types that already implement it", + with_no_trimmed_paths!(tcx.def_path_str(def_id)), + )); + } + } } else { err.span_note(tcx.def_span(item_def_id), descr); } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 15081d65682..a5481714e3e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,12 +65,12 @@ pub use self::specialize::{ pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::elaborate; -pub use self::util::{expand_trait_aliases, TraitAliasExpander}; -pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; pub use self::util::{ - supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item, - SupertraitDefIds, + check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds, + transitive_bounds_that_define_assoc_item, SupertraitDefIds, }; +pub use self::util::{expand_trait_aliases, TraitAliasExpander}; +pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 499745473a2..df93c4d45dc 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -271,7 +271,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied()) - .filter_map(|pred_span| predicate_references_self(tcx, pred_span)) + .filter_map(|(clause, span)| predicate_references_self(tcx, (clause.as_predicate(), span))) .collect() } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index de76587c7b9..2a78c5befa4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1,5 +1,6 @@ //! Code for projecting associated types out of trait references. +use super::check_substs_compatible; use super::specialization_graph; use super::translate_substs; use super::util; @@ -1584,7 +1585,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( obligation, candidate_set, ProjectionCandidate::TraitDef, - bounds.iter(), + bounds.iter().map(|clause| clause.as_predicate()), true, ); } @@ -2378,47 +2379,6 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } -// Verify that the trait item and its implementation have compatible substs lists -fn check_substs_compatible<'tcx>( - tcx: TyCtxt<'tcx>, - assoc_item: ty::AssocItem, - substs: ty::SubstsRef<'tcx>, -) -> bool { - fn check_substs_compatible_inner<'tcx>( - tcx: TyCtxt<'tcx>, - generics: &'tcx ty::Generics, - args: &'tcx [ty::GenericArg<'tcx>], - ) -> bool { - if generics.count() != args.len() { - return false; - } - - let (parent_args, own_args) = args.split_at(generics.parent_count); - - if let Some(parent) = generics.parent - && let parent_generics = tcx.generics_of(parent) - && !check_substs_compatible_inner(tcx, parent_generics, parent_args) { - return false; - } - - for (param, arg) in std::iter::zip(&generics.params, own_args) { - match (¶m.kind, arg.unpack()) { - (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_)) - | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_)) - | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {} - _ => return false, - } - } - - true - } - - let generics = tcx.generics_of(assoc_item.def_id); - // Chop off any additional substs (RPITIT) substs - let substs = &substs[0..generics.count().min(substs.len())]; - check_substs_compatible_inner(tcx, generics, substs) -} - fn confirm_impl_trait_in_trait_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3c356978d5c..a50af417a44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -170,7 +170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs); let candidate = candidate_predicate - .to_opt_poly_trait_pred() + .as_trait_clause() .expect("projection candidate is not a trait predicate") .map_bound(|t| t.trait_ref); let mut obligations = Vec::new(); @@ -631,7 +631,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let assoc_ty_substs = tcx.mk_substs(&substs); let bound = bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs); - tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars)) + ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx) }; let normalized_bound = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0f0e3f1f16a..0a8b7b688e7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1668,9 +1668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .enumerate() .filter_map(|(idx, bound)| { let bound_predicate = bound.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = - bound_predicate.skip_binder() - { + if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() { let bound = bound_predicate.rebind(pred.trait_ref); if self.infcx.probe(|_| { match self.match_normalize_trait_ref( diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 906c357e8ca..05a7f3e3b02 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -302,3 +302,44 @@ pub enum TupleArgumentsFlag { Yes, No, } + +// Verify that the trait item and its implementation have compatible substs lists +pub fn check_substs_compatible<'tcx>( + tcx: TyCtxt<'tcx>, + assoc_item: ty::AssocItem, + substs: ty::SubstsRef<'tcx>, +) -> bool { + fn check_substs_compatible_inner<'tcx>( + tcx: TyCtxt<'tcx>, + generics: &'tcx ty::Generics, + args: &'tcx [ty::GenericArg<'tcx>], + ) -> bool { + if generics.count() != args.len() { + return false; + } + + let (parent_args, own_args) = args.split_at(generics.parent_count); + + if let Some(parent) = generics.parent + && let parent_generics = tcx.generics_of(parent) + && !check_substs_compatible_inner(tcx, parent_generics, parent_args) { + return false; + } + + for (param, arg) in std::iter::zip(&generics.params, own_args) { + match (¶m.kind, arg.unpack()) { + (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_)) + | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_)) + | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {} + _ => return false, + } + } + + true + } + + let generics = tcx.generics_of(assoc_item.def_id); + // Chop off any additional substs (RPITIT) substs + let substs = &substs[0..generics.count().min(substs.len())]; + check_substs_compatible_inner(tcx, generics, substs) +} diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e80d413d976..e96e89ce73c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -77,12 +77,19 @@ pub fn unnormalized_obligations<'tcx>( param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, ) -> Option<Vec<traits::PredicateObligation<'tcx>>> { + debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); + + // However, if `arg` IS an unresolved inference variable, returns `None`, + // because we are not able to make any progress at all. This is to prevent + // "livelock" where we say "$0 is WF if $0 is WF". + if arg.is_non_region_infer() { + return None; + } + if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { return Some(vec![]); } - debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); - let mut wf = WfPredicates { infcx, param_env, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 38f94c38861..7e64cbdf54a 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -54,7 +54,9 @@ impl<'tcx> RustIrDatabase<'tcx> { .tcx .explicit_item_bounds(def_id) .subst_iter_copied(self.interner.tcx, &bound_vars) - .filter_map(|(bound, _)| LowerInto::<Option<_>>::lower_into(bound, self.interner)) + .filter_map(|(bound, _)| { + LowerInto::<Option<_>>::lower_into(bound.as_predicate(), self.interner) + }) .collect() } } @@ -520,7 +522,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t .filter_map(|bound| { LowerInto::< Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> - >::lower_into(bound, self.interner) + >::lower_into(bound.as_predicate(), self.interner) }) .collect(); diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 73756caf372..e8917d72483 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -1,6 +1,5 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::traits::query::CanonicalPredicateGoal; @@ -18,12 +17,8 @@ fn evaluate_obligation<'tcx>( ) -> Result<EvaluationResult, OverflowError> { assert!(!tcx.next_trait_solver_globally()); debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); - // HACK This bubble is required for this tests to pass: - // impl-trait/issue99642.rs - let (ref infcx, goal, _canonical_inference_vars) = tcx - .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bubble) - .build_with_canonical(DUMMY_SP, &canonical_goal); + let (ref infcx, goal, _canonical_inference_vars) = + tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal); debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 9904acb1c0d..98d814d54f2 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -2,7 +2,6 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{ParamEnvAnd, Predicate}; use rustc_trait_selection::infer::InferCtxtBuilderExt; @@ -106,15 +105,10 @@ fn type_op_prove_predicate<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - // HACK This bubble is required for this test to pass: - // impl-trait/issue-99642.rs - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query( - &canonicalized, - |ocx, key| { - type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy()); - Ok(()) - }, - ) + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { + type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy()); + Ok(()) + }) } /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 658ab03c0f4..5b731641e9d 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait( opaque_ty_def_id: LocalDefId, ) -> LocalDefId { let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = - tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin + tcx.opaque_type_origin(opaque_ty_def_id) else { bug!("expected opaque for {opaque_ty_def_id:?}"); }; diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index 553bf40ef3a..947d4bbe86e 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> { } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_not_param)] +#[diag(ty_utils_impl_trait_not_param, code = "E0792")] pub struct NotParam<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f48bba24132..c8c2c8286b0 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -145,17 +145,35 @@ fn layout_of_uncached<'tcx>( return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } - let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() // Projection eagerly bails out when the pointee references errors, // fall back to structurally deducing metadata. && !pointee.references_error() { - let metadata_ty = tcx.normalize_erasing_regions( + let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]); + let metadata_ty = match tcx.try_normalize_erasing_regions( param_env, - tcx.mk_projection(metadata_def_id, [pointee]), - ); + pointee_metadata, + ) { + Ok(metadata_ty) => metadata_ty, + Err(mut err) => { + // Usually `<Ty as Pointee>::Metadata` can't be normalized because + // its struct tail cannot be normalized either, so try to get a + // more descriptive layout error here, which will lead to less confusing + // diagnostics. + match tcx.try_normalize_erasing_regions( + param_env, + tcx.struct_tail_without_normalization(pointee), + ) { + Ok(_) => {}, + Err(better_err) => { + err = better_err; + } + } + return Err(LayoutError::NormalizationFailure(pointee, err)); + }, + }; + let metadata_layout = cx.layout_of(metadata_ty)?; // If the metadata is a 1-zst, then the pointer is thin. if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { @@ -163,10 +181,13 @@ fn layout_of_uncached<'tcx>( } let Abi::Scalar(metadata) = metadata_layout.abi else { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); }; + metadata } else { + let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + match unsized_part.kind() { ty::Foreign(..) => { return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); @@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>( vtable } _ => { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); } } }; diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4e91dd380e8..29de8bf0e53 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -1,12 +1,11 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_errors::ErrorGuaranteed; use rustc_hir::{def::DefKind, def_id::LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; -use rustc_type_ir::AliasKind; +use rustc_trait_selection::traits::check_substs_compatible; use std::ops::ControlFlow; use crate::errors::{DuplicateArg, NotParam}; @@ -19,21 +18,35 @@ struct OpaqueTypeCollector<'tcx> { /// Avoid infinite recursion due to recursive declarations. seen: FxHashSet<LocalDefId>, + + span: Option<Span>, } impl<'tcx> OpaqueTypeCollector<'tcx> { - fn collect( - tcx: TyCtxt<'tcx>, - item: LocalDefId, - val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>, - ) -> Vec<LocalDefId> { - let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() }; - val.skip_binder().visit_with(&mut collector); - collector.opaques + fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { + Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None } } fn span(&self) -> Span { - self.tcx.def_span(self.item) + self.span.unwrap_or_else(|| { + self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item)) + }) + } + + fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) { + let old = self.span; + self.span = Some(span); + value.visit_with(self); + self.span = old; + } + + fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> { + let parent = self.parent()?; + if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { + Some(self.tcx.impl_trait_ref(parent)?.subst_identity()) + } else { + None + } } fn parent(&self) -> Option<LocalDefId> { @@ -51,91 +64,124 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { } impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { - type BreakTy = ErrorGuaranteed; - #[instrument(skip(self), ret, level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> { + t.super_visit_with(self)?; match t.kind() { - ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => { + ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { if !self.seen.insert(alias_ty.def_id.expect_local()) { return ControlFlow::Continue(()); } + + self.opaques.push(alias_ty.def_id.expect_local()); + match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) { Ok(()) => { // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not // supported at all, so this is sound to do, but once we want to support them, you'll // start seeing the error below. - self.opaques.push(alias_ty.def_id.expect_local()); - // Collect opaque types nested within the associated type bounds of this opaque type. - for (pred, _span) in self + // We use identity substs here, because we already know that the opaque type uses + // only generic parameters, and thus substituting would not give us more information. + for (pred, span) in self .tcx .explicit_item_bounds(alias_ty.def_id) - .subst_iter_copied(self.tcx, alias_ty.substs) + .subst_identity_iter_copied() { trace!(?pred); - pred.visit_with(self)?; + self.visit_spanned(span, pred); } - - ControlFlow::Continue(()) } Err(NotUniqueParam::NotParam(arg)) => { - let err = self.tcx.sess.emit_err(NotParam { + self.tcx.sess.emit_err(NotParam { arg, span: self.span(), opaque_span: self.tcx.def_span(alias_ty.def_id), }); - ControlFlow::Break(err) } Err(NotUniqueParam::DuplicateParam(arg)) => { - let err = self.tcx.sess.emit_err(DuplicateArg { + self.tcx.sess.emit_err(DuplicateArg { arg, span: self.span(), opaque_span: self.tcx.def_span(alias_ty.def_id), }); - ControlFlow::Break(err) } } } - ty::Alias(AliasKind::Projection, alias_ty) => { - if let Some(parent) = self.parent() { - trace!(?alias_ty); - let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx); - - trace!(?trait_ref, ?own_substs); - // This avoids having to do normalization of `Self::AssocTy` by only - // supporting the case of a method defining opaque types from assoc types - // in the same impl block. - if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() { - for assoc in self.tcx.associated_items(parent).in_definition_order() { + ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => { + self.tcx + .type_of(alias_ty.def_id) + .subst(self.tcx, alias_ty.substs) + .visit_with(self)?; + } + ty::Alias(ty::Projection, alias_ty) => { + // This avoids having to do normalization of `Self::AssocTy` by only + // supporting the case of a method defining opaque types from assoc types + // in the same impl block. + if let Some(parent_trait_ref) = self.parent_trait_ref() { + // If the trait ref of the associated item and the impl differs, + // then we can't use the impl's identity substitutions below, so + // just skip. + if alias_ty.trait_ref(self.tcx) == parent_trait_ref { + let parent = self.parent().expect("we should have a parent here"); + + for &assoc in self.tcx.associated_items(parent).in_definition_order() { trace!(?assoc); - if assoc.trait_item_def_id == Some(alias_ty.def_id) { - // We reconstruct the generic args of the associated type within the impl - // from the impl's generics and the generic args passed to the type via the - // projection. - let substs = ty::InternalSubsts::identity_for_item( - self.tcx, - parent.to_def_id(), - ); - trace!(?substs); - let substs: Vec<_> = - substs.iter().chain(own_substs.iter().copied()).collect(); - trace!(?substs); - // Find opaque types in this associated type. + if assoc.trait_item_def_id != Some(alias_ty.def_id) { + continue; + } + + // If the type is further specializable, then the type_of + // is not actually correct below. + if !assoc.defaultness(self.tcx).is_final() { + continue; + } + + let impl_substs = alias_ty.substs.rebase_onto( + self.tcx, + parent_trait_ref.def_id, + ty::InternalSubsts::identity_for_item(self.tcx, parent), + ); + + if check_substs_compatible(self.tcx, assoc, impl_substs) { return self .tcx .type_of(assoc.def_id) - .subst(self.tcx, &substs) + .subst(self.tcx, impl_substs) .visit_with(self); + } else { + self.tcx.sess.delay_span_bug( + self.tcx.def_span(assoc.def_id), + "item had incorrect substs", + ); } } } } - t.super_visit_with(self) } - _ => t.super_visit_with(self), + ty::Adt(def, _) if def.did().is_local() => { + if !self.seen.insert(def.did().expect_local()) { + return ControlFlow::Continue(()); + } + for variant in def.variants().iter() { + for field in variant.fields.iter() { + // Don't use the `ty::Adt` substs, we either + // * found the opaque in the substs + // * will find the opaque in the unsubstituted fields + // The only other situation that can occur is that after substituting, + // some projection resolves to an opaque that we would have otherwise + // not found. While we could substitute and walk those, that would mean we + // would have to walk all substitutions of an Adt, which can quickly + // degenerate into looking at an exponential number of types. + let ty = self.tcx.type_of(field.did).subst_identity(); + self.visit_spanned(self.tcx.def_span(field.did), ty); + } + } + } + _ => trace!(kind=?t.kind()), } + ControlFlow::Continue(()) } } @@ -146,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ match kind { // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { - let defined_opaques = match kind { - DefKind::Fn => { - OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity()) + let mut collector = OpaqueTypeCollector::new(tcx, item); + match kind { + // Walk over the signature of the function-like to find the opaques. + DefKind::AssocFn | DefKind::Fn => { + let ty_sig = tcx.fn_sig(item).subst_identity(); + let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap(); + // Walk over the inputs and outputs manually in order to get good spans for them. + collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output()); + for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) { + collector.visit_spanned(hir.span, ty.map_bound(|x| *x)); + } } - DefKind::AssocFn => { - OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity()) + // Walk over the type of the item to find opaques. + DefKind::AssocTy | DefKind::AssocConst => { + let span = match tcx.hir().get_by_def_id(item).ty() { + Some(ty) => ty.span, + _ => tcx.def_span(item), + }; + collector.visit_spanned(span, tcx.type_of(item).subst_identity()); } - DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect( - tcx, - item, - ty::Binder::dummy(tcx.type_of(item).subst_identity()), - ), _ => unreachable!(), - }; - tcx.arena.alloc_from_iter(defined_opaques) + } + tcx.arena.alloc_from_iter(collector.opaques) } DefKind::Mod | DefKind::Struct @@ -189,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure - | DefKind::Generator => &[], + | DefKind::Generator => { + span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent") + } } } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 86ea154a886..7437722fd06 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -238,7 +238,7 @@ impl fmt::Debug for c_void { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), + all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", target_arch = "asmjs", target_os = "uefi", @@ -267,7 +267,7 @@ pub struct VaListImpl<'f> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), + all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", target_arch = "asmjs", target_os = "uefi", @@ -292,7 +292,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> { /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf #[cfg(all( target_arch = "aarch64", - not(any(target_os = "macos", target_os = "ios")), + not(any(target_os = "macos", target_os = "ios", target_os = "tvos")), not(target_os = "uefi"), not(windows), ))] @@ -389,7 +389,10 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), + all( + target_arch = "aarch64", + any(target_os = "macos", target_os = "ios", target_os = "tvos") + ), target_family = "wasm", target_arch = "asmjs", target_os = "uefi", @@ -404,7 +407,10 @@ pub struct VaList<'a, 'f: 'a> { target_arch = "s390x", target_arch = "x86_64" ), - any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), + any( + not(target_arch = "aarch64"), + not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) + ), not(target_family = "wasm"), not(target_arch = "asmjs"), not(target_os = "uefi"), @@ -422,7 +428,7 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "s390x"), not(target_arch = "x86_64") ), - all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), + all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", target_arch = "asmjs", target_os = "uefi", @@ -449,7 +455,10 @@ impl<'f> VaListImpl<'f> { target_arch = "s390x", target_arch = "x86_64" ), - any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), + any( + not(target_arch = "aarch64"), + not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) + ), not(target_family = "wasm"), not(target_arch = "asmjs"), not(target_os = "uefi"), diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 052fd34d0b6..48a6eb03b5e 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -32,7 +32,8 @@ use crate::ptr; /// * The memory referenced by the returned slice must not be mutated for the duration /// of lifetime `'a`, except inside an `UnsafeCell`. /// -/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`. +/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// # Caveat @@ -125,7 +126,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// (not derived from the return value) for the duration of lifetime `'a`. /// Both read and write accesses are forbidden. /// -/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`. +/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// [valid]: ptr#safety @@ -179,15 +181,16 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] { /// the last element, such that the offset from the end to the start pointer is /// the length of the slice. /// -/// * The range must contain `N` consecutive properly initialized values of type `T`: +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// * The range must contain `N` consecutive properly initialized values of type `T`. /// /// * The memory referenced by the returned slice must not be mutated for the duration /// of lifetime `'a`, except inside an `UnsafeCell`. /// -/// * The total length of the range must be no larger than `isize::MAX`. +/// * The total length of the range must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements. @@ -247,16 +250,17 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { /// the last element, such that the offset from the end to the start pointer is /// the length of the slice. /// -/// * The range must contain `N` consecutive properly initialized values of type `T`: +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// * The range must contain `N` consecutive properly initialized values of type `T`. /// /// * The memory referenced by the returned slice must not be accessed through any other pointer /// (not derived from the return value) for the duration of lifetime `'a`. /// Both read and write accesses are forbidden. /// -/// * The total length of the range must be no larger than `isize::MAX`. +/// * The total length of the range must be no larger than `isize::MAX`, +/// and adding that size to `data` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements. diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index af74efa6bf8..aaaa88624f0 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.92" } +compiler_builtins = { version = "0.1.93" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/build.rs b/library/std/build.rs index d0b37940936..ddf6e84d8d0 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -18,6 +18,7 @@ fn main() { || target.contains("illumos") || target.contains("apple-darwin") || target.contains("apple-ios") + || target.contains("apple-tvos") || target.contains("apple-watchos") || target.contains("uwp") || target.contains("windows") @@ -48,7 +49,6 @@ fn main() { // - mipsel-sony-psp // - nvptx64-nvidia-cuda // - arch=avr - // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) // - JSON targets // - Any new targets that have not been explicitly added above. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index e2480bcbbc7..9ff01b9c35d 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1640,6 +1640,10 @@ fn test_file_times() { use crate::os::ios::fs::FileTimesExt; #[cfg(target_os = "macos")] use crate::os::macos::fs::FileTimesExt; + #[cfg(target_os = "tvos")] + use crate::os::tvos::fs::FileTimesExt; + #[cfg(target_os = "tvos")] + use crate::os::tvos::fs::FileTimesExt; #[cfg(target_os = "watchos")] use crate::os::watchos::fs::FileTimesExt; #[cfg(windows)] @@ -1651,9 +1655,21 @@ fn test_file_times() { let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); times = times.set_accessed(accessed).set_modified(modified); - #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any( + windows, + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "tvos", + ))] let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); - #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any( + windows, + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "tvos", + ))] { times = times.set_created(created); } @@ -1678,7 +1694,13 @@ fn test_file_times() { let metadata = file.metadata().unwrap(); assert_eq!(metadata.accessed().unwrap(), accessed); assert_eq!(metadata.modified().unwrap(), modified); - #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any( + windows, + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "tvos", + ))] { assert_eq!(metadata.created().unwrap(), created); } diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 6d4d54b7c78..b319527a541 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -6,7 +6,7 @@ use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; use crate::time::SystemTime; #[allow(deprecated)] -use crate::os::ios::raw; +use super::raw; /// OS-specific extensions to [`fs::Metadata`]. /// diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 5b54cc5f2e4..634c3cc4a15 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -137,6 +137,9 @@ pub mod redox; pub mod solaris; #[cfg(target_os = "solid_asp3")] pub mod solid; +#[cfg(target_os = "tvos")] +#[path = "ios/mod.rs"] +pub(crate) mod tvos; #[cfg(target_os = "vita")] pub mod vita; #[cfg(target_os = "vxworks")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 6fe1111188a..401ec1e7a01 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -73,6 +73,8 @@ mod platform { pub use crate::os::redox::*; #[cfg(target_os = "solaris")] pub use crate::os::solaris::*; + #[cfg(target_os = "tvos")] + pub use crate::os::tvos::*; #[cfg(target_os = "vita")] pub use crate::os::vita::*; #[cfg(target_os = "vxworks")] @@ -96,6 +98,7 @@ pub mod thread; target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "macos", target_os = "netbsd", diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index bf2a51b5edb..e20170873bb 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -11,6 +11,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "netbsd", @@ -30,6 +31,7 @@ use crate::time::Duration; target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "netbsd", @@ -238,6 +240,7 @@ impl UnixStream { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "netbsd", diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs index 95967eac295..6a0cc2d2c48 100644 --- a/library/std/src/os/unix/ucred.rs +++ b/library/std/src/os/unix/ucred.rs @@ -36,7 +36,7 @@ pub use self::impl_linux::peer_cred; ))] pub use self::impl_bsd::peer_cred; -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub use self::impl_mac::peer_cred; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -98,7 +98,7 @@ pub mod impl_bsd { } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub mod impl_mac { use super::UCred; use crate::os::unix::io::AsRawFd; diff --git a/library/std/src/os/unix/ucred/tests.rs b/library/std/src/os/unix/ucred/tests.rs index e63a2fc248e..dd99ecdd819 100644 --- a/library/std/src/os/unix/ucred/tests.rs +++ b/library/std/src/os/unix/ucred/tests.rs @@ -8,6 +8,7 @@ use libc::{getegid, geteuid, getpid}; target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "openbsd" @@ -26,7 +27,13 @@ fn test_socket_pair() { } #[test] -#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos", target_os = "watchos"))] +#[cfg(any( + target_os = "linux", + target_os = "ios", + target_os = "macos", + target_os = "watchos", + target_os = "tvos", +))] fn test_socket_pair_pids(arg: Type) -> RetType { // Create two connected sockets and get their peer credentials. let (sock_a, sock_b) = UnixStream::pair().unwrap(); diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs index 82edb11cbd1..6552d96ca69 100644 --- a/library/std/src/personality/gcc.rs +++ b/library/std/src/personality/gcc.rs @@ -85,7 +85,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c cfg_if::cfg_if! { - if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "watchos"), not(target_os = "netbsd")))] { + if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] { // ARM EHABI personality routine. // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf // diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index 0e0c87d1c74..71ff4237d00 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -347,8 +347,8 @@ pub struct Sender<T> { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: Send> Send for Sender<T> {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<T> !Sync for Sender<T> {} +#[stable(feature = "mpsc_sender_sync", since = "CURRENT_RUSTC_VERSION")] +unsafe impl<T: Send> Sync for Sender<T> {} /// The sending-half of Rust's synchronous [`sync_channel`] type. /// diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 0efe2570d67..f8fa81e6ef1 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -168,7 +168,7 @@ mod imp { } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] mod imp { use super::Args; use crate::ffi::CStr; @@ -209,7 +209,7 @@ mod imp { // for i in (0..[args count]) // res.push([args objectAtIndex:i]) // res - #[cfg(any(target_os = "ios", target_os = "watchos"))] + #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub fn args() -> Args { use crate::ffi::OsString; use crate::mem; diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index 8c3ef88d8f8..929e9dae738 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -31,6 +31,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "tvos")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "tvos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "watchos")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 69c93c92003..85e020ae413 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -44,6 +44,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize; target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "macos", target_os = "netbsd", target_os = "openbsd", @@ -69,6 +70,7 @@ const fn max_iov() -> usize { target_os = "emscripten", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "netbsd", @@ -181,6 +183,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "illumos", target_os = "ios", + target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "netbsd", @@ -222,6 +225,7 @@ impl FileDesc { #[cfg(any( all(target_os = "android", target_pointer_width = "32"), target_os = "ios", + target_os = "tvos", target_os = "macos", ))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { @@ -320,6 +324,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "illumos", target_os = "ios", + target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "netbsd", @@ -361,6 +366,7 @@ impl FileDesc { #[cfg(any( all(target_os = "android", target_pointer_width = "32"), target_os = "ios", + target_os = "tvos", target_os = "macos", ))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index d2fb6238387..9cf5cfcc8d5 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -32,6 +32,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; all(target_os = "linux", target_env = "gnu"), target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", ))] use crate::sys::weak::syscall; @@ -43,6 +44,7 @@ use libc::{c_int, mode_t}; #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "solaris", all(target_os = "linux", target_env = "gnu") @@ -360,7 +362,7 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<SystemTime>, modified: Option<SystemTime>, - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] created: Option<SystemTime>, } @@ -519,6 +521,7 @@ impl FileAttr { target_os = "openbsd", target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", ))] pub fn created(&self) -> io::Result<SystemTime> { @@ -530,6 +533,7 @@ impl FileAttr { target_os = "openbsd", target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "vita", )))] @@ -611,7 +615,7 @@ impl FileTimes { self.modified = Some(t); } - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] pub fn set_created(&mut self, t: SystemTime) { self.created = Some(t); } @@ -895,6 +899,7 @@ impl DirEntry { #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "linux", target_os = "emscripten", @@ -928,6 +933,7 @@ impl DirEntry { #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "netbsd", target_os = "openbsd", @@ -946,6 +952,7 @@ impl DirEntry { #[cfg(not(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "netbsd", target_os = "openbsd", @@ -1107,11 +1114,21 @@ impl File { cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?; return Ok(()); - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + ))] unsafe fn os_fsync(fd: c_int) -> c_int { libc::fcntl(fd, libc::F_FULLFSYNC) } - #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))] + #[cfg(not(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + )))] unsafe fn os_fsync(fd: c_int) -> c_int { libc::fsync(fd) } @@ -1121,7 +1138,12 @@ impl File { cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?; return Ok(()); - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + ))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fcntl(fd, libc::F_FULLFSYNC) } @@ -1140,6 +1162,7 @@ impl File { target_os = "android", target_os = "freebsd", target_os = "ios", + target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "netbsd", @@ -1249,7 +1272,7 @@ impl File { io::ErrorKind::Unsupported, "setting file times not supported", )) - } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] { + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] { let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3]; let mut num_times = 0; let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; @@ -1709,6 +1732,7 @@ fn open_to_and_set_permissions( target_os = "android", target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", )))] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { @@ -1736,7 +1760,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { use crate::sync::atomic::{AtomicBool, Ordering}; diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs index 192fa216dfa..2dc1b0c601e 100644 --- a/library/std/src/sys/unix/locks/pthread_condvar.rs +++ b/library/std/src/sys/unix/locks/pthread_condvar.rs @@ -32,6 +32,7 @@ impl LazyInit for AllocatedCondvar { if #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "l4re", target_os = "android", @@ -124,6 +125,7 @@ impl Condvar { #[cfg(not(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "android", target_os = "espidf", @@ -158,6 +160,7 @@ impl Condvar { #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "android", target_os = "espidf", diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 24566d96bcd..1b72e21a832 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -87,6 +87,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // The poll on Darwin doesn't set POLLNVAL for closed fds. target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "redox", target_os = "l4re", @@ -387,7 +388,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "macos")] { #[link(name = "System")] extern "C" {} - } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] { + } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] { #[link(name = "System")] #[link(name = "objc")] #[link(name = "Security", kind = "framework")] diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 8edfd331304..a68c14758ff 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -63,7 +63,13 @@ extern "C" { #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] #[cfg_attr( - any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"), + any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "freebsd", + target_os = "watchos" + ), link_name = "__error" )] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] @@ -375,7 +381,7 @@ pub fn current_exe() -> io::Result<PathBuf> { Ok(PathBuf::from(OsString::from_vec(e))) } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub fn current_exe() -> io::Result<PathBuf> { unsafe { let mut sz: u32 = 0; @@ -609,6 +615,7 @@ pub fn home_dir() -> Option<PathBuf> { #[cfg(any( target_os = "android", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "emscripten", target_os = "redox", @@ -623,6 +630,7 @@ pub fn home_dir() -> Option<PathBuf> { #[cfg(not(any( target_os = "android", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "emscripten", target_os = "redox", diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 22d9d6141f4..129e7643661 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall; #[cfg(any( target_os = "macos", + target_os = "watchos", + target_os = "tvos", target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), @@ -28,7 +30,12 @@ use libc::RTP_ID as pid_t; #[cfg(not(target_os = "vxworks"))] use libc::{c_int, pid_t}; -#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))] +#[cfg(not(any( + target_os = "vxworks", + target_os = "l4re", + target_os = "tvos", + target_os = "watchos", +)))] use libc::{gid_t, uid_t}; cfg_if::cfg_if! { @@ -84,7 +91,6 @@ impl Command { if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? { return Ok((ret, ours)); } - let (input, output) = sys::pipe::anon_pipe()?; // Whatever happens after the fork is almost for sure going to touch or @@ -166,9 +172,31 @@ impl Command { crate::sys_common::process::wait_with_output(proc, pipes) } + // WatchOS and TVOS headers mark the `fork`/`exec*` functions with + // `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the + // `posix_spawn*` functions should be used instead. It isn't entirely clear + // what `PROHIBITED` means here (e.g. if calls to these functions are + // allowed to exist in dead code), but it sounds bad, so we go out of our + // way to avoid that all-together. + #[cfg(any(target_os = "tvos", target_os = "watchos"))] + const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!( + ErrorKind::Unsupported, + "`fork`+`exec`-based process spawning is not supported on this target", + ); + + #[cfg(any(target_os = "tvos", target_os = "watchos"))] + unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { + return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC); + } + // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, -1)) in the parent. - #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))] + #[cfg(not(any( + target_os = "linux", + target_os = "watchos", + target_os = "tvos", + all(target_os = "nto", target_env = "nto71"), + )))] unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { cvt(libc::fork()).map(|res| (res, -1)) } @@ -339,6 +367,7 @@ impl Command { // allocation). Instead we just close it manually. This will never // have the drop glue anyway because this code never returns (the // child will either exec() or invoke libc::exit) + #[cfg(not(any(target_os = "tvos", target_os = "watchos")))] unsafe fn do_exec( &mut self, stdio: ChildPipes, @@ -445,8 +474,19 @@ impl Command { Err(io::Error::last_os_error()) } + #[cfg(any(target_os = "tvos", target_os = "watchos"))] + unsafe fn do_exec( + &mut self, + _stdio: ChildPipes, + _maybe_envp: Option<&CStringArray>, + ) -> Result<!, io::Error> { + return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC); + } + #[cfg(not(any( target_os = "macos", + target_os = "tvos", + target_os = "watchos", target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), @@ -464,6 +504,9 @@ impl Command { // directly. #[cfg(any( target_os = "macos", + // FIXME: `target_os = "ios"`? + target_os = "tvos", + target_os = "watchos", target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), @@ -550,7 +593,7 @@ impl Command { } let addchdir = match self.get_cwd() { Some(cwd) => { - if cfg!(target_os = "macos") { + if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) { // There is a bug in macOS where a relative executable // path like "../myprogram" will cause `posix_spawn` to // successfully launch the program, but erroneously return diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index d8b63546b9e..d471be33ed5 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { unix, not(target_os = "macos"), not(target_os = "ios"), + not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "openbsd"), not(target_os = "freebsd"), @@ -198,7 +199,7 @@ mod imp { // once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is // only used on iOS where direct access to `/dev/urandom` is blocked by the // sandbox. -#[cfg(any(target_os = "ios", target_os = "watchos"))] +#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] mod imp { use crate::io; use crate::ptr; diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 010015667f7..893f8b8df3f 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -150,7 +150,7 @@ impl Thread { } } - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] pub fn set_name(name: &CStr) { unsafe { let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name); @@ -283,7 +283,13 @@ impl Drop for Thread { } } -#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", +))] fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { let mut result = [0; MAX_WITH_NUL]; for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) { @@ -299,6 +305,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> { target_os = "emscripten", target_os = "fuchsia", target_os = "ios", + target_os = "tvos", target_os = "linux", target_os = "macos", target_os = "solaris", diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs index 8bf4bae7a3f..ae805d84399 100644 --- a/library/std/src/sys/unix/thread_parking/pthread.rs +++ b/library/std/src/sys/unix/thread_parking/pthread.rs @@ -46,6 +46,7 @@ unsafe fn wait_timeout( #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "espidf", target_os = "horizon", @@ -73,6 +74,7 @@ unsafe fn wait_timeout( #[cfg(not(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "espidf", target_os = "horizon", @@ -120,6 +122,7 @@ impl Parker { if #[cfg(any( target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos", target_os = "l4re", target_os = "android", diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index a9fbc7ab108..17b4130c202 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -219,7 +219,8 @@ impl From<__timespec64> for Timespec { #[cfg(any( all(target_os = "macos", any(not(target_arch = "aarch64"))), target_os = "ios", - target_os = "watchos" + target_os = "watchos", + target_os = "tvos" ))] mod inner { use crate::sync::atomic::{AtomicU64, Ordering}; @@ -339,7 +340,8 @@ mod inner { #[cfg(not(any( all(target_os = "macos", any(not(target_arch = "aarch64"))), target_os = "ios", - target_os = "watchos" + target_os = "watchos", + target_os = "tvos" )))] mod inner { use crate::fmt; diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index 62ffee70bec..61088ff16ed 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -28,7 +28,7 @@ use crate::ptr; use crate::sync::atomic::{self, AtomicPtr, Ordering}; // We can use true weak linkage on ELF targets. -#[cfg(not(any(target_os = "macos", target_os = "ios")))] +#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))] pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { @@ -43,7 +43,7 @@ pub(crate) macro weak { } // On non-ELF targets, use the dlsym approximation of weak linkage. -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))] pub(crate) use self::dlsym as weak; pub(crate) struct ExternWeak<F: Copy> { diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 652c695fc57..2976a9f578e 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -18,7 +18,7 @@ use crate::ffi::{c_int, c_void}; cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", target_os = "watchos", + target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "openbsd", target_os = "netbsd", target_os = "illumos", target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index b65e2572cc5..5d6b9e94ee9 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -42,6 +42,7 @@ fn test_named_thread() { all(target_os = "linux", target_env = "gnu"), target_os = "macos", target_os = "ios", + target_os = "tvos", target_os = "watchos" ))] #[test] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index f6a68073b2f..ec24e137572 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -117,7 +117,7 @@ extern "C" { } cfg_if::cfg_if! { -if #[cfg(any(target_os = "ios", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] { +if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] { // Not ARM EHABI #[repr(C)] #[derive(Copy, Clone, PartialEq)] diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 06f479808b9..cb40521dda7 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -54,9 +54,9 @@ impl Config { /// Runs a command, printing out nice contextual information if it fails. /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. - pub(crate) fn try_run(&self, cmd: &mut Command) -> bool { + pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> { if self.dry_run() { - return true; + return Ok(()); } self.verbose(&format!("running: {:?}", cmd)); try_run(cmd, self.is_verbose()) @@ -156,12 +156,14 @@ impl Config { ]; } "; - nix_build_succeeded = self.try_run(Command::new("nix-build").args(&[ - Path::new("-E"), - Path::new(NIX_EXPR), - Path::new("-o"), - &nix_deps_dir, - ])); + nix_build_succeeded = self + .try_run(Command::new("nix-build").args(&[ + Path::new("-E"), + Path::new(NIX_EXPR), + Path::new("-o"), + &nix_deps_dir, + ])) + .is_ok(); nix_deps_dir }); if !nix_build_succeeded { @@ -186,7 +188,7 @@ impl Config { patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]); } - self.try_run(patchelf.arg(fname)); + self.try_run(patchelf.arg(fname)).unwrap(); } fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { @@ -237,7 +239,7 @@ impl Config { "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"), ), - ])) { + ])).is_err() { return; } eprintln!("\nspurious failure, trying again"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d7e77aeb338..d389b568f56 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -333,7 +333,7 @@ forward! { create(path: &Path, s: &str), remove(f: &Path), tempdir() -> PathBuf, - try_run(cmd: &mut Command) -> bool, + try_run(cmd: &mut Command) -> Result<(), ()>, llvm_link_shared() -> bool, download_rustc() -> bool, initial_rustfmt() -> Option<PathBuf>, @@ -614,11 +614,13 @@ impl Build { } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). - let has_local_modifications = !self.try_run( - Command::new("git") - .args(&["diff-index", "--quiet", "HEAD"]) - .current_dir(&absolute_path), - ); + let has_local_modifications = self + .try_run( + Command::new("git") + .args(&["diff-index", "--quiet", "HEAD"]) + .current_dir(&absolute_path), + ) + .is_err(); if has_local_modifications { self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path)); } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index ec01f744b82..c97b7592737 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -27,7 +27,8 @@ impl Step for ExpandYamlAnchors { try_run( builder, &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -39,17 +40,17 @@ impl Step for ExpandYamlAnchors { } } -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { +fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { if !builder.fail_fast { - if !builder.try_run(cmd) { + if let Err(e) = builder.try_run(cmd) { let mut failures = builder.delayed_failures.borrow_mut(); failures.push(format!("{:?}", cmd)); - return false; + return Err(e); } } else { builder.run(cmd); } - true + Ok(()) } #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9212362f6c9..873ed61daf3 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -48,17 +48,17 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ // build for, so there is no entry for "aarch64-apple-darwin" here. ]; -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { +fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { if !builder.fail_fast { - if !builder.try_run(cmd) { + if let Err(e) = builder.try_run(cmd) { let mut failures = builder.delayed_failures.borrow_mut(); failures.push(format!("{:?}", cmd)); - return false; + return Err(e); } } else { builder.run(cmd); } - true + Ok(()) } fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool { @@ -187,7 +187,8 @@ You can skip linkcheck with --exclude src/tools/linkchecker" try_run( builder, builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -240,7 +241,8 @@ impl Step for HtmlCheck { builder.default_doc(&[]); builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder)); - try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))); + try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))) + .unwrap(); } } @@ -286,7 +288,8 @@ impl Step for Cargotest { .args(builder.config.test_args()) .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)), - ); + ) + .unwrap(); } } @@ -785,7 +788,7 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder, compiler); let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder); - if builder.try_run(&mut cargo) { + if builder.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. return; } @@ -858,7 +861,7 @@ impl Step for RustdocTheme { util::lld_flag_no_threads(self.compiler.host.contains("windows")), ); } - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); } } @@ -1109,7 +1112,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` } builder.info("tidy check"); - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); builder.ensure(ExpandYamlAnchors); @@ -1157,7 +1160,8 @@ impl Step for ExpandYamlAnchors { try_run( builder, &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -1936,7 +1940,7 @@ impl BookTest { compiler.host, ); let _time = util::timeit(&builder); - let toolstate = if try_run(builder, &mut rustbook_cmd) { + let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() { ToolState::TestPass } else { ToolState::TestFail @@ -2094,7 +2098,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> cmd.arg("--test-args").arg(test_args); if builder.config.verbose_tests { - try_run(builder, &mut cmd) + try_run(builder, &mut cmd).is_ok() } else { try_run_quiet(builder, &mut cmd) } @@ -2122,7 +2126,7 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) { + let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() { ToolState::TestPass } else { ToolState::TestFail @@ -2661,7 +2665,7 @@ impl Step for Bootstrap { fn run(self, builder: &Builder<'_>) { let mut check_bootstrap = Command::new(&builder.python()); check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/")); - try_run(builder, &mut check_bootstrap); + try_run(builder, &mut check_bootstrap).unwrap(); let host = builder.config.build; let compiler = builder.compiler(0, host); @@ -2733,7 +2737,7 @@ impl Step for TierCheck { } builder.info("platform support check"); - try_run(builder, &mut cargo.into()); + try_run(builder, &mut cargo.into()).unwrap(); } } @@ -2813,7 +2817,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 96341b69df0..126f0b1eb31 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -107,7 +107,7 @@ impl Step for ToolBuild { ); let mut cargo = Command::from(cargo); - let is_expected = builder.try_run(&mut cargo); + let is_expected = builder.try_run(&mut cargo).is_ok(); builder.save_toolstate( tool, diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 1ec49f80d63..b291584b300 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -228,7 +228,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>( } pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { - if !try_run(cmd, print_cmd_on_fail) { + if try_run(cmd, print_cmd_on_fail).is_err() { crate::detail_exit_macro!(1); } } diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 2b0431a159b..1e17a90a842 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -16,6 +16,7 @@ - [Target Tier Policy](target-tier-policy.md) - [Template for Target-specific Documentation](platform-support/TEMPLATE.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) + - [\*-apple-tvos](platform-support/apple-tvos.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f69dcd5983d..62f628f8229 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -214,7 +214,7 @@ host tools. target | std | host | notes -------|:---:|:----:|------- `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 -`aarch64-apple-tvos` | * | | ARM64 tvOS +[`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS [`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS Simulator [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon @@ -316,7 +316,7 @@ target | std | host | notes `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 -`x86_64-apple-tvos` | * | | x86 64-bit tvOS +[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md new file mode 100644 index 00000000000..d87fd1959b4 --- /dev/null +++ b/src/doc/rustc/src/platform-support/apple-tvos.md @@ -0,0 +1,85 @@ +# `*-apple-tvos` +- aarch64-apple-tvos +- x86_64-apple-tvos + +**Tier: 3** + +Apple tvOS targets: +- Apple tvOS on aarch64 +- Apple tvOS Simulator on x86_64 + +## Target maintainers + +* [@thomcc](https://github.com/thomcc) + +## Requirements + +These targets are cross-compiled. You will need appropriate versions of Xcode +and the SDKs for tvOS (`AppleTVOS.sdk`) and/or the tvOS Simulator +(`AppleTVSimulator.sdk`) to build a toolchain and target these platforms. + +The targets support most (see below) of the standard library including the +allocator to the best of my knowledge, however they are very new, not yet +well-tested, and it is possible that there are various bugs. + +In theory we support back to tvOS version 7.0, although the actual minimum +version you can target may be newer than this, for example due to the versions +of Xcode and your SDKs. + +As with the other Apple targets, `rustc` respects the common environment +variables used by Xcode to configure this, in this case +`TVOS_DEPLOYMENT_TARGET`. + +#### Incompletely supported library functionality + +As mentioned, "most" of the standard library is supported, which means that some portions +are known to be unsupported. The following APIs are currently known to have +missing or incomplete support: + +- `std::process::Command`'s API will return an error if it is configured in a + manner which cannot be performed using `posix_spawn` -- this is because the + more flexible `fork`/`exec`-based approach is prohibited on these platforms in + favor of `posix_spawn{,p}` (which still probably will get you rejected from + app stores, so is likely sideloading-only). A concrete set of cases where this + will occur is difficult to enumerate (and would quickly become stale), but in + some cases it may be worked around by tweaking the manner in which `Command` + is invoked. + +## Building the target + +The targets can be built by enabling them for a `rustc` build in `config.toml`, by adding, for example: + +```toml +[build] +build-stage = 1 +target = ["aarch64-apple-tvos", "x86_64-apple-tvos"] +``` + +It's possible that cargo under `-Zbuild-std` may also be used to target them. + +## Building Rust programs + +*Note: Building for this target requires the corresponding TVOS SDK, as provided by Xcode.* + +Rust programs can be built for these targets + +```text +$ rustc --target aarch64-apple-tvos your-code.rs +... +$ rustc --target x86_64-apple-tvos your-code.rs +``` + +## Testing + +There is no support for running the Rust or standard library testsuite on tvOS +or the simulators at the moment. Testing has mostly been done manually with +builds of static libraries called from Xcode or a simulator. + +It hopefully will be possible to improve this in the future. + +## Cross-compilation toolchains and C code + +This target can be cross-compiled from x86_64 or aarch64 macOS hosts. + +Other hosts are not supported for cross-compilation, but might work when also +providing the required Xcode SDK. diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index adb73a7eef6..75013bb3df9 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -16,9 +16,21 @@ Rust code has similar formatting, less mental effort is required to comprehend a new project, lowering the barrier to entry for new developers. Thus, there are productivity benefits to using a formatting tool (such as -rustfmt), and even larger benefits by using a community-consistent formatting, -typically by using a formatting tool's default settings. +`rustfmt`), and even larger benefits by using a community-consistent +formatting, typically by using a formatting tool's default settings. +## The default Rust style + +The Rust Style Guide defines the default Rust style, and *recommends* that +developers and tools follow the default Rust style. Tools such as `rustfmt` use +the style guide as a reference for the default style. Everything in this style +guide, whether or not it uses language such as "must" or the imperative mood +such as "insert a space ..." or "break the line after ...", refers to the +default style. + +This should not be interpreted as forbidding developers from following a +non-default style, or forbidding tools from adding any particular configuration +options. ## Formatting conventions @@ -28,8 +40,47 @@ typically by using a formatting tool's default settings. * Each level of indentation must be four spaces (that is, all indentation outside of string literals and comments must be a multiple of four). * The maximum width for a line is 100 characters. -* A tool should be configurable for all three of these variables. +* A tool may choose to make some of these configurable. + +#### Block indent + +Prefer block indent over visual indent: + +```rust +// Block indent +a_function_call( + foo, + bar, +); + +// Visual indent +a_function_call(foo, + bar); +``` +This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above +example) and less rightward drift. + +### Trailing commas + +Lists should have a trailing comma when followed by a newline: + +```rust +function_call( + argument, + another_argument, +); + +let array = [ + element, + another_element, + yet_another_element, +]; +``` + +This makes moving code (e.g., by copy and paste) easier, and makes diffs +smaller, as appending or removing items does not require modifying another line +to add or remove a comma. ### Blank lines @@ -48,11 +99,7 @@ fn bar() {} fn baz() {} ``` -Formatting tools should make the bounds on blank lines configurable: there -should be separate minimum and maximum numbers of newlines between both -statements and (top-level) items (i.e., four options). As described above, the -defaults for both statements and items should be minimum: 1, maximum: 2. - +Formatting tools may wish to make the bounds on blank lines configurable. ### [Module-level items](items.md) ### [Statements](statements.md) diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md index 004692fa6a2..59fe9fdc669 100644 --- a/src/doc/style-guide/src/SUMMARY.md +++ b/src/doc/style-guide/src/SUMMARY.md @@ -2,10 +2,10 @@ [Introduction](README.md) -- [Module-level items](items.md) +- [Items](items.md) - [Statements](statements.md) - [Expressions](expressions.md) -- [Types](types.md) -- [Non-formatting conventions](advice.md) +- [Types and Bounds](types.md) +- [Other style advice](advice.md) - [`Cargo.toml` conventions](cargo.md) -- [Principles used for deciding these guidelines](principles.md) +- [Guiding principles and rationale](principles.md) diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md index ab4b92b0a24..9a617be509c 100644 --- a/src/doc/style-guide/src/advice.md +++ b/src/doc/style-guide/src/advice.md @@ -25,9 +25,9 @@ if y { * Local variables shall be `snake_case`, * Macro names shall be `snake_case`, * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. - * When a name is forbidden because it is a reserved word (e.g., `crate`), use a - trailing underscore to make the name legal (e.g., `crate_`), or use raw - identifiers if possible. + * When a name is forbidden because it is a reserved word (such as `crate`), + either use a raw identifier (`r#crate`) or use a trailing underscore + (`crate_`). Don't misspell the word (`krate`). ### Modules diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md index 13b96ca8c5e..d3b67ae4582 100644 --- a/src/doc/style-guide/src/cargo.md +++ b/src/doc/style-guide/src/cargo.md @@ -1,4 +1,4 @@ -# Cargo.toml conventions +# `Cargo.toml` conventions ## Formatting conventions @@ -25,16 +25,17 @@ not indent any key names; start all key names at the start of a line. Use multi-line strings (rather than newline escape sequences) for any string values that include multiple lines, such as the crate description. -For array values, such as a list of authors, put the entire list on the same +For array values, such as a list of features, put the entire list on the same line as the key, if it fits. Otherwise, use block indentation: put a newline after the opening square bracket, indent each item by one indentation level, put a comma after each item (including the last), and put the closing square bracket at the start of a line by itself after the last item. ```rust -authors = [ - "A Uthor <a.uthor@example.org>", - "Another Author <author@example.net>", +some_feature = [ + "another_feature", + "yet_another_feature", + "some_dependency?/some_feature", ] ``` @@ -54,11 +55,11 @@ version = "4.5.6" ## Metadata conventions -The authors list should consist of strings that each contain an author name -followed by an email address in angle brackets: `Full Name <email@address>`. -It should not contain bare email addresses, or names without email addresses. -(The authors list may also include a mailing list address without an associated -name.) +The authors list, if present, should consist of strings that each contain an +author name followed by an email address in angle brackets: `Full Name +<email@address>`. It should not contain bare email addresses, or names without +email addresses. (The authors list may also include a mailing list address +without an associated name.) The license field must contain a valid [SPDX expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60), diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 96f66c89c25..8271b42da4c 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -690,7 +690,7 @@ Where it is possible to use a block form on the right-hand side and avoid breaking the left-hand side, do that. E.g. ```rust - // Assuming the following line does done fit in the max width + // Assuming the following line does not fit in the max width a_very_long_pattern | another_pattern => ALongStructName { ... }, diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 2835975355f..1e0e60248bf 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -1,5 +1,10 @@ ## Items +Items consist of the set of things permitted at the top level of a module. +However, Rust also allows some items to appear within some other types of +items, such as within a function. The same formatting conventions apply whether +an item appears at module level or within another item. + `extern crate` statements must be first in a file. They must be ordered alphabetically. @@ -15,8 +20,8 @@ Tools should make the above ordering optional. ### Function definitions -In Rust, one finds functions by searching for `fn [function-name]`; It's -important that you style your code so that it's very searchable in this way. +In Rust, people often find functions by searching for `fn [function-name]`, so +the formatting of function definitions shold enable this. The proper ordering and spacing is: @@ -63,8 +68,9 @@ let y = (11, 22, 33); In the declaration, put each variant on its own line, block indented. -Format each variant accordingly as either a struct, tuple struct, or identifier, -which doesn't require special formatting (but without the `struct` keyword. +Format each variant accordingly as either a struct (but without the `struct` +keyword), a tuple struct, or an identifier (which doesn't require special +formatting): ```rust enum FooBar { @@ -139,7 +145,7 @@ union Foo { Put the whole struct on one line if possible. Types in the parentheses should be separated by a comma and space with no trailing comma. No spaces around the -parentheses or semi-colon: +parentheses or semicolon: ```rust pub struct Foo(String, u8); @@ -230,7 +236,7 @@ impl Bar `extern crate foo;` -Use spaces around keywords, no spaces around the semi-colon. +Use spaces around keywords, no spaces around the semicolon. ### Modules @@ -245,7 +251,7 @@ mod foo; ``` Use spaces around keywords and before the opening brace, no spaces around the -semi-colon. +semicolon. ### macro\_rules! @@ -478,8 +484,8 @@ foo::{ A *group* of imports is a set of imports on the same or sequential lines. One or more blank lines or other items (e.g., a function) separate groups of imports. -Within a group of imports, imports must be sorted ascii-betically. Groups of -imports must not be merged or re-ordered. +Within a group of imports, imports must be sorted ASCIIbetically (uppercase +before lowercase). Groups of imports must not be merged or re-ordered. E.g., input: @@ -505,13 +511,9 @@ use b; Because of `macro_use`, attributes must also start a new group and prevent re-ordering. -Note that tools which only have access to syntax (such as Rustfmt) cannot tell -which imports are from an external crate or the std lib, etc. - - #### Ordering list import -Names in a list import must be sorted ascii-betically, but with `self` and +Names in a list import must be sorted ASCIIbetically, but with `self` and `super` first, and groups and glob imports last. This applies recursively. For example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g., `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`. diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md index 2d203f264e6..d548693e39e 100644 --- a/src/doc/style-guide/src/principles.md +++ b/src/doc/style-guide/src/principles.md @@ -1,7 +1,7 @@ # Guiding principles and rationale -When deciding on style guidelines, the style team tried to be guided by the -following principles (in rough priority order): +When deciding on style guidelines, the style team follows these guiding +principles (in rough priority order): * readability - scan-ability @@ -19,35 +19,11 @@ following principles (in rough priority order): * specifics - compatibility with version control practices - preserving diffs, merge-friendliness, etc. - - preventing right-ward drift + - preventing rightward drift - minimising vertical space * application - ease of manual application - - ease of implementation (in Rustfmt, and in other tools/editors/code generators) + - ease of implementation (in `rustfmt`, and in other tools/editors/code generators) - internal consistency - simplicity of formatting rules - - -## Overarching guidelines - -Prefer block indent over visual indent. E.g., - -```rust -// Block indent -a_function_call( - foo, - bar, -); - -// Visual indent -a_function_call(foo, - bar); -``` - -This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above -example) and less rightward drift. - -Lists should have a trailing comma when followed by a newline, see the block -indent example above. This choice makes moving code (e.g., by copy and paste) -easier and makes smaller diffs. diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index b6708e6c72a..9bc521e1c7b 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -1,7 +1,9 @@ +## Statements + ### Let statements There should be spaces after the `:` and on both sides of the `=` (if they are -present). No space before the semi-colon. +present). No space before the semicolon. ```rust // A comment. @@ -213,7 +215,7 @@ fn main() { ### Macros in statement position A macro use in statement position should use parentheses or square brackets as -delimiters and should be terminated with a semi-colon. There should be no spaces +delimiters and should be terminated with a semicolon. There should be no spaces between the name, `!`, the delimiters, or the `;`. ```rust @@ -224,13 +226,13 @@ a_macro!(...); ### Expressions in statement position -There should be no space between the expression and the semi-colon. +There should be no space between the expression and the semicolon. ``` <expr>; ``` -All expressions in statement position should be terminated with a semi-colon, +All expressions in statement position should be terminated with a semicolon, unless they end with a block or are used as the value for a block. E.g., @@ -248,7 +250,7 @@ loop { } ``` -Use a semi-colon where an expression has void type, even if it could be +Use a semicolon where an expression has void type, even if it could be propagated. E.g., ```rust diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index eade9e04559..5ab1874e9ed 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -110,6 +110,9 @@ There are a number of supported commands: * `@has-dir PATH` checks for the existence of the given directory. +* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly + `[ENTRIES]`. + All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` checks if the given file does not exist, for example. @@ -321,12 +324,15 @@ class CachedFiles(object): else: return self.last_path + def get_absolute_path(self, path): + return os.path.join(self.root, path) + def get_file(self, path): path = self.resolve_path(path) if path in self.files: return self.files[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -340,7 +346,7 @@ class CachedFiles(object): if path in self.trees: return self.trees[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -356,7 +362,7 @@ class CachedFiles(object): def get_dir(self, path): path = self.resolve_path(path) - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isdir(abspath)): raise FailedCheck('Directory does not exist {!r}'.format(path)) @@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first): return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first) +def check_files_in_folder(c, cache, folder, files): + files = files.strip() + if not files.startswith('[') or not files.endswith(']'): + raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd)) + + folder = cache.get_absolute_path(folder) + + # First we create a set of files to check if there are duplicates. + files = shlex.split(files[1:-1].replace(",", "")) + files_set = set() + for file in files: + if file in files_set: + raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd)) + files_set.add(file) + folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."]) + + # Then we remove entries from both sets (we clone `folder_set` so we can iterate it while + # removing its elements). + for entry in set(folder_set): + if entry in files_set: + files_set.remove(entry) + folder_set.remove(entry) + + error = 0 + if len(files_set) != 0: + print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format( + folder, files_set)) + error += 1 + if len(folder_set) != 0: + print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format( + folder, folder_set)) + error += 1 + return error == 0 + + ERR_COUNT = 0 @@ -566,6 +607,13 @@ def check_command(c, cache): else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + elif c.cmd == 'files': # check files in given folder + if len(c.args) != 2: # @files <folder path> <file list> + raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd)) + elif c.negated: + raise InvalidCheck("@{} doesn't support negative check".format(c.cmd)) + ret = check_files_in_folder(c, cache, c.args[0], c.args[1]) + elif c.cmd == 'count': # count test if len(c.args) == 3: # @count <path> <pat> <count> = count test expected = int(c.args[2]) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9a815694e1b..f86c32158e0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1361,8 +1361,10 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - let bounds = - tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); + let bounds = tcx + .explicit_item_bounds(assoc_item.def_id) + .subst_identity_iter_copied() + .map(|(c, s)| (c.as_predicate(), s)); let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; let predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); @@ -2117,7 +2119,7 @@ pub(crate) fn clean_middle_ty<'tcx>( fn clean_middle_opaque_bounds<'tcx>( cx: &mut DocContext<'tcx>, - bounds: Vec<ty::Predicate<'tcx>>, + bounds: Vec<ty::Clause<'tcx>>, ) -> Type { let mut regions = vec![]; let mut has_sized = false; @@ -2126,13 +2128,8 @@ fn clean_middle_opaque_bounds<'tcx>( .filter_map(|bound| { let bound_predicate = bound.kind(); let trait_ref = match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => { - bound_predicate.rebind(tr.trait_ref) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - _ty, - reg, - ))) => { + ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { if let Some(r) = clean_middle_region(reg) { regions.push(GenericBound::Outlives(r)); } @@ -2149,9 +2146,7 @@ fn clean_middle_opaque_bounds<'tcx>( let bindings: ThinVec<_> = bounds .iter() .filter_map(|bound| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = - bound.kind().skip_binder() - { + if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() { if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { Some(TypeBinding { assoc: projection_to_path_segment( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 294de12cea8..f375f0efbd1 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::Write as _; use std::mem; +use std::sync::LazyLock as Lazy; use thin_vec::{thin_vec, ThinVec}; #[cfg(test)] @@ -582,6 +583,8 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { /// /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); +pub(crate) static DOC_CHANNEL: Lazy<&'static str> = + Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap()); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index f26d74629dd..b710311c858 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -347,13 +347,19 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( } } else { let mut br_with_padding = String::with_capacity(6 * indent + 28); - br_with_padding.push_str("\n"); + br_with_padding.push('\n'); - let padding_amount = - if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() }; + let where_indent = 3; + let padding_amount = if ending == Ending::Newline { + indent + 4 + } else if indent == 0 { + 4 + } else { + indent + where_indent + "where ".len() + }; for _ in 0..padding_amount { - br_with_padding.push_str(" "); + br_with_padding.push(' '); } let where_preds = where_preds.to_string().replace('\n', &br_with_padding); @@ -370,7 +376,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( let where_preds = where_preds.replacen(&br_with_padding, " ", 1); let mut clause = br_with_padding; - clause.truncate(clause.len() - "where ".len()); + // +1 is for `\n`. + clause.truncate(indent + 1 + where_indent); write!(clause, "<span class=\"where\">where{where_preds}</span>")?; clause diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6ab849c92a0..8c5871d9126 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -55,6 +55,7 @@ struct PageLayout<'a> { sidebar: String, content: String, krate_with_trailing_slash: String, + rust_channel: &'static str, pub(crate) rustdoc_version: &'a str, } @@ -82,6 +83,7 @@ pub(crate) fn render<T: Print, S: Print>( sidebar, content, krate_with_trailing_slash, + rust_channel: *crate::clean::utils::DOC_CHANNEL, rustdoc_version, } .render() diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c5d6771c2fd..f923f905451 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -799,10 +799,11 @@ fn assoc_type( if !bounds.is_empty() { write!(w, ": {}", print_generic_bounds(bounds, cx)) } - write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); + // Render the default before the where-clause which aligns with the new recommended style. See #89122. if let Some(default) = default { write!(w, " = {}", default.print(cx)) } + write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); } fn assoc_method( @@ -859,8 +860,8 @@ fn assoc_method( w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len()); write!( w, - "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a{href} class=\"fn\">{name}</a>\ - {generics}{decl}{notable_traits}{where_clause}", + "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn \ + <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}", indent = indent_str, vis = vis, constness = constness, diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f5296abaee6..254b0d8bf5a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1050,9 +1050,10 @@ function preLoadCss(cssUrl) { function buildHelpMenu() { const book_info = document.createElement("span"); + const channel = getVar("channel"); book_info.className = "top"; - book_info.innerHTML = "You can find more information in \ - <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>."; + book_info.innerHTML = `You can find more information in \ +<a href="https://doc.rust-lang.org/${channel}/rustdoc/">the rustdoc book</a>.`; const shortcuts = [ ["?", "Show this help dialog"], @@ -1072,6 +1073,9 @@ function preLoadCss(cssUrl) { div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>"; const infos = [ + `For a full list of all search features, take a look <a \ +href="https://doc.rust-lang.org/${channel}/rustdoc/how-to-read-rustdoc.html\ +#the-search-interface">here</a>.`, "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \ restrict the search to a given item kind.", "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \ diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 9133f899af6..759c4fd6012 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -31,6 +31,7 @@ data-themes="{{themes|join(",") }}" {#+ #} data-resource-suffix="{{page.resource_suffix}}" {#+ #} data-rustdoc-version="{{rustdoc_version}}" {#+ #} + data-channel="{{rust_channel}}" {#+ #} data-search-js="{{files.search_js}}" {#+ #} data-settings-js="{{files.settings_js}}" {#+ #} data-settings-css="{{files.settings_css}}" {#+ #} diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs index 731095023a9..11b8a228b8a 100644 --- a/src/tools/build_helper/src/util.rs +++ b/src/tools/build_helper/src/util.rs @@ -25,17 +25,21 @@ pub fn fail(s: &str) -> ! { detail_exit(1, cfg!(test)); } -pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { +pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> { let status = match cmd.status() { Ok(status) => status, Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), }; - if !status.success() && print_cmd_on_fail { - println!( - "\n\ncommand did not execute successfully: {:?}\n\ - expected success, got: {}\n\n", - cmd, status - ); + if !status.success() { + if print_cmd_on_fail { + println!( + "\n\ncommand did not execute successfully: {:?}\n\ + expected success, got: {}\n\n", + cmd, status + ); + } + Err(()) + } else { + Ok(()) } - status.success() } diff --git a/src/tools/cargo b/src/tools/cargo -Subproject dead4b8740c4b6a8ed5211e37c99cf81d01c3b1 +Subproject 03bc66b55c290324bd46eb22e369c8fae1908f9 diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index a391b76910a..818ebd1134d 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { - if let Some(trait_pred) = p.to_opt_poly_trait_pred() { + if let Some(trait_pred) = p.as_trait_clause() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; break; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 12f18614d71..2b185943c59 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -94,7 +94,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' match predicate.kind().skip_binder() { // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through // and check substitutions to find `U`. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { + ty::ClauseKind::Trait(trait_predicate) => { if trait_predicate .trait_ref .substs @@ -107,7 +107,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' }, // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`, // so we check the term for `U`. - ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_predicate)) => { + ty::ClauseKind::Projection(projection_predicate) => { if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() { if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) { return true; @@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() { + if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } @@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), + cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t fn sig_from_bounds<'tcx>( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: &'tcx [Predicate<'tcx>], + predicates: impl IntoIterator<Item = Predicate<'tcx>>, predicates_id: Option<DefId>, ) -> Option<ExprFnSig<'tcx>> { let mut inputs = None; @@ -747,7 +747,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(p)) + ty::ClauseKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) => @@ -760,7 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option } inputs = Some(i); }, - PredicateKind::Clause(ty::ClauseKind::Projection(p)) + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => { if output.is_some() { diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index dc902f8cb02..0ddd2c66cf9 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -67,7 +67,7 @@ fn find_librs<P: AsRef<Path>>(path: P) -> Option<PathBuf> { None } -fn main() { +fn main() -> Result<(), ()> { let config = Arc::new(Config::from_args(env::args().collect())); // The goal here is to check if the necessary packages are installed, and if not, we @@ -128,7 +128,10 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse } } - try_run(&mut cargo, config.verbose); + if try_run(&mut cargo, config.verbose).is_err() { + eprintln!("failed to document `{}`", entry.path().display()); + panic!("Cannot run rustdoc-gui tests"); + } } } @@ -158,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse command.args(&config.test_args); - try_run(&mut command, config.verbose); + try_run(&mut command, config.verbose) } diff --git a/tests/codegen/naked-nocoverage.rs b/tests/codegen/naked-nocoverage.rs index 91a6260bf2a..3c755e49c6d 100644 --- a/tests/codegen/naked-nocoverage.rs +++ b/tests/codegen/naked-nocoverage.rs @@ -11,7 +11,7 @@ use std::arch::asm; #[naked] #[no_mangle] pub unsafe extern "C" fn f() { - // CHECK: define void @f() + // CHECK: define {{(dso_local )?}}void @f() // CHECK-NEXT: start: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs index 472d921ace0..63e63c5d4aa 100644 --- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -61,7 +61,19 @@ pub type Type9 = impl Send; pub type Type10 = impl Send; pub type Type11 = impl Send; -pub fn fn1<'a>() { +pub fn fn1<'a>() where + Type1: 'static, + Type2: 'static, + Type3: 'static, + Type4: 'static, + Type5: 'static, + Type6: 'static, + Type7: 'static, + Type8: 'static, + Type9: 'static, + Type10: 'static, + Type11: 'static, +{ // Closure let closure1 = || { }; let _: Type1 = closure1; diff --git a/tests/codegen/stack-protector.rs b/tests/codegen/stack-protector.rs index a24e6f1e4f1..a680789af15 100644 --- a/tests/codegen/stack-protector.rs +++ b/tests/codegen/stack-protector.rs @@ -10,25 +10,25 @@ pub fn foo() { // CHECK: @foo() unnamed_addr #0 - // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } - // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } - // all: attributes #0 = { {{.*}} sspreq {{.*}} } - // all-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } - // all-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // all: attributes #0 = { {{.*}}sspreq {{.*}} } + // all-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // all-NOT: attributes #0 = { {{.*}}ssp {{.*}} } - // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } - // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } - // strong: attributes #0 = { {{.*}} sspstrong {{.*}} } - // strong-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } - // strong-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} } + // strong: attributes #0 = { {{.*}}sspstrong {{.*}} } + // strong-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // strong-NOT: attributes #0 = { {{.*}}ssp {{.*}} } - // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } - // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } - // basic: attributes #0 = { {{.*}} ssp {{.*}} } - // basic-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } - // basic-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } + // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // basic: attributes #0 = { {{.*}}ssp {{.*}} } + // basic-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // basic-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } - // none-NOT: attributes #0 = { {{.*}} sspreq {{.*}} } - // none-NOT: attributes #0 = { {{.*}} sspstrong {{.*}} } - // none-NOT: attributes #0 = { {{.*}} ssp {{.*}} } + // none-NOT: attributes #0 = { {{.*}}sspreq {{.*}} } + // none-NOT: attributes #0 = { {{.*}}sspstrong {{.*}} } + // none-NOT: attributes #0 = { {{.*}}ssp {{.*}} } } diff --git a/tests/run-make/target-specs/Makefile b/tests/run-make/target-specs/Makefile index a33f5368e3c..62d5365a73d 100644 --- a/tests/run-make/target-specs/Makefile +++ b/tests/run-make/target-specs/Makefile @@ -8,4 +8,5 @@ all: RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin' + $(RUSTC) foo.rs --target=endianness-mismatch 2>&1 | $(CGREP) '"data-layout" claims architecture is little-endian' $(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib diff --git a/tests/run-make/target-specs/endianness-mismatch.json b/tests/run-make/target-specs/endianness-mismatch.json new file mode 100644 index 00000000000..431053ea99b --- /dev/null +++ b/tests/run-make/target-specs/endianness-mismatch.json @@ -0,0 +1,11 @@ +{ + "pre-link-args": {"gcc": ["-m64"]}, + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "linker-flavor": "gcc", + "llvm-target": "x86_64-unknown-linux-gnu", + "target-endian": "big", + "target-pointer-width": "64", + "target-c-int-width": "32", + "arch": "x86_64", + "os": "linux" +} diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml index 1a1c1b28f61..6e880302f28 100644 --- a/tests/rustdoc-gui/help-page.goml +++ b/tests/rustdoc-gui/help-page.goml @@ -67,5 +67,5 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px. assert-false: "#help" click: "#help-button > a" -click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']" -wait-for-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"} +click: "//*[@id='help']//a[text()='the rustdoc book']" +wait-for-document-property: ({"URL": "https://doc.rust-lang.org/"}, STARTS_WITH) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 193a3eb3fd1..e3c628b366f 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -31,7 +31,7 @@ define-function: ( // color of the typename (struct, module, method, ...) before search results assert-css: ( ".result-name .typename", - {"color": "#888"}, + {"color": |grey|}, ALL, ) }, @@ -75,6 +75,7 @@ store-value: (entry_color, "#0096cf") // color of the search entry store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#3c3c3c") // hover background color +store-value: (grey, "#999") call-function: ( "check-result-color", ( @@ -186,6 +187,7 @@ store-value: (entry_color, "#ddd") // color of the search entry store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#616161") // hover background color +store-value: (grey, "#ccc") call-function: ( "check-result-color", ( @@ -282,6 +284,7 @@ store-value: (entry_color, "#000") // color of the search entry store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#ccc") // hover background color +store-value: (grey, "#999") call-function: ( "check-result-color", ( diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml index c37d969324c..e40c637dcf7 100644 --- a/tests/rustdoc-gui/settings.goml +++ b/tests/rustdoc-gui/settings.goml @@ -56,19 +56,19 @@ move-cursor-to: "#settings-menu > a" assert-css: ( "#theme-dark", { - "border-color": "rgb(153, 153, 153)", - "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset", + "border-color": "#999", + "box-shadow": "#353535 0px 0px 0px 3px inset", "border-width": "2px", }, ) -assert-css: ("#theme-light", {"border-color": "rgb(153, 153, 153)", "box-shadow": "none"}) +assert-css: ("#theme-light", {"border-color": "#999", "box-shadow": "none"}) // Let's start with the hover for radio buttons. move-cursor-to: "#theme-dark" assert-css: ( "#theme-dark", { - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset", + "border-color": "#2196f3", + "box-shadow": "#353535 0px 0px 0px 3px inset", "border-width": "2px", }, ) @@ -76,7 +76,7 @@ move-cursor-to: "#theme-light" assert-css: ( "#theme-light", { - "border-color": "rgb(33, 150, 243)", + "border-color": "#2196f3", "box-shadow": "none", "border-width": "2px", } @@ -87,8 +87,8 @@ focus: "#theme-dark" assert-css: ( "#theme-dark", { - "border-color": "rgb(153, 153, 153)", - "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px", + "border-color": "#999", + "box-shadow": "#353535 0px 0px 0px 3px inset, #2196f3 0px 0px 2px 2px", "border-width": "2px", }, ) @@ -96,8 +96,8 @@ focus: "#theme-light" assert-css: ( "#theme-light", { - "border-color": "rgb(153, 153, 153)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "border-color": "#999", + "box-shadow": "#2196f3 0px 0px 1px 1px", "border-width": "2px", }, ) @@ -107,8 +107,8 @@ focus: "#theme-dark" assert-css: ( "#theme-dark", { - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px", + "border-color": "#2196f3", + "box-shadow": "#353535 0px 0px 0px 3px inset, #2196f3 0px 0px 2px 2px", "border-width": "2px", }, ) @@ -117,8 +117,8 @@ focus: "#theme-light" assert-css: ( "#theme-light", { - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "border-color": "#2196f3", + "box-shadow": "#2196f3 0px 0px 1px 1px", "border-width": "2px", }, ) @@ -154,8 +154,8 @@ compare-elements-position-near: ( assert-css: ( "#auto-hide-large-items", { - "background-color": "rgb(33, 150, 243)", - "border-color": "rgb(153, 153, 153)", + "background-color": "#2196f3", + "border-color": "#999", // 1px border when checked "border-width": "1px", }, @@ -164,7 +164,7 @@ assert-css: ( "#auto-hide-method-docs", { "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(153, 153, 153)", + "border-color": "#999", // 2px border when unchecked "border-width": "2px", }, @@ -174,8 +174,8 @@ move-cursor-to: "#auto-hide-large-items" assert-css: ( "#auto-hide-large-items", { - "background-color": "rgb(33, 150, 243)", - "border-color": "rgb(33, 150, 243)", + "background-color": "#2196f3", + "border-color": "#2196f3", // 1px border when checked "border-width": "1px", }, @@ -185,7 +185,7 @@ assert-css: ( "#auto-hide-method-docs", { "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(33, 150, 243)", + "border-color": "#2196f3", // 2px border when unchecked "border-width": "2px", }, @@ -196,9 +196,9 @@ focus: "#auto-hide-large-items" assert-css: ( "#auto-hide-large-items", { - "background-color": "rgb(33, 150, 243)", - "border-color": "rgb(153, 153, 153)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "background-color": "#2196f3", + "border-color": "#999", + "box-shadow": "#2196f3 0px 0px 1px 1px", // 1px border when checked "border-width": "1px", }, @@ -208,8 +208,8 @@ assert-css: ( "#auto-hide-method-docs", { "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(153, 153, 153)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "border-color": "#999", + "box-shadow": "#2196f3 0px 0px 1px 1px", // 2px border when unchecked "border-width": "2px", }, @@ -220,9 +220,9 @@ focus: "#auto-hide-large-items" assert-css: ( "#auto-hide-large-items", { - "background-color": "rgb(33, 150, 243)", - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "background-color": "#2196f3", + "border-color": "#2196f3", + "box-shadow": "#2196f3 0px 0px 1px 1px", // 1px border when checked "border-width": "1px", }, @@ -233,8 +233,8 @@ assert-css: ( "#auto-hide-method-docs", { "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + "border-color": "#2196f3", + "box-shadow": "#2196f3 0px 0px 1px 1px", // 2px border when unchecked "border-width": "2px", }, diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs index bcabbfc91e8..498d9cdaef1 100644 --- a/tests/rustdoc/files-creation-hidden.rs +++ b/tests/rustdoc/files-creation-hidden.rs @@ -1,5 +1,6 @@ #![crate_name="foo"] +// @files foo '["index.html", "all.html", "sidebar-items.js"]' // @!has "foo/struct.Foo.html" #[doc(hidden)] pub struct Foo; diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/files-creation-private.rs index ca2327e0f91..e2fdbc068f8 100644 --- a/tests/rustdoc/files-creation-private.rs +++ b/tests/rustdoc/files-creation-private.rs @@ -1,5 +1,9 @@ #![crate_name="foo"] +// @files "foo" \ +// '["index.html", "all.html", "sidebar-items.js", "foo", "bar", "private", "struct.Bar.html"]' +// @files "foo/bar" '["index.html", "sidebar-items.js"]' + // @!has "foo/priv/index.html" // @!has "foo/priv/struct.Foo.html" mod private { diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs index 7ab82bb5829..605176e5fea 100644 --- a/tests/rustdoc/generic-associated-types/gats.rs +++ b/tests/rustdoc/generic-associated-types/gats.rs @@ -23,9 +23,9 @@ impl LendingIterator for () { pub struct Infinite<T>(T); // @has foo/trait.LendingIterator.html -// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" +// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> = &'a T where Self: 'a" impl<T> LendingIterator for Infinite<T> { - type Item<'a> where Self: 'a = &'a T; + type Item<'a> = &'a T where Self: 'a; fn next<'a>(&'a self) -> Self::Item<'a> { &self.0 diff --git a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs index d6832bb7a09..65c26d6a837 100644 --- a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs +++ b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs @@ -2,6 +2,12 @@ #![no_core] #![crate_name = "foo"] +// @files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \ +// 'visible']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" +// @files "foo/visible" "['index.html', 'sidebar-items.js', 'trait.Foo.html']" + // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html' // FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249 diff --git a/tests/rustdoc/issue-111249-file-creation.rs b/tests/rustdoc/issue-111249-file-creation.rs index d2042b231e4..afd65ddaf94 100644 --- a/tests/rustdoc/issue-111249-file-creation.rs +++ b/tests/rustdoc/issue-111249-file-creation.rs @@ -2,6 +2,12 @@ #![feature(no_core)] #![no_core] +// @files "foo" "['all.html', 'visible', 'index.html', 'sidebar-items.js', 'hidden', \ +// 'struct.Bar.html']" +// @files "foo/visible" "['trait.Foo.html', 'index.html', 'sidebar-items.js']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" + // The following five should not fail! // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html' diff --git a/tests/rustdoc/where.SWhere_Echo_impl.html b/tests/rustdoc/where.SWhere_Echo_impl.html new file mode 100644 index 00000000000..7517eb090f4 --- /dev/null +++ b/tests/rustdoc/where.SWhere_Echo_impl.html @@ -0,0 +1,2 @@ +<h3 class="code-header">impl<D> <a class="struct" href="struct.Delta.html" title="struct foo::Delta">Delta</a><D><span class="where fmt-newline">where + D: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></h3> \ No newline at end of file diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html index ef4294c8f76..3e72ba2b74f 100644 --- a/tests/rustdoc/where.SWhere_Simd_item-decl.html +++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html @@ -1,3 +1,3 @@ <pre class="rust item-decl"><code>pub struct Simd<T>(_) <span class="where">where - T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre> \ No newline at end of file + T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre> diff --git a/tests/rustdoc/where.alpha_trait_decl.html b/tests/rustdoc/where.alpha_trait_decl.html new file mode 100644 index 00000000000..a7700055c9a --- /dev/null +++ b/tests/rustdoc/where.alpha_trait_decl.html @@ -0,0 +1,3 @@ +<code>pub struct Alpha<A>(_) +<span class="where">where + A: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code> \ No newline at end of file diff --git a/tests/rustdoc/where.bravo_trait_decl.html b/tests/rustdoc/where.bravo_trait_decl.html new file mode 100644 index 00000000000..00524201a8a --- /dev/null +++ b/tests/rustdoc/where.bravo_trait_decl.html @@ -0,0 +1,5 @@ +<code>pub trait Bravo<B><span class="where fmt-newline">where + B: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span>{ + // Required method + fn <a href="#tymethod.get" class="fn">get</a>(&self, B: B); +}</code> \ No newline at end of file diff --git a/tests/rustdoc/where.charlie_fn_decl.html b/tests/rustdoc/where.charlie_fn_decl.html new file mode 100644 index 00000000000..8e3bc8b01ec --- /dev/null +++ b/tests/rustdoc/where.charlie_fn_decl.html @@ -0,0 +1,2 @@ +<code>pub fn charlie<C>()<span class="where fmt-newline">where + C: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a>,</span></code> \ No newline at end of file diff --git a/tests/rustdoc/where.golf_type_alias_decl.html b/tests/rustdoc/where.golf_type_alias_decl.html new file mode 100644 index 00000000000..8da5402f900 --- /dev/null +++ b/tests/rustdoc/where.golf_type_alias_decl.html @@ -0,0 +1,2 @@ +<code>pub type Golf<T><span class="where fmt-newline">where + T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span> = <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>;</code> \ No newline at end of file diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs index 8b8a126e89d..2aa9c8b5461 100644 --- a/tests/rustdoc/where.rs +++ b/tests/rustdoc/where.rs @@ -5,16 +5,20 @@ use std::io::Lines; pub trait MyTrait { fn dummy(&self) { } } // @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait" +// @snapshot alpha_trait_decl - '//*[@class="rust item-decl"]/code' pub struct Alpha<A>(A) where A: MyTrait; // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait" +// @snapshot bravo_trait_decl - '//*[@class="rust item-decl"]/code' pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); } // @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait" +// @snapshot charlie_fn_decl - '//*[@class="rust item-decl"]/code' pub fn charlie<C>() where C: MyTrait {} pub struct Delta<D>(D); // @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \ // "impl<D> Delta<D>where D: MyTrait" +// @snapshot SWhere_Echo_impl - '//*[@id="impl-Delta%3CD%3E"]/h3[@class="code-header"]' impl<D> Delta<D> where D: MyTrait { pub fn delta() {} } @@ -65,4 +69,5 @@ impl<F> MyTrait for Foxtrot<F>where F: MyTrait {} // @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \ // "type Golf<T>where T: Clone, = (T, T)" +// @snapshot golf_type_alias_decl - '//*[@class="rust item-decl"]/code' pub type Golf<T> where T: Clone = (T, T); diff --git a/tests/ui/asm/aarch64/may_unwind.rs b/tests/ui/asm/aarch64/may_unwind.rs index 6af8728bbaa..cfb75078264 100644 --- a/tests/ui/asm/aarch64/may_unwind.rs +++ b/tests/ui/asm/aarch64/may_unwind.rs @@ -1,6 +1,7 @@ // only-aarch64 // run-pass // needs-asm-support +// needs-unwind #![feature(asm_unwind)] diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.current.stderr index 95ef7d82fca..b8be132e6b6 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.current.stderr @@ -1,11 +1,11 @@ error: return type notation uses `()` instead of `(..)` for elided arguments - --> $DIR/bad-inputs-and-output.rs:18:24 + --> $DIR/bad-inputs-and-output.rs:20:24 | LL | fn baz<T: Trait<method(..): Send>>() {} | ^^ help: remove the `..` error[E0658]: associated type bounds are unstable - --> $DIR/bad-inputs-and-output.rs:10:17 + --> $DIR/bad-inputs-and-output.rs:12:17 | LL | fn foo<T: Trait<method(i32): Send>>() {} | ^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | fn foo<T: Trait<method(i32): Send>>() {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/bad-inputs-and-output.rs:14:17 + --> $DIR/bad-inputs-and-output.rs:16:17 | LL | fn bar<T: Trait<method() -> (): Send>>() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | fn bar<T: Trait<method() -> (): Send>>() {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-inputs-and-output.rs:3:12 + --> $DIR/bad-inputs-and-output.rs:5:12 | LL | #![feature(return_type_notation, async_fn_in_trait)] | ^^^^^^^^^^^^^^^^^^^^ @@ -32,13 +32,13 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: `#[warn(incomplete_features)]` on by default error: argument types not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:10:23 + --> $DIR/bad-inputs-and-output.rs:12:23 | LL | fn foo<T: Trait<method(i32): Send>>() {} | ^^^^^ help: remove the input types: `()` error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:14:25 + --> $DIR/bad-inputs-and-output.rs:16:25 | LL | fn bar<T: Trait<method() -> (): Send>>() {} | ^^^^^^ help: remove the return type diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr new file mode 100644 index 00000000000..b8be132e6b6 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.next.stderr @@ -0,0 +1,48 @@ +error: return type notation uses `()` instead of `(..)` for elided arguments + --> $DIR/bad-inputs-and-output.rs:20:24 + | +LL | fn baz<T: Trait<method(..): Send>>() {} + | ^^ help: remove the `..` + +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:12:17 + | +LL | fn foo<T: Trait<method(i32): Send>>() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/bad-inputs-and-output.rs:16:17 + | +LL | fn bar<T: Trait<method() -> (): Send>>() {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad-inputs-and-output.rs:5:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: argument types not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:12:23 + | +LL | fn foo<T: Trait<method(i32): Send>>() {} + | ^^^^^ help: remove the input types: `()` + +error: return type not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:16:25 + | +LL | fn bar<T: Trait<method() -> (): Send>>() {} + | ^^^^^^ help: remove the return type + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index 58ce41d1a89..771acb6c4e7 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -1,4 +1,6 @@ // edition: 2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr new file mode 100644 index 00000000000..98c1a282779 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.current_with.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:8:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr new file mode 100644 index 00000000000..1066c420c31 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr @@ -0,0 +1,29 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:8:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: future cannot be sent between threads safely + --> $DIR/basic.rs:26:13 + | +LL | is_send(foo::<T>()); + | ^^^^^^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/basic.rs:16:5 + | +LL | T::method().await?; + | ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send` +note: required by a bound in `is_send` + --> $DIR/basic.rs:20:20 + | +LL | fn is_send(_: impl Send) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr new file mode 100644 index 00000000000..98c1a282779 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.next_with.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:8:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr new file mode 100644 index 00000000000..1066c420c31 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr @@ -0,0 +1,29 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:8:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: future cannot be sent between threads safely + --> $DIR/basic.rs:26:13 + | +LL | is_send(foo::<T>()); + | ^^^^^^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/basic.rs:16:5 + | +LL | T::method().await?; + | ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send` +note: required by a bound in `is_send` + --> $DIR/basic.rs:20:20 + | +LL | fn is_send(_: impl Send) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.rs b/tests/ui/associated-type-bounds/return-type-notation/basic.rs index edc6a8e4caf..d443c9dc11b 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs @@ -1,6 +1,9 @@ -// revisions: with without +// revisions: current_with current_without next_with next_without +// [next_with] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// [next_without] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty // edition: 2021 -//[with] check-pass +// [current_with] check-pass +// [next_with] check-pass #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete @@ -17,11 +20,12 @@ async fn foo<T: Foo>() -> Result<(), ()> { fn is_send(_: impl Send) {} fn test< - #[cfg(with)] T: Foo<method(): Send>, - #[cfg(without)] T: Foo, + #[cfg(any(current_with, next_with))] T: Foo<method(): Send>, + #[cfg(any(current_without, next_without))] T: Foo, >() { is_send(foo::<T>()); - //[without]~^ ERROR future cannot be sent between threads safely + //[current_without]~^ ERROR future cannot be sent between threads safely + //[next_without]~^^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr index 490bfdc4c3c..b631dd0ebb5 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/equality.rs:3:12 + --> $DIR/equality.rs:5:12 | LL | #![feature(return_type_notation, async_fn_in_trait)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: `#[warn(incomplete_features)]` on by default error: return type notation is not allowed to use type equality - --> $DIR/equality.rs:12:18 + --> $DIR/equality.rs:14:18 | LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr new file mode 100644 index 00000000000..b631dd0ebb5 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr @@ -0,0 +1,17 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality.rs:5:12 + | +LL | #![feature(return_type_notation, async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation is not allowed to use type equality + --> $DIR/equality.rs:14:18 + | +LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.rs b/tests/ui/associated-type-bounds/return-type-notation/equality.rs index 6884305d7b3..0d6545cc298 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs @@ -1,4 +1,6 @@ // edition: 2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 721234aa4a7..f80bb4242aa 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -1,18 +1,25 @@ -error[E0277]: `Sender<i32>` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:13:45 +error[E0277]: `*mut ()` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:18:23 | -LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `Sender<i32>` - = note: required for `&Sender<i32>` to implement `Send` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` +note: required because it appears within the type `PhantomData<*mut ()>` + --> $SRC_DIR/core/src/marker.rs:LL:COL +note: required because it appears within the type `NotSync` + --> $DIR/issue-70935-complex-spans.rs:12:8 + | +LL | struct NotSync(PhantomData<*mut ()>); + | ^^^^^^^ + = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:17:13 + --> $DIR/issue-70935-complex-spans.rs:22:13 | -LL | baz(|| async{ +LL | baz(|| async { | ^^ note: required because it's used within this `async fn` body - --> $DIR/issue-70935-complex-spans.rs:10:67 + --> $DIR/issue-70935-complex-spans.rs:15:67 | LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { | ___________________________________________________________________^ @@ -20,11 +27,11 @@ LL | | } | |_^ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:16:5 + --> $DIR/issue-70935-complex-spans.rs:21:5 | LL | / async move { -LL | | baz(|| async{ -LL | | foo(tx.clone()); +LL | | baz(|| async { +LL | | foo(x.clone()); LL | | }).await; LL | | } | |_____^ diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr index c636be15a58..eb9d93e229f 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr @@ -1,18 +1,25 @@ -error[E0277]: `Sender<i32>` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:13:45 +error[E0277]: `*mut ()` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:18:23 | -LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `Sender<i32>` - = note: required for `&Sender<i32>` to implement `Send` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` +note: required because it appears within the type `PhantomData<*mut ()>` + --> $SRC_DIR/core/src/marker.rs:LL:COL +note: required because it appears within the type `NotSync` + --> $DIR/issue-70935-complex-spans.rs:12:8 + | +LL | struct NotSync(PhantomData<*mut ()>); + | ^^^^^^^ + = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:17:13 + --> $DIR/issue-70935-complex-spans.rs:22:13 | -LL | baz(|| async{ +LL | baz(|| async { | ^^ note: required because it's used within this `async fn` body - --> $DIR/issue-70935-complex-spans.rs:10:67 + --> $DIR/issue-70935-complex-spans.rs:15:67 | LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { | ___________________________________________________________________^ @@ -20,11 +27,11 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future<Output = ()>` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:16:5 + --> $DIR/issue-70935-complex-spans.rs:21:5 | LL | / async move { -LL | | baz(|| async{ -LL | | foo(tx.clone()); +LL | | baz(|| async { +LL | | foo(x.clone()); LL | | }).await; LL | | } | |_____^ diff --git a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr index ef0e182e515..d8ef6a5eedb 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr @@ -1,21 +1,21 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:13:45 + --> $DIR/issue-70935-complex-spans.rs:18:23 | -LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `Sync` is not implemented for `Sender<i32>` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await - --> $DIR/issue-70935-complex-spans.rs:19:12 + --> $DIR/issue-70935-complex-spans.rs:24:12 | -LL | baz(|| async{ +LL | baz(|| async { | _____________- -LL | | foo(tx.clone()); +LL | | foo(x.clone()); LL | | }).await; | | - ^^^^^- the value is later dropped here | | | | | |_________| await occurs here, with the value maybe used later - | has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send` + | has type `[closure@$DIR/issue-70935-complex-spans.rs:22:13: 22:15]` which is not `Send` error: aborting due to previous error diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 78625bd393d..9ebde1d3977 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -6,16 +6,21 @@ // with newlines which lead complex diagnostics. use std::future::Future; +use std::marker::PhantomData; + +#[derive(Clone)] +struct NotSync(PhantomData<*mut ()>); +unsafe impl Send for NotSync {} async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { } -fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send { +fn foo(x: NotSync) -> impl Future + Send { //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely - //[drop_tracking,drop_tracking_mir]~^^ ERROR `Sender<i32>` cannot be shared between threads + //[drop_tracking,drop_tracking_mir]~^^ ERROR `*mut ()` cannot be shared between threads async move { - baz(|| async{ - foo(tx.clone()); + baz(|| async { + foo(x.clone()); }).await; } } @@ -24,6 +29,6 @@ fn bar(_s: impl Future + Send) { } fn main() { - let (tx, _rx) = std::sync::mpsc::channel(); - bar(foo(tx)); + let x = NotSync(PhantomData); + bar(foo(x)); } diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr index 33e22dec3f7..1b847b59eb5 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-110963-early.rs:4:12 + --> $DIR/issue-110963-early.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(return_type_notation)] = note: `#[warn(incomplete_features)]` on by default error: higher-ranked lifetime error - --> $DIR/issue-110963-early.rs:15:5 + --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { LL | | let mut hc = hc; @@ -18,10 +18,10 @@ LL | | } LL | | }); | |______^ | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` + = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` error: higher-ranked lifetime error - --> $DIR/issue-110963-early.rs:15:5 + --> $DIR/issue-110963-early.rs:17:5 | LL | / spawn(async move { LL | | let mut hc = hc; @@ -31,7 +31,7 @@ LL | | } LL | | }); | |______^ | - = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` + = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr new file mode 100644 index 00000000000..1b847b59eb5 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.next.stderr @@ -0,0 +1,37 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-110963-early.rs:6:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: higher-ranked lifetime error + --> $DIR/issue-110963-early.rs:17:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ + | + = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` + +error: higher-ranked lifetime error + --> $DIR/issue-110963-early.rs:17:5 + | +LL | / spawn(async move { +LL | | let mut hc = hc; +LL | | if !hc.check().await { +LL | | log_health_check_failure().await; +LL | | } +LL | | }); + | |______^ + | + = note: could not prove `[async block@$DIR/issue-110963-early.rs:17:11: 22:6]: Send` + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs index 0ecbca5c13b..eee31aa1fe5 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs @@ -1,5 +1,7 @@ // edition: 2021 // known-bug: #110963 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(return_type_notation)] #![feature(async_fn_in_trait)] diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.current.stderr index 9c6966537a7..018f4f2207a 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-110963-late.rs:4:12 + --> $DIR/issue-110963-late.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr new file mode 100644 index 00000000000..018f4f2207a --- /dev/null +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-110963-late.rs:6:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs index 17b5d775d44..ea047cd3b16 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs @@ -1,5 +1,7 @@ // edition: 2021 // check-pass +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.current.stderr index ac0668d3c44..891c802c5f4 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound.stderr +++ b/tests/ui/async-await/return-type-notation/super-method-bound.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-method-bound.rs:4:31 + --> $DIR/super-method-bound.rs:6:31 | LL | #![feature(async_fn_in_trait, return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr new file mode 100644 index 00000000000..891c802c5f4 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-method-bound.rs:6:31 + | +LL | #![feature(async_fn_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.rs b/tests/ui/async-await/return-type-notation/super-method-bound.rs index 58ea3578db6..0163c62f545 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound.rs +++ b/tests/ui/async-await/return-type-notation/super-method-bound.rs @@ -1,5 +1,7 @@ // edition:2021 // check-pass +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(async_fn_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.current.stderr index c8cec4946b4..05cb0ca4abd 100644 --- a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/supertrait-bound.rs:3:49 + --> $DIR/supertrait-bound.rs:5:49 | LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr new file mode 100644 index 00000000000..05cb0ca4abd --- /dev/null +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/supertrait-bound.rs:5:49 + | +LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs index 19bcfe3046b..09de32c5d4a 100644 --- a/tests/ui/async-await/return-type-notation/supertrait-bound.rs +++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs @@ -1,4 +1,6 @@ // check-pass +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(return_position_impl_trait_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.current.stderr index 76928c5d7a3..1aa008fe469 100644 --- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr +++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ty-or-ct-params.rs:3:31 + --> $DIR/ty-or-ct-params.rs:5:31 | LL | #![feature(async_fn_in_trait, return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(async_fn_in_trait, return_type_notation)] = note: `#[warn(incomplete_features)]` on by default error: return type notation is not allowed for functions that have type parameters - --> $DIR/ty-or-ct-params.rs:14:12 + --> $DIR/ty-or-ct-params.rs:16:12 | LL | async fn bar<T>() {} | - type parameter declared here @@ -17,7 +17,7 @@ LL | T: Foo<bar(): Send, baz(): Send>, | ^^^^^^^^^^^ error: return type notation is not allowed for functions that have const parameters - --> $DIR/ty-or-ct-params.rs:14:25 + --> $DIR/ty-or-ct-params.rs:16:25 | LL | async fn baz<const N: usize>() {} | -------------- const parameter declared here diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr new file mode 100644 index 00000000000..1aa008fe469 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.next.stderr @@ -0,0 +1,29 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ty-or-ct-params.rs:5:31 + | +LL | #![feature(async_fn_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation is not allowed for functions that have type parameters + --> $DIR/ty-or-ct-params.rs:16:12 + | +LL | async fn bar<T>() {} + | - type parameter declared here +... +LL | T: Foo<bar(): Send, baz(): Send>, + | ^^^^^^^^^^^ + +error: return type notation is not allowed for functions that have const parameters + --> $DIR/ty-or-ct-params.rs:16:25 + | +LL | async fn baz<const N: usize>() {} + | -------------- const parameter declared here +... +LL | T: Foo<bar(): Send, baz(): Send>, + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs index 7871a2fed03..3141da1d296 100644 --- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs +++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs @@ -1,4 +1,6 @@ // edition: 2021 +// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// revisions: current next #![feature(async_fn_in_trait, return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs new file mode 100644 index 00000000000..d8034d57e8d --- /dev/null +++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs @@ -0,0 +1,40 @@ +use std::ops::Deref; +use std::rc::Rc; + +struct Value<T>(T); + +pub trait Wrap<T> { + fn wrap() -> Self; +} + +impl<R, A1, A2> Wrap<fn(A1, A2) -> R> for Value<fn(A1, A2) -> R> { + fn wrap() -> Self { + todo!() + } +} + +impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> { + fn wrap() -> Self { + todo!() + } +} + +impl<F> Deref for Value<Rc<F>> { + type Target = F; + + fn deref(&self) -> &Self::Target { + &*self.0 + } +} + +fn main() { + let var_fn = Value::wrap(); + //~^ ERROR type annotations needed for `Value<Rc<_>>` + + // The combination of `Value: Wrap` obligation plus the autoderef steps + // (caused by the `Deref` impl above) actually means that the self type + // of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`. + // However, that's only known to us on the error path -- we still need + // to emit an ambiguity error, though. + let _ = var_fn.clone(); +} diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr new file mode 100644 index 00000000000..06a7e90858c --- /dev/null +++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `Value<Rc<_>>` + --> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9 + | +LL | let var_fn = Value::wrap(); + | ^^^^^^ +... +LL | let _ = var_fn.clone(); + | ----- type must be known at this point + | +help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified + | +LL | let var_fn: Value<Rc<_>> = Value::wrap(); + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs index 1d43d6ba02f..b9548e91183 100644 --- a/tests/ui/cfg/diagnostics-reexport.rs +++ b/tests/ui/cfg/diagnostics-reexport.rs @@ -9,6 +9,30 @@ pub mod inner { //~^ NOTE found an item that was configured out } +pub use a::x; +//~^ ERROR unresolved import `a::x` +//~| NOTE no `x` in `a` + +mod a { + #[cfg(no)] + pub fn x() {} + //~^ NOTE found an item that was configured out +} + +pub use b::{x, y}; +//~^ ERROR unresolved imports `b::x`, `b::y` +//~| NOTE no `x` in `b` +//~| NOTE no `y` in `b` + +mod b { + #[cfg(no)] + pub fn x() {} + //~^ NOTE found an item that was configured out + #[cfg(no)] + pub fn y() {} + //~^ NOTE found an item that was configured out +} + fn main() { // There is no uwu at this path - no diagnostic. inner::uwu(); //~ ERROR cannot find function diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr index 6c977cbfa41..e25b7cf86e2 100644 --- a/tests/ui/cfg/diagnostics-reexport.stderr +++ b/tests/ui/cfg/diagnostics-reexport.stderr @@ -1,5 +1,36 @@ +error[E0432]: unresolved import `a::x` + --> $DIR/diagnostics-reexport.rs:12:9 + | +LL | pub use a::x; + | ^^^^ no `x` in `a` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport.rs:18:12 + | +LL | pub fn x() {} + | ^ + +error[E0432]: unresolved imports `b::x`, `b::y` + --> $DIR/diagnostics-reexport.rs:22:13 + | +LL | pub use b::{x, y}; + | ^ ^ no `y` in `b` + | | + | no `x` in `b` + | +note: found an item that was configured out + --> $DIR/diagnostics-reexport.rs:29:12 + | +LL | pub fn x() {} + | ^ +note: found an item that was configured out + --> $DIR/diagnostics-reexport.rs:32:12 + | +LL | pub fn y() {} + | ^ + error[E0425]: cannot find function `uwu` in module `inner` - --> $DIR/diagnostics-reexport.rs:14:12 + --> $DIR/diagnostics-reexport.rs:38:12 | LL | inner::uwu(); | ^^^ not found in `inner` @@ -10,6 +41,7 @@ note: found an item that was configured out LL | pub use super::uwu; | ^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs new file mode 100644 index 00000000000..2d8565517e8 --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs @@ -0,0 +1,11 @@ +#![feature(unsized_fn_params)] + +fn main() { + // CoerceMany "LUB" + let f = if true { |_a| {} } else { |_b| {} }; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| ERROR the size for values of type `[u8]` cannot be known at compilation time + + let slice: Box<[u8]> = Box::new([1; 8]); + f(*slice); +} diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr new file mode 100644 index 00000000000..d88b84365df --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:24 + | +LL | let f = if true { |_a| {} } else { |_b| {} }; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:41 + | +LL | let f = if true { |_a| {} } else { |_b| {} }; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.rs b/tests/ui/closures/cannot-call-unsized-via-ptr.rs new file mode 100644 index 00000000000..5ce4650b033 --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr.rs @@ -0,0 +1,10 @@ +#![feature(unsized_fn_params)] + +fn main() { + // Simple coercion + let f: fn([u8]) = |_result| {}; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + + let slice: Box<[u8]> = Box::new([1; 8]); + f(*slice); +} diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr new file mode 100644 index 00000000000..9ecc66d5ce8 --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr.rs:5:24 + | +LL | let f: fn([u8]) = |_result| {}; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-move-sync.rs b/tests/ui/closures/closure-move-sync.rs index ea2d1434c4a..3ee2b35f59f 100644 --- a/tests/ui/closures/closure-move-sync.rs +++ b/tests/ui/closures/closure-move-sync.rs @@ -13,10 +13,4 @@ fn bar() { t.join().unwrap(); } -fn foo() { - let (tx, _rx) = channel(); - thread::spawn(|| tx.send(()).unwrap()); - //~^ ERROR `Sender<()>` cannot be shared between threads safely -} - fn main() {} diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr index 64e3b51ea71..aee903ac950 100644 --- a/tests/ui/closures/closure-move-sync.stderr +++ b/tests/ui/closures/closure-move-sync.stderr @@ -20,24 +20,6 @@ LL | let t = thread::spawn(|| { note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL -error[E0277]: `Sender<()>` cannot be shared between threads safely - --> $DIR/closure-move-sync.rs:18:19 - | -LL | thread::spawn(|| tx.send(()).unwrap()); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `Sync` is not implemented for `Sender<()>` - = note: required for `&Sender<()>` to implement `Send` -note: required because it's used within this closure - --> $DIR/closure-move-sync.rs:18:19 - | -LL | thread::spawn(|| tx.send(()).unwrap()); - | ^^ -note: required by a bound in `spawn` - --> $SRC_DIR/std/src/thread/mod.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr index 0432f2fa8be..bd8a4feeff5 100644 --- a/tests/ui/const-generics/issue-112505-overflow.stderr +++ b/tests/ui/const-generics/issue-112505-overflow.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits) + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error: aborting due to previous error diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 3d1197afd0f..9e308620a9c 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture) + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error: aborting due to 6 previous errors diff --git a/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs new file mode 100644 index 00000000000..c9094999ee2 --- /dev/null +++ b/tests/ui/consts/timeout.rs @@ -0,0 +1,25 @@ +//! This test checks that external macros don't hide +//! the const eval timeout lint and then subsequently +//! ICE. + +// compile-flags: --crate-type=lib -Ztiny-const-eval-limit +// error-pattern: constant evaluation is taking a long time + +static ROOK_ATTACKS_TABLE: () = { + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); +}; diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr new file mode 100644 index 00000000000..799b5ec8dd9 --- /dev/null +++ b/tests/ui/consts/timeout.stderr @@ -0,0 +1,15 @@ +error: constant evaluation is taking a long time + --> $SRC_DIR/core/src/num/mod.rs:LL:COL + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/timeout.rs:8:1 + | +LL | static ROOK_ATTACKS_TABLE: () = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + = note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr index 90316c6e981..89e634a7064 100644 --- a/tests/ui/error-codes/E0283.stderr +++ b/tests/ui/error-codes/E0283.stderr @@ -9,8 +9,8 @@ LL | let cont: u32 = Generator::create(); | help: use a fully-qualified path to a specific available implementation (2 found) | -LL | let cont: u32 = <Impl as Generator>::create(); - | ++++++++ + +LL | let cont: u32 = </* self type */ as Generator>::create(); + | +++++++++++++++++++ + error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr index fc025a3fca2..7248766285d 100644 --- a/tests/ui/error-codes/E0790.stderr +++ b/tests/ui/error-codes/E0790.stderr @@ -65,8 +65,8 @@ LL | MyTrait2::my_fn(); | help: use a fully-qualified path to a specific available implementation (2 found) | -LL | <Impl1 as MyTrait2>::my_fn(); - | +++++++++ + +LL | </* self type */ as MyTrait2>::my_fn(); + | +++++++++++++++++++ + error: aborting due to 5 previous errors diff --git a/tests/ui/extern/extern-crate-visibility.stderr b/tests/ui/extern/extern-crate-visibility.stderr index 9eeb83ae1a7..b239727092a 100644 --- a/tests/ui/extern/extern-crate-visibility.stderr +++ b/tests/ui/extern/extern-crate-visibility.stderr @@ -9,6 +9,10 @@ note: the crate import `core` is defined here | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ +help: consider importing this module instead + | +LL | use std::cell; + | ~~~~~~~~~ error[E0603]: crate import `core` is private --> $DIR/extern-crate-visibility.rs:9:10 @@ -21,6 +25,10 @@ note: the crate import `core` is defined here | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ +help: consider importing this struct instead + | +LL | std::cell::Cell::new(0); + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr new file mode 100644 index 00000000000..ce39f6b2971 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr @@ -0,0 +1,27 @@ +error[E0658]: return type notation is experimental + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = help: add `#![feature(return_type_notation)]` to the crate attributes to enable + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^-- + | | + | help: remove these parentheses + +error[E0220]: associated type `m` not found for `Trait` + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^ associated type `m` not found + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0220, E0658. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr new file mode 100644 index 00000000000..ce39f6b2971 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr @@ -0,0 +1,27 @@ +error[E0658]: return type notation is experimental + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = help: add `#![feature(return_type_notation)]` to the crate attributes to enable + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^-- + | | + | help: remove these parentheses + +error[E0220]: associated type `m` not found for `Trait` + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^ associated type `m` not found + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0220, E0658. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr new file mode 100644 index 00000000000..d11359e7f48 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no_current.stderr @@ -0,0 +1,13 @@ +warning: return type notation is experimental + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = help: add `#![feature(return_type_notation)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860> + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr new file mode 100644 index 00000000000..d11359e7f48 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no_next.stderr @@ -0,0 +1,13 @@ +warning: return type notation is experimental + --> $DIR/feature-gate-return_type_notation.rs:17:17 + | +LL | fn foo<T: Trait<m(): Send>>() {} + | ^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = help: add `#![feature(return_type_notation)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860> + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index d9bcb65feba..7e8c1eb95ca 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -1,7 +1,10 @@ // edition: 2021 -// revisions: cfg no +// revisions: cfg_current cfg_next no_current no_next +// [cfg_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty +// [no_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty -//[no] check-pass +// [no_current] check-pass +// [no_next] check-pass // Since we're not adding new syntax, `cfg`'d out RTN must pass. #![feature(async_fn_in_trait)] @@ -10,12 +13,17 @@ trait Trait { async fn m(); } -#[cfg(cfg)] +#[cfg(any(cfg_current, cfg_next))] fn foo<T: Trait<m(): Send>>() {} -//[cfg]~^ ERROR return type notation is experimental -//[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints -//[cfg]~| ERROR associated type `m` not found for `Trait` -//[no]~^^^^ WARN return type notation is experimental -//[no]~| WARN unstable syntax can change at any point in the future, causing a hard error! +//[cfg_current]~^ ERROR return type notation is experimental +//[cfg_current]~| ERROR parenthesized generic arguments cannot be used in associated type constraints +//[cfg_current]~| ERROR associated type `m` not found for `Trait` +//[cfg_next]~^^^^ ERROR return type notation is experimental +//[cfg_next]~| ERROR parenthesized generic arguments cannot be used in associated type constraints +//[cfg_next]~| ERROR associated type `m` not found for `Trait` +//[no_current]~^^^^^^^ WARN return type notation is experimental +//[no_current]~| WARN unstable syntax can change at any point in the future, causing a hard error! +//[no_next]~^^^^^^^^^ WARN return type notation is experimental +//[no_next]~| WARN unstable syntax can change at any point in the future, causing a hard error! fn main() {} diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 5362a68c834..a96a53ca93e 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -14,7 +14,7 @@ LL | for item in *things { *item = 0 } = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature -error: the type `<_ as IntoIterator>::IntoIter` is not well-formed +error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 499271fa92f..64156b35705 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -4,7 +4,7 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) { for item in *things { *item = 0 } //~^ ERROR the size for values of type - //[next]~^^ ERROR the type `<_ as IntoIterator>::IntoIter` is not well-formed + //[next]~^^ ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed //[next]~| ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied } diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs index 7de906e7ef3..5a40a612972 100644 --- a/tests/ui/generic-associated-types/issue-88595.rs +++ b/tests/ui/generic-associated-types/issue-88595.rs @@ -19,5 +19,4 @@ impl<'a> A<'a> for C { type B<'b> = impl Clone; fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope - //~^ ERROR: mismatched types } diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr index d6caed85459..2b1a25acfa4 100644 --- a/tests/ui/generic-associated-types/issue-88595.stderr +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -1,8 +1,8 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-88595.rs:21:5 + --> $DIR/issue-88595.rs:21:23 | LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice + | ^^^^^^^^^^^ generic argument `'a` used twice | note: for this opaque type --> $DIR/issue-88595.rs:19:18 @@ -10,25 +10,5 @@ note: for this opaque type LL | type B<'b> = impl Clone; | ^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/issue-88595.rs:21:23 - | -LL | type B<'b> = impl Clone; - | ---------- the expected opaque type -LL | -LL | fn a(&'a self) -> Self::B<'a> {} - | - ^^^^^^^^^^^ expected opaque type, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - | - = note: expected opaque type `<C as A<'a>>::B<'a>` - found unit type `()` -note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/issue-88595.rs:21:5 - | -LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr index 1097cd0f452..8e61a65abe4 100644 --- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr +++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr @@ -40,10 +40,10 @@ LL | fn method() -> Self::Ty; = note: expected signature `fn() -> <() as compare_method::Trait>::Ty` found signature `fn()` note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/in-assoc-type-unconstrained.rs:22:9 + --> $DIR/in-assoc-type-unconstrained.rs:22:12 | LL | fn method() -> () {} - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: unconstrained opaque type --> $DIR/in-assoc-type-unconstrained.rs:20:19 diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index f0a272dc2d5..ab3f3a14410 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -12,10 +12,10 @@ LL | fn foo(&self) -> <Self as Foo<()>>::Bar {} = note: expected opaque type `<() as Foo<()>>::Bar` found unit type `()` note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/in-assoc-type.rs:17:5 + --> $DIR/in-assoc-type.rs:17:8 | LL | fn foo(&self) -> <Self as Foo<()>>::Bar {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index bbd60d4398b..fe765271bd2 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -20,11 +20,6 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { | = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` -note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9 - | -LL | fn eq(&self, _other: &(Foo, i32)) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 @@ -49,10 +44,10 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool { = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _` found signature `fn(&b::Bar, &(b::Bar, i32)) -> _` note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:9 + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12 | LL | fn eq(&self, _other: &(Bar, i32)) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-11680.stderr b/tests/ui/issues/issue-11680.stderr index ea224af8ed7..5bcf93de811 100644 --- a/tests/ui/issues/issue-11680.stderr +++ b/tests/ui/issues/issue-11680.stderr @@ -2,7 +2,9 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:6:21 | LL | let _b = other::Foo::Bar(1); - | ^^^ private enum + | ^^^ --- tuple variant `Bar` is not publicly re-exported + | | + | private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:1:1 @@ -14,7 +16,9 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:9:27 | LL | let _b = other::test::Foo::Bar(1); - | ^^^ private enum + | ^^^ --- tuple variant `Bar` is not publicly re-exported + | | + | private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:6:5 diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs index 82866b35557..f9dd2c54d99 100644 --- a/tests/ui/issues/issue-5883.rs +++ b/tests/ui/issues/issue-5883.rs @@ -6,7 +6,7 @@ struct Struct { fn new_struct( r: dyn A + 'static //~ ERROR the size for values of type -) -> Struct { //~ ERROR the size for values of type +) -> Struct { Struct { r: r } } diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr index ffff403e0d4..a3e2531b5ca 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/issues/issue-5883.stderr @@ -15,22 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | r: &dyn A + 'static | + -error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:9:6 - | -LL | ) -> Struct { - | ^^^^^^ doesn't have a size known at compile-time -LL | Struct { r: r } - | --------------- this returned value is of type `Struct` - | - = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` -note: required because it appears within the type `Struct` - --> $DIR/issue-5883.rs:3:8 - | -LL | struct Struct { - | ^^^^^^ - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.rs b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs new file mode 100644 index 00000000000..d2b6e1d8eba --- /dev/null +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs @@ -0,0 +1,22 @@ +trait Trait { + type RefTarget; +} + +impl Trait for () +where + Missing: Trait, + //~^ ERROR cannot find type `Missing` in this scope +{ + type RefTarget = (); +} + +struct Other { + data: <() as Trait>::RefTarget, +} + +fn main() { + unsafe { + std::mem::transmute::<Option<()>, Option<&Other>>(None); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types + } +} diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr new file mode 100644 index 00000000000..dd5119318ff --- /dev/null +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr @@ -0,0 +1,19 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/cannot-transmute-unnormalizable-type.rs:7:5 + | +LL | Missing: Trait, + | ^^^^^^^ not found in this scope + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/cannot-transmute-unnormalizable-type.rs:19:9 + | +LL | std::mem::transmute::<Option<()>, Option<&Other>>(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<()>` (8 bits) + = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0512. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/macros/issue-88228.stderr b/tests/ui/macros/issue-88228.stderr index 1dbe2b77be2..f9d0ac95da7 100644 --- a/tests/ui/macros/issue-88228.stderr +++ b/tests/ui/macros/issue-88228.stderr @@ -4,7 +4,7 @@ error: cannot find macro `bla` in this scope LL | bla!(); | ^^^ | -help: consider importing this macro +help: consider importing this macro through its public re-export | LL + use crate::hey::bla; | @@ -23,7 +23,7 @@ error: cannot find derive macro `Bla` in this scope LL | #[derive(Bla)] | ^^^ | -help: consider importing this derive macro +help: consider importing this derive macro through its public re-export | LL + use crate::hey::Bla; | diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index da4b9595c0e..ba885d1b97e 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,4 +1,4 @@ -error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { @@ -8,7 +8,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { LL | x | ^ | -help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/tests/ui/privacy/export-tag-variant.stderr b/tests/ui/privacy/export-tag-variant.stderr index f73bd454d35..e8906985e05 100644 --- a/tests/ui/privacy/export-tag-variant.stderr +++ b/tests/ui/privacy/export-tag-variant.stderr @@ -2,7 +2,9 @@ error[E0603]: enum `Y` is private --> $DIR/export-tag-variant.rs:7:26 | LL | fn main() { let z = foo::Y::Y1; } - | ^ private enum + | ^ -- unit variant `Y1` is not publicly re-exported + | | + | private enum | note: the enum `Y` is defined here --> $DIR/export-tag-variant.rs:4:5 diff --git a/tests/ui/privacy/privacy-in-paths.stderr b/tests/ui/privacy/privacy-in-paths.stderr index 2eb3ebb51c2..9c3d5e97c62 100644 --- a/tests/ui/privacy/privacy-in-paths.stderr +++ b/tests/ui/privacy/privacy-in-paths.stderr @@ -2,7 +2,9 @@ error[E0603]: module `bar` is private --> $DIR/privacy-in-paths.rs:24:16 | LL | ::foo::bar::baz::f(); - | ^^^ private module + | ^^^ - function `f` is not publicly re-exported + | | + | private module | note: the module `bar` is defined here --> $DIR/privacy-in-paths.rs:3:5 @@ -21,12 +23,18 @@ note: the module `bar` is defined here | LL | mod bar { | ^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL | foo::S::f(); + | ~~~~~~ error[E0603]: trait `T` is private --> $DIR/privacy-in-paths.rs:26:23 | LL | <() as ::foo::T>::Assoc::f(); - | ^ private trait + | ^ ----- associated type `Assoc` is not publicly re-exported + | | + | private trait | note: the trait `T` is defined here --> $DIR/privacy-in-paths.rs:8:5 diff --git a/tests/ui/privacy/privacy-ufcs.stderr b/tests/ui/privacy/privacy-ufcs.stderr index e93a458ce6c..f45f3d8ec37 100644 --- a/tests/ui/privacy/privacy-ufcs.stderr +++ b/tests/ui/privacy/privacy-ufcs.stderr @@ -2,7 +2,9 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ufcs.rs:12:20 | LL | <i32 as ::foo::Bar>::baz(); - | ^^^ private trait + | ^^^ --- associated function `baz` is not publicly re-exported + | | + | private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ufcs.rs:4:5 diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index 6ebed8ee062..ca8f242e0be 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -50,7 +50,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:104:16 | LL | ::bar::baz::A::foo(); - | ^^^ private module + | ^^^ - struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -62,7 +64,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:105:16 | LL | ::bar::baz::A::bar(); - | ^^^ private module + | ^^^ - struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -74,7 +78,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:107:16 | LL | ::bar::baz::A.foo2(); - | ^^^ private module + | ^^^ - unit struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -86,7 +92,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:108:16 | LL | ::bar::baz::A.bar2(); - | ^^^ private module + | ^^^ - unit struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -98,7 +106,9 @@ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:112:16 | LL | ::bar::B::foo(); - | ^ private trait + | ^ --- associated function `foo` is not publicly re-exported + | | + | private trait | note: the trait `B` is defined here --> $DIR/privacy1.rs:40:5 @@ -129,6 +139,10 @@ note: the module `baz` is defined here | LL | mod baz { | ^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL | bar::foo(); + | ~~~~~~~~ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:128:16 @@ -141,6 +155,10 @@ note: the module `baz` is defined here | LL | mod baz { | ^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL | bar::bar(); + | ~~~~~~~~ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:157:17 diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.rs b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs new file mode 100644 index 00000000000..426f21cc7de --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs @@ -0,0 +1,4 @@ +extern crate core; +use core::slice::index::private_slice_index::Sealed; //~ ERROR module `index` is private +fn main() { +} diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr new file mode 100644 index 00000000000..29499979866 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr @@ -0,0 +1,12 @@ +error[E0603]: module `index` is private + --> $DIR/private-trait-non-local.rs:2:18 + | +LL | use core::slice::index::private_slice_index::Sealed; + | ^^^^^ private module ------ trait `Sealed` is not publicly re-exported + | +note: the module `index` is defined here + --> $SRC_DIR/core/src/slice/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/private-trait.rs b/tests/ui/privacy/sealed-traits/private-trait.rs new file mode 100644 index 00000000000..bbcbaabfaf4 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait.rs @@ -0,0 +1,10 @@ +pub mod a { + mod b { + pub trait Hidden {} + } +} + +struct S; +impl a::b::Hidden for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/private-trait.stderr b/tests/ui/privacy/sealed-traits/private-trait.stderr new file mode 100644 index 00000000000..c7ec72ff166 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait.stderr @@ -0,0 +1,17 @@ +error[E0603]: module `b` is private + --> $DIR/private-trait.rs:8:9 + | +LL | impl a::b::Hidden for S {} + | ^ ------ trait `Hidden` is not publicly re-exported + | | + | private module + | +note: the module `b` is defined here + --> $DIR/private-trait.rs:2:5 + | +LL | mod b { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed new file mode 100644 index 00000000000..79b6a6516ab --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +pub mod a { + pub use self::b::Trait; + mod b { + pub trait Trait {} + } +} + +struct S; +impl a::Trait for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs new file mode 100644 index 00000000000..5f96dfdcbd6 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs @@ -0,0 +1,13 @@ +// run-rustfix + +pub mod a { + pub use self::b::Trait; + mod b { + pub trait Trait {} + } +} + +struct S; +impl a::b::Trait for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr new file mode 100644 index 00000000000..b630565d023 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -0,0 +1,19 @@ +error[E0603]: module `b` is private + --> $DIR/re-exported-trait.rs:11:9 + | +LL | impl a::b::Trait for S {} + | ^ private module + | +note: the module `b` is defined here + --> $DIR/re-exported-trait.rs:5:5 + | +LL | mod b { + | ^^^^^ +help: consider importing this trait through its public re-export instead + | +LL | impl a::Trait for S {} + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.rs b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs new file mode 100644 index 00000000000..778ddf0f817 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs @@ -0,0 +1,19 @@ +// provide custom privacy error for sealed traits +pub mod a { + pub trait Sealed: self::b::Hidden { + fn foo() {} + } + + struct X; + impl Sealed for X {} + impl self::b::Hidden for X {} + + mod b { + pub trait Hidden {} + } +} + +struct S; +impl a::Sealed for S {} //~ ERROR the trait bound `S: Hidden` is not satisfied + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr new file mode 100644 index 00000000000..d1052ce3508 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `S: Hidden` is not satisfied + --> $DIR/sealed-trait-local.rs:17:20 + | +LL | impl a::Sealed for S {} + | ^ the trait `Hidden` is not implemented for `S` + | +note: required by a bound in `Sealed` + --> $DIR/sealed-trait-local.rs:3:23 + | +LL | pub trait Sealed: self::b::Hidden { + | ^^^^^^^^^^^^^^^ required by this bound in `Sealed` + = note: `Sealed` is a "sealed trait", because to implement it you also need to implelement `a::b::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr index 7e7870b2951..566c4130846 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.stderr +++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr @@ -17,7 +17,7 @@ LL | #[derive(GenHelperUse)] | ^^^^^^^^^^^^ | = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this attribute macro +help: consider importing this attribute macro through its public re-export | LL + use empty_helper; | @@ -32,7 +32,7 @@ LL | gen_helper_use!(); | ----------------- in this macro invocation | = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this attribute macro +help: consider importing this attribute macro through its public re-export | LL + use crate::empty_helper; | diff --git a/tests/ui/reachable/unreachable-variant.stderr b/tests/ui/reachable/unreachable-variant.stderr index 6c27a2756f7..ca1d2be65ce 100644 --- a/tests/ui/reachable/unreachable-variant.stderr +++ b/tests/ui/reachable/unreachable-variant.stderr @@ -2,7 +2,7 @@ error[E0603]: module `super_sekrit` is private --> $DIR/unreachable-variant.rs:6:21 | LL | let _x = other::super_sekrit::sooper_sekrit::baz; - | ^^^^^^^^^^^^ private module + | ^^^^^^^^^^^^ private module --- unit variant `baz` is not publicly re-exported | note: the module `super_sekrit` is defined here --> $DIR/auxiliary/unreachable_variant.rs:1:1 diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr index 0bb09090569..b10eded015f 100644 --- a/tests/ui/resolve/privacy-enum-ctor.stderr +++ b/tests/ui/resolve/privacy-enum-ctor.stderr @@ -228,7 +228,9 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:61:22 | LL | let _: Z = m::n::Z::Fn; - | ^ private enum + | ^ -- tuple variant `Fn` is not publicly re-exported + | | + | private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -252,7 +254,9 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:68:22 | LL | let _: Z = m::n::Z::Unit {}; - | ^ private enum + | ^ ---- variant `Unit` is not publicly re-exported + | | + | private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr index 2f02a24960e..cc8758714fc 100644 --- a/tests/ui/stability-attribute/stability-in-private-module.stderr +++ b/tests/ui/stability-attribute/stability-in-private-module.stderr @@ -2,7 +2,9 @@ error[E0603]: module `thread_info` is private --> $DIR/stability-in-private-module.rs:2:26 | LL | let _ = std::thread::thread_info::current_thread(); - | ^^^^^^^^^^^ private module + | ^^^^^^^^^^^ -------------- function `current_thread` is not publicly re-exported + | | + | private module | note: the module `thread_info` is defined here --> $SRC_DIR/std/src/thread/mod.rs:LL:COL diff --git a/tests/ui/stdlib-unit-tests/not-sync.rs b/tests/ui/stdlib-unit-tests/not-sync.rs index f4648994fa9..e9395ae9e81 100644 --- a/tests/ui/stdlib-unit-tests/not-sync.rs +++ b/tests/ui/stdlib-unit-tests/not-sync.rs @@ -17,6 +17,4 @@ fn main() { test::<Receiver<i32>>(); //~^ ERROR `std::sync::mpsc::Receiver<i32>` cannot be shared between threads safely [E0277] - test::<Sender<i32>>(); - //~^ ERROR `Sender<i32>` cannot be shared between threads safely [E0277] } diff --git a/tests/ui/stdlib-unit-tests/not-sync.stderr b/tests/ui/stdlib-unit-tests/not-sync.stderr index 4e34e10e377..b9a266e4eb9 100644 --- a/tests/ui/stdlib-unit-tests/not-sync.stderr +++ b/tests/ui/stdlib-unit-tests/not-sync.stderr @@ -65,19 +65,6 @@ note: required by a bound in `test` LL | fn test<T: Sync>() {} | ^^^^ required by this bound in `test` -error[E0277]: `Sender<i32>` cannot be shared between threads safely - --> $DIR/not-sync.rs:20:12 - | -LL | test::<Sender<i32>>(); - | ^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely - | - = help: the trait `Sync` is not implemented for `Sender<i32>` -note: required by a bound in `test` - --> $DIR/not-sync.rs:5:12 - | -LL | fn test<T: Sync>() {} - | ^^^^ required by this bound in `test` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/structs/struct-variant-privacy-xc.stderr b/tests/ui/structs/struct-variant-privacy-xc.stderr index 1c1caaef8b7..7a1c84badef 100644 --- a/tests/ui/structs/struct-variant-privacy-xc.stderr +++ b/tests/ui/structs/struct-variant-privacy-xc.stderr @@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy-xc.rs:7:33 | LL | struct_variant_privacy::Bar::Baz { a: _a } => {} - | ^^^ private enum + | ^^^ --- variant `Baz` is not publicly re-exported + | | + | private enum | note: the enum `Bar` is defined here --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 diff --git a/tests/ui/structs/struct-variant-privacy.stderr b/tests/ui/structs/struct-variant-privacy.stderr index eafd26c716f..eabd66907f6 100644 --- a/tests/ui/structs/struct-variant-privacy.stderr +++ b/tests/ui/structs/struct-variant-privacy.stderr @@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy.rs:10:14 | LL | foo::Bar::Baz { a: _a } => {} - | ^^^ private enum + | ^^^ --- variant `Baz` is not publicly re-exported + | | + | private enum | note: the enum `Bar` is defined here --> $DIR/struct-variant-privacy.rs:2:5 diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs index 874dbdb42c3..fa67a784de4 100644 --- a/tests/ui/test-attrs/test-panic-abort-disabled.rs +++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs @@ -3,6 +3,7 @@ // compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no // run-flags: --test-threads=1 +// needs-unwind // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index 8416270fd81..d6d44a6b446 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -1,9 +1,8 @@ -// compile-flags: --test +// compile-flags: --test -Zpanic-abort-tests // run-flags: --test-threads=1 // check-run-results // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" // ignore-emscripten no threads support -// needs-unwind // run-pass #[test] diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 00294c708f1..6b6a77e2c7e 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -23,5 +23,7 @@ fn main() { drop(<() as Foo>::copy_me(&x)); //~^ ERROR `<() as Foo>::Item: Copy` is not satisfied //~| ERROR `<() as Foo>::Item` is not well-formed + //~| ERROR `<() as Foo>::Item` is not well-formed + //~| ERROR `<() as Foo>::Item` is not well-formed println!("{x}"); } diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index 9a43d2a6639..89abc608213 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -19,6 +19,18 @@ error: the type `<() as Foo>::Item` is not well-formed LL | drop(<() as Foo>::copy_me(&x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: the type `<() as Foo>::Item` is not well-formed + --> $DIR/alias-bound-unsound.rs:23:5 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^^^ + +error: the type `<() as Foo>::Item` is not well-formed + --> $DIR/alias-bound-unsound.rs:23:10 + | +LL | drop(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs new file mode 100644 index 00000000000..97c44305864 --- /dev/null +++ b/tests/ui/traits/new-solver/member-constraints-in-root-universe.rs @@ -0,0 +1,17 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Trait { + type Ty; +} + +impl Trait for for<'a> fn(&'a u8, &'a u8) { + type Ty = (); +} + +// argument is necessary to create universes before registering the hidden type. +fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized { + "hidden type is `&'?0 str` with '?0 member of ['static,]" +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs new file mode 100644 index 00000000000..eb19b49c7e2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs @@ -0,0 +1,28 @@ +//! This test shows that a field type that is a projection that resolves to an opaque, +//! is not a defining use. While we could substitute the struct generics, that would +//! mean we would have to walk all substitutions of an `Foo`, which can quickly +//! degenerate into looking at an exponential number of types depending on the complexity +//! of a program. + +#![feature(impl_trait_in_assoc_type)] + +struct Bar; + +trait Trait: Sized { + type Assoc; + fn foo() -> Foo<Self>; +} + +impl Trait for Bar { + type Assoc = impl std::fmt::Debug; + fn foo() -> Foo<Bar> { + Foo { field: () } + //~^ ERROR: mismatched types + } +} + +struct Foo<T: Trait> { + field: <T as Trait>::Assoc, +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr new file mode 100644 index 00000000000..648efd1cbfe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/hidden_behind_projection_behind_struct_field.rs:19:22 + | +LL | type Assoc = impl std::fmt::Debug; + | -------------------- the expected opaque type +LL | fn foo() -> Foo<Bar> { +LL | Foo { field: () } + | ^^ expected opaque type, found `()` + | + = note: expected opaque type `<Bar as Trait>::Assoc` + found unit type `()` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/hidden_behind_projection_behind_struct_field.rs:18:8 + | +LL | fn foo() -> Foo<Bar> { + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs new file mode 100644 index 00000000000..58778702de6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs @@ -0,0 +1,30 @@ +//! This test shows that the appearance of an opaque type +//! in the substs of a struct are enough to make it count +//! for making the function a defining use. It doesn't matter +//! if the opaque type is actually used in the field. + +#![feature(impl_trait_in_assoc_type)] +// check-pass + +use std::marker::PhantomData; + +struct Bar; + +trait Trait: Sized { + type Assoc; + fn foo() -> Foo<Self::Assoc>; +} + +impl Trait for Bar { + type Assoc = impl std::fmt::Debug; + fn foo() -> Foo<Self::Assoc> { + let foo: Foo<()> = Foo { field: PhantomData }; + foo + } +} + +struct Foo<T> { + field: PhantomData<T>, +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs new file mode 100644 index 00000000000..e440dce5e51 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs @@ -0,0 +1,26 @@ +//! This test shows that we can even follow projections +//! into associated types of the same impl if they are +//! indirectly mentioned in a struct field. + +#![feature(impl_trait_in_assoc_type)] +// check-pass + +struct Bar; + +trait Trait: Sized { + type Assoc; + fn foo() -> Foo; +} + +impl Trait for Bar { + type Assoc = impl std::fmt::Debug; + fn foo() -> Foo { + Foo { field: () } + } +} + +struct Foo { + field: <Bar as Trait>::Assoc, +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs new file mode 100644 index 00000000000..839a611cb71 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs @@ -0,0 +1,35 @@ +//! This test checks that we can't actually have an opaque type behind +//! a binder that references variables from that binder. + +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +trait B { + type C; +} + +struct A; + +impl<'a> B for &'a A { + type C = Tait<'a>; +} + +type Tait<'a> = impl std::fmt::Debug + 'a; + +struct Terminator; + +type Successors<'a> = impl std::fmt::Debug + 'a; + +impl Terminator { + fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { + f = g; + //~^ ERROR: mismatched types + } +} + +fn g(x: &()) -> &() { + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr new file mode 100644 index 00000000000..aaba9ad5ca7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/higher_kinded_params3.rs:26:9 + | +LL | type Tait<'a> = impl std::fmt::Debug + 'a; + | ------------------------- the expected opaque type +... +LL | f = g; + | ^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>` + found fn pointer `for<'a> fn(&'a ()) -> &'a ()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs new file mode 100644 index 00000000000..a3f65146f75 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs @@ -0,0 +1,28 @@ +#![feature(impl_trait_in_assoc_type)] + +// We weren't checking that the trait and impl generics line up in the +// normalization-shortcut code in `OpaqueTypeCollector`. + +use std::ops::Deref; + +trait Foo { + type Bar<'a>; + + type Baz<'a>; + + fn test<'a>() -> Self::Bar<'a>; +} + +impl Foo for () { + type Bar<'a> = impl Deref<Target = Self::Baz<'a>>; + + type Baz<T> = impl Sized; + //~^ ERROR type `Baz` has 1 type parameter but its trait declaration has 0 type parameters + //~| ERROR unconstrained opaque type + + fn test<'a>() -> Self::Bar<'a> { + &() + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr new file mode 100644 index 00000000000..13f5d8b8ea6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr @@ -0,0 +1,20 @@ +error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14 + | +LL | type Baz<'a>; + | -- expected 0 type parameters +... +LL | type Baz<T> = impl Sized; + | ^ found 1 type parameter + +error: unconstrained opaque type + --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:19 + | +LL | type Baz<T> = impl Sized; + | ^^^^^^^^^^ + | + = note: `Baz` must be used in combination with a concrete type within the same impl + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr index 2beed73cb85..6ec5d13f812 100644 --- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr +++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr @@ -12,10 +12,10 @@ LL | let x: Self::Foo = (); = note: expected opaque type `<() as Foo>::Foo` found unit type `()` note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5 + --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:8 | LL | fn bar() { - | ^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs new file mode 100644 index 00000000000..b5ff06572d0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multi-error.rs @@ -0,0 +1,23 @@ +//! This test checks that we don't follow up +//! with type mismatch errors of opaque types +//! with their hidden types if we failed the +//! defining scope check at the signature level. + +#![feature(impl_trait_in_assoc_type)] + +trait Foo { + type Bar<T>; + type Baz; + fn foo() -> (Self::Bar<u32>, Self::Baz); +} + +impl Foo for () { + type Bar<T> = impl Sized; + type Baz = impl Sized; + fn foo() -> (Self::Bar<u32>, Self::Baz) { + //~^ ERROR non-defining opaque type use + ((), ()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr new file mode 100644 index 00000000000..b2de2effea6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multi-error.stderr @@ -0,0 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/multi-error.rs:17:17 + | +LL | fn foo() -> (Self::Bar<u32>, Self::Baz) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `u32` is not a generic parameter + | +note: for this opaque type + --> $DIR/multi-error.rs:15:19 + | +LL | type Bar<T> = impl Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.rs b/tests/ui/type-alias-impl-trait/non-defining-method.rs new file mode 100644 index 00000000000..2f4a7052f72 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-defining-method.rs @@ -0,0 +1,21 @@ +//! This test checks that we don't follow up +//! with type mismatch errors of opaque types +//! with their hidden types if we failed the +//! defining scope check at the signature level. + +#![feature(impl_trait_in_assoc_type)] + +trait Foo { + type Bar<T>; + fn foo() -> Self::Bar<u32>; + fn bar<T>() -> Self::Bar<T>; +} + +impl Foo for () { + type Bar<T> = impl Sized; + fn foo() -> Self::Bar<u32> {} + //~^ ERROR non-defining opaque type use + fn bar<T>() -> Self::Bar<T> {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr new file mode 100644 index 00000000000..ed5590f9d71 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr @@ -0,0 +1,15 @@ +error[E0792]: non-defining opaque type use in defining scope + --> $DIR/non-defining-method.rs:16:17 + | +LL | fn foo() -> Self::Bar<u32> {} + | ^^^^^^^^^^^^^^ argument `u32` is not a generic parameter + | +note: for this opaque type + --> $DIR/non-defining-method.rs:15:19 + | +LL | type Bar<T> = impl Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr new file mode 100644 index 00000000000..dd2737c706d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr @@ -0,0 +1,55 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/normalize-hidden-types.rs:25:20 + | +LL | fn define() -> Opaque { + | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)` + | +note: previous use here + --> $DIR/normalize-hidden-types.rs:27:9 + | +LL | dyn_hoops::<_>(0) + | ^^^^^^^^^^^^^^^^^ + +error: concrete type differs from previous defining opaque type use + --> $DIR/normalize-hidden-types.rs:34:22 + | +LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } + | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)` + | +note: previous use here + --> $DIR/normalize-hidden-types.rs:34:31 + | +LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/normalize-hidden-types.rs:44:25 + | +LL | type Opaque = impl Sized; + | ---------- the expected opaque type +... +LL | let _: Opaque = dyn_hoops::<u8>(0); + | ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())` + | | + | expected due to this + | + = note: expected opaque type `typeck::Opaque` + found raw pointer `*const (dyn FnOnce(()) + 'static)` + = help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: concrete type differs from previous defining opaque type use + --> $DIR/normalize-hidden-types.rs:54:25 + | +LL | let _: Opaque = dyn_hoops::<_>(0); + | ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)` + | +note: previous use here + --> $DIR/normalize-hidden-types.rs:56:9 + | +LL | None + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs new file mode 100644 index 00000000000..8d80546444a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs @@ -0,0 +1,60 @@ +// Regression test for #112691 +// +// revisions: current next +// [next] compile-flags: -Ztrait-solver=next +// [next] check-pass +// [current]: known-bug: #112691 + +#![feature(type_alias_impl_trait)] + +trait Trait { + type Gat<'lt>; +} + +impl Trait for u8 { + type Gat<'lt> = (); +} + +fn dyn_hoops<T: Trait>(_: T) -> *const dyn FnOnce(T::Gat<'_>) { + loop {} +} + +mod typeof_1 { + use super::*; + type Opaque = impl Sized; + fn define() -> Opaque { + //[current]~^ ERROR concrete type differs + dyn_hoops::<_>(0) + } +} + +mod typeof_2 { + use super::*; + type Opaque = impl Sized; + fn define_1() -> Opaque { dyn_hoops::<_>(0) } + //[current]~^ ERROR concrete type differs + fn define_2() -> Opaque { dyn_hoops::<u8>(0) } +} + +mod typeck { + use super::*; + type Opaque = impl Sized; + fn define() -> Option<Opaque> { + let _: Opaque = dyn_hoops::<_>(0); + let _: Opaque = dyn_hoops::<u8>(0); + //[current]~^ ERROR mismatched types + None + } +} + +mod borrowck { + use super::*; + type Opaque = impl Sized; + fn define() -> Option<Opaque> { + let _: Opaque = dyn_hoops::<_>(0); + //[current]~^ ERROR concrete type differs + None + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs new file mode 100644 index 00000000000..131f8d999d8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs @@ -0,0 +1,33 @@ +#![feature(impl_trait_in_assoc_type)] + +trait Foo<T> { + type Assoc; + + fn test() -> u32; +} + +struct DefinesOpaque; +impl Foo<DefinesOpaque> for () { + type Assoc = impl Sized; + + // This test's return type is `u32`, *not* the opaque that is defined above. + // Previously we were only checking that the self type of the assoc matched, + // but this doesn't account for other impls with different trait substs. + fn test() -> <() as Foo<NoOpaques>>::Assoc { + let _: <Self as Foo<DefinesOpaque>>::Assoc = ""; + //~^ ERROR mismatched types + + 1 + } +} + +struct NoOpaques; +impl Foo<NoOpaques> for () { + type Assoc = u32; + + fn test() -> u32 { + 1 + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr new file mode 100644 index 00000000000..a621bb519cd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/not-matching-trait-refs-isnt-defining.rs:17:54 + | +LL | type Assoc = impl Sized; + | ---------- the expected opaque type +... +LL | let _: <Self as Foo<DefinesOpaque>>::Assoc = ""; + | ----------------------------------- ^^ expected opaque type, found `&str` + | | + | expected due to this + | + = note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc` + found reference `&'static str` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/not-matching-trait-refs-isnt-defining.rs:16:8 + | +LL | fn test() -> <() as Foo<NoOpaques>>::Assoc { + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr index 24f5cc8c733..e9032433494 100644 --- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -25,11 +25,6 @@ LL | fn dont_define_this(_private: Private) {} | ^^^^^^^ = note: expected signature `fn(Private)` found signature `fn(MyPrivate)` -note: this item must have the opaque type in its signature in order to be able to register hidden types - --> $DIR/unnameable_type.rs:20:5 - | -LL | fn dont_define_this(_private: MyPrivate) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/use/use-keyword.rs b/tests/ui/use/use-keyword.rs index c30c2e06c45..840cddcb907 100644 --- a/tests/ui/use/use-keyword.rs +++ b/tests/ui/use/use-keyword.rs @@ -1,4 +1,4 @@ -// Check that imports with nakes super and self don't fail during parsing +// Check that imports with naked super and self don't fail during parsing // FIXME: this shouldn't fail during name resolution either mod a { diff --git a/tests/ui/xcrate/xcrate-private-by-default.stderr b/tests/ui/xcrate/xcrate-private-by-default.stderr index 0bdd4002f40..25bbbf5f62a 100644 --- a/tests/ui/xcrate/xcrate-private-by-default.stderr +++ b/tests/ui/xcrate/xcrate-private-by-default.stderr @@ -62,7 +62,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:35:29 | LL | static_priv_by_default::foo::a; - | ^^^ private module + | ^^^ - static `a` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -74,7 +76,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:37:29 | LL | static_priv_by_default::foo::b; - | ^^^ private module + | ^^^ - function `b` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -86,7 +90,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:39:29 | LL | static_priv_by_default::foo::c; - | ^^^ private module + | ^^^ - unit struct `c` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -98,7 +104,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:41:35 | LL | foo::<static_priv_by_default::foo::d>(); - | ^^^ private module + | ^^^ - enum `d` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -110,7 +118,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:43:35 | LL | foo::<static_priv_by_default::foo::e>(); - | ^^^ private module + | ^^^ - type alias `e` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 |
