From 3041bc9e71355eea71a5070b7939439fd3cf7e01 Mon Sep 17 00:00:00 2001 From: Nathan Whitaker Date: Thu, 13 Oct 2022 20:13:52 -0700 Subject: [PATCH 01/10] Don't consider `Let` exprs terminating scopes --- compiler/rustc_hir_analysis/src/check/region.rs | 8 ++++++-- src/test/ui/drop/drop_order.rs | 4 ++-- src/test/ui/drop/issue-100276.rs | 12 ++++++++++++ src/test/ui/mir/mir_let_chains_drop_order.rs | 8 ++++---- 4 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/drop/issue-100276.rs diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index b89db79bef8..ff32329e431 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -252,9 +252,13 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h ) => { // For shortcircuiting operators, mark the RHS as a terminating // scope since it only executes conditionally. - terminating(r.hir_id.local_id); - } + // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries + // should live beyond the immediate expression + if !matches!(r.kind, hir::ExprKind::Let(_)) { + terminating(r.hir_id.local_id); + } + } hir::ExprKind::If(_, ref then, Some(ref otherwise)) => { terminating(then.hir_id.local_id); terminating(otherwise.hir_id.local_id); diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs index ba1ac53aa7c..42385216ae7 100644 --- a/src/test/ui/drop/drop_order.rs +++ b/src/test/ui/drop/drop_order.rs @@ -129,10 +129,10 @@ fn let_chain(&self) { // take the "else" branch if self.option_loud_drop(6).is_some() // 2 && self.option_loud_drop(5).is_some() // 1 - && let None = self.option_loud_drop(7) { // 3 + && let None = self.option_loud_drop(8) { // 4 unreachable!(); } else { - self.print(8); // 4 + self.print(7); // 3 } // let exprs interspersed diff --git a/src/test/ui/drop/issue-100276.rs b/src/test/ui/drop/issue-100276.rs new file mode 100644 index 00000000000..6401a8d1481 --- /dev/null +++ b/src/test/ui/drop/issue-100276.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags: -Z validate-mir +#![feature(let_chains)] + +fn let_chains(entry: std::io::Result) { + if let Ok(entry) = entry + && let Some(s) = entry.file_name().to_str() + && s.contains("") + {} +} + +fn main() {} diff --git a/src/test/ui/mir/mir_let_chains_drop_order.rs b/src/test/ui/mir/mir_let_chains_drop_order.rs index 536a84a352a..6471553e93f 100644 --- a/src/test/ui/mir/mir_let_chains_drop_order.rs +++ b/src/test/ui/mir/mir_let_chains_drop_order.rs @@ -12,7 +12,7 @@ pub struct DropLogger<'a, T> { extra: T, id: usize, - log: &'a panic::AssertUnwindSafe>> + log: &'a panic::AssertUnwindSafe>>, } impl<'a, T> Drop for DropLogger<'a, T> { @@ -55,9 +55,9 @@ fn main() { else { // 10 is not constructed d(10, None) - } + }, ); - assert_eq!(get(), vec![3, 8, 7, 1, 2]); + assert_eq!(get(), vec![8, 7, 1, 3, 2]); } assert_eq!(get(), vec![0, 4, 6, 9, 5]); @@ -89,5 +89,5 @@ fn main() { panic::panic_any(InjectedFailure) ); }); - assert_eq!(get(), vec![14, 19, 20, 17, 15, 11, 18, 16, 12, 13]); + assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]); } From 1a1ebb080f181cef75533dc829ec571745b1f174 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sun, 16 Oct 2022 14:53:51 -0700 Subject: [PATCH 02/10] Make transpose const and inline Signed-off-by: Alex Saveau --- library/core/src/lib.rs | 1 + library/core/src/mem/maybe_uninit.rs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index da84763836e..2fd8180f8b2 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -217,6 +217,7 @@ #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(asm_const)] +#![feature(const_transmute_copy)] // // Target features: #![feature(arm_target_feature)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 2ae96367628..efad9a9391b 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1297,7 +1297,8 @@ pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] /// let data: [MaybeUninit; 1000] = MaybeUninit::uninit().transpose(); /// ``` #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] - pub fn transpose(self) -> [MaybeUninit; N] { + #[inline] + pub const fn transpose(self) -> [MaybeUninit; N] { // SAFETY: T and MaybeUninit have the same layout unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } } @@ -1316,7 +1317,8 @@ pub fn slice_as_bytes_mut(this: &mut [MaybeUninit]) -> &mut [MaybeUninit] /// let data: MaybeUninit<[u8; 1000]> = data.transpose(); /// ``` #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] - pub fn transpose(self) -> MaybeUninit<[T; N]> { + #[inline] + pub const fn transpose(self) -> MaybeUninit<[T; N]> { // SAFETY: T and MaybeUninit have the same layout unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } } From 913393a0f704a8aefd21fa1ad5f35eb23a1655ed Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 17 Oct 2022 17:12:32 +0100 Subject: [PATCH 03/10] Allow `Vec::leak` with `no_global_oom_handling` --- library/alloc/src/vec/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b2bb7a5b2e6..b5b2eb0ece0 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2193,7 +2193,6 @@ pub fn resize_with(&mut self, new_len: usize, f: F) /// static_ref[0] += 1; /// assert_eq!(static_ref, &[2, 2, 3]); /// ``` - #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_leak", since = "1.47.0")] #[inline] pub fn leak<'a>(self) -> &'a mut [T] From 4ed834523e9ae3640011e0e214d17966d6dae844 Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 17 Oct 2022 21:30:41 +0200 Subject: [PATCH 04/10] Clean up query descriptions Use the same tense everywhere and prefer display over debug, as these descriptions are user facing. --- compiler/rustc_middle/src/query/mod.rs | 181 +++++++++--------- src/test/ui/async-await/no-const-async.stderr | 2 +- .../generic_const_exprs/closures.stderr | 4 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 8 +- .../ui/parser/fn-header-semantic-fail.stderr | 6 +- .../ui/treat-err-as-bug/delay_span_bug.rs | 2 +- .../ui/treat-err-as-bug/delay_span_bug.stderr | 2 +- 7 files changed, 104 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a0a857a73a2..ef2c7a003fa 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,19 +20,19 @@ // as they will raise an fatal error on query cycles instead. rustc_queries! { query trigger_delay_span_bug(key: DefId) -> () { - desc { "trigger a delay span bug" } + desc { "triggering a delay span bug" } } query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { eval_always no_hash - desc { "get the resolver outputs" } + desc { "getting the resolver outputs" } } query resolver_for_lowering(_: ()) -> &'tcx Steal { eval_always no_hash - desc { "get the resolver for lowering" } + desc { "getting the resolver for lowering" } } /// Return the span for a definition. @@ -40,7 +40,7 @@ /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside /// of rustc_middle::hir::source_map. query source_span(key: LocalDefId) -> Span { - desc { "get the source span" } + desc { "getting the source span" } } /// Represents crate as a whole (as distinct from the top-level crate module). @@ -52,14 +52,14 @@ query hir_crate(key: ()) -> Crate<'tcx> { arena_cache eval_always - desc { "get the crate HIR" } + desc { "getting the crate HIR" } } /// All items in the crate. query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems { arena_cache eval_always - desc { "get HIR crate items" } + desc { "getting HIR crate items" } } /// The items in a module. @@ -68,7 +68,7 @@ /// Avoid calling this query directly. query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems { arena_cache - desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } } @@ -77,7 +77,7 @@ /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner(key: hir::OwnerId) -> Option> { - desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } /// Gives access to the HIR ID for the given `LocalDefId` owner `key`. @@ -85,7 +85,7 @@ /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { - desc { |tcx| "HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) } } /// Gives access to the HIR node's parent for the HIR owner `key`. @@ -93,7 +93,7 @@ /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { - desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) } } /// Gives access to the HIR nodes and bodies inside the HIR owner `key`. @@ -101,7 +101,7 @@ /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { - desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } /// Gives access to the HIR attributes inside the HIR owner `key`. @@ -109,7 +109,7 @@ /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { - desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } /// Computes the `DefId` of the corresponding const parameter in case the `key` is a @@ -138,7 +138,7 @@ /// Given the def_id of a const-generic parameter, computes the associated default const /// parameter. e.g. `fn example` called on `N` would return `3`. query const_param_default(param: DefId) -> ty::Const<'tcx> { - desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } + desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) } cache_on_disk_if { param.is_local() } separate_provide_extern } @@ -167,7 +167,7 @@ query collect_trait_impl_trait_tys(key: DefId) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { - desc { "compare an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } + desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } cache_on_disk_if { key.is_local() } separate_provide_extern } @@ -290,11 +290,11 @@ query parent_module_from_def_id(key: LocalDefId) -> LocalDefId { eval_always - desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "getting the parent module of `{}`", tcx.def_path_str(key.to_def_id()) } } query expn_that_defined(key: DefId) -> rustc_span::ExpnId { - desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } + desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) } separate_provide_extern } @@ -306,7 +306,7 @@ /// Checks whether a type is representable or infinitely sized query representability(_: LocalDefId) -> rustc_middle::ty::Representability { - desc { "checking if {:?} is representable", tcx.def_path_str(key.to_def_id()) } + desc { "checking if `{}` is representable", tcx.def_path_str(key.to_def_id()) } // infinitely sized types will cause a cycle cycle_delay_bug // we don't want recursive representability calls to be forced with @@ -317,7 +317,7 @@ /// An implementation detail for the `representability` query query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability { - desc { "checking if {:?} is representable", key } + desc { "checking if `{}` is representable", key } cycle_delay_bug anon } @@ -383,7 +383,7 @@ /// See the README for the `mir` module for details. query mir_const(key: ty::WithOptConstParam) -> &'tcx Steal> { desc { - |tcx| "processing MIR for {}`{}`", + |tcx| "preparing {}`{}` for borrow checking", if key.const_param_did.is_some() { "the const argument " } else { "" }, tcx.def_path_str(key.did.to_def_id()), } @@ -395,7 +395,7 @@ key: DefId ) -> Result]>, ErrorGuaranteed> { desc { - |tcx| "building an abstract representation for {}", tcx.def_path_str(key), + |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), } separate_provide_extern } @@ -405,7 +405,7 @@ ) -> Result]>, ErrorGuaranteed> { desc { |tcx| - "building an abstract representation for the const argument {}", + "building an abstract representation for the const argument `{}`", tcx.def_path_str(key.0.to_def_id()), } } @@ -414,7 +414,7 @@ ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx> )>) -> bool { desc { - |tcx| "trying to unify the generic constants {} and {}", + |tcx| "trying to unify the generic constants `{}` and `{}`", tcx.def_path_str(key.value.0.def.did), tcx.def_path_str(key.value.1.def.did) } } @@ -436,7 +436,7 @@ query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { desc { - |tcx| "MIR for CTFE of the const argument `{}`", + |tcx| "caching MIR for CTFE of the const argument `{}`", tcx.def_path_str(key.0.to_def_id()) } } @@ -448,7 +448,7 @@ ) { no_hash desc { - |tcx| "processing {}`{}`", + |tcx| "processing MIR for {}`{}`", if key.const_param_did.is_some() { "the const argument " } else { "" }, tcx.def_path_str(key.did.to_def_id()), } @@ -459,7 +459,7 @@ ) -> Vec { arena_cache desc { - |tcx| "symbols for captures of closure `{}` in `{}`", + |tcx| "finding symbols for captures of closure `{}` in `{}`", tcx.def_path_str(key.1.to_def_id()), tcx.def_path_str(key.0.to_def_id()) } @@ -521,12 +521,12 @@ // queries). Making it anonymous avoids hashing the result, which // may save a bit of time. anon - desc { "erasing regions from `{:?}`", ty } + desc { "erasing regions from `{}`", ty } } query wasm_import_module_map(_: CrateNum) -> FxHashMap { arena_cache - desc { "wasm import module map" } + desc { "getting wasm import module map" } } /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the @@ -706,7 +706,7 @@ /// Collects the associated items defined on a trait or impl. query associated_items(key: DefId) -> ty::AssocItems<'tcx> { arena_cache - desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } + desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } } /// Maps from associated items on a trait to the corresponding associated @@ -732,7 +732,7 @@ ///`{ trait_f: impl_f, trait_g: impl_g }` query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap { arena_cache - desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) } + desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } } /// Given an `impl_id`, return the trait it implements. @@ -804,7 +804,7 @@ /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. query assumed_wf_types(key: DefId) -> &'tcx ty::List> { - desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) } + desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } /// Computes the signature of the function. @@ -853,7 +853,7 @@ } query check_liveness(key: DefId) { - desc { |tcx| "checking liveness of variables in {}", tcx.def_path_str(key) } + desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key) } } /// Return the live symbols in the crate for dead code check. @@ -865,7 +865,7 @@ FxHashMap> ) { arena_cache - desc { "find live symbols in crate" } + desc { "finding live symbols in crate" } } query check_mod_deathness(key: LocalDefId) -> () { @@ -913,7 +913,7 @@ } query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet { - desc { |tcx| "used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } } @@ -942,7 +942,7 @@ /// Not meant to be used directly outside of coherence. query crate_inherent_impls(k: ()) -> CrateInherentImpls { arena_cache - desc { "all inherent impls defined in crate" } + desc { "finding all inherent impls defined in crate" } } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. @@ -1032,7 +1032,7 @@ query try_destructure_mir_constant( key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> Option> { - desc { "destructuring mir constant"} + desc { "destructuring MIR constant"} remap_env_constness } @@ -1041,12 +1041,12 @@ query deref_mir_constant( key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> mir::ConstantKind<'tcx> { - desc { "dereferencing mir constant" } + desc { "dereferencing MIR constant" } remap_env_constness } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { - desc { "get a &core::panic::Location referring to a span" } + desc { "getting a &core::panic::Location referring to a span" } } // FIXME get rid of this with valtrees @@ -1068,7 +1068,7 @@ /// Performs part of the privacy check and computes "access levels". query privacy_access_levels(_: ()) -> &'tcx AccessLevels { eval_always - desc { "privacy access levels" } + desc { "checking privacy access levels" } } query check_private_in_public(_: ()) -> () { eval_always @@ -1196,12 +1196,12 @@ } query is_ctfe_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } + desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } query is_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } + desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern } @@ -1209,16 +1209,16 @@ query own_existential_vtable_entries( key: ty::PolyExistentialTraitRef<'tcx> ) -> &'tcx [DefId] { - desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) } + desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) } } query vtable_entries(key: ty::PolyTraitRef<'tcx>) -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) } + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) } } query vtable_trait_upcasting_coercion_new_vptr_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option { - desc { |tcx| "finding the slot within vtable for trait object {} vtable ptr during trait upcasting coercion from {} vtable", + desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable", key.1, key.0 } } @@ -1238,13 +1238,13 @@ /// Return all `impl` blocks in the current crate. query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap> { - desc { "local trait impls" } + desc { "finding local trait impls" } } /// Given a trait `trait_id`, return all known `impl` blocks. query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls { arena_cache - desc { |tcx| "trait impls of `{}`", tcx.def_path_str(trait_id) } + desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } } query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph { @@ -1253,7 +1253,7 @@ cache_on_disk_if { true } } query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] { - desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(trait_id) } + desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) } } /// Gets the ParameterEnvironment for a given item; this environment @@ -1311,7 +1311,7 @@ /// correctly. query has_structural_eq_impls(ty: Ty<'tcx>) -> bool { desc { - "computing whether `{:?}` implements `PartialStructuralEq` and `StructuralEq`", + "computing whether `{}` implements `PartialStructuralEq` and `StructuralEq`", ty } } @@ -1370,13 +1370,13 @@ query dylib_dependency_formats(_: CrateNum) -> &'tcx [(CrateNum, LinkagePreference)] { - desc { "dylib dependency formats of crate" } + desc { "getting dylib dependency formats of crate" } separate_provide_extern } query dependency_formats(_: ()) -> Lrc { arena_cache - desc { "get the linkage format of all dependencies" } + desc { "getting the linkage format of all dependencies" } } query is_compiler_builtins(_: CrateNum) -> bool { @@ -1398,31 +1398,31 @@ } query is_profiler_runtime(_: CrateNum) -> bool { fatal_cycle - desc { "query a crate is `#![profiler_runtime]`" } + desc { "checking if a crate is `#![profiler_runtime]`" } separate_provide_extern } query has_ffi_unwind_calls(key: LocalDefId) -> bool { - desc { |tcx| "check if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) } + desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } } query required_panic_strategy(_: CrateNum) -> Option { fatal_cycle - desc { "query a crate's required panic strategy" } + desc { "getting a crate's required panic strategy" } separate_provide_extern } query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { fatal_cycle - desc { "query a crate's configured panic-in-drop strategy" } + desc { "getting a crate's configured panic-in-drop strategy" } separate_provide_extern } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle - desc { "test whether a crate has `#![no_builtins]`" } + desc { "getting whether a crate has `#![no_builtins]`" } separate_provide_extern } query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { fatal_cycle - desc { "query a crate's symbol mangling version" } + desc { "getting a crate's symbol mangling version" } separate_provide_extern } @@ -1437,7 +1437,7 @@ } query in_scope_traits_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap>> { - desc { "traits in scope at a block" } + desc { "getting traits in scope at a block" } } query module_reexports(def_id: LocalDefId) -> Option<&'tcx [ModChild]> { @@ -1588,17 +1588,17 @@ } query is_dllimport_foreign_item(def_id: DefId) -> bool { - desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) } + desc { |tcx| "checking if `{}` is a a dylib", tcx.def_path_str(def_id) } } query is_statically_included_foreign_item(def_id: DefId) -> bool { - desc { |tcx| "is_statically_included_foreign_item({})", tcx.def_path_str(def_id) } + desc { |tcx| "checking if `{}` is a staticlib", tcx.def_path_str(def_id) } } query native_library_kind(def_id: DefId) -> Option { - desc { |tcx| "native_library_kind({})", tcx.def_path_str(def_id) } + desc { |tcx| "getting the native library kind of `{}`", tcx.def_path_str(def_id) } } query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { - desc { |tcx| "native_library({})", tcx.def_path_str(def_id) } + desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } } /// Does lifetime resolution, but does not descend into trait items. This @@ -1659,7 +1659,7 @@ query type_uninhabited_from( key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> ty::inhabitedness::DefIdForest<'tcx> { - desc { "computing the inhabitedness of `{:?}`", key } + desc { "computing the inhabitedness of `{}`", key.value } remap_env_constness } @@ -1698,7 +1698,7 @@ } /// Whether the function is an intrinsic query is_intrinsic(def_id: DefId) -> bool { - desc { |tcx| "is_intrinsic({})", tcx.def_path_str(def_id) } + desc { |tcx| "checking whether `{}` is an intrinsic", tcx.def_path_str(def_id) } separate_provide_extern } /// Returns the lang items defined in another crate by loading it from metadata. @@ -1765,12 +1765,12 @@ /// is marked as a private dependency query is_private_dep(c: CrateNum) -> bool { eval_always - desc { "check whether crate {} is a private dependency", c } + desc { "checking whether crate `{}` is a private dependency", c } separate_provide_extern } query allocator_kind(_: ()) -> Option { eval_always - desc { "allocator kind for the current crate" } + desc { "getting the allocator kind for the current crate" } } query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { @@ -1783,7 +1783,7 @@ desc { "looking up all possibly unused extern crates" } } query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet { - desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) } + desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) } } query stability_index(_: ()) -> stability::Index { @@ -1809,7 +1809,7 @@ /// correspond to a publicly visible symbol in `cnum` machine code. /// - The `exported_symbols` sets of different crates do not intersect. query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "exported_symbols" } + desc { "collecting exported symbols for crate `{}`", cnum} cache_on_disk_if { *cnum == LOCAL_CRATE } separate_provide_extern } @@ -1818,6 +1818,7 @@ eval_always desc { "collect_and_partition_mono_items" } } + query is_codegened_item(def_id: DefId) -> bool { desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } } @@ -1825,12 +1826,13 @@ /// All items participating in code generation together with items inlined into them. query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet { eval_always - desc { "codegened_and_inlined_items" } + desc { "collecting codegened and inlined items" } } - query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> { - desc { "codegen_unit" } + query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { + desc { "getting codegen unit `{sym}`" } } + query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet { cache_on_disk_if { key.def_id().is_local() } desc { @@ -1839,6 +1841,7 @@ } separate_provide_extern } + query backend_optimization_level(_: ()) -> OptLevel { desc { "optimization level used by backend" } } @@ -1849,7 +1852,7 @@ /// has been destroyed. query output_filenames(_: ()) -> &'tcx Arc { eval_always - desc { "output_filenames" } + desc { "getting output filenames" } } /// Do not call this query directly: invoke `normalize` instead. @@ -1859,7 +1862,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal } + desc { "normalizing `{}`", goal.value.value } remap_env_constness } @@ -1877,7 +1880,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, NoSolution, > { - desc { "computing implied outlives bounds for `{:?}`", goal } + desc { "computing implied outlives bounds for `{}`", goal.value.value } remap_env_constness } @@ -1889,7 +1892,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution, > { - desc { "computing dropck types for `{:?}`", goal } + desc { "computing dropck types for `{}`", goal.value.value } remap_env_constness } @@ -1917,7 +1920,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal } + desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value } remap_env_constness } @@ -1928,7 +1931,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_eq` `{:?}`", goal } + desc { "evaluating `type_op_eq` `{:?}`", goal.value.value } remap_env_constness } @@ -1939,7 +1942,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_subtype` `{:?}`", goal } + desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value } remap_env_constness } @@ -1950,7 +1953,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_prove_predicate` `{:?}`", goal } + desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.value.value } } /// Do not call this query directly: part of the `Normalize` type-op @@ -1960,7 +1963,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal } + desc { "normalizing `{}`", goal.value.value.value } remap_env_constness } @@ -1971,7 +1974,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal } + desc { "normalizing `{:?}`", goal.value.value.value } remap_env_constness } @@ -1982,7 +1985,7 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal } + desc { "normalizing `{:?}`", goal.value.value.value } remap_env_constness } @@ -1993,20 +1996,20 @@ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal } + desc { "normalizing `{:?}`", goal.value.value.value } remap_env_constness } query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { desc { |tcx| - "impossible substituted predicates:`{}`", + "checking impossible substituted predicates: `{}`", tcx.def_path_str(key.0) } } query is_impossible_method(key: (DefId, DefId)) -> bool { desc { |tcx| - "checking if {} is impossible to call within {}", + "checking if `{}` is impossible to call within `{}`", tcx.def_path_str(key.1), tcx.def_path_str(key.0), } @@ -2015,7 +2018,7 @@ query method_autoderef_steps( goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { - desc { "computing autoderef types for `{:?}`", goal } + desc { "computing autoderef types for `{}`", goal.value.value } remap_env_constness } @@ -2063,7 +2066,7 @@ } query normalize_opaque_types(key: &'tcx ty::List>) -> &'tcx ty::List> { - desc { "normalizing opaque types in {:?}", key } + desc { "normalizing opaque types in `{:?}`", key } } /// Checks whether a type is definitely uninhabited. This is @@ -2073,7 +2076,7 @@ /// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero /// size, to account for partial initialisation. See #49298 for details.) query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "conservatively checking if {:?} is privately uninhabited", key } + desc { "conservatively checking if `{}` is privately uninhabited", key.value } remap_env_constness } @@ -2093,7 +2096,7 @@ arena_cache eval_always no_hash - desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 } + desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } } @@ -2112,11 +2115,11 @@ } query permits_uninit_init(key: TyAndLayout<'tcx>) -> bool { - desc { "checking to see if {:?} permits being left uninit", key.ty } + desc { "checking to see if `{}` permits being left uninit", key.ty } } query permits_zero_init(key: TyAndLayout<'tcx>) -> bool { - desc { "checking to see if {:?} permits being left zeroed", key.ty } + desc { "checking to see if `{}` permits being left zeroed", key.ty } } query compare_assoc_const_impl_item_with_trait_item( diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index e6f6e9e9f65..c5bd520aaea 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -18,7 +18,7 @@ note: ...which requires borrow-checking `x`... | LL | pub const async fn x() {} | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `x`... +note: ...which requires processing MIR for `x`... --> $DIR/no-const-async.rs:4:1 | LL | pub const async fn x() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr index a15dd2016e9..a7d891d7790 100644 --- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when building an abstract representation for test::{constant#0} +error[E0391]: cycle detected when building an abstract representation for `test::{constant#0}` --> $DIR/closures.rs:3:35 | LL | fn test() -> [u8; N + (|| 42)()] {} @@ -14,7 +14,7 @@ note: ...which requires type-checking `test::{constant#0}`... | LL | fn test() -> [u8; N + (|| 42)()] {} | ^^^^^^^^^^^^^ - = note: ...which again requires building an abstract representation for test::{constant#0}, completing the cycle + = note: ...which again requires building an abstract representation for `test::{constant#0}`, completing the cycle note: cycle used when checking that `test` is well-formed --> $DIR/closures.rs:3:1 | diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index b6e28364768..feedfc40aaf 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -9,12 +9,12 @@ note: ...which requires borrow-checking `cycle1`... | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `cycle1`... +note: ...which requires processing MIR for `cycle1`... --> $DIR/auto-trait-leak.rs:12:1 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing MIR for `cycle1`... +note: ...which requires preparing `cycle1` for borrow checking... --> $DIR/auto-trait-leak.rs:12:1 | LL | fn cycle1() -> impl Clone { @@ -50,12 +50,12 @@ note: ...which requires borrow-checking `cycle2`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `cycle2`... +note: ...which requires processing MIR for `cycle2`... --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing MIR for `cycle2`... +note: ...which requires preparing `cycle2` for borrow checking... --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 800b5a43a00..038fdfb2d51 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -199,7 +199,7 @@ note: ...which requires borrow-checking `main::ff5`... | LL | const async unsafe extern "C" fn ff5() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires processing `main::ff5`... +note: ...which requires processing MIR for `main::ff5`... --> $DIR/fn-header-semantic-fail.rs:12:5 | LL | const async unsafe extern "C" fn ff5() {} @@ -235,7 +235,7 @@ note: ...which requires borrow-checking `main::::ft5`... +note: ...which requires processing MIR for `main::::ft5`... --> $DIR/fn-header-semantic-fail.rs:33:9 | LL | const async unsafe extern "C" fn ft5() {} @@ -271,7 +271,7 @@ note: ...which requires borrow-checking `main::::fi5`... +note: ...which requires processing MIR for `main::::fi5`... --> $DIR/fn-header-semantic-fail.rs:45:9 | LL | const async unsafe extern "C" fn fi5() {} diff --git a/src/test/ui/treat-err-as-bug/delay_span_bug.rs b/src/test/ui/treat-err-as-bug/delay_span_bug.rs index d4d44049c91..832afddf891 100644 --- a/src/test/ui/treat-err-as-bug/delay_span_bug.rs +++ b/src/test/ui/treat-err-as-bug/delay_span_bug.rs @@ -1,7 +1,7 @@ // compile-flags: -Ztreat-err-as-bug // failure-status: 101 // error-pattern: aborting due to `-Z treat-err-as-bug=1` -// error-pattern: [trigger_delay_span_bug] trigger a delay span bug +// error-pattern: [trigger_delay_span_bug] triggering a delay span bug // normalize-stderr-test "note: .*\n\n" -> "" // normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" // rustc-env:RUST_BACKTRACE=0 diff --git a/src/test/ui/treat-err-as-bug/delay_span_bug.stderr b/src/test/ui/treat-err-as-bug/delay_span_bug.stderr index c23c2b81b97..e9457c8faff 100644 --- a/src/test/ui/treat-err-as-bug/delay_span_bug.stderr +++ b/src/test/ui/treat-err-as-bug/delay_span_bug.stderr @@ -7,5 +7,5 @@ LL | fn main() {} error: internal compiler error: unexpected panic query stack during panic: -#0 [trigger_delay_span_bug] trigger a delay span bug +#0 [trigger_delay_span_bug] triggering a delay span bug end of query stack From 9c3bf4de5534846b289de626dd4dc78f7dc7d13c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 18 Oct 2022 20:53:24 +0000 Subject: [PATCH 05/10] Consider patterns in fn params in an `Elided(Infer)` lifetime rib. --- compiler/rustc_resolve/src/late.rs | 17 +++++++++++------ .../lifetimes/elided-lifetime-in-param-pat.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 776c8ad528c..1675580bd89 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1853,9 +1853,11 @@ fn resolve_fn_params( let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; for (index, (pat, ty)) in inputs.enumerate() { debug!(?pat, ?ty); - if let Some(pat) = pat { - self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); - } + self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { + if let Some(pat) = pat { + this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); + } + }); self.visit_ty(ty); if let Some(ref candidates) = self.lifetime_elision_candidates { @@ -2827,10 +2829,13 @@ fn check_trait_item( fn resolve_params(&mut self, params: &'ast [Param]) { let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; - for Param { pat, ty, .. } in params { - self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); + self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { + for Param { pat, .. } in params { + this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); + } + }); + for Param { ty, .. } in params { self.visit_ty(ty); - debug!("(resolving function / closure) recorded parameter"); } } diff --git a/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs b/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs new file mode 100644 index 00000000000..c1425fa4243 --- /dev/null +++ b/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs @@ -0,0 +1,11 @@ +// check-pass + +struct S { + _t: T, +} + +fn f(S::<&i8> { .. }: S<&i8>) {} + +fn main() { + f(S { _t: &42_i8 }); +} From 63be7a24242b262ba9924eec89a5cc6512d8b504 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 9 Oct 2022 21:02:12 +0000 Subject: [PATCH 06/10] Suggest calling ctor when trait is unimplemented --- .../src/traits/error_reporting/suggestions.rs | 19 ++++++++++++++- .../suggestions/call-on-unimplemented-ctor.rs | 17 +++++++++++++ .../call-on-unimplemented-ctor.stderr | 24 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/call-on-unimplemented-ctor.rs create mode 100644 src/test/ui/suggestions/call-on-unimplemented-ctor.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 4431cf9f443..0b2fcc9b0d1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -817,7 +817,14 @@ fn suggest_fn_call( let (def_id, output_ty, callable) = match *self_ty.kind() { ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"), - ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"), + ty::FnDef(def_id, _) => ( + def_id, + self_ty.fn_sig(self.tcx).output(), + match self.tcx.def_kind(def_id) { + DefKind::Ctor(..) => "constructor", + _ => "function", + }, + ), _ => return false, }; let msg = format!("use parentheses to call the {}", callable); @@ -878,6 +885,16 @@ fn suggest_fn_call( let sugg = format!("({})", args); (format!("{}{}", ident, sugg), sugg) } + Some(hir::Node::Ctor(data)) => { + let name = self.tcx.def_path_str(def_id); + err.span_label( + self.tcx.def_span(def_id), + format!("consider calling the constructor for `{}`", name), + ); + let args = data.fields().iter().map(|_| "_").collect::>().join(", "); + let sugg = format!("({})", args); + (format!("{name}{sugg}"), sugg) + } _ => return false, }; if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs new file mode 100644 index 00000000000..28a319382e6 --- /dev/null +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs @@ -0,0 +1,17 @@ +fn main() { + insert_resource(Marker); + insert_resource(Time); + //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied + //~| HELP use parentheses to call the constructor +} + +trait Resource {} + +fn insert_resource(resource: R) {} + +struct Marker; +impl Resource for Marker {} + +struct Time(u32); + +impl Resource for Time {} diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr new file mode 100644 index 00000000000..ea8aec3098d --- /dev/null +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied + --> $DIR/call-on-unimplemented-ctor.rs:3:21 + | +LL | insert_resource(Time); + | --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}` + | | + | required by a bound introduced by this call +... +LL | struct Time(u32); + | ----------- consider calling the constructor for `Time` + | +note: required by a bound in `insert_resource` + --> $DIR/call-on-unimplemented-ctor.rs:10:23 + | +LL | fn insert_resource(resource: R) {} + | ^^^^^^^^ required by this bound in `insert_resource` +help: use parentheses to call the constructor + | +LL | insert_resource(Time(_)); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From b3edd9f775b734deb215f05269e7af0b6102c50a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 9 Oct 2022 21:06:59 +0000 Subject: [PATCH 07/10] Use predicate_must_hold_modulo_regions --- .../src/traits/error_reporting/mod.rs | 8 ++++---- .../src/traits/error_reporting/suggestions.rs | 14 ++++---------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4e8baa2dfab..6abff0ac577 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2,10 +2,10 @@ pub mod suggestions; use super::{ - EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + FulfillmentContext, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, + OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, + SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 0b2fcc9b0d1..1faf13cbddf 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1,6 +1,5 @@ use super::{ - EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, - SelectionContext, + Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, }; use crate::autoderef::Autoderef; @@ -839,15 +838,10 @@ fn suggest_fn_call( let new_obligation = self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); - match self.evaluate_obligation(&new_obligation) { - Ok( - EvaluationResult::EvaluatedToOk - | EvaluationResult::EvaluatedToOkModuloRegions - | EvaluationResult::EvaluatedToOkModuloOpaqueTypes - | EvaluationResult::EvaluatedToAmbig, - ) => {} - _ => return false, + if !self.predicate_must_hold_modulo_regions(&new_obligation) { + return false; } + let hir = self.tcx.hir(); // Get the name of the callable and the arguments to be used in the suggestion. let (snippet, sugg) = match hir.get_if_local(def_id) { From f5336a969ca549ba72f91b14b50b9830cdda49b6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 9 Oct 2022 21:39:57 +0000 Subject: [PATCH 08/10] Standardize arg suggestions between typeck and trait selection --- .../src/check/fn_ctxt/suggestions.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 106 +++++++++--------- src/test/ui/binop/issue-77910-1.stderr | 2 +- .../call-on-unimplemented-ctor.stderr | 4 +- 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs index 7a40def177a..429f068c91b 100644 --- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs @@ -90,7 +90,7 @@ pub(crate) fn suggest_fn_call( if ty.is_suggestable(self.tcx, false) { format!("/* {ty} */") } else { - "".to_string() + "/* value */".to_string() } }) .collect::>() diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1faf13cbddf..316afe28a0a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -21,6 +21,7 @@ use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::hir::map; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, @@ -28,7 +29,7 @@ ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::fmt; @@ -814,80 +815,85 @@ fn suggest_fn_call( // Skipping binder here, remapping below let self_ty = trait_pred.self_ty().skip_binder(); - let (def_id, output_ty, callable) = match *self_ty.kind() { - ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"), - ty::FnDef(def_id, _) => ( - def_id, - self_ty.fn_sig(self.tcx).output(), - match self.tcx.def_kind(def_id) { - DefKind::Ctor(..) => "constructor", - _ => "function", - }, - ), + let (def_id, inputs, output, kind) = match *self_ty.kind() { + ty::Closure(def_id, substs) => { + let sig = substs.as_closure().sig(); + (def_id, sig.inputs().map_bound(|inputs| &inputs[1..]), sig.output(), "closure") + } + ty::FnDef(def_id, _) => { + let sig = self_ty.fn_sig(self.tcx); + ( + def_id, + sig.inputs(), + sig.output(), + match self.tcx.def_kind(def_id) { + DefKind::Ctor(..) => "constructor", + _ => "function", + }, + ) + } _ => return false, }; - let msg = format!("use parentheses to call the {}", callable); - - // "We should really create a single list of bound vars from the combined vars - // from the predicate and function, but instead we just liberate the function bound vars" - let output_ty = self.tcx.liberate_late_bound_regions(def_id, output_ty); + let output = self.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + LateBoundRegionConversionTime::FnCall, + output, + ); + let inputs = inputs.skip_binder().iter().map(|ty| { + self.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + LateBoundRegionConversionTime::FnCall, + inputs.rebind(*ty), + ) + }); // Remapping bound vars here - let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output_ty)); + let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output)); let new_obligation = self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); - if !self.predicate_must_hold_modulo_regions(&new_obligation) { return false; } - let hir = self.tcx.hir(); // Get the name of the callable and the arguments to be used in the suggestion. - let (snippet, sugg) = match hir.get_if_local(def_id) { + let hir = self.tcx.hir(); + + let msg = format!("use parentheses to call the {}", kind); + + let args = inputs + .map(|ty| { + if ty.is_suggestable(self.tcx, false) { + format!("/* {ty} */") + } else { + "/* value */".to_string() + } + }) + .collect::>() + .join(", "); + + let name = match hir.get_if_local(def_id) { Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { fn_decl, fn_decl_span, .. }), + kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }), .. })) => { err.span_label(*fn_decl_span, "consider calling this closure"); let Some(name) = self.get_closure_name(def_id, err, &msg) else { return false; }; - let args = fn_decl.inputs.iter().map(|_| "_").collect::>().join(", "); - let sugg = format!("({})", args); - (format!("{}{}", name, sugg), sugg) + name.to_string() } - Some(hir::Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Fn(.., body_id), - .. - })) => { + Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => { err.span_label(ident.span, "consider calling this function"); - let body = hir.body(*body_id); - let args = body - .params - .iter() - .map(|arg| match &arg.pat.kind { - hir::PatKind::Binding(_, _, ident, None) - // FIXME: provide a better suggestion when encountering `SelfLower`, it - // should suggest a method call. - if ident.name != kw::SelfLower => ident.to_string(), - _ => "_".to_string(), - }) - .collect::>() - .join(", "); - let sugg = format!("({})", args); - (format!("{}{}", ident, sugg), sugg) + ident.to_string() } - Some(hir::Node::Ctor(data)) => { + Some(hir::Node::Ctor(..)) => { let name = self.tcx.def_path_str(def_id); err.span_label( self.tcx.def_span(def_id), format!("consider calling the constructor for `{}`", name), ); - let args = data.fields().iter().map(|_| "_").collect::>().join(", "); - let sugg = format!("({})", args); - (format!("{name}{sugg}"), sugg) + name } _ => return false, }; @@ -901,11 +907,11 @@ fn suggest_fn_call( err.span_suggestion_verbose( obligation.cause.span.shrink_to_hi(), &msg, - sugg, + format!("({args})"), Applicability::HasPlaceholders, ); } else { - err.help(&format!("{}: `{}`", msg, snippet)); + err.help(&format!("{msg}: `{name}({args})`")); } true } diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index 9c7bf6228be..cacea71ac97 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -19,7 +19,7 @@ LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` - = help: use parentheses to call the function: `foo(s)` + = help: use parentheses to call the function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr index ea8aec3098d..8ffdff2a4a3 100644 --- a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -16,8 +16,8 @@ LL | fn insert_resource(resource: R) {} | ^^^^^^^^ required by this bound in `insert_resource` help: use parentheses to call the constructor | -LL | insert_resource(Time(_)); - | +++ +LL | insert_resource(Time(/* u32 */)); + | +++++++++++ error: aborting due to previous error From 7eb2d4e7d0e070eaf15955fc376498d9e5fa9e78 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 9 Oct 2022 22:25:52 +0000 Subject: [PATCH 09/10] Generalize call suggestion for unsatisfied predicate --- .../rustc_hir_analysis/src/check/callee.rs | 3 +- .../src/check/fn_ctxt/suggestions.rs | 7 +- .../src/traits/error_reporting/mod.rs | 5 + .../src/traits/error_reporting/suggestions.rs | 164 +++++++++++++----- src/test/ui/binop/issue-77910-1.stderr | 2 +- .../ui/closures/closure-bounds-subtype.stderr | 4 + ...70724-add_type_neq_err_label-unwrap.stderr | 2 +- ...rg-where-it-should-have-been-called.stderr | 9 +- .../suggestions/call-on-unimplemented-ctor.rs | 2 +- .../call-on-unimplemented-ctor.stderr | 5 +- .../call-on-unimplemented-fn-ptr.rs | 15 ++ .../call-on-unimplemented-fn-ptr.stderr | 21 +++ ...rg-where-it-should-have-been-called.stderr | 9 +- 13 files changed, 174 insertions(+), 74 deletions(-) create mode 100644 src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs create mode 100644 src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr diff --git a/compiler/rustc_hir_analysis/src/check/callee.rs b/compiler/rustc_hir_analysis/src/check/callee.rs index f0a7c910906..088de1979ba 100644 --- a/compiler/rustc_hir_analysis/src/check/callee.rs +++ b/compiler/rustc_hir_analysis/src/check/callee.rs @@ -1,6 +1,6 @@ use super::method::probe::{IsSuggestion, Mode, ProbeScope}; use super::method::MethodCallee; -use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag}; +use super::{Expectation, FnCtxt, TupleArgumentsFlag}; use crate::type_error_struct; use rustc_ast::util::parser::PREC_POSTFIX; @@ -27,6 +27,7 @@ use rustc_target::spec::abi; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use std::iter; diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs index 429f068c91b..8c4fe75878f 100644 --- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs @@ -2,7 +2,6 @@ use crate::astconv::AstConv; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; -use hir::def_id::DefId; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; @@ -19,6 +18,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -1209,8 +1209,3 @@ pub(crate) fn consider_removing_semicolon( } } } - -pub enum DefIdOrName { - DefId(DefId), - Name(&'static str), -} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 6abff0ac577..b7e6a564f39 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2796,3 +2796,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { } } } + +pub enum DefIdOrName { + DefId(DefId), + Name(&'static str), +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 316afe28a0a..98e32e2ce85 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1,11 +1,13 @@ use super::{ - Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, + DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, + SelectionContext, }; use crate::autoderef::Autoderef; use crate::infer::InferCtxt; use crate::traits::normalize_to; +use hir::def::CtorOf; use hir::HirId; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -812,28 +814,87 @@ fn suggest_fn_call( err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { - // Skipping binder here, remapping below - let self_ty = trait_pred.self_ty().skip_binder(); + if let ty::PredicateKind::Trait(trait_pred) = obligation.predicate.kind().skip_binder() + && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait() + { + // Don't suggest calling to turn an unsized type into a sized type + return false; + } - let (def_id, inputs, output, kind) = match *self_ty.kind() { - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(); - (def_id, sig.inputs().map_bound(|inputs| &inputs[1..]), sig.output(), "closure") + // This is duplicated from `extract_callable_info` in typeck, which + // relies on autoderef, so we can't use it here. + let found = trait_pred.self_ty().skip_binder().peel_refs(); + let Some((def_id_or_name, output, inputs)) = (match *found.kind() + { + ty::FnPtr(fn_sig) => { + Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())) } ty::FnDef(def_id, _) => { - let sig = self_ty.fn_sig(self.tcx); - ( - def_id, - sig.inputs(), - sig.output(), - match self.tcx.def_kind(def_id) { - DefKind::Ctor(..) => "constructor", - _ => "function", - }, - ) + let fn_sig = found.fn_sig(self.tcx); + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) } - _ => return false, - }; + ty::Closure(def_id, substs) => { + let fn_sig = substs.as_closure().sig(); + Some(( + DefIdOrName::DefId(def_id), + fn_sig.output(), + fn_sig.inputs().map_bound(|inputs| &inputs[1..]), + )) + } + ty::Opaque(def_id, substs) => { + self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { + if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder() + && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() + // args tuple will always be substs[1] + && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() + { + Some(( + DefIdOrName::DefId(def_id), + pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }) + } + ty::Dynamic(data, _, ty::Dyn) => { + data.iter().find_map(|pred| { + if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() + && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output() + // for existential projection, substs are shifted over by 1 + && let ty::Tuple(args) = proj.substs.type_at(0).kind() + { + Some(( + DefIdOrName::Name("trait object"), + pred.rebind(proj.term.ty().unwrap()), + pred.rebind(args.as_slice()), + )) + } else { + None + } + }) + } + ty::Param(_) => { + obligation.param_env.caller_bounds().iter().find_map(|pred| { + if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder() + && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() + && proj.projection_ty.self_ty() == found + // args tuple will always be substs[1] + && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() + { + Some(( + DefIdOrName::Name("type parameter"), + pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }) + } + _ => None, + }) else { return false; }; let output = self.replace_bound_vars_with_fresh_vars( obligation.cause.span, LateBoundRegionConversionTime::FnCall, @@ -859,7 +920,18 @@ fn suggest_fn_call( // Get the name of the callable and the arguments to be used in the suggestion. let hir = self.tcx.hir(); - let msg = format!("use parentheses to call the {}", kind); + let msg = match def_id_or_name { + DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) { + DefKind::Ctor(CtorOf::Struct, _) => { + "use parentheses to instantiate this tuple struct".to_string() + } + DefKind::Ctor(CtorOf::Variant, _) => { + "use parentheses to instantiate this tuple variant".to_string() + } + kind => format!("use parentheses to call this {}", kind.descr(def_id)), + }, + DefIdOrName::Name(name) => format!("use parentheses to call this {name}"), + }; let args = inputs .map(|ty| { @@ -872,31 +944,6 @@ fn suggest_fn_call( .collect::>() .join(", "); - let name = match hir.get_if_local(def_id) { - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }), - .. - })) => { - err.span_label(*fn_decl_span, "consider calling this closure"); - let Some(name) = self.get_closure_name(def_id, err, &msg) else { - return false; - }; - name.to_string() - } - Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => { - err.span_label(ident.span, "consider calling this function"); - ident.to_string() - } - Some(hir::Node::Ctor(..)) => { - let name = self.tcx.def_path_str(def_id); - err.span_label( - self.tcx.def_span(def_id), - format!("consider calling the constructor for `{}`", name), - ); - name - } - _ => return false, - }; if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) && obligation.cause.span.can_be_used_for_suggestions() { @@ -910,7 +957,32 @@ fn suggest_fn_call( format!("({args})"), Applicability::HasPlaceholders, ); - } else { + } else if let DefIdOrName::DefId(def_id) = def_id_or_name { + let name = match hir.get_if_local(def_id) { + Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }), + .. + })) => { + err.span_label(*fn_decl_span, "consider calling this closure"); + let Some(name) = self.get_closure_name(def_id, err, &msg) else { + return false; + }; + name.to_string() + } + Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => { + err.span_label(ident.span, "consider calling this function"); + ident.to_string() + } + Some(hir::Node::Ctor(..)) => { + let name = self.tcx.def_path_str(def_id); + err.span_label( + self.tcx.def_span(def_id), + format!("consider calling the constructor for `{}`", name), + ); + name + } + _ => return false, + }; err.help(&format!("{msg}: `{name}({args})`")); } true diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index cacea71ac97..263a35d9829 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -19,7 +19,7 @@ LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` - = help: use parentheses to call the function: `foo(/* &i32 */)` + = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index 1a40326d986..8ad8273fc2b 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -11,6 +11,10 @@ note: required by a bound in `take_const_owned` | LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { | ^^^^ required by this bound in `take_const_owned` +help: use parentheses to call this type parameter + | +LL | take_const_owned(f()); + | ++ help: consider further restricting this bound | LL | fn give_owned(f: F) where F: FnOnce() + Send + std::marker::Sync { diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr index 7f29709ce50..b30bcfb776c 100644 --- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr +++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr @@ -29,7 +29,7 @@ LL | assert_eq!(a, 0); | ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}` - = help: use parentheses to call the function: `a()` + = help: use parentheses to call this function: `a()` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index bfd506c9f6e..8ed62f854f0 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,9 +1,6 @@ error[E0277]: `fn() -> impl Future {foo}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9 | -LL | async fn foo() {} - | --- consider calling this function -... LL | bar(foo); | --- ^^^ `fn() -> impl Future {foo}` is not a future | | @@ -16,7 +13,7 @@ note: required by a bound in `bar` | LL | fn bar(f: impl Future) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` -help: use parentheses to call the function +help: use parentheses to call this function | LL | bar(foo()); | ++ @@ -24,8 +21,6 @@ LL | bar(foo()); error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | -LL | let async_closure = async || (); - | -------- consider calling this closure LL | bar(async_closure); | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future | | @@ -38,7 +33,7 @@ note: required by a bound in `bar` | LL | fn bar(f: impl Future) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` -help: use parentheses to call the closure +help: use parentheses to call this closure | LL | bar(async_closure()); | ++ diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs index 28a319382e6..0e7412807b4 100644 --- a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs @@ -2,7 +2,7 @@ fn main() { insert_resource(Marker); insert_resource(Time); //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied - //~| HELP use parentheses to call the constructor + //~| HELP use parentheses to instantiate this tuple struct } trait Resource {} diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr index 8ffdff2a4a3..48f3366596f 100644 --- a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -5,16 +5,13 @@ LL | insert_resource(Time); | --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}` | | | required by a bound introduced by this call -... -LL | struct Time(u32); - | ----------- consider calling the constructor for `Time` | note: required by a bound in `insert_resource` --> $DIR/call-on-unimplemented-ctor.rs:10:23 | LL | fn insert_resource(resource: R) {} | ^^^^^^^^ required by this bound in `insert_resource` -help: use parentheses to call the constructor +help: use parentheses to instantiate this tuple struct | LL | insert_resource(Time(/* u32 */)); | +++++++++++ diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs new file mode 100644 index 00000000000..86490c724e0 --- /dev/null +++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs @@ -0,0 +1,15 @@ +struct Foo; + +trait Bar {} + +impl Bar for Foo {} + +fn needs_bar(_: T) {} + +fn blah(f: fn() -> Foo) { + needs_bar(f); + //~^ ERROR the trait bound `fn() -> Foo: Bar` is not satisfied + //~| HELP use parentheses to call this function pointer +} + +fn main() {} diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr new file mode 100644 index 00000000000..167f7e592a9 --- /dev/null +++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `fn() -> Foo: Bar` is not satisfied + --> $DIR/call-on-unimplemented-fn-ptr.rs:10:15 + | +LL | needs_bar(f); + | --------- ^ the trait `Bar` is not implemented for `fn() -> Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_bar` + --> $DIR/call-on-unimplemented-fn-ptr.rs:7:17 + | +LL | fn needs_bar(_: T) {} + | ^^^ required by this bound in `needs_bar` +help: use parentheses to call this function pointer + | +LL | needs_bar(f()); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index fe603b67575..955148315ba 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -1,9 +1,6 @@ error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 | -LL | fn foo() -> impl T { S } - | --- consider calling this function -... LL | bar(foo); | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T {foo}` | | @@ -14,7 +11,7 @@ note: required by a bound in `bar` | LL | fn bar(f: impl T) {} | ^^^^^^^ required by this bound in `bar` -help: use parentheses to call the function +help: use parentheses to call this function | LL | bar(foo()); | ++ @@ -22,8 +19,6 @@ LL | bar(foo()); error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 | -LL | let closure = || S; - | -- consider calling this closure LL | bar(closure); | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` | | @@ -34,7 +29,7 @@ note: required by a bound in `bar` | LL | fn bar(f: impl T) {} | ^^^^^^^ required by this bound in `bar` -help: use parentheses to call the closure +help: use parentheses to call this closure | LL | bar(closure()); | ++ From 35f157073238b9e0e97d9e9d17b4861103d87962 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Oct 2022 02:53:47 +0000 Subject: [PATCH 10/10] instantiate -> construct --- .../rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs | 6 ++---- .../src/traits/error_reporting/suggestions.rs | 4 ++-- src/test/ui/issues/issue-35241.stderr | 2 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 6 +++--- src/test/ui/suggestions/call-on-unimplemented-ctor.rs | 2 +- src/test/ui/suggestions/call-on-unimplemented-ctor.stderr | 2 +- .../ui/suggestions/fn-or-tuple-struct-without-args.stderr | 6 +++--- src/test/ui/typeck/issue-87181/empty-tuple-method.stderr | 2 +- src/test/ui/typeck/issue-87181/enum-variant.stderr | 2 +- src/test/ui/typeck/issue-87181/tuple-field.stderr | 2 +- 10 files changed, 16 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs index 8c4fe75878f..08b21b82faf 100644 --- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs @@ -102,10 +102,8 @@ pub(crate) fn suggest_fn_call( let msg = match def_id_or_name { DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) { - DefKind::Ctor(CtorOf::Struct, _) => "instantiate this tuple struct".to_string(), - DefKind::Ctor(CtorOf::Variant, _) => { - "instantiate this tuple variant".to_string() - } + DefKind::Ctor(CtorOf::Struct, _) => "construct this tuple struct".to_string(), + DefKind::Ctor(CtorOf::Variant, _) => "construct this tuple variant".to_string(), kind => format!("call this {}", kind.descr(def_id)), }, DefIdOrName::Name(name) => format!("call this {name}"), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 98e32e2ce85..8c41d9d240c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -923,10 +923,10 @@ fn suggest_fn_call( let msg = match def_id_or_name { DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) { DefKind::Ctor(CtorOf::Struct, _) => { - "use parentheses to instantiate this tuple struct".to_string() + "use parentheses to construct this tuple struct".to_string() } DefKind::Ctor(CtorOf::Variant, _) => { - "use parentheses to instantiate this tuple variant".to_string() + "use parentheses to construct this tuple variant".to_string() } kind => format!("use parentheses to call this {}", kind.descr(def_id)), }, diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 9ee7654a088..42a78ed97e0 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -11,7 +11,7 @@ LL | fn test() -> Foo { Foo } | = note: expected struct `Foo` found fn item `fn(u32) -> Foo {Foo}` -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | fn test() -> Foo { Foo(/* u32 */) } | +++++++++++ diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index a369dc6db52..82a4211f08a 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -327,7 +327,7 @@ LL | let _: Z = Z::Fn; | = note: expected enum `Z` found fn item `fn(u8) -> Z {Z::Fn}` -help: use parentheses to instantiate this tuple variant +help: use parentheses to construct this tuple variant | LL | let _: Z = Z::Fn(/* u8 */); | ++++++++++ @@ -362,7 +362,7 @@ LL | let _: E = m::E::Fn; | = note: expected enum `E` found fn item `fn(u8) -> E {E::Fn}` -help: use parentheses to instantiate this tuple variant +help: use parentheses to construct this tuple variant | LL | let _: E = m::E::Fn(/* u8 */); | ++++++++++ @@ -397,7 +397,7 @@ LL | let _: E = E::Fn; | = note: expected enum `E` found fn item `fn(u8) -> E {E::Fn}` -help: use parentheses to instantiate this tuple variant +help: use parentheses to construct this tuple variant | LL | let _: E = E::Fn(/* u8 */); | ++++++++++ diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs index 0e7412807b4..5f811044eb3 100644 --- a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs @@ -2,7 +2,7 @@ fn main() { insert_resource(Marker); insert_resource(Time); //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied - //~| HELP use parentheses to instantiate this tuple struct + //~| HELP use parentheses to construct this tuple struct } trait Resource {} diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr index 48f3366596f..58612cbfb23 100644 --- a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr +++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -11,7 +11,7 @@ note: required by a bound in `insert_resource` | LL | fn insert_resource(resource: R) {} | ^^^^^^^^ required by this bound in `insert_resource` -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | insert_resource(Time(/* u32 */)); | +++++++++++ diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index f05dba1d4ca..597dc61c3f7 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -49,7 +49,7 @@ LL | let _: S = S; | = note: expected struct `S` found fn item `fn(usize, usize) -> S {S}` -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | let _: S = S(/* usize */, /* usize */); | ++++++++++++++++++++++++++ @@ -85,7 +85,7 @@ LL | let _: V = V; | = note: expected struct `V` found fn item `fn() -> V {V}` -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | let _: V = V(); | ++ @@ -139,7 +139,7 @@ LL | let _: E = E::A; | = note: expected enum `E` found fn item `fn(usize) -> E {E::A}` -help: use parentheses to instantiate this tuple variant +help: use parentheses to construct this tuple variant | LL | let _: E = E::A(/* usize */); | +++++++++++++ diff --git a/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr b/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr index a18c54a29b5..23e7b7cc363 100644 --- a/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr +++ b/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the LL | thing.bar.foo(); | ^^^ method not found in `fn() -> Foo {Foo}` | -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | (thing.bar)().foo(); | + +++ diff --git a/src/test/ui/typeck/issue-87181/enum-variant.stderr b/src/test/ui/typeck/issue-87181/enum-variant.stderr index 90641410d8e..2247ea27021 100644 --- a/src/test/ui/typeck/issue-87181/enum-variant.stderr +++ b/src/test/ui/typeck/issue-87181/enum-variant.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` i LL | thing.bar.foo(); | ^^^ method not found in `fn() -> Foo {Foo::Tup}` | -help: use parentheses to instantiate this tuple variant +help: use parentheses to construct this tuple variant | LL | (thing.bar)().foo(); | + +++ diff --git a/src/test/ui/typeck/issue-87181/tuple-field.stderr b/src/test/ui/typeck/issue-87181/tuple-field.stderr index c1ca26ee9af..0a7d30b615a 100644 --- a/src/test/ui/typeck/issue-87181/tuple-field.stderr +++ b/src/test/ui/typeck/issue-87181/tuple-field.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}` LL | thing.bar.0; | ^ | -help: use parentheses to instantiate this tuple struct +help: use parentheses to construct this tuple struct | LL | (thing.bar)(/* char */, /* u16 */).0; | + ++++++++++++++++++++++++