From 3f94047d8cd96846465048b5570d41cd1f90bd6f Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Sat, 23 Nov 2024 23:59:03 +0100 Subject: [PATCH 01/24] Switch rtems target to panic unwind --- compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs | 2 +- library/panic_unwind/src/lib.rs | 2 +- library/std/src/sys/personality/mod.rs | 2 +- library/unwind/src/lib.rs | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs index 4238c4c1c15f1..865549ab4862a 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), linker: None, relocation_model: RelocModel::Static, - panic_strategy: PanicStrategy::Abort, + panic_strategy: PanicStrategy::Unwind, features: "+thumb2,+neon,+vfp3".into(), max_atomic_width: Some(64), emit_debug_gdb_scripts: false, diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 1981675f40922..8c28bb5c5b033 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -46,7 +46,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems", target_os = "nuttx"))), + all(target_family = "unix", not(any(target_os = "espidf", target_os = "nuttx"))), all(target_vendor = "fortanix", target_env = "sgx"), target_family = "wasm", ))] { diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index 9754e840d151a..2e1d2e53a2979 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -31,7 +31,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems"), not(target_os = "nuttx")), + all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "nuttx")), all(target_vendor = "fortanix", target_env = "sgx"), ))] { mod gcc; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 79baa5b0b83ec..883de3174c8e8 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -20,7 +20,6 @@ cfg_if::cfg_if! { target_os = "l4re", target_os = "none", target_os = "espidf", - target_os = "rtems", target_os = "nuttx", ))] { // These "unix" family members do not have unwinder. From ed63d5ead5f44e5c1af376d7454135d006f0f0a8 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Tue, 31 Dec 2024 13:34:13 +0100 Subject: [PATCH 02/24] Make Boxy UwU --- .mailmap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 874a42656c512..fd075a4427f2f 100644 --- a/.mailmap +++ b/.mailmap @@ -84,7 +84,8 @@ boolean_coercion Boris Egorov bors bors[bot] <26634292+bors[bot]@users.noreply.github.com> bors bors[bot] -Boxy +BoxyUwU +BoxyUwU Braden Nelson Brandon Sanderson Brandon Sanderson Brett Cannon Brett Cannon From f3646748cd9d3cf5a6834f299acd10af1fe99c1b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 00:38:11 +0000 Subject: [PATCH 03/24] Remove hack for filtering out param-env outlives that match item-bound outlives --- .../src/infer/outlives/obligations.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index b1d5d688295d9..3512b2a5657eb 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -388,26 +388,9 @@ where // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty); + let approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty); debug!(?approx_env_bounds); - // Remove outlives bounds that we get from the environment but - // which are also deducible from the trait. This arises (cc - // #55756) in cases where you have e.g., `>::Item: - // 'a` in the environment but `trait Foo<'b> { type Item: 'b - // }` in the trait definition. - approx_env_bounds.retain(|bound_outlives| { - // OK to skip binder because we only manipulate and compare against other values from - // the same binder. e.g. if we have (e.g.) `for<'a> >::Item: 'a` in - // `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. If the - // declaration is `trait Trait<'b> { type Item: 'b; }`, then - // `projection_declared_bounds_from_trait` will be invoked with `['b => ^1]` and so we - // will get `^1` returned. - let bound = bound_outlives.skip_binder(); - let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") }; - self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1) - }); - // If declared bounds list is empty, the only applicable rule is // OutlivesProjectionComponent. If there are inference variables, // then, we can break down the outlives into more primitive From 2a373d7dd38a4bc3b04402d7cf84bd167727d1c8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 00:47:43 +0000 Subject: [PATCH 04/24] Make it clearer that the only infers we expect to see when processing outlives are regions --- compiler/rustc_infer/src/infer/outlives/obligations.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 3512b2a5657eb..0383c81f2af0d 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -363,6 +363,13 @@ where return; } + if alias_ty.has_non_region_infer() { + self.tcx + .dcx() + .span_delayed_bug(origin.span(), "an alias has infers during region solving"); + return; + } + // This case is thorny for inference. The fundamental problem is // that there are many cases where we have choice, and inference // doesn't like choice (the current region inference in @@ -408,7 +415,7 @@ where let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque; if approx_env_bounds.is_empty() && trait_bounds.is_empty() - && (alias_ty.has_infer() || is_opaque) + && (alias_ty.has_infer_regions() || is_opaque) { debug!("no declared bounds"); let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id)); From dd210eca43bbada8835789f85f83fb106d70c637 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 01:30:55 +0000 Subject: [PATCH 05/24] Simplify declared_generic_bounds_from_env --- .../rustc_infer/src/infer/outlives/verify.rs | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 247fbc259652e..7a21c2883d1ac 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -192,7 +192,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// Obviously these must be approximate -- they are in fact both *over* and /// and *under* approximated: /// - /// * Over-approximated because we erase regions, so + /// * Over-approximated because we don't consider equality of regions. /// * Under-approximated because we look for syntactic equality and so for complex types /// like `>::Item` or whatever we may fail to figure out /// all the subtleties. @@ -205,13 +205,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { erased_ty: Ty<'tcx>, ) -> Vec> { let tcx = self.tcx; + let mut bounds = vec![]; // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| { + bounds.extend(self.caller_bounds.iter().copied().filter(move |outlives_predicate| { super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) - }); + })); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -224,37 +225,27 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // The problem is that the type of `x` is `&'a A`. To be // well-formed, then, A must outlive `'a`, but we don't know that // this holds from first principles. - let from_region_bound_pairs = - self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| { - debug!( - "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", - (r, p) - ); - // Fast path for the common case. - match (&p, erased_ty.kind()) { - // In outlive routines, all types are expected to be fully normalized. - // And therefore we can safely use structural equality for alias types. - (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} - (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} - (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {} - _ => return None, - } + bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| { + debug!( + "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", + (r, p) + ); + // Fast path for the common case. + match (&p, erased_ty.kind()) { + // In outlive routines, all types are expected to be fully normalized. + // And therefore we can safely use structural equality for alias types. + (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} + (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} + (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {} + _ => return None, + } - let p_ty = p.to_ty(tcx); - let erased_p_ty = self.tcx.erase_regions(p_ty); - (erased_p_ty == erased_ty) - .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) - }); + let p_ty = p.to_ty(tcx); + let erased_p_ty = self.tcx.erase_regions(p_ty); + (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r))) + })); - param_bounds - .chain(from_region_bound_pairs) - .inspect(|bound| { - debug!( - "declared_generic_bounds_from_env_for_erased_ty: result predicate = {:?}", - bound - ) - }) - .collect() + bounds } /// Given a projection like `>::Bar`, returns any bounds From c7cb8224e2020d30df6bceb8ea2e16e7a2594585 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 2 Jan 2025 11:58:15 -0700 Subject: [PATCH 06/24] rustdoc: treat `allowed_through_unstable_modules` as deprecation This ensures `std::intrinsics::transmute` is deemphasized in the search engine and other UI, by cleaning it into a deprecation without propagating it through reexports when the parent module is stable. --- src/librustdoc/clean/types.rs | 22 +++++++++++++++++++- src/librustdoc/passes/propagate_stability.rs | 9 ++++++++ tests/rustdoc-js-std/core-transmute.js | 11 ++++++++++ tests/rustdoc-js-std/transmute-fail.js | 3 ++- tests/rustdoc-js-std/transmute.js | 3 ++- 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/rustdoc-js-std/core-transmute.js diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3c4fad4bca97e..dcee96978d2b5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -400,7 +400,27 @@ impl Item { } pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option { - self.def_id().and_then(|did| tcx.lookup_deprecation(did)) + self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| { + // `allowed_through_unstable_modules` is a bug-compatibility hack for old rustc + // versions; the paths that are exposed through it are "deprecated" because they + // were never supposed to work at all. + let stab = self.stability(tcx)?; + if let rustc_attr_parsing::StabilityLevel::Stable { + allowed_through_unstable_modules: true, + .. + } = stab.level + { + Some(Deprecation { + // FIXME(#131676, #135003): when a note is added to this stability tag, + // translate it here + since: rustc_attr_parsing::DeprecatedSince::Unspecified, + note: None, + suggestion: None, + }) + } else { + None + } + }) } pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index 4c682c3d4ca05..9e06102bef6d4 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -107,6 +107,15 @@ fn merge_stability( || parent_stab.stable_since().is_some_and(|parent_since| parent_since > own_since)) { parent_stability + } else if let Some(mut own_stab) = own_stability + && let StabilityLevel::Stable { since, allowed_through_unstable_modules: true } = + own_stab.level + && let Some(parent_stab) = parent_stability + && parent_stab.is_stable() + { + // this property does not apply transitively through re-exports + own_stab.level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false }; + Some(own_stab) } else { own_stability } diff --git a/tests/rustdoc-js-std/core-transmute.js b/tests/rustdoc-js-std/core-transmute.js new file mode 100644 index 0000000000000..8c9910a32d7f1 --- /dev/null +++ b/tests/rustdoc-js-std/core-transmute.js @@ -0,0 +1,11 @@ +const FILTER_CRATE = "core"; +const EXPECTED = [ + { + 'query': 'generic:T -> generic:U', + 'others': [ + { 'path': 'core::intrinsics::simd', 'name': 'simd_as' }, + { 'path': 'core::intrinsics::simd', 'name': 'simd_cast' }, + { 'path': 'core::mem', 'name': 'transmute' }, + ], + }, +]; diff --git a/tests/rustdoc-js-std/transmute-fail.js b/tests/rustdoc-js-std/transmute-fail.js index c4dddf3cf3cee..ddfb276194818 100644 --- a/tests/rustdoc-js-std/transmute-fail.js +++ b/tests/rustdoc-js-std/transmute-fail.js @@ -1,4 +1,5 @@ // should-fail +const FILTER_CRATE = "std"; const EXPECTED = [ { // Keep this test case identical to `transmute`, except the @@ -7,7 +8,7 @@ const EXPECTED = [ 'others': [ { 'path': 'std::intrinsics::simd', 'name': 'simd_as' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' }, - { 'path': 'std::intrinsics', 'name': 'transmute' }, + { 'path': 'std::mem', 'name': 'transmute' }, ], }, ]; diff --git a/tests/rustdoc-js-std/transmute.js b/tests/rustdoc-js-std/transmute.js index 0e52e21e0dead..f52e0ab14362d 100644 --- a/tests/rustdoc-js-std/transmute.js +++ b/tests/rustdoc-js-std/transmute.js @@ -1,3 +1,4 @@ +const FILTER_CRATE = "std"; const EXPECTED = [ { // Keep this test case identical to `transmute-fail`, except the @@ -6,7 +7,7 @@ const EXPECTED = [ 'others': [ { 'path': 'std::intrinsics::simd', 'name': 'simd_as' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' }, - { 'path': 'std::intrinsics', 'name': 'transmute' }, + { 'path': 'std::mem', 'name': 'transmute' }, ], }, ]; From 8af769d1b13faf4863b1ed06e800dd8faa2d75e4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 2 Jan 2025 14:08:43 -0700 Subject: [PATCH 07/24] Use `is_some_and` helper Co-authored-by: Guillaume Gomez --- src/librustdoc/passes/propagate_stability.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index 9e06102bef6d4..d892c58583778 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -110,8 +110,7 @@ fn merge_stability( } else if let Some(mut own_stab) = own_stability && let StabilityLevel::Stable { since, allowed_through_unstable_modules: true } = own_stab.level - && let Some(parent_stab) = parent_stability - && parent_stab.is_stable() + && parent_stability.is_some_and(|stab| stab.is_stable()) { // this property does not apply transitively through re-exports own_stab.level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false }; From c5d4996404fe7ed37a94d83d7b632ed6a566d2ac Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 18:19:46 +0000 Subject: [PATCH 08/24] nit: Make get_infer_ret_ty name more consistent with is_suggestable_infer_ty --- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_ty_utils/src/sig_types.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7a3cde4bc2fb7..44762299ee833 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3387,7 +3387,7 @@ impl<'hir> FnRetTy<'hir> { } } - pub fn get_infer_ret_ty(&self) -> Option<&'hir Ty<'hir>> { + pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> { if let Self::Return(ty) = self { if ty.is_suggestable_infer_ty() { return Some(*ty); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index ada70117b626f..2ba7e2d16696f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1371,7 +1371,7 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( generics: &'tcx hir::Generics<'tcx>, def_id: LocalDefId, ) -> ty::PolyFnSig<'tcx> { - if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() { + if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() { return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 66255829dcffe..c933095fd3db5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -187,7 +187,7 @@ impl TaitConstraintLocator<'_> { "foreign items cannot constrain opaque types", ); if let Some(hir_sig) = hir_node.fn_sig() - && hir_sig.decl.output.get_infer_ret_ty().is_some() + && hir_sig.decl.output.is_suggestable_infer_ty().is_some() { let guar = self.tcx.dcx().span_delayed_bug( hir_sig.decl.output.span(), diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 91ea34eb54d35..b24aa0e469383 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -150,7 +150,7 @@ fn typeck_with_fallback<'tcx>( let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { - let fn_sig = if decl.output.get_infer_ret_ty().is_some() { + let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() { fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None) } else { tcx.fn_sig(def_id).instantiate_identity() diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 6f1cbb0fee700..64e5a609b2f6d 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -31,7 +31,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // If the type of the item uses `_`, we're gonna error out anyway, but // typeck (which type_of invokes below), will call back into opaque_types_defined_by // causing a cycle. So we just bail out in this case. - if hir_sig.output.get_infer_ret_ty().is_some() { + if hir_sig.output.is_suggestable_infer_ty().is_some() { return V::Result::output(); } let ty_sig = tcx.fn_sig(item).instantiate_identity(); From c529fe0475e7c8161e950c9dc2d1409073593750 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 18:18:19 +0000 Subject: [PATCH 09/24] Remove diagnostic_only_typeck and fix placeholder suggestion for const/static --- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 43 +++++++++---------- compiler/rustc_middle/src/query/mod.rs | 3 -- .../generic_arg_infer/in-signature.stderr | 10 ++++- tests/ui/consts/issue-104768.rs | 1 + tests/ui/consts/issue-104768.stderr | 18 +++++++- .../assoc-const-missing-type.rs | 1 - .../assoc-const-missing-type.stderr | 18 ++------ tests/ui/parser/issues/issue-89574.rs | 1 - tests/ui/parser/issues/issue-89574.stderr | 10 +---- tests/ui/typeck/issue-79040.rs | 6 +-- tests/ui/typeck/issue-79040.stderr | 12 +----- .../ui/typeck/typeck_type_placeholder_item.rs | 1 + .../typeck_type_placeholder_item.stderr | 41 ++++++++++++------ 14 files changed, 85 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index c0526903e8881..f51018f5c3f80 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -412,7 +412,7 @@ fn infer_placeholder_type<'tcx>( kind: &'static str, ) -> Ty<'tcx> { let tcx = cx.tcx(); - let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); + let ty = tcx.typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, // then the user may have written e.g. `const A = 42;`. diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index b24aa0e469383..5a0a855147deb 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -87,21 +87,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { - let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); - typeck_with_fallback(tcx, def_id, fallback, None) -} - -/// Used only to get `TypeckResults` for type inference during error recovery. -/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. -fn diagnostic_only_typeck<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, -) -> &'tcx ty::TypeckResults<'tcx> { - let fallback = move || { - let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); - Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") - }; - typeck_with_fallback(tcx, def_id, fallback, None) + typeck_with_fallback(tcx, def_id, None) } /// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation. @@ -113,15 +99,13 @@ pub fn inspect_typeck<'tcx>( def_id: LocalDefId, inspect: ObligationInspector<'tcx>, ) -> &'tcx ty::TypeckResults<'tcx> { - let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); - typeck_with_fallback(tcx, def_id, fallback, Some(inspect)) + typeck_with_fallback(tcx, def_id, Some(inspect)) } -#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)] +#[instrument(level = "debug", skip(tcx, inspector), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - fallback: impl Fn() -> Ty<'tcx> + 'tcx, inspector: Option>, ) -> &'tcx ty::TypeckResults<'tcx> { // Closures' typeck results come from their outermost function, @@ -151,6 +135,10 @@ fn typeck_with_fallback<'tcx>( if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() { + // In the case that we're recovering `fn() -> W<_>` or some other return + // type that has an infer in it, lower the type directly so that it'll + // be correctly filled with infer. We'll use this inference to provide + // a suggestion later on. fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None) } else { tcx.fn_sig(def_id).instantiate_identity() @@ -164,8 +152,19 @@ fn typeck_with_fallback<'tcx>( check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params()); } else { - let expected_type = infer_type_if_missing(&fcx, node); - let expected_type = expected_type.unwrap_or_else(fallback); + let expected_type = if let Some(infer_ty) = infer_type_if_missing(&fcx, node) { + infer_ty + } else if let Some(ty) = node.ty() + && ty.is_suggestable_infer_ty() + { + // In the case that we're recovering `const X: [T; _]` or some other + // type that has an infer in it, lower the type directly so that it'll + // be correctly filled with infer. We'll use this inference to provide + // a suggestion later on. + fcx.lowerer().lower_ty(ty) + } else { + tcx.type_of(def_id).instantiate_identity() + }; let expected_type = fcx.normalize(body.value.span, expected_type); @@ -506,5 +505,5 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { pub fn provide(providers: &mut Providers) { method::provide(providers); - *providers = Providers { typeck, diagnostic_only_typeck, used_trait_imports, ..*providers }; + *providers = Providers { typeck, used_trait_imports, ..*providers }; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7e7b602c560ba..b6934495e4419 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1100,9 +1100,6 @@ rustc_queries! { desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) } } - query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { - desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } - } query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) } diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr index fcac95732d12e..afe6f5eb67e1c 100644 --- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -30,13 +30,19 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/in-signature.rs:22:15 | LL | const ARR_CT: [u8; _] = [0; 3]; - | ^^^^^^^ not allowed in type signatures + | ^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `[u8; 3]` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:24:20 | LL | static ARR_STATIC: [u8; _] = [0; 3]; - | ^^^^^^^ not allowed in type signatures + | ^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `[u8; 3]` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:26:14 diff --git a/tests/ui/consts/issue-104768.rs b/tests/ui/consts/issue-104768.rs index 3192daafa0b92..52a8070be4e41 100644 --- a/tests/ui/consts/issue-104768.rs +++ b/tests/ui/consts/issue-104768.rs @@ -1,4 +1,5 @@ const A: &_ = 0_u32; //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr index 8a4a41e4d68a8..b5f22763e28ed 100644 --- a/tests/ui/consts/issue-104768.stderr +++ b/tests/ui/consts/issue-104768.stderr @@ -1,3 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-104768.rs:1:15 + | +LL | const A: &_ = 0_u32; + | ^^^^^ expected `&_`, found `u32` + | + = note: expected reference `&'static _` + found type `u32` +help: consider borrowing here + | +LL | const A: &_ = &0_u32; + | + + error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/issue-104768.rs:1:10 | @@ -7,6 +20,7 @@ LL | const A: &_ = 0_u32; | not allowed in type signatures | help: replace with the correct type: `u32` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0308. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs index 93160f0b5758d..0c94a4262ef47 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.rs +++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs @@ -12,7 +12,6 @@ impl Trait for () { const K = (); //~^ ERROR missing type for `const` item //~| ERROR mismatched types - //~| ERROR mismatched types const Q = ""; //~^ ERROR missing type for `const` item //~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr index 6f35c0958d45c..5af119dffa7c8 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr +++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr @@ -16,7 +16,7 @@ LL | const K = (); | ^ help: provide a type for the associated constant: `()` error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration - --> $DIR/assoc-const-missing-type.rs:16:12 + --> $DIR/assoc-const-missing-type.rs:15:12 | LL | const Q<'a>: &'a str; | ---- lifetimes in impl do not match this const in trait @@ -25,24 +25,12 @@ LL | const Q = ""; | ^ lifetimes do not match const in trait error: missing type for `const` item - --> $DIR/assoc-const-missing-type.rs:16:12 + --> $DIR/assoc-const-missing-type.rs:15:12 | LL | const Q = ""; | ^ help: provide a type for the associated constant: `: &str` -error[E0308]: mismatched types - --> $DIR/assoc-const-missing-type.rs:12:18 - | -LL | const K = (); - | - ^^ expected type parameter `T`, found `()` - | | - | expected this type parameter - | - = note: expected type parameter `T` - found unit type `()` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0195, E0308. For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs index bafb0ce5e6680..276abfe71102b 100644 --- a/tests/ui/parser/issues/issue-89574.rs +++ b/tests/ui/parser/issues/issue-89574.rs @@ -2,5 +2,4 @@ fn main() { const EMPTY_ARRAY = []; //~^ missing type for `const` item //~| ERROR type annotations needed - //~| ERROR type annotations needed } diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr index aa5e66b18a927..f40f5aded8ef1 100644 --- a/tests/ui/parser/issues/issue-89574.stderr +++ b/tests/ui/parser/issues/issue-89574.stderr @@ -15,14 +15,6 @@ help: provide a type for the item LL | const EMPTY_ARRAY: = []; | ++++++++ -error[E0282]: type annotations needed - --> $DIR/issue-89574.rs:2:25 - | -LL | const EMPTY_ARRAY = []; - | ^^ cannot infer type - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/typeck/issue-79040.rs b/tests/ui/typeck/issue-79040.rs index 03e008207566e..f8e38e7867d52 100644 --- a/tests/ui/typeck/issue-79040.rs +++ b/tests/ui/typeck/issue-79040.rs @@ -1,6 +1,6 @@ fn main() { - const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str` - //~^ missing type for `const` item - //~| ERROR cannot add `{integer}` to `&str` + const FOO = "hello" + 1; + //~^ ERROR cannot add `{integer}` to `&str` + //~| missing type for `const` item println!("{}", FOO); } diff --git a/tests/ui/typeck/issue-79040.stderr b/tests/ui/typeck/issue-79040.stderr index 39636db85a784..4ab8df8f6c936 100644 --- a/tests/ui/typeck/issue-79040.stderr +++ b/tests/ui/typeck/issue-79040.stderr @@ -17,16 +17,6 @@ help: provide a type for the item LL | const FOO: = "hello" + 1; | ++++++++ -error[E0369]: cannot add `{integer}` to `&str` - --> $DIR/issue-79040.rs:2:25 - | -LL | const FOO = "hello" + 1; - | ------- ^ - {integer} - | | - | &str - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 437a1aed40307..9f1bfd7909e38 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -221,6 +221,7 @@ fn value() -> Option<&'static _> { const _: Option<_> = map(value); //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +//~| ERROR cannot call non-const function `map::` in constants fn evens_squared(n: usize) -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index e62ebae5fd24b..30cdd0e72a771 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -85,7 +85,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:19:15 | LL | static TEST5: (_, _) = (1, 2); - | ^^^^^^ not allowed in type signatures + | ^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `(i32, i32)` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:22:13 @@ -229,7 +232,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:77:15 | LL | static C: Option<_> = Some(42); - | ^^^^^^^^^ not allowed in type signatures + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:79:21 @@ -272,7 +278,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST5: (_, _) = (1, 2); - | ^^^^^^ not allowed in type signatures + | ^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `(i32, i32)` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:94:20 @@ -578,7 +587,7 @@ LL | const _: Option<_> = map(value); | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:225:31 + --> $DIR/typeck_type_placeholder_item.rs:226:31 | LL | fn evens_squared(n: usize) -> _ { | ^ @@ -587,13 +596,13 @@ LL | fn evens_squared(n: usize) -> _ { | help: replace with an appropriate return type: `impl Iterator` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:230:10 + --> $DIR/typeck_type_placeholder_item.rs:231:10 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^ not allowed in type signatures | -note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named - --> $DIR/typeck_type_placeholder_item.rs:230:14 +note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:231:29}>, {closure@typeck_type_placeholder_item.rs:231:49}>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:231:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -668,23 +677,31 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | type F: std::ops::Fn(_); | ^ not allowed in type signatures -error[E0015]: cannot call non-const method ` as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}>` in constants - --> $DIR/typeck_type_placeholder_item.rs:230:22 +error[E0015]: cannot call non-const function `map::` in constants + --> $DIR/typeck_type_placeholder_item.rs:222:22 + | +LL | const _: Option<_> = map(value); + | ^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const method ` as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}>` in constants + --> $DIR/typeck_type_placeholder_item.rs:231:22 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}> as Iterator>::map::` in constants - --> $DIR/typeck_type_placeholder_item.rs:230:45 +error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}> as Iterator>::map::` in constants + --> $DIR/typeck_type_placeholder_item.rs:231:45 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 74 previous errors +error: aborting due to 75 previous errors Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403. For more information about an error, try `rustc --explain E0015`. From b85a91fc598117ab23eb5dd294ed3371bc7081d9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 18:25:52 +0000 Subject: [PATCH 10/24] More refined spans for placeholder error in const/static --- .../rustc_hir_analysis/src/collect/type_of.rs | 13 ++++- .../generic_arg_infer/in-signature.stderr | 50 ++++++++++--------- tests/ui/consts/issue-104768.stderr | 8 +-- .../typeck_type_placeholder_item.stderr | 34 +++++++------ 4 files changed, 59 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index f51018f5c3f80..35a319dc5bd92 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -4,6 +4,7 @@ use rustc_errors::{Applicability, StashKey, Suggestions}; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::intravisit::Visitor; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -12,7 +13,7 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; -use super::{ItemCtxt, bad_placeholder}; +use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder}; use crate::errors::TypeofReservedKeywordUsed; use crate::hir_ty_lowering::HirTyLowerer; @@ -447,7 +448,15 @@ fn infer_placeholder_type<'tcx>( } }) .unwrap_or_else(|| { - let mut diag = bad_placeholder(cx, vec![span], kind); + let mut visitor = HirPlaceholderCollector::default(); + if let Some(ty) = tcx.hir_node_by_def_id(def_id).ty() { + visitor.visit_ty(ty); + } + // If we didn't find any infer tys, then just fallback to `span``. + if visitor.0.is_empty() { + visitor.0.push(span); + } + let mut diag = bad_placeholder(cx, visitor.0, kind); if !ty.references_error() { if let Some(ty) = ty.make_suggestable(tcx, false, None) { diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr index afe6f5eb67e1c..71fd5b140b1f7 100644 --- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -27,57 +27,59 @@ LL | fn ty_fn_mixed() -> Bar<_, _> { | help: replace with the correct return type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/in-signature.rs:22:15 + --> $DIR/in-signature.rs:22:20 | LL | const ARR_CT: [u8; _] = [0; 3]; - | ^^^^^^^ - | | - | not allowed in type signatures + | -----^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `[u8; 3]` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/in-signature.rs:24:20 + --> $DIR/in-signature.rs:24:25 | LL | static ARR_STATIC: [u8; _] = [0; 3]; - | ^^^^^^^ - | | - | not allowed in type signatures + | -----^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `[u8; 3]` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/in-signature.rs:26:14 + --> $DIR/in-signature.rs:26:23 | LL | const TY_CT: Bar = Bar::(0); - | ^^^^^^^^^^^ - | | - | not allowed in type signatures + | ---------^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/in-signature.rs:28:19 + --> $DIR/in-signature.rs:28:28 | LL | static TY_STATIC: Bar = Bar::(0); - | ^^^^^^^^^^^ - | | - | not allowed in type signatures + | ---------^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/in-signature.rs:30:20 + --> $DIR/in-signature.rs:30:24 | LL | const TY_CT_MIXED: Bar<_, _> = Bar::(0); - | ^^^^^^^^^ - | | - | not allowed in type signatures + | ----^--^- + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/in-signature.rs:32:25 + --> $DIR/in-signature.rs:32:29 | LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); - | ^^^^^^^^^ - | | - | not allowed in type signatures + | ----^--^- + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr index b5f22763e28ed..762fda74a83fb 100644 --- a/tests/ui/consts/issue-104768.stderr +++ b/tests/ui/consts/issue-104768.stderr @@ -12,12 +12,12 @@ LL | const A: &_ = &0_u32; | + error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/issue-104768.rs:1:10 + --> $DIR/issue-104768.rs:1:11 | LL | const A: &_ = 0_u32; - | ^^ - | | - | not allowed in type signatures + | -^ + | || + | |not allowed in type signatures | help: replace with the correct type: `u32` error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 30cdd0e72a771..09d03e7c75cfa 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -82,12 +82,13 @@ LL | static TEST4: _ = 145; | help: replace with the correct type: `i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/typeck_type_placeholder_item.rs:19:15 + --> $DIR/typeck_type_placeholder_item.rs:19:16 | LL | static TEST5: (_, _) = (1, 2); - | ^^^^^^ - | | - | not allowed in type signatures + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures | help: replace with the correct type: `(i32, i32)` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions @@ -229,12 +230,12 @@ LL | static B: _ = 42; | help: replace with the correct type: `i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/typeck_type_placeholder_item.rs:77:15 + --> $DIR/typeck_type_placeholder_item.rs:77:22 | LL | static C: Option<_> = Some(42); - | ^^^^^^^^^ - | | - | not allowed in type signatures + | -------^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types @@ -275,12 +276,13 @@ LL | static FN_TEST4: _ = 145; | help: replace with the correct type: `i32` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables - --> $DIR/typeck_type_placeholder_item.rs:91:22 + --> $DIR/typeck_type_placeholder_item.rs:91:23 | LL | static FN_TEST5: (_, _) = (1, 2); - | ^^^^^^ - | | - | not allowed in type signatures + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures | help: replace with the correct type: `(i32, i32)` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions @@ -578,12 +580,12 @@ LL | fn value() -> Option<&'static _> { | help: replace with the correct return type: `Option<&'static u8>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:222:10 + --> $DIR/typeck_type_placeholder_item.rs:222:17 | LL | const _: Option<_> = map(value); - | ^^^^^^^^^ - | | - | not allowed in type signatures + | -------^- + | | | + | | not allowed in type signatures | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types From 6885ff4a7b40f7550fd27c405c7f4ea3768bddb6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 18:49:43 +0000 Subject: [PATCH 11/24] Unconditionally lower generic_arg_infer --- compiler/rustc_ast_lowering/src/lib.rs | 9 +- .../rustc_hir_analysis/src/collect/type_of.rs | 17 +++- compiler/rustc_hir_typeck/src/expr.rs | 1 - .../suggest-array-length.fixed | 25 +++-- .../array-slice-vec/suggest-array-length.rs | 25 +++-- .../suggest-array-length.stderr | 93 +++++++------------ tests/ui/async-await/issues/issue-95307.rs | 4 +- .../ui/async-await/issues/issue-95307.stderr | 12 ++- ...ature-gate-generic_arg_infer.normal.stderr | 18 +--- .../feature-gate-generic_arg_infer.rs | 2 - 10 files changed, 89 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 46e91636cfbbb..fe2d5a594f312 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2031,11 +2031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> { match c.value.kind { ExprKind::Underscore => { - if self.tcx.features().generic_arg_infer() { - let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); - self.arena - .alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) - } else { + if !self.tcx.features().generic_arg_infer() { feature_err( &self.tcx.sess, sym::generic_arg_infer, @@ -2043,8 +2039,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fluent_generated::ast_lowering_underscore_array_length_unstable, ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - self.lower_anon_const_to_const_arg(c) } + let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); + self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) } _ => self.lower_anon_const_to_const_arg(c), } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 35a319dc5bd92..76e125aebf997 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -452,6 +452,12 @@ fn infer_placeholder_type<'tcx>( if let Some(ty) = tcx.hir_node_by_def_id(def_id).ty() { visitor.visit_ty(ty); } + // If we have just one span, let's try to steal a const `_` feature error. + let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.0.len() == 1 { + visitor.0.first().copied() + } else { + None + }; // If we didn't find any infer tys, then just fallback to `span``. if visitor.0.is_empty() { visitor.0.push(span); @@ -473,7 +479,16 @@ fn infer_placeholder_type<'tcx>( )); } } - diag.emit() + + if let Some(try_steal_span) = try_steal_span { + cx.dcx().try_steal_replace_and_emit_err( + try_steal_span, + StashKey::UnderscoreForArrayLengths, + diag, + ) + } else { + diag.emit() + } }); Ty::new_error(tcx, guar) } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8ba9a4bab5783..1f32887ce9b8e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1774,7 +1774,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(( _, hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }), )) = parent_node else { return; diff --git a/tests/ui/array-slice-vec/suggest-array-length.fixed b/tests/ui/array-slice-vec/suggest-array-length.fixed index 29f85da56e578..2eacc2517d310 100644 --- a/tests/ui/array-slice-vec/suggest-array-length.fixed +++ b/tests/ui/array-slice-vec/suggest-array-length.fixed @@ -3,24 +3,21 @@ fn main() { const Foo: [i32; 3] = [1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants const REF_FOO: &[u8; 1] = &[1]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + static Statik: [i32; 3] = [1, 2, 3]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + static REF_STATIK: &[u8; 1] = &[1]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables let foo: [i32; 3] = [1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let bar: [i32; 3] = [0; 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let ref_foo: &[i32; 3] = &[1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let ref_bar: &[i32; 3] = &[0; 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let multiple_ref_foo: &&[i32; 3] = &&[1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable } diff --git a/tests/ui/array-slice-vec/suggest-array-length.rs b/tests/ui/array-slice-vec/suggest-array-length.rs index 82d871cf8754a..fb4424cfed99d 100644 --- a/tests/ui/array-slice-vec/suggest-array-length.rs +++ b/tests/ui/array-slice-vec/suggest-array-length.rs @@ -3,24 +3,21 @@ fn main() { const Foo: [i32; _] = [1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants const REF_FOO: &[u8; _] = &[1]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + static Statik: [i32; _] = [1, 2, 3]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + static REF_STATIK: &[u8; _] = &[1]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables let foo: [i32; _] = [1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let bar: [i32; _] = [0; 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let ref_foo: &[i32; _] = &[1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let ref_bar: &[i32; _] = &[0; 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; - //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment - //~| ERROR using `_` for array lengths is unstable + //~^ ERROR using `_` for array lengths is unstable } diff --git a/tests/ui/array-slice-vec/suggest-array-length.stderr b/tests/ui/array-slice-vec/suggest-array-length.stderr index fdab7ba7064e4..c0fc2989d5b05 100644 --- a/tests/ui/array-slice-vec/suggest-array-length.stderr +++ b/tests/ui/array-slice-vec/suggest-array-length.stderr @@ -1,67 +1,41 @@ -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:11:20 - | -LL | let foo: [i32; _] = [1, 2, 3]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:14:20 - | -LL | let bar: [i32; _] = [0; 3]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:17:25 - | -LL | let ref_foo: &[i32; _] = &[1, 2, 3]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:20:25 - | -LL | let ref_bar: &[i32; _] = &[0; 3]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:23:35 - | -LL | let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/suggest-array-length.rs:5:22 | LL | const Foo: [i32; _] = [1, 2, 3]; - | ^ `_` not allowed here + | ------^- + | | | + | | not allowed in type signatures + | help: replace with the correct type: `[i32; 3]` -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/suggest-array-length.rs:8:26 +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/suggest-array-length.rs:7:26 | LL | const REF_FOO: &[u8; _] = &[1]; - | ^ `_` not allowed here + | ------^- + | | | + | | not allowed in type signatures + | help: replace with the correct type: `&[u8; 1]` -error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:5:22 - | -LL | const Foo: [i32; _] = [1, 2, 3]; - | ^ help: consider specifying the array length: `3` - | - = note: see issue #85077 for more information - = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/suggest-array-length.rs:9:26 + | +LL | static Statik: [i32; _] = [1, 2, 3]; + | ------^- + | | | + | | not allowed in type signatures + | help: replace with the correct type: `[i32; 3]` -error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:8:26 - | -LL | const REF_FOO: &[u8; _] = &[1]; - | ^ help: consider specifying the array length: `1` - | - = note: see issue #85077 for more information - = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/suggest-array-length.rs:11:30 + | +LL | static REF_STATIK: &[u8; _] = &[1]; + | ------^- + | | | + | | not allowed in type signatures + | help: replace with the correct type: `&[u8; 1]` error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:11:20 + --> $DIR/suggest-array-length.rs:13:20 | LL | let foo: [i32; _] = [1, 2, 3]; | ^ help: consider specifying the array length: `3` @@ -71,7 +45,7 @@ LL | let foo: [i32; _] = [1, 2, 3]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:14:20 + --> $DIR/suggest-array-length.rs:15:20 | LL | let bar: [i32; _] = [0; 3]; | ^ help: consider specifying the array length: `3` @@ -91,7 +65,7 @@ LL | let ref_foo: &[i32; _] = &[1, 2, 3]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:20:25 + --> $DIR/suggest-array-length.rs:19:25 | LL | let ref_bar: &[i32; _] = &[0; 3]; | ^ help: consider specifying the array length: `3` @@ -101,7 +75,7 @@ LL | let ref_bar: &[i32; _] = &[0; 3]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: using `_` for array lengths is unstable - --> $DIR/suggest-array-length.rs:23:35 + --> $DIR/suggest-array-length.rs:21:35 | LL | let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; | ^ help: consider specifying the array length: `3` @@ -110,6 +84,7 @@ LL | let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 14 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0121, E0658. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/async-await/issues/issue-95307.rs b/tests/ui/async-await/issues/issue-95307.rs index 40700c610f33b..27903a667fb5c 100644 --- a/tests/ui/async-await/issues/issue-95307.rs +++ b/tests/ui/async-await/issues/issue-95307.rs @@ -5,8 +5,8 @@ pub trait C { async fn new() -> [u8; _]; - //~^ ERROR: using `_` for array lengths is unstable - //~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR using `_` for array lengths is unstable } fn main() {} diff --git a/tests/ui/async-await/issues/issue-95307.stderr b/tests/ui/async-await/issues/issue-95307.stderr index dd8fcd3690a71..8445c3f981199 100644 --- a/tests/ui/async-await/issues/issue-95307.stderr +++ b/tests/ui/async-await/issues/issue-95307.stderr @@ -1,8 +1,13 @@ -error: in expressions, `_` can only be used on the left-hand side of an assignment +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-95307.rs:7:28 | LL | async fn new() -> [u8; _]; - | ^ `_` not allowed here + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | async fn new() -> [u8; T]; + | +++ ~ error[E0658]: using `_` for array lengths is unstable --> $DIR/issue-95307.rs:7:28 @@ -16,4 +21,5 @@ LL | async fn new() -> [u8; _]; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0121, E0658. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr index 97370f0489b56..96fb4a53609eb 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr @@ -1,17 +1,5 @@ -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/feature-gate-generic_arg_infer.rs:11:27 - | -LL | let _x: [u8; 3] = [0; _]; - | ^ `_` not allowed here - -error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/feature-gate-generic_arg_infer.rs:14:18 - | -LL | let _y: [u8; _] = [0; 3]; - | ^ `_` not allowed here - error[E0658]: using `_` for array lengths is unstable - --> $DIR/feature-gate-generic_arg_infer.rs:14:18 + --> $DIR/feature-gate-generic_arg_infer.rs:13:18 | LL | let _y: [u8; _] = [0; 3]; | ^ help: consider specifying the array length: `3` @@ -21,7 +9,7 @@ LL | let _y: [u8; _] = [0; 3]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0747]: type provided when a constant was expected - --> $DIR/feature-gate-generic_arg_infer.rs:20:20 + --> $DIR/feature-gate-generic_arg_infer.rs:18:20 | LL | let _x = foo::<_>([1,2]); | ^ @@ -42,7 +30,7 @@ LL | let _x: [u8; 3] = [0; _]; = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0658, E0747. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs index 0473253004a45..de4b7078ea683 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs @@ -10,10 +10,8 @@ fn foo(_: [u8; N]) -> [u8; N] { fn bar() { let _x: [u8; 3] = [0; _]; //[normal]~^ ERROR: using `_` for array lengths is unstable - //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment let _y: [u8; _] = [0; 3]; //[normal]~^ ERROR: using `_` for array lengths is unstable - //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment } fn main() { From 8e344ae127782afeda06062266945b8f6368c985 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 19:08:12 +0000 Subject: [PATCH 12/24] Suppress type param suggestion if encountering invalid const infer --- compiler/rustc_hir_analysis/src/collect.rs | 62 ++++++++++++++----- .../rustc_hir_analysis/src/collect/type_of.rs | 13 ++-- compiler/rustc_hir_typeck/src/expr.rs | 6 +- .../ui/async-await/issues/issue-95307.stderr | 5 -- 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2ba7e2d16696f..888605b2345df 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -131,19 +131,25 @@ pub struct ItemCtxt<'tcx> { /////////////////////////////////////////////////////////////////////////// #[derive(Default)] -pub(crate) struct HirPlaceholderCollector(pub(crate) Vec); +pub(crate) struct HirPlaceholderCollector { + pub spans: Vec, + // If any of the spans points to a const infer var, then suppress any messages + // that may try to turn that const infer into a type parameter. + pub may_contain_const_infer: bool, +} impl<'v> Visitor<'v> for HirPlaceholderCollector { fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { if let hir::TyKind::Infer = t.kind { - self.0.push(t.span); + self.spans.push(t.span); } intravisit::walk_ty(self, t) } fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) { match generic_arg { hir::GenericArg::Infer(inf) => { - self.0.push(inf.span); + self.spans.push(inf.span); + self.may_contain_const_infer = true; intravisit::walk_inf(self, inf); } hir::GenericArg::Type(t) => self.visit_ty(t), @@ -152,7 +158,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { } fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) { if let hir::ConstArgKind::Infer(span) = const_arg.kind { - self.0.push(span); + self.may_contain_const_infer = true; + self.spans.push(span); } intravisit::walk_const_arg(self, const_arg) } @@ -277,8 +284,8 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( placeholder_type_error( icx.lowerer(), Some(generics), - visitor.0, - suggest, + visitor.spans, + suggest && !visitor.may_contain_const_infer, None, item.kind.descr(), ); @@ -607,16 +614,16 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { hir::FnRetTy::DefaultReturn(..) => tcx.types.unit, }; - if !(visitor.0.is_empty() && infer_replacements.is_empty()) { + if !(visitor.spans.is_empty() && infer_replacements.is_empty()) { // We check for the presence of // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. let mut diag = crate::collect::placeholder_type_error_diag( self, generics, - visitor.0, + visitor.spans, infer_replacements.iter().map(|(s, _)| *s).collect(), - true, + !visitor.may_contain_const_infer, hir_ty, "function", ); @@ -712,7 +719,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { placeholder_type_error( icx.lowerer(), None, - visitor.0, + visitor.spans, false, None, "static variable", @@ -780,7 +787,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { placeholder_type_error( icx.lowerer(), None, - visitor.0, + visitor.spans, false, None, it.kind.descr(), @@ -822,7 +829,7 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { placeholder_type_error( icx.lowerer(), None, - visitor.0, + visitor.spans, false, None, "associated constant", @@ -837,7 +844,14 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { // Account for `type T = _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type"); + placeholder_type_error( + icx.lowerer(), + None, + visitor.spans, + false, + None, + "associated type", + ); } hir::TraitItemKind::Type(_, None) => { @@ -848,7 +862,14 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type"); + placeholder_type_error( + icx.lowerer(), + None, + visitor.spans, + false, + None, + "associated type", + ); } }; @@ -872,7 +893,14 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { let mut visitor = HirPlaceholderCollector::default(); visitor.visit_impl_item(impl_item); - placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type"); + placeholder_type_error( + icx.lowerer(), + None, + visitor.spans, + false, + None, + "associated type", + ); } hir::ImplItemKind::Const(ty, _) => { // Account for `const T: _ = ..;` @@ -882,7 +910,7 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { placeholder_type_error( icx.lowerer(), None, - visitor.0, + visitor.spans, false, None, "associated constant", @@ -1422,7 +1450,7 @@ fn recover_infer_ret_ty<'tcx>( let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(infer_ret_ty); - let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type"); + let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type"); let ret_ty = fn_sig.output(); // Don't leak types into signatures unless they're nameable! diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 76e125aebf997..a3cbf8118150e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -453,16 +453,17 @@ fn infer_placeholder_type<'tcx>( visitor.visit_ty(ty); } // If we have just one span, let's try to steal a const `_` feature error. - let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.0.len() == 1 { - visitor.0.first().copied() + let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.spans.len() == 1 + { + visitor.spans.first().copied() } else { None }; - // If we didn't find any infer tys, then just fallback to `span``. - if visitor.0.is_empty() { - visitor.0.push(span); + // If we didn't find any infer tys, then just fallback to `span`. + if visitor.spans.is_empty() { + visitor.spans.push(span); } - let mut diag = bad_placeholder(cx, visitor.0, kind); + let mut diag = bad_placeholder(cx, visitor.spans, kind); if !ty.references_error() { if let Some(ty) = ty.make_suggestable(tcx, false, None) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1f32887ce9b8e..ae36628d54979 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1771,11 +1771,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| { !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. })) }); - let Some(( - _, - hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) - )) = parent_node - else { + let Some((_, hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }))) = parent_node else { return; }; if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind { diff --git a/tests/ui/async-await/issues/issue-95307.stderr b/tests/ui/async-await/issues/issue-95307.stderr index 8445c3f981199..90100f391637a 100644 --- a/tests/ui/async-await/issues/issue-95307.stderr +++ b/tests/ui/async-await/issues/issue-95307.stderr @@ -3,11 +3,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures | LL | async fn new() -> [u8; _]; | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | async fn new() -> [u8; T]; - | +++ ~ error[E0658]: using `_` for array lengths is unstable --> $DIR/issue-95307.rs:7:28 From 7601adb4a06be26c5d240b7678ea1d0f661be5ed Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 22:19:45 +0000 Subject: [PATCH 13/24] Make suggestion verbose and tweak error message --- .../rustc_hir_analysis/src/collect/type_of.rs | 4 +- .../suggest-array-length.stderr | 40 ++++--- .../generic_arg_infer/in-signature.stderr | 66 ++++++----- tests/ui/consts/issue-104768.stderr | 10 +- tests/ui/error-codes/E0121.stderr | 10 +- .../issue-69396-const-no-type-in-macro.stderr | 9 +- tests/ui/suggestions/unnamable-types.rs | 2 +- tests/ui/suggestions/unnamable-types.stderr | 10 +- .../typeck_type_placeholder_item.stderr | 106 +++++++++++------- .../typeck_type_placeholder_item_help.stderr | 40 ++++--- 10 files changed, 178 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index a3cbf8118150e..208fa238f80e3 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -467,9 +467,9 @@ fn infer_placeholder_type<'tcx>( if !ty.references_error() { if let Some(ty) = ty.make_suggestable(tcx, false, None) { - diag.span_suggestion( + diag.span_suggestion_verbose( span, - "replace with the correct type", + "replace this with a fully-specified type", ty, Applicability::MachineApplicable, ); diff --git a/tests/ui/array-slice-vec/suggest-array-length.stderr b/tests/ui/array-slice-vec/suggest-array-length.stderr index c0fc2989d5b05..b71be306780fc 100644 --- a/tests/ui/array-slice-vec/suggest-array-length.stderr +++ b/tests/ui/array-slice-vec/suggest-array-length.stderr @@ -2,37 +2,45 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/suggest-array-length.rs:5:22 | LL | const Foo: [i32; _] = [1, 2, 3]; - | ------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `[i32; 3]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const Foo: [i32; 3] = [1, 2, 3]; + | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/suggest-array-length.rs:7:26 | LL | const REF_FOO: &[u8; _] = &[1]; - | ------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `&[u8; 1]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const REF_FOO: &[u8; 1] = &[1]; + | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/suggest-array-length.rs:9:26 | LL | static Statik: [i32; _] = [1, 2, 3]; - | ------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `[i32; 3]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static Statik: [i32; 3] = [1, 2, 3]; + | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/suggest-array-length.rs:11:30 | LL | static REF_STATIK: &[u8; _] = &[1]; - | ------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `&[u8; 1]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static REF_STATIK: &[u8; 1] = &[1]; + | ~~~~~~~~ error[E0658]: using `_` for array lengths is unstable --> $DIR/suggest-array-length.rs:13:20 diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr index 71fd5b140b1f7..5999bc1820405 100644 --- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -30,57 +30,71 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/in-signature.rs:22:20 | LL | const ARR_CT: [u8; _] = [0; 3]; - | -----^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `[u8; 3]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const ARR_CT: [u8; 3] = [0; 3]; + | ~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:24:25 | LL | static ARR_STATIC: [u8; _] = [0; 3]; - | -----^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `[u8; 3]` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static ARR_STATIC: [u8; 3] = [0; 3]; + | ~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:26:23 | LL | const TY_CT: Bar = Bar::(0); - | ---------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TY_CT: Bar = Bar::(0); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:28:28 | LL | static TY_STATIC: Bar = Bar::(0); - | ---------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static TY_STATIC: Bar = Bar::(0); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:30:24 | LL | const TY_CT_MIXED: Bar<_, _> = Bar::(0); - | ----^--^- - | | | | - | | | not allowed in type signatures - | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TY_CT_MIXED: Bar = Bar::(0); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:32:29 | LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); - | ----^--^- - | | | | - | | | not allowed in type signatures - | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static TY_STATIC_MIXED: Bar = Bar::(0); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/in-signature.rs:51:23 diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr index 762fda74a83fb..41a9bab0961ab 100644 --- a/tests/ui/consts/issue-104768.stderr +++ b/tests/ui/consts/issue-104768.stderr @@ -15,10 +15,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-104768.rs:1:11 | LL | const A: &_ = 0_u32; - | -^ - | || - | |not allowed in type signatures - | help: replace with the correct type: `u32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const A: u32 = 0_u32; + | ~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0121.stderr b/tests/ui/error-codes/E0121.stderr index 023d7e011bf3a..5f5df0fd0ae0e 100644 --- a/tests/ui/error-codes/E0121.stderr +++ b/tests/ui/error-codes/E0121.stderr @@ -11,10 +11,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/E0121.rs:3:13 | LL | static BAR: _ = "test"; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `&str` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static BAR: &str = "test"; + | ~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr index 89aeafebac497..ef49a0bc2b577 100644 --- a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr +++ b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr @@ -31,10 +31,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 | LL | const A = "A".$fn(); - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `bool` + | ^ not allowed in type signatures ... LL | / suite! { LL | | len; @@ -43,6 +40,10 @@ LL | | } | |_- in this macro invocation | = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) +help: replace this with a fully-specified type + | +LL | const Abool = "A".$fn(); + | ++++ error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs index dd2c3536eb92e..094584ff850b3 100644 --- a/tests/ui/suggestions/unnamable-types.rs +++ b/tests/ui/suggestions/unnamable-types.rs @@ -10,7 +10,7 @@ const A = 5; static B: _ = "abc"; //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables //~| NOTE: not allowed in type signatures -//~| HELP: replace with the correct type +//~| HELP: replace this with a fully-specified type // FIXME: this should also suggest a function pointer, as the closure is non-capturing diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr index 6623678fd0c2d..dc236af91f823 100644 --- a/tests/ui/suggestions/unnamable-types.stderr +++ b/tests/ui/suggestions/unnamable-types.stderr @@ -8,10 +8,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/unnamable-types.rs:10:11 | LL | static B: _ = "abc"; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `&str` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static B: &str = "abc"; + | ~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/unnamable-types.rs:17:10 diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 09d03e7c75cfa..c97b9312076d3 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -67,29 +67,36 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:13:15 | LL | static TEST3: _ = "test"; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `&str` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static TEST3: &str = "test"; + | ~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:16:15 | LL | static TEST4: _ = 145; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static TEST4: i32 = 145; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:19:16 | LL | static TEST5: (_, _) = (1, 2); - | -^--^- - | || | - | || not allowed in type signatures - | |not allowed in type signatures - | help: replace with the correct type: `(i32, i32)` + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static TEST5: (i32, i32) = (1, 2); + | ~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:22:13 @@ -224,19 +231,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:75:15 | LL | static B: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static B: i32 = 42; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:77:22 | LL | static C: Option<_> = Some(42); - | -------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `Option` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static C: Option = Some(42); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:79:21 @@ -261,29 +272,36 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:85:22 | LL | static FN_TEST3: _ = "test"; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `&str` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static FN_TEST3: &str = "test"; + | ~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST4: _ = 145; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static FN_TEST4: i32 = 145; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:91:23 | LL | static FN_TEST5: (_, _) = (1, 2); - | -^--^- - | || | - | || not allowed in type signatures - | |not allowed in type signatures - | help: replace with the correct type: `(i32, i32)` + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | static FN_TEST5: (i32, i32) = (1, 2); + | ~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:94:20 @@ -550,10 +568,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:194:14 | LL | const D: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const D: i32 = 42; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/typeck_type_placeholder_item.rs:209:14 @@ -583,10 +603,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:222:17 | LL | const _: Option<_> = map(value); - | -------^- - | | | - | | not allowed in type signatures - | help: replace with the correct type: `Option` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const _: Option = map(value); + | ~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:226:31 diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr index 32585e2937b77..a05e27cebfcd1 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -11,19 +11,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:7:14 | LL | const TEST2: _ = 42u32; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `u32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TEST2: u32 = 42u32; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:10:14 | LL | const TEST3: _ = Some(42); - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `Option` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TEST3: Option = Some(42); + | ~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item_help.rs:13:22 @@ -41,19 +45,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item_help.rs:25:18 | LL | const TEST6: _ = 13; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TEST6: i32 = 13; + | ~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/typeck_type_placeholder_item_help.rs:18:18 | LL | const TEST5: _ = 42; - | ^ - | | - | not allowed in type signatures - | help: replace with the correct type: `i32` + | ^ not allowed in type signatures + | +help: replace this with a fully-specified type + | +LL | const TEST5: i32 = 42; + | ~~~ error[E0308]: mismatched types --> $DIR/typeck_type_placeholder_item_help.rs:30:28 From 0fd64efa2f3677ca0f1f0f970b31474a5218f0b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 Jan 2025 22:33:41 +0000 Subject: [PATCH 14/24] Fix macro shenanigans --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 13 +++++++++++-- .../ui/macros/issue-69396-const-no-type-in-macro.rs | 2 +- .../issue-69396-const-no-type-in-macro.stderr | 6 +----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 208fa238f80e3..87a04820f7ec1 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -449,7 +449,8 @@ fn infer_placeholder_type<'tcx>( }) .unwrap_or_else(|| { let mut visitor = HirPlaceholderCollector::default(); - if let Some(ty) = tcx.hir_node_by_def_id(def_id).ty() { + let node = tcx.hir_node_by_def_id(def_id); + if let Some(ty) = node.ty() { visitor.visit_ty(ty); } // If we have just one span, let's try to steal a const `_` feature error. @@ -465,7 +466,15 @@ fn infer_placeholder_type<'tcx>( } let mut diag = bad_placeholder(cx, visitor.spans, kind); - if !ty.references_error() { + // HACK(#69396): Stashing and stealing diagnostics does not interact + // well with macros which may delay more than one diagnostic on the + // same span. If this happens, we will fall through to this arm, so + // we need to suppress the suggestion since it's invalid. Ideally we + // would suppress the duplicated error too, but that's really hard. + if span.is_empty() && span.from_expansion() { + // An approximately better primary message + no suggestion... + diag.primary_message("missing type for item"); + } else if !ty.references_error() { if let Some(ty) = ty.make_suggestable(tcx, false, None) { diag.span_suggestion_verbose( span, diff --git a/tests/ui/macros/issue-69396-const-no-type-in-macro.rs b/tests/ui/macros/issue-69396-const-no-type-in-macro.rs index 45a30857413b9..c200a1fd0b41e 100644 --- a/tests/ui/macros/issue-69396-const-no-type-in-macro.rs +++ b/tests/ui/macros/issue-69396-const-no-type-in-macro.rs @@ -4,7 +4,7 @@ macro_rules! suite { const A = "A".$fn(); //~^ ERROR the name `A` is defined multiple times //~| ERROR missing type for `const` item - //~| ERROR the placeholder `_` is not allowed within types on item signatures for constants + //~| ERROR missing type for item )* } } diff --git a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr index ef49a0bc2b577..4342d7d88f54b 100644 --- a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr +++ b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr @@ -27,7 +27,7 @@ LL | | } | = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants +error[E0121]: missing type for item --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 | LL | const A = "A".$fn(); @@ -40,10 +40,6 @@ LL | | } | |_- in this macro invocation | = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) -help: replace this with a fully-specified type - | -LL | const Abool = "A".$fn(); - | ++++ error: aborting due to 3 previous errors From a8516c052e35951f86ccdc0a2ee9ce670bd159c8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 2 Jan 2025 18:24:28 +0300 Subject: [PATCH 15/24] refactor bootstrap path resolution Previously we removed paths as soon as we found the first intersection, which made it impossible to find other intersecting paths. This patch changes that by marking the intersecting paths instead, so we can collect them all and remove them together when needed. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/mod.rs | 37 +++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 30e42a5bfb78d..2a95301c4142f 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -3,7 +3,7 @@ mod cargo; use std::any::{Any, type_name}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::fmt::{Debug, Write}; +use std::fmt::{self, Debug, Write}; use std::hash::Hash; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -271,12 +271,12 @@ impl PathSet { /// This is used for `StepDescription::krate`, which passes all matching crates at once to /// `Step::make_run`, rather than calling it many times with a single crate. /// See `tests.rs` for examples. - fn intersection_removing_matches(&self, needles: &mut Vec, module: Kind) -> PathSet { + fn intersection_removing_matches(&self, needles: &mut [CLIStepPath], module: Kind) -> PathSet { let mut check = |p| { - for (i, n) in needles.iter().enumerate() { - let matched = Self::check(p, n, module); + for n in needles.iter_mut() { + let matched = Self::check(p, &n.path, module); if matched { - needles.remove(i); + n.will_be_executed = true; return true; } } @@ -361,6 +361,24 @@ fn remap_paths(paths: &mut Vec) { paths.append(&mut add); } +#[derive(Clone, PartialEq)] +struct CLIStepPath { + path: PathBuf, + will_be_executed: bool, +} + +impl Debug for CLIStepPath { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.path.display()) + } +} + +impl From for CLIStepPath { + fn from(path: PathBuf) -> Self { + Self { path, will_be_executed: false } + } +} + impl StepDescription { fn from(kind: Kind) -> StepDescription { StepDescription { @@ -478,7 +496,8 @@ impl StepDescription { return; } - let mut path_lookup: Vec<(PathBuf, bool)> = + let mut paths: Vec = paths.into_iter().map(|p| p.into()).collect(); + let mut path_lookup: Vec<(CLIStepPath, bool)> = paths.clone().into_iter().map(|p| (p, false)).collect(); // List of `(usize, &StepDescription, Vec)` where `usize` is the closest index of a path @@ -518,8 +537,10 @@ impl StepDescription { } } + paths.retain(|p| !p.will_be_executed); + if !paths.is_empty() { - eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths,); + eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths); eprintln!( "HELP: run `x.py {} --help --verbose` to show a list of available paths", builder.kind.as_str() @@ -682,7 +703,7 @@ impl<'a> ShouldRun<'a> { /// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?) fn pathset_for_paths_removing_matches( &self, - paths: &mut Vec, + paths: &mut [CLIStepPath], kind: Kind, ) -> Vec { let mut sets = vec![]; From 00cd94370959ece80f675249ba6f4235a4ff8c3c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 2 Jan 2025 18:39:25 +0300 Subject: [PATCH 16/24] adapt bootstrap tests to the new path resolution logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 2 +- src/bootstrap/src/core/build_steps/doc.rs | 5 ++++- src/bootstrap/src/core/builder/mod.rs | 8 ++++++++ src/bootstrap/src/core/builder/tests.rs | 12 ++++++++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index ca337aa9f4c32..148b96181d1d2 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -93,7 +93,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").path("library") + run.crate_or_deps("sysroot").path("library").alias("core") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 1e9f7cbd9b4ca..75edc8ff78128 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -574,7 +574,10 @@ impl Step for Std { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs) + run.crate_or_deps("sysroot") + .path("library") + .alias("core") + .default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 2a95301c4142f..e9a31500ad128 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -367,6 +367,14 @@ struct CLIStepPath { will_be_executed: bool, } +#[cfg(test)] +impl CLIStepPath { + fn will_be_executed(mut self, will_be_executed: bool) -> Self { + self.will_be_executed = will_be_executed; + self + } +} + impl Debug for CLIStepPath { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.path.display()) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 21694cf46fe21..fd84c2667eeed 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -108,13 +108,17 @@ fn test_intersection() { }; let library_set = set(&["library/core", "library/alloc", "library/std"]); let mut command_paths = vec![ - PathBuf::from("library/core"), - PathBuf::from("library/alloc"), - PathBuf::from("library/stdarch"), + CLIStepPath::from(PathBuf::from("library/core")), + CLIStepPath::from(PathBuf::from("library/alloc")), + CLIStepPath::from(PathBuf::from("library/stdarch")), ]; let subset = library_set.intersection_removing_matches(&mut command_paths, Kind::Build); assert_eq!(subset, set(&["library/core", "library/alloc"]),); - assert_eq!(command_paths, vec![PathBuf::from("library/stdarch")]); + assert_eq!(command_paths, vec![ + CLIStepPath::from(PathBuf::from("library/core")).will_be_executed(true), + CLIStepPath::from(PathBuf::from("library/alloc")).will_be_executed(true), + CLIStepPath::from(PathBuf::from("library/stdarch")).will_be_executed(false), + ]); } #[test] From c367c62b27b8f75b04d59d34727066c080472db8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 2 Jan 2025 18:41:16 +0300 Subject: [PATCH 17/24] revert step order from #134919 Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index e9a31500ad128..e04be1ae69743 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -958,14 +958,10 @@ impl<'a> Builder<'a> { test::Rustdoc, test::CoverageRunRustdoc, test::Pretty, - test::Crate, - test::CrateLibrustc, - // The cranelift and gcc tests need to be listed after the - // compiler unit tests (CrateLibrustc) so that they don't - // hijack the whole `compiler` directory during path matching. - // test::CodegenCranelift, test::CodegenGCC, + test::Crate, + test::CrateLibrustc, test::CrateRustdoc, test::CrateRustdocJsonTypes, test::CrateBootstrap, From be2f75f3b7c226c6dd025fe43c8df8d8d2477aac Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 3 Jan 2025 08:57:58 +0300 Subject: [PATCH 18/24] Revert "bootstrap: temporarily flip `compile::Rustc` vs `compile::Assemble`" This reverts commit 552c1f5f45ec8b8cb5c9427754a7c3d16ca9f741. --- src/bootstrap/src/core/builder/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index e04be1ae69743..3bfa9071e70e0 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -854,12 +854,8 @@ impl<'a> Builder<'a> { match kind { Kind::Build => describe!( compile::Std, - // FIXME(#135022): `compile::Assemble` **must** come before `compile::Rustc` after - // `PathSet` also permits prefix-matching, because `compile::Rustc` can consume the - // `"compiler"` path filter first, causing `compile::Assemble` to no longer run when - // the user writes `./x build compiler --stage 0`. - compile::Assemble, compile::Rustc, + compile::Assemble, compile::CodegenBackend, compile::StartupObjects, tool::BuildManifest, From 3807440a000d07da1c589887f847efdecee6b429 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 3 Jan 2025 09:54:36 +0300 Subject: [PATCH 19/24] avoid early return to handle all paths Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 3bfa9071e70e0..04d51fab5d521 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -273,14 +273,15 @@ impl PathSet { /// See `tests.rs` for examples. fn intersection_removing_matches(&self, needles: &mut [CLIStepPath], module: Kind) -> PathSet { let mut check = |p| { + let mut result = false; for n in needles.iter_mut() { let matched = Self::check(p, &n.path, module); if matched { n.will_be_executed = true; - return true; + result = true; } } - false + result }; match self { PathSet::Set(set) => PathSet::Set(set.iter().filter(|&p| check(p)).cloned().collect()), From baa7fcec85e1939b38e84d885e746df08d2f5bb0 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 3 Jan 2025 10:01:22 +0300 Subject: [PATCH 20/24] add coverage for multiple paths Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index fd84c2667eeed..5769198afac64 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -121,6 +121,26 @@ fn test_intersection() { ]); } +#[test] +fn test_resolve_parent_and_subpaths() { + let set = |paths: &[&str]| { + PathSet::Set(paths.into_iter().map(|p| TaskPath { path: p.into(), kind: None }).collect()) + }; + + let mut command_paths = vec![ + CLIStepPath::from(PathBuf::from("src/tools/miri")), + CLIStepPath::from(PathBuf::from("src/tools/miri/cargo-miri")), + ]; + + let library_set = set(&["src/tools/miri", "src/tools/miri/cargo-miri"]); + library_set.intersection_removing_matches(&mut command_paths, Kind::Build); + + assert_eq!(command_paths, vec![ + CLIStepPath::from(PathBuf::from("src/tools/miri")).will_be_executed(true), + CLIStepPath::from(PathBuf::from("src/tools/miri/cargo-miri")).will_be_executed(true), + ]); +} + #[test] fn validate_path_remap() { let build = Build::new(configure("test", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); From 5397616868c5ba175edeff2ad4f66295f82f049b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 3 Jan 2025 09:52:14 +0100 Subject: [PATCH 21/24] crashes: add latest batch of tests --- tests/crashes/134336.rs | 11 +++++++++++ tests/crashes/134355.rs | 6 ++++++ tests/crashes/134479.rs | 24 ++++++++++++++++++++++++ tests/crashes/134587.rs | 27 +++++++++++++++++++++++++++ tests/crashes/134615.rs | 16 ++++++++++++++++ tests/crashes/134641.rs | 13 +++++++++++++ tests/crashes/134654.rs | 11 +++++++++++ tests/crashes/134838.rs | 14 ++++++++++++++ tests/crashes/134905.rs | 16 ++++++++++++++++ tests/crashes/135020.rs | 11 +++++++++++ tests/crashes/135039.rs | 34 ++++++++++++++++++++++++++++++++++ 11 files changed, 183 insertions(+) create mode 100644 tests/crashes/134336.rs create mode 100644 tests/crashes/134355.rs create mode 100644 tests/crashes/134479.rs create mode 100644 tests/crashes/134587.rs create mode 100644 tests/crashes/134615.rs create mode 100644 tests/crashes/134641.rs create mode 100644 tests/crashes/134654.rs create mode 100644 tests/crashes/134838.rs create mode 100644 tests/crashes/134905.rs create mode 100644 tests/crashes/135020.rs create mode 100644 tests/crashes/135039.rs diff --git a/tests/crashes/134336.rs b/tests/crashes/134336.rs new file mode 100644 index 0000000000000..14b88e14f04f0 --- /dev/null +++ b/tests/crashes/134336.rs @@ -0,0 +1,11 @@ +//@ known-bug: #134336 +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +trait Tr { + fn f(); +} + +fn g() { + become T::f(); +} diff --git a/tests/crashes/134355.rs b/tests/crashes/134355.rs new file mode 100644 index 0000000000000..b662341e6b1b3 --- /dev/null +++ b/tests/crashes/134355.rs @@ -0,0 +1,6 @@ +//@ known-bug: #134355 + +//@compile-flags: --crate-type=lib +fn digit() -> str { + return { i32::MIN }; +} diff --git a/tests/crashes/134479.rs b/tests/crashes/134479.rs new file mode 100644 index 0000000000000..0e4ddb2bfd56d --- /dev/null +++ b/tests/crashes/134479.rs @@ -0,0 +1,24 @@ +//@ known-bug: #134479 +//@ compile-flags: -Csymbol-mangling-version=v0 -Cdebuginfo=1 + +#![feature(generic_const_exprs)] + +fn main() { + test::<2>(); +} + +struct Test; + +fn new() -> Test +where + [(); N * 1]: Sized, +{ + Test +} + +fn test() -> Test<{ N - 1 }> +where + [(); (N - 1) * 1]: Sized, +{ + new() +} diff --git a/tests/crashes/134587.rs b/tests/crashes/134587.rs new file mode 100644 index 0000000000000..6d4441012e062 --- /dev/null +++ b/tests/crashes/134587.rs @@ -0,0 +1,27 @@ +//@ known-bug: #134587 + +use std::ops::Add; + +pub fn foo(slf: *const T) +where + *const T: Add, +{ + slf + slf; +} + +pub fn foo2(slf: *const T) +where + *const T: Add, +{ + slf + 1_u8; +} + + +pub trait TimesTwo + where *const Self: Add<*const Self>, +{ + extern "C" fn t2_ptr(slf: *const Self) + -> <*const Self as Add<*const Self>>::Output { + slf + slf + } +} diff --git a/tests/crashes/134615.rs b/tests/crashes/134615.rs new file mode 100644 index 0000000000000..d7aa51389a0d7 --- /dev/null +++ b/tests/crashes/134615.rs @@ -0,0 +1,16 @@ +//@ known-bug: #134615 + +#![feature(generic_const_exprs)] + +trait Trait { + const CONST: usize; +} + +fn f() +where + for<'a> (): Trait, + [(); <() as Trait>::CONST]:, +{ +} + +pub fn main() {} diff --git a/tests/crashes/134641.rs b/tests/crashes/134641.rs new file mode 100644 index 0000000000000..e3e5ab69287b7 --- /dev/null +++ b/tests/crashes/134641.rs @@ -0,0 +1,13 @@ +//@ known-bug: #134641 +#![feature(associated_const_equality)] + +pub trait IsVoid { + const IS_VOID: bool; +} +impl IsVoid for () { + const IS_VOID: bool = true; +} + +pub trait Maybe {} +impl Maybe for () {} +impl Maybe for () where (): IsVoid {} diff --git a/tests/crashes/134654.rs b/tests/crashes/134654.rs new file mode 100644 index 0000000000000..32fc9399655d8 --- /dev/null +++ b/tests/crashes/134654.rs @@ -0,0 +1,11 @@ +//@ known-bug: #134654 +//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir + +fn function_with_bytes() -> &'static [u8] { + BYTES +} + +fn main() { + function_with_bytes::() == &[]; +} diff --git a/tests/crashes/134838.rs b/tests/crashes/134838.rs new file mode 100644 index 0000000000000..ac8af09b31bbd --- /dev/null +++ b/tests/crashes/134838.rs @@ -0,0 +1,14 @@ +//@ known-bug: #134838 +#![feature(type_ascription)] +#![allow(dead_code)] + +struct Ty(()); + +fn mk() -> impl Sized { + if false { + let _ = type_ascribe!(mk(), Ty).0; + } + Ty(()) +} + +fn main() {} diff --git a/tests/crashes/134905.rs b/tests/crashes/134905.rs new file mode 100644 index 0000000000000..9f0f0f4b3f227 --- /dev/null +++ b/tests/crashes/134905.rs @@ -0,0 +1,16 @@ +//@ known-bug: #134905 + +trait Iterate<'a> { + type Ty: Valid; +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); +} + +trait Check {} +impl<'a, T> Eq for T where >::Ty: Valid {} + +trait Valid {} diff --git a/tests/crashes/135020.rs b/tests/crashes/135020.rs new file mode 100644 index 0000000000000..b44056eb3af30 --- /dev/null +++ b/tests/crashes/135020.rs @@ -0,0 +1,11 @@ +//@ known-bug: #135020 + +pub fn problem_thingy(items: &mut impl Iterator) { + let mut peeker = items.peekable(); + match peeker.peek() { + Some(_) => (), + None => return (), + } +} + +pub fn main() {} diff --git a/tests/crashes/135039.rs b/tests/crashes/135039.rs new file mode 100644 index 0000000000000..c4c5336fd4fdd --- /dev/null +++ b/tests/crashes/135039.rs @@ -0,0 +1,34 @@ +//@ known-bug: #135039 +//@ edition:2021 + +pub type UserId = <::User as AuthUser>::Id; + +pub trait AuthUser { + type Id; +} + +pub trait AuthnBackend { + type User: AuthUser; +} + +pub struct AuthSession { + user: Option, + data: Option>, +} + +pub trait Authz: Sized { + type AuthnBackend: AuthnBackend; +} + +pub trait Query { + type Output; + async fn run(&self) -> Result; +} + +pub async fn run_query + 'static>( + auth: AuthSession, + query: Q, +) -> Result { + let user = auth.user; + query.run().await +} From f7d0842198df9c47a75c397cff62bd56a3c023f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 19:56:30 +0800 Subject: [PATCH 22/24] run-make-support: convert `assertion_helpers` to module --- .../src/{assertion_helpers.rs => assertion_helpers/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tools/run-make-support/src/{assertion_helpers.rs => assertion_helpers/mod.rs} (100%) diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs similarity index 100% rename from src/tools/run-make-support/src/assertion_helpers.rs rename to src/tools/run-make-support/src/assertion_helpers/mod.rs From 7b763031e12c6f8455ea1b4b7c39adcb00391c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 19:57:30 +0800 Subject: [PATCH 23/24] run-make-support: add basic sanity tests for assertion helpers --- .../src/assertion_helpers/mod.rs | 3 + .../src/assertion_helpers/tests.rs | 100 ++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/tools/run-make-support/src/assertion_helpers/tests.rs diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs index e84a3cf633f97..ae926f0c2079c 100644 --- a/src/tools/run-make-support/src/assertion_helpers/mod.rs +++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs @@ -1,5 +1,8 @@ //! Collection of assertions and assertion-related helpers. +#[cfg(test)] +mod tests; + use std::panic; use std::path::Path; diff --git a/src/tools/run-make-support/src/assertion_helpers/tests.rs b/src/tools/run-make-support/src/assertion_helpers/tests.rs new file mode 100644 index 0000000000000..8bf7740d2e69e --- /dev/null +++ b/src/tools/run-make-support/src/assertion_helpers/tests.rs @@ -0,0 +1,100 @@ +//! Basic sanity checks for assertion helpers. +use super::*; + +mod test_assert_equals { + use super::*; + + #[test] + fn assert_equals_same() { + assert_equals("foo", "foo"); + assert_equals("", ""); + } + + #[test] + #[should_panic] + fn assert_equals_different() { + assert_equals("foo", "bar"); + } +} + +mod test_assert_contains { + use super::*; + + #[test] + fn assert_contains_yes() { + assert_contains("", ""); + assert_contains(" ", ""); + assert_contains("a", "a"); + assert_contains("ab", "a"); + } + + #[test] + #[should_panic] + fn assert_contains_no() { + assert_contains("a", "b"); + } +} + +mod test_assert_not_contains { + use super::*; + + #[test] + fn assert_not_contains_yes() { + assert_not_contains("a", "b"); + } + + #[test] + #[should_panic] + fn assert_not_contains_no() { + assert_not_contains(" ", ""); + } +} + +mod assert_contains_regex { + use super::*; + + #[test] + fn assert_contains_regex_yes() { + assert_contains_regex("", ""); + assert_contains_regex("", ".*"); + assert_contains_regex("abcde", ".*"); + assert_contains_regex("abcde", ".+"); + } + + #[test] + #[should_panic] + fn assert_contains_regex_no() { + assert_contains_regex("", ".+"); + } +} + +mod assert_not_contains_regex_regex { + use super::*; + + #[test] + fn assert_not_contains_regex_yes() { + assert_not_contains_regex("abc", "d"); + } + + #[test] + #[should_panic] + fn assert_not_contains_regex_no() { + assert_not_contains_regex("abc", ".*"); + } +} + +mod test_assert_count_is { + use super::*; + + #[test] + fn assert_count_is_yes() { + assert_count_is(0, "", "b"); + assert_count_is(3, "abcbdb", "b"); + } + + #[test] + #[should_panic] + fn assert_count_is_no() { + assert_count_is(2, "abcbdb", "b"); + } +} From 6175d738625d07a1e3d3c7db06b6d6a69f59a04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 3 Jan 2025 20:06:46 +0800 Subject: [PATCH 24/24] run-make-support: tidy up assertion failure dumping Avoid double-dumping or dumping even when assertion is successful. --- .../src/assertion_helpers/mod.rs | 91 ++++++++++++------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs index ae926f0c2079c..9b666473b5b37 100644 --- a/src/tools/run-make-support/src/assertion_helpers/mod.rs +++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs @@ -8,40 +8,44 @@ use std::path::Path; use crate::{fs, regex}; -fn print<'a, 'e, A: AsRef, E: AsRef>( - assertion_kind: &str, - haystack: &'a A, - needle: &'e E, -) -> (&'a str, &'e str) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); - eprintln!("{assertion_kind}:"); - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); - (haystack, needle) -} - /// Assert that `actual` is equal to `expected`. #[track_caller] pub fn assert_equals, E: AsRef>(actual: A, expected: E) { let actual = actual.as_ref(); let expected = expected.as_ref(); - eprintln!("=== ACTUAL TEXT ==="); - eprintln!("{}", actual); - eprintln!("=== EXPECTED ==="); - eprintln!("{}", expected); + if actual != expected { - panic!("expected text was not found in actual text"); + eprintln!("=== ACTUAL TEXT ==="); + eprintln!("{}", actual); + eprintln!("=== EXPECTED ==="); + eprintln!("{}", expected); + panic!("expected text does not match actual text"); + } +} + +struct SearchDetails<'assertion_name, 'haystack, 'needle> { + assertion_name: &'assertion_name str, + haystack: &'haystack str, + needle: &'needle str, +} + +impl<'assertion_name, 'haystack, 'needle> SearchDetails<'assertion_name, 'haystack, 'needle> { + fn dump(&self) { + eprintln!("{}:", self.assertion_name); + eprintln!("=== HAYSTACK ==="); + eprintln!("{}", self.haystack); + eprintln!("=== NEEDLE ==="); + eprintln!("{}", self.needle); } } /// Assert that `haystack` contains `needle`. #[track_caller] pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_contains", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); if !haystack.contains(needle) { + SearchDetails { assertion_name: "assert_contains", haystack, needle }.dump(); panic!("needle was not found in haystack"); } } @@ -49,42 +53,63 @@ pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { /// Assert that `haystack` does not contain `needle`. #[track_caller] pub fn assert_not_contains, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_not_contains", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); if haystack.contains(needle) { + SearchDetails { assertion_name: "assert_not_contains", haystack, needle }.dump(); panic!("needle was unexpectedly found in haystack"); } } -/// Assert that `haystack` contains the regex pattern `needle`. +/// Assert that `haystack` contains the regex `needle`. #[track_caller] pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_contains_regex", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); let re = regex::Regex::new(needle).unwrap(); if !re.is_match(haystack) { - panic!("needle was not found in haystack"); + SearchDetails { assertion_name: "assert_contains_regex", haystack, needle }.dump(); + panic!("regex was not found in haystack"); } } -/// Assert that `haystack` does not contain the regex pattern `needle`. +/// Assert that `haystack` does not contain the regex `needle`. #[track_caller] pub fn assert_not_contains_regex, N: AsRef>(haystack: H, needle: N) { - let (haystack, needle) = print("assert_not_contains_regex", &haystack, &needle); + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); let re = regex::Regex::new(needle).unwrap(); if re.is_match(haystack) { - panic!("needle was unexpectedly found in haystack"); + SearchDetails { assertion_name: "assert_not_contains_regex", haystack, needle }.dump(); + panic!("regex was unexpectedly found in haystack"); } } -/// Assert that `haystack` contains `needle` a `count` number of times. +/// Assert that `haystack` contains regex `needle` an `expected_count` number of times. #[track_caller] -pub fn assert_count_is, N: AsRef>(count: usize, haystack: H, needle: N) { - let (haystack, needle) = print("assert_count_is", &haystack, &needle); - if count != haystack.matches(needle).count() { - panic!("needle did not appear {count} times in haystack"); +pub fn assert_count_is, N: AsRef>( + expected_count: usize, + haystack: H, + needle: N, +) { + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); + + let actual_count = haystack.matches(needle).count(); + if expected_count != actual_count { + let count_fmt = format!( + "assert_count_is (expected_count = {expected_count}, actual_count = {actual_count})" + ); + SearchDetails { assertion_name: &count_fmt, haystack, needle }.dump(); + panic!( + "regex did not appear {expected_count} times in haystack (expected_count = \ + {expected_count}, actual_count = {actual_count})" + ); } } /// Assert that all files in `dir1` exist and have the same content in `dir2` +// FIXME(#135037): not robust against symlinks, lacks sanity test coverage. pub fn assert_dirs_are_equal(dir1: impl AsRef, dir2: impl AsRef) { let dir2 = dir2.as_ref(); fs::read_dir_entries(dir1, |entry_path| {