From 5be14f5fda8da0f9169bcb798488d3b90011207a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 14 Jun 2023 12:30:17 +0200 Subject: [PATCH 01/19] ensure test harness test works on panic=abort targets --- tests/ui/test-attrs/test-type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index 8416270fd8159..9c7b8b96d6908 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -1,4 +1,4 @@ -// 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" From 0526267ffd2d59305319f73c4a63055c34281e45 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 14 Jun 2023 12:19:21 +0200 Subject: [PATCH 02/19] mark relevant tests as requiring unwinding --- tests/ui/asm/aarch64/may_unwind.rs | 1 + tests/ui/test-attrs/test-panic-abort-disabled.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ui/asm/aarch64/may_unwind.rs b/tests/ui/asm/aarch64/may_unwind.rs index 6af8728bbaa96..cfb75078264df 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/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs index 874dbdb42c33c..fa67a784de47f 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 From f5d3de2abccd0de94d96367b35e33a776a242d69 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 14 Jun 2023 12:31:00 +0200 Subject: [PATCH 03/19] update codegent test to be independent of panic strategy --- tests/codegen/naked-nocoverage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/naked-nocoverage.rs b/tests/codegen/naked-nocoverage.rs index 91a6260bf2aa2..3c755e49c6dba 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 From 0d6da78b06e0fa4e1df1fe6795f3e17f0320071a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 03:18:12 +0000 Subject: [PATCH 04/19] Always register sized obligation for argument --- compiler/rustc_hir_typeck/src/check.rs | 5 +---- .../closures/cannot-call-unsized-via-ptr-2.rs | 11 ++++++++++ .../cannot-call-unsized-via-ptr-2.stderr | 21 +++++++++++++++++++ .../closures/cannot-call-unsized-via-ptr.rs | 10 +++++++++ .../cannot-call-unsized-via-ptr.stderr | 12 +++++++++++ tests/ui/issues/issue-5883.rs | 2 +- tests/ui/issues/issue-5883.stderr | 18 +--------------- 7 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 tests/ui/closures/cannot-call-unsized-via-ptr-2.rs create mode 100644 tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr create mode 100644 tests/ui/closures/cannot-call-unsized-via-ptr.rs create mode 100644 tests/ui/closures/cannot-call-unsized-via-ptr.stderr diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 69ccbf0b58ff3..0a1b639af5157 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/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 0000000000000..2d8565517e897 --- /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 0000000000000..d88b84365dfae --- /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 0000000000000..5ce4650b0333c --- /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 0000000000000..9ecc66d5ce897 --- /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/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs index 82866b355573c..f9dd2c54d997f 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 ffff403e0d465..a3e2531b5caa4 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`. From dd620aa73aac7dc219774c8e09fed13853d8af58 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Jun 2023 19:57:44 +0000 Subject: [PATCH 05/19] Don't ICE on unnormalized struct tail in layout computation --- compiler/rustc_middle/src/ty/layout.rs | 8 ++++++- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++++------ .../issue-112505-overflow.stderr | 4 ++-- tests/ui/const-generics/transmute-fail.stderr | 4 ++-- .../cannot-transmute-unnormalizable-type.rs | 22 +++++++++++++++++++ ...annot-transmute-unnormalizable-type.stderr | 19 ++++++++++++++++ 6 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 tests/ui/layout/cannot-transmute-unnormalizable-type.rs create mode 100644 tests/ui/layout/cannot-transmute-unnormalizable-type.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c5a306fdf1f9a..c1d6856d33c92 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_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 7015778e24b85..f35f501b902da 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -145,17 +145,20 @@ 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(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 +166,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 +184,7 @@ fn layout_of_uncached<'tcx>( vtable } _ => { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); } } }; diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr index 0432f2fa8be5d..bd8a4feeff5e7 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 3d1197afd0f79..9e308620a9c2e 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/layout/cannot-transmute-unnormalizable-type.rs b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs new file mode 100644 index 0000000000000..d2b6e1d8eba66 --- /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<&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 0000000000000..3cfa09ef9d499 --- /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<&Other>>(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<()>` (8 bits) + = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `::Metadata` 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`. From 32f83e18ab1891482873eea6e4337d610393c0a5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Jun 2023 20:00:37 +0000 Subject: [PATCH 06/19] Better error message --- compiler/rustc_ty_utils/src/layout.rs | 17 ++++++++++++++++- .../cannot-transmute-unnormalizable-type.stderr | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f35f501b902da..fde64cb3ee7d8 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -156,7 +156,22 @@ fn layout_of_uncached<'tcx>( pointee_metadata, ) { Ok(metadata_ty) => metadata_ty, - Err(err) => return Err(LayoutError::NormalizationFailure(pointee, err)), + Err(mut err) => { + // Usually `::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)?; diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr index 3cfa09ef9d499..dd5119318ff4b 100644 --- a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr @@ -11,7 +11,7 @@ LL | std::mem::transmute::, Option<&Other>>(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: source type: `Option<()>` (8 bits) - = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `::Metadata` cannot be normalized) + = 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 From fd4726f74041672c20e9e0753058bf7712dcff19 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 21 Jun 2023 09:14:47 +0200 Subject: [PATCH 07/19] remove needs-unwind attr for test with -Zpanic-abort-tests --- tests/ui/test-attrs/test-type.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index 9c7b8b96d6908..d6d44a6b4461b 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -3,7 +3,6 @@ // check-run-results // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" // ignore-emscripten no threads support -// needs-unwind // run-pass #[test] From aacd7028954608a2bb17fcbc8ea4c143aad206eb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 22 Jun 2023 14:11:10 +0000 Subject: [PATCH 08/19] Stop hiding const eval limit in external macros --- compiler/rustc_lint_defs/src/builtin.rs | 3 ++- tests/ui/consts/timeout.rs | 25 +++++++++++++++++++++++++ tests/ui/consts/timeout.stderr | 15 +++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/ui/consts/timeout.rs create mode 100644 tests/ui/consts/timeout.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 53ece08ac3d92..cbb4458d1d49a 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/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs new file mode 100644 index 0000000000000..c9094999ee276 --- /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 0000000000000..799b5ec8dd9f1 --- /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 + From 46a650f4e0783da10513e6d41c5f3c69e42b0198 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Jun 2023 20:46:46 +0000 Subject: [PATCH 09/19] Migrate item_bounds to ty::Clause --- .../src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 4 +- .../src/collect/item_bounds.rs | 34 ++++------ .../rustc_hir_analysis/src/variance/mod.rs | 13 ++-- compiler/rustc_hir_typeck/src/_match.rs | 16 ++--- compiler/rustc_hir_typeck/src/closure.rs | 9 ++- .../src/generator_interior/mod.rs | 2 +- .../src/infer/error_reporting/mod.rs | 6 +- .../rustc_infer/src/infer/opaque_types.rs | 4 +- .../rustc_infer/src/infer/outlives/verify.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 20 ++++++ .../src/opaque_hidden_inferred_bound.rs | 4 +- compiler/rustc_lint/src/unused.rs | 5 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 10 ++- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 7 ++ compiler/rustc_middle/src/ty/codec.rs | 21 ++++++ compiler/rustc_middle/src/ty/context.rs | 29 ++++++-- compiler/rustc_middle/src/ty/mod.rs | 27 +++++++- compiler/rustc_middle/src/ty/parameterized.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 6 +- .../rustc_middle/src/ty/structural_impls.rs | 9 +++ compiler/rustc_mir_transform/src/generator.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 68 ++++++++----------- .../src/solve/assembly/mod.rs | 10 ++- .../src/solve/assembly/structural_traits.rs | 6 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/object_safety.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/select/confirmation.rs | 4 +- .../src/traits/select/mod.rs | 4 +- compiler/rustc_traits/src/chalk/db.rs | 6 +- src/librustdoc/clean/mod.rs | 21 +++--- .../clippy_lints/src/future_not_send.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 14 ++-- 37 files changed, 232 insertions(+), 152 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7119510849a31..5c365e98f0bab 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_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 1dfe053b21530..596c5518086d6 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 51e9b4c4501d8..814a290178ebc 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, ) }); @@ -1562,7 +1562,7 @@ impl<'tcx> TypeVisitor> 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 5f35678d95d93..e976304828895 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.as_clause().unwrap(), 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::EarlyBinder<&'_ ty::List>> { 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/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 8bb9ca2acf24a..23d8da88a454b 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 a07580fe72d4a..c7fa27da1acfe 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/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 94b37fb3450d0..c64b64e925a45 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 dabe7749cb610..fdbb153ec7d44 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_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 63370eec10b29..15213c4b0239a 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/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3cb1788dc194a..0390c868c1b84 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -649,9 +649,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 59ae2ce6c603e..871171f9447fd 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 00d4934b74962..a6475a766c459 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -167,6 +167,26 @@ 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.as_clause().unwrap(), self.1) + } + + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + (predicate.as_clause().unwrap(), self.1) + } +} + impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { fn predicate(&self) -> ty::Predicate<'tcx> { self.as_predicate() diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 61c23b4c255e2..63a56806a4578 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 e0033c48edbf1..5015b751eeed4 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_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 21cbab542933c..90014bd92671d 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> for &'tcx [(ty::Predicate<'tcx } } +impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { + ty::codec::RefDecodable::decode(d) + } +} + impl<'a, 'tcx, T> Decodable> for LazyValue { 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/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index d11308196eafd..059cc0a36898a 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -375,7 +375,7 @@ define_tables! { is_type_alias_impl_trait: Table, attr_flags: Table, def_path_hashes: Table, - explicit_item_bounds: Table, Span)>>, + explicit_item_bounds: Table, Span)>>, inferred_outlives_of: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 440dede170049..6338e1719f475 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>> { + query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 105667ba1e6c0..a0fffce7071e3 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -798,6 +798,13 @@ impl<'a, 'tcx> Decodable> for &'tcx [(ty::Predicate<'tcx> } } +impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { + #[inline] + fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { + RefDecodable::decode(d) + } +} + impl<'a, 'tcx> Decodable> for &'tcx [(ty::ClauseKind<'tcx>, Span)] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index ff8cd904ef86b..d252a3fda5422 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>> Encodable for ty::Predicate<'tcx> } } +impl<'tcx, E: TyEncoder>> Encodable for ty::Clause<'tcx> { + fn encode(&self, e: &mut E) { + self.as_predicate().encode(e); + } +} + impl<'tcx, E: TyEncoder>> Encodable for ty::Region<'tcx> { fn encode(&self, e: &mut E) { self.kind().encode(e); @@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder>> Decodable for ty::Predicate<'tcx> } } +impl<'tcx, D: TyDecoder>> Decodable for ty::Clause<'tcx> { + fn decode(decoder: &mut D) -> ty::Clause<'tcx> { + let pred: ty::Predicate<'tcx> = Decodable::decode(decoder); + pred.as_clause().unwrap() + } +} + impl<'tcx, D: TyDecoder>> Decodable for SubstsRef<'tcx> { fn decode(decoder: &mut D) -> Self { let len = decoder.read_usize(); @@ -365,6 +378,14 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> } } +impl<'tcx, D: TyDecoder>> 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::>(), + ) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [(ty::ClauseKind<'tcx>, Span)] { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2b4f69167bfb0..b2ada4882e1a6 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>>, predicate: InternedSet<'tcx, WithCachedTypeInfo>>>, + // FIXME(clause): remove this when all usages are moved to predicate predicates: InternedSet<'tcx, List>>, + clauses: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, 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(), @@ -1533,6 +1536,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 +1568,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 +2088,13 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_predicates(preds) } + pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List> { + // 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(self, iter: I) -> T::Output where I: Iterator, @@ -2135,6 +2146,14 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_predicates(xs)) } + pub fn mk_clauses_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: CollectAndApply, &'tcx List>>, + { + T::collect_and_apply(iter, |xs| self.mk_clauses(xs)) + } + pub fn mk_type_list_from_iter(self, iter: I) -> T::Output where I: Iterator, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cd4591308278b..84ad96084c486 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>> { + 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>> { + 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)] @@ -1243,7 +1261,14 @@ 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() } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 97d13822adccf..cc2b26a5e1457 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 fdcc608bf8ed7..7afda73862d23 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 e53e1e0a54c52..2817d7256de84 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -713,6 +713,15 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { } } +impl<'tcx> TypeFoldable> for &'tcx ty::List> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) + } +} + impl<'tcx> TypeFoldable> for ty::Const<'tcx> { fn try_fold_with>>( self, diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 9f58cce276906..029fb2e9ba04c 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_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index b897a6198e366..8a848e5db6295 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -114,6 +114,12 @@ trait DefIdVisitor<'tcx> { ) -> ControlFlow { self.skeleton().visit_predicates(predicates) } + fn visit_clauses( + &mut self, + predicates: &[(ty::Clause<'tcx>, Span)], + ) -> ControlFlow { + 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 { - 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 { + 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 { 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 { + 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_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index f2a39faf38368..cde8a52cdec92 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 97b86a06c8cad..439cf788ab4f2 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/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 966c4a7dcf38f..dfb122e4c8c79 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() diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 499745473a22c..df93c4d45dc83 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 81b1ecc0d8819..2a78c5befa4da 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1585,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, ); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3c356978d5ca8..a50af417a4436 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 0f0e3f1f16a6a..0a8b7b688e7f8 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_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 38f94c3886188..7e64cbdf54a86 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::>::lower_into(bound, self.interner)) + .filter_map(|(bound, _)| { + LowerInto::>::lower_into(bound.as_predicate(), self.interner) + }) .collect() } } @@ -520,7 +522,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .filter_map(|bound| { LowerInto::< Option>> - >::lower_into(bound, self.interner) + >::lower_into(bound.as_predicate(), self.interner) }) .collect(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9a815694e1b47..f86c32158e0b3 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>, + bounds: Vec>, ) -> 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/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index a391b76910ad6..818ebd1134de0 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 12f18614d713e..2b185943c59ca 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`, it will register a predicate of `T: Trait`, 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`, it will register a predicate of `::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 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( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: &'tcx [Predicate<'tcx>], + predicates: impl IntoIterator>, predicates_id: Option, ) -> Option> { 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() { From 2fa796a3c796c819b53421577d5fd2e0f6a9f920 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Jun 2023 20:48:46 +0000 Subject: [PATCH 10/19] Expect clause more --- compiler/rustc_hir_analysis/src/collect/item_bounds.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 8 ++++---- compiler/rustc_middle/src/ty/codec.rs | 2 +- compiler/rustc_middle/src/ty/structural_impls.rs | 5 +---- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index e976304828895..958313fee6fb7 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -47,7 +47,7 @@ fn associated_type_bounds<'tcx>( } _ => false, }) - .map(|(pred, span)| (pred.as_clause().unwrap(), span)); + .map(|(pred, span)| (pred.expect_clause(), span)); let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); debug!( diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index a6475a766c459..2691987295298 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -173,7 +173,7 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { } fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - (predicate.as_clause().unwrap(), self.1) + (predicate.expect_clause(), self.1) } fn child_with_derived_cause( @@ -183,7 +183,7 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - (predicate.as_clause().unwrap(), self.1) + (predicate.expect_clause(), self.1) } } @@ -193,7 +193,7 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { } fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - predicate.as_clause().unwrap() + predicate.expect_clause() } fn child_with_derived_cause( @@ -203,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_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index d252a3fda5422..e2771fc53e758 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -250,7 +250,7 @@ impl<'tcx, D: TyDecoder>> Decodable for ty::Predicate<'tcx> impl<'tcx, D: TyDecoder>> Decodable for ty::Clause<'tcx> { fn decode(decoder: &mut D) -> ty::Clause<'tcx> { let pred: ty::Predicate<'tcx> = Decodable::decode(decoder); - pred.as_clause().unwrap() + pred.expect_clause() } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2817d7256de84..959bf032a83e4 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> for ty::Clause<'tcx> { self, folder: &mut F, ) -> Result { - 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()) } } From 471830b3a488b203e3bfde2e58eecad826287c2d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 20 Jun 2023 03:25:40 +0000 Subject: [PATCH 11/19] migrate inferred_outlives_of to Clause --- compiler/rustc_hir_analysis/src/outlives/mod.rs | 12 +++++++----- compiler/rustc_lint/src/builtin.rs | 8 ++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/query/on_disk_cache.rs | 7 ------- compiler/rustc_middle/src/ty/codec.rs | 10 ---------- compiler/rustc_middle/src/ty/mod.rs | 9 ++++++++- 7 files changed, 21 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 98f4a8e00ef90..48624cefe4d02 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 = 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_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9fb83bec99372..5c5ec4528504e 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> { 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> { 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_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 059cc0a36898a..9cffd96f4a396 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -376,7 +376,7 @@ define_tables! { attr_flags: Table, def_path_hashes: Table, explicit_item_bounds: Table, Span)>>, - inferred_outlives_of: Table, Span)>>, + inferred_outlives_of: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, opt_rpitit_info: Table>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6338e1719f475..5d6a477b9ad9c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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 a0fffce7071e3..220118ae5ccb8 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -805,13 +805,6 @@ impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, S } } -impl<'a, 'tcx> Decodable> for &'tcx [(ty::ClauseKind<'tcx>, Span)] { - #[inline] - fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { - RefDecodable::decode(d) - } -} - impl<'a, 'tcx> Decodable> for &'tcx [rustc_ast::InlineAsmTemplatePiece] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index e2771fc53e758..248251e1ef5a1 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -386,16 +386,6 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [(ty::Claus } } -impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> - for [(ty::ClauseKind<'tcx>, Span)] -{ - fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::>(), - ) - } -} - impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 84ad96084c486..0e604fdf6f499 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -731,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, Span)]>, + pub predicates: FxHashMap, Span)]>, } impl<'tcx> Predicate<'tcx> { @@ -1272,6 +1272,13 @@ impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { } } +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() + } +} + impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { From 65a7047ee470e71ccaf2a6ecdb38d7e8f1192664 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 14:18:05 +0200 Subject: [PATCH 12/19] Add @files command --- src/etc/htmldocck.py | 54 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index eade9e0455912..5ab1874e9ed46 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -110,6 +110,9 @@ * `@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 @@ def resolve_path(self, path): 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 @@ def get_tree(self, path): 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 @@ def get_tree(self, path): 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 + 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 = count test expected = int(c.args[2]) From 752fb52ae94cfb36bb01dff5b2b31134605a7da3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 15:12:13 +0200 Subject: [PATCH 13/19] Add @files checks in rustdoc tests --- tests/rustdoc/files-creation-hidden.rs | 1 + tests/rustdoc/files-creation-private.rs | 4 ++++ tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs | 6 ++++++ tests/rustdoc/issue-111249-file-creation.rs | 6 ++++++ 4 files changed, 17 insertions(+) diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs index bcabbfc91e869..498d9cdaef1f0 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 ca2327e0f911a..e2fdbc068f8aa 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/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs index d6832bb7a0977..65c26d6a83751 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 d2042b231e469..afd65ddaf941f 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' From 616469aa8aa84585bbaeaee0c9e5b9e06ec15149 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 15:50:20 +0200 Subject: [PATCH 14/19] Fix rustdoc-gui tester --- src/tools/rustdoc-gui-test/src/main.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index dc902f8cb0242..ed91763420a59 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>(path: P) -> Option { 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) { + 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); + if try_run(&mut command, config.verbose) { Ok(()) } else { Err(()) } } From d70faf3645d826bd8b0d76107d7b54db639fcec9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 15:50:30 +0200 Subject: [PATCH 15/19] Fix failing rustdoc GUI test --- tests/rustdoc-gui/search-result-color.goml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 193a3eb3fd134..e3c628b366fbd 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", ( From 2f3bed0c4c72cf4ef8019888a3bc7a9c515e6213 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 17 Jun 2023 13:58:27 +0200 Subject: [PATCH 16/19] Add link to rustdoc book search chapter in help popover --- src/librustdoc/html/static/js/main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f5296abaee661..3a9e94e9f9fe4 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1072,6 +1072,9 @@ function preLoadCss(cssUrl) { div_shortcuts.innerHTML = "

