From 7e7d0074671a4b1c4940defbabb30c67c4369fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 3 Jul 2022 00:00:00 +0000 Subject: [PATCH 01/16] Add `SourceScope::inlined_instance` --- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 7 ++----- compiler/rustc_middle/src/mir/mod.rs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index a283bf1de763a..f1fe495282abc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -9,11 +9,8 @@ use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { // Determine the instance that coverage data was originally generated for. - let scope_data = &self.mir.source_scopes[scope]; - let instance = if let Some((inlined_instance, _)) = scope_data.inlined { - self.monomorphize(inlined_instance) - } else if let Some(inlined_scope) = scope_data.inlined_parent_scope { - self.monomorphize(self.mir.source_scopes[inlined_scope].inlined.unwrap().0) + let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { + self.monomorphize(inlined) } else { self.instance }; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9368612810198..743e02ad3e19e 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1650,6 +1650,22 @@ impl SourceScope { ClearCrossCrate::Clear => None, } } + + /// The instance this source scope was inlined from, if any. + #[inline] + pub fn inlined_instance<'tcx>( + self, + source_scopes: &IndexVec>, + ) -> Option> { + let scope_data = &source_scopes[self]; + if let Some((inlined_instance, _)) = scope_data.inlined { + Some(inlined_instance) + } else if let Some(inlined_scope) = scope_data.inlined_parent_scope { + Some(source_scopes[inlined_scope].inlined.unwrap().0) + } else { + None + } + } } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] From fadae872fabd317020eeefbb118d8e07e5e43994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 3 Jul 2022 00:00:00 +0000 Subject: [PATCH 02/16] Use extend instead of repeatedly pushing into a vec --- compiler/rustc_mir_transform/src/simplify.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 980af98436281..ec0eebe5611e8 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -352,15 +352,15 @@ fn save_unreachable_coverage( } let start_block = &mut basic_blocks[START_BLOCK]; - for (source_info, code_region) in dropped_coverage { - start_block.statements.push(Statement { + start_block.statements.extend(dropped_coverage.into_iter().map( + |(source_info, code_region)| Statement { source_info, kind: StatementKind::Coverage(Box::new(Coverage { kind: CoverageKind::Unreachable, code_region: Some(code_region), })), - }) - } + }, + )); } pub struct SimplifyLocals; From 62ab4b61609e6f1329c3f386e545412e8c7e58d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 3 Jul 2022 00:00:00 +0000 Subject: [PATCH 03/16] Fix unreachable coverage generation for inlined functions To generate a function coverage we need at least one coverage counter, so a coverage from unreachable blocks is retained only when some live counters remain. The previous implementation incorrectly retained unreachable coverage, because it didn't account for the fact that those live counters can belong to another function due to inlining. --- compiler/rustc_mir_transform/src/simplify.rs | 72 ++++++++++--------- .../src/partitioning/mod.rs | 12 +++- .../expected_show_coverage.inline-dead.txt | 21 ++++++ .../run-make-fulldeps/coverage/inline-dead.rs | 20 ++++++ 4 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt create mode 100644 src/test/run-make-fulldeps/coverage/inline-dead.rs diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index ec0eebe5611e8..59c38b87b5cb2 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -28,6 +28,7 @@ //! return. use crate::MirPass; +use rustc_data_structures::stable_set::FxHashSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -267,7 +268,8 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { return; } - let basic_blocks = body.basic_blocks_mut(); + let basic_blocks = body.basic_blocks.as_mut(); + let source_scopes = &body.source_scopes; let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut used_blocks = 0; for alive_index in reachable.iter() { @@ -282,7 +284,7 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, used_blocks); + save_unreachable_coverage(basic_blocks, source_scopes, used_blocks); } basic_blocks.raw.truncate(used_blocks); @@ -311,48 +313,54 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// `Unreachable` coverage statements. These are non-executable statements whose /// code regions are still recorded in the coverage map, representing regions /// with `0` executions. +/// +/// If there are no live `Counter` `Coverage` statements remaining, we remove +/// dead `Coverage` statements along with the dead blocks. Since at least one +/// counter per function is required by LLVM (and necessary, to add the +/// `function_hash` to the counter's call to the LLVM intrinsic +/// `instrprof.increment()`). +/// +/// The `generator::StateTransform` MIR pass and MIR inlining can create +/// atypical conditions, where all live `Counter`s are dropped from the MIR. +/// +/// With MIR inlining we can have coverage counters belonging to different +/// instances in a single body, so the strategy described above is applied to +/// coverage counters from each instance individually. fn save_unreachable_coverage( basic_blocks: &mut IndexVec>, + source_scopes: &IndexVec>, first_dead_block: usize, ) { - let has_live_counters = basic_blocks.raw[0..first_dead_block].iter().any(|live_block| { - live_block.statements.iter().any(|statement| { - if let StatementKind::Coverage(coverage) = &statement.kind { - matches!(coverage.kind, CoverageKind::Counter { .. }) - } else { - false - } - }) - }); - if !has_live_counters { - // If there are no live `Counter` `Coverage` statements anymore, don't - // move dead coverage to the `START_BLOCK`. Just allow the dead - // `Coverage` statements to be dropped with the dead blocks. - // - // The `generator::StateTransform` MIR pass can create atypical - // conditions, where all live `Counter`s are dropped from the MIR. - // - // At least one Counter per function is required by LLVM (and necessary, - // to add the `function_hash` to the counter's call to the LLVM - // intrinsic `instrprof.increment()`). + // Identify instances that still have some live coverage counters left. + let mut live = FxHashSet::default(); + for basic_block in &basic_blocks.raw[0..first_dead_block] { + for statement in &basic_block.statements { + let StatementKind::Coverage(coverage) = &statement.kind else { continue }; + let CoverageKind::Counter { .. } = coverage.kind else { continue }; + let instance = statement.source_info.scope.inlined_instance(source_scopes); + live.insert(instance); + } + } + + if live.is_empty() { return; } - // Retain coverage info for dead blocks, so coverage reports will still - // report `0` executions for the uncovered code regions. - let mut dropped_coverage = Vec::new(); - for dead_block in basic_blocks.raw[first_dead_block..].iter() { - for statement in dead_block.statements.iter() { - if let StatementKind::Coverage(coverage) = &statement.kind { - if let Some(code_region) = &coverage.code_region { - dropped_coverage.push((statement.source_info, code_region.clone())); - } + // Retain coverage for instances that still have some live counters left. + let mut retained_coverage = Vec::new(); + for dead_block in &basic_blocks.raw[first_dead_block..] { + for statement in &dead_block.statements { + let StatementKind::Coverage(coverage) = &statement.kind else { continue }; + let Some(code_region) = &coverage.code_region else { continue }; + let instance = statement.source_info.scope.inlined_instance(source_scopes); + if live.contains(&instance) { + retained_coverage.push((statement.source_info, code_region.clone())); } } } let start_block = &mut basic_blocks[START_BLOCK]; - start_block.statements.extend(dropped_coverage.into_iter().map( + start_block.statements.extend(retained_coverage.into_iter().map( |(source_info, code_region)| Statement { source_info, kind: StatementKind::Coverage(Box::new(Coverage { diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index c1992137575bc..a1061dbf67fbd 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -98,6 +98,7 @@ mod merging; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; use rustc_hir::def_id::DefIdSet; +use rustc_middle::mir; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -479,9 +480,14 @@ fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSe if !visited.insert(did) { continue; } - for scope in &tcx.instance_mir(instance.def).source_scopes { - if let Some((ref inlined, _)) = scope.inlined { - result.insert(inlined.def_id()); + let body = tcx.instance_mir(instance.def); + for block in body.basic_blocks() { + for statement in &block.statements { + let mir::StatementKind::Coverage(_) = statement.kind else { continue }; + let scope = statement.source_info.scope; + if let Some(inlined) = scope.inlined_instance(&body.source_scopes) { + result.insert(inlined.def_id()); + } } } } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt new file mode 100644 index 0000000000000..d102d9ecf7d14 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt @@ -0,0 +1,21 @@ + 1| |// Regression test for issue #98833. + 2| |// compile-flags: -Zinline-mir + 3| | + 4| 1|fn main() { + 5| 1| println!("{}", live::()); + 6| 1|} + 7| | + 8| |#[inline] + 9| 1|fn live() -> u32 { + 10| 1| if B { + 11| 0| dead() + 12| | } else { + 13| 1| 0 + 14| | } + 15| 1|} + 16| | + 17| |#[inline] + 18| 0|fn dead() -> u32 { + 19| 0| 42 + 20| 0|} + diff --git a/src/test/run-make-fulldeps/coverage/inline-dead.rs b/src/test/run-make-fulldeps/coverage/inline-dead.rs new file mode 100644 index 0000000000000..cd1ae911a5f7e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/inline-dead.rs @@ -0,0 +1,20 @@ +// Regression test for issue #98833. +// compile-flags: -Zinline-mir + +fn main() { + println!("{}", live::()); +} + +#[inline] +fn live() -> u32 { + if B { + dead() + } else { + 0 + } +} + +#[inline] +fn dead() -> u32 { + 42 +} From 0e146148c44abc9afa20331b837358b73b8ed415 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 18 Jul 2022 17:45:54 +0200 Subject: [PATCH 04/16] Group CSS font rule --- src/librustdoc/html/static/css/rustdoc.css | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index c6933a8254bc2..f0bbf2e664d66 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -216,6 +216,15 @@ details.rustdoc-toggle > summary::before, div.impl-items > div:not(.docblock):not(.item-info), .content ul.crate a.crate, a.srclink, +#main-content > .since, +#help-button > button, +details.rustdoc-toggle.top-doc > summary, +details.rustdoc-toggle.top-doc > summary::before, +details.rustdoc-toggle.non-exhaustive > summary, +details.rustdoc-toggle.non-exhaustive > summary::before, +.scraped-example-title, +.more-examples-toggle summary, .more-examples-toggle .hide-more, +.example-links a, /* This selector is for the items listed in the "all items" page. */ #main-content > ul.docblock > li > a { font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; @@ -702,7 +711,6 @@ pre, .rustdoc.source .example-wrap { } #main-content > .since { top: inherit; - font-family: "Fira Sans", Arial, sans-serif; } .content table:not(.table-display) { @@ -1521,7 +1529,6 @@ input:checked + .slider { } #help-button > button { - font-family: "Fira Sans", Arial, sans-serif; text-align: center; /* Rare exception to specifying font sizes in rem. Since this is acting as an icon, it's okay to specify their sizes in pixels. */ @@ -1693,7 +1700,6 @@ details.rustdoc-toggle.top-doc > summary, details.rustdoc-toggle.top-doc > summary::before, details.rustdoc-toggle.non-exhaustive > summary, details.rustdoc-toggle.non-exhaustive > summary::before { - font-family: 'Fira Sans'; font-size: 1rem; } @@ -2179,10 +2185,6 @@ in storage.js plus the media query with (min-width: 701px) border-radius: 50px; } -.scraped-example-title { - font-family: 'Fira Sans'; -} - .scraped-example .code-wrapper { position: relative; display: flex; @@ -2286,10 +2288,6 @@ in storage.js plus the media query with (min-width: 701px) cursor: pointer; } -.more-examples-toggle summary, .more-examples-toggle .hide-more { - font-family: 'Fira Sans'; -} - .more-scraped-examples { margin-left: 5px; display: flex; @@ -2324,7 +2322,6 @@ in storage.js plus the media query with (min-width: 701px) .example-links a { margin-top: 20px; - font-family: 'Fira Sans'; } .example-links ul { From c39826e3fac3a3d63a75355d87b6a62ff3cbb8cb Mon Sep 17 00:00:00 2001 From: Artur Sinila Date: Tue, 19 Jul 2022 02:25:14 +0300 Subject: [PATCH 05/16] feat: omit suffixes in const generics (e.g. `1_i32`) Closes #99255 --- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../match_arr_unknown_len.stderr | 2 +- .../associated-type-bound-fail.stderr | 2 +- .../generic-expr-default-concrete.stderr | 6 ++-- .../ui/const-generics/defaults/mismatch.rs | 22 ++++++------ .../const-generics/defaults/mismatch.stderr | 34 +++++++++---------- .../defaults/rp_impl_trait_fail.rs | 5 ++- .../defaults/rp_impl_trait_fail.stderr | 18 +++++----- .../defaults/trait_objects_fail.rs | 4 +-- .../defaults/trait_objects_fail.stderr | 10 +++--- src/test/ui/const-generics/defaults/wfness.rs | 12 ++++--- .../ui/const-generics/defaults/wfness.stderr | 27 ++++++++------- .../different_generic_args.full.stderr | 6 ++-- .../different_generic_args.min.stderr | 6 ++-- .../different_generic_args_array.stderr | 6 ++-- .../ui/const-generics/exhaustive-value.stderr | 16 ++++----- .../generic_arg_infer/in-signature.stderr | 12 +++---- .../abstract-const-as-cast-3.stderr | 24 ++++++------- .../generic_const_exprs/from-sig-fail.rs | 2 +- .../generic_const_exprs/from-sig-fail.stderr | 2 +- .../generic_const_exprs/issue-69654.stderr | 4 +-- .../issue-72787.min.stderr | 8 ++--- .../generic_const_exprs/simple_fail.rs | 9 +++-- .../generic_const_exprs/simple_fail.stderr | 10 +++--- .../infer/one-param-uninferred.stderr | 4 +-- src/test/ui/const-generics/issue-66451.stderr | 6 ++-- .../ui/const-generics/nested-type.full.stderr | 2 +- .../occurs-check/unused-substs-1.stderr | 6 ++-- .../types-mismatch-const-args.full.stderr | 10 +++--- .../types-mismatch-const-args.min.stderr | 10 +++--- .../ui/consts/const-eval/issue-85155.stderr | 4 +-- .../reject-specialized-drops-8142.stderr | 2 +- .../const-expr-generic-err.stderr | 4 +-- .../ui/lint/function-item-references.stderr | 4 +-- .../method-not-found-generic-arg-elision.rs | 14 ++++---- ...ethod-not-found-generic-arg-elision.stderr | 8 ++--- .../ui/simd/intrinsic/generic-shuffle.stderr | 4 +-- .../ui/simd/libm_no_std_cant_float.stderr | 12 +++---- .../type-generic-monomorphisation-empty.rs | 2 +- ...type-generic-monomorphisation-empty.stderr | 2 +- ...type-generic-monomorphisation-oversized.rs | 2 +- ...-generic-monomorphisation-oversized.stderr | 2 +- .../generic_nondefining_use.stderr | 2 +- 43 files changed, 179 insertions(+), 170 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 96e84bc8f0acf..5378c63a87da0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1727,7 +1727,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } fn print_const(self, ct: ty::Const<'tcx>) -> Result { - self.pretty_print_const(ct, true) + self.pretty_print_const(ct, false) } fn path_crate(mut self, cnum: CrateNum) -> Result { diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr index 1a14ab40b1f86..5e531a993c62c 100644 --- a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/match_arr_unknown_len.rs:3:9 | LL | [1, 2] => true, - | ^^^^^^ expected `2_usize`, found `N` + | ^^^^^^ expected `2`, found `N` | = note: expected array `[u32; 2]` found array `[u32; N]` diff --git a/src/test/ui/const-generics/associated-type-bound-fail.stderr b/src/test/ui/const-generics/associated-type-bound-fail.stderr index da2558229a758..e5e7ee26e44bc 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.stderr +++ b/src/test/ui/const-generics/associated-type-bound-fail.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `u16: Bar` is not satisfied LL | type Assoc = u16; | ^^^ the trait `Bar` is not implemented for `u16` | - = help: the trait `Bar<3_usize>` is implemented for `u16` + = help: the trait `Bar<3>` is implemented for `u16` note: required by a bound in `Foo::Assoc` --> $DIR/associated-type-bound-fail.rs:4:17 | diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr index 905a285370a0d..e8826ce4335e7 100644 --- a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr +++ b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/generic-expr-default-concrete.rs:10:5 | LL | Foo::<10, 12> - | ^^^^^^^^^^^^^ expected `11_usize`, found `12_usize` + | ^^^^^^^^^^^^^ expected `11`, found `12` | - = note: expected type `11_usize` - found type `12_usize` + = note: expected type `11` + found type `12` error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs index fce4ec4edda08..ec131505ed755 100644 --- a/src/test/ui/const-generics/defaults/mismatch.rs +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -1,22 +1,22 @@ -pub struct Example; -pub struct Example2(T); -pub struct Example3(T); -pub struct Example4; +pub struct Example; +pub struct Example2(T); +pub struct Example3(T); +pub struct Example4; fn main() { - let e: Example::<13> = (); + let e: Example<13> = (); //~^ Error: mismatched types //~| expected struct `Example` - let e: Example2:: = (); + let e: Example2 = (); //~^ Error: mismatched types //~| expected struct `Example2` - let e: Example3::<13, u32> = (); + let e: Example3<13, u32> = (); //~^ Error: mismatched types //~| expected struct `Example3` - let e: Example3::<7> = (); + let e: Example3<7> = (); //~^ Error: mismatched types - //~| expected struct `Example3<7_usize>` - let e: Example4::<7> = (); + //~| expected struct `Example3<7>` + let e: Example4<7> = (); //~^ Error: mismatched types - //~| expected struct `Example4<7_usize>` + //~| expected struct `Example4<7>` } diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr index 369768191951b..52c54aace5f16 100644 --- a/src/test/ui/const-generics/defaults/mismatch.stderr +++ b/src/test/ui/const-generics/defaults/mismatch.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/mismatch.rs:7:28 + --> $DIR/mismatch.rs:7:26 | -LL | let e: Example::<13> = (); - | ------------- ^^ expected struct `Example`, found `()` +LL | let e: Example<13> = (); + | ----------- ^^ expected struct `Example`, found `()` | | | expected due to this | @@ -10,10 +10,10 @@ LL | let e: Example::<13> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:10:34 + --> $DIR/mismatch.rs:10:32 | -LL | let e: Example2:: = (); - | ------------------- ^^ expected struct `Example2`, found `()` +LL | let e: Example2 = (); + | ----------------- ^^ expected struct `Example2`, found `()` | | | expected due to this | @@ -21,10 +21,10 @@ LL | let e: Example2:: = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:13:34 + --> $DIR/mismatch.rs:13:32 | -LL | let e: Example3::<13, u32> = (); - | ------------------- ^^ expected struct `Example3`, found `()` +LL | let e: Example3<13, u32> = (); + | ----------------- ^^ expected struct `Example3`, found `()` | | | expected due to this | @@ -32,25 +32,25 @@ LL | let e: Example3::<13, u32> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:16:28 + --> $DIR/mismatch.rs:16:26 | -LL | let e: Example3::<7> = (); - | ------------- ^^ expected struct `Example3`, found `()` +LL | let e: Example3<7> = (); + | ----------- ^^ expected struct `Example3`, found `()` | | | expected due to this | - = note: expected struct `Example3<7_usize>` + = note: expected struct `Example3<7>` found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:19:28 + --> $DIR/mismatch.rs:19:26 | -LL | let e: Example4::<7> = (); - | ------------- ^^ expected struct `Example4`, found `()` +LL | let e: Example4<7> = (); + | ----------- ^^ expected struct `Example4`, found `()` | | | expected due to this | - = note: expected struct `Example4<7_usize>` + = note: expected struct `Example4<7>` found unit type `()` error: aborting due to 5 previous errors diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs index f633e56b0ec1d..80013e7b4b230 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -4,16 +4,15 @@ trait Trait {} impl Trait for Uwu {} fn rawr() -> impl Trait { - //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied + //~^ error: the trait bound `Uwu<10, 12>: Trait` is not satisfied Uwu::<10, 12> } -trait Traitor { } +trait Traitor {} impl Traitor for u32 {} impl Traitor<1, 2> for u64 {} - fn uwu() -> impl Traitor { //~^ error: the trait bound `u32: Traitor` is not satisfied 1_u32 diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index cbc7b93f3a925..f2e7777ce6814 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -1,16 +1,16 @@ -error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied +error[E0277]: the trait bound `Uwu<10, 12>: Trait` is not satisfied --> $DIR/rp_impl_trait_fail.rs:6:14 | LL | fn rawr() -> impl Trait { - | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` + | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10, 12>` LL | LL | Uwu::<10, 12> - | ------------- return type was inferred to be `Uwu<10_u32, 12_u32>` here + | ------------- return type was inferred to be `Uwu<10, 12>` here | = help: the trait `Trait` is implemented for `Uwu` error[E0277]: the trait bound `u32: Traitor` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:17:26 + --> $DIR/rp_impl_trait_fail.rs:16:26 | LL | fn uwu() -> impl Traitor { | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` @@ -19,11 +19,11 @@ LL | 1_u32 | ----- return type was inferred to be `u32` here | = help: the following other types implement trait `Traitor`: - > - > + > + > error[E0277]: the trait bound `u64: Traitor` is not satisfied - --> $DIR/rp_impl_trait_fail.rs:22:13 + --> $DIR/rp_impl_trait_fail.rs:21:13 | LL | fn owo() -> impl Traitor { | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64` @@ -32,8 +32,8 @@ LL | 1_u64 | ----- return type was inferred to be `u64` here | = help: the following other types implement trait `Traitor`: - > - > + > + > error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.rs b/src/test/ui/const-generics/defaults/trait_objects_fail.rs index 5e779d2e8de59..6ab803f990920 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.rs +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.rs @@ -16,7 +16,7 @@ trait Traitor { } } -impl Traitor<2, 3> for bool { } +impl Traitor<2, 3> for bool {} fn bar(arg: &dyn Traitor) -> u8 { arg.owo() @@ -26,5 +26,5 @@ fn main() { foo(&10_u32); //~^ error: the trait bound `u32: Trait` is not satisfied bar(&true); - //~^ error: the trait bound `bool: Traitor<{_: u8}>` is not satisfied + //~^ error: the trait bound `bool: Traitor<_>` is not satisfied } diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr index da85b2059f0a3..a9c185e5fcbd1 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr @@ -6,19 +6,19 @@ LL | foo(&10_u32); | | | required by a bound introduced by this call | - = help: the trait `Trait<2_u8>` is implemented for `u32` + = help: the trait `Trait<2>` is implemented for `u32` = note: required for the cast from `u32` to the object type `dyn Trait` -error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied +error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied --> $DIR/trait_objects_fail.rs:28:9 | LL | bar(&true); - | --- ^^^^^ the trait `Traitor<{_: u8}>` is not implemented for `bool` + | --- ^^^^^ the trait `Traitor<_>` is not implemented for `bool` | | | required by a bound introduced by this call | - = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` - = note: required for the cast from `bool` to the object type `dyn Traitor<{_: u8}>` + = help: the trait `Traitor<2, 3>` is implemented for `bool` + = note: required for the cast from `bool` to the object type `dyn Traitor<_>` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/wfness.rs b/src/test/ui/const-generics/defaults/wfness.rs index d366040ba3ea6..a93f670815a03 100644 --- a/src/test/ui/const-generics/defaults/wfness.rs +++ b/src/test/ui/const-generics/defaults/wfness.rs @@ -3,16 +3,20 @@ struct Ooopsies; trait Trait {} impl Trait<3> for () {} -struct WhereClause where (): Trait; -//~^ error: the trait bound `(): Trait<2_u8>` is not satisfied +struct WhereClause +where + (): Trait; +//~^ error: the trait bound `(): Trait<2>` is not satisfied trait Traitor {} -struct WhereClauseTooGeneric(T) where (): Traitor; +struct WhereClauseTooGeneric(T) +where + (): Traitor; // no error on struct def struct DependentDefaultWfness>(T); fn foo() -> DependentDefaultWfness { - //~^ error: the trait bound `(): Trait<1_u8>` is not satisfied + //~^ error: the trait bound `(): Trait<1>` is not satisfied loop {} } diff --git a/src/test/ui/const-generics/defaults/wfness.stderr b/src/test/ui/const-generics/defaults/wfness.stderr index 8b405d6753e56..25038f830befc 100644 --- a/src/test/ui/const-generics/defaults/wfness.stderr +++ b/src/test/ui/const-generics/defaults/wfness.stderr @@ -4,26 +4,29 @@ error[E0080]: evaluation of constant value failed LL | struct Ooopsies; | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -error[E0277]: the trait bound `(): Trait<2_u8>` is not satisfied - --> $DIR/wfness.rs:6:47 +error[E0277]: the trait bound `(): Trait<2>` is not satisfied + --> $DIR/wfness.rs:8:9 | -LL | struct WhereClause where (): Trait; - | ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` +LL | (): Trait; + | ^^^^^^^^ the trait `Trait<2>` is not implemented for `()` | - = help: the trait `Trait<3_u8>` is implemented for `()` + = help: the trait `Trait<3>` is implemented for `()` -error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied - --> $DIR/wfness.rs:14:13 +error[E0277]: the trait bound `(): Trait<1>` is not satisfied + --> $DIR/wfness.rs:18:13 | LL | fn foo() -> DependentDefaultWfness { - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()` | - = help: the trait `Trait<3_u8>` is implemented for `()` + = help: the trait `Trait<3>` is implemented for `()` note: required by a bound in `WhereClause` - --> $DIR/wfness.rs:6:47 + --> $DIR/wfness.rs:8:9 | -LL | struct WhereClause where (): Trait; - | ^^^^^^^^ required by this bound in `WhereClause` +LL | struct WhereClause + | ----------- required by a bound in this +LL | where +LL | (): Trait; + | ^^^^^^^^ required by this bound in `WhereClause` error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/different_generic_args.full.stderr b/src/test/ui/const-generics/different_generic_args.full.stderr index a2dcc033627c6..eba1768f7dda3 100644 --- a/src/test/ui/const-generics/different_generic_args.full.stderr +++ b/src/test/ui/const-generics/different_generic_args.full.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/different_generic_args.rs:11:9 | LL | u = ConstUsize::<4> {}; - | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` | - = note: expected struct `ConstUsize<3_usize>` - found struct `ConstUsize<4_usize>` + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/different_generic_args.min.stderr b/src/test/ui/const-generics/different_generic_args.min.stderr index a2dcc033627c6..eba1768f7dda3 100644 --- a/src/test/ui/const-generics/different_generic_args.min.stderr +++ b/src/test/ui/const-generics/different_generic_args.min.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/different_generic_args.rs:11:9 | LL | u = ConstUsize::<4> {}; - | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize` + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` | - = note: expected struct `ConstUsize<3_usize>` - found struct `ConstUsize<4_usize>` + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/different_generic_args_array.stderr b/src/test/ui/const-generics/different_generic_args_array.stderr index f0b9035357d82..4c5b5ada4f132 100644 --- a/src/test/ui/const-generics/different_generic_args_array.stderr +++ b/src/test/ui/const-generics/different_generic_args_array.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/different_generic_args_array.rs:9:9 | LL | x = Const::<{ [4] }> {}; - | ^^^^^^^^^^^^^^^^^^^ expected `[3_usize]`, found `[4_usize]` + | ^^^^^^^^^^^^^^^^^^^ expected `[3]`, found `[4]` | - = note: expected struct `Const<[3_usize]>` - found struct `Const<[4_usize]>` + = note: expected struct `Const<[3]>` + found struct `Const<[4]>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index 9c1b086f4da9a..76a83ba67ce79 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr @@ -5,14 +5,14 @@ LL | <() as Foo>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | = help: the following other types implement trait `Foo`: - <() as Foo<0_u8>> - <() as Foo<100_u8>> - <() as Foo<101_u8>> - <() as Foo<102_u8>> - <() as Foo<103_u8>> - <() as Foo<104_u8>> - <() as Foo<105_u8>> - <() as Foo<106_u8>> + <() as Foo<0>> + <() as Foo<100>> + <() as Foo<101>> + <() as Foo<102>> + <() as Foo<103>> + <() as Foo<104>> + <() as Foo<105>> + <() as Foo<106>> and 248 others error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr b/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr index 7581cf4120ecf..52d1b29f93222 100644 --- a/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -14,7 +14,7 @@ LL | fn ty_fn() -> Bar { | ---------^- | | | | | not allowed in type signatures - | help: replace with the correct return type: `Bar` + | help: replace with the correct return type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/in-signature.rs:17:25 @@ -24,7 +24,7 @@ LL | fn ty_fn_mixed() -> Bar<_, _> { | | | | | | | not allowed in type signatures | | not allowed in type signatures - | help: replace with the correct return type: `Bar` + | help: replace with the correct return type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:22:15 @@ -45,7 +45,7 @@ LL | const TY_CT: Bar = Bar::(0); | ^^^^^^^^^^^ | | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:28:19 @@ -54,7 +54,7 @@ LL | static TY_STATIC: Bar = Bar::(0); | ^^^^^^^^^^^ | | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:30:20 @@ -63,7 +63,7 @@ LL | const TY_CT_MIXED: Bar<_, _> = Bar::(0); | ^^^^^^^^^ | | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/in-signature.rs:32:25 @@ -72,7 +72,7 @@ LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); | ^^^^^^^^^ | | | not allowed in type signatures - | help: replace with the correct type: `Bar` + | help: replace with the correct type: `Bar` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/in-signature.rs:35:21 diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr index f235eb443b829..ababb27a869d6 100644 --- a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -56,19 +56,19 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:23:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | - = note: expected type `12_u128` - found type `13_u128` + = note: expected type `12` + found type `13` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:25:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | - = note: expected type `13_u128` - found type `14_u128` + = note: expected type `13` + found type `14` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:35:5 @@ -128,19 +128,19 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:41:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | - = note: expected type `12_u128` - found type `13_u128` + = note: expected type `12` + found type `13` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:43:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | - = note: expected type `13_u128` - found type `14_u128` + = note: expected type `13` + found type `14` error: aborting due to 12 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs index 90953145944fe..b8f9827ec9187 100644 --- a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs +++ b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs @@ -2,7 +2,7 @@ #![allow(incomplete_features)] fn test() -> [u8; N - 1] { - //~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed todo!() } diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr index 31ccf97969472..bd71b49ee238b 100644 --- a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed +error[E0080]: evaluation of `test::<0>::{constant#0}` failed --> $DIR/from-sig-fail.rs:4:35 | LL | fn test() -> [u8; N - 1] { diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr index 77a3b77ad428b..7a083733a2cd1 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -4,14 +4,14 @@ error[E0423]: expected value, found type parameter `T` LL | impl Bar for [u8; T] {} | ^ not a value -error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied +error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied --> $DIR/issue-69654.rs:17:10 | LL | struct Foo {} | -------------------------- function or associated item `foo` not found for this struct ... LL | Foo::foo(); - | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds + | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `[u8; _]: Bar<[(); _]>` diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index 41afaec86b6e4..4d0d0253f1b6d 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -34,21 +34,21 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, = help: const parameters may only be used as standalone arguments, i.e. `J` = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual: True` +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual: True, | ^^^^ | - = note: cannot satisfy `IsLessOrEqual: True` + = note: cannot satisfy `IsLessOrEqual: True` -error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual: True` +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual: True, | ^^^^ | - = note: cannot satisfy `IsLessOrEqual: True` + = note: cannot satisfy `IsLessOrEqual: True` error: aborting due to 6 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs index c47a350c7fb43..cae54df4c1210 100644 --- a/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs +++ b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs @@ -2,10 +2,13 @@ #![allow(incomplete_features)] type Arr = [u8; N - 1]; -//~^ ERROR evaluation of `Arr::<0_usize>::{constant#0}` failed +//~^ ERROR evaluation of `Arr::<0>::{constant#0}` failed -fn test() -> Arr where [u8; N - 1]: Sized { -//~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed +fn test() -> Arr +where + [u8; N - 1]: Sized, + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed +{ todo!() } diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr index 99fc92fb4f0ad..a25fa56b7d498 100644 --- a/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr @@ -1,10 +1,10 @@ -error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed - --> $DIR/simple_fail.rs:7:48 +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:9:10 | -LL | fn test() -> Arr where [u8; N - 1]: Sized { - | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow +LL | [u8; N - 1]: Sized, + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error[E0080]: evaluation of `Arr::<0_usize>::{constant#0}` failed +error[E0080]: evaluation of `Arr::<0>::{constant#0}` failed --> $DIR/simple_fail.rs:4:33 | LL | type Arr = [u8; N - 1]; diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.stderr index 98ea8df825265..cf70c21813950 100644 --- a/src/test/ui/const-generics/infer/one-param-uninferred.stderr +++ b/src/test/ui/const-generics/infer/one-param-uninferred.stderr @@ -6,8 +6,8 @@ LL | let _: [u8; 17] = foo(); | help: consider specifying the generic arguments | -LL | let _: [u8; 17] = foo::<17_usize, M>(); - | +++++++++++++++ +LL | let _: [u8; 17] = foo::<17, M>(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issue-66451.stderr b/src/test/ui/const-generics/issue-66451.stderr index b691eac4f2d0e..e0cb0b661ff65 100644 --- a/src/test/ui/const-generics/issue-66451.stderr +++ b/src/test/ui/const-generics/issue-66451.stderr @@ -8,12 +8,12 @@ LL | | value: 3, LL | | nested: &Bar(5), LL | | } LL | | }> = x; - | | - ^ expected `Foo { value: 3_i32, nested: &Bar::(5_i32) }`, found `Foo { value: 3_i32, nested: &Bar::(4_i32) }` + | | - ^ expected `Foo { value: 3, nested: &Bar::(5) }`, found `Foo { value: 3, nested: &Bar::(4) }` | |______| | expected due to this | - = note: expected struct `Test(5_i32) }>` - found struct `Test(4_i32) }>` + = note: expected struct `Test(5) }>` + found struct `Test(4) }>` error: aborting due to previous error diff --git a/src/test/ui/const-generics/nested-type.full.stderr b/src/test/ui/const-generics/nested-type.full.stderr index 52f1c58825823..6d9f4406504ee 100644 --- a/src/test/ui/const-generics/nested-type.full.stderr +++ b/src/test/ui/const-generics/nested-type.full.stderr @@ -1,4 +1,4 @@ -error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants +error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants --> $DIR/nested-type.rs:15:5 | LL | Foo::<17>::value() diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr index 48e12e903b86a..a3c011d927b5a 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -1,10 +1,10 @@ -error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied +error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied --> $DIR/unused-substs-1.rs:12:13 | LL | let _ = A; - | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` + | ^ the trait `Bar<_>` is not implemented for `A<_>` | - = help: the trait `Bar` is implemented for `A<7_usize>` + = help: the trait `Bar` is implemented for `A<7>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 | diff --git a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr index 4d6b752867f1b..486506239ddfd 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:14:41 | LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` | - = note: expected type `2_u32` - found type `4_u32` + = note: expected type `2` + found type `4` error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:16:41 @@ -26,8 +26,8 @@ LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data | | | expected due to this | - = note: expected struct `A<'a, u16, 4_u32, _>` - found struct `A<'b, u32, 2_u32, _>` + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr index 8b60238cb0c03..6ac93a08d5d68 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.min.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.min.stderr @@ -2,12 +2,12 @@ error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:14:41 | LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; - | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32` + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` | | | expected due to this | - = note: expected struct `A<'_, _, 2_u32, _>` - found struct `A<'_, _, 4_u32, _>` + = note: expected struct `A<'_, _, 2, _>` + found struct `A<'_, _, 4, _>` error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:16:41 @@ -28,8 +28,8 @@ LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data | | | expected due to this | - = note: expected struct `A<'a, u16, 4_u32, _>` - found struct `A<'b, u32, 2_u32, _>` + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/issue-85155.stderr b/src/test/ui/consts/const-eval/issue-85155.stderr index c36d7c1721526..3d2c76b7ed040 100644 --- a/src/test/ui/consts/const-eval/issue-85155.stderr +++ b/src/test/ui/consts/const-eval/issue-85155.stderr @@ -1,10 +1,10 @@ -error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2_i32, 0_i32, 1_i32>::VALID` failed +error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2, 0, 1>::VALID` failed --> $DIR/auxiliary/post_monomorphization_error.rs:7:17 | LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero -note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2_i32>` +note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2>` --> $DIR/issue-85155.rs:19:5 | LL | post_monomorphization_error::stdarch_intrinsic::<2>(); diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index ebd484b880001..cb48221c67a82 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -104,7 +104,7 @@ error[E0366]: `Drop` impls cannot be specialized LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `3_usize` is not a generic parameter + = note: `3` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition --> $DIR/reject-specialized-drops-8142.rs:17:1 | diff --git a/src/test/ui/inline-const/const-expr-generic-err.stderr b/src/test/ui/inline-const/const-expr-generic-err.stderr index db0d85a2d4e74..fc0b6cc445164 100644 --- a/src/test/ui/inline-const/const-expr-generic-err.stderr +++ b/src/test/ui/inline-const/const-expr-generic-err.stderr @@ -12,13 +12,13 @@ note: the above error was encountered while instantiating `fn foo::` LL | foo::(); | ^^^^^^^^^^^^ -error[E0080]: evaluation of `bar::<0_usize>::{constant#0}` failed +error[E0080]: evaluation of `bar::<0>::{constant#0}` failed --> $DIR/const-expr-generic-err.rs:9:13 | LL | const { N - 1 } | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -note: the above error was encountered while instantiating `fn bar::<0_usize>` +note: the above error was encountered while instantiating `fn bar::<0>` --> $DIR/const-expr-generic-err.rs:14:5 | LL | bar::<0>(); diff --git a/src/test/ui/lint/function-item-references.stderr b/src/test/ui/lint/function-item-references.stderr index 33db687df31d2..a9d18bb6a4743 100644 --- a/src/test/ui/lint/function-item-references.stderr +++ b/src/test/ui/lint/function-item-references.stderr @@ -116,7 +116,7 @@ warning: taking a reference to a function item does not give a function pointer --> $DIR/function-item-references.rs:118:22 | LL | println!("{:p}", &take_generic_array::); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array:: as fn(_)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array:: as fn(_)` warning: taking a reference to a function item does not give a function pointer --> $DIR/function-item-references.rs:120:22 @@ -128,7 +128,7 @@ warning: taking a reference to a function item does not give a function pointer --> $DIR/function-item-references.rs:122:22 | LL | println!("{:p}", &multiple_generic_arrays::); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays:: as fn(_, _)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays:: as fn(_, _)` warning: taking a reference to a function item does not give a function pointer --> $DIR/function-item-references.rs:124:22 diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.rs b/src/test/ui/methods/method-not-found-generic-arg-elision.rs index 3df928b5d804d..799ced5e9c460 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.rs +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.rs @@ -61,13 +61,13 @@ impl Other { fn other(&self) {} } -struct Struct{ - _phatom: PhantomData +struct Struct { + _phatom: PhantomData, } impl Default for Struct { fn default() -> Self { - Self{ _phatom: PhantomData } + Self { _phatom: PhantomData } } } @@ -76,9 +76,9 @@ impl Struct { } fn main() { - let point_f64 = Point{ x: 1_f64, y: 1_f64}; + let point_f64 = Point { x: 1_f64, y: 1_f64 }; let d = point_f64.distance(); - let point_i32 = Point{ x: 1_i32, y: 1_i32}; + let point_i32 = Point { x: 1_i32, y: 1_i32 }; let d = point_i32.distance(); //~^ ERROR no method named `distance` found for struct `Point let d = point_i32.other(); @@ -92,9 +92,9 @@ fn main() { wrapper.other(); //~^ ERROR no method named `other` found for struct `Wrapper let boolean = true; - let wrapper = Wrapper2::<'_, _, 3> {x: &boolean}; + let wrapper = Wrapper2::<'_, _, 3> { x: &boolean }; wrapper.method(); - //~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3_usize> + //~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3> wrapper.other(); //~^ ERROR no method named `other` found for struct `Wrapper2 let a = vec![1, 2, 3]; diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index 56e1b5a0f4473..fc42d1a4dcd08 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -50,14 +50,14 @@ LL | struct Wrapper(T); LL | wrapper.other(); | ^^^^^ method not found in `Wrapper` -error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3_usize>` in the current scope +error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3>` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:96:13 | LL | struct Wrapper2<'a, T, const C: usize> { | -------------------------------------- method `method` not found for this struct ... LL | wrapper.method(); - | ^^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` + | ^^^^^^ method not found in `Wrapper2<'_, bool, 3>` | = note: the method was found for - `Wrapper2<'a, i8, C>` @@ -71,7 +71,7 @@ LL | struct Wrapper2<'a, T, const C: usize> { | -------------------------------------- method `other` not found for this struct ... LL | wrapper.other(); - | ^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` + | ^^^^^ method not found in `Wrapper2<'_, bool, 3>` error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:101:7 @@ -82,7 +82,7 @@ LL | a.not_found(); error[E0599]: the method `method` exists for struct `Struct`, but its trait bounds were not satisfied --> $DIR/method-not-found-generic-arg-elision.rs:104:7 | -LL | struct Struct{ +LL | struct Struct { | ---------------- method `method` not found for this struct ... LL | s.method(); diff --git a/src/test/ui/simd/intrinsic/generic-shuffle.stderr b/src/test/ui/simd/intrinsic/generic-shuffle.stderr index 44c57cd7c47bc..81e641612ce00 100644 --- a/src/test/ui/simd/intrinsic/generic-shuffle.stderr +++ b/src/test/ui/simd/intrinsic/generic-shuffle.stderr @@ -1,10 +1,10 @@ -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 --> $DIR/generic-shuffle.rs:24:31 | LL | let _: Simd = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` --> $DIR/generic-shuffle.rs:27:31 | LL | let _: Simd = simd_shuffle(v, v, I); diff --git a/src/test/ui/simd/libm_no_std_cant_float.stderr b/src/test/ui/simd/libm_no_std_cant_float.stderr index dc8638f6ab72d..7249914256cd9 100644 --- a/src/test/ui/simd/libm_no_std_cant_float.stderr +++ b/src/test/ui/simd/libm_no_std_cant_float.stderr @@ -2,37 +2,37 @@ error[E0599]: no method named `ceil` found for struct `Simd` in the current scop --> $DIR/libm_no_std_cant_float.rs:14:17 | LL | let _xc = x.ceil(); - | ^^^^ method not found in `Simd` + | ^^^^ method not found in `Simd` error[E0599]: no method named `floor` found for struct `Simd` in the current scope --> $DIR/libm_no_std_cant_float.rs:15:17 | LL | let _xf = x.floor(); - | ^^^^^ method not found in `Simd` + | ^^^^^ method not found in `Simd` error[E0599]: no method named `round` found for struct `Simd` in the current scope --> $DIR/libm_no_std_cant_float.rs:16:17 | LL | let _xr = x.round(); - | ^^^^^ method not found in `Simd` + | ^^^^^ method not found in `Simd` error[E0599]: no method named `trunc` found for struct `Simd` in the current scope --> $DIR/libm_no_std_cant_float.rs:17:17 | LL | let _xt = x.trunc(); - | ^^^^^ method not found in `Simd` + | ^^^^^ method not found in `Simd` error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope --> $DIR/libm_no_std_cant_float.rs:18:19 | LL | let _xfma = x.mul_add(x, x); - | ^^^^^^^ method not found in `Simd` + | ^^^^^^^ method not found in `Simd` error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope --> $DIR/libm_no_std_cant_float.rs:19:20 | LL | let _xsqrt = x.sqrt(); - | ^^^^ method not found in `Simd` + | ^^^^ method not found in `Simd` error: aborting due to 6 previous errors diff --git a/src/test/ui/simd/type-generic-monomorphisation-empty.rs b/src/test/ui/simd/type-generic-monomorphisation-empty.rs index 0121404c74935..2bf6641e9c91c 100644 --- a/src/test/ui/simd/type-generic-monomorphisation-empty.rs +++ b/src/test/ui/simd/type-generic-monomorphisation-empty.rs @@ -2,7 +2,7 @@ #![feature(repr_simd, platform_intrinsics)] -// error-pattern:monomorphising SIMD type `Simd<0_usize>` of zero length +// error-pattern:monomorphising SIMD type `Simd<0>` of zero length #[repr(simd)] struct Simd([f32; N]); diff --git a/src/test/ui/simd/type-generic-monomorphisation-empty.stderr b/src/test/ui/simd/type-generic-monomorphisation-empty.stderr index 00fde199b12a2..b334b1f4b5893 100644 --- a/src/test/ui/simd/type-generic-monomorphisation-empty.stderr +++ b/src/test/ui/simd/type-generic-monomorphisation-empty.stderr @@ -1,4 +1,4 @@ -error: monomorphising SIMD type `Simd<0_usize>` of zero length +error: monomorphising SIMD type `Simd<0>` of zero length error: aborting due to previous error diff --git a/src/test/ui/simd/type-generic-monomorphisation-oversized.rs b/src/test/ui/simd/type-generic-monomorphisation-oversized.rs index bd0d457b35e27..a7dc482f3cb1d 100644 --- a/src/test/ui/simd/type-generic-monomorphisation-oversized.rs +++ b/src/test/ui/simd/type-generic-monomorphisation-oversized.rs @@ -2,7 +2,7 @@ #![feature(repr_simd, platform_intrinsics)] -// error-pattern:monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768 +// error-pattern:monomorphising SIMD type `Simd<65536>` of length greater than 32768 #[repr(simd)] struct Simd([f32; N]); diff --git a/src/test/ui/simd/type-generic-monomorphisation-oversized.stderr b/src/test/ui/simd/type-generic-monomorphisation-oversized.stderr index f441835011532..a2dba1222eecd 100644 --- a/src/test/ui/simd/type-generic-monomorphisation-oversized.stderr +++ b/src/test/ui/simd/type-generic-monomorphisation-oversized.stderr @@ -1,4 +1,4 @@ -error: monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768 +error: monomorphising SIMD type `Simd<65536>` of length greater than 32768 error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 6c82d31e18d8b..e7565525ad338 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -25,7 +25,7 @@ error: non-defining opaque type use in defining scope LL | 7u32 | ^^^^ | -note: used non-generic constant `123_usize` for generic parameter +note: used non-generic constant `123` for generic parameter --> $DIR/generic_nondefining_use.rs:11:15 | LL | type OneConst = impl Debug; From c6454a8d654aed1ab08aaf8a5038c40819e9a48a Mon Sep 17 00:00:00 2001 From: Artur Sinila Date: Tue, 19 Jul 2022 02:54:13 +0300 Subject: [PATCH 06/16] tests: fix `rustc-pass-by-value-self` --- .../ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs | 4 ++-- .../internal-lints/rustc_pass_by_value_self.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs index 2868517774d46..6ce67dcaf1d9b 100644 --- a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs +++ b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs @@ -44,11 +44,11 @@ struct WithParameters { } impl WithParameters { - fn with_ref(&self) {} //~ ERROR passing `WithParameters` by reference + fn with_ref(&self) {} //~ ERROR passing `WithParameters` by reference } impl WithParameters { - fn with_ref(&self) {} //~ ERROR passing `WithParameters` by reference + fn with_ref(&self) {} //~ ERROR passing `WithParameters` by reference } fn main() {} diff --git a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr index 54a7cf7cab757..9cc97c0d16500 100644 --- a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr +++ b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr @@ -26,13 +26,13 @@ error: passing `WithParameters` by reference --> $DIR/rustc_pass_by_value_self.rs:47:17 | LL | fn with_ref(&self) {} - | ^^^^^ help: try passing by value: `WithParameters` + | ^^^^^ help: try passing by value: `WithParameters` error: passing `WithParameters` by reference --> $DIR/rustc_pass_by_value_self.rs:51:17 | LL | fn with_ref(&self) {} - | ^^^^^ help: try passing by value: `WithParameters` + | ^^^^^ help: try passing by value: `WithParameters` error: aborting due to 5 previous errors From c44fa6e94cbcf5ed570c5ae6a46e5e6f517d5b25 Mon Sep 17 00:00:00 2001 From: Artur Sinila Date: Tue, 19 Jul 2022 03:19:24 +0300 Subject: [PATCH 07/16] tests: fix `rustc-pass-by-value-self` --- .../internal-lints/rustc_pass_by_value_self.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr index 9cc97c0d16500..fb39ed60b8235 100644 --- a/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr +++ b/src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr @@ -22,13 +22,13 @@ error: passing `Foo` by reference LL | fn with_ref(&self) {} | ^^^^^ help: try passing by value: `Foo` -error: passing `WithParameters` by reference +error: passing `WithParameters` by reference --> $DIR/rustc_pass_by_value_self.rs:47:17 | LL | fn with_ref(&self) {} | ^^^^^ help: try passing by value: `WithParameters` -error: passing `WithParameters` by reference +error: passing `WithParameters` by reference --> $DIR/rustc_pass_by_value_self.rs:51:17 | LL | fn with_ref(&self) {} From 8530407e311dae1f6b735ed09727cc592b29f522 Mon Sep 17 00:00:00 2001 From: Artur Sinila Date: Tue, 19 Jul 2022 03:46:32 +0300 Subject: [PATCH 08/16] tests: fix `rustdoc` tests --- src/test/rustdoc/const-generics/add-impl.rs | 2 +- src/test/rustdoc/const-generics/const-generic-defaults.rs | 2 +- src/test/rustdoc/const-generics/const-generics-docs.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs index e54f9a57ae4ee..591139523456e 100644 --- a/src/test/rustdoc/const-generics/add-impl.rs +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -7,7 +7,7 @@ pub struct Simd { inner: T, } -// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add> for Simd' +// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add> for Simd' impl Add for Simd { type Output = Self; diff --git a/src/test/rustdoc/const-generics/const-generic-defaults.rs b/src/test/rustdoc/const-generics/const-generic-defaults.rs index 8035f826775ef..2693d9b596993 100644 --- a/src/test/rustdoc/const-generics/const-generic-defaults.rs +++ b/src/test/rustdoc/const-generics/const-generic-defaults.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \ -// 'pub struct Foo(_);' +// 'pub struct Foo(_);' pub struct Foo(T); diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 61af7de4794a6..352a8e646bb49 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -19,8 +19,8 @@ pub use extern_crate::WTrait; // @has foo/trait.Trait.html '//pre[@class="rust trait"]' \ // 'pub trait Trait' -// @has - '//*[@id="impl-Trait%3C1_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1_usize> for u8' -// @has - '//*[@id="impl-Trait%3C2_usize%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2_usize> for u8' +// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1> for u8' +// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2> for u8' // @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8' // @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \ // 'impl Trait for [u8; N]' From 3d9dd681f520d1d59f38aed0056cf9474894cc74 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 20 Jul 2022 23:42:24 +0000 Subject: [PATCH 09/16] Resolve vars in same_type_modulo_infer --- .../src/infer/error_reporting/mod.rs | 146 ++++++++++-------- .../src/traits/error_reporting/mod.rs | 3 +- 2 files changed, 79 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d7505717bf3d2..6c57e7f4347f2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -316,37 +316,6 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( err } -/// Structurally compares two types, modulo any inference variables. -/// -/// Returns `true` if two types are equal, or if one type is an inference variable compatible -/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or -/// FloatVar inference type are compatible with themselves or their concrete types (Int and -/// Float types, respectively). When comparing two ADTs, these rules apply recursively. -pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.kind(), &b.kind()) { - (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { - if did_a != did_b { - return false; - } - - substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type_modulo_infer(a, b)) - } - (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_))) - | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_))) - | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_))) - | ( - &ty::Infer(ty::InferTy::FloatVar(_)), - &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)), - ) - | (&ty::Infer(ty::InferTy::TyVar(_)), _) - | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, - (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => { - mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b) - } - _ => a == b, - } -} - impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_region_errors( &self, @@ -1723,15 +1692,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code()); if let Some(exp_found) = exp_found { - let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } = - cause.code() - { - // Skip if the root_ty of the pattern is not the same as the expected_ty. - // If these types aren't equal then we've probably peeled off a layer of arrays. - same_type_modulo_infer(self.resolve_vars_if_possible(*root_ty), exp_found.expected) - } else { - true - }; + let should_suggest_fixes = + if let ObligationCauseCode::Pattern { root_ty, .. } = cause.code() { + // Skip if the root_ty of the pattern is not the same as the expected_ty. + // If these types aren't equal then we've probably peeled off a layer of arrays. + self.same_type_modulo_infer(*root_ty, exp_found.expected) + } else { + true + }; if should_suggest_fixes { self.suggest_tuple_pattern(cause, &exp_found, diag); @@ -1786,7 +1754,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .filter_map(|variant| { let sole_field = &variant.fields[0]; let sole_field_ty = sole_field.ty(self.tcx, substs); - if same_type_modulo_infer(sole_field_ty, exp_found.found) { + if self.same_type_modulo_infer(sole_field_ty, exp_found.found) { let variant_path = with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); // FIXME #56861: DRYer prelude filtering @@ -1902,39 +1870,41 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder), self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder), ) { - (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { - ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { - diag.multipart_suggestion( - "consider `await`ing on both `Future`s", - vec![ - (then.shrink_to_hi(), ".await".to_string()), - (exp_span.shrink_to_hi(), ".await".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - prior_arms, - .. - }) => { - if let [.., arm_span] = &prior_arms[..] { + (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => { + match cause.code() { + ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diag.multipart_suggestion( "consider `await`ing on both `Future`s", vec![ - (arm_span.shrink_to_hi(), ".await".to_string()), + (then.shrink_to_hi(), ".await".to_string()), (exp_span.shrink_to_hi(), ".await".to_string()), ], Applicability::MaybeIncorrect, ); - } else { + } + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + prior_arms, + .. + }) => { + if let [.., arm_span] = &prior_arms[..] { + diag.multipart_suggestion( + "consider `await`ing on both `Future`s", + vec![ + (arm_span.shrink_to_hi(), ".await".to_string()), + (exp_span.shrink_to_hi(), ".await".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } else { + diag.help("consider `await`ing on both `Future`s"); + } + } + _ => { diag.help("consider `await`ing on both `Future`s"); } } - _ => { - diag.help("consider `await`ing on both `Future`s"); - } - }, - (_, Some(ty)) if same_type_modulo_infer(exp_found.expected, ty) => { + } + (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { diag.span_suggestion_verbose( exp_span.shrink_to_hi(), "consider `await`ing on the `Future`", @@ -1942,7 +1912,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code() { + (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() + { ObligationCauseCode::Pattern { span: Some(span), .. } | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { diag.span_suggestion_verbose( @@ -1992,7 +1963,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .iter() .filter(|field| field.vis.is_accessible_from(field.did, self.tcx)) .map(|field| (field.name, field.ty(self.tcx, expected_substs))) - .find(|(_, ty)| same_type_modulo_infer(*ty, exp_found.found)) + .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found)) { if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { @@ -2057,7 +2028,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | (_, ty::Infer(_)) | (ty::Param(_), _) | (ty::Infer(_), _) => {} - _ if same_type_modulo_infer(exp_ty, found_ty) => {} + _ if self.same_type_modulo_infer(exp_ty, found_ty) => {} _ => show_suggestion = false, }; } @@ -2179,7 +2150,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) { let [expected_tup_elem] = expected_fields[..] else { return }; - if !same_type_modulo_infer(expected_tup_elem, found) { + if !self.same_type_modulo_infer(expected_tup_elem, found) { return; } @@ -2647,6 +2618,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span.is_desugaring(DesugaringKind::QuestionMark) && self.tcx.is_diagnostic_item(sym::From, trait_def_id) } + + /// Structurally compares two types, modulo any inference variables. + /// + /// Returns `true` if two types are equal, or if one type is an inference variable compatible + /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or + /// FloatVar inference type are compatible with themselves or their concrete types (Int and + /// Float types, respectively). When comparing two ADTs, these rules apply recursively. + pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + let (a, b) = self.resolve_vars_if_possible((a, b)); + match (&a.kind(), &b.kind()) { + (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { + if did_a != did_b { + return false; + } + + substs_a + .types() + .zip(substs_b.types()) + .all(|(a, b)| self.same_type_modulo_infer(a, b)) + } + (&ty::Int(_) | &ty::Uint(_), &ty::Infer(ty::InferTy::IntVar(_))) + | ( + &ty::Infer(ty::InferTy::IntVar(_)), + &ty::Int(_) | &ty::Uint(_) | &ty::Infer(ty::InferTy::IntVar(_)), + ) + | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_))) + | ( + &ty::Infer(ty::InferTy::FloatVar(_)), + &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)), + ) + | (&ty::Infer(ty::InferTy::TyVar(_)), _) + | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, + (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => { + mut_a == mut_b && self.same_type_modulo_infer(*ty_a, *ty_b) + } + // FIXME(compiler-errors): This needs to be generalized more + _ => a == b, + } + } } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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 29df771b95780..1fbc904eb48e8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -22,7 +22,6 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::GenericParam; use rustc_hir::Item; use rustc_hir::Node; -use rustc_infer::infer::error_reporting::same_type_modulo_infer; use rustc_infer::traits::TraitEngine; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; @@ -640,7 +639,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if expected.len() == 1 { "" } else { "s" }, ) ); - } else if !same_type_modulo_infer(given_ty, expected_ty) { + } else if !self.same_type_modulo_infer(given_ty, expected_ty) { // Print type mismatch let (expected_args, given_args) = self.cmp(given_ty, expected_ty); From 99c32570bbe20645fa953b0618cec9970c9750fd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 00:03:02 +0000 Subject: [PATCH 10/16] Do if-expression obligation stuff less eagerly --- compiler/rustc_hir/src/hir.rs | 10 + .../src/infer/error_reporting/mod.rs | 335 ++++++++++++++++-- compiler/rustc_middle/src/traits/mod.rs | 16 +- .../src/traits/structural_impls.rs | 1 - compiler/rustc_typeck/src/check/_match.rs | 124 +++---- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 84 +---- .../src/check/fn_ctxt/suggestions.rs | 116 +----- ...block-control-flow-static-semantics.stderr | 18 +- src/test/ui/suggestions/return-bindings.fixed | 23 -- src/test/ui/suggestions/return-bindings.rs | 10 +- .../ui/suggestions/return-bindings.stderr | 24 +- 11 files changed, 411 insertions(+), 350 deletions(-) delete mode 100644 src/test/ui/suggestions/return-bindings.fixed diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 48a41c8bd245a..d6e183dd5a3bb 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -954,6 +954,16 @@ pub struct Block<'hir> { pub targeted_by_break: bool, } +impl<'hir> Block<'hir> { + pub fn peel_blocks(&self) -> &Block<'hir> { + let mut block = self; + while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr { + block = inner_block; + } + block + } +} + #[derive(Debug, HashStable_Generic)] pub struct Pat<'hir> { #[stable_hasher(ignore)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6c57e7f4347f2..a8fc306b28677 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -721,25 +721,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }, ObligationCauseCode::IfExpression(box IfExpressionCause { - then, - else_sp, - outer, - semicolon, + then_id, + else_id, + then_ty, + else_ty, + outer_span, opt_suggest_box_span, }) => { - err.span_label(then, "expected because of this"); - if let Some(sp) = outer { + let then_span = self.find_block_span_from_hir_id(then_id); + let else_span = self.find_block_span_from_hir_id(then_id); + err.span_label(then_span, "expected because of this"); + if let Some(sp) = outer_span { err.span_label(sp, "`if` and `else` have incompatible types"); } + let semicolon = if let hir::Node::Block(blk) = self.tcx.hir().get(then_id) + && let Some(remove_semicolon) = self.could_remove_semicolon(blk, else_ty) + { + Some(remove_semicolon) + } else if let hir::Node::Block(blk) = self.tcx.hir().get(else_id) + && let Some(remove_semicolon) = self.could_remove_semicolon(blk, then_ty) + { + Some(remove_semicolon) + } else { + None + }; if let Some((sp, boxed)) = semicolon { if matches!(boxed, StatementAsExpression::NeedsBoxing) { err.multipart_suggestion( "consider removing this semicolon and boxing the expression", vec![ - (then.shrink_to_lo(), "Box::new(".to_string()), - (then.shrink_to_hi(), ")".to_string()), - (else_sp.shrink_to_lo(), "Box::new(".to_string()), - (else_sp.shrink_to_hi(), ")".to_string()), + (then_span.shrink_to_lo(), "Box::new(".to_string()), + (then_span.shrink_to_hi(), ")".to_string()), + (else_span.shrink_to_lo(), "Box::new(".to_string()), + (else_span.shrink_to_hi(), ")".to_string()), (sp, String::new()), ], Applicability::MachineApplicable, @@ -752,12 +766,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } + } else { + let suggested = if let hir::Node::Block(blk) = self.tcx.hir().get(then_id) { + self.consider_returning_binding(blk, else_ty, err) + } else { + false + }; + if !suggested && let hir::Node::Block(blk) = self.tcx.hir().get(else_id) { + self.consider_returning_binding(blk, then_ty, err); + } } if let Some(ret_sp) = opt_suggest_box_span { self.suggest_boxing_for_return_impl_trait( err, ret_sp, - [then, else_sp].into_iter(), + [then_span, else_span].into_iter(), ); } } @@ -1870,40 +1893,41 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.get_impl_future_output_ty(exp_found.expected).map(Binder::skip_binder), self.get_impl_future_output_ty(exp_found.found).map(Binder::skip_binder), ) { - (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => { - match cause.code() { - ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { + (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause + .code() + { + ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { + let then_span = self.find_block_span_from_hir_id(*then_id); + diag.multipart_suggestion( + "consider `await`ing on both `Future`s", + vec![ + (then_span.shrink_to_hi(), ".await".to_string()), + (exp_span.shrink_to_hi(), ".await".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } + ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { + prior_arms, + .. + }) => { + if let [.., arm_span] = &prior_arms[..] { diag.multipart_suggestion( "consider `await`ing on both `Future`s", vec![ - (then.shrink_to_hi(), ".await".to_string()), + (arm_span.shrink_to_hi(), ".await".to_string()), (exp_span.shrink_to_hi(), ".await".to_string()), ], Applicability::MaybeIncorrect, ); - } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - prior_arms, - .. - }) => { - if let [.., arm_span] = &prior_arms[..] { - diag.multipart_suggestion( - "consider `await`ing on both `Future`s", - vec![ - (arm_span.shrink_to_hi(), ".await".to_string()), - (exp_span.shrink_to_hi(), ".await".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } else { - diag.help("consider `await`ing on both `Future`s"); - } - } - _ => { + } else { diag.help("consider `await`ing on both `Future`s"); } } - } + _ => { + diag.help("consider `await`ing on both `Future`s"); + } + }, (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { diag.span_suggestion_verbose( exp_span.shrink_to_hi(), @@ -1914,10 +1938,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() { - ObligationCauseCode::Pattern { span: Some(span), .. } - | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { + ObligationCauseCode::Pattern { span: Some(then_span), .. } => { + diag.span_suggestion_verbose( + then_span.shrink_to_hi(), + "consider `await`ing on the `Future`", + ".await", + Applicability::MaybeIncorrect, + ); + } + ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { + let then_span = self.find_block_span_from_hir_id(*then_id); diag.span_suggestion_verbose( - span.shrink_to_hi(), + then_span.shrink_to_hi(), "consider `await`ing on the `Future`", ".await", Applicability::MaybeIncorrect, @@ -2808,3 +2840,230 @@ impl TyCategory { } } } + +impl<'tcx> InferCtxt<'_, 'tcx> { + pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { + let block = block.peel_blocks(); + if let Some(expr) = &block.expr { + expr.span + } else if let Some(stmt) = block.stmts.last() { + // possibly incorrect trailing `;` in the else arm + stmt.span + } else { + // empty block; point at its entirety + block.span + } + } + + pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { + match self.tcx.hir().get(hir_id) { + hir::Node::Block(blk) => self.find_block_span(blk), + // The parser was in a weird state if either of these happen... + hir::Node::Expr(e) => e.span, + _ => rustc_span::DUMMY_SP, + } + } + + pub fn could_remove_semicolon( + &self, + blk: &'tcx hir::Block<'tcx>, + expected_ty: Ty<'tcx>, + ) -> Option<(Span, StatementAsExpression)> { + let blk = blk.peel_blocks(); + // Do not suggest if we have a tail expr. + if blk.expr.is_some() { + return None; + } + // Be helpful when the user wrote `{... expr;}` and + // taking the `;` off is enough to fix the error. + let last_stmt = blk.stmts.last()?; + let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { + return None; + }; + let last_expr_ty = self.in_progress_typeck_results?.borrow().expr_ty_opt(*last_expr)?; + let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { + _ if last_expr_ty.references_error() => return None, + _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => { + StatementAsExpression::CorrectType + } + (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _)) + if last_def_id == exp_def_id => + { + StatementAsExpression::CorrectType + } + (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => { + debug!( + "both opaque, likely future {:?} {:?} {:?} {:?}", + last_def_id, last_bounds, exp_def_id, exp_bounds + ); + + let last_local_id = last_def_id.as_local()?; + let exp_local_id = exp_def_id.as_local()?; + + match ( + &self.tcx.hir().expect_item(last_local_id).kind, + &self.tcx.hir().expect_item(exp_local_id).kind, + ) { + ( + hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), + hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }), + ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| { + match (left, right) { + ( + hir::GenericBound::Trait(tl, ml), + hir::GenericBound::Trait(tr, mr), + ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id() + && ml == mr => + { + true + } + ( + hir::GenericBound::LangItemTrait(langl, _, _, argsl), + hir::GenericBound::LangItemTrait(langr, _, _, argsr), + ) if langl == langr => { + // FIXME: consider the bounds! + debug!("{:?} {:?}", argsl, argsr); + true + } + _ => false, + } + }) => + { + StatementAsExpression::NeedsBoxing + } + _ => StatementAsExpression::CorrectType, + } + } + _ => return None, + }; + let span = if last_stmt.span.from_expansion() { + let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span); + self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)? + } else { + last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1)) + }; + Some((span, needs_box)) + } + + pub fn consider_returning_binding( + &self, + blk: &'tcx hir::Block<'tcx>, + expected_ty: Ty<'tcx>, + err: &mut Diagnostic, + ) -> bool { + let blk = blk.peel_blocks(); + // Do not suggest if we have a tail expr. + if blk.expr.is_some() { + return false; + } + let mut shadowed = FxHashSet::default(); + let mut candidate_idents = vec![]; + let mut find_compatible_candidates = |pat: &hir::Pat<'_>| { + if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind + && let Some(pat_ty) = self + .in_progress_typeck_results + .and_then(|typeck_results| typeck_results.borrow().node_type_opt(*hir_id)) + { + let pat_ty = self.resolve_vars_if_possible(pat_ty); + if self.same_type_modulo_infer(pat_ty, expected_ty) + && !(pat_ty, expected_ty).references_error() + && shadowed.insert(ident.name) + { + candidate_idents.push((*ident, pat_ty)); + } + } + true + }; + + let hir = self.tcx.hir(); + for stmt in blk.stmts.iter().rev() { + let hir::StmtKind::Local(local) = &stmt.kind else { continue; }; + local.pat.walk(&mut find_compatible_candidates); + } + match hir.find(hir.get_parent_node(blk.hir_id)) { + Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => { + match hir.find(hir.get_parent_node(*hir_id)) { + Some(hir::Node::Arm(hir::Arm { pat, .. })) => { + pat.walk(&mut find_compatible_candidates); + } + Some( + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(_, body), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(hir::Closure { body, .. }), + .. + }), + ) => { + for param in hir.body(*body).params { + param.pat.walk(&mut find_compatible_candidates); + } + } + Some(hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::If( + hir::Expr { kind: hir::ExprKind::Let(let_), .. }, + then_block, + _, + ), + .. + })) if then_block.hir_id == *hir_id => { + let_.pat.walk(&mut find_compatible_candidates); + } + _ => {} + } + } + _ => {} + } + + match &candidate_idents[..] { + [(ident, _ty)] => { + let sm = self.tcx.sess.source_map(); + if let Some(stmt) = blk.stmts.last() { + let stmt_span = sm.stmt_span(stmt.span, blk.span); + let sugg = if sm.is_multiline(blk.span) + && let Some(spacing) = sm.indentation_before(stmt_span) + { + format!("\n{spacing}{ident}") + } else { + format!(" {ident}") + }; + err.span_suggestion_verbose( + stmt_span.shrink_to_hi(), + format!("consider returning the local binding `{ident}`"), + sugg, + Applicability::MaybeIncorrect, + ); + } else { + let sugg = if sm.is_multiline(blk.span) + && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo()) + { + format!("\n{spacing} {ident}\n{spacing}") + } else { + format!(" {ident} ") + }; + let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi(); + err.span_suggestion_verbose( + sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span), + format!("consider returning the local binding `{ident}`"), + sugg, + Applicability::MaybeIncorrect, + ); + } + true + } + values if (1..3).contains(&values.len()) => { + let spans = values.iter().map(|(ident, _)| ident.span).collect::>(); + err.span_note(spans, "consider returning one of these bindings"); + true + } + _ => false, + } + } +} diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 75559d4f8b843..7a38c800ccf5f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -351,7 +351,7 @@ pub enum ObligationCauseCode<'tcx> { ConstPatternStructural, /// Computing common supertype in an if expression - IfExpression(Box), + IfExpression(Box>), /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, @@ -498,12 +498,14 @@ pub struct MatchExpressionArmCause<'tcx> { pub opt_suggest_box_span: Option, } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct IfExpressionCause { - pub then: Span, - pub else_sp: Span, - pub outer: Option, - pub semicolon: Option<(Span, StatementAsExpression)>, +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Lift, TypeFoldable, TypeVisitable)] +pub struct IfExpressionCause<'tcx> { + pub then_id: hir::HirId, + pub else_id: hir::HirId, + pub then_ty: Ty<'tcx>, + pub else_ty: Ty<'tcx>, + pub outer_span: Option, pub opt_suggest_box_span: Option, } diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 8f1a1564fc8e8..7fbd57ac7354a 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -130,7 +130,6 @@ impl fmt::Debug for traits::ImplSourceConstDestructData { // Lift implementations TrivialTypeTraversalAndLiftImpls! { - super::IfExpressionCause, super::ImplSourceDiscriminantKindData, super::ImplSourcePointeeData, } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index c733f0d3c86d0..00547a6d8278f 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -216,13 +216,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Span, Option<(Span, StatementAsExpression)>) { let arm = &arms[i]; let (arm_span, mut semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind { - self.find_block_span(blk, prior_arm_ty) + ( + self.find_block_span(blk), + prior_arm_ty + .and_then(|prior_arm_ty| self.could_remove_semicolon(blk, prior_arm_ty)), + ) } else { (arm.body.span, None) }; if semi_span.is_none() && i > 0 { if let hir::ExprKind::Block(blk, _) = &arms[i - 1].body.kind { - let (_, semi_span_prev) = self.find_block_span(blk, Some(arm_ty)); + let semi_span_prev = self.could_remove_semicolon(blk, arm_ty); semi_span = semi_span_prev; } } @@ -313,7 +317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { else_ty: Ty<'tcx>, opt_suggest_box_span: Option, ) -> ObligationCause<'tcx> { - let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) { + let mut outer_span = if self.tcx.sess.source_map().is_multiline(span) { // The `if`/`else` isn't in one line in the output, include some context to make it // clear it is an if/else expression: // ``` @@ -339,69 +343,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; - let mut remove_semicolon = None; - let error_sp = if let ExprKind::Block(block, _) = &else_expr.kind { - let (error_sp, semi_sp) = self.find_block_span(block, Some(then_ty)); - remove_semicolon = semi_sp; - if block.expr.is_none() && block.stmts.is_empty() { - // Avoid overlapping spans that aren't as readable: - // ``` - // 2 | let x = if true { - // | _____________- - // 3 | | 3 - // | | - expected because of this - // 4 | | } else { - // | |____________^ - // 5 | || - // 6 | || }; - // | || ^ - // | ||_____| - // | |______if and else have incompatible types - // | expected integer, found `()` - // ``` - // by not pointing at the entire expression: - // ``` - // 2 | let x = if true { - // | ------- `if` and `else` have incompatible types - // 3 | 3 - // | - expected because of this - // 4 | } else { - // | ____________^ - // 5 | | - // 6 | | }; - // | |_____^ expected integer, found `()` - // ``` - if outer_sp.is_some() { - outer_sp = Some(self.tcx.sess.source_map().guess_head_span(span)); - } + let (error_sp, else_id) = if let ExprKind::Block(block, _) = &else_expr.kind { + let block = block.peel_blocks(); + + // Avoid overlapping spans that aren't as readable: + // ``` + // 2 | let x = if true { + // | _____________- + // 3 | | 3 + // | | - expected because of this + // 4 | | } else { + // | |____________^ + // 5 | || + // 6 | || }; + // | || ^ + // | ||_____| + // | |______if and else have incompatible types + // | expected integer, found `()` + // ``` + // by not pointing at the entire expression: + // ``` + // 2 | let x = if true { + // | ------- `if` and `else` have incompatible types + // 3 | 3 + // | - expected because of this + // 4 | } else { + // | ____________^ + // 5 | | + // 6 | | }; + // | |_____^ expected integer, found `()` + // ``` + if block.expr.is_none() && block.stmts.is_empty() + && let Some(outer_span) = &mut outer_span + { + *outer_span = self.tcx.sess.source_map().guess_head_span(*outer_span); } - error_sp + + (self.find_block_span(block), block.hir_id) } else { - // shouldn't happen unless the parser has done something weird - else_expr.span + (else_expr.span, else_expr.hir_id) }; - // Compute `Span` of `then` part of `if`-expression. - let then_sp = if let ExprKind::Block(block, _) = &then_expr.kind { - let (then_sp, semi_sp) = self.find_block_span(block, Some(else_ty)); - remove_semicolon = remove_semicolon.or(semi_sp); + let then_id = if let ExprKind::Block(block, _) = &then_expr.kind { + let block = block.peel_blocks(); + // Exclude overlapping spans if block.expr.is_none() && block.stmts.is_empty() { - outer_sp = None; // same as in `error_sp`; cleanup output + outer_span = None; } - then_sp + block.hir_id } else { - // shouldn't happen unless the parser has done something weird - then_expr.span + then_expr.hir_id }; // Finally construct the cause: self.cause( error_sp, ObligationCauseCode::IfExpression(Box::new(IfExpressionCause { - then: then_sp, - else_sp: error_sp, - outer: outer_sp, - semicolon: remove_semicolon, + else_id, + then_id, + then_ty, + else_ty, + outer_span, opt_suggest_box_span, })), ) @@ -482,22 +484,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn find_block_span( - &self, - block: &'tcx hir::Block<'tcx>, - expected_ty: Option>, - ) -> (Span, Option<(Span, StatementAsExpression)>) { - if let Some(expr) = &block.expr { - (expr.span, None) - } else if let Some(stmt) = block.stmts.last() { - // possibly incorrect trailing `;` in the else arm - (stmt.span, expected_ty.and_then(|ty| self.could_remove_semicolon(block, ty))) - } else { - // empty block; point at its entirety - (block.span, None) - } - } - // When we have a `match` as a tail expression in a `fn` with a returned `impl Trait` // we check if the different arms would work with boxed trait objects instead and // provide a structured suggestion in that case. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index d079aeb4801ca..21b3c9063a78a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -30,17 +30,15 @@ use rustc_middle::ty::{ }; use rustc_session::lint; use rustc_span::hygiene::DesugaringKind; -use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{self, BytePos, Span}; +use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, + self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt, }; use std::collections::hash_map::Entry; -use std::iter; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -1059,84 +1057,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } - pub(in super::super) fn could_remove_semicolon( - &self, - blk: &'tcx hir::Block<'tcx>, - expected_ty: Ty<'tcx>, - ) -> Option<(Span, StatementAsExpression)> { - // Be helpful when the user wrote `{... expr;}` and - // taking the `;` off is enough to fix the error. - let last_stmt = blk.stmts.last()?; - let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { - return None; - }; - let last_expr_ty = self.node_ty(last_expr.hir_id); - let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { - (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _)) - if last_def_id == exp_def_id => - { - StatementAsExpression::CorrectType - } - (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => { - debug!( - "both opaque, likely future {:?} {:?} {:?} {:?}", - last_def_id, last_bounds, exp_def_id, exp_bounds - ); - - let last_local_id = last_def_id.as_local()?; - let exp_local_id = exp_def_id.as_local()?; - - match ( - &self.tcx.hir().expect_item(last_local_id).kind, - &self.tcx.hir().expect_item(exp_local_id).kind, - ) { - ( - hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), - hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }), - ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| { - match (left, right) { - ( - hir::GenericBound::Trait(tl, ml), - hir::GenericBound::Trait(tr, mr), - ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id() - && ml == mr => - { - true - } - ( - hir::GenericBound::LangItemTrait(langl, _, _, argsl), - hir::GenericBound::LangItemTrait(langr, _, _, argsr), - ) if langl == langr => { - // FIXME: consider the bounds! - debug!("{:?} {:?}", argsl, argsr); - true - } - _ => false, - } - }) => - { - StatementAsExpression::NeedsBoxing - } - _ => StatementAsExpression::CorrectType, - } - } - _ => StatementAsExpression::CorrectType, - }; - if (matches!(last_expr_ty.kind(), ty::Error(_)) - || self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err()) - && matches!(needs_box, StatementAsExpression::CorrectType) - { - return None; - } - let span = if last_stmt.span.from_expansion() { - let mac_call = original_sp(last_stmt.span, blk.span); - self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)? - } else { - last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1)) - }; - Some((span, needs_box)) - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. #[instrument(skip(self, span), level = "debug")] diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 871fc4a21f2a7..3e6ff72204f4c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -3,7 +3,6 @@ use crate::astconv::AstConv; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; use rustc_ast::util::parser::ExprPrecedence; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; @@ -14,7 +13,7 @@ use rustc_hir::{ use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty, TypeVisitable}; +use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; @@ -904,117 +903,4 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } } - - pub(crate) fn consider_returning_binding( - &self, - blk: &'tcx hir::Block<'tcx>, - expected_ty: Ty<'tcx>, - err: &mut Diagnostic, - ) { - let mut shadowed = FxHashSet::default(); - let mut candidate_idents = vec![]; - let mut find_compatible_candidates = |pat: &hir::Pat<'_>| { - if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind - && let Some(pat_ty) = self.typeck_results.borrow().node_type_opt(*hir_id) - { - let pat_ty = self.resolve_vars_if_possible(pat_ty); - if self.can_coerce(pat_ty, expected_ty) - && !(pat_ty, expected_ty).references_error() - && shadowed.insert(ident.name) - { - candidate_idents.push((*ident, pat_ty)); - } - } - true - }; - - let hir = self.tcx.hir(); - for stmt in blk.stmts.iter().rev() { - let StmtKind::Local(local) = &stmt.kind else { continue; }; - local.pat.walk(&mut find_compatible_candidates); - } - match hir.find(hir.get_parent_node(blk.hir_id)) { - Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => { - match hir.find(hir.get_parent_node(*hir_id)) { - Some(hir::Node::Arm(hir::Arm { pat, .. })) => { - pat.walk(&mut find_compatible_candidates); - } - Some( - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(_, body), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)), - .. - }) - | hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { body, .. }), - .. - }), - ) => { - for param in hir.body(*body).params { - param.pat.walk(&mut find_compatible_candidates); - } - } - Some(hir::Node::Expr(hir::Expr { - kind: - hir::ExprKind::If( - hir::Expr { kind: hir::ExprKind::Let(let_), .. }, - then_block, - _, - ), - .. - })) if then_block.hir_id == *hir_id => { - let_.pat.walk(&mut find_compatible_candidates); - } - _ => {} - } - } - _ => {} - } - - match &candidate_idents[..] { - [(ident, _ty)] => { - let sm = self.tcx.sess.source_map(); - if let Some(stmt) = blk.stmts.last() { - let stmt_span = sm.stmt_span(stmt.span, blk.span); - let sugg = if sm.is_multiline(blk.span) - && let Some(spacing) = sm.indentation_before(stmt_span) - { - format!("\n{spacing}{ident}") - } else { - format!(" {ident}") - }; - err.span_suggestion_verbose( - stmt_span.shrink_to_hi(), - format!("consider returning the local binding `{ident}`"), - sugg, - Applicability::MachineApplicable, - ); - } else { - let sugg = if sm.is_multiline(blk.span) - && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo()) - { - format!("\n{spacing} {ident}\n{spacing}") - } else { - format!(" {ident} ") - }; - let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi(); - err.span_suggestion_verbose( - sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span), - format!("consider returning the local binding `{ident}`"), - sugg, - Applicability::MachineApplicable, - ); - } - } - values if (1..3).contains(&values.len()) => { - let spans = values.iter().map(|(ident, _)| ident.span).collect::>(); - err.span_note(spans, "consider returning one of these bindings"); - } - _ => {} - } - } } diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index ada6e357aea5e..e5887689690e7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -18,14 +18,6 @@ LL | | break 0u8; LL | | }; | |_________- enclosing `async` block -error[E0271]: type mismatch resolving ` as Future>::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:26:39 - | -LL | let _: &dyn Future = █ - | ^^^^^^ expected `()`, found `u8` - | - = note: required for the cast from `impl Future` to the object type `dyn Future` - error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:21:58 | @@ -40,7 +32,7 @@ LL | | } | |_^ expected `u8`, found `()` error[E0271]: type mismatch resolving ` as Future>::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:17:39 + --> $DIR/async-block-control-flow-static-semantics.rs:26:39 | LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` @@ -55,6 +47,14 @@ LL | fn return_targets_async_block_not_fn() -> u8 { | | | implicitly returns `()` as its body has no tail or `return` expression +error[E0271]: type mismatch resolving ` as Future>::Output == ()` + --> $DIR/async-block-control-flow-static-semantics.rs:17:39 + | +LL | let _: &dyn Future = █ + | ^^^^^^ expected `()`, found `u8` + | + = note: required for the cast from `impl Future` to the object type `dyn Future` + error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:47:44 | diff --git a/src/test/ui/suggestions/return-bindings.fixed b/src/test/ui/suggestions/return-bindings.fixed deleted file mode 100644 index 4fabc411abcbe..0000000000000 --- a/src/test/ui/suggestions/return-bindings.fixed +++ /dev/null @@ -1,23 +0,0 @@ -// run-rustfix - -#![allow(unused)] - -fn a(i: i32) -> i32 { i } -//~^ ERROR mismatched types - -fn b(opt_str: Option) { - let s: String = if let Some(s) = opt_str { - s - //~^ ERROR mismatched types - } else { - String::new() - }; -} - -fn c() -> Option { - //~^ ERROR mismatched types - let x = Some(1); - x -} - -fn main() {} diff --git a/src/test/ui/suggestions/return-bindings.rs b/src/test/ui/suggestions/return-bindings.rs index d05b4ba27d6e8..80c83a70d50c1 100644 --- a/src/test/ui/suggestions/return-bindings.rs +++ b/src/test/ui/suggestions/return-bindings.rs @@ -1,5 +1,3 @@ -// run-rustfix - #![allow(unused)] fn a(i: i32) -> i32 {} @@ -18,4 +16,12 @@ fn c() -> Option { let x = Some(1); } +fn d(opt_str: Option) { + let s: String = if let Some(s) = opt_str { + //~^ ERROR mismatched types + } else { + String::new() + }; +} + fn main() {} diff --git a/src/test/ui/suggestions/return-bindings.stderr b/src/test/ui/suggestions/return-bindings.stderr index e5d4925500556..53ef7106fa808 100644 --- a/src/test/ui/suggestions/return-bindings.stderr +++ b/src/test/ui/suggestions/return-bindings.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/return-bindings.rs:5:17 + --> $DIR/return-bindings.rs:3:17 | LL | fn a(i: i32) -> i32 {} | - ^^^ expected `i32`, found `()` @@ -12,7 +12,7 @@ LL | fn a(i: i32) -> i32 { i } | + error[E0308]: mismatched types - --> $DIR/return-bindings.rs:9:46 + --> $DIR/return-bindings.rs:7:46 | LL | let s: String = if let Some(s) = opt_str { | ______________________________________________^ @@ -28,7 +28,7 @@ LL ~ | error[E0308]: mismatched types - --> $DIR/return-bindings.rs:16:11 + --> $DIR/return-bindings.rs:14:11 | LL | fn c() -> Option { | - ^^^^^^^^^^^ expected enum `Option`, found `()` @@ -43,6 +43,22 @@ LL ~ let x = Some(1); LL + x | -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:20:46 + | +LL | let s: String = if let Some(s) = opt_str { + | ______________________________________________^ +LL | | +LL | | } else { + | |_____^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL ~ let s: String = if let Some(s) = opt_str { +LL + s +LL ~ + | + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. From 8926dac54911e9382763876dc3a8e7a4ae50e270 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 01:26:00 +0000 Subject: [PATCH 11/16] And for patterns too --- .../src/infer/error_reporting/mod.rs | 167 ++++++++++-------- compiler/rustc_middle/src/traits/mod.rs | 7 +- compiler/rustc_typeck/src/check/_match.rs | 57 ++---- src/test/ui/suggestions/return-bindings.rs | 24 +++ .../ui/suggestions/return-bindings.stderr | 48 ++++- 5 files changed, 184 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a8fc306b28677..5c1ab2bf5888d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -614,13 +614,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_label(span, "expected due to this"); } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - semi_span, + arm_block_id, + arm_span, + arm_ty, + prior_arm_block_id, + prior_arm_span, + prior_arm_ty, source, ref prior_arms, - last_ty, scrut_hir_id, opt_suggest_box_span, - arm_span, scrut_span, .. }) => match source { @@ -651,10 +654,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } _ => { - // `last_ty` can be `!`, `expected` will have better info when present. + // `prior_arm_ty` can be `!`, `expected` will have better info when present. let t = self.resolve_vars_if_possible(match exp_found { Some(ty::error::ExpectedFound { expected, .. }) => expected, - _ => last_ty, + _ => prior_arm_ty, }); let source_map = self.tcx.sess.source_map(); let mut any_multiline_arm = source_map.is_multiline(arm_span); @@ -679,37 +682,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let msg = "`match` arms have incompatible types"; err.span_label(outer_error_span, msg); - if let Some((sp, boxed)) = semi_span { - if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) = - (boxed, &prior_arms[..]) - { - err.multipart_suggestion( - "consider removing this semicolon and boxing the expressions", - vec![ - (prior_arm.shrink_to_lo(), "Box::new(".to_string()), - (prior_arm.shrink_to_hi(), ")".to_string()), - (arm_span.shrink_to_lo(), "Box::new(".to_string()), - (arm_span.shrink_to_hi(), ")".to_string()), - (sp, String::new()), - ], - Applicability::HasPlaceholders, - ); - } else if matches!(boxed, StatementAsExpression::NeedsBoxing) { - err.span_suggestion_short( - sp, - "consider removing this semicolon and boxing the expressions", - "", - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion_short( - sp, - "consider removing this semicolon", - "", - Applicability::MachineApplicable, - ); - } - } + self.suggest_remove_semi_or_return_binding( + err, + prior_arm_block_id, + prior_arm_ty, + prior_arm_span, + arm_block_id, + arm_ty, + arm_span, + ); if let Some(ret_sp) = opt_suggest_box_span { // Get return type span and point to it. self.suggest_boxing_for_return_impl_trait( @@ -734,48 +715,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(sp) = outer_span { err.span_label(sp, "`if` and `else` have incompatible types"); } - let semicolon = if let hir::Node::Block(blk) = self.tcx.hir().get(then_id) - && let Some(remove_semicolon) = self.could_remove_semicolon(blk, else_ty) - { - Some(remove_semicolon) - } else if let hir::Node::Block(blk) = self.tcx.hir().get(else_id) - && let Some(remove_semicolon) = self.could_remove_semicolon(blk, then_ty) - { - Some(remove_semicolon) - } else { - None - }; - if let Some((sp, boxed)) = semicolon { - if matches!(boxed, StatementAsExpression::NeedsBoxing) { - err.multipart_suggestion( - "consider removing this semicolon and boxing the expression", - vec![ - (then_span.shrink_to_lo(), "Box::new(".to_string()), - (then_span.shrink_to_hi(), ")".to_string()), - (else_span.shrink_to_lo(), "Box::new(".to_string()), - (else_span.shrink_to_hi(), ")".to_string()), - (sp, String::new()), - ], - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion_short( - sp, - "consider removing this semicolon", - "", - Applicability::MachineApplicable, - ); - } - } else { - let suggested = if let hir::Node::Block(blk) = self.tcx.hir().get(then_id) { - self.consider_returning_binding(blk, else_ty, err) - } else { - false - }; - if !suggested && let hir::Node::Block(blk) = self.tcx.hir().get(else_id) { - self.consider_returning_binding(blk, then_ty, err); - } - } + self.suggest_remove_semi_or_return_binding( + err, + Some(then_id), + then_ty, + then_span, + Some(else_id), + else_ty, + else_span, + ); if let Some(ret_sp) = opt_suggest_box_span { self.suggest_boxing_for_return_impl_trait( err, @@ -800,6 +748,69 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + fn suggest_remove_semi_or_return_binding( + &self, + err: &mut Diagnostic, + first_id: Option, + first_ty: Ty<'tcx>, + first_span: Span, + second_id: Option, + second_ty: Ty<'tcx>, + second_span: Span, + ) { + let semicolon = + if let Some(first_id) = first_id + && let hir::Node::Block(blk) = self.tcx.hir().get(first_id) + && let Some(remove_semicolon) = self.could_remove_semicolon(blk, second_ty) + { + Some(remove_semicolon) + } else if let Some(second_id) = second_id + && let hir::Node::Block(blk) = self.tcx.hir().get(second_id) + && let Some(remove_semicolon) = self.could_remove_semicolon(blk, first_ty) + { + Some(remove_semicolon) + } else { + None + }; + if let Some((sp, boxed)) = semicolon { + if matches!(boxed, StatementAsExpression::NeedsBoxing) { + err.multipart_suggestion( + "consider removing this semicolon and boxing the expressions", + vec![ + (first_span.shrink_to_lo(), "Box::new(".to_string()), + (first_span.shrink_to_hi(), ")".to_string()), + (second_span.shrink_to_lo(), "Box::new(".to_string()), + (second_span.shrink_to_hi(), ")".to_string()), + (sp, String::new()), + ], + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_short( + sp, + "consider removing this semicolon", + "", + Applicability::MachineApplicable, + ); + } + } else { + let suggested = + if let Some(first_id) = first_id + && let hir::Node::Block(blk) = self.tcx.hir().get(first_id) + { + self.consider_returning_binding(blk, second_ty, err) + } else { + false + }; + if !suggested + && let Some(second_id) = second_id + && let hir::Node::Block(blk) = self.tcx.hir().get(second_id) + { + self.consider_returning_binding(blk, first_ty, err); + } + } + } + fn suggest_boxing_for_return_impl_trait( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 7a38c800ccf5f..c55971557fac1 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -488,12 +488,15 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression { #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] pub struct MatchExpressionArmCause<'tcx> { + pub arm_block_id: Option, + pub arm_ty: Ty<'tcx>, pub arm_span: Span, + pub prior_arm_block_id: Option, + pub prior_arm_ty: Ty<'tcx>, + pub prior_arm_span: Span, pub scrut_span: Span, - pub semi_span: Option<(Span, StatementAsExpression)>, pub source: hir::MatchSource, pub prior_arms: Vec, - pub last_ty: Ty<'tcx>, pub scrut_hir_id: hir::HirId, pub opt_suggest_box_span: Option, } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 00547a6d8278f..2671f2f4f89ca 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -9,7 +9,6 @@ use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, - StatementAsExpression, }; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -75,8 +74,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut other_arms = vec![]; // Used only for diagnostics. - let mut prior_arm_ty = None; - for (i, arm) in arms.iter().enumerate() { + let mut prior_arm = None; + for arm in arms { if let Some(g) = &arm.guard { self.diverges.set(Diverges::Maybe); match g { @@ -96,21 +95,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected); - let (arm_span, semi_span) = - self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty); - let (span, code) = match i { + let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind { + (Some(blk.hir_id), self.find_block_span(blk)) + } else { + (None, arm.body.span) + }; + + let (span, code) = match prior_arm { // The reason for the first arm to fail is not that the match arms diverge, // but rather that there's a prior obligation that doesn't hold. - 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), - _ => ( + None => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)), + Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => ( expr.span, ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause { + arm_block_id, arm_span, + arm_ty, + prior_arm_block_id, + prior_arm_ty, + prior_arm_span, scrut_span: scrut.span, - semi_span, source: match_src, prior_arms: other_arms.clone(), - last_ty: prior_arm_ty.unwrap(), scrut_hir_id: scrut.hir_id, opt_suggest_box_span, })), @@ -139,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); self.can_coerce(arm_ty, ret_ty) - && prior_arm_ty.map_or(true, |t| self.can_coerce(t, ret_ty)) + && prior_arm.map_or(true, |(_, t, _)| self.can_coerce(t, ret_ty)) // The match arms need to unify for the case of `impl Trait`. && !matches!(ret_ty.kind(), ty::Opaque(..)) } @@ -181,7 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if other_arms.len() > 5 { other_arms.remove(0); } - prior_arm_ty = Some(arm_ty); + + prior_arm = Some((arm_block_id, arm_ty, arm_span)); } // If all of the arms in the `match` diverge, @@ -207,32 +214,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match_ty } - fn get_appropriate_arm_semicolon_removal_span( - &self, - arms: &'tcx [hir::Arm<'tcx>], - i: usize, - prior_arm_ty: Option>, - arm_ty: Ty<'tcx>, - ) -> (Span, Option<(Span, StatementAsExpression)>) { - let arm = &arms[i]; - let (arm_span, mut semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind { - ( - self.find_block_span(blk), - prior_arm_ty - .and_then(|prior_arm_ty| self.could_remove_semicolon(blk, prior_arm_ty)), - ) - } else { - (arm.body.span, None) - }; - if semi_span.is_none() && i > 0 { - if let hir::ExprKind::Block(blk, _) = &arms[i - 1].body.kind { - let semi_span_prev = self.could_remove_semicolon(blk, arm_ty); - semi_span = semi_span_prev; - } - } - (arm_span, semi_span) - } - /// When the previously checked expression (the scrutinee) diverges, /// warn the user about the match arms being unreachable. fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm<'tcx>]) { diff --git a/src/test/ui/suggestions/return-bindings.rs b/src/test/ui/suggestions/return-bindings.rs index 80c83a70d50c1..fa1bad37699f3 100644 --- a/src/test/ui/suggestions/return-bindings.rs +++ b/src/test/ui/suggestions/return-bindings.rs @@ -24,4 +24,28 @@ fn d(opt_str: Option) { }; } +fn d2(opt_str: Option) { + let s = if let Some(s) = opt_str { + } else { + String::new() + //~^ ERROR `if` and `else` have incompatible types + }; +} + +fn e(opt_str: Option) { + let s: String = match opt_str { + Some(s) => {} + //~^ ERROR mismatched types + None => String::new(), + }; +} + +fn e2(opt_str: Option) { + let s = match opt_str { + Some(s) => {} + None => String::new(), + //~^ ERROR `match` arms have incompatible types + }; +} + fn main() {} diff --git a/src/test/ui/suggestions/return-bindings.stderr b/src/test/ui/suggestions/return-bindings.stderr index 53ef7106fa808..c14fb336773d1 100644 --- a/src/test/ui/suggestions/return-bindings.stderr +++ b/src/test/ui/suggestions/return-bindings.stderr @@ -59,6 +59,52 @@ LL + s LL ~ | -error: aborting due to 4 previous errors +error[E0308]: `if` and `else` have incompatible types + --> $DIR/return-bindings.rs:30:9 + | +LL | let s = if let Some(s) = opt_str { + | ______________________________________- +LL | | } else { + | |_____- expected because of this +LL | String::new() + | ^^^^^^^^^^^^^ expected `()`, found struct `String` + | +help: consider returning the local binding `s` + | +LL ~ let s = if let Some(s) = opt_str { +LL + s +LL ~ } else { + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:37:20 + | +LL | Some(s) => {} + | ^^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error[E0308]: `match` arms have incompatible types + --> $DIR/return-bindings.rs:46:17 + | +LL | let s = match opt_str { + | _____________- +LL | | Some(s) => {} + | | -- this is found to be of type `()` +LL | | None => String::new(), + | | ^^^^^^^^^^^^^ expected `()`, found struct `String` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. From cd89978d869587fc025286b0326116819d5b78e4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 15:45:35 +0000 Subject: [PATCH 12/16] Generalize same_type_modulo_infer --- .../src/infer/error_reporting/mod.rs | 37 +++++++++++++++++-- src/test/ui/issues/issue-59494.stderr | 2 - 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 5c1ab2bf5888d..93f94bd497a55 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2670,8 +2670,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Float types, respectively). When comparing two ADTs, these rules apply recursively. pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { let (a, b) = self.resolve_vars_if_possible((a, b)); - match (&a.kind(), &b.kind()) { - (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { + match (a.kind(), b.kind()) { + (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) => { + if def_a != def_b { + return false; + } + + substs_a + .types() + .zip(substs_b.types()) + .all(|(a, b)| self.same_type_modulo_infer(a, b)) + } + (&ty::FnDef(did_a, substs_a), &ty::FnDef(did_b, substs_b)) => { if did_a != did_b { return false; } @@ -2694,7 +2704,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | (&ty::Infer(ty::InferTy::TyVar(_)), _) | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => { - mut_a == mut_b && self.same_type_modulo_infer(*ty_a, *ty_b) + mut_a == mut_b && self.same_type_modulo_infer(ty_a, ty_b) + } + (&ty::RawPtr(a), &ty::RawPtr(b)) => { + a.mutbl == b.mutbl && self.same_type_modulo_infer(a.ty, b.ty) + } + (&ty::Slice(a), &ty::Slice(b)) => self.same_type_modulo_infer(a, b), + (&ty::Array(a_ty, a_ct), &ty::Array(b_ty, b_ct)) => { + self.same_type_modulo_infer(a_ty, b_ty) && a_ct == b_ct + } + (&ty::Tuple(a), &ty::Tuple(b)) => { + if a.len() != b.len() { + return false; + } + std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b)) + } + (&ty::FnPtr(a), &ty::FnPtr(b)) => { + let a = a.skip_binder().inputs_and_output; + let b = b.skip_binder().inputs_and_output; + if a.len() != b.len() { + return false; + } + std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b)) } // FIXME(compiler-errors): This needs to be generalized more _ => a == b, diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr index 8b542bb69de2e..a9284535e4dc4 100644 --- a/src/test/ui/issues/issue-59494.stderr +++ b/src/test/ui/issues/issue-59494.stderr @@ -7,8 +7,6 @@ LL | let t8 = t8n(t7, t7p(f, g)); | required by a bound introduced by this call | = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` - = note: expected a closure with arguments `(((_, _), _),)` - found a closure with arguments `(_,)` note: required by a bound in `t8n` --> $DIR/issue-59494.rs:5:45 | From 947314125370164f52feb221ef2f1aac0e420309 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 21 Jul 2022 11:51:40 -0400 Subject: [PATCH 13/16] Update compiler/rustc_mir_transform/src/simplify.rs --- compiler/rustc_mir_transform/src/simplify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 59c38b87b5cb2..d305960b4856d 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -28,7 +28,7 @@ //! return. use crate::MirPass; -use rustc_data_structures::stable_set::FxHashSet; +use rustc_data_structures::fx::FxHashSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; From eb5acc9b9b520092cc667a810a18498b28d052ab Mon Sep 17 00:00:00 2001 From: Martin Habovstiak Date: Thu, 16 Jun 2022 19:47:24 +0200 Subject: [PATCH 14/16] Rename `<*{mut,const} T>::as_{const,mut}` to `cast_` This renames the methods to use the `cast_` prefix instead of `as_` to make it more readable and avoid confusion with `<*mut T>::as_mut()` which is `unsafe` and returns a reference. See #92675 --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 74aa0d9c7bcb2..55f781ce0222a 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -97,7 +97,7 @@ impl *const T { /// refactored. #[unstable(feature = "ptr_const_cast", issue = "92675")] #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] - pub const fn as_mut(self) -> *mut T { + pub const fn cast_mut(self) -> *mut T { self as _ } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index b988090f4bc4c..27e8b20b3c52d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -96,11 +96,13 @@ impl *mut T { /// refactored. /// /// While not strictly required (`*mut T` coerces to `*const T`), this is provided for symmetry - /// with `as_mut()` on `*const T` and may have documentation value if used instead of implicit + /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit /// coercion. + /// + /// [`cast_mut`]: #method.cast_mut #[unstable(feature = "ptr_const_cast", issue = "92675")] #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] - pub const fn as_const(self) -> *const T { + pub const fn cast_const(self) -> *const T { self as _ } @@ -289,7 +291,7 @@ impl *mut T { /// For the mutable counterpart see [`as_mut`]. /// /// [`as_uninit_ref`]: #method.as_uninit_ref-1 - /// [`as_mut`]: #method.as_mut-1 + /// [`as_mut`]: #method.as_mut /// /// # Safety /// From 3eef023da04cd732ee6656867e2161b7dbfee821 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 16:12:57 +0000 Subject: [PATCH 15/16] Address more nits --- compiler/rustc_hir/src/hir.rs | 2 +- .../src/infer/error_reporting/mod.rs | 68 +++++++++---------- compiler/rustc_typeck/src/check/_match.rs | 4 +- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d6e183dd5a3bb..18ffc227fed86 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -955,7 +955,7 @@ pub struct Block<'hir> { } impl<'hir> Block<'hir> { - pub fn peel_blocks(&self) -> &Block<'hir> { + pub fn innermost_block(&self) -> &Block<'hir> { let mut block = self; while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr { block = inner_block; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 93f94bd497a55..4e87ec86658f8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -758,22 +758,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { second_ty: Ty<'tcx>, second_span: Span, ) { - let semicolon = - if let Some(first_id) = first_id - && let hir::Node::Block(blk) = self.tcx.hir().get(first_id) - && let Some(remove_semicolon) = self.could_remove_semicolon(blk, second_ty) - { - Some(remove_semicolon) - } else if let Some(second_id) = second_id - && let hir::Node::Block(blk) = self.tcx.hir().get(second_id) - && let Some(remove_semicolon) = self.could_remove_semicolon(blk, first_ty) - { - Some(remove_semicolon) - } else { - None - }; - if let Some((sp, boxed)) = semicolon { - if matches!(boxed, StatementAsExpression::NeedsBoxing) { + let remove_semicolon = + [(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| { + let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None }; + self.could_remove_semicolon(blk, ty) + }); + match remove_semicolon { + Some((sp, StatementAsExpression::NeedsBoxing)) => { err.multipart_suggestion( "consider removing this semicolon and boxing the expressions", vec![ @@ -785,7 +776,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ], Applicability::MachineApplicable, ); - } else { + } + Some((sp, StatementAsExpression::CorrectType)) => { err.span_suggestion_short( sp, "consider removing this semicolon", @@ -793,20 +785,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - } else { - let suggested = - if let Some(first_id) = first_id - && let hir::Node::Block(blk) = self.tcx.hir().get(first_id) - { - self.consider_returning_binding(blk, second_ty, err) - } else { - false - }; - if !suggested - && let Some(second_id) = second_id - && let hir::Node::Block(blk) = self.tcx.hir().get(second_id) - { - self.consider_returning_binding(blk, first_ty, err); + None => { + for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] { + if let Some(id) = id + && let hir::Node::Block(blk) = self.tcx.hir().get(id) + && self.consider_returning_binding(blk, ty, err) + { + break; + } + } } } } @@ -2884,8 +2871,10 @@ impl TyCategory { } impl<'tcx> InferCtxt<'_, 'tcx> { + /// Given a [`hir::Block`], get the span of its last expression or + /// statement, peeling off any inner blocks. pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { - let block = block.peel_blocks(); + let block = block.innermost_block(); if let Some(expr) = &block.expr { expr.span } else if let Some(stmt) = block.stmts.last() { @@ -2897,27 +2886,30 @@ impl<'tcx> InferCtxt<'_, 'tcx> { } } + /// Given a [`hir::HirId`] for a block, get the span of its last expression + /// or statement, peeling off any inner blocks. pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { match self.tcx.hir().get(hir_id) { hir::Node::Block(blk) => self.find_block_span(blk), - // The parser was in a weird state if either of these happen... + // The parser was in a weird state if either of these happen, but + // it's better not to panic. hir::Node::Expr(e) => e.span, _ => rustc_span::DUMMY_SP, } } + /// Be helpful when the user wrote `{... expr; }` and taking the `;` off + /// is enough to fix the error. pub fn could_remove_semicolon( &self, blk: &'tcx hir::Block<'tcx>, expected_ty: Ty<'tcx>, ) -> Option<(Span, StatementAsExpression)> { - let blk = blk.peel_blocks(); + let blk = blk.innermost_block(); // Do not suggest if we have a tail expr. if blk.expr.is_some() { return None; } - // Be helpful when the user wrote `{... expr;}` and - // taking the `;` off is enough to fix the error. let last_stmt = blk.stmts.last()?; let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { return None; @@ -2987,13 +2979,15 @@ impl<'tcx> InferCtxt<'_, 'tcx> { Some((span, needs_box)) } + /// Suggest returning a local binding with a compatible type if the block + /// has no return expression. pub fn consider_returning_binding( &self, blk: &'tcx hir::Block<'tcx>, expected_ty: Ty<'tcx>, err: &mut Diagnostic, ) -> bool { - let blk = blk.peel_blocks(); + let blk = blk.innermost_block(); // Do not suggest if we have a tail expr. if blk.expr.is_some() { return false; diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 2671f2f4f89ca..f629f6a0099d7 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let (error_sp, else_id) = if let ExprKind::Block(block, _) = &else_expr.kind { - let block = block.peel_blocks(); + let block = block.innermost_block(); // Avoid overlapping spans that aren't as readable: // ``` @@ -366,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let then_id = if let ExprKind::Block(block, _) = &then_expr.kind { - let block = block.peel_blocks(); + let block = block.innermost_block(); // Exclude overlapping spans if block.expr.is_none() && block.stmts.is_empty() { outer_span = None; From 7ba0be832a0f9c7a22f4b9e2cb76b653d4010b30 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Thu, 21 Jul 2022 18:15:24 -0600 Subject: [PATCH 16/16] add same warning to Result::expect as Result::unwrap --- library/core/src/result.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 8a68cdf7d651b..45b052c824d31 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1009,6 +1009,15 @@ impl Result { /// Returns the contained [`Ok`] value, consuming the `self` value. /// + /// Because this function may panic, its use is generally discouraged. + /// Instead, prefer to use pattern matching and handle the [`Err`] + /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or + /// [`unwrap_or_default`]. + /// + /// [`unwrap_or`]: Result::unwrap_or + /// [`unwrap_or_else`]: Result::unwrap_or_else + /// [`unwrap_or_default`]: Result::unwrap_or_default + /// /// # Panics /// /// Panics if the value is an [`Err`], with a panic message including the