From 8490b8ec63782938cc529b7f09518944f907744a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Nov 2023 01:02:23 +0000 Subject: [PATCH 01/14] Dont suggest `!` for path in function call if it has generic args --- .../rustc_resolve/src/late/diagnostics.rs | 22 ++++++++++++++----- tests/ui/resolve/resolve-dont-hint-macro.rs | 4 ++++ .../ui/resolve/resolve-dont-hint-macro.stderr | 9 ++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 tests/ui/resolve/resolve-dont-hint-macro.rs create mode 100644 tests/ui/resolve/resolve-dont-hint-macro.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8316102b50725..df30c185c6062 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -744,6 +744,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err, span, source, + path, res, &path_str, &base_error.fallback_label, @@ -1328,6 +1329,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, span: Span, source: PathSource<'_>, + path: &[Segment], res: Res, path_str: &str, fallback_label: &str, @@ -1523,12 +1525,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | PathSource::Struct, ) => { err.span_label(span, fallback_label.to_string()); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "use `!` to invoke the macro", - "!", - Applicability::MaybeIncorrect, - ); + + // Don't suggest `!` for a macro invocation if there are generic args + if path + .last() + .is_some_and(|segment| !segment.has_generic_args && !segment.has_lifetime_args) + { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "use `!` to invoke the macro", + "!", + Applicability::MaybeIncorrect, + ); + } + if path_str == "try" && span.is_rust_2015() { err.note("if you want the `try` keyword, you need Rust 2018 or later"); } diff --git a/tests/ui/resolve/resolve-dont-hint-macro.rs b/tests/ui/resolve/resolve-dont-hint-macro.rs new file mode 100644 index 0000000000000..da1752b337ebf --- /dev/null +++ b/tests/ui/resolve/resolve-dont-hint-macro.rs @@ -0,0 +1,4 @@ +fn main() { + let zero = assert_eq::<()>(); + //~^ ERROR expected function, found macro `assert_eq` +} diff --git a/tests/ui/resolve/resolve-dont-hint-macro.stderr b/tests/ui/resolve/resolve-dont-hint-macro.stderr new file mode 100644 index 0000000000000..597e014d255dc --- /dev/null +++ b/tests/ui/resolve/resolve-dont-hint-macro.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected function, found macro `assert_eq` + --> $DIR/resolve-dont-hint-macro.rs:2:16 + | +LL | let zero = assert_eq::<()>(); + | ^^^^^^^^^^^^^^^ not a function + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0423`. From fd37da7148ce50ab51058dfd2cb82d9d6b0fba7f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 12:19:38 +1100 Subject: [PATCH 02/14] Remove a comment. It was merged by accident in a previous PR. --- compiler/rustc_span/src/def_id.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 4b5bd75d5b10e..b2d51ac6c0dbd 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -222,7 +222,6 @@ rustc_index::newtype_index! { } } -// njn: I don't understand these impl Encodable for DefIndex { default fn encode(&self, _: &mut E) { panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::()); From 3570468ce713dd5b5d12fc99c47adccd42ca794e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 24 Nov 2023 16:38:59 +1100 Subject: [PATCH 03/14] Remove unused feature. --- compiler/rustc_ast_lowering/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e9e842559225c..129cfa8a910fb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -35,7 +35,6 @@ #![doc(rust_logo)] #![feature(box_patterns)] #![feature(let_chains)] -#![feature(never_type)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] From dbaa78621adf9d2da2ef52eebc8a1f3b35283030 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 26 Nov 2023 06:46:10 +1100 Subject: [PATCH 04/14] Reduce exposure of some things. --- compiler/rustc_ast_lowering/src/index.rs | 2 +- compiler/rustc_ast_lowering/src/lifetime_collector.rs | 2 +- compiler/rustc_ast_lowering/src/pat.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index e91b78720a86b..1741611fb11c5 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::{Span, DUMMY_SP}; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. -pub(super) struct NodeCollector<'a, 'hir> { +struct NodeCollector<'a, 'hir> { tcx: TyCtxt<'hir>, bodies: &'a SortedMap>, diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index d66bba517e019..4b1c057cdbf1d 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -108,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } } -pub fn lifetimes_in_bounds( +pub(crate) fn lifetimes_in_bounds( resolver: &ResolverAstLowering, bounds: &GenericBounds, ) -> Vec { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index a30f264bc7dc7..4950f6e54b5ff 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -18,7 +18,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(self.lower_pat_mut(pattern)) } - pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { + fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion let node = loop { From b12851ce5d56290b6583e23ee484498c0d68937e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 Nov 2023 16:59:53 +1100 Subject: [PATCH 05/14] Avoid an unnecessary `by_ref`. --- compiler/rustc_data_structures/src/graph/scc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index cf9312ea8fb64..b54d75f7ed703 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -492,7 +492,7 @@ where let returned_walk = return_value.take().into_iter().map(|walk| (*successor_node, Some(walk))); - let successor_walk = successors.by_ref().map(|successor_node| { + let successor_walk = successors.map(|successor_node| { debug!(?node, ?successor_node); (successor_node, self.inspect_node(successor_node)) }); From ed2868eb9d4a48dc2aabaf0296807b150d5ea10d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 12:07:05 +1100 Subject: [PATCH 06/14] Create `LoweringContext::lower_assoc_item`. By moving most of `ItemLowerer::lower_assoc_item` into it. This is similar to `LoweringContext::lower_foreign_item`. --- compiler/rustc_ast_lowering/src/item.rs | 68 ++++++++++++++----------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c4c08096b8bb4..bdb2d58167fe9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -136,39 +136,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = self.tcx.local_parent(def_id); let parent_hir = self.lower_node(parent_id).unwrap(); - self.with_lctx(item.id, |lctx| { - // Evaluate with the lifetimes in `params` in-scope. - // This is used to track which lifetimes have already been defined, - // and which need to be replicated when lowering an async fn. - - match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(impl_) => { - lctx.is_in_trait_impl = impl_.of_trait.is_some(); - } - hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => { - lctx.host_param_id = generics - .params - .iter() - .find(|param| { - parent_hir - .attrs - .get(param.hir_id.local_id) - .iter() - .any(|attr| attr.has_name(sym::rustc_host)) - }) - .map(|param| param.def_id); - } - _ => {} - } - - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), - } - }) + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir)) } fn lower_foreign_item(&mut self, item: &ForeignItem) { @@ -609,6 +579,42 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn lower_assoc_item( + &mut self, + item: &AssocItem, + ctxt: AssocCtxt, + parent_hir: &'hir hir::OwnerInfo<'hir>, + ) -> hir::OwnerNode<'hir> { + // Evaluate with the lifetimes in `params` in-scope. + // This is used to track which lifetimes have already been defined, + // and which need to be replicated when lowering an async fn. + + match parent_hir.node().expect_item().kind { + hir::ItemKind::Impl(impl_) => { + self.is_in_trait_impl = impl_.of_trait.is_some(); + } + hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => { + self.host_param_id = generics + .params + .iter() + .find(|param| { + parent_hir + .attrs + .get(param.hir_id.local_id) + .iter() + .any(|attr| attr.has_name(sym::rustc_host)) + }) + .map(|param| param.def_id); + } + _ => {} + } + + match ctxt { + AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)), + } + } + fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let owner_id = hir_id.expect_owner(); From 3bae9276fa13f0b7c39a1d1e1c39aba0fd96bf8d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 12:19:17 +1100 Subject: [PATCH 07/14] Add `LoweringContext::new`. --- compiler/rustc_ast_lowering/src/item.rs | 38 +---------------------- compiler/rustc_ast_lowering/src/lib.rs | 40 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bdb2d58167fe9..2d395179a95ae 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -7,7 +7,6 @@ use hir::definitions::DefPathData; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -55,42 +54,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) { - let allow_gen_future = Some(if self.tcx.features().async_fn_track_caller { - [sym::gen_future, sym::closure_track_caller][..].into() - } else { - [sym::gen_future][..].into() - }); - let mut lctx = LoweringContext { - // Pseudo-globals. - tcx: self.tcx, - resolver: self.resolver, - arena: self.tcx.hir_arena, - - // HirId handling. - bodies: Vec::new(), - attrs: SortedMap::default(), - children: Vec::default(), - current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::new(0), - node_id_to_local_id: Default::default(), - trait_map: Default::default(), - - // Lowering state. - catch_scope: None, - loop_scope: None, - is_in_loop_condition: false, - is_in_trait_impl: false, - is_in_dyn_type: false, - coroutine_kind: None, - task_context: None, - current_item: None, - impl_trait_defs: Vec::new(), - impl_trait_bounds: Vec::new(), - allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), - allow_gen_future, - generics_def_id_map: Default::default(), - host_param_id: None, - }; + let mut lctx = LoweringContext::new(self.tcx, self.resolver); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 129cfa8a910fb..d3f832284ea65 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -144,6 +144,46 @@ struct LoweringContext<'a, 'hir> { host_param_id: Option, } +impl<'a, 'hir> LoweringContext<'a, 'hir> { + fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { + Self { + // Pseudo-globals. + tcx, + resolver: resolver, + arena: tcx.hir_arena, + + // HirId handling. + bodies: Vec::new(), + attrs: SortedMap::default(), + children: Vec::default(), + current_hir_id_owner: hir::CRATE_OWNER_ID, + item_local_id_counter: hir::ItemLocalId::new(0), + node_id_to_local_id: Default::default(), + trait_map: Default::default(), + + // Lowering state. + catch_scope: None, + loop_scope: None, + is_in_loop_condition: false, + is_in_trait_impl: false, + is_in_dyn_type: false, + coroutine_kind: None, + task_context: None, + current_item: None, + impl_trait_defs: Vec::new(), + impl_trait_bounds: Vec::new(), + allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), + allow_gen_future: Some(if tcx.features().async_fn_track_caller { + [sym::gen_future, sym::closure_track_caller][..].into() + } else { + [sym::gen_future][..].into() + }), + generics_def_id_map: Default::default(), + host_param_id: None, + } + } +} + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; fn get_partial_res(&self, id: NodeId) -> Option; From 5c680e1bcb926f76add3f118d17af7f0366b5378 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Nov 2023 12:29:21 +1100 Subject: [PATCH 08/14] Remove unnecessary `Option` from `LoweringContext::allow_{try_trait,gen_future}`. Also remove some unnecessary slicing. --- compiler/rustc_ast_lowering/src/expr.rs | 21 ++++++++++++--------- compiler/rustc_ast_lowering/src/lib.rs | 14 +++++++------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6f2f9787e7727..d3fb6ae0482c2 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -524,7 +524,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.mark_span_with_reason( DesugaringKind::TryBlock, expr.span, - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ), expr, ) @@ -532,7 +532,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, this.tcx.sess.source_map().end_point(body.span), - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ); (try_span, this.expr_unit(try_span)) @@ -612,8 +612,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); // Resume argument type: `ResumeTy` - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + span, + Some(self.allow_gen_future.clone()), + ); let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span); let input_ty = hir::Ty { hir_id: self.next_id(), @@ -735,7 +738,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); self.lower_attrs( inner_hir_id, @@ -782,7 +785,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, full_span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; @@ -1640,13 +1643,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); // `Try::branch()` @@ -1739,7 +1742,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::YeetExpr, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let from_yeet_expr = self.wrap_in_try_constructor( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d3f832284ea65..1964297ace653 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -132,8 +132,8 @@ struct LoweringContext<'a, 'hir> { /// NodeIds that are lowered inside the current HIR owner. node_id_to_local_id: FxHashMap, - allow_try_trait: Option>, - allow_gen_future: Option>, + allow_try_trait: Lrc<[Symbol]>, + allow_gen_future: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -172,12 +172,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { current_item: None, impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), - allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), - allow_gen_future: Some(if tcx.features().async_fn_track_caller { - [sym::gen_future, sym::closure_track_caller][..].into() + allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), + allow_gen_future: if tcx.features().async_fn_track_caller { + [sym::gen_future, sym::closure_track_caller].into() } else { - [sym::gen_future][..].into() - }), + [sym::gen_future].into() + }, generics_def_id_map: Default::default(), host_param_id: None, } From de13a3871d3dabded59a8c434e800647ac011465 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 28 Nov 2023 14:40:24 +0300 Subject: [PATCH 09/14] unwrap return Option value, as it always returns Some for some fns --- compiler/rustc_builtin_macros/src/format.rs | 24 +++++++------------ .../src/format_foreign.rs | 24 +++++++++---------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 12d12d5bff068..c5fd535b03620 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -672,30 +672,22 @@ fn report_missing_placeholders( if explained.contains(&sub) { continue; } - explained.insert(sub.clone()); + explained.insert(sub); if !found_foreign { found_foreign = true; show_doc_note = true; } - if let Some(inner_sp) = pos { - let sp = fmt_span.from_inner(inner_sp); + let sp = fmt_span.from_inner(pos); - if success { - suggestions.push((sp, trn)); - } else { - diag.span_note( - sp, - format!("format specifiers use curly braces, and {}", trn), - ); - } + if success { + suggestions.push((sp, trn)); } else { - if success { - diag.help(format!("`{}` should be written as `{}`", sub, trn)); - } else { - diag.note(format!("`{}` should use curly braces, and {}", sub, trn)); - } + diag.span_note( + sp, + format!("format specifiers use curly braces, and {}", trn), + ); } } diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 2fc8a07636687..307e582d65ef6 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -19,10 +19,10 @@ pub(crate) mod printf { } } - pub fn position(&self) -> Option { + pub fn position(&self) -> InnerSpan { match self { - Substitution::Format(fmt) => Some(fmt.position), - &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), + Substitution::Format(fmt) => fmt.position, + &Substitution::Escape((start, end)) => InnerSpan::new(start, end), } } @@ -302,10 +302,9 @@ pub(crate) mod printf { fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } + let InnerSpan { start, end } = sub.position(); + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; Some(sub) } @@ -629,9 +628,9 @@ pub mod shell { } } - pub fn position(&self) -> Option { + pub fn position(&self) -> InnerSpan { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; - Some(InnerSpan::new(pos.0, pos.1)) + InnerSpan::new(pos.0, pos.1) } pub fn set_position(&mut self, start: usize, end: usize) { @@ -664,10 +663,9 @@ pub mod shell { fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } + let InnerSpan { start, end } = sub.position(); + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; Some(sub) } From 9386e14401b451165630890fa5b8b575dd4723ee Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 28 Nov 2023 23:36:58 +0800 Subject: [PATCH 10/14] fix the issue of suggest unwrap/expect for shorthand field --- .../src/fn_ctxt/suggestions.rs | 6 ++++ .../issue-118145-unwrap-for-shorthand.fixed | 20 +++++++++++++ .../issue-118145-unwrap-for-shorthand.rs | 20 +++++++++++++ .../issue-118145-unwrap-for-shorthand.stderr | 29 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed create mode 100644 tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs create mode 100644 tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c74ef8f271338..2a072795a6c95 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1811,6 +1811,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ".expect(\"REASON\")", ) }; + + let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!(": {ident}{sugg}"), + None => sugg.to_string(), + }; + err.span_suggestion_verbose( expr.span.shrink_to_hi(), msg, diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed new file mode 100644 index 0000000000000..15d4e393874eb --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, dead_code)] + +#[derive(Clone, Copy)] +struct Stuff { + count: i32, +} +struct Error; + +fn demo() -> Result { + let count = Ok(1); + Ok(Stuff { count: count? }) //~ ERROR mismatched types +} + +fn demo_unwrap() -> Stuff { + let count = Some(1); + Stuff { count: count.expect("REASON") } //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs new file mode 100644 index 0000000000000..8e811caa3bdce --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, dead_code)] + +#[derive(Clone, Copy)] +struct Stuff { + count: i32, +} +struct Error; + +fn demo() -> Result { + let count = Ok(1); + Ok(Stuff { count }) //~ ERROR mismatched types +} + +fn demo_unwrap() -> Stuff { + let count = Some(1); + Stuff { count } //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr new file mode 100644 index 0000000000000..0bcbd6f27c44b --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/issue-118145-unwrap-for-shorthand.rs:12:16 + | +LL | Ok(Stuff { count }) + | ^^^^^ expected `i32`, found `Result<{integer}, _>` + | + = note: expected type `i32` + found enum `Result<{integer}, _>` +help: use the `?` operator to extract the `Result<{integer}, _>` value, propagating a `Result::Err` value to the caller + | +LL | Ok(Stuff { count: count? }) + | ++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-118145-unwrap-for-shorthand.rs:17:13 + | +LL | Stuff { count } + | ^^^^^ expected `i32`, found `Option<{integer}>` + | + = note: expected type `i32` + found enum `Option<{integer}>` +help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None` + | +LL | Stuff { count: count.expect("REASON") } + | ++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 115eac03bbd2a4b8b301c3bc627bd0f2c1235525 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 25 Nov 2023 15:45:44 -0500 Subject: [PATCH 11/14] Address unused tuple struct fields in the standard library --- library/alloc/src/boxed/thin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index f83c8f83cc989..a8005b7067d07 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -171,6 +171,7 @@ struct WithHeader(NonNull, PhantomData); /// An opaque representation of `WithHeader` to avoid the /// projection invariance of `::Metadata`. #[repr(transparent)] +#[allow(unused_tuple_struct_fields)] // Field only used through `WithHeader` type above. struct WithOpaqueHeader(NonNull); impl WithOpaqueHeader { From 9b85fc0d1cb9f84e1b94b2f8017a1e13b95ef98d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 28 Nov 2023 16:20:25 -0500 Subject: [PATCH 12/14] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 9b13310ca5960..26333c732095d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9b13310ca596020a737aaa47daa4ed9ff8898a2f +Subproject commit 26333c732095d207aa05932ce863d850fb309386 From 3a4edf0a7f96a413b160b3e9a17e0806abdd4255 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 29 Nov 2023 08:25:06 +0800 Subject: [PATCH 13/14] More fix on mismatched type suggestion for shorthand fields --- compiler/rustc_hir_typeck/src/errors.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 39 +++++++-- .../mismatch-sugg-for-shorthand-field.fixed | 77 ++++++++++++++++++ .../mismatch-sugg-for-shorthand-field.rs | 77 ++++++++++++++++++ .../mismatch-sugg-for-shorthand-field.stderr | 80 +++++++++++++++++++ 5 files changed, 266 insertions(+), 9 deletions(-) create mode 100644 tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed create mode 100644 tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs create mode 100644 tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index aff1baa19601d..74aec897f959e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> { pub span: Span, #[suggestion_part(code = "")] pub borrow_removal_span: Option, - pub sugg: &'static str, + pub sugg: String, pub expected: Ty<'tcx>, pub found: Ty<'tcx>, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 2a072795a6c95..a904b419a94d6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -442,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected, ) }); + + let prefix_wrap = |sugg: &str| { + if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + format!(": {}{}", name, sugg) + } else { + sugg.to_string() + } + }; + // FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`, // but those checks need to be a bit more delicate and the benefit is diminishing. if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref { + let sugg = prefix_wrap(".as_ref()"); err.subdiagnostic(errors::SuggestConvertViaMethod { span: expr.span.shrink_to_hi(), - sugg: ".as_ref()", + sugg, expected, found, borrow_removal_span, @@ -458,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.can_eq(self.param_env, deref_ty, peeled) && error_tys_equate_as_ref { + let sugg = prefix_wrap(".as_deref()"); err.subdiagnostic(errors::SuggestConvertViaMethod { span: expr.span.shrink_to_hi(), - sugg: ".as_deref()", + sugg, expected, found, borrow_removal_span, @@ -474,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.can_eq(self.param_env, found, expected) }) { + let sugg = prefix_wrap(".map(|x| x.as_str())"); err.span_suggestion_verbose( expr.span.shrink_to_hi(), fluent::hir_typeck_convert_to_str, - ".map(|x| x.as_str())", + sugg, Applicability::MachineApplicable, ); return true; @@ -628,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help("use `Box::pin`"); } _ => { + let prefix = if let Some(name) = + self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) + { + format!("{}: ", name) + } else { + String::new() + }; + let suggestion = vec![ + (expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")), + (expr.span.shrink_to_hi(), ")".to_string()), + ]; err.multipart_suggestion( "you need to pin and box this expression", - vec![ - (expr.span.shrink_to_lo(), "Box::pin(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], + suggestion, Applicability::MaybeIncorrect, ); } @@ -1214,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span = parent_callsite; } - let sugg = if expr.precedence().order() >= PREC_POSTFIX { + let mut sugg = if expr.precedence().order() >= PREC_POSTFIX { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -1222,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (span.shrink_to_hi(), ").into()".to_owned()), ] }; + if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name))); + } diag.multipart_suggestion( format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"), sugg, diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed new file mode 100644 index 0000000000000..e1f929e61703c --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed @@ -0,0 +1,77 @@ +// run-rustfix +// edition:2021 +#![allow(dead_code)] +#![allow(unused_variables)] +use std::future::Future; +use std::pin::Pin; + +fn test1() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option: Option<&'a str>, + } + + let option: Option = Some(string.clone()); + let s = Demo { option: option.as_deref() }; //~ ERROR mismatched types +} + +fn test2() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types +} + +fn test3() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let option_ref_ref = option_ref.as_ref(); + + let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types +} + +fn test4() { + let a = 1; + struct Demo { + a: String, + } + let s = Demo { a: a.to_string() }; //~ ERROR mismatched types +} + +type BoxFuture<'a, T> = Pin + Send + 'a>>; +fn test5() { + let a = async { 42 }; + struct Demo { + a: BoxFuture<'static, i32>, + } + let s = Demo { a: Box::pin(a) }; //~ ERROR mismatched types +} + +fn test6() { + struct A; + struct B; + + impl From for A { + fn from(_: B) -> Self { + A + } + } + + struct Demo { + a: A, + } + let a = B; + let s = Demo { a: a.into() }; //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs new file mode 100644 index 0000000000000..956936c925ba0 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs @@ -0,0 +1,77 @@ +// run-rustfix +// edition:2021 +#![allow(dead_code)] +#![allow(unused_variables)] +use std::future::Future; +use std::pin::Pin; + +fn test1() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option: Option<&'a str>, + } + + let option: Option = Some(string.clone()); + let s = Demo { option }; //~ ERROR mismatched types +} + +fn test2() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let s = Demo { option_ref }; //~ ERROR mismatched types +} + +fn test3() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let option_ref_ref = option_ref.as_ref(); + + let s = Demo { option_ref_ref }; //~ ERROR mismatched types +} + +fn test4() { + let a = 1; + struct Demo { + a: String, + } + let s = Demo { a }; //~ ERROR mismatched types +} + +type BoxFuture<'a, T> = Pin + Send + 'a>>; +fn test5() { + let a = async { 42 }; + struct Demo { + a: BoxFuture<'static, i32>, + } + let s = Demo { a }; //~ ERROR mismatched types +} + +fn test6() { + struct A; + struct B; + + impl From for A { + fn from(_: B) -> Self { + A + } + } + + struct Demo { + a: A, + } + let a = B; + let s = Demo { a }; //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr new file mode 100644 index 0000000000000..1baf95d2bf781 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:16:20 + | +LL | let s = Demo { option }; + | ^^^^^^ expected `Option<&str>`, found `Option` + | + = note: expected enum `Option<&str>` + found enum `Option` +help: try using `: option.as_deref()` to convert `Option` to `Option<&str>` + | +LL | let s = Demo { option: option.as_deref() }; + | +++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:27:20 + | +LL | let s = Demo { option_ref }; + | ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>` + | + = note: expected enum `Option<&str>` + found enum `Option<&String>` +help: try converting the passed type into a `&str` + | +LL | let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; + | ++++++++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:40:20 + | +LL | let s = Demo { option_ref_ref }; + | ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>` + | + = note: expected enum `Option<&str>` + found enum `Option<&&String>` +help: try converting the passed type into a `&str` + | +LL | let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; + | ++++++++++++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:48:20 + | +LL | let s = Demo { a }; + | ^ expected `String`, found integer + | +help: try using a conversion method + | +LL | let s = Demo { a: a.to_string() }; + | ++ ++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20 + | +LL | let a = async { 42 }; + | ------------ the found `async` block +... +LL | let s = Demo { a }; + | ^ expected `Pin>`, found `async` block + | + = note: expected struct `Pin + Send + 'static)>>` + found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}` +help: you need to pin and box this expression + | +LL | let s = Demo { a: Box::pin(a) }; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:74:20 + | +LL | let s = Demo { a }; + | ^ expected `A`, found `B` + | +help: call `Into::into` on this expression to convert `B` into `A` + | +LL | let s = Demo { a: a.into() }; + | ++ +++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. From b8cdd4338daa127f2ed0bb6e1d8f666b7e2a6c2f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 28 Nov 2023 17:12:20 -0800 Subject: [PATCH 14/14] Fix a typo in a `format_args!` note --- compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9225f19876dee..ef4bf54345436 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2352,7 +2352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MaybeIncorrect, ); } else { - err.note("the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used"); + err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used"); err.note("to learn more, visit "); } suggested = true; diff --git a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr index 8221505b100e9..3ee89d9734a0f 100644 --- a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr +++ b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr @@ -9,7 +9,7 @@ LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3); LL | bar(x); | - borrow later used here | - = note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used + = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -24,7 +24,7 @@ LL | LL | bar(foo); | --- borrow later used here | - = note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used + = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)