From 756be4a052cf43d5dec2b7ee99e611d2127d989e Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 03:14:05 +0300 Subject: [PATCH 01/22] refactored StyledBuffer parts into StyledChar --- compiler/rustc_errors/src/styled_buffer.rs | 47 ++++++++++++---------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index ec122e7be6e8e..89b8afdc7ab55 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -1,39 +1,49 @@ // Code for creating styled buffers use crate::snippet::{Style, StyledString}; -use std::iter; #[derive(Debug)] pub struct StyledBuffer { - text: Vec>, - styles: Vec>, + text: Vec>, +} + +#[derive(Debug)] +struct StyledChar { + chr: char, + style: Style, +} + +impl StyledChar { + fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } + } } impl StyledBuffer { pub fn new() -> StyledBuffer { - StyledBuffer { text: vec![], styles: vec![] } + StyledBuffer { text: vec![] } } pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(self.text.iter().all(|r| !r.contains(&'\t'))); + debug_assert!(self.text.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for (row, row_style) in iter::zip(&self.text, &self.styles) { + for styled_row in &self.text { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for (&c, &s) in iter::zip(row, row_style) { - if s != current_style { + for sc in styled_row { + if sc.style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); } - current_style = s; + current_style = sc.style; current_text = String::new(); } - current_text.push(c); + current_text.push(sc.chr); } if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); @@ -51,24 +61,20 @@ impl StyledBuffer { fn ensure_lines(&mut self, line: usize) { while line >= self.text.len() { self.text.push(vec![]); - self.styles.push(vec![]); } } pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); if col < self.text[line].len() { - self.text[line][col] = chr; - self.styles[line][col] = style; + self.text[line][col] = StyledChar::new(chr, style); } else { let mut i = self.text[line].len(); while i < col { - self.text[line].push(' '); - self.styles[line].push(Style::NoStyle); + self.text[line].push(StyledChar::new(' ', Style::NoStyle)); i += 1; } - self.text[line].push(chr); - self.styles[line].push(style); + self.text[line].push(StyledChar::new(chr, style)); } } @@ -86,8 +92,7 @@ impl StyledBuffer { // Push the old content over to make room for new content for _ in 0..string_len { - self.styles[line].insert(0, Style::NoStyle); - self.text[line].insert(0, ' '); + self.text[line].insert(0, StyledChar::new(' ', Style::NoStyle)); } self.puts(line, 0, string, style); @@ -120,8 +125,8 @@ impl StyledBuffer { } pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { - if let Some(ref mut line) = self.styles.get_mut(line) { - if let Some(s) = line.get_mut(col) { + if let Some(ref mut line) = self.text.get_mut(line) { + if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { if *s == Style::NoStyle || *s == Style::Quotation || overwrite { *s = style; } From f5229916e350e5b70a6db4f3378f63993eaecb3d Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 03:20:07 +0300 Subject: [PATCH 02/22] added default for StyledChar --- compiler/rustc_errors/src/styled_buffer.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 89b8afdc7ab55..8ce9c4bbfa1b6 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -19,6 +19,12 @@ impl StyledChar { } } +impl Default for StyledChar { + fn default() -> Self { + StyledChar::new(' ', Style::NoStyle) + } +} + impl StyledBuffer { pub fn new() -> StyledBuffer { StyledBuffer { text: vec![] } @@ -71,7 +77,7 @@ impl StyledBuffer { } else { let mut i = self.text[line].len(); while i < col { - self.text[line].push(StyledChar::new(' ', Style::NoStyle)); + self.text[line].push(StyledChar::default()); i += 1; } self.text[line].push(StyledChar::new(chr, style)); @@ -92,7 +98,7 @@ impl StyledBuffer { // Push the old content over to make room for new content for _ in 0..string_len { - self.text[line].insert(0, StyledChar::new(' ', Style::NoStyle)); + self.text[line].insert(0, StyledChar::default()); } self.puts(line, 0, string, style); From e97ddedac644fb192c25490f6f6eab711bc1bea8 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 04:14:59 +0300 Subject: [PATCH 03/22] added some docs for StyledBuffer --- compiler/rustc_errors/src/styled_buffer.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 8ce9c4bbfa1b6..a89d0aeaffd84 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -30,6 +30,7 @@ impl StyledBuffer { StyledBuffer { text: vec![] } } + /// Returns content of `StyledBuffer` splitted by lines and line styles pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(self.text.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); @@ -70,6 +71,9 @@ impl StyledBuffer { } } + /// Sets `chr` with `style` for given `line`, `col`. + /// If line not exist in `StyledBuffer`, adds lines up to given + /// and fills last line with spaces and `Style::NoStyle` style pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); if col < self.text[line].len() { @@ -84,6 +88,9 @@ impl StyledBuffer { } } + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If line not exist in `StyledBuffer`, adds lines up to given + /// and fills last line with spaces and `Style::NoStyle` style pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { @@ -92,6 +99,8 @@ impl StyledBuffer { } } + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); @@ -104,6 +113,8 @@ impl StyledBuffer { self.puts(line, 0, string, style); } + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed pub fn append(&mut self, line: usize, string: &str, style: Style) { if line >= self.text.len() { self.puts(line, 0, string, style); @@ -117,6 +128,9 @@ impl StyledBuffer { self.text.len() } + /// Set `style` for `line`, `col_start..col_end` range if: + /// 1. That line and column range exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style_range( &mut self, line: usize, @@ -130,6 +144,9 @@ impl StyledBuffer { } } + /// Set `style` for `line`, `col` if: + /// 1. That line and column exist in `StyledBuffer` + /// 2. Existing style is `Style::NoStyle` or `Style::Quotation` or `overwrite` is `true` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { if let Some(ref mut line) = self.text.get_mut(line) { if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { From 7e9d3c6f6cf3956dbf2a7870cebe89ebeb5d9ea5 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 05:11:45 +0300 Subject: [PATCH 04/22] StyledBuffer::prepend: if line is empty, insert content without inserting spaces --- compiler/rustc_errors/src/styled_buffer.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index a89d0aeaffd84..9c19c96d64f9a 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -105,9 +105,11 @@ impl StyledBuffer { self.ensure_lines(line); let string_len = string.chars().count(); - // Push the old content over to make room for new content - for _ in 0..string_len { - self.text[line].insert(0, StyledChar::default()); + if !self.text[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.text[line].insert(0, StyledChar::default()); + } } self.puts(line, 0, string, style); From 247d74f207633a5aeceb1e0ede878427465c5093 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 05:23:40 +0300 Subject: [PATCH 05/22] StyledBuffer::set_style: check overwrite first --- compiler/rustc_errors/src/styled_buffer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 9c19c96d64f9a..01d2a8de39d50 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -148,11 +148,11 @@ impl StyledBuffer { /// Set `style` for `line`, `col` if: /// 1. That line and column exist in `StyledBuffer` - /// 2. Existing style is `Style::NoStyle` or `Style::Quotation` or `overwrite` is `true` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { if let Some(ref mut line) = self.text.get_mut(line) { if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { - if *s == Style::NoStyle || *s == Style::Quotation || overwrite { + if overwrite || *s == Style::NoStyle || *s == Style::Quotation { *s = style; } } From cb2d52282fb3c226c370a86c9111892384bbcb21 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 05:38:32 +0300 Subject: [PATCH 06/22] rename StyledBuffer.text to lines --- compiler/rustc_errors/src/styled_buffer.rs | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 01d2a8de39d50..fb9575b290a0d 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -4,7 +4,7 @@ use crate::snippet::{Style, StyledString}; #[derive(Debug)] pub struct StyledBuffer { - text: Vec>, + lines: Vec>, } #[derive(Debug)] @@ -27,22 +27,22 @@ impl Default for StyledChar { impl StyledBuffer { pub fn new() -> StyledBuffer { - StyledBuffer { text: vec![] } + StyledBuffer { lines: vec![] } } /// Returns content of `StyledBuffer` splitted by lines and line styles pub fn render(&self) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. - debug_assert!(self.text.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); + debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; - for styled_row in &self.text { + for styled_line in &self.lines { let mut current_style = Style::NoStyle; let mut current_text = String::new(); - for sc in styled_row { + for sc in styled_line { if sc.style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); @@ -66,8 +66,8 @@ impl StyledBuffer { } fn ensure_lines(&mut self, line: usize) { - while line >= self.text.len() { - self.text.push(vec![]); + while line >= self.lines.len() { + self.lines.push(vec![]); } } @@ -76,15 +76,15 @@ impl StyledBuffer { /// and fills last line with spaces and `Style::NoStyle` style pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); - if col < self.text[line].len() { - self.text[line][col] = StyledChar::new(chr, style); + if col < self.lines[line].len() { + self.lines[line][col] = StyledChar::new(chr, style); } else { - let mut i = self.text[line].len(); + let mut i = self.lines[line].len(); while i < col { - self.text[line].push(StyledChar::default()); + self.lines[line].push(StyledChar::default()); i += 1; } - self.text[line].push(StyledChar::new(chr, style)); + self.lines[line].push(StyledChar::new(chr, style)); } } @@ -105,10 +105,10 @@ impl StyledBuffer { self.ensure_lines(line); let string_len = string.chars().count(); - if !self.text[line].is_empty() { + if !self.lines[line].is_empty() { // Push the old content over to make room for new content for _ in 0..string_len { - self.text[line].insert(0, StyledChar::default()); + self.lines[line].insert(0, StyledChar::default()); } } @@ -118,16 +118,16 @@ impl StyledBuffer { /// For given `line` inserts `string` with `style` after old content of that line, /// adding lines if needed pub fn append(&mut self, line: usize, string: &str, style: Style) { - if line >= self.text.len() { + if line >= self.lines.len() { self.puts(line, 0, string, style); } else { - let col = self.text[line].len(); + let col = self.lines[line].len(); self.puts(line, col, string, style); } } pub fn num_lines(&self) -> usize { - self.text.len() + self.lines.len() } /// Set `style` for `line`, `col_start..col_end` range if: @@ -150,7 +150,7 @@ impl StyledBuffer { /// 1. That line and column exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { - if let Some(ref mut line) = self.text.get_mut(line) { + if let Some(ref mut line) = self.lines.get_mut(line) { if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { if overwrite || *s == Style::NoStyle || *s == Style::Quotation { *s = style; From e4ce655cbf11dded14af67a9d8201207c6d18c1f Mon Sep 17 00:00:00 2001 From: Smitty Date: Fri, 23 Apr 2021 13:29:18 -0400 Subject: [PATCH 07/22] Handle pretty printing of `else if let` clauses Closes #84434. Closes #82329. --- compiler/rustc_hir_pretty/src/lib.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5820e7a261230..77d083fc5e967 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1095,8 +1095,8 @@ impl<'a> State<'a> { fn print_else(&mut self, els: Option<&hir::Expr<'_>>) { match els { - Some(_else) => { - match _else.kind { + Some(else_) => { + match else_.kind { // "another else-if" hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); @@ -1114,6 +1114,26 @@ impl<'a> State<'a> { self.s.word(" else "); self.print_block(&b) } + hir::ExprKind::Match(ref expr, arms, _) => { + // else if let desugared to match + assert!(arms.len() == 2, "if let desugars to match with two arms"); + + self.s.word(" else "); + self.s.word("{"); + + self.cbox(INDENT_UNIT); + self.ibox(INDENT_UNIT); + self.word_nbsp("match"); + self.print_expr_as_cond(&expr); + self.s.space(); + self.bopen(); + for arm in arms { + self.print_arm(arm); + } + self.bclose(expr.span); + + self.s.word("}"); + } // BLEAH, constraints would be great here _ => { panic!("print_if saw if with weird alternative"); From fc97ce6daed320027a47c1a0ddb86c9242ebde0c Mon Sep 17 00:00:00 2001 From: Smitty Date: Fri, 23 Apr 2021 14:06:02 -0400 Subject: [PATCH 08/22] add tests for new behavior --- src/test/ui/match/issue-82392.rs | 9 +++++++++ src/test/ui/match/issue-82392.stdout | 20 ++++++++++++++++++++ src/test/ui/match/issue-84434.rs | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/test/ui/match/issue-82392.rs create mode 100644 src/test/ui/match/issue-82392.stdout create mode 100644 src/test/ui/match/issue-84434.rs diff --git a/src/test/ui/match/issue-82392.rs b/src/test/ui/match/issue-82392.rs new file mode 100644 index 0000000000000..d26d883040b48 --- /dev/null +++ b/src/test/ui/match/issue-82392.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() { + if true { + } else if let Some(a) = Some(3) { + } +} diff --git a/src/test/ui/match/issue-82392.stdout b/src/test/ui/match/issue-82392.stdout new file mode 100644 index 0000000000000..8ff76c64fc789 --- /dev/null +++ b/src/test/ui/match/issue-82392.stdout @@ -0,0 +1,20 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() ({ + (if (true as bool) + ({ } as + ()) else {match ((Some as + fn(i32) -> Option {Option::::Some})((3 + as + i32)) + as Option) { + Some(a) => { } + _ => { } + }} as ()) + } as ()) diff --git a/src/test/ui/match/issue-84434.rs b/src/test/ui/match/issue-84434.rs new file mode 100644 index 0000000000000..423481fd5f02d --- /dev/null +++ b/src/test/ui/match/issue-84434.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, +}; + +fn main() {} From 862901781d5980e7cd1865b6cd6d77760f4016ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Apr 2021 18:08:51 -0700 Subject: [PATCH 09/22] Add regression test --- .../import-trait-for-method-call.rs | 9 +++++++ .../import-trait-for-method-call.stderr | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/suggestions/import-trait-for-method-call.rs create mode 100644 src/test/ui/suggestions/import-trait-for-method-call.stderr diff --git a/src/test/ui/suggestions/import-trait-for-method-call.rs b/src/test/ui/suggestions/import-trait-for-method-call.rs new file mode 100644 index 0000000000000..646f68dea14e8 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.rs @@ -0,0 +1,9 @@ +use std::hash::BuildHasher; + +fn next_u64() -> u64 { + let bh = std::collections::hash_map::RandomState::new(); + let h = bh.build_hasher(); + h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` +} + +fn main() {} diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr new file mode 100644 index 0000000000000..8b72e8c922cfe --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -0,0 +1,26 @@ +error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope + --> $DIR/import-trait-for-method-call.rs:6:7 + | +LL | h.finish() + | ^^^^^^ method not found in `DefaultHasher` + | + ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL + | +LL | fn finish(&self) -> u64; + | ------ + | | + | the method is available for `Box` here + | the method is available for `Box<&mut DefaultHasher>` here + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(h).finish() + | ^^^^^^^^^ ^ +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(&mut h).finish() + | ^^^^^^^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 64ee9cc28ceda652ac06b7d6bf68d1b7f408cf23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Apr 2021 18:12:54 -0700 Subject: [PATCH 10/22] Recover trait import suggestion --- compiler/rustc_typeck/src/check/method/suggest.rs | 2 +- src/test/ui/suggestions/import-trait-for-method-call.stderr | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 02fe8312c4c1f..47e4e1223ff18 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1047,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) { + if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr index 8b72e8c922cfe..b6fc09cc5d0ad 100644 --- a/src/test/ui/suggestions/import-trait-for-method-call.stderr +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -12,6 +12,7 @@ LL | fn finish(&self) -> u64; | the method is available for `Box` here | the method is available for `Box<&mut DefaultHasher>` here | + = help: items from traits can only be used if the trait is in scope help: consider wrapping the receiver expression with the appropriate type | LL | Box::new(h).finish() @@ -20,6 +21,10 @@ help: consider wrapping the receiver expression with the appropriate type | LL | Box::new(&mut h).finish() | ^^^^^^^^^^^^^ ^ +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::hash::Hasher; + | error: aborting due to previous error From fb1fb7d2ef45760bfe133381286dc750fe51e49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Apr 2021 18:24:02 -0700 Subject: [PATCH 11/22] Tweak suggestion output --- .../rustc_typeck/src/check/method/suggest.rs | 35 +++++++++++++++---- src/test/ui/hygiene/trait_items.stderr | 3 ++ .../no-method-suggested-traits.stderr | 8 +++++ src/test/ui/issues/issue-43189.stderr | 5 +++ src/test/ui/issues/issue-56175.stderr | 10 ++++++ .../rust-2018/trait-import-suggestions.stderr | 6 ++++ .../ui/shadowed/shadowed-trait-methods.stderr | 3 ++ .../import-trait-for-method-call.stderr | 13 +------ src/test/ui/traits/item-privacy.stderr | 3 ++ 9 files changed, 67 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 47e4e1223ff18..73e35f0171aa7 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut alt_rcvr_sugg = false; if let SelfSource::MethodCall(rcvr) = source { debug!(?span, ?item_name, ?rcvr_ty, ?rcvr); + let skippable = [ + self.tcx.lang_items().clone_trait(), + self.tcx.lang_items().deref_trait(), + self.tcx.lang_items().deref_mut_trait(), + self.tcx.lang_items().drop_trait(), + ]; // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not // just this list. @@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "), (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"), ] { + if let Ok(pick) = self.lookup_probe( + span, + item_name, + rcvr_ty, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + // If the method is defined for the receiver we have, it likely wasn't `use`d. + // We point at the method, but we just skip the rest of the check for arbitrary + // self types and rely on the suggestion to `use` the trait from + // `suggest_valid_traits`. + let did = Some(pick.item.container.id()); + let skip = skippable.contains(&did); + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident.span, + &format!("the method is available for `{}` here", rcvr_ty), + ); + } + break; + } for (rcvr_ty, pre) in &[ (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"), (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"), @@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We don't want to suggest a container type when the missing // method is `.clone()` or `.deref()` otherwise we'd suggest // `Arc::new(foo).clone()`, which is far from what the user wants. - let skip = [ - self.tcx.lang_items().clone_trait(), - self.tcx.lang_items().deref_trait(), - self.tcx.lang_items().deref_mut_trait(), - self.tcx.lang_items().drop_trait(), - ] - .contains(&did); + let skip = skippable.contains(&did); // Make sure the method is defined for the *actual* receiver: we don't // want to treat `Box` as a receiver if it only works because of // an autoderef to `&self` diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index d24336883e963..2913a955dce1b 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/trait_items.rs:17:24 | +LL | fn f(&self) {} + | - the method is available for `()` here +... LL | fn f() { ::baz::m!(); } | ------------ in this macro invocation ... diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 64ddcb81c0a9b..b993115502fd5 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -37,6 +37,9 @@ LL | use no_method_suggested_traits::Reexported; error[E0599]: no method named `method` found for type `char` in the current scope --> $DIR/no-method-suggested-traits.rs:30:9 | +LL | fn method(&self) {} + | ------ the method is available for `char` here +... LL | 'a'.method(); | ^^^^^^ method not found in `char` | @@ -63,6 +66,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope | LL | 1i32.method(); | ^^^^^^ method not found in `i32` + | + ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12 + | +LL | fn method(&self) {} + | ------ the method is available for `i32` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr index 3f63cb8e78fba..3a3767c349d65 100644 --- a/src/test/ui/issues/issue-43189.stderr +++ b/src/test/ui/issues/issue-43189.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope | LL | ().a(); | ^ method not found in `()` + | + ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8 + | +LL | fn a(&self) {} + | - the method is available for `()` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr index ee3f609f47dca..e6b0fffce663d 100644 --- a/src/test/ui/issues/issue-56175.stderr +++ b/src/test/ui/issues/issue-56175.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the | LL | reexported_trait::FooStruct.trait_method(); | ^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:3:12 + | +LL | fn trait_method(&self) { + | ------------ the method is available for `FooStruct` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: @@ -15,6 +20,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t | LL | reexported_trait::FooStruct.trait_method_b(); | ^^^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:7:12 + | +LL | fn trait_method_b(&self) { + | -------------- the method is available for `FooStruct` here | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index 4b1898345a32e..2cf5a073fe5c2 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foobar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:22:11 | +LL | fn foobar(&self) { } + | ------ the method is available for `u32` here +... LL | x.foobar(); | ^^^^^^ method not found in `u32` | @@ -11,6 +14,9 @@ LL | x.foobar(); error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:28:7 | +LL | fn bar(&self) { } + | --- the method is available for `u32` here +... LL | x.bar(); | ^^^ method not found in `u32` | diff --git a/src/test/ui/shadowed/shadowed-trait-methods.stderr b/src/test/ui/shadowed/shadowed-trait-methods.stderr index 362907ecbd7ef..c3b9084affdb3 100644 --- a/src/test/ui/shadowed/shadowed-trait-methods.stderr +++ b/src/test/ui/shadowed/shadowed-trait-methods.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `f` found for unit type `()` in the current scope --> $DIR/shadowed-trait-methods.rs:13:8 | +LL | pub trait T { fn f(&self) {} } + | - the method is available for `()` here +... LL | ().f() | ^ method not found in `()` | diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr index b6fc09cc5d0ad..f3ae20552f3d5 100644 --- a/src/test/ui/suggestions/import-trait-for-method-call.stderr +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -7,20 +7,9 @@ LL | h.finish() ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL | LL | fn finish(&self) -> u64; - | ------ - | | - | the method is available for `Box` here - | the method is available for `Box<&mut DefaultHasher>` here + | ------ the method is available for `DefaultHasher` here | = help: items from traits can only be used if the trait is in scope -help: consider wrapping the receiver expression with the appropriate type - | -LL | Box::new(h).finish() - | ^^^^^^^^^ ^ -help: consider wrapping the receiver expression with the appropriate type - | -LL | Box::new(&mut h).finish() - | ^^^^^^^^^^^^^ ^ help: the following trait is implemented but not in scope; perhaps add a `use` for it: | LL | use std::hash::Hasher; diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index 68d527dc786aa..30daf8e277024 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope LL | struct S; | --------- method `b` not found for this ... +LL | fn b(&self) { } + | - the method is available for `S` here +... LL | S.b(); | ^ method not found in `S` | From ad78b50a86c6ac908df1c385642d46d3183740d6 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sat, 24 Apr 2021 13:57:41 +0200 Subject: [PATCH 12/22] Implemented suggestion. --- compiler/rustc_typeck/src/check/coercion.rs | 4 +- .../src/check/fn_ctxt/suggestions.rs | 78 ++++++++++++++++++- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 427f967a9b6bd..236fec94bdba7 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1494,7 +1494,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some((expr, _)), Some((fn_decl, _, _))) = (expression, fcx.get_node_fn_decl(parent_item)) { - fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found, parent_id); + fcx.suggest_missing_break_or_return_expr( + &mut err, expr, fn_decl, expected, found, id, parent_id, + ); } if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index b758334484535..c3417247725fe 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, ItemKind, Node}; +use rustc_hir::{ExprKind, ItemKind, Node, StmtKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -55,7 +55,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pointing_at_return_type = self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); - self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found, fn_id); + self.suggest_missing_break_or_return_expr( + err, expr, &fn_decl, expected, found, blk_id, fn_id, + ); } pointing_at_return_type } @@ -472,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(in super::super) fn suggest_missing_return_expr( + pub(in super::super) fn suggest_missing_break_or_return_expr( &self, err: &mut DiagnosticBuilder<'_>, expr: &'tcx hir::Expr<'tcx>, @@ -480,14 +482,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, id: hir::HirId, + fn_id: hir::HirId, ) { if !expected.is_unit() { return; } let found = self.resolve_vars_with_obligations(found); + + if self.in_loop(id) { + if self.in_local_statement(id) { + err.multipart_suggestion( + "you might have meant to break the loop with this value", + vec![ + (expr.span.shrink_to_lo(), "break ".to_string()), + (expr.span.shrink_to_hi(), ";".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return; + } + } + if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(self, ty); - let bound_vars = self.tcx.late_bound_vars(id); + let bound_vars = self.tcx.late_bound_vars(fn_id); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); if self.can_coerce(found, ty) { @@ -514,4 +532,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None); } } + + fn in_loop(&self, id: hir::HirId) -> bool { + if self.is_loop(id) { + return true; + } + + for (parent_id, _) in self.tcx.hir().parent_iter(id) { + if self.is_loop(parent_id) { + return true; + } + } + + false + } + + fn is_loop(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + + if let Node::Expr(expr) = node { + if let ExprKind::Loop(..) = expr.kind { + return true; + } + } + + false + } + + fn in_local_statement(&self, id: hir::HirId) -> bool { + if self.is_local_statement(id) { + return true; + } + + for (parent_id, _) in self.tcx.hir().parent_iter(id) { + if self.is_local_statement(parent_id) { + return true; + } + } + + false + } + + fn is_local_statement(&self, id: hir::HirId) -> bool { + let node = self.tcx.hir().get(id); + + if let Node::Stmt(stmt) = node { + if let StmtKind::Local(..) = stmt.kind { + return true; + } + } + + false + } } From 0e7489a2e9443069d5a7063f0b47d9923921f57f Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sat, 24 Apr 2021 18:08:22 +0200 Subject: [PATCH 13/22] Added a test. --- src/test/ui/loops/loop-no-implicit-break.rs | 5 +++++ src/test/ui/loops/loop-no-implicit-break.stderr | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/test/ui/loops/loop-no-implicit-break.rs create mode 100644 src/test/ui/loops/loop-no-implicit-break.stderr diff --git a/src/test/ui/loops/loop-no-implicit-break.rs b/src/test/ui/loops/loop-no-implicit-break.rs new file mode 100644 index 0000000000000..0c57baf14394b --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.rs @@ -0,0 +1,5 @@ +fn main() { + let x: i8 = loop { + 10 //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/loops/loop-no-implicit-break.stderr b/src/test/ui/loops/loop-no-implicit-break.stderr new file mode 100644 index 0000000000000..99767b78d35e3 --- /dev/null +++ b/src/test/ui/loops/loop-no-implicit-break.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:3:9 + | +LL | 10 + | ^^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 10; + | ^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 8bc81a0e4d9d5edc72af0cffe31a78a0bd2156f2 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sat, 24 Apr 2021 18:49:21 +0200 Subject: [PATCH 14/22] Refactor. --- .../src/check/fn_ctxt/suggestions.rs | 80 ++++++------------- 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index c3417247725fe..d6b1e56316b37 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, ItemKind, Node, StmtKind}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -489,18 +489,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let found = self.resolve_vars_with_obligations(found); - if self.in_loop(id) { - if self.in_local_statement(id) { - err.multipart_suggestion( - "you might have meant to break the loop with this value", - vec![ - (expr.span.shrink_to_lo(), "break ".to_string()), - (expr.span.shrink_to_hi(), ";".to_string()), - ], - Applicability::MaybeIncorrect, - ); - return; - } + let in_loop = self.is_loop(id) + || self.tcx.hir().parent_iter(id).any(|(parent_id, _)| self.is_loop(parent_id)); + + let in_local_statement = self.is_local_statement(id) + || self + .tcx + .hir() + .parent_iter(id) + .any(|(parent_id, _)| self.is_local_statement(parent_id)); + + if in_loop && in_local_statement { + err.multipart_suggestion( + "you might have meant to break the loop with this value", + vec![ + (expr.span.shrink_to_lo(), "break ".to_string()), + (expr.span.shrink_to_hi(), ";".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return; } if let hir::FnRetTy::Return(ty) = fn_decl.output { @@ -533,55 +541,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn in_loop(&self, id: hir::HirId) -> bool { - if self.is_loop(id) { - return true; - } - - for (parent_id, _) in self.tcx.hir().parent_iter(id) { - if self.is_loop(parent_id) { - return true; - } - } - - false - } - fn is_loop(&self, id: hir::HirId) -> bool { let node = self.tcx.hir().get(id); - - if let Node::Expr(expr) = node { - if let ExprKind::Loop(..) = expr.kind { - return true; - } - } - - false - } - - fn in_local_statement(&self, id: hir::HirId) -> bool { - if self.is_local_statement(id) { - return true; - } - - for (parent_id, _) in self.tcx.hir().parent_iter(id) { - if self.is_local_statement(parent_id) { - return true; - } - } - - false + matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. })) } fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir().get(id); - - if let Node::Stmt(stmt) = node { - if let StmtKind::Local(..) = stmt.kind { - return true; - } - } - - false + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) } } From 05a5a1128fc5da178f9b7bd0ab499258652dfc49 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sat, 24 Apr 2021 19:00:24 +0200 Subject: [PATCH 15/22] More tests. --- src/test/ui/loops/loop-no-implicit-break.rs | 26 +++++++++++++-- .../ui/loops/loop-no-implicit-break.stderr | 32 ++++++++++++++++--- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/test/ui/loops/loop-no-implicit-break.rs b/src/test/ui/loops/loop-no-implicit-break.rs index 0c57baf14394b..fc3b3c4a30fac 100644 --- a/src/test/ui/loops/loop-no-implicit-break.rs +++ b/src/test/ui/loops/loop-no-implicit-break.rs @@ -1,5 +1,27 @@ fn main() { - let x: i8 = loop { - 10 //~ ERROR mismatched types + let a: i8 = loop { + 1 //~ ERROR mismatched types }; + + let b: i8 = loop { + break 1; + }; +} + +fn foo() -> i8 { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; + + loop { + 1 //~ ERROR mismatched types + } + + loop { + return 1; + } } diff --git a/src/test/ui/loops/loop-no-implicit-break.stderr b/src/test/ui/loops/loop-no-implicit-break.stderr index 99767b78d35e3..cde6bbe512b28 100644 --- a/src/test/ui/loops/loop-no-implicit-break.stderr +++ b/src/test/ui/loops/loop-no-implicit-break.stderr @@ -1,14 +1,36 @@ error[E0308]: mismatched types --> $DIR/loop-no-implicit-break.rs:3:9 | -LL | 10 - | ^^ expected `()`, found integer +LL | 1 + | ^ expected `()`, found integer | help: you might have meant to break the loop with this value | -LL | break 10; - | ^^^^^ ^ +LL | break 1; + | ^^^^^ ^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:13:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | ^^^^^ ^ + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:21:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. From 8ebd811b32de96c0e9e4208703465016da3d8764 Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 18 Apr 2021 02:15:15 +0300 Subject: [PATCH 16/22] review --- compiler/rustc_errors/src/styled_buffer.rs | 38 ++++++++-------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index fb9575b290a0d..e262d95bb70f2 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -7,21 +7,17 @@ pub struct StyledBuffer { lines: Vec>, } -#[derive(Debug)] +#[derive(Debug, Clone)] struct StyledChar { chr: char, style: Style, } impl StyledChar { - fn new(chr: char, style: Style) -> Self { - StyledChar { chr, style } - } -} + const SPACE: Self = StyledChar::new(' ', Style::NoStyle); -impl Default for StyledChar { - fn default() -> Self { - StyledChar::new(' ', Style::NoStyle) + const fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } } } @@ -66,31 +62,25 @@ impl StyledBuffer { } fn ensure_lines(&mut self, line: usize) { - while line >= self.lines.len() { - self.lines.push(vec![]); + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); } } /// Sets `chr` with `style` for given `line`, `col`. - /// If line not exist in `StyledBuffer`, adds lines up to given - /// and fills last line with spaces and `Style::NoStyle` style + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); - if col < self.lines[line].len() { - self.lines[line][col] = StyledChar::new(chr, style); - } else { - let mut i = self.lines[line].len(); - while i < col { - self.lines[line].push(StyledChar::default()); - i += 1; - } - self.lines[line].push(StyledChar::new(chr, style)); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); } + self.lines[line][col] = StyledChar::new(chr, style); } /// Sets `string` with `style` for given `line`, starting from `col`. - /// If line not exist in `StyledBuffer`, adds lines up to given - /// and fills last line with spaces and `Style::NoStyle` style + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { @@ -108,7 +98,7 @@ impl StyledBuffer { if !self.lines[line].is_empty() { // Push the old content over to make room for new content for _ in 0..string_len { - self.lines[line].insert(0, StyledChar::default()); + self.lines[line].insert(0, StyledChar::SPACE); } } From 3b504610b6768d8cb700bc2a8fa2a6263b9d3a06 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sat, 24 Apr 2021 22:20:08 +0200 Subject: [PATCH 17/22] One more test case. --- src/test/ui/loops/loop-no-implicit-break.rs | 4 ++++ src/test/ui/loops/loop-no-implicit-break.stderr | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test/ui/loops/loop-no-implicit-break.rs b/src/test/ui/loops/loop-no-implicit-break.rs index fc3b3c4a30fac..93078cb4b144b 100644 --- a/src/test/ui/loops/loop-no-implicit-break.rs +++ b/src/test/ui/loops/loop-no-implicit-break.rs @@ -24,4 +24,8 @@ fn foo() -> i8 { loop { return 1; } + + loop { + 1 //~ ERROR mismatched types + } } diff --git a/src/test/ui/loops/loop-no-implicit-break.stderr b/src/test/ui/loops/loop-no-implicit-break.stderr index cde6bbe512b28..5087662e7bfa4 100644 --- a/src/test/ui/loops/loop-no-implicit-break.stderr +++ b/src/test/ui/loops/loop-no-implicit-break.stderr @@ -31,6 +31,17 @@ help: you might have meant to return this value LL | return 1; | ^^^^^^ ^ -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:29:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ^^^^^^ ^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. From fbc2aadbfc6a54da9d8cc5929287d2bcc55c545e Mon Sep 17 00:00:00 2001 From: KaiJewson Date: Sun, 25 Apr 2021 07:39:09 +0100 Subject: [PATCH 18/22] Inline most raw socket, fd and handle conversions --- library/std/src/sys/sgx/ext/io.rs | 6 ++++++ library/std/src/sys/unix/ext/io.rs | 12 +++++++++++ library/std/src/sys/unix/ext/net/datagram.rs | 3 +++ library/std/src/sys/unix/ext/net/listener.rs | 3 +++ library/std/src/sys/unix/ext/net/raw_fd.rs | 3 +++ library/std/src/sys/unix/ext/net/stream.rs | 3 +++ library/std/src/sys/unix/ext/process.rs | 7 +++++++ library/std/src/sys/wasi/ext/io.rs | 21 ++++++++++++++++++++ library/std/src/sys/windows/ext/io.rs | 12 +++++++++++ library/std/src/sys/windows/ext/process.rs | 4 ++++ library/std/src/sys/windows/ext/thread.rs | 2 ++ 11 files changed, 76 insertions(+) diff --git a/library/std/src/sys/sgx/ext/io.rs b/library/std/src/sys/sgx/ext/io.rs index 795a4d190cf4e..7223ade68158f 100644 --- a/library/std/src/sys/sgx/ext/io.rs +++ b/library/std/src/sys/sgx/ext/io.rs @@ -63,12 +63,14 @@ pub trait TryIntoRawFd: Sized { } impl AsRawFd for net::TcpStream { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() } } impl AsRawFd for net::TcpListener { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().as_inner().as_inner().as_inner() } @@ -87,6 +89,7 @@ pub struct TcpStreamMetadata { impl FromRawFd for net::TcpStream { type Metadata = TcpStreamMetadata; + #[inline] unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream { let fd = sys::fd::FileDesc::from_inner(fd); let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); @@ -105,6 +108,7 @@ pub struct TcpListenerMetadata { impl FromRawFd for net::TcpListener { type Metadata = TcpListenerMetadata; + #[inline] unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener { let fd = sys::fd::FileDesc::from_inner(fd); let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); @@ -113,6 +117,7 @@ impl FromRawFd for net::TcpListener { } impl TryIntoRawFd for net::TcpStream { + #[inline] fn try_into_raw_fd(self) -> Result { let (socket, peer_addr) = self.into_inner().into_inner(); match socket.try_into_inner() { @@ -126,6 +131,7 @@ impl TryIntoRawFd for net::TcpStream { } impl TryIntoRawFd for net::TcpListener { + #[inline] fn try_into_raw_fd(self) -> Result { match self.into_inner().into_inner().try_into_inner() { Ok(fd) => Ok(fd.into_inner()), diff --git a/library/std/src/sys/unix/ext/io.rs b/library/std/src/sys/unix/ext/io.rs index ef3c689bd3921..07c30bfa9ed15 100644 --- a/library/std/src/sys/unix/ext/io.rs +++ b/library/std/src/sys/unix/ext/io.rs @@ -104,18 +104,21 @@ pub trait IntoRawFd { #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl AsRawFd for RawFd { + #[inline] fn as_raw_fd(&self) -> RawFd { *self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl IntoRawFd for RawFd { + #[inline] fn into_raw_fd(self) -> RawFd { self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl FromRawFd for RawFd { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> RawFd { fd } @@ -123,18 +126,21 @@ impl FromRawFd for RawFd { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for fs::File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for fs::File { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> fs::File { fs::File::from_inner(sys::fs::File::from_inner(fd)) } } #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for fs::File { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -142,6 +148,7 @@ impl IntoRawFd for fs::File { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stdin { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } @@ -149,6 +156,7 @@ impl AsRawFd for io::Stdin { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stdout { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO } @@ -156,6 +164,7 @@ impl AsRawFd for io::Stdout { #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stderr { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } @@ -163,6 +172,7 @@ impl AsRawFd for io::Stderr { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StdinLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } @@ -170,6 +180,7 @@ impl<'a> AsRawFd for io::StdinLock<'a> { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StdoutLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO } @@ -177,6 +188,7 @@ impl<'a> AsRawFd for io::StdoutLock<'a> { #[stable(feature = "asraw_stdio_locks", since = "1.35.0")] impl<'a> AsRawFd for io::StderrLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } diff --git a/library/std/src/sys/unix/ext/net/datagram.rs b/library/std/src/sys/unix/ext/net/datagram.rs index a8c13fbb87480..9e39f70f68e69 100644 --- a/library/std/src/sys/unix/ext/net/datagram.rs +++ b/library/std/src/sys/unix/ext/net/datagram.rs @@ -879,6 +879,7 @@ impl UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixDatagram { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -886,6 +887,7 @@ impl AsRawFd for UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixDatagram { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { UnixDatagram(Socket::from_inner(fd)) } @@ -893,6 +895,7 @@ impl FromRawFd for UnixDatagram { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixDatagram { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/net/listener.rs b/library/std/src/sys/unix/ext/net/listener.rs index 9803c6e27462c..bdd08fe8380fa 100644 --- a/library/std/src/sys/unix/ext/net/listener.rs +++ b/library/std/src/sys/unix/ext/net/listener.rs @@ -240,6 +240,7 @@ impl UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixListener { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -247,6 +248,7 @@ impl AsRawFd for UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixListener { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(Socket::from_inner(fd)) } @@ -254,6 +256,7 @@ impl FromRawFd for UnixListener { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixListener { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/net/raw_fd.rs b/library/std/src/sys/unix/ext/net/raw_fd.rs index c42fee4c73bcd..b3f1284410124 100644 --- a/library/std/src/sys/unix/ext/net/raw_fd.rs +++ b/library/std/src/sys/unix/ext/net/raw_fd.rs @@ -6,6 +6,7 @@ macro_rules! impl_as_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::$t { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } @@ -18,6 +19,7 @@ macro_rules! impl_from_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::$t { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::$t { let socket = sys::net::Socket::from_inner(fd); net::$t::from_inner(sys_common::net::$t::from_inner(socket)) @@ -31,6 +33,7 @@ macro_rules! impl_into_raw_fd { ($($t:ident)*) => {$( #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for net::$t { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_socket().into_inner() } diff --git a/library/std/src/sys/unix/ext/net/stream.rs b/library/std/src/sys/unix/ext/net/stream.rs index fc08edacb828d..a6f6e091305d5 100644 --- a/library/std/src/sys/unix/ext/net/stream.rs +++ b/library/std/src/sys/unix/ext/net/stream.rs @@ -654,6 +654,7 @@ impl<'a> io::Write for &'a UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixStream { + #[inline] fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } @@ -661,6 +662,7 @@ impl AsRawFd for UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixStream { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(Socket::from_inner(fd)) } @@ -668,6 +670,7 @@ impl FromRawFd for UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixStream { + #[inline] fn into_raw_fd(self) -> RawFd { self.0.into_inner() } diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs index bc3bc0dcb0ce3..355855bcd10e2 100644 --- a/library/std/src/sys/unix/ext/process.rs +++ b/library/std/src/sys/unix/ext/process.rs @@ -274,6 +274,7 @@ impl ExitStatusExt for process::ExitStatus { #[stable(feature = "process_extensions", since = "1.2.0")] impl FromRawFd for process::Stdio { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio { let fd = sys::fd::FileDesc::new(fd); let io = sys::process::Stdio::Fd(fd); @@ -283,6 +284,7 @@ impl FromRawFd for process::Stdio { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStdin { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -290,6 +292,7 @@ impl AsRawFd for process::ChildStdin { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStdout { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -297,6 +300,7 @@ impl AsRawFd for process::ChildStdout { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawFd for process::ChildStderr { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().raw() } @@ -304,6 +308,7 @@ impl AsRawFd for process::ChildStderr { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStdin { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -311,6 +316,7 @@ impl IntoRawFd for process::ChildStdin { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStdout { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } @@ -318,6 +324,7 @@ impl IntoRawFd for process::ChildStdout { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for process::ChildStderr { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } diff --git a/library/std/src/sys/wasi/ext/io.rs b/library/std/src/sys/wasi/ext/io.rs index 3c480aa8e19bf..b2e79cc1b4a9d 100644 --- a/library/std/src/sys/wasi/ext/io.rs +++ b/library/std/src/sys/wasi/ext/io.rs @@ -54,126 +54,147 @@ pub trait IntoRawFd { #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl AsRawFd for RawFd { + #[inline] fn as_raw_fd(&self) -> RawFd { *self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl IntoRawFd for RawFd { + #[inline] fn into_raw_fd(self) -> RawFd { self } } #[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] impl FromRawFd for RawFd { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> RawFd { fd } } impl AsRawFd for net::TcpStream { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::TcpStream { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { net::TcpStream::from_inner(sys::net::TcpStream::from_inner(fd)) } } impl IntoRawFd for net::TcpStream { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for net::TcpListener { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::TcpListener { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { net::TcpListener::from_inner(sys::net::TcpListener::from_inner(fd)) } } impl IntoRawFd for net::TcpListener { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for net::UdpSocket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for net::UdpSocket { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(fd)) } } impl IntoRawFd for net::UdpSocket { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for fs::File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().fd().as_raw() } } impl FromRawFd for fs::File { + #[inline] unsafe fn from_raw_fd(fd: RawFd) -> fs::File { fs::File::from_inner(sys::fs::File::from_inner(fd)) } } impl IntoRawFd for fs::File { + #[inline] fn into_raw_fd(self) -> RawFd { self.into_inner().into_fd().into_raw() } } impl AsRawFd for io::Stdin { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO as RawFd } } impl AsRawFd for io::Stdout { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO as RawFd } } impl AsRawFd for io::Stderr { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO as RawFd } } impl<'a> AsRawFd for io::StdinLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO as RawFd } } impl<'a> AsRawFd for io::StdoutLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDOUT_FILENO as RawFd } } impl<'a> AsRawFd for io::StderrLock<'a> { + #[inline] fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO as RawFd } diff --git a/library/std/src/sys/windows/ext/io.rs b/library/std/src/sys/windows/ext/io.rs index e75f9a4bfd5e3..31b5d015ed0c3 100644 --- a/library/std/src/sys/windows/ext/io.rs +++ b/library/std/src/sys/windows/ext/io.rs @@ -59,6 +59,7 @@ pub trait IntoRawHandle { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawHandle for fs::File { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as RawHandle } @@ -108,6 +109,7 @@ impl<'a> AsRawHandle for io::StderrLock<'a> { #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawHandle for fs::File { + #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> fs::File { let handle = handle as c::HANDLE; fs::File::from_inner(sys::fs::File::from_inner(handle)) @@ -116,6 +118,7 @@ impl FromRawHandle for fs::File { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawHandle for fs::File { + #[inline] fn into_raw_handle(self) -> RawHandle { self.into_inner().into_handle().into_raw() as *mut _ } @@ -161,18 +164,21 @@ pub trait IntoRawSocket { #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpStream { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::TcpListener { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawSocket for net::UdpSocket { + #[inline] fn as_raw_socket(&self) -> RawSocket { *self.as_inner().socket().as_inner() } @@ -180,6 +186,7 @@ impl AsRawSocket for net::UdpSocket { #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpStream { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { let sock = sys::net::Socket::from_inner(sock); net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) @@ -187,6 +194,7 @@ impl FromRawSocket for net::TcpStream { } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::TcpListener { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { let sock = sys::net::Socket::from_inner(sock); net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) @@ -194,6 +202,7 @@ impl FromRawSocket for net::TcpListener { } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawSocket for net::UdpSocket { + #[inline] unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { let sock = sys::net::Socket::from_inner(sock); net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) @@ -202,6 +211,7 @@ impl FromRawSocket for net::UdpSocket { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::TcpStream { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } @@ -209,6 +219,7 @@ impl IntoRawSocket for net::TcpStream { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::TcpListener { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } @@ -216,6 +227,7 @@ impl IntoRawSocket for net::TcpListener { #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawSocket for net::UdpSocket { + #[inline] fn into_raw_socket(self) -> RawSocket { self.into_inner().into_socket().into_inner() } diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs index 67412e1677937..67756b15531bf 100644 --- a/library/std/src/sys/windows/ext/process.rs +++ b/library/std/src/sys/windows/ext/process.rs @@ -19,6 +19,7 @@ impl FromRawHandle for process::Stdio { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::Child { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -33,6 +34,7 @@ impl IntoRawHandle for process::Child { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStdin { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -40,6 +42,7 @@ impl AsRawHandle for process::ChildStdin { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStdout { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -47,6 +50,7 @@ impl AsRawHandle for process::ChildStdout { #[stable(feature = "process_extensions", since = "1.2.0")] impl AsRawHandle for process::ChildStderr { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } diff --git a/library/std/src/sys/windows/ext/thread.rs b/library/std/src/sys/windows/ext/thread.rs index 41c29f5b950ef..6bd02054f7150 100644 --- a/library/std/src/sys/windows/ext/thread.rs +++ b/library/std/src/sys/windows/ext/thread.rs @@ -8,6 +8,7 @@ use crate::thread; #[stable(feature = "thread_extensions", since = "1.9.0")] impl AsRawHandle for thread::JoinHandle { + #[inline] fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } @@ -15,6 +16,7 @@ impl AsRawHandle for thread::JoinHandle { #[stable(feature = "thread_extensions", since = "1.9.0")] impl IntoRawHandle for thread::JoinHandle { + #[inline] fn into_raw_handle(self) -> RawHandle { self.into_inner().into_handle().into_raw() as *mut _ } From 75bab0782a8b6377479bfd553f2f29fd5a8aac76 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Apr 2021 11:02:08 +0200 Subject: [PATCH 19/22] 'const fn' in trait are rejected in the AST, this feature gate check is a NOP --- compiler/rustc_ast_passes/src/feature_gate.rs | 7 +---- src/test/ui/consts/const-fn-not-in-trait.rs | 2 +- .../ui/feature-gates/feature-gate-const_fn.rs | 6 ++--- .../feature-gate-const_fn.stderr | 27 +++---------------- .../feature-gate-min_const_fn.rs | 6 ++--- .../feature-gate-min_const_fn.stderr | 27 +++---------------- 6 files changed, 14 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0679ccabe726c..077ab06d82dde 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -586,12 +586,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { let is_fn = match i.kind { - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => { - if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { - gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); - } - true - } + ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( diff --git a/src/test/ui/consts/const-fn-not-in-trait.rs b/src/test/ui/consts/const-fn-not-in-trait.rs index 1006d854688a4..cbc220a1ba29b 100644 --- a/src/test/ui/consts/const-fn-not-in-trait.rs +++ b/src/test/ui/consts/const-fn-not-in-trait.rs @@ -1,5 +1,5 @@ // Test that const fn is illegal in a trait declaration, whether or -// not a default is provided. +// not a default is provided, and even with the feature gate. #![feature(const_fn)] diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.rs b/src/test/ui/feature-gates/feature-gate-const_fn.rs index 691c367aeb859..b97aa214f843a 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // ok trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-const_fn.stderr b/src/test/ui/feature-gates/feature-gate-const_fn.stderr index 843e56301375a..1e7fd669b1d48 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:8:5 + --> $DIR/feature-gate-const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-const_fn.rs:13:5 + --> $DIR/feature-gate-const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs index 5a01e053ed038..8f9b433009d3c 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.rs +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.rs @@ -3,10 +3,8 @@ const fn foo() -> usize { 0 } // stabilized trait Foo { - const fn foo() -> u32; //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const - const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable - //~| ERROR functions in traits cannot be declared const + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const } impl Foo for u32 { diff --git a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr index 56a882e30fc4a..d7a58591364ed 100644 --- a/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr +++ b/src/test/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -5,36 +5,17 @@ LL | const fn foo() -> u32; | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:8:5 + --> $DIR/feature-gate-min_const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } | ^^^^^ functions in traits cannot be const error[E0379]: functions in traits cannot be declared const - --> $DIR/feature-gate-min_const_fn.rs:13:5 + --> $DIR/feature-gate-min_const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } | ^^^^^ functions in traits cannot be const -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:6:5 - | -LL | const fn foo() -> u32; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0658]: const fn is unstable - --> $DIR/feature-gate-min_const_fn.rs:8:5 - | -LL | const fn bar() -> u32 { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0379, E0658. -For more information about an error, try `rustc --explain E0379`. +For more information about this error, try `rustc --explain E0379`. From 34e51279ab5ea725431d930736b3a97cd22ad286 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Sun, 25 Apr 2021 11:58:59 +0200 Subject: [PATCH 20/22] Fix 'const-stable since' of reverse_bits --- library/core/src/num/int_macros.rs | 2 +- library/core/src/num/uint_macros.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 608deb49a9dbf..4b341132e31ec 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -254,7 +254,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")] #[inline(always)] #[must_use] pub const fn reverse_bits(self) -> Self { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 46638ea446316..08d9161eff112 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -257,7 +257,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[rustc_const_stable(feature = "const_math", since = "1.37.0")] #[inline(always)] #[must_use] pub const fn reverse_bits(self) -> Self { From 8a961a5b334a4f871093462823e8c86aab2611b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Apr 2021 12:19:06 +0200 Subject: [PATCH 21/22] remove const_fn from some error_code descriptions --- compiler/rustc_error_codes/src/error_codes/E0379.md | 2 -- compiler/rustc_error_codes/src/error_codes/E0764.md | 2 -- 2 files changed, 4 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md index 930204847ecd8..ab438e4144712 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0379.md +++ b/compiler/rustc_error_codes/src/error_codes/E0379.md @@ -3,8 +3,6 @@ A trait method was declared const. Erroneous code example: ```compile_fail,E0379 -#![feature(const_fn)] - trait Foo { const fn bar() -> u32; // error! } diff --git a/compiler/rustc_error_codes/src/error_codes/E0764.md b/compiler/rustc_error_codes/src/error_codes/E0764.md index 0a2e2290e77c2..152627cf6545f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0764.md +++ b/compiler/rustc_error_codes/src/error_codes/E0764.md @@ -3,7 +3,6 @@ A mutable reference was used in a constant. Erroneous code example: ```compile_fail,E0764 -#![feature(const_fn)] #![feature(const_mut_refs)] fn main() { @@ -27,7 +26,6 @@ Remember: you cannot use a function call inside a constant or static. However, you can totally use it in constant functions: ``` -#![feature(const_fn)] #![feature(const_mut_refs)] const fn foo(x: usize) -> usize { From ba9d1431185a97e6dfcb17df6a97abde68996e4c Mon Sep 17 00:00:00 2001 From: CohenArthur Date: Sun, 25 Apr 2021 14:10:57 +0200 Subject: [PATCH 22/22] liveness: Fix typo report_unsed_assign -> report_unused_assign --- compiler/rustc_passes/src/liveness.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index e22a108aaf07e..fa930471c2110 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1476,7 +1476,7 @@ impl<'tcx> Liveness<'_, 'tcx> { for p in body.params { self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| { if !self.live_on_entry(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value passed to `{}` is never read", name) }); } @@ -1615,13 +1615,13 @@ impl<'tcx> Liveness<'_, 'tcx> { fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { if !self.live_on_exit(ln, var) { - self.report_unsed_assign(hir_id, spans, var, |name| { + self.report_unused_assign(hir_id, spans, var, |name| { format!("value assigned to `{}` is never read", name) }); } } - fn report_unsed_assign( + fn report_unused_assign( &self, hir_id: HirId, spans: Vec,