From 756be4a052cf43d5dec2b7ee99e611d2127d989e Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 16 Apr 2021 03:14:05 +0300 Subject: [PATCH 01/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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 259a368e9eae8e9952d18e211d2fe0a7e5fae714 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 13:57:22 +0200 Subject: [PATCH 07/24] fix name resolution for param defaults --- compiler/rustc_resolve/src/diagnostics.rs | 11 --- compiler/rustc_resolve/src/late.rs | 69 +++++++++++-------- compiler/rustc_resolve/src/lib.rs | 58 +++------------- .../defaults/complex-generic-default-expr.rs | 9 +++ .../complex-generic-default-expr.stderr | 16 +++++ .../defaults/default-on-impl.rs | 9 +++ .../defaults/default-on-impl.stderr | 8 +++ .../defaults/pretty-printing-ast.rs | 3 +- .../defaults/pretty-printing-ast.stdout | 3 +- .../defaults/type-default-const-param-name.rs | 17 +++++ ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 23 +++++-- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 5 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 4 +- .../generics/generic-non-trailing-defaults.rs | 1 + .../generic-non-trailing-defaults.stderr | 9 ++- 15 files changed, 141 insertions(+), 104 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.rs create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.rs create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.stderr create mode 100644 src/test/ui/const-generics/defaults/type-default-const-param-name.rs diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 87e28f7fcc592..c5f12c0c691b3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -472,17 +472,6 @@ impl<'a> Resolver<'a> { ); err } - ResolutionError::ParamInAnonConstInTyDefault(name) => { - let mut err = self.session.struct_span_err( - span, - "constant values inside of type parameter defaults must not depend on generic parameters", - ); - err.span_label( - span, - format!("the anonymous constant must not depend on the parameter `{}`", name), - ); - err - } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9321f11f65933..92f21191de430 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind); - let mut found_default = false; - default_ban_rib.bindings.extend(generics.params.iter().filter_map( - |param| match param.kind { - GenericParamKind::Type { default: Some(_), .. } - | GenericParamKind::Const { default: Some(_), .. } => { - found_default = true; - Some((Ident::with_dummy_span(param.ident.name), Res::Err)) + let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind); + for param in generics.params.iter() { + match param.kind { + GenericParamKind::Type { .. } => { + forward_ty_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); } - _ => None, - }, - )); + GenericParamKind::Const { .. } => { + forward_const_ban_rib + .bindings + .insert(Ident::with_dummy_span(param.ident.name), Res::Err); + } + GenericParamKind::Lifetime => {} + } + } // rust-lang/rust#61631: The type `Self` is essentially // another type parameter. For ADTs, we consider it @@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // such as in the case of `trait Add`.) if self.diagnostic_metadata.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) - default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); + forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } for param in &generics.params { @@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } if let Some(ref ty) = default { - self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| { - // HACK: We use an empty `ForwardGenericParamBanRibKind` here which - // is only used to forbid the use of const parameters inside of - // type defaults. - // - // While the rib name doesn't really fit here, it does allow us to use the same - // code for both const and type parameters. - this.visit_ty(ty); - }); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_ty(ty); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); + forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { - // FIXME(const_generics_defaults): handle `default` value here - for bound in ¶m.bounds { - self.visit_param_bound(bound); - } + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + // Const parameters can't have param bounds. + assert!(param.bounds.is_empty()); + self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + + if let Some(ref expr) = default { + self.ribs[TypeNS].push(forward_ty_ban_rib); + self.ribs[ValueNS].push(forward_const_ban_rib); + self.visit_anon_const(expr); + forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap(); + forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this const parameter. + forward_const_ban_rib + .bindings + .remove(&Ident::with_dummy_span(param.ident.name)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 129954381c9ba..1d1969f7e78ab 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -239,8 +239,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), - /// constant values inside of type parameter defaults must not depend on generic parameters. - ParamInAnonConstInTyDefault(Symbol), /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. @@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> { } } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { - let mut in_ty_param_default = false; for rib in ribs { - let has_generic_params = match rib.kind { + let has_generic_params: HasGenericParams = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => { + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; } - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> { } } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } // This was an attempt to use a type parameter outside its scope. @@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> { ribs.next(); } - let mut in_ty_param_default = false; for rib in ribs { let has_generic_params = match rib.kind { NormalRibKind | ClosureOrAsyncRibKind | AssocItemRibKind | ModuleRibKind(..) - | MacroDefinition(..) => continue, - - // We only forbid constant items if we are inside of type defaults, - // for example `struct Foo()]>` - ForwardGenericParamBanRibKind => { - // FIXME(const_generic_defaults): we may need to distinguish between - // being in type parameter defaults and const parameter defaults - in_ty_param_default = true; - continue; - } + | MacroDefinition(..) + | ForwardGenericParamBanRibKind => continue, + ConstantItemRibKind(trivial, _) => { let features = self.session.features_untracked(); // HACK(min_const_generics): We currently only allow `N` or `{ N }`. @@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> { return Res::Err; } - if in_ty_param_default { - if record_used { - self.report_error( - span, - ResolutionError::ParamInAnonConstInTyDefault( - rib_ident.name, - ), - ); - } - return Res::Err; - } else { - continue; - } + continue; } ItemRibKind(has_generic_params) => has_generic_params, diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 0000000000000..ba00e4b15ca15 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +struct Bar() }>(T); +//~^ ERROR the size for values of type `T` cannot be known at compilation time + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr new file mode 100644 index 0000000000000..06865fdd8fd3a --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/complex-generic-default-expr.rs:6:62 + | +LL | struct Bar() }>(T); + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 0000000000000..2555450a9e7f8 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.stderr new file mode 100644 index 0000000000000..b30b18a7b3c71 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:6:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index a25d4baca1a97..12a92a10476d5 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -10,4 +10,5 @@ trait Foo {} fn foo() {} -struct Range; +struct Range; + diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index f7a1d2ca4b2ef..c514bbe72e1d8 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -17,4 +17,5 @@ trait Foo { } fn foo() { } struct Range; + FROM>; + diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 0000000000000..c0c83cda285da --- /dev/null +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_generics, const_generics_defaults)] +#![allow(incomplete_features)] + +struct N; + +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index c2b7b206653a6..d8bfab6aa52c8 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -6,17 +6,26 @@ LL | struct Bar(T); | = note: using type defaults and const parameters in the same parameter list is currently not permitted -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + | +LL | struct Bar(T); + | ^ defaulted generic parameters cannot be forward declared + +error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 | LL | struct Foo()]>(T, U); - | ^ the anonymous constant must not depend on the parameter `T` - -error: constant values inside of type parameter defaults must not depend on generic parameters - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL | -LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` error: aborting due to 3 previous errors +Some errors have detailed explanations: E0128, E0277. +For more information about an error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4a462c328bf64..44393a30266d6 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -15,11 +15,12 @@ LL | struct Foo()]>(T, U); = note: type parameters may not be used in const expressions = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions -error: constant values inside of type parameter defaults must not depend on generic parameters +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 | LL | struct Bar(T); - | ^ the anonymous constant must not depend on the parameter `N` + | ^ defaulted generic parameters cannot be forward declared error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index c7be8bdaf9c3d..8a84afd065c1e 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -4,12 +4,12 @@ #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR constant values inside of type parameter defaults +//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time //[min]~^^ ERROR generic parameters may not be used in const operations // FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); -//~^ ERROR constant values inside of type parameter defaults +//~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index cb2bb2832b70e..16ea71d48c825 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -5,5 +5,6 @@ struct Vec(A, T); struct Foo, C>(A, B, C); //~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index 6d76861750335..713ba091b861c 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing LL | struct Foo, C>(A, B, C); | ^ -error: aborting due to 2 previous errors +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-non-trailing-defaults.rs:6:23 + | +LL | struct Foo, C>(A, B, C); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0128`. From 7cb1dcd48802378929032ad9363c296891443d76 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 14:31:00 +0200 Subject: [PATCH 08/24] loosen ordering restricts for `const_generics_defaults` --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_feature/src/active.rs | 4 ++ compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_middle/src/ty/generics.rs | 2 +- compiler/rustc_typeck/src/astconv/generics.rs | 6 ++- .../defaults/auxiliary/const_defaulty.rs | 2 +- ... complex-generic-default-expr.full.stderr} | 2 +- .../complex-generic-default-expr.min.stderr | 20 +++++++ .../defaults/complex-generic-default-expr.rs | 8 ++- .../const-generics/defaults/const-default.rs | 4 +- ...mpl.stderr => default-on-impl.full.stderr} | 2 +- .../defaults/default-on-impl.min.stderr | 8 +++ .../defaults/default-on-impl.rs | 4 +- .../ui/const-generics/defaults/external.rs | 2 + .../defaults/intermixed-lifetime.full.stderr | 2 +- .../defaults/intermixed-lifetime.min.stderr | 22 ++------ .../defaults/intermixed-lifetime.rs | 10 ++-- .../{mismatch.stderr => mismatch.full.stderr} | 10 ++-- .../defaults/mismatch.min.stderr | 52 +++++++++++++++++++ .../ui/const-generics/defaults/mismatch.rs | 3 +- .../defaults/pretty-printing-ast.stdout | 1 - .../defaults/repr-c-issue-82792.rs | 2 +- .../defaults/simple-defaults.min.stderr | 8 --- .../defaults/simple-defaults.rs | 10 ++-- .../defaults/type-default-const-param-name.rs | 4 +- .../defaults/wrong-order.full.stderr | 15 +----- .../defaults/wrong-order.min.stderr | 4 +- .../ui/const-generics/defaults/wrong-order.rs | 4 +- ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 4 +- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 4 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 1 - 31 files changed, 145 insertions(+), 81 deletions(-) rename src/test/ui/const-generics/defaults/{complex-generic-default-expr.stderr => complex-generic-default-expr.full.stderr} (93%) create mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr rename src/test/ui/const-generics/defaults/{default-on-impl.stderr => default-on-impl.full.stderr} (85%) create mode 100644 src/test/ui/const-generics/defaults/default-on-impl.min.stderr rename src/test/ui/const-generics/defaults/{mismatch.stderr => mismatch.full.stderr} (90%) create mode 100644 src/test/ui/const-generics/defaults/mismatch.min.stderr delete mode 100644 src/test/ui/const-generics/defaults/simple-defaults.min.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index bb09f701531cf..e79392adf74b8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -754,7 +754,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().const_generics; + let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) } }; diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 6fd1af60fe2d8..80f237148c3d2 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -63,6 +63,10 @@ macro_rules! declare_features { _ => panic!("`{}` was not listed in `declare_features`", feature), } } + + pub fn unordered_const_ty_params(&self) -> bool { + self.const_generics || self.const_generics_defaults + } } }; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1051fb8cea279..a70be14546b41 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -296,7 +296,9 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + GenericArg::Const(_) => { + ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } + } } } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index d30a8693959f3..c8fdbc30d1591 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -36,7 +36,7 @@ impl GenericParamDefKind { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, GenericParamDefKind::Const { .. } => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } } } } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 7a297f2c65f13..2bbb38c294d57 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -286,7 +286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ParamKindOrd::Const { unordered: tcx .features() - .const_generics, + .unordered_const_ty_params(), } } }, @@ -309,7 +309,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx.features().const_generics, + unordered: tcx + .features() + .unordered_const_ty_params(), }, }), Some(&format!( diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs index 769b6e952dc9c..6514409698e3e 100644 --- a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -1,4 +1,4 @@ -#![feature(const_generics)] +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr similarity index 93% rename from src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr rename to src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr index 06865fdd8fd3a..c1444abbd3f32 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/complex-generic-default-expr.rs:6:62 + --> $DIR/complex-generic-default-expr.rs:9:62 | LL | struct Bar() }>(T); | - ^ doesn't have a size known at compile-time diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 0000000000000..d50a0a61d4949 --- /dev/null +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:9:62 + | +LL | struct Bar() }>(T); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index ba00e4b15ca15..1c25fda8d30ca 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,9 +1,13 @@ -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; +//[min]~^ ERROR generic parameters may not be used in const operations struct Bar() }>(T); -//~^ ERROR the size for values of type `T` cannot be known at compilation time +//[min]~^ ERROR generic parameters may not be used in const operations +//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs index 150c70770ae51..4fa21b8b1fb78 100644 --- a/src/test/ui/const-generics/defaults/const-default.rs +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -1,6 +1,6 @@ // run-pass - -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr similarity index 85% rename from src/test/ui/const-generics/defaults/default-on-impl.stderr rename to src/test/ui/const-generics/defaults/default-on-impl.full.stderr index b30b18a7b3c71..c417a26842ed1 100644 --- a/src/test/ui/const-generics/defaults/default-on-impl.stderr +++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr @@ -1,5 +1,5 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/default-on-impl.rs:6:12 + --> $DIR/default-on-impl.rs:8:12 | LL | impl Foo {} | ^ diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr new file mode 100644 index 0000000000000..c417a26842ed1 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:8:12 + | +LL | impl Foo {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs index 2555450a9e7f8..735549defeaf0 100644 --- a/src/test/ui/const-generics/defaults/default-on-impl.rs +++ b/src/test/ui/const-generics/defaults/default-on-impl.rs @@ -1,4 +1,6 @@ -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs index b39e69ab10b66..32acf567cf2b9 100644 --- a/src/test/ui/const-generics/defaults/external.rs +++ b/src/test/ui/const-generics/defaults/external.rs @@ -1,5 +1,7 @@ // aux-build:const_defaulty.rs // check-pass +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr index c4a666a829d8c..29d835e36c6eb 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr @@ -1,5 +1,5 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo(&'a (), T); | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr index 69a490978d1df..985e7b655ece9 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr @@ -1,26 +1,14 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:28 + --> $DIR/intermixed-lifetime.rs:7:28 | LL | struct Foo(&'a (), T); - | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:6:32 - | -LL | struct Foo(&'a (), T); - | ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: lifetime parameters must be declared prior to const parameters +error: lifetime parameters must be declared prior to type parameters --> $DIR/intermixed-lifetime.rs:10:37 | LL | struct Bar(&'a (), T); - | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: type parameters must be declared prior to const parameters - --> $DIR/intermixed-lifetime.rs:10:28 - | -LL | struct Bar(&'a (), T); - | -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` + | --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs index 9e83bf92a59b9..307e3aaf1fbf3 100644 --- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs +++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs @@ -1,15 +1,13 @@ -// revisions: full min // Checks that lifetimes cannot be interspersed between consts and types. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct Foo(&'a (), T); //~^ Error lifetime parameters must be declared prior to const parameters -//[min]~^^ Error type parameters must be declared prior to const parameters struct Bar(&'a (), T); -//[full]~^ Error lifetime parameters must be declared prior to type parameters -//[min]~^^ Error type parameters must be declared prior to const parameters -//[min]~| Error lifetime parameters must be declared prior to const parameters +//~^ Error lifetime parameters must be declared prior to type parameters fn main() {} diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr similarity index 90% rename from src/test/ui/const-generics/defaults/mismatch.stderr rename to src/test/ui/const-generics/defaults/mismatch.full.stderr index ff72c71c40f0f..be4f364d8ee62 100644 --- a/src/test/ui/const-generics/defaults/mismatch.stderr +++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatch.rs:11:28 + --> $DIR/mismatch.rs:12:28 | LL | let e: Example::<13> = (); | ------------- ^^ expected struct `Example`, found `()` @@ -7,7 +7,7 @@ LL | let e: Example::<13> = (); | expected due to this error[E0308]: mismatched types - --> $DIR/mismatch.rs:13:34 + --> $DIR/mismatch.rs:14:34 | LL | let e: Example2:: = (); | ------------------- ^^ expected struct `Example2`, found `()` @@ -18,7 +18,7 @@ LL | let e: Example2:: = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:15:34 + --> $DIR/mismatch.rs:16:34 | LL | let e: Example3::<13, u32> = (); | ------------------- ^^ expected struct `Example3`, found `()` @@ -29,7 +29,7 @@ LL | let e: Example3::<13, u32> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:17:28 + --> $DIR/mismatch.rs:18:28 | LL | let e: Example3::<7> = (); | ------------- ^^ expected struct `Example3`, found `()` @@ -40,7 +40,7 @@ LL | let e: Example3::<7> = (); found unit type `()` error[E0308]: mismatched types - --> $DIR/mismatch.rs:21:28 + --> $DIR/mismatch.rs:22:28 | LL | let e: Example4::<7> = (); | ------------- ^^ expected struct `Example4`, found `()` diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr new file mode 100644 index 0000000000000..be4f364d8ee62 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:12:28 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:14:34 + | +LL | let e: Example2:: = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:34 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:18:28 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:22:28 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs index d85b756f538dc..68a640c0a08b3 100644 --- a/src/test/ui/const-generics/defaults/mismatch.rs +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -1,4 +1,5 @@ -#![feature(const_generics)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout index c514bbe72e1d8..f549993c413d4 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -18,4 +18,3 @@ fn foo() { } struct Range; - diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs index 18ecf46729977..c64c2974c8f8f 100644 --- a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs +++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -6,7 +6,7 @@ #![allow(incomplete_features)] #[repr(C)] -pub struct Loaf { +pub struct Loaf { head: [T; N], slice: [T], } diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr deleted file mode 100644 index 0746c64ac8cf4..0000000000000 --- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: type parameters must be declared prior to const parameters - --> $DIR/simple-defaults.rs:8:40 - | -LL | struct FixedOutput<'a, const N: usize, T=u32> { - | ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>` - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs index cb66c7769bb23..c003cb2c5a6ee 100644 --- a/src/test/ui/const-generics/defaults/simple-defaults.rs +++ b/src/test/ui/const-generics/defaults/simple-defaults.rs @@ -1,12 +1,12 @@ -// [full] run-pass -// revisions: min full -// Checks some basic test cases for defaults. +// run-pass +// Checks that type param defaults are allowed after const params. +// revisions: full min #![cfg_attr(full, feature(const_generics))] -#![cfg_attr(full, allow(incomplete_features))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] #![allow(dead_code)] struct FixedOutput<'a, const N: usize, T=u32> { - //[min]~^ ERROR type parameters must be declared prior to const parameters out: &'a [T; N], } diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs index c0c83cda285da..e68075ee3c627 100644 --- a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs +++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs @@ -1,5 +1,7 @@ // check-pass -#![feature(const_generics, const_generics_defaults)] +// revisions: full min +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] struct N; diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index accc73134d899..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,19 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted - -warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wrong-order.rs:2:27 - | -LL | #![cfg_attr(full, feature(const_generics))] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44580 for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index c8f1d471b244b..eb0bcb2821556 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,10 +1,8 @@ error: generic parameters with a default must be trailing - --> $DIR/wrong-order.rs:4:10 + --> $DIR/wrong-order.rs:6:10 | LL | struct A { | ^ - | - = note: using type defaults and const parameters in the same parameter list is currently not permitted error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 5c2d9b8ad4751..88e9e96ba43f9 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -1,5 +1,7 @@ // revisions: full min -#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete +#![cfg_attr(full, feature(const_generics))] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] struct A { //~^ ERROR generic parameters with a default must be trailing diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index d8bfab6aa52c8..cf947a565c454 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 44393a30266d6..4c97012f36185 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 | LL | struct Bar(T); | ^ @@ -16,7 +16,7 @@ LL | struct Foo()]>(T, U); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index 8a84afd065c1e..bf4f9558adc26 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -7,7 +7,6 @@ struct Foo()]>(T, U); //[full]~^ ERROR the size for values of type `T` cannot be known at compilation time //[min]~^^ ERROR generic parameters may not be used in const operations -// FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); //~^ ERROR generic parameters with a default cannot use forward declared identifiers //~| ERROR generic parameters with a default From 312b4fdfd281a5ebd740acaf88cc82c47225be23 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 15:14:17 +0200 Subject: [PATCH 09/24] improve wf check for const param defaults --- compiler/rustc_typeck/src/check/wfcheck.rs | 53 ++++++++++++++----- .../complex-generic-default-expr.min.stderr | 4 +- .../defaults/complex-generic-default-expr.rs | 8 ++- .../defaults/const-param-as-default-value.rs | 14 +++++ .../defaults/const-param-in-ty-defaults.rs | 18 +++++++ .../defaults/default-param-wf-concrete.rs | 5 ++ .../defaults/default-param-wf-concrete.stderr | 9 ++++ .../defaults/pretty-printing-ast.rs | 1 - 8 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/const-param-as-default-value.rs create mode 100644 src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.rs create mode 100644 src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 887cc42a1dd27..26871d6f0285c 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -728,20 +728,36 @@ fn check_where_clauses<'tcx, 'fcx>( // // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. for param in &generics.params { - if let GenericParamDefKind::Type { .. } = param.kind { - if is_our_default(¶m) { - let ty = fcx.tcx.type_of(param.def_id); - // Ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ``). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + match param.kind { + GenericParamDefKind::Type { .. } => { + if is_our_default(¶m) { + let ty = fcx.tcx.type_of(param.def_id); + // Ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ``). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation( + ty.into(), + fcx.tcx.def_span(param.def_id), + ObligationCauseCode::MiscObligation, + ); + } + } + } + GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): Figure out if this + // is the behavior we want, see the comment further below. + if is_our_default(¶m) { + let default_ct = tcx.const_param_default(param.def_id); fcx.register_wf_obligation( - ty.into(), + default_ct.into(), fcx.tcx.def_span(param.def_id), ObligationCauseCode::MiscObligation, ); } } + // Doesn't have defaults. + GenericParamDefKind::Lifetime => {} } } @@ -774,14 +790,25 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } GenericParamDefKind::Const { .. } => { + // FIXME(const_generics_defaults): I(@lcnr) feel like always + // using the const parameter is the right choice here, even + // if it needs substs. + // + // Before stabilizing this we probably want to get some tests + // where this makes a difference and figure out what's the exact + // behavior we want here. + + // If the param has a default, ... if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id); - // Const params currently have to be concrete. - assert!(!default_ct.needs_subst()); - default_ct.into() - } else { - fcx.tcx.mk_param_from_def(param) + // ... and it's not a dependent default, ... + if !default_ct.needs_subst() { + // ... then substitute it with the default. + return default_ct.into(); + } } + + fcx.tcx.mk_param_from_def(param) } } }); diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index d50a0a61d4949..7d51e9aa0f3be 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:6:47 + --> $DIR/complex-generic-default-expr.rs:10:47 | LL | struct Foo; | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct Foo; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:9:62 + --> $DIR/complex-generic-default-expr.rs:13:62 | LL | struct Bar() }>(T); | ^ cannot perform const operation using `T` diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index 1c25fda8d30ca..a1c04b5e7c387 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,4 +1,8 @@ -// revisions: full min +// revisions: min +// FIXME(const_generics): add the `full` revision, +// currently causes an ICE as we don't supply substs to +// anon consts in the parameter listing, as that would +// cause that anon const to reference itself. #![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] @@ -8,6 +12,6 @@ struct Foo; struct Bar() }>(T); //[min]~^ ERROR generic parameters may not be used in const operations -//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time +//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 0000000000000..d9cab34327e9d --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo([u8; N], [u8; M]); + +fn foo() -> Foo { + let x = [0; N]; + Foo(x, x) +} + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); +} diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 0000000000000..e3d78fe2ee0ea --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +// FIXME(const_generics_defaults): while we can allow this, +// we probably won't easily allow this with more complex const operations. +// +// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering. +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 0000000000000..4bb56c6a1c08c --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,5 @@ +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 0000000000000..8464ea98bf695 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:3:28 + | +LL | struct Foo; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs index 12a92a10476d5..7a57950dfc924 100644 --- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -11,4 +11,3 @@ trait Foo {} fn foo() {} struct Range; - From d3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 18 Apr 2021 16:43:43 +0200 Subject: [PATCH 10/24] supply substs to anon consts in defaults --- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 +- compiler/rustc_typeck/src/collect.rs | 39 +++++++++---------- .../complex-generic-default-expr.full.stderr | 24 ++++++------ .../complex-generic-default-expr.min.stderr | 4 +- .../defaults/complex-generic-default-expr.rs | 13 +++---- .../defaults/const-param-as-default-value.rs | 9 +++++ .../defaults/const-param-in-ty-defaults.rs | 4 -- ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 22 ++--------- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 6 +-- .../params-in-ct-in-ty-param-lazy-norm.rs | 4 +- 11 files changed, 62 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index b6de491911ab7..62a1584d16be0 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { if infer_args { self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 9ace455042103..a50f8e1c65599 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default, .. } => { if !infer_args && has_default { - tcx.const_param_default(param.def_id).into() + tcx.const_param_default(param.def_id) + .subst_spanned(tcx, substs.unwrap(), Some(self.span)) + .into() } else { self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1477418d5d8cf..927d8c57191a7 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1316,13 +1316,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option Visitor<'v> for AnonConstInParamListDetector { +impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1330,15 +1330,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - let prev = self.in_param_list; - self.in_param_list = true; - intravisit::walk_generic_param(self, p); - self.in_param_list = prev; + if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + let prev = self.in_param_ty; + self.in_param_ty = true; + self.visit_ty(ty); + self.in_param_ty = prev; + } } fn visit_anon_const(&mut self, c: &'v hir::AnonConst) { - if self.in_param_list && self.ct == c.hir_id { - self.found_anon_const_in_list = true; + if self.in_param_ty && self.ct == c.hir_id { + self.found_anon_const_in_param_ty = true; } else { intravisit::walk_anon_const(self, c) } @@ -1366,27 +1368,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let mut in_param_list = false; + let mut in_param_ty = false; for (_parent, node) in tcx.hir().parent_iter(hir_id) { if let Some(generics) = node.generics() { - let mut visitor = AnonConstInParamListDetector { - in_param_list: false, - found_anon_const_in_list: false, + let mut visitor = AnonConstInParamTyDetector { + in_param_ty: false, + found_anon_const_in_param_ty: false, ct: hir_id, }; visitor.visit_generics(generics); - in_param_list = visitor.found_anon_const_in_list; + in_param_ty = visitor.found_anon_const_in_param_ty; break; } } - if in_param_list { + if in_param_ty { // We do not allow generic parameters in anon consts if we are inside - // of a param list. - // - // This affects both default type bindings, e.g. `struct()]>(T, U)`, - // and the types of const parameters, e.g. `struct V();`. + // of a const parameter type, e.g. `struct Foo` is not allowed. None } else if tcx.lazy_normalization() { // HACK(eddyb) this provides the correct generics when diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr index c1444abbd3f32..e0e2b6c69f280 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr @@ -1,16 +1,18 @@ -error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/complex-generic-default-expr.rs:9:62 +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:6:34 + | +LL | struct Foo; + | ^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/complex-generic-default-expr.rs:10:21 | LL | struct Bar() }>(T); - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `std::marker::Sized` - | - ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | ^^^^^^^^^ | -LL | pub const fn size_of() -> usize { - | - required by this bound in `std::mem::size_of` + = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index 7d51e9aa0f3be..58abd8db9f09f 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:10:47 + --> $DIR/complex-generic-default-expr.rs:6:47 | LL | struct Foo; | ^ cannot perform const operation using `N` @@ -8,7 +8,7 @@ LL | struct Foo; = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:13:62 + --> $DIR/complex-generic-default-expr.rs:10:62 | LL | struct Bar() }>(T); | ^ cannot perform const operation using `T` diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index a1c04b5e7c387..a7b712f7b4b86 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,17 +1,14 @@ -// revisions: min -// FIXME(const_generics): add the `full` revision, -// currently causes an ICE as we don't supply substs to -// anon consts in the parameter listing, as that would -// cause that anon const to reference itself. +// revisions: full min #![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; -//[min]~^ ERROR generic parameters may not be used in const operations +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations struct Bar() }>(T); -//[min]~^ ERROR generic parameters may not be used in const operations -//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time +//[full]~^ ERROR constant expression depends on a generic parameter +//[min]~^^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs index d9cab34327e9d..59ac261f44fd5 100644 --- a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs +++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs @@ -8,7 +8,16 @@ fn foo() -> Foo { Foo(x, x) } +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + fn main() { let val = foo::<13>(); assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); } diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs index e3d78fe2ee0ea..3f534ca0308ba 100644 --- a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs +++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -1,10 +1,6 @@ // run-pass #![feature(const_generics_defaults)] #![allow(incomplete_features)] -// FIXME(const_generics_defaults): while we can allow this, -// we probably won't easily allow this with more complex const operations. -// -// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering. struct Foo(T); impl Foo { diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index cf947a565c454..e8fd9e7769b79 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ @@ -7,25 +7,11 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared -error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 - | -LL | struct Foo()]>(T, U); - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `std::marker::Sized` - | - ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | pub const fn size_of() -> usize { - | - required by this bound in `std::mem::size_of` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0128, E0277. -For more information about an error, try `rustc --explain E0128`. +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 4c97012f36185..5fa6423306c5a 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,5 +1,5 @@ error: generic parameters with a default must be trailing - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 | LL | struct Bar(T); | ^ @@ -7,7 +7,7 @@ LL | struct Bar(T); = note: using type defaults and const parameters in the same parameter list is currently not permitted error: generic parameters may not be used in const operations - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 | LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` @@ -16,7 +16,7 @@ LL | struct Foo()]>(T, U); = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21 + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 | LL | struct Bar(T); | ^ defaulted generic parameters cannot be forward declared diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index bf4f9558adc26..76c1b84aef557 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -1,11 +1,9 @@ // revisions: full min - #![cfg_attr(full, feature(const_generics))] #![cfg_attr(full, allow(incomplete_features))] struct Foo()]>(T, U); -//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations struct Bar(T); //~^ ERROR generic parameters with a default cannot use forward declared identifiers From 00c95a3d1212491793865e7f6f97486eafe59383 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 Apr 2021 16:50:07 +0200 Subject: [PATCH 11/24] update Miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index a86eab3e6c3d6..58436e942a9f3 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a86eab3e6c3d645769bfdb2d09efd84d1e1fcbc0 +Subproject commit 58436e942a9f301748a2d7e88e6184e168cfcfbd From e4ce655cbf11dded14af67a9d8201207c6d18c1f Mon Sep 17 00:00:00 2001 From: Smitty Date: Fri, 23 Apr 2021 13:29:18 -0400 Subject: [PATCH 12/24] 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 13/24] 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 14/24] 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 15/24] 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 16/24] 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 17/24] 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 18/24] 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 19/24] 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 20/24] 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 21/24] 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 22/24] 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 75bab0782a8b6377479bfd553f2f29fd5a8aac76 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Apr 2021 11:02:08 +0200 Subject: [PATCH 23/24] '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 8a961a5b334a4f871093462823e8c86aab2611b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Apr 2021 12:19:06 +0200 Subject: [PATCH 24/24] 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 {