diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index e9e7065ec03cc..1329e3a0b959d 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -10,7 +10,7 @@ use Destination::*; use rustc_span::source_map::SourceMap; -use rustc_span::{SourceFile, Span}; +use rustc_span::{FileLines, SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; @@ -1761,12 +1761,6 @@ impl EmitterWriter { let has_deletion = parts.iter().any(|p| p.is_deletion()); let is_multiline = complete.lines().count() > 1; - enum DisplaySuggestion { - Underline, - Diff, - None, - } - if let Some(span) = span.primary_span() { // Compare the primary span of the diagnostic with the span of the suggestion // being emitted. If they belong to the same file, we don't *need* to show the @@ -1839,79 +1833,94 @@ impl EmitterWriter { } row_num += line_end - line_start; } - for (line_pos, (line, highlight_parts)) in - lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() - { - // Print the span column to avoid confusion - buffer.puts( - row_num, - 0, - &self.maybe_anonymized(line_start + line_pos), - Style::LineNumber, - ); - if let DisplaySuggestion::Diff = show_code_change { - // Add the line number for both addition and removal to drive the point home. - // - // N - fn foo(bar: A) { - // N + fn foo(bar: impl T) { - buffer.puts( - row_num - 1, - 0, - &self.maybe_anonymized(line_start + line_pos), - Style::LineNumber, - ); - buffer.puts(row_num - 1, max_line_num_len + 1, "- ", Style::Removal); - buffer.puts( - row_num - 1, - max_line_num_len + 3, - &normalize_whitespace( - &*file_lines - .file - .get_line(file_lines.lines[line_pos].line_index) - .unwrap(), - ), - Style::NoStyle, - ); - buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); - } else if is_multiline { - match &highlight_parts[..] { - [SubstitutionHighlight { start: 0, end }] if *end == line.len() => { - buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); - } - [] => { - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); - } - _ => { - buffer.puts(row_num, max_line_num_len + 1, "~ ", Style::Addition); - } - } - } else { - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + let mut unhighlighted_lines = Vec::new(); + for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() { + debug!(%line_pos, %line, ?highlight_parts); + + // Remember lines that are not highlighted to hide them if needed + if highlight_parts.is_empty() { + unhighlighted_lines.push((line_pos, line)); + continue; } - // print the suggestion - buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle); + match unhighlighted_lines.len() { + 0 => (), + // Since we show first line, "..." line and last line, + // There is no reason to hide if there are 3 or less lines + // (because then we just replace a line with ... which is + // not helpful) + n if n <= 3 => unhighlighted_lines.drain(..).for_each(|(p, l)| { + self.draw_code_line( + &mut buffer, + &mut row_num, + &Vec::new(), + p, + l, + line_start, + show_code_change, + max_line_num_len, + &file_lines, + is_multiline, + ) + }), + // Print first unhighlighted line, "..." and last unhighlighted line, like so: + // + // LL | this line was highlighted + // LL | this line is just for context + // ... + // LL | this line is just for context + // LL | this line was highlighted + _ => { + let last_line = unhighlighted_lines.pop(); + let first_line = unhighlighted_lines.drain(..).next(); + + first_line.map(|(p, l)| { + self.draw_code_line( + &mut buffer, + &mut row_num, + &Vec::new(), + p, + l, + line_start, + show_code_change, + max_line_num_len, + &file_lines, + is_multiline, + ) + }); - // Colorize addition/replacements with green. - for &SubstitutionHighlight { start, end } in highlight_parts { - // Account for tabs when highlighting (#87972). - let tabs: usize = line - .chars() - .take(start) - .map(|ch| match ch { - '\t' => 3, - _ => 0, - }) - .sum(); - buffer.set_style_range( - row_num, - max_line_num_len + 3 + start + tabs, - max_line_num_len + 3 + end + tabs, - Style::Addition, - true, - ); + buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); + row_num += 1; + + last_line.map(|(p, l)| { + self.draw_code_line( + &mut buffer, + &mut row_num, + &Vec::new(), + p, + l, + line_start, + show_code_change, + max_line_num_len, + &file_lines, + is_multiline, + ) + }); + } } - row_num += 1; + + self.draw_code_line( + &mut buffer, + &mut row_num, + highlight_parts, + line_pos, + line, + line_start, + show_code_change, + max_line_num_len, + &file_lines, + is_multiline, + ) } // This offset and the ones below need to be signed to account for replacement code @@ -2096,6 +2105,90 @@ impl EmitterWriter { } } } + + fn draw_code_line( + &self, + buffer: &mut StyledBuffer, + row_num: &mut usize, + highlight_parts: &Vec, + line_pos: usize, + line: &str, + line_start: usize, + show_code_change: DisplaySuggestion, + max_line_num_len: usize, + file_lines: &FileLines, + is_multiline: bool, + ) { + // Print the span column to avoid confusion + buffer.puts(*row_num, 0, &self.maybe_anonymized(line_start + line_pos), Style::LineNumber); + if let DisplaySuggestion::Diff = show_code_change { + // Add the line number for both addition and removal to drive the point home. + // + // N - fn foo(bar: A) { + // N + fn foo(bar: impl T) { + buffer.puts( + *row_num - 1, + 0, + &self.maybe_anonymized(line_start + line_pos), + Style::LineNumber, + ); + buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal); + buffer.puts( + *row_num - 1, + max_line_num_len + 3, + &normalize_whitespace( + &*file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(), + ), + Style::NoStyle, + ); + buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); + } else if is_multiline { + match &highlight_parts[..] { + [SubstitutionHighlight { start: 0, end }] if *end == line.len() => { + buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); + } + [] => { + draw_col_separator(buffer, *row_num, max_line_num_len + 1); + } + _ => { + buffer.puts(*row_num, max_line_num_len + 1, "~ ", Style::Addition); + } + } + } else { + draw_col_separator(buffer, *row_num, max_line_num_len + 1); + } + + // print the suggestion + buffer.append(*row_num, &normalize_whitespace(line), Style::NoStyle); + + // Colorize addition/replacements with green. + for &SubstitutionHighlight { start, end } in highlight_parts { + // Account for tabs when highlighting (#87972). + let tabs: usize = line + .chars() + .take(start) + .map(|ch| match ch { + '\t' => 3, + _ => 0, + }) + .sum(); + buffer.set_style_range( + *row_num, + max_line_num_len + 3 + start + tabs, + max_line_num_len + 3 + end + tabs, + Style::Addition, + true, + ); + } + *row_num += 1; + } +} + +#[derive(Clone, Copy)] +enum DisplaySuggestion { + Underline, + Diff, + None, } impl FileWithAnnotatedLines { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index aa4ea82dffb61..78b0892b3bc17 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1174,7 +1174,7 @@ impl HandlerInner { !this.emitted_diagnostics.insert(diagnostic_hash) }; - // Only emit the diagnostic if we've been asked to deduplicate and + // Only emit the diagnostic if we've been asked to deduplicate or // haven't already emitted an equivalent diagnostic. if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { debug!(?diagnostic); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c56f70e853daa..acf892cec5328 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2042,9 +2042,9 @@ impl<'a> Parser<'a> { match pat.kind { PatKind::Ident(_, ident, _) => ( ident, - "self: ".to_string(), + "self: ", ": TypeName".to_string(), - "_: ".to_string(), + "_: ", pat.span.shrink_to_lo(), pat.span.shrink_to_hi(), pat.span.shrink_to_lo(), @@ -2058,9 +2058,9 @@ impl<'a> Parser<'a> { let mutab = mutab.prefix_str(); ( ident, - "self: ".to_string(), + "self: ", format!("{ident}: &{mutab}TypeName"), - "_: ".to_string(), + "_: ", pat.span.shrink_to_lo(), pat.span, pat.span.shrink_to_lo(), diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index dc9d76160c4e9..37d12b4ed5da4 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1561,73 +1561,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: We are currently creating two branches here in order to maintain // consistency. But they should be merged as much as possible. let fru_tys = if self.tcx.features().type_changing_struct_update { - if let ty::Adt(adt, substs) = adt_ty.kind() && adt.is_struct() { - // Make an ADT with fresh inference substitutions. This - // will allow us to guide inference along so that, e.g. + if adt.is_struct() { + // Make some fresh substitutions for our ADT type. + let fresh_substs = self.fresh_substs_for_item(base_expr.span, adt.did()); + // We do subtyping on the FRU fields first, so we can + // learn exactly what types we expect the base expr + // needs constrained to be compatible with the struct + // type we expect from the expectation value. + let fru_tys = variant + .fields + .iter() + .map(|f| { + let fru_ty = self.normalize_associated_types_in( + expr_span, + self.field_ty(base_expr.span, f, fresh_substs), + ); + let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id); + if let Some(_) = remaining_fields.remove(&ident) { + let target_ty = self.field_ty(base_expr.span, f, substs); + let cause = self.misc(base_expr.span); + match self.at(&cause, self.param_env).sup(target_ty, fru_ty) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations) + } + Err(_) => { + // This should never happen, since we're just subtyping the + // remaining_fields, but it's fine to emit this, I guess. + self.report_mismatched_types( + &cause, + target_ty, + fru_ty, + FieldMisMatch(variant.name, ident.name), + ) + .emit(); + } + } + } + self.resolve_vars_if_possible(fru_ty) + }) + .collect(); + // The use of fresh substs that we have subtyped against + // our base ADT type's fields allows us to guide inference + // along so that, e.g. // ``` - // let x = MyStruct<'a, B, const C: usize> { - // f: 1, - // ..Default::default() + // MyStruct<'a, F1, F2, const C: usize> { + // f: F1, + // // Other fields that reference `'a`, `F2`, and `C` + // } + // + // let x = MyStruct { + // f: 1usize, + // ..other_struct // }; // ``` - // will have the default base expression constrained to - // `MyStruct<'_, _, _>`, as opposed to just `_`... This - // will allow us to then do a subtyping relation on all - // of the `remaining_fields` below, per the RFC. - let fresh_substs = self.fresh_substs_for_item(base_expr.span, adt.did()); + // will have the `other_struct` expression constrained to + // `MyStruct<'a, _, F2, C>`, as opposed to just `_`... + // This is important to allow coercions to happen in + // `other_struct` itself. See `coerce-in-base-expr.rs`. let fresh_base_ty = self.tcx.mk_adt(*adt, fresh_substs); - let base_ty = self.check_expr_has_type_or_error( + self.check_expr_has_type_or_error( base_expr, - fresh_base_ty, - |_| { - error_happened = true; - }, + self.resolve_vars_if_possible(fresh_base_ty), + |_| {}, ); - let base_ty = self.shallow_resolve(base_ty); - if let ty::Adt(base_adt, base_substs) = base_ty.kind() && adt == base_adt { - variant - .fields - .iter() - .map(|f| { - let fru_ty = self.normalize_associated_types_in( - expr_span, - self.field_ty(base_expr.span, f, base_substs), - ); - let ident = self - .tcx - .adjust_ident(f.ident(self.tcx), variant.def_id); - if let Some(_) = remaining_fields.remove(&ident) { - let target_ty = - self.field_ty(base_expr.span, f, substs); - let cause = self.misc(base_expr.span); - match self - .at(&cause, self.param_env) - .sup(target_ty, fru_ty) - { - Ok(InferOk { obligations, value: () }) => { - self.register_predicates(obligations) - } - // FIXME: Need better diagnostics for `FieldMisMatch` error - Err(_) => { - self.report_mismatched_types( - &cause, - target_ty, - fru_ty, - FieldMisMatch(variant.name, ident.name), - ) - .emit(); - } - } - } - self.resolve_vars_if_possible(fru_ty) - }) - .collect() - } else { - if !error_happened && !base_ty.references_error() { - span_bug!(base_expr.span, "expected an error to have been reported in `check_expr_has_type_or_error`"); - } - return; - } + fru_tys } else { // Check the base_expr, regardless of a bad expected adt_ty, so we can get // type errors on that expression, too. diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 839088eac21ea..3706300dcfeb7 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -978,7 +978,6 @@ impl BinaryHeap { /// # Examples /// /// ``` - /// #![feature(try_reserve_2)] /// use std::collections::BinaryHeap; /// use std::collections::TryReserveError; /// @@ -995,7 +994,7 @@ impl BinaryHeap { /// } /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.data.try_reserve_exact(additional) } @@ -1014,7 +1013,6 @@ impl BinaryHeap { /// # Examples /// /// ``` - /// #![feature(try_reserve_2)] /// use std::collections::BinaryHeap; /// use std::collections::TryReserveError; /// @@ -1031,7 +1029,7 @@ impl BinaryHeap { /// } /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.data.try_reserve(additional) } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 1212ff6f74ac3..95d274c3c91e7 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -300,7 +300,6 @@ impl OsString { /// # Examples /// /// ``` - /// #![feature(try_reserve_2)] /// use std::ffi::{OsStr, OsString}; /// use std::collections::TryReserveError; /// @@ -317,7 +316,7 @@ impl OsString { /// } /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); /// ``` - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] #[inline] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve(additional) @@ -372,7 +371,6 @@ impl OsString { /// # Examples /// /// ``` - /// #![feature(try_reserve_2)] /// use std::ffi::{OsStr, OsString}; /// use std::collections::TryReserveError; /// @@ -389,7 +387,7 @@ impl OsString { /// } /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); /// ``` - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] #[inline] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve_exact(additional) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 36d6469c02d31..6bbc8f55ace35 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1520,7 +1520,7 @@ impl PathBuf { /// Invokes [`try_reserve`] on the underlying instance of [`OsString`]. /// /// [`try_reserve`]: OsString::try_reserve - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] #[inline] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve(additional) @@ -1538,7 +1538,7 @@ impl PathBuf { /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`]. /// /// [`try_reserve_exact`]: OsString::try_reserve_exact - #[unstable(feature = "try_reserve_2", issue = "91789")] + #[stable(feature = "try_reserve_2", since = "1.63.0")] #[inline] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve_exact(additional) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 27776fdf533ee..5469487df1eed 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -276,6 +276,7 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; +pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values @@ -1264,7 +1265,7 @@ compat_fn! { EaBuffer: *mut c_void, EaLength: ULONG ) -> NTSTATUS { - panic!("`NtCreateFile` not available"); + STATUS_NOT_IMPLEMENTED } pub fn NtReadFile( FileHandle: BorrowedHandle<'_>, @@ -1277,7 +1278,7 @@ compat_fn! { ByteOffset: Option<&LARGE_INTEGER>, Key: Option<&ULONG> ) -> NTSTATUS { - panic!("`NtReadFile` not available"); + STATUS_NOT_IMPLEMENTED } pub fn NtWriteFile( FileHandle: BorrowedHandle<'_>, @@ -1290,12 +1291,12 @@ compat_fn! { ByteOffset: Option<&LARGE_INTEGER>, Key: Option<&ULONG> ) -> NTSTATUS { - panic!("`NtWriteFile` not available"); + STATUS_NOT_IMPLEMENTED } pub fn RtlNtStatusToDosError( Status: NTSTATUS ) -> ULONG { - panic!("`RtlNtStatusToDosError` not available"); + Status as ULONG } pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, diff --git a/src/test/ui/associated-consts/issue-93835.stderr b/src/test/ui/associated-consts/issue-93835.stderr index 12df0e4381d15..0406a16a39732 100644 --- a/src/test/ui/associated-consts/issue-93835.stderr +++ b/src/test/ui/associated-consts/issue-93835.stderr @@ -19,11 +19,10 @@ help: you might have meant to write a `struct` literal | LL ~ fn e() { SomeStruct { LL | p:a> -LL | -LL | -LL | -LL | ... +LL | +LL ~ }} + | help: maybe you meant to write a path separator here | LL | p::a> diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index a8367766ae1cf..a3c43690f1f32 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -17,11 +17,10 @@ help: add a dummy let to cause `fptr` to be fully captured | LL ~ thread::spawn(move || { let _ = &fptr; unsafe { LL | -LL | -LL | -LL | -LL | *fptr.0 = 20; ... +LL | +LL ~ } }); + | error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/auto_traits.rs:42:19 @@ -39,12 +38,11 @@ LL | *fptr.0.0 = 20; help: add a dummy let to cause `fptr` to be fully captured | LL ~ thread::spawn(move || { let _ = &fptr; unsafe { -LL | -LL | -LL | -LL | LL | ... +LL | +LL ~ } }); + | error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements --> $DIR/auto_traits.rs:67:13 diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index 483eae6bb4b1f..fa6082cbb59b4 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -108,12 +108,11 @@ LL | *fptr2.0 = 20; help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured | LL ~ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { -LL | -LL | -LL | -LL | LL | ... +LL | +LL ~ } }); + | error: aborting due to 5 previous errors diff --git a/src/test/ui/imports/issue-59764.stderr b/src/test/ui/imports/issue-59764.stderr index c2cfc0939d6b3..8d99d757c17d6 100644 --- a/src/test/ui/imports/issue-59764.stderr +++ b/src/test/ui/imports/issue-59764.stderr @@ -209,8 +209,7 @@ help: a macro with this name exists at the root of the crate | LL ~ issue_59764::{makro as foobar, LL | -LL | foobaz, -LL | + ... LL | LL ~ foo::{baz} | diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index 6bec98121b759..039ffbfd3d89f 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -89,12 +89,11 @@ LL | 5); help: try comparing the cast value | LL ~ println!("{}", (a -LL | -LL | -LL | as -LL | LL | ... +LL | +LL ~ usize) + | error: `<` is interpreted as a start of generic arguments for `usize`, not a shift --> $DIR/issue-22644.rs:32:31 diff --git a/src/test/ui/let-else/let-else-if.stderr b/src/test/ui/let-else/let-else-if.stderr index a0324565673da..746738bbd939b 100644 --- a/src/test/ui/let-else/let-else-if.stderr +++ b/src/test/ui/let-else/let-else-if.stderr @@ -8,8 +8,7 @@ help: try placing this code inside a block | LL ~ let Some(_) = Some(()) else { if true { LL | -LL | return; -LL | } else { + ... LL | return; LL ~ } }; | diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr index 767389c48088a..d95c25fdea8b5 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.stderr +++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr @@ -54,11 +54,10 @@ help: consider enclosing expression in a block | LL ~ let _i = 'label: { match x { LL | 0 => 42, -LL | 1 if false => break 'label 17, -LL | 1 => { -LL | if true { -LL | break 'label 13 ... +LL | _ => 1, +LL ~ } }; + | error: expected `while`, `for`, `loop` or `{` after a label --> $DIR/recover-labeled-non-block-expr.rs:26:24 diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs new file mode 100644 index 0000000000000..75e48bf4a482a --- /dev/null +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +use std::any::Any; + +struct Foo { + a: A, + b: Box, + c: Box, +} + +struct B; +struct C; + +fn main() { + let y = Foo:: { + a: 0, + b: Box::new(B), + ..Foo { + a: 0, + b: Box::new(B), + // C needs to be told to coerce to `Box` + c: Box::new(C), + } + }; +} diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs index d8b1396a692a7..dae1241d35a5f 100644 --- a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -50,7 +50,6 @@ fn fail_update() { let m3 = Machine:: { ..m1 //~^ ERROR mismatched types [E0308] - //~| ERROR mismatched types [E0308] }; } diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr index fa8d6ee23d5ec..6f31b1a962078 100644 --- a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr +++ b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -2,29 +2,20 @@ error[E0308]: mismatched types --> $DIR/type-generic-update.rs:46:11 | LL | ..m1 - | ^^ field type mismatch: Machine.state + | ^^ expected `i32`, found `f64` | - = note: expected type `i32` - found type `f64` + = note: expected struct `Machine<'_, i32, _>` + found struct `Machine<'_, f64, _>` error[E0308]: mismatched types --> $DIR/type-generic-update.rs:51:11 | LL | ..m1 - | ^^ field type mismatch: Machine.state + | ^^ expected `i32`, found `f64` | - = note: expected type `i32` - found type `f64` + = note: expected struct `Machine<'_, i32, i32>` + found struct `Machine<'_, f64, f64>` -error[E0308]: mismatched types - --> $DIR/type-generic-update.rs:51:11 - | -LL | ..m1 - | ^^ field type mismatch: Machine.message - | - = note: expected type `i32` - found type `f64` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr index 43f0fbbc4e387..6819d14bb0106 100644 --- a/src/test/ui/type/ascription/issue-34255-1.stderr +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -8,8 +8,7 @@ help: you might have meant to write a `struct` literal | LL ~ pub fn new() -> Self { SomeStruct { LL | input_cells: Vec::new() -LL | -LL | + ... LL | LL ~ }} | diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 64d14d0fc5fa4..d25452456bb21 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -9,11 +9,10 @@ help: consider introducing a named lifetime parameter | LL ~ fn main<'a>() { LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, -LL | dyn Foo(&isize) -> &isize >(); -LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>, -LL | dyn Foo(&isize) -> (&isize, &isize) >(); -LL | ... +LL | +LL ~ let _: dyn Foo(&'a isize, &'a usize) -> &'a usize; + | error: aborting due to previous error diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 4d21ba8bd1d16..aa119539b1b39 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -771,7 +771,7 @@ impl DiagnosticExt for rustc_errors::Diagnostic { } } - self.span_suggestion(remove_span, msg, String::new(), applicability); + self.span_suggestion(remove_span, msg, "", applicability); } } diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr index f822b6f49fa35..0152a93feee42 100644 --- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr +++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr @@ -56,7 +56,25 @@ LL | if s == "43" { LL ~ return 43; LL | } LL | s == "42" +LL | } { +LL ~ return 45; +LL | } +LL | match s.len() { +LL ~ 10 => 2, +LL | 20 => { ... +LL | if foo() { +LL ~ return 20; +LL | } +LL | println!("foo"); +LL ~ 3 +LL | }; +LL | } +LL ~ 20 +LL | }, +LL ~ 40 => 30, +LL ~ _ => 1, + | error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` --> $DIR/bind_instead_of_map_multipart.rs:61:13 diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr index 11843cc03d8d1..a270f637f2b91 100644 --- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr @@ -98,7 +98,8 @@ LL + id: e_id, LL + name: "Player 1".to_string(), LL + some_data: vec![0x12, 0x34, 0x56, 0x78, 0x90], LL + }; - ... +LL + process_data(pack); + | error: all if blocks contain the same code at both the start and the end --> $DIR/shared_at_top_and_bottom.rs:94:5 diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr index 1076500498d32..2ef9966525cef 100644 --- a/src/tools/clippy/tests/ui/entry.stderr +++ b/src/tools/clippy/tests/ui/entry.stderr @@ -28,7 +28,8 @@ LL + v LL + } else { LL + v2 LL + } - ... +LL + }); + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:38:5 @@ -50,7 +51,8 @@ LL + v LL + } else { LL + v2 LL + } - ... +LL + }); + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:47:5 @@ -72,7 +74,9 @@ LL + e.insert(v); LL + } else { LL + e.insert(v2); LL + return; - ... +LL + } +LL + } + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:57:5 @@ -111,7 +115,11 @@ LL + 1 if true => { LL + v LL + }, LL + _ => { - ... +LL + v2 +LL + }, +LL + } +LL + }); + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:75:5 @@ -133,7 +141,9 @@ LL + 0 => foo(), LL + _ => { LL + e.insert(v2); LL + }, - ... +LL + }; +LL + } + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:85:5 @@ -155,7 +165,26 @@ LL + match 0 { LL + 0 if false => { LL + v LL + }, - ... +LL + 1 => { +LL + foo(); +LL + v +LL + }, +LL + 2 | 3 => { +LL + for _ in 0..2 { +LL + foo(); +LL + } +LL + if true { +LL + v +LL + } else { +LL + v2 +LL + } +LL + }, +LL + _ => { +LL + v2 +LL + }, +LL + } +LL + }); + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry.rs:119:5 diff --git a/src/tools/clippy/tests/ui/entry_with_else.stderr b/src/tools/clippy/tests/ui/entry_with_else.stderr index 7279efc595959..e0f6671b460ed 100644 --- a/src/tools/clippy/tests/ui/entry_with_else.stderr +++ b/src/tools/clippy/tests/ui/entry_with_else.stderr @@ -17,7 +17,9 @@ LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Occupied(mut e) => { LL + e.insert(v2); - ... +LL + } +LL + } + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry_with_else.rs:22:5 @@ -37,7 +39,9 @@ LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Vacant(e) => { LL + e.insert(v2); - ... +LL + } +LL + } + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry_with_else.rs:28:5 @@ -95,7 +99,9 @@ LL + e.insert(v); LL + } LL + std::collections::hash_map::Entry::Occupied(mut e) => { LL + e.insert(v2); - ... +LL + } +LL + } + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry_with_else.rs:46:5 @@ -115,7 +121,10 @@ LL + if true { Some(e.insert(v)) } else { Some(e.insert(v2)) } LL + } LL + std::collections::hash_map::Entry::Vacant(e) => { LL + e.insert(v); - ... +LL + None +LL + } +LL ~ }; + | error: usage of `contains_key` followed by `insert` on a `HashMap` --> $DIR/entry_with_else.rs:52:5 diff --git a/src/tools/clippy/tests/ui/let_unit.stderr b/src/tools/clippy/tests/ui/let_unit.stderr index 13ec11a6d33e9..45bf67acdb736 100644 --- a/src/tools/clippy/tests/ui/let_unit.stderr +++ b/src/tools/clippy/tests/ui/let_unit.stderr @@ -32,7 +32,8 @@ LL + .map(|i| i * 2) LL + .filter(|i| i % 2 == 0) LL + .map(|_| ()) LL + .next() - ... +LL + .unwrap(); + | error: this let-binding has unit value --> $DIR/let_unit.rs:80:5 diff --git a/src/tools/clippy/tests/ui/manual_async_fn.stderr b/src/tools/clippy/tests/ui/manual_async_fn.stderr index 7435f46074c81..0a903ed6fd436 100644 --- a/src/tools/clippy/tests/ui/manual_async_fn.stderr +++ b/src/tools/clippy/tests/ui/manual_async_fn.stderr @@ -122,7 +122,14 @@ LL + let a = 42; LL + let b = 21; LL + if a < b { LL + let c = 21; - ... +LL + let d = 42; +LL + if c < d { +LL + let _ = 42; +LL + } +LL + } +LL + 42 +LL + } + | error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:92:1 diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr index f607e0a430e24..7893ff31a6fdb 100644 --- a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr +++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr @@ -19,7 +19,8 @@ LL + return; LL + } else { LL + println!("{}", v); LL + } - ... +LL + } + | help: ...and replace `return` with `continue` | LL | continue; diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr index 19572dfe8b075..212a69ab94e65 100644 --- a/src/tools/clippy/tests/ui/new_without_default.stderr +++ b/src/tools/clippy/tests/ui/new_without_default.stderr @@ -117,7 +117,8 @@ LL + Self::new() LL + } LL + } LL + - ... +LL ~ impl Foo { + | error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index a9613daadde10..7ec4a566ff34b 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -56,7 +56,8 @@ LL | let f = e.clone(); // OK LL | let g = x; LL ~ let h = g.to_owned(); LL | let i = (e).clone(); - ... +LL ~ x.to_owned() + | error: writing `&String` instead of `&str` involves a new object where a slice will do --> $DIR/ptr_arg.rs:57:18 diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr index 303f3c1df033c..5ce9520441637 100644 --- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr +++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr @@ -188,7 +188,9 @@ LL + _ => mutex2.lock().unwrap(), LL + } LL + .s LL + .len() - ... +LL + > 1; +LL ~ match value + | error: temporary with significant drop in match scrutinee --> $DIR/significant_drop_in_scrutinee.rs:397:11 @@ -211,7 +213,10 @@ LL + } else { LL + mutex2.lock().unwrap() LL + } LL + .s - ... +LL + .len() +LL + > 1; +LL ~ match value + | error: temporary with significant drop in match scrutinee --> $DIR/significant_drop_in_scrutinee.rs:451:11 diff --git a/src/tools/clippy/tests/ui/unit_arg.stderr b/src/tools/clippy/tests/ui/unit_arg.stderr index 394dee29dc96e..11cfe66a30e85 100644 --- a/src/tools/clippy/tests/ui/unit_arg.stderr +++ b/src/tools/clippy/tests/ui/unit_arg.stderr @@ -137,7 +137,13 @@ LL + foo(1); LL + }; LL + { LL + foo(2); - ... +LL + foo(3); +LL + }; +LL + taking_multiple_units( +LL + (), +LL + (), +LL ~ ); + | error: passing a unit value to a function --> $DIR/unit_arg.rs:85:13 diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr index 8e31db3950247..a6a0b22cf689f 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr @@ -23,7 +23,8 @@ LL | if a { LL | Some(-1); LL ~ 2 LL | } else { - ... +LL ~ return 1337; + | error: this function's return value is unnecessarily wrapped by `Option` --> $DIR/unnecessary_wraps.rs:21:1 @@ -122,7 +123,8 @@ LL | if a { LL | Some(()); LL ~ LL | } else { - ... +LL ~ return ; + | error: this function's return value is unnecessary --> $DIR/unnecessary_wraps.rs:117:1