Keyboard Shortcuts

" + shortcuts + "
"; const infos = [ + "For a full list of all search features, take a look here.", "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ From 2f1939ab8b147b28809604d14876cb958e935cdd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 16:20:57 +0200 Subject: [PATCH 17/19] Link to the corresponding channel in the help popover --- src/librustdoc/clean/utils.rs | 3 +++ src/librustdoc/html/layout.rs | 2 ++ src/librustdoc/html/static/js/main.js | 11 ++++++----- src/librustdoc/html/templates/page.html | 1 + 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 294de12cea8e2..f375f0efbd17b 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/layout.rs b/src/librustdoc/html/layout.rs index 6ab849c92a076..8c5871d912647 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( sidebar, content, krate_with_trailing_slash, + rust_channel: *crate::clean::utils::DOC_CHANNEL, rustdoc_version, } .render() diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 3a9e94e9f9fe4..254b0d8bf5a43 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 \ - the rustdoc book."; + book_info.innerHTML = `You can find more information in \ +the rustdoc book.`; const shortcuts = [ ["?", "Show this help dialog"], @@ -1072,9 +1073,9 @@ function preLoadCss(cssUrl) { div_shortcuts.innerHTML = "

Keyboard Shortcuts

" + shortcuts + "
"; const infos = [ - "For a full list of all search features, take a look here.", + `For a full list of all search features, take a look here.`, "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 9133f899af60d..759c4fd601226 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}}" {#+ #} From 7b5577985df7e7f3132c1e8db1eb6e1022f31276 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 16:33:59 +0200 Subject: [PATCH 18/19] Make `try_run` return a `Result<(), ()>` instead of a boolean --- src/bootstrap/download.rs | 22 ++++++++------- src/bootstrap/lib.rs | 14 ++++++---- src/bootstrap/run.rs | 11 ++++---- src/bootstrap/test.rs | 38 ++++++++++++++------------ src/bootstrap/tool.rs | 2 +- src/bootstrap/util.rs | 2 +- src/tools/build_helper/src/util.rs | 20 ++++++++------ src/tools/rustdoc-gui-test/src/main.rs | 4 +-- 8 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 06f479808b975..cb40521dda763 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 d7e77aeb338f6..d389b568f563d 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, @@ -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 ec01f744b8250..c97b759273717 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 9212362f6c9e1..873ed61daf33c 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 96341b69df046..126f0b1eb31a4 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 1ec49f80d632e..b291584b300ce 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>( } 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/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs index 731095023a96e..11b8a228b8a8e 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/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index ed91763420a59..0ddd2c66cf9ea 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -128,7 +128,7 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse } } - if !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"); } @@ -161,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse command.args(&config.test_args); - if try_run(&mut command, config.verbose) { Ok(()) } else { Err(()) } + try_run(&mut command, config.verbose) } From 3b17012ac9db67be037e3ce3fa822e562a021eb4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jun 2023 19:34:37 +0200 Subject: [PATCH 19/19] Fix GUI test for popover --- tests/rustdoc-gui/help-page.goml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml index 1a1c1b28f6131..6e880302f28d5 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)