From 2d438d6993017ae2b991cd92ea243112e2357c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Aug 2019 10:15:57 -0700 Subject: [PATCH 01/20] Correctly suggest adding bounds to `impl Trait` argument --- src/librustc_typeck/check/method/suggest.rs | 14 +++++++++++-- ...ait-with-missing-trait-bounds-in-arg.fixed | 20 +++++++++++++++++++ ...-trait-with-missing-trait-bounds-in-arg.rs | 20 +++++++++++++++++++ ...it-with-missing-trait-bounds-in-arg.stderr | 15 ++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 53024d97c3b13..9f4fed23697ab 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -743,8 +743,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. let mut has_bounds = false; + let mut impl_trait = false; if let Node::GenericParam(ref param) = hir.get(id) { - has_bounds = !param.bounds.is_empty(); + match param.kind { + hir::GenericParamKind::Type { synthetic: Some(_), .. } => { + impl_trait = true; // #63706 + has_bounds = param.bounds.len() > 1; + } + _ => { + has_bounds = !param.bounds.is_empty(); + } + } } let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers @@ -765,8 +774,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, &msg[..], candidates.iter().map(|t| format!( - "{}: {}{}", + "{}{} {}{}", param, + if impl_trait { " +" } else { ":" }, self.tcx.def_path_str(t.def_id), if has_bounds { " +"} else { "" }, )), diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 0000000000000..5109511f95a6b --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 0000000000000..cd05b77386192 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 0000000000000..48c2503e8eb32 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `hello` found for type `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | foo.hello(); + | ^^^^^ + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 055f7e2ec23f36e522e318a64eab414caba55e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Aug 2019 13:45:18 -0700 Subject: [PATCH 02/20] Extend comment --- src/librustc_typeck/check/method/suggest.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9f4fed23697ab..440e7e5d0e314 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -747,7 +747,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Node::GenericParam(ref param) = hir.get(id) { match param.kind { hir::GenericParamKind::Type { synthetic: Some(_), .. } => { - impl_trait = true; // #63706 + // We've found `fn foo(x: impl Trait)` instead of + // `fn foo(x: T)`. We want to suggest the correct + // `fn foo(x: impl Trait + TraitBound)` instead of + // `fn foo(x: T)`. (#63706) + impl_trait = true; has_bounds = param.bounds.len() > 1; } _ => { From 5cc1559c600f34f534fa3e0328ca1c2659562229 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 10:14:07 +0200 Subject: [PATCH 03/20] token: refactor with is_non_raw_ident_where. --- src/libsyntax/parse/token.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1865f925165bd..dfea34c331ad4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -409,7 +409,7 @@ impl Token { crate fn expect_lit(&self) -> Lit { match self.kind { Literal(lit) => lit, - _=> panic!("`expect_lit` called on non-literal"), + _ => panic!("`expect_lit` called on non-literal"), } } @@ -457,6 +457,7 @@ impl Token { pub fn is_ident(&self) -> bool { self.ident().is_some() } + /// Returns `true` if the token is a lifetime. crate fn is_lifetime(&self) -> bool { self.lifetime().is_some() @@ -508,45 +509,38 @@ impl Token { /// Returns `true` if the token is a given keyword, `kw`. pub fn is_keyword(&self, kw: Symbol) -> bool { - self.ident().map(|(id, is_raw)| id.name == kw && !is_raw).unwrap_or(false) + self.is_non_raw_ident_where(|id| id.name == kw) } crate fn is_path_segment_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_path_segment_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword) } // Returns true for reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. crate fn is_special_ident(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_special(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_special) } /// Returns `true` if the token is a keyword used in the language. crate fn is_used_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_used_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_used_keyword) } /// Returns `true` if the token is a keyword reserved for possible future use. crate fn is_unused_keyword(&self) -> bool { - match self.ident() { - Some((id, false)) => id.is_unused_keyword(), - _ => false, - } + self.is_non_raw_ident_where(ast::Ident::is_unused_keyword) } /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { + self.is_non_raw_ident_where(ast::Ident::is_reserved) + } + + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. + fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { match self.ident() { - Some((id, false)) => id.is_reserved(), + Some((id, false)) => pred(id), _ => false, } } From e49b9581baba9d89519d17ac0d8400b6ae77e754 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 10:21:41 +0200 Subject: [PATCH 04/20] Simplify with Symbol/Token::is_book_lit. --- src/libsyntax/parse/literal.rs | 4 ++-- src/libsyntax/parse/parser/path.rs | 2 +- src/libsyntax/parse/token.rs | 11 +++++++---- src/libsyntax_pos/symbol.rs | 5 +++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 6409acba573ad..36233de3cfb57 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -104,7 +104,7 @@ impl LitKind { Ok(match kind { token::Bool => { - assert!(symbol == kw::True || symbol == kw::False); + assert!(symbol.is_bool_lit()); LitKind::Bool(symbol == kw::True) } token::Byte => return unescape_byte(&symbol.as_str()) @@ -261,7 +261,7 @@ impl Lit { /// Converts arbitrary token into an AST literal. crate fn from_token(token: &Token) -> Result { let lit = match token.kind { - token::Ident(name, false) if name == kw::True || name == kw::False => + token::Ident(name, false) if name.is_bool_lit() => token::Lit::new(token::Bool, name, None), token::Literal(lit) => lit, diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 3eb4d45045a9e..d4b13cc2e0121 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -423,7 +423,7 @@ impl<'a> Parser<'a> { // FIXME(const_generics): to distinguish between idents for types and consts, // we should introduce a GenericArg::Ident in the AST and distinguish when // lowering to the HIR. For now, idents for const args are not permitted. - if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) { + if self.token.is_bool_lit() { self.parse_literal_maybe_minus()? } else { return Err( diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index dfea34c331ad4..fe3b51aa246b8 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -417,10 +417,8 @@ impl Token { /// for example a '-42', or one of the boolean idents). crate fn can_begin_literal_or_bool(&self) -> bool { match self.kind { - Literal(..) => true, - BinOp(Minus) => true, - Ident(name, false) if name == kw::True => true, - Ident(name, false) if name == kw::False => true, + Literal(..) | BinOp(Minus) => true, + Ident(name, false) if name.is_bool_lit() => true, Interpolated(ref nt) => match **nt { NtLiteral(..) => true, _ => false, @@ -537,6 +535,11 @@ impl Token { self.is_non_raw_ident_where(ast::Ident::is_reserved) } + /// Returns `true` if the token is the identifier `true` or `false`. + crate fn is_bool_lit(&self) -> bool { + self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool { match self.ident() { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 0b8f16bbc3b99..856857f74e352 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1063,6 +1063,11 @@ impl Symbol { self == kw::DollarCrate } + /// Returns `true` if the symbol is `true` or `false`. + pub fn is_bool_lit(self) -> bool { + self == kw::True || self == kw::False + } + /// This symbol can be a raw identifier. pub fn can_be_raw(self) -> bool { self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword() From f908aa9e8000dd7fd2c3de54fe1d914fddf4fe92 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 13:04:48 +0200 Subject: [PATCH 05/20] recover on 'mut ' and improve recovery for keywords. --- src/libsyntax/parse/parser/pat.rs | 136 ++++++++++++++---- .../keyword-extern-as-identifier-pat.rs | 2 +- .../keyword-extern-as-identifier-pat.stderr | 8 +- src/test/ui/parser/issue-32501.rs | 3 +- src/test/ui/parser/issue-32501.stderr | 6 +- src/test/ui/parser/keyword-abstract.rs | 2 +- src/test/ui/parser/keyword-abstract.stderr | 8 +- .../ui/parser/keyword-as-as-identifier.rs | 2 +- .../ui/parser/keyword-as-as-identifier.stderr | 8 +- .../ui/parser/keyword-break-as-identifier.rs | 2 +- .../parser/keyword-break-as-identifier.stderr | 8 +- .../ui/parser/keyword-const-as-identifier.rs | 2 +- .../parser/keyword-const-as-identifier.stderr | 8 +- .../parser/keyword-continue-as-identifier.rs | 2 +- .../keyword-continue-as-identifier.stderr | 8 +- .../ui/parser/keyword-else-as-identifier.rs | 2 +- .../parser/keyword-else-as-identifier.stderr | 8 +- .../ui/parser/keyword-enum-as-identifier.rs | 2 +- .../parser/keyword-enum-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-final.rs | 2 +- src/test/ui/parser/keyword-final.stderr | 8 +- .../ui/parser/keyword-fn-as-identifier.rs | 2 +- .../ui/parser/keyword-fn-as-identifier.stderr | 8 +- .../ui/parser/keyword-for-as-identifier.rs | 2 +- .../parser/keyword-for-as-identifier.stderr | 8 +- .../ui/parser/keyword-if-as-identifier.rs | 2 +- .../ui/parser/keyword-if-as-identifier.stderr | 8 +- .../ui/parser/keyword-impl-as-identifier.rs | 2 +- .../parser/keyword-impl-as-identifier.stderr | 8 +- .../ui/parser/keyword-let-as-identifier.rs | 2 +- .../parser/keyword-let-as-identifier.stderr | 8 +- .../ui/parser/keyword-loop-as-identifier.rs | 2 +- .../parser/keyword-loop-as-identifier.stderr | 8 +- .../ui/parser/keyword-match-as-identifier.rs | 2 +- .../parser/keyword-match-as-identifier.stderr | 8 +- .../ui/parser/keyword-mod-as-identifier.rs | 2 +- .../parser/keyword-mod-as-identifier.stderr | 8 +- .../ui/parser/keyword-move-as-identifier.rs | 2 +- .../parser/keyword-move-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-override.rs | 2 +- src/test/ui/parser/keyword-override.stderr | 8 +- .../ui/parser/keyword-pub-as-identifier.rs | 2 +- .../parser/keyword-pub-as-identifier.stderr | 8 +- .../ui/parser/keyword-return-as-identifier.rs | 2 +- .../keyword-return-as-identifier.stderr | 8 +- .../ui/parser/keyword-static-as-identifier.rs | 2 +- .../keyword-static-as-identifier.stderr | 8 +- .../ui/parser/keyword-struct-as-identifier.rs | 2 +- .../keyword-struct-as-identifier.stderr | 8 +- .../ui/parser/keyword-trait-as-identifier.rs | 2 +- .../parser/keyword-trait-as-identifier.stderr | 8 +- .../keyword-try-as-identifier-edition2018.rs | 2 +- ...yword-try-as-identifier-edition2018.stderr | 8 +- .../ui/parser/keyword-type-as-identifier.rs | 2 +- .../parser/keyword-type-as-identifier.stderr | 8 +- src/test/ui/parser/keyword-typeof.rs | 2 +- src/test/ui/parser/keyword-typeof.stderr | 8 +- .../ui/parser/keyword-unsafe-as-identifier.rs | 2 +- .../keyword-unsafe-as-identifier.stderr | 8 +- .../ui/parser/keyword-use-as-identifier.rs | 2 +- .../parser/keyword-use-as-identifier.stderr | 8 +- .../ui/parser/keyword-where-as-identifier.rs | 2 +- .../parser/keyword-where-as-identifier.stderr | 8 +- .../ui/parser/keyword-while-as-identifier.rs | 2 +- .../parser/keyword-while-as-identifier.stderr | 8 +- src/test/ui/parser/mut-patterns.rs | 30 +++- src/test/ui/parser/mut-patterns.stderr | 68 ++++++++- src/test/ui/reserved/reserved-become.rs | 2 +- src/test/ui/reserved/reserved-become.stderr | 8 +- src/test/ui/self/self_type_keyword.rs | 3 +- src/test/ui/self/self_type_keyword.stderr | 30 ++-- 71 files changed, 449 insertions(+), 147 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 78c9a289b3702..7b228a700a748 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -4,6 +4,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac}; use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind}; +use crate::mut_visit::{noop_visit_pat, MutVisitor}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -273,7 +274,7 @@ impl<'a> Parser<'a> { // Parse _ PatKind::Wild } else if self.eat_keyword(kw::Mut) { - self.recover_pat_ident_mut_first()? + self.parse_pat_ident_mut()? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); @@ -281,13 +282,12 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Box) { // Parse `box pat` PatKind::Box(self.parse_pat_with_range_pat(false, None)?) - } else if self.token.is_ident() && !self.token.is_reserved_ident() && - self.parse_as_ident() { + } else if self.can_be_ident_pat() { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))? - } else if self.token.is_path_start() { + } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { // Parse a qualified path @@ -384,24 +384,85 @@ impl<'a> Parser<'a> { }) } + fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { + let mut_span = self.prev_span; + + if self.eat_keyword(kw::Ref) { + return self.recover_mut_ref_ident(mut_span) + } + + self.recover_additional_muts(); + + let mut pat = self.parse_pat(Some("identifier"))?; + + // Add `mut` to any binding in the parsed pattern. + struct AddMut; + impl MutVisitor for AddMut { + fn visit_pat(&mut self, pat: &mut P) { + if let PatKind::Ident(BindingMode::ByValue(ref mut m), ..) = pat.node { + *m = Mutability::Mutable; + } + noop_visit_pat(pat, self); + } + } + AddMut.visit_pat(&mut pat); + + // Unwrap; If we don't have `mut $ident`, error. + let pat = pat.into_inner(); + match &pat.node { + PatKind::Ident(..) => {} + _ => self.ban_mut_general_pat(mut_span, &pat), + } + + Ok(pat.node) + } + /// Recover on `mut ref? ident @ pat` and suggest /// that the order of `mut` and `ref` is incorrect. - fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> { - let mutref_span = self.prev_span.to(self.token.span); - let binding_mode = if self.eat_keyword(kw::Ref) { - self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") - .span_suggestion( - mutref_span, - "try switching the order", - "ref mut".into(), - Applicability::MachineApplicable - ) - .emit(); - BindingMode::ByRef(Mutability::Mutable) - } else { - BindingMode::ByValue(Mutability::Mutable) - }; - self.parse_pat_ident(binding_mode) + fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> { + let mutref_span = lo.to(self.prev_span); + self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") + .span_suggestion( + mutref_span, + "try switching the order", + "ref mut".into(), + Applicability::MachineApplicable + ) + .emit(); + + self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable)) + } + + /// Error on `mut $pat` where `$pat` is not an ident. + fn ban_mut_general_pat(&self, lo: Span, pat: &Pat) { + let span = lo.to(pat.span); + self.struct_span_err(span, "`mut` must be attached to each individual binding") + .span_suggestion( + span, + "add `mut` to each binding", + pprust::pat_to_string(&pat), + Applicability::MachineApplicable, + ) + .emit(); + } + + /// Eat any extraneous `mut`s and error + recover if we ate any. + fn recover_additional_muts(&mut self) { + let lo = self.token.span; + while self.eat_keyword(kw::Mut) {} + if lo == self.token.span { + return; + } + + let span = lo.to(self.prev_span); + self.struct_span_err(span, "`mut` on a binding may not be repeated") + .span_suggestion( + span, + "remove the additional `mut`s", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); } /// Parse macro invocation @@ -479,17 +540,6 @@ impl<'a> Parser<'a> { Err(err) } - // Helper function to decide whether to parse as ident binding - // or to try to do something more complex like range patterns. - fn parse_as_ident(&mut self) -> bool { - self.look_ahead(1, |t| match t.kind { - token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | - token::DotDotDot | token::DotDotEq | token::DotDot | - token::ModSep | token::Not => false, - _ => true, - }) - } - /// Is the current token suitable as the start of a range patterns end? fn is_pat_range_end_start(&self) -> bool { self.token.is_path_start() // e.g. `MY_CONST`; @@ -563,6 +613,30 @@ impl<'a> Parser<'a> { } } + /// Is this the start of a pattern beginning with a path? + fn is_start_of_pat_with_path(&mut self) -> bool { + self.check_path() + // Just for recovery (see `can_be_ident`). + || self.token.is_ident() && !self.token.is_bool_lit() && !self.token.is_keyword(kw::In) + } + + /// Would `parse_pat_ident` be appropriate here? + fn can_be_ident_pat(&mut self) -> bool { + self.check_ident() + && !self.token.is_bool_lit() // Avoid `true` or `false` as a binding as it is a literal. + && !self.token.is_path_segment_keyword() // Avoid e.g. `Self` as it is a path. + // Avoid `in`. Due to recovery in the list parser this messes with `for ( $pat in $expr )`. + && !self.token.is_keyword(kw::In) + && self.look_ahead(1, |t| match t.kind { // Try to do something more complex? + token::OpenDelim(token::Paren) // A tuple struct pattern. + | token::OpenDelim(token::Brace) // A struct pattern. + | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. + | token::ModSep // A tuple / struct variant pattern. + | token::Not => false, // A macro expanding to a pattern. + _ => true, + }) + } + /// Parses `ident` or `ident @ pat`. /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs index f9b6bad7c2552..8a420f7203cac 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs @@ -1,3 +1,3 @@ fn main() { - let extern = 0; //~ ERROR expected pattern, found keyword `extern` + let extern = 0; //~ ERROR expected identifier, found keyword `extern` } diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr index d7b9ad2abe97a..73ac113f1b1e0 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `extern` +error: expected identifier, found keyword `extern` --> $DIR/keyword-extern-as-identifier-pat.rs:2:9 | LL | let extern = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#extern = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs index 9c01a5c6d20e3..695baf8187276 100644 --- a/src/test/ui/parser/issue-32501.rs +++ b/src/test/ui/parser/issue-32501.rs @@ -4,5 +4,6 @@ fn main() { let _ = 0; let mut b = 0; let mut _b = 0; - let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_` + let mut _ = 0; + //~^ ERROR `mut` must be attached to each individual binding } diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr index 97efb89593579..f5d3300cf9c56 100644 --- a/src/test/ui/parser/issue-32501.stderr +++ b/src/test/ui/parser/issue-32501.stderr @@ -1,8 +1,8 @@ -error: expected identifier, found reserved identifier `_` - --> $DIR/issue-32501.rs:7:13 +error: `mut` must be attached to each individual binding + --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^ expected identifier, found reserved identifier + | ^^^^^ help: add `mut` to each binding: `_` error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-abstract.rs b/src/test/ui/parser/keyword-abstract.rs index 890802ac134a0..570206575ab07 100644 --- a/src/test/ui/parser/keyword-abstract.rs +++ b/src/test/ui/parser/keyword-abstract.rs @@ -1,3 +1,3 @@ fn main() { - let abstract = (); //~ ERROR expected pattern, found reserved keyword `abstract` + let abstract = (); //~ ERROR expected identifier, found reserved keyword `abstract` } diff --git a/src/test/ui/parser/keyword-abstract.stderr b/src/test/ui/parser/keyword-abstract.stderr index 2c79598a81b18..eb2c810099e16 100644 --- a/src/test/ui/parser/keyword-abstract.stderr +++ b/src/test/ui/parser/keyword-abstract.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `abstract` +error: expected identifier, found reserved keyword `abstract` --> $DIR/keyword-abstract.rs:2:9 | LL | let abstract = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#abstract = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-as-as-identifier.rs b/src/test/ui/parser/keyword-as-as-identifier.rs index 23ff259db3048..cd47c8a3907d9 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.rs +++ b/src/test/ui/parser/keyword-as-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py as' fn main() { - let as = "foo"; //~ error: expected pattern, found keyword `as` + let as = "foo"; //~ error: expected identifier, found keyword `as` } diff --git a/src/test/ui/parser/keyword-as-as-identifier.stderr b/src/test/ui/parser/keyword-as-as-identifier.stderr index ef466488ad061..5648652be9bca 100644 --- a/src/test/ui/parser/keyword-as-as-identifier.stderr +++ b/src/test/ui/parser/keyword-as-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `as` +error: expected identifier, found keyword `as` --> $DIR/keyword-as-as-identifier.rs:4:9 | LL | let as = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#as = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-break-as-identifier.rs b/src/test/ui/parser/keyword-break-as-identifier.rs index 5ee111d38c9c3..04b25a7aaf613 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.rs +++ b/src/test/ui/parser/keyword-break-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py break' fn main() { - let break = "foo"; //~ error: expected pattern, found keyword `break` + let break = "foo"; //~ error: expected identifier, found keyword `break` } diff --git a/src/test/ui/parser/keyword-break-as-identifier.stderr b/src/test/ui/parser/keyword-break-as-identifier.stderr index 690bd84221a94..820193db70b0f 100644 --- a/src/test/ui/parser/keyword-break-as-identifier.stderr +++ b/src/test/ui/parser/keyword-break-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `break` +error: expected identifier, found keyword `break` --> $DIR/keyword-break-as-identifier.rs:4:9 | LL | let break = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#break = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-const-as-identifier.rs b/src/test/ui/parser/keyword-const-as-identifier.rs index 48fc142cf64b1..6a2d926bf5796 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.rs +++ b/src/test/ui/parser/keyword-const-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py const' fn main() { - let const = "foo"; //~ error: expected pattern, found keyword `const` + let const = "foo"; //~ error: expected identifier, found keyword `const` } diff --git a/src/test/ui/parser/keyword-const-as-identifier.stderr b/src/test/ui/parser/keyword-const-as-identifier.stderr index 6da47f88d04e3..95b536c99c75a 100644 --- a/src/test/ui/parser/keyword-const-as-identifier.stderr +++ b/src/test/ui/parser/keyword-const-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `const` +error: expected identifier, found keyword `const` --> $DIR/keyword-const-as-identifier.rs:4:9 | LL | let const = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#const = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-continue-as-identifier.rs b/src/test/ui/parser/keyword-continue-as-identifier.rs index 06315a48349ff..cfdd62a2d1bce 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.rs +++ b/src/test/ui/parser/keyword-continue-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py continue' fn main() { - let continue = "foo"; //~ error: expected pattern, found keyword `continue` + let continue = "foo"; //~ error: expected identifier, found keyword `continue` } diff --git a/src/test/ui/parser/keyword-continue-as-identifier.stderr b/src/test/ui/parser/keyword-continue-as-identifier.stderr index 4b0a659f9ad7e..6b24422a5557e 100644 --- a/src/test/ui/parser/keyword-continue-as-identifier.stderr +++ b/src/test/ui/parser/keyword-continue-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `continue` +error: expected identifier, found keyword `continue` --> $DIR/keyword-continue-as-identifier.rs:4:9 | LL | let continue = "foo"; - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#continue = "foo"; + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-else-as-identifier.rs b/src/test/ui/parser/keyword-else-as-identifier.rs index 0c69105cf9457..f12dac3ff75eb 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.rs +++ b/src/test/ui/parser/keyword-else-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py else' fn main() { - let else = "foo"; //~ error: expected pattern, found keyword `else` + let else = "foo"; //~ error: expected identifier, found keyword `else` } diff --git a/src/test/ui/parser/keyword-else-as-identifier.stderr b/src/test/ui/parser/keyword-else-as-identifier.stderr index bec7b7ba01e12..f28635cd08cd6 100644 --- a/src/test/ui/parser/keyword-else-as-identifier.stderr +++ b/src/test/ui/parser/keyword-else-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `else` +error: expected identifier, found keyword `else` --> $DIR/keyword-else-as-identifier.rs:4:9 | LL | let else = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#else = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-enum-as-identifier.rs b/src/test/ui/parser/keyword-enum-as-identifier.rs index d1675800a2791..fe66230d02830 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.rs +++ b/src/test/ui/parser/keyword-enum-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py enum' fn main() { - let enum = "foo"; //~ error: expected pattern, found keyword `enum` + let enum = "foo"; //~ error: expected identifier, found keyword `enum` } diff --git a/src/test/ui/parser/keyword-enum-as-identifier.stderr b/src/test/ui/parser/keyword-enum-as-identifier.stderr index 51a834f797c32..fc54dce1b68f4 100644 --- a/src/test/ui/parser/keyword-enum-as-identifier.stderr +++ b/src/test/ui/parser/keyword-enum-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `enum` +error: expected identifier, found keyword `enum` --> $DIR/keyword-enum-as-identifier.rs:4:9 | LL | let enum = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#enum = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-final.rs b/src/test/ui/parser/keyword-final.rs index e1cecd0e8e07a..a79a11032a018 100644 --- a/src/test/ui/parser/keyword-final.rs +++ b/src/test/ui/parser/keyword-final.rs @@ -1,3 +1,3 @@ fn main() { - let final = (); //~ ERROR expected pattern, found reserved keyword `final` + let final = (); //~ ERROR expected identifier, found reserved keyword `final` } diff --git a/src/test/ui/parser/keyword-final.stderr b/src/test/ui/parser/keyword-final.stderr index e8372643be6b7..291710d05cbfd 100644 --- a/src/test/ui/parser/keyword-final.stderr +++ b/src/test/ui/parser/keyword-final.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `final` +error: expected identifier, found reserved keyword `final` --> $DIR/keyword-final.rs:2:9 | LL | let final = (); - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#final = (); + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-fn-as-identifier.rs b/src/test/ui/parser/keyword-fn-as-identifier.rs index bca2d5996a54b..f30e115f7947e 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.rs +++ b/src/test/ui/parser/keyword-fn-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py fn' fn main() { - let fn = "foo"; //~ error: expected pattern, found keyword `fn` + let fn = "foo"; //~ error: expected identifier, found keyword `fn` } diff --git a/src/test/ui/parser/keyword-fn-as-identifier.stderr b/src/test/ui/parser/keyword-fn-as-identifier.stderr index a071a40a70e0d..692f195b2888d 100644 --- a/src/test/ui/parser/keyword-fn-as-identifier.stderr +++ b/src/test/ui/parser/keyword-fn-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `fn` +error: expected identifier, found keyword `fn` --> $DIR/keyword-fn-as-identifier.rs:4:9 | LL | let fn = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#fn = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-for-as-identifier.rs b/src/test/ui/parser/keyword-for-as-identifier.rs index ce49fd90d9101..9e8a2ad53420c 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.rs +++ b/src/test/ui/parser/keyword-for-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py for' fn main() { - let for = "foo"; //~ error: expected pattern, found keyword `for` + let for = "foo"; //~ error: expected identifier, found keyword `for` } diff --git a/src/test/ui/parser/keyword-for-as-identifier.stderr b/src/test/ui/parser/keyword-for-as-identifier.stderr index 090046cebdc56..bcaf421286e76 100644 --- a/src/test/ui/parser/keyword-for-as-identifier.stderr +++ b/src/test/ui/parser/keyword-for-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `for` +error: expected identifier, found keyword `for` --> $DIR/keyword-for-as-identifier.rs:4:9 | LL | let for = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#for = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-if-as-identifier.rs b/src/test/ui/parser/keyword-if-as-identifier.rs index a1302970689c4..0bd5756afce7f 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.rs +++ b/src/test/ui/parser/keyword-if-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py if' fn main() { - let if = "foo"; //~ error: expected pattern, found keyword `if` + let if = "foo"; //~ error: expected identifier, found keyword `if` } diff --git a/src/test/ui/parser/keyword-if-as-identifier.stderr b/src/test/ui/parser/keyword-if-as-identifier.stderr index 98bfdb46e9770..43fbcd7148a1d 100644 --- a/src/test/ui/parser/keyword-if-as-identifier.stderr +++ b/src/test/ui/parser/keyword-if-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `if` +error: expected identifier, found keyword `if` --> $DIR/keyword-if-as-identifier.rs:4:9 | LL | let if = "foo"; - | ^^ expected pattern + | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#if = "foo"; + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-impl-as-identifier.rs b/src/test/ui/parser/keyword-impl-as-identifier.rs index 95a34483ad21a..df529bae07214 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.rs +++ b/src/test/ui/parser/keyword-impl-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py impl' fn main() { - let impl = "foo"; //~ error: expected pattern, found keyword `impl` + let impl = "foo"; //~ error: expected identifier, found keyword `impl` } diff --git a/src/test/ui/parser/keyword-impl-as-identifier.stderr b/src/test/ui/parser/keyword-impl-as-identifier.stderr index 2672959b7c68e..01886eb45cb6d 100644 --- a/src/test/ui/parser/keyword-impl-as-identifier.stderr +++ b/src/test/ui/parser/keyword-impl-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `impl` +error: expected identifier, found keyword `impl` --> $DIR/keyword-impl-as-identifier.rs:4:9 | LL | let impl = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#impl = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-let-as-identifier.rs b/src/test/ui/parser/keyword-let-as-identifier.rs index 07c0ddf8ce573..9b1183501b28d 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.rs +++ b/src/test/ui/parser/keyword-let-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py let' fn main() { - let let = "foo"; //~ error: expected pattern, found keyword `let` + let let = "foo"; //~ error: expected identifier, found keyword `let` } diff --git a/src/test/ui/parser/keyword-let-as-identifier.stderr b/src/test/ui/parser/keyword-let-as-identifier.stderr index 99dbc0530f3fe..f6c39077be23b 100644 --- a/src/test/ui/parser/keyword-let-as-identifier.stderr +++ b/src/test/ui/parser/keyword-let-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `let` +error: expected identifier, found keyword `let` --> $DIR/keyword-let-as-identifier.rs:4:9 | LL | let let = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#let = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-loop-as-identifier.rs b/src/test/ui/parser/keyword-loop-as-identifier.rs index 8643ffe434505..46914a19be2bd 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.rs +++ b/src/test/ui/parser/keyword-loop-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py loop' fn main() { - let loop = "foo"; //~ error: expected pattern, found keyword `loop` + let loop = "foo"; //~ error: expected identifier, found keyword `loop` } diff --git a/src/test/ui/parser/keyword-loop-as-identifier.stderr b/src/test/ui/parser/keyword-loop-as-identifier.stderr index 783507eb35cd7..f0c282faa29f1 100644 --- a/src/test/ui/parser/keyword-loop-as-identifier.stderr +++ b/src/test/ui/parser/keyword-loop-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `loop` +error: expected identifier, found keyword `loop` --> $DIR/keyword-loop-as-identifier.rs:4:9 | LL | let loop = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#loop = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-match-as-identifier.rs b/src/test/ui/parser/keyword-match-as-identifier.rs index 8ef6b6810a56b..d3cecb991b8f9 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.rs +++ b/src/test/ui/parser/keyword-match-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py match' fn main() { - let match = "foo"; //~ error: expected pattern, found keyword `match` + let match = "foo"; //~ error: expected identifier, found keyword `match` } diff --git a/src/test/ui/parser/keyword-match-as-identifier.stderr b/src/test/ui/parser/keyword-match-as-identifier.stderr index e56a115c91636..f1f4397d194f0 100644 --- a/src/test/ui/parser/keyword-match-as-identifier.stderr +++ b/src/test/ui/parser/keyword-match-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `match` +error: expected identifier, found keyword `match` --> $DIR/keyword-match-as-identifier.rs:4:9 | LL | let match = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#match = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-mod-as-identifier.rs b/src/test/ui/parser/keyword-mod-as-identifier.rs index 96bcdccf0a096..b9c7b6c78ed6c 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.rs +++ b/src/test/ui/parser/keyword-mod-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py mod' fn main() { - let mod = "foo"; //~ error: expected pattern, found keyword `mod` + let mod = "foo"; //~ error: expected identifier, found keyword `mod` } diff --git a/src/test/ui/parser/keyword-mod-as-identifier.stderr b/src/test/ui/parser/keyword-mod-as-identifier.stderr index a8be2ceb037d6..65ae3baa8c21d 100644 --- a/src/test/ui/parser/keyword-mod-as-identifier.stderr +++ b/src/test/ui/parser/keyword-mod-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `mod` +error: expected identifier, found keyword `mod` --> $DIR/keyword-mod-as-identifier.rs:4:9 | LL | let mod = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#mod = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-move-as-identifier.rs b/src/test/ui/parser/keyword-move-as-identifier.rs index 2193af530bd7a..65be02e3c70cf 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.rs +++ b/src/test/ui/parser/keyword-move-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py move' fn main() { - let move = "foo"; //~ error: expected pattern, found keyword `move` + let move = "foo"; //~ error: expected identifier, found keyword `move` } diff --git a/src/test/ui/parser/keyword-move-as-identifier.stderr b/src/test/ui/parser/keyword-move-as-identifier.stderr index e0687e27eb585..216f7c931eea7 100644 --- a/src/test/ui/parser/keyword-move-as-identifier.stderr +++ b/src/test/ui/parser/keyword-move-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `move` +error: expected identifier, found keyword `move` --> $DIR/keyword-move-as-identifier.rs:4:9 | LL | let move = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#move = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-override.rs b/src/test/ui/parser/keyword-override.rs index 948a20095f1ea..009bebd7ddba8 100644 --- a/src/test/ui/parser/keyword-override.rs +++ b/src/test/ui/parser/keyword-override.rs @@ -1,3 +1,3 @@ fn main() { - let override = (); //~ ERROR expected pattern, found reserved keyword `override` + let override = (); //~ ERROR expected identifier, found reserved keyword `override` } diff --git a/src/test/ui/parser/keyword-override.stderr b/src/test/ui/parser/keyword-override.stderr index 1bfc6c9b3858d..3183fa510c2d1 100644 --- a/src/test/ui/parser/keyword-override.stderr +++ b/src/test/ui/parser/keyword-override.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `override` +error: expected identifier, found reserved keyword `override` --> $DIR/keyword-override.rs:2:9 | LL | let override = (); - | ^^^^^^^^ expected pattern + | ^^^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#override = (); + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-pub-as-identifier.rs b/src/test/ui/parser/keyword-pub-as-identifier.rs index 2ed8cc6b268ca..2b2bb14118d7d 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.rs +++ b/src/test/ui/parser/keyword-pub-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py pub' fn main() { - let pub = "foo"; //~ error: expected pattern, found keyword `pub` + let pub = "foo"; //~ error: expected identifier, found keyword `pub` } diff --git a/src/test/ui/parser/keyword-pub-as-identifier.stderr b/src/test/ui/parser/keyword-pub-as-identifier.stderr index 526ddcd6ee0ff..f81078b12bd3c 100644 --- a/src/test/ui/parser/keyword-pub-as-identifier.stderr +++ b/src/test/ui/parser/keyword-pub-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `pub` +error: expected identifier, found keyword `pub` --> $DIR/keyword-pub-as-identifier.rs:4:9 | LL | let pub = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#pub = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-return-as-identifier.rs b/src/test/ui/parser/keyword-return-as-identifier.rs index 920931b00f954..e1a2db5e4d82d 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.rs +++ b/src/test/ui/parser/keyword-return-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py return' fn main() { - let return = "foo"; //~ error: expected pattern, found keyword `return` + let return = "foo"; //~ error: expected identifier, found keyword `return` } diff --git a/src/test/ui/parser/keyword-return-as-identifier.stderr b/src/test/ui/parser/keyword-return-as-identifier.stderr index c0156a63fa9d1..8cc4d12fbbb9a 100644 --- a/src/test/ui/parser/keyword-return-as-identifier.stderr +++ b/src/test/ui/parser/keyword-return-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `return` +error: expected identifier, found keyword `return` --> $DIR/keyword-return-as-identifier.rs:4:9 | LL | let return = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#return = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-static-as-identifier.rs b/src/test/ui/parser/keyword-static-as-identifier.rs index 3ccbfccfc9394..423b9854b8aa1 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.rs +++ b/src/test/ui/parser/keyword-static-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py static' fn main() { - let static = "foo"; //~ error: expected pattern, found keyword `static` + let static = "foo"; //~ error: expected identifier, found keyword `static` } diff --git a/src/test/ui/parser/keyword-static-as-identifier.stderr b/src/test/ui/parser/keyword-static-as-identifier.stderr index 00a65977732f8..7d22bc97d66ae 100644 --- a/src/test/ui/parser/keyword-static-as-identifier.stderr +++ b/src/test/ui/parser/keyword-static-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `static` +error: expected identifier, found keyword `static` --> $DIR/keyword-static-as-identifier.rs:4:9 | LL | let static = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#static = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-struct-as-identifier.rs b/src/test/ui/parser/keyword-struct-as-identifier.rs index 69d8f19065533..18cfe11592aed 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.rs +++ b/src/test/ui/parser/keyword-struct-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py struct' fn main() { - let struct = "foo"; //~ error: expected pattern, found keyword `struct` + let struct = "foo"; //~ error: expected identifier, found keyword `struct` } diff --git a/src/test/ui/parser/keyword-struct-as-identifier.stderr b/src/test/ui/parser/keyword-struct-as-identifier.stderr index b2d6639e72ecb..b109fa6247dcd 100644 --- a/src/test/ui/parser/keyword-struct-as-identifier.stderr +++ b/src/test/ui/parser/keyword-struct-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `struct` +error: expected identifier, found keyword `struct` --> $DIR/keyword-struct-as-identifier.rs:4:9 | LL | let struct = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#struct = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-trait-as-identifier.rs b/src/test/ui/parser/keyword-trait-as-identifier.rs index f62858442d252..67f81167dbdd3 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.rs +++ b/src/test/ui/parser/keyword-trait-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py trait' fn main() { - let trait = "foo"; //~ error: expected pattern, found keyword `trait` + let trait = "foo"; //~ error: expected identifier, found keyword `trait` } diff --git a/src/test/ui/parser/keyword-trait-as-identifier.stderr b/src/test/ui/parser/keyword-trait-as-identifier.stderr index b31c0df28c008..ccc675cdb3a7c 100644 --- a/src/test/ui/parser/keyword-trait-as-identifier.stderr +++ b/src/test/ui/parser/keyword-trait-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `trait` +error: expected identifier, found keyword `trait` --> $DIR/keyword-trait-as-identifier.rs:4:9 | LL | let trait = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#trait = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs index 13a938b2e0988..4fa37bdb057b7 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 fn main() { - let try = "foo"; //~ error: expected pattern, found reserved keyword `try` + let try = "foo"; //~ error: expected identifier, found reserved keyword `try` } diff --git a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr index c342e3a76fbb4..f71b889a30db5 100644 --- a/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr +++ b/src/test/ui/parser/keyword-try-as-identifier-edition2018.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `try` +error: expected identifier, found reserved keyword `try` --> $DIR/keyword-try-as-identifier-edition2018.rs:4:9 | LL | let try = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#try = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-type-as-identifier.rs b/src/test/ui/parser/keyword-type-as-identifier.rs index 992547e6f59c0..04adddf72c6ff 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.rs +++ b/src/test/ui/parser/keyword-type-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py type' fn main() { - let type = "foo"; //~ error: expected pattern, found keyword `type` + let type = "foo"; //~ error: expected identifier, found keyword `type` } diff --git a/src/test/ui/parser/keyword-type-as-identifier.stderr b/src/test/ui/parser/keyword-type-as-identifier.stderr index b749c708d441d..88099d949a829 100644 --- a/src/test/ui/parser/keyword-type-as-identifier.stderr +++ b/src/test/ui/parser/keyword-type-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `type` +error: expected identifier, found keyword `type` --> $DIR/keyword-type-as-identifier.rs:4:9 | LL | let type = "foo"; - | ^^^^ expected pattern + | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#type = "foo"; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-typeof.rs b/src/test/ui/parser/keyword-typeof.rs index 4ef102646ef1c..29dc77d276cbd 100644 --- a/src/test/ui/parser/keyword-typeof.rs +++ b/src/test/ui/parser/keyword-typeof.rs @@ -1,3 +1,3 @@ fn main() { - let typeof = (); //~ ERROR expected pattern, found reserved keyword `typeof` + let typeof = (); //~ ERROR expected identifier, found reserved keyword `typeof` } diff --git a/src/test/ui/parser/keyword-typeof.stderr b/src/test/ui/parser/keyword-typeof.stderr index e7b18023e61a9..4a1b63d5c9357 100644 --- a/src/test/ui/parser/keyword-typeof.stderr +++ b/src/test/ui/parser/keyword-typeof.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `typeof` +error: expected identifier, found reserved keyword `typeof` --> $DIR/keyword-typeof.rs:2:9 | LL | let typeof = (); - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#typeof = (); + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.rs b/src/test/ui/parser/keyword-unsafe-as-identifier.rs index adb20ebe48c79..0ff6d188c6480 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.rs +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe' fn main() { - let unsafe = "foo"; //~ error: expected pattern, found keyword `unsafe` + let unsafe = "foo"; //~ error: expected identifier, found keyword `unsafe` } diff --git a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr index 67935ce43ba04..205bb81df405b 100644 --- a/src/test/ui/parser/keyword-unsafe-as-identifier.stderr +++ b/src/test/ui/parser/keyword-unsafe-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `unsafe` +error: expected identifier, found keyword `unsafe` --> $DIR/keyword-unsafe-as-identifier.rs:4:9 | LL | let unsafe = "foo"; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#unsafe = "foo"; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-use-as-identifier.rs b/src/test/ui/parser/keyword-use-as-identifier.rs index 198444bafc5b8..821bedee08832 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.rs +++ b/src/test/ui/parser/keyword-use-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py use' fn main() { - let use = "foo"; //~ error: expected pattern, found keyword `use` + let use = "foo"; //~ error: expected identifier, found keyword `use` } diff --git a/src/test/ui/parser/keyword-use-as-identifier.stderr b/src/test/ui/parser/keyword-use-as-identifier.stderr index 2c69d0a8744a0..85a0492f5735f 100644 --- a/src/test/ui/parser/keyword-use-as-identifier.stderr +++ b/src/test/ui/parser/keyword-use-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `use` +error: expected identifier, found keyword `use` --> $DIR/keyword-use-as-identifier.rs:4:9 | LL | let use = "foo"; - | ^^^ expected pattern + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#use = "foo"; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-where-as-identifier.rs b/src/test/ui/parser/keyword-where-as-identifier.rs index 5624a8fc46038..56301bd20adfd 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.rs +++ b/src/test/ui/parser/keyword-where-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py where' fn main() { - let where = "foo"; //~ error: expected pattern, found keyword `where` + let where = "foo"; //~ error: expected identifier, found keyword `where` } diff --git a/src/test/ui/parser/keyword-where-as-identifier.stderr b/src/test/ui/parser/keyword-where-as-identifier.stderr index fc01183ca046b..b8b8506907636 100644 --- a/src/test/ui/parser/keyword-where-as-identifier.stderr +++ b/src/test/ui/parser/keyword-where-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `where` +error: expected identifier, found keyword `where` --> $DIR/keyword-where-as-identifier.rs:4:9 | LL | let where = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#where = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/keyword-while-as-identifier.rs b/src/test/ui/parser/keyword-while-as-identifier.rs index c0a539d350764..22026d15dcbfb 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.rs +++ b/src/test/ui/parser/keyword-while-as-identifier.rs @@ -1,5 +1,5 @@ // This file was auto-generated using 'src/etc/generate-keyword-tests.py while' fn main() { - let while = "foo"; //~ error: expected pattern, found keyword `while` + let while = "foo"; //~ error: expected identifier, found keyword `while` } diff --git a/src/test/ui/parser/keyword-while-as-identifier.stderr b/src/test/ui/parser/keyword-while-as-identifier.stderr index f72ac87742099..bb0c0ac668a41 100644 --- a/src/test/ui/parser/keyword-while-as-identifier.stderr +++ b/src/test/ui/parser/keyword-while-as-identifier.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found keyword `while` +error: expected identifier, found keyword `while` --> $DIR/keyword-while-as-identifier.rs:4:9 | LL | let while = "foo"; - | ^^^^^ expected pattern + | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#while = "foo"; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index bffeb1e2e7c40..87e127f9d364a 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -1,7 +1,35 @@ // Can't put mut in non-ident pattern +// edition:2018 + +#![feature(box_patterns)] +#![allow(warnings)] + pub fn main() { + let mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + struct Foo { x: isize } let mut Foo { x: x } = Foo { x: 3 }; - //~^ ERROR: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + let mut Foo { x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + struct r#yield(u8, u8); + let mut mut yield(become, await) = r#yield(0, 0); + //~^ ERROR `mut` on a binding may not be repeated + //~| ERROR `mut` must be attached to each individual binding + //~| ERROR expected identifier, found reserved keyword `yield` + //~| ERROR expected identifier, found reserved keyword `become` + //~| ERROR expected identifier, found reserved keyword `await` + + struct W(T, U); + struct B { f: Box } + let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + //~^ ERROR `mut` must be attached to each individual binding + = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index b39209afd4295..a251e2908f02c 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,8 +1,68 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `{` - --> $DIR/mut-patterns.rs:5:17 +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:9:13 + | +LL | let mut mut x = 0; + | ^^^ help: remove the additional `mut`s + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:14:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; - | ^ expected one of `:`, `;`, `=`, `@`, or `|` here + | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:18:9 + | +LL | let mut Foo { x } = Foo { x: 3 }; + | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:23:13 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^ help: remove the additional `mut`s + +error: expected identifier, found reserved keyword `yield` + --> $DIR/mut-patterns.rs:23:17 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut r#yield(become, await) = r#yield(0, 0); + | ^^^^^^^ + +error: expected identifier, found reserved keyword `become` + --> $DIR/mut-patterns.rs:23:23 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(r#become, await) = r#yield(0, 0); + | ^^^^^^^^ + +error: expected identifier, found reserved keyword `await` + --> $DIR/mut-patterns.rs:23:31 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut mut yield(become, r#await) = r#yield(0, 0); + | ^^^^^^^ + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:23:9 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:32:9 + | +LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` -error: aborting due to previous error +error: aborting due to 9 previous errors diff --git a/src/test/ui/reserved/reserved-become.rs b/src/test/ui/reserved/reserved-become.rs index 2279a05e6b2db..56645255ee5f6 100644 --- a/src/test/ui/reserved/reserved-become.rs +++ b/src/test/ui/reserved/reserved-become.rs @@ -1,4 +1,4 @@ fn main() { let become = 0; - //~^ ERROR expected pattern, found reserved keyword `become` + //~^ ERROR expected identifier, found reserved keyword `become` } diff --git a/src/test/ui/reserved/reserved-become.stderr b/src/test/ui/reserved/reserved-become.stderr index f9fe78e18b393..3ce9fb33c289e 100644 --- a/src/test/ui/reserved/reserved-become.stderr +++ b/src/test/ui/reserved/reserved-become.stderr @@ -1,8 +1,12 @@ -error: expected pattern, found reserved keyword `become` +error: expected identifier, found reserved keyword `become` --> $DIR/reserved-become.rs:2:9 | LL | let become = 0; - | ^^^^^^ expected pattern + | ^^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let r#become = 0; + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index 01b3309fcacb1..d479905932be0 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -14,7 +14,8 @@ pub fn main() { ref Self => (), //~^ ERROR expected identifier, found keyword `Self` mut Self => (), - //~^ ERROR expected identifier, found keyword `Self` + //~^ ERROR `mut` must be attached to each individual binding + //~| ERROR cannot find unit struct/variant or constant `Self` ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` Self!() => (), diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index b63de98b8e702..fdae06ccdd9f5 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -10,38 +10,38 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:16:13 +error: `mut` must be attached to each individual binding + --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^ expected identifier, found keyword + | ^^^^^^^^ help: add `mut` to each binding: `Self` error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:18:17 + --> $DIR/self_type_keyword.rs:19:17 | LL | ref mut Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:22:15 + --> $DIR/self_type_keyword.rs:23:15 | LL | Foo { Self } => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:28:26 + --> $DIR/self_type_keyword.rs:29:26 | LL | extern crate core as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:33:32 + --> $DIR/self_type_keyword.rs:34:32 | LL | use std::option::Option as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:38:11 + --> $DIR/self_type_keyword.rs:39:11 | LL | trait Self {} | ^^^^ expected identifier, found keyword @@ -53,11 +53,21 @@ LL | struct Bar<'Self>; | ^^^^^ error: cannot find macro `Self!` in this scope - --> $DIR/self_type_keyword.rs:20:9 + --> $DIR/self_type_keyword.rs:21:9 | LL | Self!() => (), | ^^^^ +error[E0531]: cannot find unit struct/variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use foo::Self; + | + error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | @@ -66,6 +76,6 @@ LL | struct Bar<'Self>; | = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. From 3b2c14736d6d8fc44cf60588ed41a67eaf9459ad Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Tue, 27 Aug 2019 10:13:59 -0700 Subject: [PATCH 06/20] remove the reference to __cxa_thread_atexit_impl --- src/libstd/sys/vxworks/fast_thread_local.rs | 27 ++------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/src/libstd/sys/vxworks/fast_thread_local.rs b/src/libstd/sys/vxworks/fast_thread_local.rs index f5a2e263d25e7..2e021980778e5 100644 --- a/src/libstd/sys/vxworks/fast_thread_local.rs +++ b/src/libstd/sys/vxworks/fast_thread_local.rs @@ -1,33 +1,10 @@ +// Copyright (c) 2019 Wind River Systems, Inc. + #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -// Since what appears to be glibc 2.18 this symbol has been shipped which -// GCC and clang both use to invoke destructors in thread_local globals, so -// let's do the same! -// -// Note, however, that we run on lots older linuxes, as well as cross -// compiling from a newer linux to an older linux, so we also have a -// fallback implementation to use as well. -// -// Due to rust-lang/rust#18804, make sure this is not generic! pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use crate::mem; use crate::sys_common::thread_local::register_dtor_fallback; - - extern { - #[linkage = "extern_weak"] - static __dso_handle: *mut u8; - #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; - } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) - (dtor, t, &__dso_handle as *const _ as *mut _); - return - } register_dtor_fallback(t, dtor); } From dbbe3363c94b120d1eba9cba01dadddd862716b8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 19:51:21 +0200 Subject: [PATCH 07/20] Ensure 'let mut ;' where ':pat' is banned. --- src/libsyntax/parse/parser/pat.rs | 9 +++++++++ src/test/ui/parser/mut-patterns.rs | 8 ++++++++ src/test/ui/parser/mut-patterns.stderr | 11 ++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 7b228a700a748..08934e8533049 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -384,6 +384,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a mutable binding with the `mut` token already eaten. fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { let mut_span = self.prev_span; @@ -393,6 +394,14 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); + // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. + if let token::Interpolated(ref nt) = self.token.kind { + if let token::NtPat(_) = **nt { + self.expected_ident_found().emit(); + } + } + + // Parse the pattern we hope to be an identifier. let mut pat = self.parse_pat(Some("identifier"))?; // Add `mut` to any binding in the parsed pattern. diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index 87e127f9d364a..0c78ca726e003 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -32,4 +32,12 @@ pub fn main() { let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) //~^ ERROR `mut` must be attached to each individual binding = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); + + // Make sure we don't accidentally allow `mut $p` where `$p:pat`. + macro_rules! foo { + ($p:pat) => { + let mut $p = 0; //~ ERROR expected identifier, found `x` + } + } + foo!(x); } diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index a251e2908f02c..a1293129e2eaf 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -64,5 +64,14 @@ error: `mut` must be attached to each individual binding LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` -error: aborting due to 9 previous errors +error: expected identifier, found `x` + --> $DIR/mut-patterns.rs:39:21 + | +LL | let mut $p = 0; + | ^^ expected identifier +... +LL | foo!(x); + | -------- in this macro invocation + +error: aborting due to 10 previous errors From 7677d1f771525606af256e2972cb7116d8fde99f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2019 22:18:25 +0200 Subject: [PATCH 08/20] const_prop: only call error_to_const_error if we are actually showing something --- src/librustc_mir/const_eval.rs | 3 +++ src/librustc_mir/transform/const_prop.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 67d63e52b2bfa..5aa487d901663 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -519,6 +519,9 @@ pub fn const_variant_index<'tcx>( ecx.read_discriminant(op).unwrap().1 } +/// Turn an interpreter error into something to report to the user. +/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. +/// Should be called only if the error is actually going to to be reported! pub fn error_to_const_error<'mir, 'tcx>( ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, mut error: InterpErrorInfo<'tcx>, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b6146b6b7227d..f261fdc268b5b 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -237,9 +237,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = match f(self) { Ok(val) => Some(val), Err(error) => { - let diagnostic = error_to_const_error(&self.ecx, error); use rustc::mir::interpret::InterpError::*; - match diagnostic.error { + match error.kind { Exit(_) => bug!("the CTFE program cannot exit"), Unsupported(_) | UndefinedBehavior(_) @@ -248,6 +247,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Ignore these errors. } Panic(_) => { + let diagnostic = error_to_const_error(&self.ecx, error); diagnostic.report_as_lint( self.ecx.tcx, "this expression will panic at runtime", From 42e895d4d99ec7724f3efd632f52170f3f99a5aa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 27 Aug 2019 23:44:44 +0200 Subject: [PATCH 09/20] Improve 'mut ' diagnostic. --- src/libsyntax/parse/parser/pat.rs | 54 ++++++++++++++--------- src/test/ui/parser/issue-32501.rs | 2 +- src/test/ui/parser/issue-32501.stderr | 6 ++- src/test/ui/parser/mut-patterns.rs | 3 ++ src/test/ui/parser/mut-patterns.stderr | 46 ++++++++++++++----- src/test/ui/self/self_type_keyword.rs | 2 +- src/test/ui/self/self_type_keyword.stderr | 6 ++- 7 files changed, 82 insertions(+), 37 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 08934e8533049..1ffb112a5e87e 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -405,22 +405,13 @@ impl<'a> Parser<'a> { let mut pat = self.parse_pat(Some("identifier"))?; // Add `mut` to any binding in the parsed pattern. - struct AddMut; - impl MutVisitor for AddMut { - fn visit_pat(&mut self, pat: &mut P) { - if let PatKind::Ident(BindingMode::ByValue(ref mut m), ..) = pat.node { - *m = Mutability::Mutable; - } - noop_visit_pat(pat, self); - } - } - AddMut.visit_pat(&mut pat); + let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat); // Unwrap; If we don't have `mut $ident`, error. let pat = pat.into_inner(); match &pat.node { PatKind::Ident(..) => {} - _ => self.ban_mut_general_pat(mut_span, &pat), + _ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding), } Ok(pat.node) @@ -442,17 +433,40 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable)) } + /// Turn all by-value immutable bindings in a pattern into mutable bindings. + /// Returns `true` if any change was made. + fn make_all_value_bindings_mutable(pat: &mut P) -> bool { + struct AddMut(bool); + impl MutVisitor for AddMut { + fn visit_pat(&mut self, pat: &mut P) { + if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..) + = pat.node + { + *m = Mutability::Mutable; + self.0 = true; + } + noop_visit_pat(pat, self); + } + } + + let mut add_mut = AddMut(false); + add_mut.visit_pat(pat); + add_mut.0 + } + /// Error on `mut $pat` where `$pat` is not an ident. - fn ban_mut_general_pat(&self, lo: Span, pat: &Pat) { + fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) { let span = lo.to(pat.span); - self.struct_span_err(span, "`mut` must be attached to each individual binding") - .span_suggestion( - span, - "add `mut` to each binding", - pprust::pat_to_string(&pat), - Applicability::MachineApplicable, - ) - .emit(); + let fix = pprust::pat_to_string(&pat); + let (problem, suggestion) = if changed_any_binding { + ("`mut` must be attached to each individual binding", "add `mut` to each binding") + } else { + ("`mut` must be followed by a named binding", "remove the `mut` prefix") + }; + self.struct_span_err(span, problem) + .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable) + .note("`mut` may be followed by `variable` and `variable @ pattern`") + .emit() } /// Eat any extraneous `mut`s and error + recover if we ate any. diff --git a/src/test/ui/parser/issue-32501.rs b/src/test/ui/parser/issue-32501.rs index 695baf8187276..500242030c655 100644 --- a/src/test/ui/parser/issue-32501.rs +++ b/src/test/ui/parser/issue-32501.rs @@ -5,5 +5,5 @@ fn main() { let mut b = 0; let mut _b = 0; let mut _ = 0; - //~^ ERROR `mut` must be attached to each individual binding + //~^ ERROR `mut` must be followed by a named binding } diff --git a/src/test/ui/parser/issue-32501.stderr b/src/test/ui/parser/issue-32501.stderr index f5d3300cf9c56..d53302449a806 100644 --- a/src/test/ui/parser/issue-32501.stderr +++ b/src/test/ui/parser/issue-32501.stderr @@ -1,8 +1,10 @@ -error: `mut` must be attached to each individual binding +error: `mut` must be followed by a named binding --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^^^^^ help: add `mut` to each binding: `_` + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: aborting due to previous error diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index 0c78ca726e003..d46186a0fea0e 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -6,6 +6,9 @@ #![allow(warnings)] pub fn main() { + let mut _ = 0; //~ ERROR `mut` must be followed by a named binding + let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding + let mut mut x = 0; //~^ ERROR `mut` on a binding may not be repeated //~| remove the additional `mut`s diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index a1293129e2eaf..18ffaa5255870 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -1,29 +1,49 @@ +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:9:9 + | +LL | let mut _ = 0; + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:10:9 + | +LL | let mut (_, _) = (0, 0); + | ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:9:13 + --> $DIR/mut-patterns.rs:12:13 | LL | let mut mut x = 0; | ^^^ help: remove the additional `mut`s error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:14:9 + --> $DIR/mut-patterns.rs:17:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:18:9 + --> $DIR/mut-patterns.rs:21:9 | LL | let mut Foo { x } = Foo { x: 3 }; | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:23:13 + --> $DIR/mut-patterns.rs:26:13 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^ help: remove the additional `mut`s error: expected identifier, found reserved keyword `yield` - --> $DIR/mut-patterns.rs:23:17 + --> $DIR/mut-patterns.rs:26:17 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -33,7 +53,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0); | ^^^^^^^ error: expected identifier, found reserved keyword `become` - --> $DIR/mut-patterns.rs:23:23 + --> $DIR/mut-patterns.rs:26:23 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^ expected identifier, found reserved keyword @@ -43,7 +63,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ^^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/mut-patterns.rs:23:31 + --> $DIR/mut-patterns.rs:26:31 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -53,19 +73,23 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ^^^^^^^ error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:23:9 + --> $DIR/mut-patterns.rs:26:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:32:9 + --> $DIR/mut-patterns.rs:35:9 | LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found `x` - --> $DIR/mut-patterns.rs:39:21 + --> $DIR/mut-patterns.rs:42:21 | LL | let mut $p = 0; | ^^ expected identifier @@ -73,5 +97,5 @@ LL | let mut $p = 0; LL | foo!(x); | -------- in this macro invocation -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index d479905932be0..844f13c2f896a 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -14,7 +14,7 @@ pub fn main() { ref Self => (), //~^ ERROR expected identifier, found keyword `Self` mut Self => (), - //~^ ERROR `mut` must be attached to each individual binding + //~^ ERROR `mut` must be followed by a named binding //~| ERROR cannot find unit struct/variant or constant `Self` ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index fdae06ccdd9f5..bb631194bf3df 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -10,11 +10,13 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: `mut` must be attached to each individual binding +error: `mut` must be followed by a named binding --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^^^^^ help: add `mut` to each binding: `Self` + | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found keyword `Self` --> $DIR/self_type_keyword.rs:19:17 From 82f2b376357e68cdde86d75259fed39ea4df79e3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 06:17:58 +0900 Subject: [PATCH 10/20] Add Option to `require_lang_item` --- src/librustc/infer/mod.rs | 2 +- src/librustc/middle/lang_items.rs | 8 ++++++-- src/librustc/traits/select.rs | 2 +- src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 6 +++--- src/librustc/ty/util.rs | 6 +++--- src/librustc/ty/wf.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 5 ++++- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 4 ++-- src/librustdoc/clean/auto_trait.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 2 +- src/test/ui/lang-item-missing-generator.stderr | 4 ++++ 19 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e1d77a97c1160..cc28567e2fc9e 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1460,7 +1460,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c5c8639324358..334c06618bb28 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -381,9 +381,13 @@ language_item_table! { impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. /// If not found, fatally abort compilation. - pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { + pub fn require_lang_item(&self, lang_item: LangItem, span: Option) -> DefId { self.lang_items().require(lang_item).unwrap_or_else(|msg| { - self.sess.fatal(&msg) + if let Some(span) = span { + self.sess.span_fatal(span, &msg) + } else { + self.sess.fatal(&msg) + } }) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d4ae366262cbf..217c887d5254e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3513,7 +3513,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // We can only make objects from sized types. let tr = ty::TraitRef { - def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: tcx.mk_substs_trait(source, &[]), }; nested.push(predicate_to_obligation(tr.to_predicate())); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9f316e93111a3..c0d86a79882ef 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2385,13 +2385,13 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); + let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem, None); self.mk_generic_adt(def_id, ty) } #[inline] pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem); + let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None); self.mk_generic_adt(def_id, ty) } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index c71e1ea4e5859..a26fa72f33041 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -327,7 +327,7 @@ impl<'tcx> Instance<'tcx> { } pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { - let def_id = tcx.require_lang_item(DropInPlaceFnLangItem); + let def_id = tcx.require_lang_item(DropInPlaceFnLangItem, None); let substs = tcx.intern_substs(&[ty.into()]); Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap() } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0b81f193df409..90b3b7ebb0635 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2588,12 +2588,12 @@ impl<'tcx> ClosureKind { pub fn trait_did(&self, tcx: TyCtxt<'tcx>) -> DefId { match *self { - ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), + ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem, None), ClosureKind::FnMut => { - tcx.require_lang_item(FnMutTraitLangItem) + tcx.require_lang_item(FnMutTraitLangItem, None) } ClosureKind::FnOnce => { - tcx.require_lang_item(FnOnceTraitLangItem) + tcx.require_lang_item(FnOnceTraitLangItem, None) } } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 96e16efd1300a..7a77418050cdb 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -998,7 +998,7 @@ impl<'tcx> ty::TyS<'tcx> { fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1011,7 +1011,7 @@ fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, @@ -1024,7 +1024,7 @@ fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); + let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index d32c32af29e0d..d6de217f79c29 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { - def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate())); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index cdc54bb179ebf..4acbe0356b47c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -456,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' let arg_argv = param_argv; let (start_fn, args) = if use_start_lang_item { - let start_def_id = cx.tcx().require_lang_item(StartFnLangItem); + let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); let start_fn = callee::resolve_and_get_fn( cx, start_def_id, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index ec85daccd476e..d5890d00ea80f 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => bug!("non_scalar_compare called on non-reference type: {}", ty), }; - let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem); + let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem, None); let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); let bool_ty = self.hir.bool_ty(); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7f8ae88342934..a59bd6677cb51 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1752,7 +1752,10 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { fulfillment_cx.register_bound(&infcx, param_env, ty, - tcx.require_lang_item(lang_items::SyncTraitLangItem), + tcx.require_lang_item( + lang_items::SyncTraitLangItem, + None + ), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index c5561a1ae0d15..3e9e4b7767f1e 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -897,7 +897,7 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem, None); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 53101499af1dc..55e7a10f1aaa4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 06b1e7bfd4eaf..e9370429f3f55 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); - let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem); + let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem, cause_span); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator"); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c4dbe97a7bd96..29fae13e6a866 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9c6ea7d30ccf9..f95b3e44bf0f7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -287,7 +287,7 @@ fn check_type_defn<'tcx, F>( let last = idx == variant.fields.len() - 1; fcx.register_bound( field.ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), traits::ObligationCause::new( field.span, fcx.body_id, @@ -375,7 +375,7 @@ fn check_item_type( if forbid_unsized { fcx.register_bound( item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 5a4dc7be326d2..516be99ed6aad 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // it is *not* required (i.e., '?Sized') let sized_trait = self.cx .tcx - .require_lang_item(lang_items::SizedTraitLangItem); + .require_lang_item(lang_items::SizedTraitLangItem, None); let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, @@ -777,9 +777,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool { match &ty { &&Type::ResolvedPath { ref did, .. } => { - *did == tcx.require_lang_item(lang_items::FnTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem) - || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem) + *did == tcx.require_lang_item(lang_items::FnTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem, None) + || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem, None) } _ => false, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ba792a413b3c4..ad1fa96cd3557 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1060,7 +1060,7 @@ pub enum GenericBound { impl GenericBound { fn maybe_sized(cx: &DocContext<'_>) -> GenericBound { - let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); diff --git a/src/test/ui/lang-item-missing-generator.stderr b/src/test/ui/lang-item-missing-generator.stderr index d0cc4b81be685..fa13bf0b12719 100644 --- a/src/test/ui/lang-item-missing-generator.stderr +++ b/src/test/ui/lang-item-missing-generator.stderr @@ -1,4 +1,8 @@ error: requires `generator` lang_item + --> $DIR/lang-item-missing-generator.rs:15:17 + | +LL | pub fn abc() -> impl FnOnce(f32) { + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error From 8c921beebbc4501f301cd1830b7c2528368e517a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 07:10:47 +0900 Subject: [PATCH 11/20] Apply review comments --- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 5 ++++- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/lang-item-missing.stderr | 4 ++++ src/test/ui/privacy/privacy2.rs | 2 +- src/test/ui/privacy/privacy2.stderr | 4 ++++ src/test/ui/privacy/privacy3.rs | 2 +- src/test/ui/privacy/privacy3.stderr | 4 ++++ 9 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a59bd6677cb51..a77421ce15008 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1754,7 +1754,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { ty, tcx.require_lang_item( lang_items::SyncTraitLangItem, - None + Some(body.span) ), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 3e9e4b7767f1e..f3e03e7f81daa 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -897,7 +897,10 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem, None); + let free_func = tcx.require_lang_item( + lang_items::BoxFreeFnLangItem, + Some(self.source_info.span) + ); let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 55e7a10f1aaa4..6b88144d1fc10 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 29fae13e6a866..62e11fb421ee7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/test/ui/lang-item-missing.stderr b/src/test/ui/lang-item-missing.stderr index f7516c7d377da..94d62023f3562 100644 --- a/src/test/ui/lang-item-missing.stderr +++ b/src/test/ui/lang-item-missing.stderr @@ -1,4 +1,8 @@ error: requires `sized` lang_item + --> $DIR/lang-item-missing.rs:10:50 + | +LL | fn start(argc: isize, argv: *const *const u8) -> isize { + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy2.rs b/src/test/ui/privacy/privacy2.rs index c8fa436bd14fc..07634d9132e78 100644 --- a/src/test/ui/privacy/privacy2.rs +++ b/src/test/ui/privacy/privacy2.rs @@ -11,7 +11,7 @@ mod bar { } } -pub fn foo() {} +pub fn foo() {} //~ ERROR: requires `sized` lang_item fn test1() { use bar::foo; diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 9f2359657bd7c..eaa9f1ad6528e 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -11,6 +11,10 @@ LL | use bar::glob::foo; | ^^^ error: requires `sized` lang_item + --> $DIR/privacy2.rs:14:14 + | +LL | pub fn foo() {} + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/privacy3.rs b/src/test/ui/privacy/privacy3.rs index 5a7cd76a98f6e..8853700180dbc 100644 --- a/src/test/ui/privacy/privacy3.rs +++ b/src/test/ui/privacy/privacy3.rs @@ -8,7 +8,7 @@ mod bar { pub use self::glob::*; mod glob { - fn gpriv() {} + fn gpriv() {} //~ ERROR: requires `sized` lang_item } } diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 22c1e48b07d94..6826fbf9df290 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -5,6 +5,10 @@ LL | use bar::gpriv; | ^^^^^^^^^^ no `gpriv` in `bar` error: requires `sized` lang_item + --> $DIR/privacy3.rs:11:20 + | +LL | fn gpriv() {} + | ^ error: aborting due to 2 previous errors From ede7a777c08658ec54abea504da0e46cd0fb5e5b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 28 Aug 2019 07:32:25 +0900 Subject: [PATCH 12/20] Remove `sized` spans --- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/lang-item-missing.stderr | 4 ---- src/test/ui/privacy/privacy2.rs | 2 +- src/test/ui/privacy/privacy2.stderr | 4 ---- src/test/ui/privacy/privacy3.rs | 2 +- src/test/ui/privacy/privacy3.stderr | 4 ---- 7 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6b88144d1fc10..55e7a10f1aaa4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 62e11fb421ee7..29fae13e6a866 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2622,7 +2622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, Some(span)); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } diff --git a/src/test/ui/lang-item-missing.stderr b/src/test/ui/lang-item-missing.stderr index 94d62023f3562..f7516c7d377da 100644 --- a/src/test/ui/lang-item-missing.stderr +++ b/src/test/ui/lang-item-missing.stderr @@ -1,8 +1,4 @@ error: requires `sized` lang_item - --> $DIR/lang-item-missing.rs:10:50 - | -LL | fn start(argc: isize, argv: *const *const u8) -> isize { - | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy2.rs b/src/test/ui/privacy/privacy2.rs index 07634d9132e78..c8fa436bd14fc 100644 --- a/src/test/ui/privacy/privacy2.rs +++ b/src/test/ui/privacy/privacy2.rs @@ -11,7 +11,7 @@ mod bar { } } -pub fn foo() {} //~ ERROR: requires `sized` lang_item +pub fn foo() {} fn test1() { use bar::foo; diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index eaa9f1ad6528e..9f2359657bd7c 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -11,10 +11,6 @@ LL | use bar::glob::foo; | ^^^ error: requires `sized` lang_item - --> $DIR/privacy2.rs:14:14 - | -LL | pub fn foo() {} - | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/privacy/privacy3.rs b/src/test/ui/privacy/privacy3.rs index 8853700180dbc..5a7cd76a98f6e 100644 --- a/src/test/ui/privacy/privacy3.rs +++ b/src/test/ui/privacy/privacy3.rs @@ -8,7 +8,7 @@ mod bar { pub use self::glob::*; mod glob { - fn gpriv() {} //~ ERROR: requires `sized` lang_item + fn gpriv() {} } } diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 6826fbf9df290..22c1e48b07d94 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -5,10 +5,6 @@ LL | use bar::gpriv; | ^^^^^^^^^^ no `gpriv` in `bar` error: requires `sized` lang_item - --> $DIR/privacy3.rs:11:20 - | -LL | fn gpriv() {} - | ^ error: aborting due to 2 previous errors From 6f67bbc445e5c2b426abc4ac0db4c1dcffd48452 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 28 Aug 2019 02:23:58 +0200 Subject: [PATCH 13/20] or-pattern: fix typo in error message --- src/libsyntax/parse/parser/pat.rs | 2 +- src/test/ui/or-patterns/while-parsing-this-or-pattern.rs | 2 +- src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 78c9a289b3702..4c6b6ce38f66b 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -113,7 +113,7 @@ impl<'a> Parser<'a> { let mut pats = vec![first_pat]; while self.eat_or_separator() { let pat = self.parse_pat(expected).map_err(|mut err| { - err.span_label(lo, "while parsing this or-pattern staring here"); + err.span_label(lo, "while parsing this or-pattern starting here"); err })?; self.maybe_recover_unexpected_comma(pat.span, rc)?; diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs index 4a9fae1406af7..b9bfb8638b2ce 100644 --- a/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -3,7 +3,7 @@ fn main() { match Some(42) { Some(42) | .=. => {} //~ ERROR expected pattern, found `.` - //~^ while parsing this or-pattern staring here + //~^ while parsing this or-pattern starting here //~| NOTE expected pattern } } diff --git a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr index 21fece6c64fe5..7ad62ff99ee73 100644 --- a/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr +++ b/src/test/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -4,7 +4,7 @@ error: expected pattern, found `.` LL | Some(42) | .=. => {} | -------- ^ expected pattern | | - | while parsing this or-pattern staring here + | while parsing this or-pattern starting here error: aborting due to previous error From 42bd6fa22b753858bd57aec5e987247fd6a00897 Mon Sep 17 00:00:00 2001 From: Logan Wendholt Date: Tue, 27 Aug 2019 20:35:33 -0400 Subject: [PATCH 14/20] Prevent syntax error in ld linker version script --- src/librustc_codegen_ssa/back/linker.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 26091005f25aa..de481d2262478 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -430,10 +430,13 @@ impl<'a> Linker for GccLinker<'a> { // Write an LD version script let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); - writeln!(f, "{{\n global:")?; - for sym in self.info.exports[&crate_type].iter() { - debug!(" {};", sym); - writeln!(f, " {};", sym)?; + writeln!(f, "{{")?; + if !self.info.exports[&crate_type].is_empty() { + writeln!(f, " global:")?; + for sym in self.info.exports[&crate_type].iter() { + debug!(" {};", sym); + writeln!(f, " {};", sym)?; + } } writeln!(f, "\n local:\n *;\n}};")?; }; From 0006216c9d83dabed3f13f5ed231c152561ceb6a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 28 Aug 2019 11:23:41 +0300 Subject: [PATCH 15/20] rustc_apfloat: make the crate #![no_std] explicitly. --- src/librustc_apfloat/ieee.rs | 16 ++++++++-------- src/librustc_apfloat/lib.rs | 36 ++++++++++++++++++++---------------- src/librustc_apfloat/ppc.rs | 6 +++--- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 9f68d770b9e87..18d968fbddd9b 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -1,13 +1,13 @@ use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO}; use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd}; +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt::{self, Write}; +use core::marker::PhantomData; +use core::mem; +use core::ops::Neg; use smallvec::{SmallVec, smallvec}; -use std::cmp::{self, Ordering}; -use std::convert::TryFrom; -use std::fmt::{self, Write}; -use std::marker::PhantomData; -use std::mem; -use std::ops::Neg; #[must_use] pub struct IeeeFloat { @@ -2287,8 +2287,8 @@ impl Loss { /// Implementation details of IeeeFloat significands, such as big integer arithmetic. /// As a rule of thumb, no functions in this module should dynamically allocate. mod sig { - use std::cmp::Ordering; - use std::mem; + use core::cmp::Ordering; + use core::mem; use super::{ExpInt, Limb, LIMB_BITS, limbs_for_bits, Loss}; pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool { diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 9e6d5a6f62434..1190cea21acc3 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -31,15 +31,19 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![no_std] #![forbid(unsafe_code)] #![feature(nll)] -use std::cmp::Ordering; -use std::fmt; -use std::ops::{Neg, Add, Sub, Mul, Div, Rem}; -use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use std::str::FromStr; +#[macro_use] +extern crate alloc; + +use core::cmp::Ordering; +use core::fmt; +use core::ops::{Neg, Add, Sub, Mul, Div, Rem}; +use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use core::str::FromStr; bitflags::bitflags! { /// IEEE-754R 7: Default exception handling. @@ -587,7 +591,7 @@ macro_rules! float_common_impls { } } - impl<$t> ::std::str::FromStr for $ty<$t> where Self: Float { + impl<$t> ::core::str::FromStr for $ty<$t> where Self: Float { type Err = ParseError; fn from_str(s: &str) -> Result { Self::from_str_r(s, Round::NearestTiesToEven).map(|x| x.value) @@ -596,66 +600,66 @@ macro_rules! float_common_impls { // Rounding ties to the nearest even, by default. - impl<$t> ::std::ops::Add for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Add for $ty<$t> where Self: Float { type Output = StatusAnd; fn add(self, rhs: Self) -> StatusAnd { self.add_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Sub for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Sub for $ty<$t> where Self: Float { type Output = StatusAnd; fn sub(self, rhs: Self) -> StatusAnd { self.sub_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Mul for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Mul for $ty<$t> where Self: Float { type Output = StatusAnd; fn mul(self, rhs: Self) -> StatusAnd { self.mul_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Div for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Div for $ty<$t> where Self: Float { type Output = StatusAnd; fn div(self, rhs: Self) -> StatusAnd { self.div_r(rhs, Round::NearestTiesToEven) } } - impl<$t> ::std::ops::Rem for $ty<$t> where Self: Float { + impl<$t> ::core::ops::Rem for $ty<$t> where Self: Float { type Output = StatusAnd; fn rem(self, rhs: Self) -> StatusAnd { self.c_fmod(rhs) } } - impl<$t> ::std::ops::AddAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::AddAssign for $ty<$t> where Self: Float { fn add_assign(&mut self, rhs: Self) { *self = (*self + rhs).value; } } - impl<$t> ::std::ops::SubAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::SubAssign for $ty<$t> where Self: Float { fn sub_assign(&mut self, rhs: Self) { *self = (*self - rhs).value; } } - impl<$t> ::std::ops::MulAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::MulAssign for $ty<$t> where Self: Float { fn mul_assign(&mut self, rhs: Self) { *self = (*self * rhs).value; } } - impl<$t> ::std::ops::DivAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::DivAssign for $ty<$t> where Self: Float { fn div_assign(&mut self, rhs: Self) { *self = (*self / rhs).value; } } - impl<$t> ::std::ops::RemAssign for $ty<$t> where Self: Float { + impl<$t> ::core::ops::RemAssign for $ty<$t> where Self: Float { fn rem_assign(&mut self, rhs: Self) { *self = (*self % rhs).value; } diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index ddccfd6ca623b..8e2e390568e48 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -1,9 +1,9 @@ use crate::{Category, ExpInt, Float, FloatConvert, Round, ParseError, Status, StatusAnd}; use crate::ieee; -use std::cmp::Ordering; -use std::fmt; -use std::ops::Neg; +use core::cmp::Ordering; +use core::fmt; +use core::ops::Neg; #[must_use] #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] From cca64e73399c02b2f964e3b34f969e826d061eed Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 26 Aug 2019 21:07:58 -0400 Subject: [PATCH 16/20] Add some comments to `mir::Static` and `mir::StaticKind` --- src/librustc/mir/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 60efeaab97602..a5ef3792c6b96 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1733,6 +1733,10 @@ pub enum PlaceBase<'tcx> { pub struct Static<'tcx> { pub ty: Ty<'tcx>, pub kind: StaticKind<'tcx>, + /// The `DefId` of the item this static was declared in. For promoted values, usually, this is + /// the same as the `DefId` of the `mir::Body` containing the `Place` this promoted appears in. + /// However, after inlining, that might no longer be the case as inlined `Place`s are copied + /// into the calling frame. pub def_id: DefId, } @@ -1740,6 +1744,9 @@ pub struct Static<'tcx> { Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] pub enum StaticKind<'tcx> { + /// Promoted references consist of an id (`Promoted`) and the substs necessary to monomorphize + /// it. Usually, these substs are just the identity substs for the item. However, the inliner + /// will adjust these substs when it inlines a function based on the substs at the callsite. Promoted(Promoted, SubstsRef<'tcx>), Static, } From 30b29ab0f7c54a2ca74de5117395371101fa9518 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 26 Aug 2019 21:58:16 -0400 Subject: [PATCH 17/20] Simplify `maybe_get_optimized_mir` and `maybe_get_promoted_mir` Since both functions are always unwrapped, don't wrap the return value in an `Option`. --- src/librustc_metadata/cstore_impl.rs | 20 ++--------------- src/librustc_metadata/decoder.rs | 32 ++++++++++++++++++---------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7aeeef00ea934..81e0cd7a4c4dd 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -127,24 +127,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); }) } - optimized_mir => { - let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) - }); - - let mir = tcx.arena.alloc(mir); - - mir - } - promoted_mir => { - let promoted = cdata.maybe_get_promoted_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_promoted_mir: missing promoted MIR for `{:?}`", def_id) - }); - - let promoted = tcx.arena.alloc(promoted); - - promoted - } + optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } + promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af235..10b165c906625 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -917,22 +917,32 @@ impl<'a, 'tcx> CrateMetadata { self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } - pub fn maybe_get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option> { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), - } + pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + let mir = + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), + }; + + mir.unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } - pub fn maybe_get_promoted_mir( + pub fn get_promoted_mir( &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> Option>> { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) - } + ) -> IndexVec> { + let promoted = + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx))) + }; + + promoted.unwrap_or_else(|| { + bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { From 009cce88ebcbdb5825c86fd7f3ff84216a2d3fec Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 27 Aug 2019 21:24:57 -0400 Subject: [PATCH 18/20] Extract `Decoder::entry_unless_proc_macro()` --- src/librustc_metadata/decoder.rs | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 10b165c906625..4d2f9f58226d7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -450,11 +450,19 @@ impl<'a, 'tcx> CrateMetadata { pub fn is_proc_macro_crate(&self) -> bool { self.root.proc_macro_decls_static.is_some() } + fn is_proc_macro(&self, id: DefIndex) -> bool { self.is_proc_macro_crate() && self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } + fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { + match self.is_proc_macro(id) { + true => None, + false => Some(self.entry(id)), + } + } + fn maybe_entry(&self, item_id: DefIndex) -> Option>> { self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } @@ -704,10 +712,8 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_deprecation(&self, id: DefIndex) -> Option { - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).deprecation.map(|depr| depr.decode(self)), - } + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) } pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { @@ -918,15 +924,11 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { - let mir = - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), - }; - - mir.unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) - }) + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id)) + }) } pub fn get_promoted_mir( @@ -934,15 +936,11 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - let promoted = - match self.is_proc_macro(id) { - true => None, - false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx))) - }; - - promoted.unwrap_or_else(|| { - bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) - }) + self.entry_unless_proc_macro(id) + .and_then(|entry| entry.promoted_mir.map(|promoted| promoted.decode((self, tcx)))) + .unwrap_or_else(|| { + bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) + }) } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { From 8cf392114da9deb8bdf160b196b8fd1503fb395e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 28 Aug 2019 13:23:00 +0200 Subject: [PATCH 19/20] Notify me (flip1995) when Clippy toolstate changes --- src/tools/publish_toolstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 648838d26efe9..1411f4c0b05a2 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -22,7 +22,7 @@ # List of people to ping when the status of a tool or a book changed. MAINTAINERS = { 'miri': '@oli-obk @RalfJung @eddyb', - 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch', + 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995', 'rls': '@Xanewok', 'rustfmt': '@topecongiro', 'book': '@carols10cents @steveklabnik', From 080fdb8184cea898f48818312a7645007c8b7594 Mon Sep 17 00:00:00 2001 From: Dodo Date: Wed, 28 Aug 2019 17:38:24 +0200 Subject: [PATCH 20/20] add missing `#[repr(C)]` on a union --- src/libcore/str/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f20cb7bfbc3bd..752c372e93e3a 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2170,6 +2170,7 @@ impl str { #[inline(always)] #[rustc_const_unstable(feature="const_str_as_bytes")] pub const fn as_bytes(&self) -> &[u8] { + #[repr(C)] union Slices<'a> { str: &'a str, slice: &'a [u8],