From f5560754591532d7cde4c9f5dd51dfbd7670e98f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 2 Nov 2021 17:20:21 +0000 Subject: [PATCH 1/6] Apply adjustments for field expression even if inaccessible The adjustments are used later by ExprUseVisitor to build Place projections and without adjustments it can produce invalid result. --- compiler/rustc_typeck/src/check/expr.rs | 9 ++++++--- .../issue-90483-inaccessible-field-adjustment.rs | 14 ++++++++++++++ ...ssue-90483-inaccessible-field-adjustment.stderr | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 3846aad2cfc10..2d0a4068fbbe3 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1698,15 +1698,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Save the index of all fields regardless of their visibility in case // of error recovery. self.write_field_index(expr.hir_id, index); + let adjustments = self.adjust_steps(&autoderef); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); return field_ty; } - private_candidate = Some((base_def.did, field_ty)); + private_candidate = Some((adjustments, base_def.did, field_ty)); } } ty::Tuple(tys) => { @@ -1729,7 +1729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - if let Some((did, field_ty)) = private_candidate { + if let Some((adjustments, did, field_ty)) = private_candidate { + // (#90483) apply adjustments to avoid ExprUseVisitor from + // creating erroneous projection. + self.apply_adjustments(base, adjustments); self.ban_private_field_access(expr, expr_t, field, did); return field_ty; } diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs new file mode 100644 index 0000000000000..74e50d46e8dcf --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs @@ -0,0 +1,14 @@ +// edition:2021 + +mod m { + pub struct S { foo: i32 } + impl S { + pub fn foo(&self) -> i32 { 42 } + } +} + +fn bar(s: &m::S) { + || s.foo() + s.foo; //~ ERROR E0616 +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr new file mode 100644 index 0000000000000..02cdc102c15ba --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `foo` of struct `S` is private + --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18 + | +LL | || s.foo() + s.foo; + | ^^^ private field + | +help: a method `foo` also exists, call it with parentheses + | +LL | || s.foo() + s.foo(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. From 768554af7924f38b910ddf733e499653b8076fe7 Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Mon, 1 Nov 2021 16:45:01 -0500 Subject: [PATCH 2/6] Add a chapter on reading Rustdoc output Includes documentation for: - general page structure - navigation - searching - themes - deep-linking Doesn't include docs on the settings page. --- src/doc/rustdoc/src/SUMMARY.md | 1 + src/doc/rustdoc/src/how-to-read-rustdoc.md | 107 +++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/doc/rustdoc/src/how-to-read-rustdoc.md diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 3fa91bb51f02f..eb18185945387 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,6 +1,7 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [How to read rustdoc output](how-to-read-rustdoc.md) - [How to write documentation](how-to-write-documentation.md) - [What to include (and exclude)](what-to-include.md) - [Command-line arguments](command-line-arguments.md) diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md new file mode 100644 index 0000000000000..99724d859ee75 --- /dev/null +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -0,0 +1,107 @@ +# How to read rustdoc output + +Rustdoc's HTML output includes a friendly and useful navigation interface which +makes it easier for users to navigate and understand your code. +This chapter covers the major features of that interface, +and is a great starting point for documentation authors and users alike. + +## Structure + +The `rustdoc` output is divided into three sections. +Along the left side of each page is a quick navigation bar, +which shows contextual information about the current entry. +The rest of the page is taken up by the search interface at the top +and the documentation for the current item below that. + +## The Item Documentation + +The majority of the screen is taken up with the documentation text for the item +currently being viewed. +At the top is some at-a-glance info and controls: + +- the type and name of the item, + such as "Struct `std::time::Duration`", +- a button to copy the item's path to the clipboard, + which is a clipboard item +- a button to collapse or expand the top-level documentation for that item + (`[+]` or `[-]`), +- a link to the source code (`[src]`), + if [configured](the-doc-attribute.html#html_no_source), + and present (the source may not be available if + the documentation was created with `cargo doc --no-deps`), +- and the version in which the item became stable, + if it's a stable item in the standard library. + +Below this is the main documentation for the item, +including a definition or function signature if appropriate, +followed by a list of fields or variants for Rust types. +Finally, the page lists associated functions and trait implementations, +including automatic and blanket implementations that `rustdoc` knows about. + +### Navigation + +Subheadings, variants, fields, and many other things in this documentation +are anchors and can be clicked on and deep-linked to, +which is a great way to communicate exactly what you're talking about. +The typograpical character "ยง" appears next to lines with anchors on them +when hovered or given keyboard focus. + +## The Navigation Bar + +For example, when looking at documentation for the crate root, +it shows all the crates documented in the documentation bundle, +and quick links to the modules, structs, traits, functions, and macros available +from the current crate. +At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url) +alongside the current crate's name and version, +or the current item whose documentation is being displayed. + +## The Theme Picker and Search Interface + +When viewing `rustdoc`'s output in a browser with JavaScript enabled, +a dynamic interface appears at the top of the page. +To the left is the theme picker, denoted with a paint-brush icon, +and the search interface, help screen, and options appear to the right of that. + +### The Theme Picker + +Clicking on the theme picker provides a list of themes - +by default `ayu`, `light`, and `dark` - +which are available for viewing. + +### The Search Interface + +Typing in the search bar instantly searches the available documentation for +the string entered with a fuzzy matching algorithm that is tolerant of minor +typos. + +By default, the search results give are "In Names", +meaning that the fuzzy match is made against the names of items. +Matching names are shown on the left, and the first few words of their +descriptions are given on the right. +By clicking an item, you will navigate to its particular documentation. + +There are two other sets of results, shown as tabs in the search results pane. +"In Parameters" shows matches for the string in the types of parameters to +functions, and "In Return Types" shows matches in the return types of functions. +Both are very useful when looking for a function whose name you can't quite +bring to mind when you know the type you have or want. + +When typing in the search bar, you can prefix your search term with a type +followed by a colon (such as `mod:`) to restrict the results to just that +kind of item. (The available items are listed in the help popup.) + +### Shortcuts + +Pressing `S` while focused elsewhere on the page will move focus to the +search bar, and pressing `?` shows the help screen, +which includes all these shortcuts and more. +Pressing `T` focuses the theme picker. + +When the search results are focused, +the left and right arrows move between tabs and the up and down arrows move +among the results. +Pressing the enter or return key opens the highlighted result. + +When looking at the documentation for an item, the plus and minus keys expand +and collapse all sections in the document. From abb9a9853b094eeeea5ea784d188e842a17c5dc8 Mon Sep 17 00:00:00 2001 From: Ellen Date: Sat, 6 Nov 2021 10:32:11 +0000 Subject: [PATCH 3/6] type error go brrrrrrrr --- compiler/rustc_middle/src/ty/relate.rs | 8 ++++-- .../rustc_typeck/src/check/compare_method.rs | 1 + src/test/ui/compare-method/issue-90444.rs | 17 ++++++++++++ src/test/ui/compare-method/issue-90444.stderr | 27 +++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/compare-method/issue-90444.rs create mode 100644 src/test/ui/compare-method/issue-90444.stderr diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8b20e1eec9a86..c7d8bec506f6b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -187,8 +187,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { }) .enumerate() .map(|(i, r)| match r { - Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)), - Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)), + Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => { + Err(TypeError::ArgumentSorts(exp_found, i)) + } + Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => { + Err(TypeError::ArgumentMutability(i)) + } r => r, }); Ok(ty::FnSig { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index d5b631df058ae..7c262dcf72339 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -453,6 +453,7 @@ fn check_region_bounds_on_impl_item<'tcx>( Ok(()) } +#[instrument(level = "debug", skip(infcx))] fn extract_spans_for_error_reporting<'a, 'tcx>( infcx: &infer::InferCtxt<'a, 'tcx>, terr: &TypeError<'_>, diff --git a/src/test/ui/compare-method/issue-90444.rs b/src/test/ui/compare-method/issue-90444.rs new file mode 100644 index 0000000000000..6c287d9a707de --- /dev/null +++ b/src/test/ui/compare-method/issue-90444.rs @@ -0,0 +1,17 @@ +pub struct A; +impl From for A { + fn from(_: fn((), (), &mut ())) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +pub struct B; +impl From for B { + fn from(_: fn((), (), u64)) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +fn main() {} diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr new file mode 100644 index 0000000000000..84bbec0623fd8 --- /dev/null +++ b/src/test/ui/compare-method/issue-90444.stderr @@ -0,0 +1,27 @@ +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:3:16 + | +LL | fn from(_: fn((), (), &mut ())) -> Self { + | ^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())` + | + = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A` + found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A` + +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:11:16 + | +LL | fn from(_: fn((), (), u64)) -> Self { + | ^^^^^^^^^^^^^^^ + | | + | expected `u32`, found `u64` + | help: change the parameter type to match the trait: `fn((), (), u32)` + | + = note: expected fn pointer `fn(fn((), (), u32)) -> B` + found fn pointer `fn(fn((), (), u64)) -> B` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. From a3776d99ccdd60d3f880005e4fe4e9478768ea41 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Nov 2021 15:56:29 +0100 Subject: [PATCH 4/6] Run reveal_all on MIR more often. --- compiler/rustc_mir_transform/src/reveal_all.rs | 2 +- src/test/mir-opt/issue-78192.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 7b4eb4912cb36..6c423a2bb5756 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -11,7 +11,7 @@ impl<'tcx> MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // This pass must run before inlining, since we insert callee bodies in RevealAll mode. // Do not apply this transformation to generators. - if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx)) + if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx)) && body.generator.is_none() { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); diff --git a/src/test/mir-opt/issue-78192.rs b/src/test/mir-opt/issue-78192.rs index 906d094f72b4a..39f665402b025 100644 --- a/src/test/mir-opt/issue-78192.rs +++ b/src/test/mir-opt/issue-78192.rs @@ -1,4 +1,4 @@ -// EMIT_MIR issue_78192.f.InstCombine.diff +// compile-flags: -Zmir-opt-level=1 -Zinline-mir pub fn f(a: &T) -> *const T { let b: &*const T = &(a as *const T); *b @@ -7,3 +7,5 @@ pub fn f(a: &T) -> *const T { fn main() { f(&2); } + +// EMIT_MIR issue_78192.f.InstCombine.diff From 0a5640b55f4a34a1f96859663449b0cabfb08c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 6 Nov 2021 01:31:32 +0100 Subject: [PATCH 5/6] use matches!() macro in more places --- compiler/rustc_ast/src/util/parser.rs | 8 ++++---- .../src/diagnostics/explain_borrow.rs | 5 +---- compiler/rustc_borrowck/src/region_infer/mod.rs | 14 +++++++------- compiler/rustc_borrowck/src/universal_regions.rs | 10 ++-------- .../rustc_codegen_ssa/src/debuginfo/type_names.rs | 5 +---- compiler/rustc_const_eval/src/const_eval/error.rs | 5 +---- .../rustc_const_eval/src/const_eval/fn_queries.rs | 4 +--- .../src/interpret/intrinsics/type_name.rs | 6 ++---- .../rustc_const_eval/src/interpret/terminator.rs | 6 ++---- .../src/transform/check_consts/check.rs | 5 +---- .../src/transform/check_consts/qualifs.rs | 11 ++++++----- compiler/rustc_lexer/src/unescape.rs | 9 ++++----- compiler/rustc_middle/src/mir/interpret/error.rs | 10 +++++----- compiler/rustc_mir_transform/src/coverage/mod.rs | 2 +- compiler/rustc_mir_transform/src/coverage/spans.rs | 7 +++---- .../rustc_mir_transform/src/unreachable_prop.rs | 5 ++--- .../rustc_trait_selection/src/traits/select/mod.rs | 5 +---- compiler/rustc_typeck/src/check/cast.rs | 7 ++----- .../wrong_number_of_generic_args.rs | 2 +- library/std/src/net/ip.rs | 7 +------ library/std/src/os/unix/net/addr.rs | 2 +- 21 files changed, 49 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 500c97e65ef9c..742a7d1d2df70 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -212,7 +212,8 @@ impl AssocOp { /// parentheses while having a high degree of confidence on the correctness of the suggestion. pub fn can_continue_expr_unambiguously(&self) -> bool { use AssocOp::*; - match self { + matches!( + self, BitXor | // `{ 42 } ^ 3` Assign | // `{ 42 } = { 42 }` Divide | // `{ 42 } / 42` @@ -225,9 +226,8 @@ impl AssocOp { As | // `{ 42 } as usize` // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. - Colon => true, // `{ 42 }: usize` - _ => false, - } + Colon, // `{ 42 }: usize` + ) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index d5de0801ac443..79973ab170cad 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -53,10 +53,7 @@ pub(crate) enum LaterUseKind { impl BorrowExplanation { pub(crate) fn is_explained(&self) -> bool { - match self { - BorrowExplanation::Unexplained => false, - _ => true, - } + !matches!(self, BorrowExplanation::Unexplained) } pub(crate) fn add_explanation_to_diagnostic<'tcx>( &self, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 22bb3a29425ee..f4a5da1fe36fa 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2110,14 +2110,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { _ => constraint_sup_scc != target_scc, } } else { - match categorized_path[*i].category { + !matches!( + categorized_path[*i].category, ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal - | ConstraintCategory::Predicate(_) => false, - _ => true, - } + | ConstraintCategory::Boring + | ConstraintCategory::BoringNoLocation + | ConstraintCategory::Internal + | ConstraintCategory::Predicate(_) + ) } }; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index bebd19370299d..147e2aead648d 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -138,17 +138,11 @@ impl<'tcx> DefiningTy<'tcx> { } pub fn is_fn_def(&self) -> bool { - match *self { - DefiningTy::FnDef(..) => true, - _ => false, - } + matches!(*self, DefiningTy::FnDef(..)) } pub fn is_const(&self) -> bool { - match *self { - DefiningTy::Const(..) => true, - _ => false, - } + matches!(*self, DefiningTy::Const(..)) } pub fn def_id(&self) -> DefId { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index accb54e464553..ab119ae25f5e8 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -124,10 +124,7 @@ fn push_debuginfo_type_name<'tcx>( // info for MSVC debugger. However, wrapping these types' names in a synthetic type // causes the .natvis engine for WinDbg to fail to display their data, so we opt these // types out to aid debugging in MSVC. - let is_slice_or_str = match *inner_type.kind() { - ty::Slice(_) | ty::Str => true, - _ => false, - }; + let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); if !cpp_like_names { output.push('&'); diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 5da1681662577..87298023980ed 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -25,10 +25,7 @@ pub enum ConstEvalErrKind { impl MachineStopType for ConstEvalErrKind { fn is_hard_err(&self) -> bool { - match self { - Self::Panic { .. } => true, - _ => false, - } + matches!(self, Self::Panic { .. }) } } diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 80551518d3c5d..821b048eb9bcf 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -51,10 +51,8 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // If the function itself is not annotated with `const`, it may still be a `const fn` // if it resides in a const trait impl. is_parent_const_impl_raw(tcx, hir_id) - } else if let hir::Node::Ctor(_) = node { - true } else { - false + matches!(node, hir::Node::Ctor(_)) } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index a7012cd63f313..5b4a5ac357722 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -138,10 +138,8 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { args: &[GenericArg<'tcx>], ) -> Result { self = print_prefix(self)?; - let args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => false, - _ => true, - }); + let args = + args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))); if args.clone().next().is_some() { self.generic_delimiters(|cx| cx.comma_sep(args)) } else { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 8d3544d434acf..00208574c555e 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -345,10 +345,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Figure out how to pass which arguments. // The Rust ABI is special: ZST get skipped. - let rust_abi = match caller_abi { - Abi::Rust | Abi::RustCall => true, - _ => false, - }; + let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall); + // We have two iterators: Where the arguments come from, // and where they go to. diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 3a5bc37b85ad6..3785c170f6b2b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -131,10 +131,7 @@ impl Qualifs<'mir, 'tcx> { .body .basic_blocks() .iter_enumerated() - .find(|(_, block)| match block.terminator().kind { - TerminatorKind::Return => true, - _ => false, - }) + .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return)) .map(|(bb, _)| bb); let return_block = match return_block { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 0fdb772c262dd..abc5a3c6a5206 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -170,11 +170,12 @@ impl Qualif for NeedsNonConstDrop { let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); selcx.select(&obligation) }); - match implsrc { - Ok(Some(ImplSource::ConstDrop(_))) - | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false, - _ => true, - } + !matches!( + implsrc, + Ok(Some( + ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + )) + ) } fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index b970c9e4911fa..d789237e692d2 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -68,11 +68,10 @@ pub enum EscapeError { impl EscapeError { /// Returns true for actual errors, as opposed to warnings. pub fn is_fatal(&self) -> bool { - match self { - EscapeError::UnskippedWhitespaceWarning => false, - EscapeError::MultipleSkippedLinesWarning => false, - _ => true, - } + !matches!( + self, + EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning + ) } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 9472a287e5a41..7a51bb4a1f32a 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -538,12 +538,12 @@ impl InterpError<'_> { /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors, /// so this method lets us detect them and `bug!` on unexpected errors. pub fn formatted_string(&self) -> bool { - match self { + matches!( + self, InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. }) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, - _ => false, - } + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. }) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) + ) } /// Should this error be reported as a hard error, preventing compilation, or a soft error, diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 4ac93f7161923..6807d02519e2b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -485,7 +485,7 @@ fn inject_statement( // Non-code expressions are injected into the coverage map, without generating executable code. fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) { - debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false }); + debug_assert!(matches!(expression, CoverageKind::Expression { .. })); debug!(" injecting non-code expression {:?}", expression); let inject_in_bb = mir::START_BLOCK; let data = &mut mir_body[inject_in_bb]; diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index cc525a4d6b91c..d13fa0729cd95 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -94,10 +94,9 @@ impl CoverageSpan { stmt_index: usize, ) -> Self { let is_closure = match statement.kind { - StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => match kind { - AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _) => true, - _ => false, - }, + StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => { + matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _)) + } _ => false, }; diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index baf381081ddab..64cd6f56a9ffa 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -27,9 +27,8 @@ impl MirPass<'_> for UnreachablePropagation { // This is a temporary solution that handles possibly diverging asm statements. // Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs let asm_stmt_in_block = || { - bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind { - StatementKind::LlvmInlineAsm(..) => true, - _ => false, + bb_data.statements.iter().any(|stmt: &Statement<'_>| { + matches!(stmt.kind, StatementKind::LlvmInlineAsm(..)) }) }; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 60676ad3f4f60..481bfa4a26b36 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -320,10 +320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Returns `true` if the trait predicate is considerd `const` to this selection context. pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { - match pred.constness { - ty::BoundConstness::ConstIfConst if self.is_in_const_context => true, - _ => false, - } + matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context } /// Returns `true` if the predicate is considered `const` to diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 78849b276d6bf..511a2d7ddacf9 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -436,11 +436,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Very crude check to see whether the expression must be wrapped // in parentheses for the suggestion to work (issue #89497). // Can/should be extended in the future. - let needs_parens = !has_parens - && match self.expr.kind { - hir::ExprKind::Cast(..) => true, - _ => false, - }; + let needs_parens = + !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..)); let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)]; if needs_parens { diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index 8d3862ffc8f01..a1c2945770920 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { hir::TyKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Def(_, id), .. }, - )) if *id == def_id => true, + )) => *id == def_id, _ => false, }) }) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 140647128a937..da95fe21ac9af 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -878,12 +878,7 @@ impl Ipv4Addr { #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { - match self.octets() { - [192, 0, 2, _] => true, - [198, 51, 100, _] => true, - [203, 0, 113, _] => true, - _ => false, - } + matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]) } /// Converts this address to an [IPv4-compatible] [`IPv6` address]. diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 887f605993918..f450e41bfea1e 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -159,7 +159,7 @@ impl SocketAddr { #[must_use] #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { true } else { false } + matches!(self.address(), AddressKind::Unnamed) } /// Returns the contents of this address if it is a `pathname` address. From d93f7f93c44a7106071411224c0615c7cfcb2468 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 4 Nov 2021 23:25:16 -0700 Subject: [PATCH 6/6] Suggest dereference of `Box` when inner type is expected For example: enum Ty { Unit, List(Box), } fn foo(x: Ty) -> Ty { match x { Ty::Unit => Ty::Unit, Ty::List(elem) => foo(elem), } } Before, the only suggestion was to rewrap `elem` with `Ty::List`, which is unhelpful and confusing: error[E0308]: mismatched types --> src/test/ui/suggestions/boxed-variant-field.rs:9:31 | 9 | Ty::List(elem) => foo(elem), | ^^^^ | | | expected enum `Ty`, found struct `Box` | help: try using a variant of the expected enum: `Ty::List(elem)` | = note: expected enum `Ty` found struct `Box` Now, rustc will first suggest dereferencing the `Box`, which is most likely what the user intended: error[E0308]: mismatched types --> src/test/ui/suggestions/boxed-variant-field.rs:9:31 | 9 | Ty::List(elem) => foo(elem), | ^^^^ expected enum `Ty`, found struct `Box` | = note: expected enum `Ty` found struct `Box` help: try dereferencing the `Box` | 9 | Ty::List(elem) => foo(*elem), | + help: try using a variant of the expected enum | 9 | Ty::List(elem) => foo(Ty::List(elem)), | ~~~~~~~~~~~~~~ --- compiler/rustc_typeck/src/check/demand.rs | 18 +++++++++++++++++ .../ui/suggestions/boxed-variant-field.rs | 16 +++++++++++++++ .../ui/suggestions/boxed-variant-field.stderr | 20 +++++++++++++++++++ src/test/ui/terr-sorts.stderr | 4 ++++ 4 files changed, 58 insertions(+) create mode 100644 src/test/ui/suggestions/boxed-variant-field.rs create mode 100644 src/test/ui/suggestions/boxed-variant-field.stderr diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 2b3672211e4f5..0cbbcdd107371 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -29,6 +29,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) { self.annotate_expected_due_to_let_ty(err, expr); + self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { @@ -167,6 +168,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn suggest_box_deref( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr<'_>, + expected: Ty<'tcx>, + expr_ty: Ty<'tcx>, + ) { + if expr_ty.is_box() && expr_ty.boxed_ty() == expected { + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "try dereferencing the `Box`", + "*".to_string(), + Applicability::MachineApplicable, + ); + } + } + /// If the expected type is an enum (Issue #55250) with any variants whose /// sole field is of the found type, suggest such variants. (Issue #42764) fn suggest_compatible_variants( diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs new file mode 100644 index 0000000000000..d8f7fac151356 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -0,0 +1,16 @@ +enum Ty { + Unit, + List(Box), +} + +fn foo(x: Ty) -> Ty { + match x { + Ty::Unit => Ty::Unit, + Ty::List(elem) => foo(elem), + //~^ ERROR mismatched types + //~| HELP try dereferencing the `Box` + //~| HELP try using a variant of the expected enum + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr new file mode 100644 index 0000000000000..d4ccb2ca490bc --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/boxed-variant-field.rs:9:31 + | +LL | Ty::List(elem) => foo(elem), + | ^^^^ expected enum `Ty`, found struct `Box` + | + = note: expected enum `Ty` + found struct `Box` +help: try dereferencing the `Box` + | +LL | Ty::List(elem) => foo(*elem), + | + +help: try using a variant of the expected enum + | +LL | Ty::List(elem) => foo(Ty::List(elem)), + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terr-sorts.stderr b/src/test/ui/terr-sorts.stderr index 869b372965966..65d90678040d5 100644 --- a/src/test/ui/terr-sorts.stderr +++ b/src/test/ui/terr-sorts.stderr @@ -6,6 +6,10 @@ LL | want_foo(b); | = note: expected struct `Foo` found struct `Box` +help: try dereferencing the `Box` + | +LL | want_foo(*b); + | + error: aborting due to previous error